|
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 }); |