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.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 and REQUEST.json then local f = io.open(ospath .. "/" .. ".settings.json", "w") if f then f:write(REQUEST.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.json ~= nil then rq = (JSON.decodeString(REQUEST.json)) else rq = REQUEST 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 and REQUEST.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 local ospath = require("vfs").ospath(data.path) r, e = loadfile(ospath) 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 or websocket exit ulib.waitpid(pid, 0) 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.json then data = JSON.decodeString(REQUEST.json) --std.json() exec_with_user_priv(data) else fail("Unkown request") end end print("Child exit") ulib.kill(-1) end else echo('{"error":"User unauthorized. Please login"}') end end