mod_register_json/mod_register_json.lua
changeset 355 a5da789b2e7d
child 356 5dacfbc9cd86
equal deleted inserted replaced
354:f24998ec7f8d 355:a5da789b2e7d
       
     1 -- Expose a simple servlet to handle user registrations from web pages
       
     2 -- via JSON.
       
     3 --
       
     4 -- A Good chunk of the code is from mod_data_access.lua by Kim Alvefur
       
     5 -- aka Zash.
       
     6 
       
     7 local usermanager = require "core.usermanager";
       
     8 local b64_decode = require "util.encodings".base64.decode;
       
     9 local json_decode = require "util.json".decode;
       
    10 
       
    11 module.host = "*" -- HTTP/BOSH Servlets need to be loaded globally.
       
    12 
       
    13 local set_realm_name = module:get_option("reg_servlet_realm") or "Restricted";
       
    14 
       
    15 local function http_response(code, message, extra_headers)
       
    16         local response = {
       
    17                 status = code .. " " .. message;
       
    18                 body = message .. "\n"; }
       
    19         if extra_headers then response.headers = extra_headers; end
       
    20         return response
       
    21 end
       
    22 
       
    23 local function handle_req(method, body, request)
       
    24 	if request.method ~= "POST" then
       
    25 		return http_response(405, "Bad method...", {["Allow"] = "POST"});
       
    26 	end
       
    27 	if not request.headers["authorization"] then
       
    28 		return http_response(401, "No... No...",
       
    29 		{["WWW-Authenticate"]='Basic realm="'.. set_realm_name ..'"'})
       
    30 	end
       
    31 	
       
    32 	local user, password = b64_decode(request.headers.authorization
       
    33 		:match("[^ ]*$") or ""):match("([^:]*):(.*)");
       
    34 	user = jid_prep(user);
       
    35 	if not user or not password then return http_response(400, "What's this..?"); end
       
    36 	local user_node, user_host = jid_split(user)
       
    37 	if not hosts[user_host] then return http_response(401, "Negative."); end
       
    38 	
       
    39 	module:log("debug", "%s is authing to submit a new user registration data", user)
       
    40 	if not usermanager.test_password(user_node, user_host, password) then
       
    41 		module:log("debug", "%s failed authentication", user)
       
    42 		return http_response(401, "Who the hell are you?! Guards!");
       
    43 	end
       
    44 	
       
    45 	local req_body; pcall(function() req_body = json.decode(body) end);
       
    46 	-- Check if user is an admin of said host
       
    47 	if not usermanager.is_admin(user, req_body["host"]) then
       
    48 		module:log("debug", "%s tried to submit registration data for %s but he's not an admin", user, req_body["host"])
       
    49 		return http_response(401, "I obey only to my masters... Have a nice day.");
       
    50 	else
       
    51 		-- Various sanity checks.
       
    52 		if req_body == nil then module:log("debug", "JSON data submitted for user registration by %s failed to Decode.", user); return http_response(400, "JSON Decoding failed."); end
       
    53 		if req_body["password"]:match("%s") then module:log("debug", "Password submitted for user registration by %s contained spaces.", user); return http_response(400, "Supplied user passwords can't contain spaces."); end
       
    54 		-- We first check if the supplied username for registration is already there.
       
    55 		if not usermanager.user_exists(req_body["username"], req_body["host"]) then
       
    56 			usermanager.create_user(req_body["username"], req_body["password"], req_body["host]);
       
    57 			module:log("debug", "%s registration data submission for %s is successful", user, req_body["user"]);
       
    58 			return http_response(200, "Done.");
       
    59 		else
       
    60 			module:log("debug", "%s registration data submission for %s failed (user already exists)", user, req_body["user"]);
       
    61 			return http_response(409, "User already exists.");
       
    62 		end
       
    63 	end
       
    64 end
       
    65 
       
    66 local function setup()
       
    67         local ports = module:get_option("reg_servlet_port") or { 5280 };
       
    68         local base_name = module:get_option("reg_servlet_base") or "register_account";
       
    69         require "net.httpserver".new_from_config(ports, handle_req, { base = base_name });
       
    70 end
       
    71 if prosody.start_time then -- already started
       
    72         setup();
       
    73 else
       
    74         prosody.events.add_handler("server-started", setup);
       
    75 end