Mercurial > prosody-modules
comparison mod_invites_register_web/mod_invites_register_web.lua @ 4093:a2116f5a7c8f
mod_invites_register_web: New module to allow web registration with an invite token
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Fri, 11 Sep 2020 13:51:54 +0100 |
parents | |
children | f49e3ea99785 |
comparison
equal
deleted
inserted
replaced
4092:2b6918714792 | 4093:a2116f5a7c8f |
---|---|
1 local id = require "util.id"; | |
2 local http_formdecode = require "net.http".formdecode; | |
3 local usermanager = require "core.usermanager"; | |
4 local nodeprep = require "util.encodings".stringprep.nodeprep; | |
5 local st = require "util.stanza"; | |
6 local url_escape = require "util.http".urlencode; | |
7 local render_html_template = require"util.interpolation".new("%b{}", st.xml_escape, { | |
8 urlescape = url_escape; | |
9 }); | |
10 | |
11 | |
12 module:depends("register_apps"); | |
13 | |
14 local site_name = module:get_option_string("site_name", module.host); | |
15 local site_apps = module:shared("register_apps/apps"); | |
16 | |
17 module:depends("http"); | |
18 module:depends("easy_invite"); | |
19 local invites = module:depends("invites"); | |
20 local invites_page = module:depends("invites_page"); | |
21 | |
22 function serve_register_page(event) | |
23 local register_page_template = assert(module:load_resource("html/register.html")):read("*a"); | |
24 | |
25 local query_params = http_formdecode(event.request.url.query); | |
26 | |
27 local invite = invites.get(query_params.t); | |
28 if not invite then | |
29 return { | |
30 status_code = 303; | |
31 headers = { | |
32 ["Location"] = invites.module:http_url().."?"..event.request.url.query; | |
33 }; | |
34 }; | |
35 end | |
36 | |
37 local invite_page = render_html_template(register_page_template, { | |
38 site_name = site_name; | |
39 token = invite.token; | |
40 domain = module.host; | |
41 uri = invite.uri; | |
42 type = invite.type; | |
43 jid = invite.jid; | |
44 inviter = invite.inviter; | |
45 app = query_params.c and site_apps[query_params.c]; | |
46 }); | |
47 return invite_page; | |
48 end | |
49 | |
50 function handle_register_form(event) | |
51 local request, response = event.request, event.response; | |
52 local form_data = http_formdecode(request.body); | |
53 local user, password, token = form_data["user"], form_data["password"], form_data["token"]; | |
54 local app_id = form_data["app_id"]; | |
55 | |
56 local register_page_template = assert(module:load_resource("html/register.html")):read("*a"); | |
57 local error_template = assert(module:load_resource("html/register_error.html")):read("*a"); | |
58 | |
59 local invite = invites.get(token); | |
60 if not invite then | |
61 return { | |
62 status_code = 303; | |
63 headers = { | |
64 ["Location"] = invites_page.module:http_url().."?"..event.request.url.query; | |
65 }; | |
66 }; | |
67 end | |
68 | |
69 response.headers.content_type = "text/html; charset=utf-8"; | |
70 | |
71 if not user or #user == 0 or not password or #password == 0 or not token then | |
72 return render_html_template(register_page_template, { | |
73 site_name = site_name; | |
74 token = invite.token; | |
75 domain = module.host; | |
76 uri = invite.uri; | |
77 type = invite.type; | |
78 jid = invite.jid; | |
79 | |
80 msg_class = "alert-warning"; | |
81 message = "Please fill in all fields."; | |
82 }); | |
83 end | |
84 | |
85 -- Shamelessly copied from mod_register_web. | |
86 local prepped_username = nodeprep(user); | |
87 | |
88 if not prepped_username or #prepped_username == 0 then | |
89 return render_html_template(register_page_template, { | |
90 site_name = site_name; | |
91 token = invite.token; | |
92 domain = module.host; | |
93 uri = invite.uri; | |
94 type = invite.type; | |
95 jid = invite.jid; | |
96 | |
97 msg_class = "alert-warning"; | |
98 message = "This username contains invalid characters."; | |
99 }); | |
100 end | |
101 | |
102 if usermanager.user_exists(prepped_username, module.host) then | |
103 return render_html_template(register_page_template, { | |
104 site_name = site_name; | |
105 token = invite.token; | |
106 domain = module.host; | |
107 uri = invite.uri; | |
108 type = invite.type; | |
109 jid = invite.jid; | |
110 | |
111 msg_class = "alert-warning"; | |
112 message = "This username is already in use."; | |
113 }); | |
114 end | |
115 | |
116 local registering = { | |
117 validated_invite = invite; | |
118 username = prepped_username; | |
119 host = module.host; | |
120 allowed = true; | |
121 }; | |
122 | |
123 module:fire_event("user-registering", registering); | |
124 | |
125 if not registering.allowed then | |
126 return render_html_template(error_template, { | |
127 site_name = site_name; | |
128 msg_class = "alert-danger"; | |
129 message = registering.reason or "Registration is not allowed."; | |
130 }); | |
131 end | |
132 | |
133 local ok, err = usermanager.create_user(prepped_username, password, module.host); | |
134 | |
135 if ok then | |
136 module:fire_event("user-registered", { | |
137 username = prepped_username; | |
138 host = module.host; | |
139 source = "mod_"..module.name; | |
140 validated_invite = invite; | |
141 }); | |
142 | |
143 local app_info = site_apps[app_id]; | |
144 | |
145 local success_template; | |
146 if app_info then | |
147 -- If recognised app, we serve a page that includes setup instructions | |
148 success_template = assert(module:load_resource("html/register_success_setup.html")):read("*a"); | |
149 else | |
150 success_template = assert(module:load_resource("html/register_success.html")):read("*a"); | |
151 end | |
152 | |
153 -- Due to the credentials being served here, ensure that | |
154 -- the browser or any intermediary does not cache the page | |
155 event.response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"; | |
156 event.response.headers["Pragma"] = "no-cache"; | |
157 event.response.headers["Expires"] = "0"; | |
158 | |
159 return render_html_template(success_template, { | |
160 site_name = site_name; | |
161 username = prepped_username; | |
162 domain = module.host; | |
163 password = password; | |
164 app = app_info; | |
165 }); | |
166 else | |
167 local err_id = id.short(); | |
168 module:log("warn", "Registration failed (%s): %s", err_id, tostring(err)); | |
169 return render_html_template(error_template, { | |
170 site_name = site_name; | |
171 msg_class = "alert-danger"; | |
172 message = ("An unknown error has occurred (%s)"):format(err_id); | |
173 }); | |
174 end | |
175 end | |
176 | |
177 module:provides("http", { | |
178 default_path = "register"; | |
179 route = { | |
180 ["GET"] = serve_register_page; | |
181 ["POST"] = handle_register_form; | |
182 }; | |
183 }); |