From 544ea51c3663070dadd588d9de3e22d6e045743e Mon Sep 17 00:00:00 2001 From: Kaarle Ritvanen Date: Wed, 27 Feb 2013 07:39:26 +0000 Subject: basic login session management --- server.lua | 76 +++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 16 deletions(-) (limited to 'server.lua') 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 -- cgit v1.2.3