mod_invites_register_web/mod_invites_register_web.lua
changeset 4097 a2116f5a7c8f
child 4112 f49e3ea99785
equal deleted inserted replaced
4096:2b6918714792 4097: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 });