mirror of
https://github.com/lxsang/antd-web-apps
synced 2025-07-23 17:19:47 +02:00
use silk framework for os
This commit is contained in:
33
os/controllers/IndexController.lua
Normal file
33
os/controllers/IndexController.lua
Normal file
@ -0,0 +1,33 @@
|
||||
BaseController:subclass(
|
||||
"IndexController",
|
||||
{
|
||||
registry = {},
|
||||
models = {}
|
||||
}
|
||||
)
|
||||
|
||||
function IndexController:actionnotfound(...)
|
||||
return self:index(table.unpack({...}))
|
||||
end
|
||||
|
||||
function IndexController:index(...)
|
||||
html()
|
||||
std.f(WWW_ROOT..DIR_SEP.."index.html")
|
||||
end
|
||||
|
||||
function IndexController:doc(...)
|
||||
local api = {
|
||||
author = "Xuan Sang LE",
|
||||
email = "xsang.le@gmail.com",
|
||||
api_name = "AntOS API",
|
||||
version = "0.2.4 a",
|
||||
documents = {
|
||||
vfs = HTTP_ROOT.."/VFS",
|
||||
vdb = HTTP_ROOT.."/VDB",
|
||||
user = HTTP_ROOT.."/user",
|
||||
system = HTTP_ROOT.."/system"
|
||||
}
|
||||
}
|
||||
result(api)
|
||||
return false
|
||||
end
|
196
os/controllers/SystemController.lua
Normal file
196
os/controllers/SystemController.lua
Normal file
@ -0,0 +1,196 @@
|
||||
BaseController:subclass(
|
||||
"SystemController",
|
||||
{
|
||||
registry = {},
|
||||
models = {}
|
||||
}
|
||||
)
|
||||
|
||||
function SystemController:actionnotfound(...)
|
||||
return self:index(table.unpack({...}))
|
||||
end
|
||||
|
||||
function SystemController:index(...)
|
||||
local api = {
|
||||
description = "This api handle system operations",
|
||||
actions = {
|
||||
["/packages"] = "Handle all operation relate to package: list, install, cache, uninstall",
|
||||
["/settings"] = "Save user setting",
|
||||
["/application"] = "Call a specific server side application api",
|
||||
["/apigateway"] = "Gateway for executing custom server side code"
|
||||
}
|
||||
}
|
||||
result(api)
|
||||
return false
|
||||
end
|
||||
|
||||
function SystemController:packages(...)
|
||||
auth_or_die("User unauthorized. Please login")
|
||||
local rq = (JSON.decodeString(REQUEST.query.json))
|
||||
local packages = require("packages")
|
||||
packages.init(rq.args.paths)
|
||||
if rq ~= nil then
|
||||
-- check user command here
|
||||
if (rq.command == "install") then
|
||||
packages.install(rq.args)
|
||||
elseif rq.command == "cache" then
|
||||
packages.cache(rq.args)
|
||||
elseif rq.command == "list" then
|
||||
packages.list(rq.args.paths)
|
||||
elseif rq.command == "uninstall" then
|
||||
packages.uninstall(rq.args.path)
|
||||
else
|
||||
fail("Uknown packages command")
|
||||
end
|
||||
else
|
||||
fail("Uknown request")
|
||||
end
|
||||
end
|
||||
|
||||
function SystemController:settings(...)
|
||||
auth_or_die("User unauthorized. Please login")
|
||||
local user = SESSION.user
|
||||
if user then
|
||||
local ospath = require("vfs").ospath("home:///", user)
|
||||
if REQUEST.query and REQUEST.query.json then
|
||||
local f = io.open(ospath .. "/" .. ".settings.json", "w")
|
||||
if f then
|
||||
f:write(REQUEST.query.json)
|
||||
f:close()
|
||||
result(true)
|
||||
else
|
||||
fail("Cannot save setting")
|
||||
end
|
||||
else
|
||||
fail("No setting founds")
|
||||
end
|
||||
else
|
||||
fail("User not found")
|
||||
end
|
||||
end
|
||||
|
||||
function SystemController:application(...)
|
||||
auth_or_die("User unauthorized. Please login")
|
||||
local rq = nil
|
||||
if REQUEST.query.json ~= nil then
|
||||
rq = (JSON.decodeString(REQUEST.query.json))
|
||||
else
|
||||
rq = REQUEST.query
|
||||
end
|
||||
|
||||
if rq.path ~= nil then
|
||||
local pkg = require("vfs").ospath(rq.path)
|
||||
if pkg == nil then
|
||||
pkg = WWW_ROOT .. "/packages/" .. rq.path
|
||||
--die("unkown request path:"..rq.path)
|
||||
end
|
||||
pkg = pkg .. "/api.lua"
|
||||
if ulib.exists(pkg) then
|
||||
dofile(pkg).exec(rq.method, rq.arguments)
|
||||
else
|
||||
fail("Uknown application handler: " .. pkg)
|
||||
end
|
||||
else
|
||||
fail("Uknown request")
|
||||
end
|
||||
end
|
||||
|
||||
function SystemController:apigateway(...)
|
||||
local use_ws = false
|
||||
if REQUEST.query and REQUEST.query.ws == "1" then
|
||||
-- override the global echo command
|
||||
echo = std.ws.swrite
|
||||
use_ws = true
|
||||
else
|
||||
std.json()
|
||||
end
|
||||
local exec_with_user_priv = function(data)
|
||||
local uid = ulib.uid(SESSION.user)
|
||||
if not ulib.setgid(uid.gid) or not ulib.setuid(uid.id) then
|
||||
echo("Cannot set permission to execute the code")
|
||||
return
|
||||
end
|
||||
local r, e
|
||||
e = "{'error': 'Unknow function'}"
|
||||
if data.code then
|
||||
r, e = load(data.code)
|
||||
if r then
|
||||
local status, result = pcall(r)
|
||||
if (status) then
|
||||
echo(JSON.encode(result))
|
||||
else
|
||||
echo(result)
|
||||
end
|
||||
else
|
||||
echo(e)
|
||||
end
|
||||
elseif data.path then
|
||||
r, e = loadfile(data.path)
|
||||
if r then
|
||||
local status, result = pcall(r, data.parameters)
|
||||
if (status) then
|
||||
echo(JSON.encode(result))
|
||||
else
|
||||
echo(result)
|
||||
end
|
||||
else
|
||||
echo(e)
|
||||
end
|
||||
else
|
||||
echo(e)
|
||||
end
|
||||
end
|
||||
|
||||
if (is_auth()) then
|
||||
local pid = ulib.fork()
|
||||
if (pid == -1) then
|
||||
echo("{'error':'Cannot create process'}")
|
||||
elseif pid > 0 then -- parent
|
||||
-- wait for the child exit
|
||||
ulib.waitpid(pid)
|
||||
print("Parent exit")
|
||||
else -- child
|
||||
if use_ws then
|
||||
if std.ws.enable() then
|
||||
-- read header
|
||||
local header = std.ws.header()
|
||||
if header then
|
||||
if header.mask == 0 then
|
||||
print("Data is not masked")
|
||||
std.ws.close(1012)
|
||||
elseif header.opcode == std.ws.CLOSE then
|
||||
print("Connection closed")
|
||||
std.ws.close(1000)
|
||||
elseif header.opcode == std.ws.TEXT then
|
||||
-- read the file
|
||||
local data = std.ws.read(header)
|
||||
if data then
|
||||
data = (JSON.decodeString(data))
|
||||
exec_with_user_priv(data)
|
||||
std.ws.close(1011)
|
||||
else
|
||||
echo("Error: Invalid request")
|
||||
std.ws.close(1011)
|
||||
end
|
||||
end
|
||||
else
|
||||
std.ws.close(1011)
|
||||
end
|
||||
else
|
||||
print("Web socket is not available.")
|
||||
end
|
||||
else
|
||||
if REQUEST.query.json then
|
||||
data = JSON.decodeString(REQUEST.query.json)
|
||||
--std.json()
|
||||
exec_with_user_priv(data)
|
||||
else
|
||||
fail("Unkown request")
|
||||
end
|
||||
end
|
||||
print("Child exit")
|
||||
end
|
||||
else
|
||||
echo('{"error":"User unauthorized. Please login"}')
|
||||
end
|
||||
end
|
96
os/controllers/UserController.lua
Normal file
96
os/controllers/UserController.lua
Normal file
@ -0,0 +1,96 @@
|
||||
BaseController:subclass(
|
||||
"UserController",
|
||||
{
|
||||
registry = {},
|
||||
models = {}
|
||||
}
|
||||
)
|
||||
|
||||
function UserController:actionnotfound(...)
|
||||
return self:index(table.unpack({...}))
|
||||
end
|
||||
|
||||
function UserController:index(...)
|
||||
local api = {
|
||||
description = "This api handle the user authentification",
|
||||
actions = {
|
||||
["/auth"] = "Return user information if a user is alreay logged in",
|
||||
["/login"] = "Perform a login operation",
|
||||
["/logout"] = "Perform a logout operation"
|
||||
}
|
||||
}
|
||||
result(api)
|
||||
return false
|
||||
end
|
||||
--[[
|
||||
request query: none
|
||||
return:
|
||||
|
||||
]]
|
||||
function UserController:auth(...)
|
||||
auth_or_die("User unauthorized. Please login")
|
||||
local user = require("uman").userinfo(SESSION.user)
|
||||
result(user)
|
||||
return false
|
||||
end
|
||||
|
||||
--[[ request:
|
||||
{"username":"mrsang", "password":"pass"}
|
||||
return:
|
||||
{} ]]
|
||||
function UserController:login(...)
|
||||
if REQUEST.query.json ~= nil then
|
||||
local request = JSON.decodeString(REQUEST.query.json)
|
||||
local r = ulib.auth(request.username,request.password)
|
||||
if r == true then
|
||||
local cookie = {sessionid=std.sha1(request.username..request.password)} -- iotos_user = request.username
|
||||
local db = sysdb();
|
||||
if db == nil then return fail("Cannot setup session") end
|
||||
local cond = {exp= {["="] = { sessionid = cookie.sessionid }}}
|
||||
local data = db:find(cond)
|
||||
--print(data)
|
||||
if data == nil or data[1] == nil then
|
||||
--print("insert new data")
|
||||
data = {sessionid = cookie.sessionid, username=request.username, stamp=os.time(os.date("!*t"))}
|
||||
else
|
||||
data = data[1]
|
||||
--print("Update old data")
|
||||
data.stamp = os.time(os.date("!*t"))
|
||||
end
|
||||
if data.id == nil then
|
||||
db:insert(data)
|
||||
else
|
||||
db:update(data)
|
||||
end
|
||||
db:close()
|
||||
std.cjson(cookie)
|
||||
SESSION.user = request.username
|
||||
local user = {
|
||||
result = require("uman").userinfo(request.username),
|
||||
error = false
|
||||
}
|
||||
std.t(JSON.encode(user))
|
||||
else
|
||||
fail("Invalid login")
|
||||
end
|
||||
else
|
||||
fail("Invalid request")
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function UserController:logout(...)
|
||||
if SESSION.sessionid ~= nil and SESSION.sessionid ~= '0' then
|
||||
local cookie = {sessionid='0'}
|
||||
local db = sysdb()
|
||||
if db ~= nil then
|
||||
local cond = {["="] = { sessionid = SESSION.sessionid }}
|
||||
db:delete(cond)
|
||||
db:close()
|
||||
end
|
||||
std.cjson(cookie)
|
||||
else
|
||||
std.json()
|
||||
end
|
||||
std.t(JSON.encode({error=false,result=true}))
|
||||
end
|
130
os/controllers/VDBController.lua
Normal file
130
os/controllers/VDBController.lua
Normal file
@ -0,0 +1,130 @@
|
||||
BaseController:subclass(
|
||||
"VDBController",
|
||||
{
|
||||
registry = {},
|
||||
models = {}
|
||||
}
|
||||
)
|
||||
|
||||
function VDBController:actionnotfound(...)
|
||||
return self:index(table.unpack({...}))
|
||||
end
|
||||
|
||||
function VDBController:index(...)
|
||||
local api = {
|
||||
description = "This api handle database operation",
|
||||
actions = {
|
||||
["/save"] = "Save a record to a table",
|
||||
["/get"] = "Get all records or Get a record by id",
|
||||
["/select"] = "Select records by a condition",
|
||||
["/delete"] = "Delete record(s) by condition or by id"
|
||||
}
|
||||
}
|
||||
result(api)
|
||||
return false
|
||||
end
|
||||
|
||||
function VDBController:save(...)
|
||||
auth_or_die("User unauthorized. Please login")
|
||||
local rq = (JSON.decodeString(REQUEST.query.json))
|
||||
if (rq ~= nil and rq.table ~= nil) then
|
||||
local model = require("dbmodel").get(SESSION.user, rq.table, rq.data)
|
||||
local ret
|
||||
if model == nil then
|
||||
fail("Cannot get table metadata:" .. rq.table)
|
||||
else
|
||||
if (rq.data.id ~= nil) then
|
||||
rq.data.id = tonumber(rq.data.id)
|
||||
ret = model:update(rq.data)
|
||||
else
|
||||
ret = model:insert(rq.data)
|
||||
end
|
||||
model:close()
|
||||
if ret == true then
|
||||
result(ret)
|
||||
else
|
||||
fail("Cannot modify/update table " .. rq.table)
|
||||
end
|
||||
end
|
||||
else
|
||||
fail("Unknown database request")
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function VDBController:get(...)
|
||||
auth_or_die("User unauthorized. Please login")
|
||||
local rq = (JSON.decodeString(REQUEST.query.json))
|
||||
if (rq ~= nil and rq.table ~= nil) then
|
||||
local model = require("dbmodel").get(SESSION.user, rq.table, nil)
|
||||
local ret
|
||||
if model == nil then
|
||||
fail("Cannot get table metadata:" .. rq.table)
|
||||
else
|
||||
if (rq.id == nil) then
|
||||
ret = model:getAll()
|
||||
else
|
||||
ret = model:get(rq.id)
|
||||
end
|
||||
model:close()
|
||||
result(ret)
|
||||
end
|
||||
else
|
||||
fail("Unknown database request")
|
||||
end
|
||||
end
|
||||
|
||||
function VDBController:select(...)
|
||||
auth_or_die("User unauthorized. Please login")
|
||||
local rq = (JSON.decodeString(REQUEST.query.json))
|
||||
if (rq ~= nil and rq.table ~= nil) then
|
||||
local model = require("dbmodel").get(SESSION.user, rq.table, nil)
|
||||
local ret
|
||||
if model == nil then
|
||||
fail("Cannot get table metadata:" .. rq.table)
|
||||
else
|
||||
if (rq.cond == nil) then
|
||||
model:close()
|
||||
return fail("Unknow condition")
|
||||
else
|
||||
ret = model:find(rq.cond)
|
||||
end
|
||||
model:close()
|
||||
result(ret)
|
||||
end
|
||||
else
|
||||
fail("Unknown database request")
|
||||
end
|
||||
end
|
||||
|
||||
function VDBController:delete(...)
|
||||
auth_or_die("User unauthorized. Please login")
|
||||
local rq = (JSON.decodeString(REQUEST.query.json))
|
||||
if (rq ~= nil and rq.table ~= nil) then
|
||||
local model = require("dbmodel").get(SESSION.user, rq.table, nil)
|
||||
local ret
|
||||
if model == nil then
|
||||
fail("Cannot get table metadata:" .. rq.table)
|
||||
else
|
||||
if (rq.id == nil) then
|
||||
if (rq.cond) then
|
||||
ret = model:delete(rq.cond)
|
||||
model:close()
|
||||
else
|
||||
model:close()
|
||||
return fail("Unknow element to delete")
|
||||
end
|
||||
else
|
||||
ret = model:deleteByID(rq.id)
|
||||
model:close()
|
||||
end
|
||||
if ret then
|
||||
result(ret)
|
||||
else
|
||||
fail("Querry error or database is locked")
|
||||
end
|
||||
end
|
||||
else
|
||||
fail("Unknown database request")
|
||||
end
|
||||
end
|
249
os/controllers/VFSController.lua
Normal file
249
os/controllers/VFSController.lua
Normal file
@ -0,0 +1,249 @@
|
||||
BaseController:subclass(
|
||||
"VFSController",
|
||||
{
|
||||
registry = {},
|
||||
models = {}
|
||||
}
|
||||
)
|
||||
|
||||
function VFSController:actionnotfound(...)
|
||||
return self:index(table.unpack({...}))
|
||||
end
|
||||
|
||||
function VFSController:index(...)
|
||||
local api = {
|
||||
description = "This api handle file operations",
|
||||
actions = {
|
||||
["/fileinfo"] = "Get file information",
|
||||
["/exists"] = "Check if file exists",
|
||||
["/delete"] = "Delete a file",
|
||||
["/get"] = "Get a file content",
|
||||
["/mkdir"] = "Create directory",
|
||||
["/move"] = "Move file to a new destination",
|
||||
["/publish"] = "Share a file to all users",
|
||||
["/scandir"] = "List all files and folders",
|
||||
["/write"] = "Write data to file",
|
||||
["/shared"] = "Get shared file content"
|
||||
}
|
||||
}
|
||||
result(api)
|
||||
return false
|
||||
end
|
||||
|
||||
function VFSController:fileinfo(...)
|
||||
auth_or_die("User unauthorized. Please login")
|
||||
local vfspath = (JSON.decodeString(REQUEST.query.json)).path
|
||||
local r, m = require("vfs").fileinfo(vfspath)
|
||||
if r then
|
||||
result(m)
|
||||
else
|
||||
fail(m)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function VFSController:exists(...)
|
||||
auth_or_die("User unauthorized. Please login")
|
||||
|
||||
local vfs = require("vfs")
|
||||
local rq = (JSON.decodeString(REQUEST.query.json))
|
||||
|
||||
if rq ~= nil then
|
||||
result(vfs.exists(rq.path))
|
||||
else
|
||||
fail("Uknown request")
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function VFSController:delete(...)
|
||||
auth_or_die("User unauthorized. Please login")
|
||||
|
||||
local vfs = require("vfs")
|
||||
local rq = (JSON.decodeString(REQUEST.query.json))
|
||||
|
||||
if rq ~= nil then
|
||||
local r, e = vfs.delete(rq.path)
|
||||
if r then
|
||||
result(r)
|
||||
else
|
||||
fail(e)
|
||||
end
|
||||
else
|
||||
fail("Uknown request")
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function VFSController:get(...)
|
||||
local args = {...}
|
||||
local uri = implode(args, "/")
|
||||
auth_or_die("User unauthorized. Please login")
|
||||
local vfsfile = utils.decodeURI(uri)
|
||||
local r, m = require("vfs").checkperm(vfsfile, "read")
|
||||
if r then
|
||||
local mime = std.mimeOf(m)
|
||||
if mime == "audio/mpeg" then
|
||||
local finfo = ulib.file_stat(m)
|
||||
local len = tostring(math.floor(finfo.size))
|
||||
local len1 = tostring(math.floor(finfo.size - 1))
|
||||
std.status(200, "OK")
|
||||
std.custom_header("Pragma", "public")
|
||||
std.custom_header("Expires", "0")
|
||||
std.custom_header("Content-Type", mime)
|
||||
std.custom_header("Content-Length", len)
|
||||
std.custom_header("Content-Disposition", "inline; filename=" .. std.basename(m))
|
||||
std.custom_header("Content-Range:", "bytes 0-" .. len1 .. "/" .. len)
|
||||
std.custom_header("Accept-Ranges", "bytes")
|
||||
std.custom_header("X-Pad", "avoid browser bug")
|
||||
std.custom_header("Content-Transfer-Encoding", "binary")
|
||||
std.custom_header("Cache-Control", "no-cache, no-store")
|
||||
std.custom_header("Connection", "Keep-Alive")
|
||||
std.custom_header("Etag", "a404b-c3f-47c3a14937c80")
|
||||
std.header_flush()
|
||||
else
|
||||
std.header(mime)
|
||||
end
|
||||
|
||||
if std.is_bin(m) then
|
||||
std.fb(m)
|
||||
else
|
||||
std.f(m)
|
||||
end
|
||||
else
|
||||
fail(m)
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function VFSController:mkdir(...)
|
||||
auth_or_die("User unauthorized. Please login")
|
||||
|
||||
local rq = (JSON.decodeString(REQUEST.query.json))
|
||||
|
||||
if rq ~= nil then
|
||||
local r, m = require("vfs").mkdir(rq.path)
|
||||
if r then
|
||||
result(r)
|
||||
else
|
||||
fail(m)
|
||||
end
|
||||
else
|
||||
fail("Uknown request")
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function VFSController:move(...)
|
||||
auth_or_die("User unauthorized. Please login")
|
||||
|
||||
local rq = (JSON.decodeString(REQUEST.query.json))
|
||||
|
||||
if rq ~= nil then
|
||||
local r, m = require("vfs").move(rq.src, rq.dest)
|
||||
if r then
|
||||
result(r)
|
||||
else
|
||||
fail(m)
|
||||
end
|
||||
else
|
||||
fail("Uknown request")
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function VFSController:publish(...)
|
||||
auth_or_die("User unauthorized. Please login")
|
||||
|
||||
local rq = (JSON.decodeString(REQUEST.query.json))
|
||||
|
||||
if rq ~= nil then
|
||||
local p = nil
|
||||
if rq.publish then
|
||||
p = require("vfs").ospath(rq.path)
|
||||
else
|
||||
p = require("shared").ospath(rq.path)
|
||||
end
|
||||
local user = SESSION.user
|
||||
local uid = ulib.uid(user)
|
||||
local st = ulib.file_stat(p)
|
||||
if uid.id ~= st.uid then
|
||||
die("Only the owner can share or unshare this file")
|
||||
end
|
||||
local entry = {sid = std.sha1(p), user = SESSION.user, path = p, uid = uid.id}
|
||||
local db = require("dbmodel").get("sysdb", "shared", entry)
|
||||
if db == nil then
|
||||
die("Cannot get system database")
|
||||
end
|
||||
local cond = nil
|
||||
if rq.publish then
|
||||
cond = {exp = {["="] = {path = p}}}
|
||||
local data = db:find(cond)
|
||||
if data == nil or data[0] == nil then
|
||||
-- insert entry
|
||||
db:insert(entry)
|
||||
end
|
||||
else
|
||||
cond = {["="] = {sid = rq.path}}
|
||||
db:delete(cond)
|
||||
end
|
||||
db:close()
|
||||
result(entry.sid)
|
||||
else
|
||||
fail("Uknown request")
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function VFSController:scandir(...)
|
||||
auth_or_die("User unauthorized. Please login")
|
||||
local rq = JSON.decodeString(REQUEST.query.json)
|
||||
local vfspath = rq.path
|
||||
local r = require("vfs").readDir(vfspath)
|
||||
if r == nil then
|
||||
fail("Resource not found: " .. rq.path)
|
||||
else
|
||||
--print(JSON.encode(readDir(ospath, vfspath)))
|
||||
result(r)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function VFSController:upload(...)
|
||||
auth_or_die("User unauthorized. Please login")
|
||||
local vfs = require("vfs")
|
||||
if REQUEST.query then
|
||||
local r, m = require("vfs").upload(REQUEST.query.path)
|
||||
if r then
|
||||
result(r)
|
||||
else
|
||||
fail(m)
|
||||
end
|
||||
else
|
||||
fail("Query not found")
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function VFSController:write(...)
|
||||
auth_or_die("User unauthorized. Please login")
|
||||
local rq = (JSON.decodeString(REQUEST.query.json))
|
||||
|
||||
if rq ~= nil then
|
||||
local r, m = require("vfs").write(rq.path, rq.data)
|
||||
sqlite.dbclose()
|
||||
if r then
|
||||
result(r)
|
||||
else
|
||||
fail(m)
|
||||
end
|
||||
else
|
||||
fail("Uknown request")
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function VFSController:shared(sid)
|
||||
require("shared").get(sid)
|
||||
end
|
Reference in New Issue
Block a user