summaryrefslogtreecommitdiffstats
path: root/server.lua
diff options
context:
space:
mode:
Diffstat (limited to 'server.lua')
-rw-r--r--server.lua76
1 files changed, 60 insertions, 16 deletions
diff --git a/server.lua b/server.lua
index 11bfe55..c6fe586 100644
--- a/server.lua
+++ b/server.lua
@@ -1,5 +1,5 @@
--[[
-Copyright (c) 2012 Kaarle Ritvanen
+Copyright (c) 2012-2013 Kaarle Ritvanen
See LICENSE file for license details
--]]
@@ -10,13 +10,7 @@ require 'json'
require 'stringy'
-local function handle(env, txn, path)
- local method = env.REQUEST_METHOD
- local data
- if env.CONTENT_LENGTH then
- data = json.decode(env.input:read(env.CONTENT_LENGTH))
- end
-
+local function handle(txn, method, path, data)
local parent, name
if path ~= '/' then
parent = txn:search(acf.path.parent(path))
@@ -60,30 +54,80 @@ local function handle(env, txn, path)
end
+-- TODO shared storage for login sessions
+local last_sid = 0
+local sessions = {}
+
-- TODO implement transactions as threads or store their state in
-- shared storage
-local last_id = 0
+local last_txn_id = 0
local txns = {}
+-- TODO expire stale sessions and transactions
+
return function(env)
local method = env.REQUEST_METHOD
local path = env.REQUEST_URI
- -- TODO login session management
+ local data
+ if env.CONTENT_LENGTH then
+ data = json.decode(env.input:read(env.CONTENT_LENGTH))
+ end
+
+ local sid = tonumber(env.HTTP_X_ACF_AUTH_TOKEN)
+ local user, txn_id
+ if sid then
+ user = sessions[sid]
+ if not user then return 401 end
+ txn_id = tonumber(env.HTTP_X_ACF_TRANSACTION_ID)
+ end
- local txn_id = tonumber(env.HTTP_X_ACF_TRANSACTION_ID)
local txn
if txn_id then
txn = txns[txn_id]
if not txn then return 404 end
else txn = acf.transaction.start() end
+ local function fetch_user(name)
+ user = name and txn:search('/auth/users')[name]
+ end
+ if user then
+ fetch_user(user)
+ if not user then return 401 end
+ end
+
+ if path == '/login' then
+ if method == 'POST' then
+ if not data.username or not data.password then return 401 end
+ fetch_user(data.username)
+ if user and user:check_password(data.password) then
+ last_sid = last_sid + 1
+ local sid = last_sid
+ sessions[sid] = data.username
+ return 200, {['X-ACF-Auth-Token']=sid}
+ end
+ return 401
+ end
+
+ if not user then return 401 end
+
+ if method == 'DELETE' then
+ sessions[sid] = nil
+ return 200
+ end
+
+ return 405
+ end
+
+ if not user then return 401 end
+
if stringy.startswith(path, '/config/') then
-- TODO catch and forward relevant errors to the client
- local code, hdr, body = handle(env,
- txn,
- string.sub(path, 8, -1))
+ local code, hdr, body = handle(txn,
+ method,
+ string.sub(path, 8, -1),
+ data)
if not txn_id and method ~= 'GET' and code == 200 then
txn:commit()
end
@@ -105,8 +149,8 @@ return function(env)
if method == 'DELETE' then return 405 end
- last_id = last_id + 1
- local txn_id = last_id
+ last_txn_id = last_txn_id + 1
+ local txn_id = last_txn_id
txns[txn_id] = txn
return 200, {['X-ACF-Transaction-ID']=txn_id}
end