http: Handler logic improvements (affects auth, config, templates)

Thu, 22 Jun 2023 21:27:34 +0100

author
Matthew Wild <mwild1@gmail.com>
date
Thu, 22 Jun 2023 21:27:34 +0100
changeset 12
dfa7cb60647e
parent 11
635b385df3a2
child 13
763288302cf0

http: Handler logic improvements (affects auth, config, templates)

src/http.lua file | annotate | diff | comparison | revisions
--- a/src/http.lua	Thu Jun 22 21:25:35 2023 +0100
+++ b/src/http.lua	Thu Jun 22 21:27:34 2023 +0100
@@ -15,19 +15,6 @@
 
 local log = require "util.logger".init("web");
 
-local usercookie = require"util.usercookie";
-local secret = uuid.generate();
-
-local check_auth = require "app.auth".check_auth;
-
-local function set_auth_cookie(username, response)
-	local expires = config.cookie_ttl or 604800;
-	local cookie = usercookie.generate(username, os.time()+expires, secret);
-	cookie = "remember=".. cookie .. "; Path="..config.base_path
-		.."; Max-Age="..tostring(expires).."; HttpOnly";
-	return web.set_cookie(response.headers, cookie);
-end
-
 local csrf_token_len = #uuid.generate();
 
 local function check_csrf(event, viewdata)
@@ -44,30 +31,44 @@
 	end
 end
 
-local function wrap_handler(f, t, path_prefix_len)
+local function wrap_handler(f, default_tpl, path_prefix_len, check_auth)
 	return function (event)
 		log("debug", "Check auth...");
-		local authed = check_auth(event.request, config);
+		local request = event.request;
+		local authed, handler_override = check_auth(request, config);
+		if authed and not request.authenticated then
+			request.authenticated = authed;
+		end
 		log("debug", "Checked, %s", authed);
 		event.config = config;
 		local sub_path = nil;
 		if path_prefix_len then
 			sub_path = event.request.path:sub(path_prefix_len+2);
 		end
-		local p = f(event, sub_path);
-		return promise.resolve(p):next(function (resp)
-			if type(resp) == "table" then
+
+		local h = handler_override or f;
+
+		local p, custom_tpl;
+		if web.is_response(h) then
+			p = h;
+		else
+			p, custom_tpl = (handler_override or f)(event, sub_path);
+		end
+
+		-- Process response (may be promises)
+		return promise.join(function (resp, tpl)
+			if type(resp) == "table" and not web.is_response(resp) then
 				local headers = event.response.headers;
 				local accept = event.request.headers.accept or "";
 				web.add_header(headers, "vary", "Accept, Cookie");
 				if accept:find"application/json" then
 					headers.content_type = "application/json";
 					return json.encode(resp);
-				elseif t then
+				elseif tpl then
 					if authed or event.needs_csrf then check_csrf(event, resp); end
 					resp.authenticated = event.request.authenticated;
 					resp.config = config;
-					resp = render(t, resp);
+					resp = render(tpl, resp);
 					if not headers.content_type then
 						headers.content_type = "text/html; charset=utf-8";
 					end
@@ -76,7 +77,7 @@
 				end
 			end
 			return resp;
-		end):catch(function (err)
+		end, p, custom_tpl or default_tpl):catch(function (err)
 			log("error", "Failed inside handler wrapper: %s", json.encode(err));
 			return promise.reject(errors.wrap(err));
 		end);
@@ -133,10 +134,10 @@
 	end
 end
 
-local function register_handlers(handlers, event_base, path_prefix)
+local function register_handlers(handlers, event_base, path_prefix, check_auth)
 	for method_path, handler in pairs(handlers) do
 		if type(handler) == "table" then
-			register_handlers(handler, event_base, (path_prefix and (path_prefix.."/") or "")..method_path);
+			register_handlers(handler, event_base, (path_prefix and (path_prefix.."/") or "")..method_path, check_auth);
 		else
 			local method, path, wildcard = method_path:match"^(%w+)_(.-)(_?)$";
 			method = method:upper();
@@ -161,7 +162,7 @@
 				path_prefix_len = #path+1;
 			end
 
-			handler = wrap_handler(handler, templates[template_name], path_prefix_len);
+			handler = wrap_handler(handler, templates[template_name], path_prefix_len, check_auth);
 			local head_event = event_base:format("HEAD", path, wildcard);
 			http_server.add_handler(head_event, head_handler(handler));
 
@@ -181,11 +182,14 @@
 	local base_path = url.parse_path(config.base_path or base_url.path or "/");
 	base_path.is_directory = true;
 	base_url.path = url.build_path(base_path);
+	config.templates = templates;
 	config.base_host = base_url.host;
 	config.base_path = base_url.path;
 	config.base_url = url.build(base_url);
 	local event_base = ("%%s %s%s%%s%%s"):format(base_url.host, base_url.path);
 
+	_G.CONFIG = config;
+	local check_auth = require "app.auth".check_auth;
 	local handlers = require "app.routes";
 
 	handlers.get_static_ = files.serve { path = "./static", http_base = base_url.path.."static" };
@@ -196,7 +200,7 @@
 		return handle_error(error, config)
 	end);
 
-	register_handlers(handlers, event_base);
+	register_handlers(handlers, event_base, nil, check_auth);
 
 	local listen_port = config.listen_port or 8007;
 	local listen_interface = config.listen_interface or "*";
@@ -207,4 +211,6 @@
 return {
 	init = init;
 	render = render;
+	set_auth_cookie = set_auth_cookie;
+	get_auth_cookie = get_auth_cookie;
 }

mercurial