view mod_register_web/mod_register_web.lua @ 1088:6f8e7f65f704

mod_net_dovecotauth: Initial commit of server implementation of the Dovecot authentication protocol
author Kim Alvefur <zash@zash.se>
date Fri, 28 Jun 2013 01:38:35 +0200
parents b9d149936764
children 6617f5f79d68
line wrap: on
line source

local captcha_options = module:get_option("captcha_options", {});
local nodeprep = require "util.encodings".stringprep.nodeprep;

function generate_captcha(display_options)
	return (([[
		<script type="text/javascript"
     		src="http://www.google.com/recaptcha/api/challenge?k=$$recaptcha_public_key$$">
  		</script>
  		<noscript>
     		<iframe src="http://www.google.com/recaptcha/api/noscript?k=$$recaptcha_public_key$$$$recaptcha_display_error$$"
         		height="300" width="500" frameborder="0"></iframe><br>
     		<textarea name="recaptcha_challenge_field" rows="3" cols="40">
     		</textarea>
     		<input type="hidden" name="recaptcha_response_field"
         		value="manual_challenge">
  		</noscript>
  	]]):gsub("$$([^$]+)$%$", setmetatable({
  		recaptcha_display_error = display_options and display_options.recaptcha_error
  			and ("&error="..display_options.recaptcha_error) or "";
  	}, {
  		__index = function (t, k)
  			if captcha_options[k] then return captcha_options[k]; end
  			module:log("error", "Missing parameter from captcha_options: %s", k);
  		end })
  	));
end

function generate_page(event, display_options)
	local request = event.request;
	return [[<!DOCTYPE html>
	<html><body>
	<h1>XMPP Account Registration</h1>
	<form action="]]..request.path..[[" method="POST">]]
	..("<p>%s</p>\n"):format((display_options or {}).register_error or "")..
	[[	<table>
		<tr>
			<td>Username:</td>
			<td><input type="text" name="username">@]]..module.host..[[</td>
		</tr>
		<tr>
			<td>Password:</td>
			<td><input type="password" name="password"></td>
		</tr>
		<tr>
			<td colspan='2'>]]..generate_captcha(display_options)..[[</td>
		</tr>
		</table>
		<input type="submit" value="Register!">
	</form>
	</body></html>]];
end

function register_user(form)
        local prepped_username = nodeprep(form.username);
        if usermanager.user_exists(prepped_username, module.host) then
                return nil, "user-exists";
        end
        return usermanager.create_user(prepped_username, form.password, module.host);
end

function generate_success(event, form)
	return [[<!DOCTYPE html>
	<html><body><p>Registration succeeded! Your account is <pre>]]
		..form.username.."@"..module.host..
	[[</pre> - happy chatting!</p></body></html>]];
end

function generate_register_response(event, form, ok, err)
	local message;
	if ok then
		return generate_success(event, form);
	else
		return generate_page(event, { register_error = err });
	end
end

function handle_form(event)
	local request, response = event.request, event.response;
	local form = http.formdecode(request.body);
	http.request("http://www.google.com/recaptcha/api/verify", {
		body = http.formencode {
			privatekey = captcha_options.recaptcha_private_key;
			remoteip = request.conn:ip();
			challenge = form.recaptcha_challenge_field;
			response = form.recaptcha_response_field;
		};
	}, function (verify_result, code)
		local verify_ok, verify_err = verify_result:match("^([^\n]+)\n([^\n]+)");
		if verify_ok == "true" then
			local register_ok, register_err = register_user(form);
			response:send(generate_register_response(event, form, register_ok, register_err));
		else
			response:send(generate_page(event, { register_error = verify_err }));
		end
	end);
	return true; -- Leave connection open until we respond above
end

module:provides("http", {
	route = {
		GET = generate_page;
		POST = handle_form;
	};
});