Diff

mod_invites_register_api/mod_invites_register_api.lua @ 4380:cba8cd564641

mod_invites_register_api: New module to allow turning invites into accounts via a HTTP API
author Matthew Wild <mwild1@gmail.com>
date Mon, 25 Jan 2021 12:44:20 +0000
child 4381:a1256e376dca
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_invites_register_api/mod_invites_register_api.lua	Mon Jan 25 12:44:20 2021 +0000
@@ -0,0 +1,118 @@
+local id = require "util.id";
+local json = require "util.json";
+local usermanager = require "core.usermanager";
+local nodeprep = require "util.encodings".stringprep.nodeprep;
+
+local site_name = module:get_option_string("site_name", module.host);
+
+local json_content_type = "application/json";
+
+module:depends("http");
+
+local invites = module:depends("invites");
+
+function get_invite_info(event, invite_token)
+	if not invite_token or #invite_token == 0 then
+		return 404;
+	end
+	local invite = invites.get(invite_token);
+	if not invite then
+		return 404;
+	end
+
+	event.response.headers["Content-Type"] = json_content_type;
+	return json.encode({
+		site_name = site_name;
+		token = invite.token;
+		domain = module.host;
+		uri = invite.uri;
+		type = invite.type;
+		jid = invite.jid;
+		inviter = invite.inviter;
+	});
+end
+
+function register_with_invite(event, invite_token)
+	if not invite_token or #invite_token == 0 then
+		return 404;
+	end
+
+	local request, response = event.request, event.response;
+
+	if not request.body or #request.body == 0
+	or request.headers.content_type ~= json_content_type then
+		module:log("warn", "Invalid payload");
+		return 400;
+	end
+
+	local register_data = json.decode(event.request.body);
+	if not register_data then
+		module:log("warn", "Invalid JSON");
+		return 400;
+	end
+
+	local user, password, token = register_data.username, register_data.password, register_data.token;
+
+	local invite = invites.get(token);
+	if not invite then
+		return 404;
+	end
+
+	response.headers["Content-Type"] = json_content_type;
+
+	if not user or #user == 0 or not password or #password == 0 or not token then
+		module:log("warn", "Invalid data");
+		return 400;
+	end
+
+	-- Shamelessly copied from mod_register_web.
+	local prepped_username = nodeprep(user);
+
+	if not prepped_username or #prepped_username == 0 then
+		return 400;
+	end
+
+	if usermanager.user_exists(prepped_username, module.host) then
+		return 409; -- Conflict
+	end
+
+	local registering = {
+		validated_invite = invite;
+		username = prepped_username;
+		host = module.host;
+		ip = request.ip;
+		allowed = true;
+	};
+
+	module:fire_event("user-registering", registering);
+
+	if not registering.allowed then
+		return 403;
+	end
+
+	local ok, err = usermanager.create_user(prepped_username, password, module.host);
+
+	if not ok then
+		local err_id = id.short();
+		module:log("warn", "Registration failed (%s): %s", err_id, tostring(err));
+		return 500;
+	end
+
+	module:fire_event("user-registered", {
+		username = prepped_username;
+		host = module.host;
+		source = "mod_"..module.name;
+		validated_invite = invite;
+		ip = request.ip;
+	});
+
+	return 200;
+end
+
+module:provides("http", {
+	default_path = "register_api";
+	route = {
+		["GET /invite/*"] = get_invite_info;
+		["POST /register/*"] = register_with_invite;
+	};
+});