Mercurial > prosody-modules
comparison mod_register_json/mod_register_json.lua @ 648:6f0e0d6790a7
mod_register_json: updated to current HTTP API.
| author | Marco Cirillo <maranda@lightwitch.org> |
|---|---|
| date | Sun, 29 Apr 2012 13:05:46 +0000 |
| parents | 121762432eb1 |
| children | 78a23a7dc613 |
comparison
equal
deleted
inserted
replaced
| 647:6b3606e0a6e7 | 648:6f0e0d6790a7 |
|---|---|
| 7 local jid_prep = require "util.jid".prep | 7 local jid_prep = require "util.jid".prep |
| 8 local jid_split = require "util.jid".split | 8 local jid_split = require "util.jid".split |
| 9 local usermanager = require "core.usermanager" | 9 local usermanager = require "core.usermanager" |
| 10 local b64_decode = require "util.encodings".base64.decode | 10 local b64_decode = require "util.encodings".base64.decode |
| 11 local json_decode = require "util.json".decode | 11 local json_decode = require "util.json".decode |
| 12 local httpserver = require "net.httpserver" | |
| 13 local os_time = os.time | 12 local os_time = os.time |
| 14 local nodeprep = require "util.encodings".stringprep.nodeprep | 13 local nodeprep = require "util.encodings".stringprep.nodeprep |
| 15 | 14 |
| 16 module.host = "*" -- HTTP/BOSH Servlets need to be global. | 15 module:depends("http") |
| 16 module:set_global() | |
| 17 | 17 |
| 18 -- Pick up configuration. | 18 -- Pick up configuration. |
| 19 | 19 |
| 20 local set_realm_name = module:get_option_string("reg_servlet_realm", "Restricted") | 20 local set_realm_name = module:get_option_string("reg_servlet_realm", "Restricted") |
| 21 local base_path = module:get_option_string("reg_servlet_base", "/register_account/") | |
| 21 local throttle_time = module:get_option_number("reg_servlet_ttime", nil) | 22 local throttle_time = module:get_option_number("reg_servlet_ttime", nil) |
| 22 local whitelist = module:get_option_set("reg_servlet_wl", {}) | 23 local whitelist = module:get_option_set("reg_servlet_wl", {}) |
| 23 local blacklist = module:get_option_set("reg_servlet_bl", {}) | 24 local blacklist = module:get_option_set("reg_servlet_bl", {}) |
| 24 local ports = module:get_option_array("reg_servlet_ports", {{ port = 9280 }}) | |
| 25 local recent_ips = {} | 25 local recent_ips = {} |
| 26 | 26 |
| 27 -- Begin | 27 -- Begin |
| 28 | 28 |
| 29 local function http_response(code, message, extra_headers) | 29 local function http_response(event, code, message, headers) |
| 30 local response = { | 30 local response = event.response |
| 31 status = code .. " " .. message, | 31 |
| 32 body = message .. "\n" } | 32 if headers then |
| 33 if extra_headers then response.headers = extra_headers end | 33 for header, data in pairs(headers) do response.headers[header] = data end |
| 34 return response | 34 end |
| 35 | |
| 36 response.headers.content_type = "application/json" | |
| 37 response.status_code = code | |
| 38 response:send(message) | |
| 35 end | 39 end |
| 36 | 40 |
| 37 local function handle_req(method, body, request) | 41 local function handle_req(event) |
| 42 local request = event.request | |
| 43 local body = request.body | |
| 44 | |
| 38 if request.method ~= "POST" then | 45 if request.method ~= "POST" then |
| 39 return http_response(405, "Bad method...", {["Allow"] = "POST"}) | 46 return http_response(event, 405, "Bad method...", {["Allow"] = "POST"}) |
| 40 end | 47 end |
| 41 if not request.headers["authorization"] then | 48 if not request.headers["authorization"] then |
| 42 return http_response(401, "No... No...", {["WWW-Authenticate"]='Basic realm="'.. set_realm_name ..'"'}) | 49 return http_response(event, 401, "No... No...", {["WWW-Authenticate"]='Basic realm="'.. set_realm_name ..'"'}) |
| 43 end | 50 end |
| 44 | 51 |
| 45 local user, password = b64_decode(request.headers.authorization:match("[^ ]*$") or ""):match("([^:]*):(.*)") | 52 local user, password = b64_decode(request.headers.authorization:match("[^ ]*$") or ""):match("([^:]*):(.*)") |
| 46 user = jid_prep(user) | 53 user = jid_prep(user) |
| 47 if not user or not password then return http_response(400, "What's this..?") end | 54 if not user or not password then return http_response(event, 400, "What's this..?") end |
| 48 local user_node, user_host = jid_split(user) | 55 local user_node, user_host = jid_split(user) |
| 49 if not hosts[user_host] then return http_response(401, "Negative.") end | 56 if not hosts[user_host] then return http_response(event, 401, "Negative.") end |
| 50 | 57 |
| 51 module:log("warn", "%s is authing to submit a new user registration data", user) | 58 module:log("warn", "%s is authing to submit a new user registration data", user) |
| 52 if not usermanager.test_password(user_node, user_host, password) then | 59 if not usermanager.test_password(user_node, user_host, password) then |
| 53 module:log("warn", "%s failed authentication", user) | 60 module:log("warn", "%s failed authentication", user) |
| 54 return http_response(401, "Who the hell are you?! Guards!") | 61 return http_response(event, 401, "Who the hell are you?! Guards!") |
| 55 end | 62 end |
| 56 | 63 |
| 57 local req_body | 64 local req_body |
| 58 -- We check that what we have is valid JSON wise else we throw an error... | 65 -- We check that what we have is valid JSON wise else we throw an error... |
| 59 if not pcall(function() req_body = json_decode(body) end) then | 66 if not pcall(function() req_body = json_decode(body) end) then |
| 60 module:log("debug", "JSON data submitted for user registration by %s failed to Decode.", user) | 67 module:log("debug", "JSON data submitted for user registration by %s failed to Decode.", user) |
| 61 return http_response(400, "JSON Decoding failed.") | 68 return http_response(event, 400, "JSON Decoding failed.") |
| 62 else | 69 else |
| 63 -- Decode JSON data and check that all bits are there else throw an error | 70 -- Decode JSON data and check that all bits are there else throw an error |
| 64 req_body = json_decode(body) | 71 req_body = json_decode(body) |
| 65 if req_body["username"] == nil or req_body["password"] == nil or req_body["host"] == nil or req_body["ip"] == nil then | 72 if req_body["username"] == nil or req_body["password"] == nil or req_body["host"] == nil or req_body["ip"] == nil then |
| 66 module:log("debug", "%s supplied an insufficent number of elements or wrong elements for the JSON registration", user) | 73 module:log("debug", "%s supplied an insufficent number of elements or wrong elements for the JSON registration", user) |
| 67 return http_response(400, "Invalid syntax.") | 74 return http_response(event, 400, "Invalid syntax.") |
| 68 end | 75 end |
| 69 -- Check if user is an admin of said host | 76 -- Check if user is an admin of said host |
| 70 if not usermanager.is_admin(user, req_body["host"]) then | 77 if not usermanager.is_admin(user, req_body["host"]) then |
| 71 module:log("warn", "%s tried to submit registration data for %s but he's not an admin", user, req_body["host"]) | 78 module:log("warn", "%s tried to submit registration data for %s but he's not an admin", user, req_body["host"]) |
| 72 return http_response(401, "I obey only to my masters... Have a nice day.") | 79 return http_response(event, 401, "I obey only to my masters... Have a nice day.") |
| 73 else | 80 else |
| 74 -- Checks for both Throttling/Whitelist and Blacklist (basically copycatted from prosody's register.lua code) | 81 -- Checks for both Throttling/Whitelist and Blacklist (basically copycatted from prosody's register.lua code) |
| 75 if blacklist:contains(req_body["ip"]) then module:log("warn", "Attempt of reg. submission to the JSON servlet from blacklisted address: %s", req_body["ip"]) ; return http_response(403, "The specified address is blacklisted, sorry sorry.") end | 82 if blacklist:contains(req_body["ip"]) then module:log("warn", "Attempt of reg. submission to the JSON servlet from blacklisted address: %s", req_body["ip"]) ; return http_response(403, "The specified address is blacklisted, sorry sorry.") end |
| 76 if throttle_time and not whitelist:contains(req_body["ip"]) then | 83 if throttle_time and not whitelist:contains(req_body["ip"]) then |
| 77 if not recent_ips[req_body["ip"]] then | 84 if not recent_ips[req_body["ip"]] then |
| 90 -- And nodeprep the username | 97 -- And nodeprep the username |
| 91 local username = nodeprep(req_body["username"]) | 98 local username = nodeprep(req_body["username"]) |
| 92 if not usermanager.user_exists(username, req_body["host"]) then | 99 if not usermanager.user_exists(username, req_body["host"]) then |
| 93 if not username then | 100 if not username then |
| 94 module:log("debug", "%s supplied an username containing invalid characters: %s", user, username) | 101 module:log("debug", "%s supplied an username containing invalid characters: %s", user, username) |
| 95 return http_response(406, "Supplied username contains invalid characters, see RFC 6122.") | 102 return http_response(event, 406, "Supplied username contains invalid characters, see RFC 6122.") |
| 96 else | 103 else |
| 97 local ok, error = usermanager.create_user(username, req_body["password"], req_body["host"]) | 104 local ok, error = usermanager.create_user(username, req_body["password"], req_body["host"]) |
| 98 if ok then | 105 if ok then |
| 99 hosts[req_body["host"]].events.fire_event("user-registered", { username = username, host = req_body["host"], source = "mod_register_json", session = { ip = req_body["ip"] } }) | 106 hosts[req_body["host"]].events.fire_event("user-registered", { username = username, host = req_body["host"], source = "mod_register_json", session = { ip = req_body["ip"] } }) |
| 100 module:log("debug", "%s registration data submission for %s@%s is successful", user, username, req_body["host"]) | 107 module:log("debug", "%s registration data submission for %s@%s is successful", user, username, req_body["host"]) |
| 101 return http_response(200, "Done.") | 108 return http_response(event, 200, "Done.") |
| 102 else | 109 else |
| 103 module:log("error", "user creation failed: "..error) | 110 module:log("error", "user creation failed: "..error) |
| 104 return http_response(500, "Encountered server error while creating the user: "..error) | 111 return http_response(event 500, "Encountered server error while creating the user: "..error) |
| 105 end | 112 end |
| 106 end | 113 end |
| 107 else | 114 else |
| 108 module:log("debug", "%s registration data submission for %s failed (user already exists)", user, username) | 115 module:log("debug", "%s registration data submission for %s failed (user already exists)", user, username) |
| 109 return http_response(409, "User already exists.") | 116 return http_response(event, 409, "User already exists.") |
| 110 end | 117 end |
| 111 end | 118 end |
| 112 end | 119 end |
| 113 end | 120 end |
| 114 | 121 |
| 115 -- Set it up! | 122 -- Set it up! |
| 116 | 123 |
| 117 function setup() | 124 module:provides("http", { |
| 118 for id, options in ipairs(ports) do | 125 default_path = base_path, |
| 119 if not options.port then | 126 route = { |
| 120 if not options.ssl then ports[id].port = 9280 | 127 ["GET /"] = handle_req, |
| 121 else ports[id].port = 9443 end | 128 ["POST /"] = handle_req |
| 122 elseif options.port == 9280 and options.ssl then ports[id].port = 9443 end end | 129 } |
| 123 httpserver.new_from_config(ports, handle_req, { base = "register_account" }) | 130 }) |
| 124 end | |
| 125 | |
| 126 if prosody.start_time then -- already started | |
| 127 setup() | |
| 128 else | |
| 129 module:hook("server-started", setup) | |
| 130 end |
