# HG changeset patch # User Matthew Wild # Date 1611578660 0 # Node ID cba8cd5646413837bf907746c23f1c4ab933efd1 # Parent 950abc6c67b895d989161d61210de31315fe3263 mod_invites_register_api: New module to allow turning invites into accounts via a HTTP API diff -r 950abc6c67b8 -r cba8cd564641 mod_invites_register_api/mod_invites_register_api.lua --- /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; + }; +});