mirror of
https://github.com/antos-rde/antos-backend.git
synced 2024-11-20 04:18:23 +01:00
News version of antos backend for luad fastcgi
This commit is contained in:
parent
389067f4d4
commit
116e304e76
41
Jenkinsfile
vendored
Normal file
41
Jenkinsfile
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
pipeline{
|
||||||
|
agent { node{ label'workstation' }}
|
||||||
|
options {
|
||||||
|
// Limit build history with buildDiscarder option:
|
||||||
|
// daysToKeepStr: history is only kept up to this many days.
|
||||||
|
// numToKeepStr: only this many build logs are kept.
|
||||||
|
// artifactDaysToKeepStr: artifacts are only kept up to this many days.
|
||||||
|
// artifactNumToKeepStr: only this many builds have their artifacts kept.
|
||||||
|
buildDiscarder(logRotator(numToKeepStr: "1"))
|
||||||
|
// Enable timestamps in build log console
|
||||||
|
timestamps()
|
||||||
|
// Maximum time to run the whole pipeline before canceling it
|
||||||
|
timeout(time: 1, unit: 'HOURS')
|
||||||
|
// Use Jenkins ANSI Color Plugin for log console
|
||||||
|
ansiColor('xterm')
|
||||||
|
// Limit build concurrency to 1 per branch
|
||||||
|
disableConcurrentBuilds()
|
||||||
|
}
|
||||||
|
stages
|
||||||
|
{
|
||||||
|
stage('Build') {
|
||||||
|
steps {
|
||||||
|
sh'''
|
||||||
|
cd $WORKSPACE
|
||||||
|
[ -d build ] && rm -rf build
|
||||||
|
mkdir -p build/opt/www/htdocs/os
|
||||||
|
export BUILDDIR="$WORKSPACE/build/opt/www/htdocs/os"
|
||||||
|
cp router.lua "$BUILDDIR"
|
||||||
|
cp -rf controllers "$BUILDDIR"
|
||||||
|
cp -rf libs "$BUILDDIR"
|
||||||
|
'''
|
||||||
|
script {
|
||||||
|
// only useful for any master branch
|
||||||
|
//if (env.BRANCH_NAME =~ /^master/) {
|
||||||
|
archiveArtifacts artifacts: 'build/', fingerprint: true
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,2 +1,4 @@
|
|||||||
# antos-backend
|
## AntOS lua-based backend
|
||||||
Backend implementation for AntOS
|
|
||||||
|
This backend is the reference implementation of AntOS server side API.
|
||||||
|
The backend is implemented for Antd webserver + fcgi plugin + luafcgi FastCGI server
|
33
controllers/IndexController.lua
Normal file
33
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 = "2.0.0-a",
|
||||||
|
documents = {
|
||||||
|
vfs = HTTP_ROOT.."/VFS",
|
||||||
|
vdb = HTTP_ROOT.."/VDB",
|
||||||
|
user = HTTP_ROOT.."/user",
|
||||||
|
system = HTTP_ROOT.."/system"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result(api)
|
||||||
|
return false
|
||||||
|
end
|
249
controllers/SystemController.lua
Normal file
249
controllers/SystemController.lua
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
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 file_path = ospath .. "/" .. ".settings.json"
|
||||||
|
local f = io.open(file_path, "w")
|
||||||
|
if f then
|
||||||
|
f:write(REQUEST.json)
|
||||||
|
f:close()
|
||||||
|
-- TODO: maybe use ulib
|
||||||
|
os.execute("chmod o-r "..file_path)
|
||||||
|
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 args={...}
|
||||||
|
local use_ws = false
|
||||||
|
if REQUEST and REQUEST.ws == "1" then
|
||||||
|
-- override the global cout command
|
||||||
|
cout = std.ws.t
|
||||||
|
echo = std.ws.t
|
||||||
|
use_ws = true
|
||||||
|
else
|
||||||
|
cout = function(e)
|
||||||
|
std.json()
|
||||||
|
echo(e)
|
||||||
|
end
|
||||||
|
-- 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
|
||||||
|
cout("Cannot set permission to execute the code")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local r, e
|
||||||
|
e = "{'error': 'Unknow function'}"
|
||||||
|
-- set env var
|
||||||
|
local home = ulib.home_dir(uid.id)
|
||||||
|
ulib.setenv("USER", SESSION.user, 1)
|
||||||
|
ulib.setenv("LOGNAME", SESSION.user, 1)
|
||||||
|
if home then
|
||||||
|
ulib.setenv("HOME", home, 1)
|
||||||
|
ulib.setenv("PWD", home,1)
|
||||||
|
local paths = ""
|
||||||
|
if ulib.exists(home.."/bin") then
|
||||||
|
paths = home.."/bin:"
|
||||||
|
end
|
||||||
|
if ulib.exists(home.."/.local/bin") then
|
||||||
|
paths = paths..home.."/.local/bin:"
|
||||||
|
end
|
||||||
|
local envar = ulib.getenv("PATH")
|
||||||
|
if envar then
|
||||||
|
paths = paths..envar
|
||||||
|
end
|
||||||
|
ulib.setenv("PATH", paths,1)
|
||||||
|
end
|
||||||
|
-- run the code as user
|
||||||
|
if data.code then
|
||||||
|
r, e = load(data.code)
|
||||||
|
if r then
|
||||||
|
local status, result = pcall(r)
|
||||||
|
if result then
|
||||||
|
if (status) then
|
||||||
|
cout(JSON.encode(result))
|
||||||
|
else
|
||||||
|
cout(result)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
cout(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 result then
|
||||||
|
if (status) then
|
||||||
|
cout(JSON.encode(result))
|
||||||
|
else
|
||||||
|
cout(result)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
cout(e)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
cout(e)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if (is_auth()) then
|
||||||
|
local pid = ulib.fork()--std.pfork(HTTP_REQUEST.id)
|
||||||
|
if (pid == -1) then
|
||||||
|
cout("{'error':'Cannot create process'}")
|
||||||
|
elseif pid > 0 then -- parent
|
||||||
|
-- wait for the child exit or websocket exit
|
||||||
|
ulib.waitpid(pid, 0)
|
||||||
|
--ulib.kill(pid)
|
||||||
|
LOG_INFO("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
|
||||||
|
LOG_WARN("Web socket Data is not masked")
|
||||||
|
std.ws.close(1012)
|
||||||
|
elseif header.opcode == std.ws.CLOSE then
|
||||||
|
LOG_DEBUG("Websocket 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(tostring(data)))
|
||||||
|
exec_with_user_priv(data)
|
||||||
|
std.ws.close(1011)
|
||||||
|
else
|
||||||
|
print("Error: Invalid request")
|
||||||
|
std.ws.close(1011)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
std.ws.close(1011)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
fail("Web socket is not available.")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if REQUEST.path then
|
||||||
|
exec_with_user_priv(REQUEST)
|
||||||
|
elseif REQUEST.json then
|
||||||
|
data = JSON.decodeString(REQUEST.json)
|
||||||
|
exec_with_user_priv(data)
|
||||||
|
elseif args and #args > 0 then
|
||||||
|
-- data is encoded in url safe base64
|
||||||
|
local encoded = args[1]:gsub('_', '/'):gsub('-', '+')
|
||||||
|
if #encoded % 4 == 2 then
|
||||||
|
encoded = encoded.."=="
|
||||||
|
elseif #encoded %4 == 3 then
|
||||||
|
encoded = encoded.."="
|
||||||
|
end
|
||||||
|
local decoded = enc.b64decode(encoded)
|
||||||
|
data = JSON.decodeString(tostring(decoded))
|
||||||
|
if data and data.path then
|
||||||
|
exec_with_user_priv(data)
|
||||||
|
else
|
||||||
|
fail("Unknown request")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
fail("Unkown request")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
print("Child exit")
|
||||||
|
ulib.kill(-1)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
cout('{"error":"User unauthorized. Please login"}')
|
||||||
|
end
|
||||||
|
end
|
102
controllers/UserController.lua
Normal file
102
controllers/UserController.lua
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
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.json ~= nil then
|
||||||
|
local request = JSON.decodeString(REQUEST.json)
|
||||||
|
local r = ulib.auth(request.username,request.password)
|
||||||
|
if r == true then
|
||||||
|
local salt = utils.generate_salt(20)
|
||||||
|
local cookie = {sessionid=enc.sha1(request.username..request.password..salt)} -- 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()
|
||||||
|
for k,v in pairs(cookie) do
|
||||||
|
--- TODO: add expire date to cookie
|
||||||
|
std.setCookie(k.."="..v, "Path=/")
|
||||||
|
end
|
||||||
|
std.json()
|
||||||
|
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
|
||||||
|
for k,v in pairs(cookie) do
|
||||||
|
std.setCookie(k.."="..v, "Path=/")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
std.json()
|
||||||
|
std.t(JSON.encode({error=false,result=true}))
|
||||||
|
end
|
130
controllers/VDBController.lua
Normal file
130
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.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.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.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.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
|
222
controllers/VFSController.lua
Normal file
222
controllers/VFSController.lua
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
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.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.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.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
|
||||||
|
std.sendFile(m)
|
||||||
|
else
|
||||||
|
fail(m)
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function VFSController:mkdir(...)
|
||||||
|
auth_or_die("User unauthorized. Please login")
|
||||||
|
|
||||||
|
local rq = (JSON.decodeString(REQUEST.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.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.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 = enc.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.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 and REQUEST.path then
|
||||||
|
local r, m = require("vfs").upload(REQUEST.path)
|
||||||
|
if r then
|
||||||
|
result(r)
|
||||||
|
else
|
||||||
|
self:error(m)
|
||||||
|
fail(m)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
fail("Invalid query")
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function VFSController:write(...)
|
||||||
|
auth_or_die("User unauthorized. Please login")
|
||||||
|
local rq = (JSON.decodeString(REQUEST.json))
|
||||||
|
|
||||||
|
if rq ~= nil then
|
||||||
|
local r, m = require("vfs").write(rq.path, rq.data)
|
||||||
|
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
|
80
libs/common.lua
Normal file
80
libs/common.lua
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
require("silk.core.sqlite")
|
||||||
|
local TUNNEL_KEYCHAIN = "/opt/www/tmp/channels/antunnel_keychain"
|
||||||
|
function fail(msg)
|
||||||
|
std.custom_header("Connection", "close")
|
||||||
|
std.json()
|
||||||
|
std.t(JSON.encode({
|
||||||
|
error = msg
|
||||||
|
}))
|
||||||
|
end
|
||||||
|
|
||||||
|
function result(obj)
|
||||||
|
std.custom_header("Connection", "close")
|
||||||
|
std.json()
|
||||||
|
std.t(JSON.encode({
|
||||||
|
result = obj,
|
||||||
|
error = false
|
||||||
|
}))
|
||||||
|
end
|
||||||
|
|
||||||
|
function die(msg)
|
||||||
|
fail(msg)
|
||||||
|
debug.traceback = nil
|
||||||
|
error("Permission denied")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- check if the sysdb is create, otherwise create the table
|
||||||
|
function sysdb()
|
||||||
|
local meta = {}
|
||||||
|
meta.sessionid = ""
|
||||||
|
meta.username = ""
|
||||||
|
meta.stamp = 0
|
||||||
|
return require("dbmodel").get("sysdb", "sessions", meta)
|
||||||
|
end
|
||||||
|
|
||||||
|
function is_auth()
|
||||||
|
local sessionid = nil
|
||||||
|
if SESSION.sessionid and SESSION.sessionid ~= '0' then
|
||||||
|
sessionid = SESSION.sessionid
|
||||||
|
-- should be used only by API call
|
||||||
|
elseif REQUEST.sessionid and REQUEST.sessionid ~= '0' then
|
||||||
|
sessionid = REQUEST.sessionid
|
||||||
|
elseif REQUEST.access_token and REQUEST.access_token ~= '0' then
|
||||||
|
sessionid = REQUEST.access_token
|
||||||
|
end
|
||||||
|
if sessionid == nil then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
-- query session id from database
|
||||||
|
local db = sysdb()
|
||||||
|
if db == nil then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local cond = {
|
||||||
|
exp = {
|
||||||
|
["="] = {
|
||||||
|
sessionid = sessionid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
local data = db:find(cond)
|
||||||
|
db:close()
|
||||||
|
if data == nil or data[1] == nil then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
-- TODO check the stamp
|
||||||
|
SESSION.user = data[1].username
|
||||||
|
local f = io.open(TUNNEL_KEYCHAIN, "w")
|
||||||
|
if f then
|
||||||
|
f:write(sessionid .. SESSION.user)
|
||||||
|
f:close()
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function auth_or_die(msg)
|
||||||
|
if (is_auth() == false) then
|
||||||
|
die(msg)
|
||||||
|
end
|
||||||
|
end
|
57
libs/dbmodel.lua
Normal file
57
libs/dbmodel.lua
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
local model = {}
|
||||||
|
|
||||||
|
model.get = function(name, tbl, data)
|
||||||
|
local mod = {
|
||||||
|
name = tbl,
|
||||||
|
db = DBModel:new{db = name}
|
||||||
|
}
|
||||||
|
function mod:close()
|
||||||
|
self.db:close()
|
||||||
|
end
|
||||||
|
function mod:open()
|
||||||
|
self.db:open()
|
||||||
|
end
|
||||||
|
function mod:createTable(m)
|
||||||
|
return self.db:createTable(self.name,m)
|
||||||
|
end
|
||||||
|
function mod:insert(m)
|
||||||
|
return self.db:insert(self.name,m)
|
||||||
|
end
|
||||||
|
function mod:get(id)
|
||||||
|
return self.db:get(self.name, id)
|
||||||
|
end
|
||||||
|
function mod:getAll()
|
||||||
|
return self.db:getAll(self.name)
|
||||||
|
end
|
||||||
|
function mod:find(cond)
|
||||||
|
return self.db:find(self.name, cond)
|
||||||
|
end
|
||||||
|
function mod:update(m)
|
||||||
|
return self.db:update(self.name, m)
|
||||||
|
end
|
||||||
|
function mod:available()
|
||||||
|
return self.db:available(self.name)
|
||||||
|
end
|
||||||
|
function mod:delete(cond)
|
||||||
|
return self.db:delete(self.name, cond)
|
||||||
|
end
|
||||||
|
function mod:deleteByID(id)
|
||||||
|
return self.db:deleteByID(self.name, id)
|
||||||
|
end
|
||||||
|
mod:open()
|
||||||
|
|
||||||
|
if mod:available() then return mod end
|
||||||
|
if data == nil then return nil end
|
||||||
|
local meta = {}
|
||||||
|
--print(JSON.encode(data))
|
||||||
|
for k,v in pairs(data) do
|
||||||
|
if type(v) == "number" or type(v) == "boolean" then
|
||||||
|
meta[k] = "NUMERIC"
|
||||||
|
else
|
||||||
|
meta[k] = "TEXT"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
mod:createTable(meta)
|
||||||
|
return mod
|
||||||
|
end
|
||||||
|
return model
|
119
libs/packages.lua
Normal file
119
libs/packages.lua
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
local packages={}
|
||||||
|
local vfs = require("vfs")
|
||||||
|
local uid = ulib.uid(SESSION.user)
|
||||||
|
|
||||||
|
packages._cache = function(y)
|
||||||
|
local p = vfs.ospath(y)
|
||||||
|
local f = io.open(p.."/packages.json", "w")
|
||||||
|
local has_cache = false
|
||||||
|
local i = 1
|
||||||
|
local meta = {}
|
||||||
|
if f then
|
||||||
|
local files = vfs.readDir(y)
|
||||||
|
for k,v in pairs(files) do
|
||||||
|
if v.type == "dir" then
|
||||||
|
local f1 = io.open(vfs.ospath(v.path.."/package.json"))
|
||||||
|
if f1 then
|
||||||
|
|
||||||
|
local name = utils.basename(v.path)
|
||||||
|
local mt = JSON.decodeString(f1:read("*all"))
|
||||||
|
mt.path = v.path
|
||||||
|
meta[i] ='"'..name..'":'..JSON.encode(mt)
|
||||||
|
i = i+1
|
||||||
|
f1:close()
|
||||||
|
has_cache = true;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
f:write(table.concat(meta, ","))
|
||||||
|
f:close()
|
||||||
|
if has_cache == false then
|
||||||
|
ulib.delete(p.."/packages.json");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- we will change this later
|
||||||
|
packages.list = function(paths)
|
||||||
|
std.json()
|
||||||
|
std.t("{\"result\" : { ")
|
||||||
|
local first = true
|
||||||
|
--std.f(__ROOT__.."/system/packages.json")
|
||||||
|
for k,v in pairs(paths) do
|
||||||
|
local osp = vfs.ospath(v.."/packages.json")
|
||||||
|
if ulib.exists(osp) == false then
|
||||||
|
packages._cache(v)
|
||||||
|
end
|
||||||
|
if ulib.exists(osp) then
|
||||||
|
if first == false then
|
||||||
|
std.t(",")
|
||||||
|
else
|
||||||
|
first = false
|
||||||
|
end
|
||||||
|
std.f(osp)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
std.t("}, \"error\":false}")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- generate the packages caches
|
||||||
|
packages.cache = function(args)
|
||||||
|
-- perform a packages caches
|
||||||
|
for x,y in pairs(args.paths) do
|
||||||
|
packages._cache(y)
|
||||||
|
end
|
||||||
|
result(true)
|
||||||
|
end
|
||||||
|
-- install a function from zip file
|
||||||
|
packages.install = function(args)
|
||||||
|
local path = vfs.ospath(args.dest)
|
||||||
|
local zip = vfs.ospath(args.zip)
|
||||||
|
if(ulib.exists(path) == false) then
|
||||||
|
-- create directory if not exist
|
||||||
|
ulib.mkdir(path)
|
||||||
|
-- change permission
|
||||||
|
ulib.chown(path, uid.id, uid.gid)
|
||||||
|
end
|
||||||
|
-- extract the zip file to it
|
||||||
|
if(ulib.unzip(zip, path)) then
|
||||||
|
-- read metadata
|
||||||
|
local meta = JSON.decodeFile(path.."/metadata.json")
|
||||||
|
meta.path = args.dest
|
||||||
|
meta.scope = "user"
|
||||||
|
local f=io.open(path.."/package.json","w")
|
||||||
|
if f then
|
||||||
|
f:write(JSON.encode(meta))
|
||||||
|
f:close()
|
||||||
|
end
|
||||||
|
result(true)
|
||||||
|
else
|
||||||
|
fail("Problem extracting zip file")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
-- uninstall the package
|
||||||
|
packages.uninstall = function(path)
|
||||||
|
local osf = vfs.ospath(path)
|
||||||
|
if(osf and ulib.exists(osf) ) then
|
||||||
|
--remove it
|
||||||
|
ulib.delete(osf)
|
||||||
|
result(true)
|
||||||
|
else
|
||||||
|
fail("Cannot find package")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- set user packages environment
|
||||||
|
packages.init = function(paths)
|
||||||
|
if(paths) then
|
||||||
|
for k,v in pairs(paths) do
|
||||||
|
local p = vfs.ospath(v)
|
||||||
|
if p and (ulib.exists(p) == false) then
|
||||||
|
ulib.mkdir(p)
|
||||||
|
-- change permission
|
||||||
|
ulib.chown(p, uid.id, uid.gid)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return packages
|
45
libs/shared.lua
Normal file
45
libs/shared.lua
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
local shared = {}
|
||||||
|
shared.get = function(sharedid)
|
||||||
|
if sharedid == "all" then
|
||||||
|
-- get all shared files
|
||||||
|
local db = require("dbmodel").get("sysdb", "shared", nil)
|
||||||
|
if db == nil then die("Cannot get shared database") end
|
||||||
|
local data = db:getAll()
|
||||||
|
if data == nil then die("No file found") end
|
||||||
|
local i = 1
|
||||||
|
local ret = {}
|
||||||
|
for k,v in pairs(data) do
|
||||||
|
if(ulib.exists(v.path)) then
|
||||||
|
local r = ulib.file_stat(v.path)
|
||||||
|
if(r.error == nil) then
|
||||||
|
r.path = "shared://"..v.sid
|
||||||
|
r.filename = utils.basename(v.path)
|
||||||
|
r.mime = std.mimeOf(r.filename)
|
||||||
|
ret[i] = r
|
||||||
|
i = i+1
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local cond = { ["="] = { sid = v.sid } }
|
||||||
|
db:delete(cond)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
db:close()
|
||||||
|
--std.json()
|
||||||
|
result(ret)
|
||||||
|
else
|
||||||
|
|
||||||
|
local p = shared.ospath(sharedid)
|
||||||
|
std.sendFile(p)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
shared.ospath = function(sharedid)
|
||||||
|
local db = require("dbmodel").get("sysdb", "shared", nil)
|
||||||
|
if db == nil then die("Cannot get shared database") end
|
||||||
|
local cond = { exp = { ["="] = { sid = sharedid } } }
|
||||||
|
local data = db:find(cond)
|
||||||
|
db:close()
|
||||||
|
if data == nil or data[1] == nil then die("Cannot get shared file with: "..sharedid) end
|
||||||
|
return data[1].path
|
||||||
|
end
|
||||||
|
return shared;
|
27
libs/uman.lua
Normal file
27
libs/uman.lua
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
local uman={}
|
||||||
|
|
||||||
|
uman.userinfo = function(user)
|
||||||
|
local info = {}
|
||||||
|
local uid = ulib.uid(user)
|
||||||
|
if uid then
|
||||||
|
-- read the setting
|
||||||
|
-- use the decodeFile function of JSON instead
|
||||||
|
local file = require('vfs').ospath("home:///").."/.settings.json"
|
||||||
|
local st = JSON.decodeFile(file)
|
||||||
|
if(st) then
|
||||||
|
info = st
|
||||||
|
end
|
||||||
|
info.user = {
|
||||||
|
username = user,
|
||||||
|
id = uid.id,
|
||||||
|
name = user,
|
||||||
|
groups = uid.groups
|
||||||
|
}
|
||||||
|
--print(JSON.encode(info))
|
||||||
|
return info
|
||||||
|
else
|
||||||
|
return {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return uman
|
241
libs/vfs.lua
Normal file
241
libs/vfs.lua
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
local vfs = {}
|
||||||
|
|
||||||
|
vfs.ospath = function(path)
|
||||||
|
local user = SESSION.user
|
||||||
|
local prefix = string.match(path, "%a+:/")
|
||||||
|
if (prefix ~= nil) then
|
||||||
|
local suffix = string.gsub(path, prefix, "")
|
||||||
|
if prefix == "home:/" then
|
||||||
|
return string.format(VFS_HOME, user) .. '/' .. suffix
|
||||||
|
elseif prefix == "desktop:/" then
|
||||||
|
return string.format(VFS_HOME, user) .. "/.desktop/" .. suffix
|
||||||
|
elseif prefix == "shared:/" then
|
||||||
|
return require("shared").ospath(ulib.trim(suffix, "/"))
|
||||||
|
elseif prefix == "os:/" then
|
||||||
|
return WWW_ROOT .. "/" .. suffix
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return nil;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
vfs.delete = function(path)
|
||||||
|
local r, m = vfs.checkperm(path, "write")
|
||||||
|
if r then
|
||||||
|
if ulib.delete(m) then
|
||||||
|
-- change permission
|
||||||
|
return true, nil
|
||||||
|
else
|
||||||
|
return false, "Cant not delete the file"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return r, m
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
vfs.exists = function(path)
|
||||||
|
local osfile = vfs.ospath(path)
|
||||||
|
return ulib.exists(osfile)
|
||||||
|
end
|
||||||
|
|
||||||
|
vfs.fileinfo = function(vfspath)
|
||||||
|
local ospath = vfs.ospath(vfspath)
|
||||||
|
if ospath then
|
||||||
|
if (ulib.exists(ospath) == false) then
|
||||||
|
return false, "File not found"
|
||||||
|
end
|
||||||
|
local r = ulib.file_stat(ospath)
|
||||||
|
if (r.error ~= nil) then
|
||||||
|
return false, r.error
|
||||||
|
end
|
||||||
|
r.path = vfspath
|
||||||
|
r.name = utils.basename(vfspath)
|
||||||
|
r.mime = std.mimeOf(r.name)
|
||||||
|
return true, r
|
||||||
|
else
|
||||||
|
return false, "Resource not found"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
vfs.mkdir = function(path)
|
||||||
|
local file = utils.basename(path)
|
||||||
|
local folder = string.gsub(path, utils.escape_pattern(file) .. "$", "")
|
||||||
|
local r, m = vfs.checkperm(folder, "write")
|
||||||
|
|
||||||
|
if r then
|
||||||
|
local osfile = m .. "/" .. file
|
||||||
|
local uid = ulib.uid(SESSION.user)
|
||||||
|
ulib.mkdir(osfile)
|
||||||
|
-- change permission
|
||||||
|
ulib.chown(osfile, uid.id, uid.gid)
|
||||||
|
return true, nil
|
||||||
|
else
|
||||||
|
return r, m
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
vfs.move = function(src, dest)
|
||||||
|
local file = utils.basename(dest)
|
||||||
|
local folder = string.gsub(dest, utils.escape_pattern(file), "")
|
||||||
|
|
||||||
|
local sp, sm = vfs.checkperm(src, "write")
|
||||||
|
if sp then
|
||||||
|
local dp, dm = vfs.checkperm(folder, "write")
|
||||||
|
if dp then
|
||||||
|
ulib.move(sm, dm .. "/" .. file)
|
||||||
|
-- change permission
|
||||||
|
return true, nil
|
||||||
|
else
|
||||||
|
return dp, dm
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return sp, sm
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
vfs.write = function(path, data)
|
||||||
|
local file = utils.basename(path)
|
||||||
|
local folder = string.gsub(path, utils.escape_pattern(file), "")
|
||||||
|
|
||||||
|
local r, m = vfs.checkperm(folder, "write")
|
||||||
|
if r then
|
||||||
|
local osfile = m .. "/" .. file
|
||||||
|
|
||||||
|
if ulib.exists(osfile) then
|
||||||
|
local r1, m1 = vfs.checkperm(path, "write")
|
||||||
|
if not r1 then
|
||||||
|
return r1, m1 .. ": " .. path
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local uid = ulib.uid(SESSION.user)
|
||||||
|
--
|
||||||
|
if data ~= "" then
|
||||||
|
local header = string.match(data, "^data%:[%w%.-%+]+%/[%w%.-%+]+;base64,")
|
||||||
|
if header ~= nil then
|
||||||
|
local b64data = string.gsub(data, utils.escape_pattern(header), "")
|
||||||
|
local barr = enc.b64decode(b64data)
|
||||||
|
|
||||||
|
barr:fileout(osfile)
|
||||||
|
--[[ if std.isBinary(osfile) then
|
||||||
|
|
||||||
|
else
|
||||||
|
local f = io.open(osfile, "w")
|
||||||
|
f:write(bytes.__tostring(barr))
|
||||||
|
f:close()
|
||||||
|
end ]]
|
||||||
|
else
|
||||||
|
return false, "Wrong data format"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
slice.new(0):fileout(osfile)
|
||||||
|
end
|
||||||
|
-- f:close()
|
||||||
|
-- change permission
|
||||||
|
ulib.chown(osfile, uid.id, uid.gid)
|
||||||
|
return true, nil
|
||||||
|
else
|
||||||
|
return r, m .. ": " .. folder
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
vfs.upload = function(path)
|
||||||
|
if (not path) then
|
||||||
|
return false, "Unknown upload destination, abort!"
|
||||||
|
end
|
||||||
|
local r, m = vfs.checkperm(path, "write")
|
||||||
|
if (r) then
|
||||||
|
local uid = ulib.uid(SESSION.user)
|
||||||
|
local index = 0
|
||||||
|
while (REQUEST["upload-" .. index .. ".tmp"] ~= nil) do
|
||||||
|
local file = m .. "/" .. REQUEST["upload-" .. index .. ".file"]
|
||||||
|
local ret = ulib.move(REQUEST["upload-" .. index .. ".tmp"], file)
|
||||||
|
if not ret then
|
||||||
|
ret = ulib.send_file(REQUEST["upload-" .. index .. ".tmp"], file)
|
||||||
|
end
|
||||||
|
if not ret then
|
||||||
|
return false, "Unable to copy file"
|
||||||
|
end
|
||||||
|
ulib.chown(file, uid.id, uid.gid)
|
||||||
|
index = index + 1
|
||||||
|
end
|
||||||
|
if (index == 0) then
|
||||||
|
return false, "No file is uploaded"
|
||||||
|
end
|
||||||
|
return true, index
|
||||||
|
else
|
||||||
|
return r, m
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
vfs.checkperm = function(path, right)
|
||||||
|
if path:match("^shared:/.*") then
|
||||||
|
if right == "write" then
|
||||||
|
return false, "Shared file is readonly"
|
||||||
|
else
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local osfile = vfs.ospath(path)
|
||||||
|
local perm = vfs.perm(osfile)
|
||||||
|
-- print(osfile)
|
||||||
|
if not ulib.exists(osfile) then
|
||||||
|
return false, "Resource does not exist"
|
||||||
|
end
|
||||||
|
-- check if user own the file
|
||||||
|
if perm ~= nil then
|
||||||
|
if perm[right] == true then
|
||||||
|
-- print("Permission granted")
|
||||||
|
return true, osfile
|
||||||
|
else
|
||||||
|
LOG_INFO("Permission denie")
|
||||||
|
return false, "You dont have " .. right .. " permission on this file"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return false, "User is unrecognized"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
vfs.perm = function(file)
|
||||||
|
local user = SESSION.user
|
||||||
|
local uid = ulib.uid(user)
|
||||||
|
local st = ulib.file_stat(file)
|
||||||
|
-- check if user own the file
|
||||||
|
if uid ~= nil and st ~= nil and st.perm ~= nil then
|
||||||
|
-- print(JSON.encode({uid, st}))
|
||||||
|
if (uid.id == st.uid) then -- the user owned the file
|
||||||
|
-- print("file belong to user")
|
||||||
|
return st.perm.owner
|
||||||
|
elseif uid.groups and uid.groups[st.gid] then
|
||||||
|
-- print("User belong to this group")
|
||||||
|
return st.perm.group
|
||||||
|
else
|
||||||
|
-- print("User belong to other")
|
||||||
|
return st.perm.other
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
vfs.readDir = function(vfspath)
|
||||||
|
if (string.sub(vfspath, -1) == "/") then
|
||||||
|
prefix = string.sub(vfspath, 1, -2)
|
||||||
|
else
|
||||||
|
prefix = vfspath
|
||||||
|
end
|
||||||
|
local ospath = vfs.ospath(vfspath)
|
||||||
|
local r = ulib.read_dir(ospath, prefix)
|
||||||
|
if (r.error ~= nil) then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
-- add extra mime type
|
||||||
|
for k, v in pairs(r) do
|
||||||
|
v.mime = std.mimeOf(v.filename)
|
||||||
|
end
|
||||||
|
return r
|
||||||
|
end
|
||||||
|
|
||||||
|
return vfs
|
46
router.lua
Normal file
46
router.lua
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
|
||||||
|
-- the rewrite rule for the framework
|
||||||
|
-- should be something like this
|
||||||
|
-- ^\/apps\/+(.*)$ = /apps/router.lua?r=<1>&<query>
|
||||||
|
-- some global variables
|
||||||
|
package.path = _SERVER["LIB_DIR"].."/lua/?.lua"
|
||||||
|
require("silk.api")
|
||||||
|
-- crypto lib
|
||||||
|
enc = require("enc")
|
||||||
|
WWW_ROOT = __ROOT__.."/os"
|
||||||
|
|
||||||
|
-- add aditional paths
|
||||||
|
package.path = package.path..";"..WWW_ROOT .. '/libs/?.lua'
|
||||||
|
-- require needed library
|
||||||
|
require("common")
|
||||||
|
|
||||||
|
DIR_SEP = "/"
|
||||||
|
VFS_HOME = "/home/%s"
|
||||||
|
-- class path: path.to.class
|
||||||
|
CONTROLLER_ROOT = "os.controllers"
|
||||||
|
MODEL_ROOT = "os.models"
|
||||||
|
-- file path: path/to/file
|
||||||
|
VIEW_ROOT = WWW_ROOT..DIR_SEP.."views"
|
||||||
|
|
||||||
|
if HEADER.Host then
|
||||||
|
HTTP_ROOT= "https://"..HEADER["Host"]
|
||||||
|
else
|
||||||
|
HTTP_ROOT = "https://os.lxsang.me"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- registry object store global variables
|
||||||
|
local REGISTRY = {}
|
||||||
|
-- set logging level
|
||||||
|
REGISTRY.logger = Logger:new{ level = Logger.INFO}
|
||||||
|
--REGISTRY.db = DBHelper:new{db="sysdb"}
|
||||||
|
REGISTRY.layout = 'default'
|
||||||
|
REGISTRY.fileaccess = true
|
||||||
|
|
||||||
|
--REGISTRY.db:open()
|
||||||
|
local router = Router:new{registry = REGISTRY}
|
||||||
|
REGISTRY.router = router
|
||||||
|
router:setPath(CONTROLLER_ROOT)
|
||||||
|
|
||||||
|
router:delegate()
|
||||||
|
--if REGISTRY.db then REGISTRY.db:close() end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user