Mercurial > prosody-modules
view mod_register_json/mod_register_json.lua @ 737:e4ea03b060ed
mod_archive: switch from/to
The XEP-0136 is not very explicit about the meening of <from> and <to>
elements, but the examples are clear: <from> means it comes from the user in
the 'with' attribute of the collection.
That is the opposite of what is currently implemented in that module.
So for better compatibility with complient clients, this switch the 'from' and
'to' fields
author | Olivier Goffart <ogoffart@woboq.com> |
---|---|
date | Wed, 04 Jul 2012 14:08:43 +0200 |
parents | c26652d055b5 |
children | 836e4e110c71 |
line wrap: on
line source
-- Expose a simple servlet to handle user registrations from web pages -- via JSON. -- -- A Good chunk of the code is from mod_data_access.lua by Kim Alvefur -- aka Zash. local jid_prep = require "util.jid".prep local jid_split = require "util.jid".split local usermanager = usermanager local b64_decode = require "util.encodings".base64.decode local json_decode = require "util.json".decode local os_time = os.time local nodeprep = require "util.encodings".stringprep.nodeprep module:depends("http") -- Pick up configuration. local secure = module:get_option_boolean("reg_servlet_secure", true) local set_realm_name = module:get_option_string("reg_servlet_realm", "Restricted") local base_path = module:get_option_string("reg_servlet_base", "/register_account/") local throttle_time = module:get_option_number("reg_servlet_ttime", nil) local whitelist = module:get_option_set("reg_servlet_wl", {}) local blacklist = module:get_option_set("reg_servlet_bl", {}) local recent_ips = {} -- Begin local function http_response(event, code, message, headers) local response = event.response if headers then for header, data in pairs(headers) do response.headers[header] = data end end response.headers.content_type = "application/json" response.status_code = code response:send(message) end local function handle_req(event) local request = event.request local body = request.body if request.method ~= "POST" then return http_response(event, 405, "Bad method...", {["Allow"] = "POST"}) end if not request.headers["authorization"] then return http_response(event, 401, "No... No...", {["WWW-Authenticate"]='Basic realm="'.. set_realm_name ..'"'}) end local user, password = b64_decode(request.headers.authorization:match("[^ ]*$") or ""):match("([^:]*):(.*)") user = jid_prep(user) if not user or not password then return http_response(event, 400, "What's this..?") end local user_node, user_host = jid_split(user) if not hosts[user_host] then return http_response(event, 401, "Negative.") end module:log("warn", "%s is authing to submit a new user registration data", user) if not usermanager.test_password(user_node, user_host, password) then module:log("warn", "%s failed authentication", user) return http_response(event, 401, "Who the hell are you?! Guards!") end local req_body -- We check that what we have is valid JSON wise else we throw an error... if not pcall(function() req_body = json_decode(body) end) then module:log("debug", "JSON data submitted for user registration by %s failed to Decode.", user) return http_response(event, 400, "JSON Decoding failed.") else -- Decode JSON data and check that all bits are there else throw an error req_body = json_decode(body) if req_body["username"] == nil or req_body["password"] == nil or req_body["host"] == nil or req_body["ip"] == nil then module:log("debug", "%s supplied an insufficent number of elements or wrong elements for the JSON registration", user) return http_response(event, 400, "Invalid syntax.") end -- Check if user is an admin of said host if not usermanager.is_admin(user, req_body["host"]) then module:log("warn", "%s tried to submit registration data for %s but he's not an admin", user, req_body["host"]) return http_response(event, 401, "I obey only to my masters... Have a nice day.") else -- Blacklist can be checked here. 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 -- We first check if the supplied username for registration is already there. -- And nodeprep the username local username = nodeprep(req_body["username"]) if not username then module:log("debug", "%s supplied an username containing invalid characters: %s", user, username) return http_response(event, 406, "Supplied username contains invalid characters, see RFC 6122.") else if not usermanager.user_exists(username, req_body["host"]) then -- if username fails to register successive requests shouldn't be throttled until one is successful. if throttle_time and not whitelist:contains(req_body["ip"]) then if not recent_ips[req_body["ip"]] then recent_ips[req_body["ip"]] = os_time() else if os_time() - recent_ips[req_body["ip"]] < throttle_time then recent_ips[req_body["ip"]] = os_time() module:log("warn", "JSON Registration request from %s has been throttled.", req_body["ip"]) return http_response(event, 503, "Woah... How many users you want to register..? Request throttled, wait a bit and try again.") end recent_ips[req_body["ip"]] = os_time() end end local ok, error = usermanager.create_user(username, req_body["password"], req_body["host"]) if ok then hosts[req_body["host"]].events.fire_event("user-registered", { username = username, host = req_body["host"], source = "mod_register_json", session = { ip = req_body["ip"] } }) module:log("debug", "%s registration data submission for %s@%s is successful", user, username, req_body["host"]) return http_response(event, 200, "Done.") else module:log("error", "user creation failed: "..error) return http_response(event, 500, "Encountered server error while creating the user: "..error) end else module:log("debug", "%s registration data submission for %s failed (user already exists)", user, username) return http_response(event, 409, "User already exists.") end end end end end -- Set it up! module:provides("http", { default_path = base_path, route = { ["GET /"] = handle_req, ["POST /"] = handle_req } })