Software / code / prosody
Comparison
plugins/mod_register.lua @ 3529:3f9cc12308aa
mod_register: Updated to use the new events API.
| author | Waqas Hussain <waqas20@gmail.com> |
|---|---|
| date | Sat, 16 Oct 2010 05:59:26 +0500 |
| parent | 3394:9bf5f2b3314b |
| child | 3540:bc139431830b |
comparison
equal
deleted
inserted
replaced
| 3528:5cdcd7ee6ef5 | 3529:3f9cc12308aa |
|---|---|
| 16 local os_time = os.time; | 16 local os_time = os.time; |
| 17 local nodeprep = require "util.encodings".stringprep.nodeprep; | 17 local nodeprep = require "util.encodings".stringprep.nodeprep; |
| 18 | 18 |
| 19 module:add_feature("jabber:iq:register"); | 19 module:add_feature("jabber:iq:register"); |
| 20 | 20 |
| 21 module:add_iq_handler("c2s", "jabber:iq:register", function (session, stanza) | 21 module:hook("iq/self/jabber:iq:register:query", function(event) |
| 22 if stanza.tags[1].name == "query" then | 22 local session, stanza = event.origin, event.stanza; |
| 23 local query = stanza.tags[1]; | 23 |
| 24 if stanza.attr.type == "get" then | 24 local query = stanza.tags[1]; |
| 25 local reply = st.reply(stanza); | 25 if stanza.attr.type == "get" then |
| 26 reply:tag("query", {xmlns = "jabber:iq:register"}) | 26 local reply = st.reply(stanza); |
| 27 :tag("registered"):up() | 27 reply:tag("query", {xmlns = "jabber:iq:register"}) |
| 28 :tag("username"):text(session.username):up() | 28 :tag("registered"):up() |
| 29 :tag("password"):up(); | 29 :tag("username"):text(session.username):up() |
| 30 session.send(reply); | 30 :tag("password"):up(); |
| 31 elseif stanza.attr.type == "set" then | 31 session.send(reply); |
| 32 if query.tags[1] and query.tags[1].name == "remove" then | 32 else -- stanza.attr.type == "set" |
| 33 -- TODO delete user auth data, send iq response, kick all user resources with a <not-authorized/>, delete all user data | 33 if query.tags[1] and query.tags[1].name == "remove" then |
| 34 local username, host = session.username, session.host; | 34 -- TODO delete user auth data, send iq response, kick all user resources with a <not-authorized/>, delete all user data |
| 35 --session.send(st.error_reply(stanza, "cancel", "not-allowed")); | 35 local username, host = session.username, session.host; |
| 36 --return; | 36 --session.send(st.error_reply(stanza, "cancel", "not-allowed")); |
| 37 usermanager_set_password(username, nil, host); -- Disable account | 37 --return; |
| 38 -- FIXME the disabling currently allows a different user to recreate the account | 38 usermanager_set_password(username, nil, host); -- Disable account |
| 39 -- we should add an in-memory account block mode when we have threading | 39 -- FIXME the disabling currently allows a different user to recreate the account |
| 40 session.send(st.reply(stanza)); | 40 -- we should add an in-memory account block mode when we have threading |
| 41 local roster = session.roster; | 41 session.send(st.reply(stanza)); |
| 42 for _, session in pairs(hosts[host].sessions[username].sessions) do -- disconnect all resources | 42 local roster = session.roster; |
| 43 session:close({condition = "not-authorized", text = "Account deleted"}); | 43 for _, session in pairs(hosts[host].sessions[username].sessions) do -- disconnect all resources |
| 44 end | 44 session:close({condition = "not-authorized", text = "Account deleted"}); |
| 45 -- TODO datamanager should be able to delete all user data itself | 45 end |
| 46 datamanager.store(username, host, "vcard", nil); | 46 -- TODO datamanager should be able to delete all user data itself |
| 47 datamanager.store(username, host, "private", nil); | 47 datamanager.store(username, host, "vcard", nil); |
| 48 datamanager.list_store(username, host, "offline", nil); | 48 datamanager.store(username, host, "private", nil); |
| 49 local bare = username.."@"..host; | 49 datamanager.list_store(username, host, "offline", nil); |
| 50 for jid, item in pairs(roster) do | 50 local bare = username.."@"..host; |
| 51 if jid and jid ~= "pending" then | 51 for jid, item in pairs(roster) do |
| 52 if item.subscription == "both" or item.subscription == "from" or (roster.pending and roster.pending[jid]) then | 52 if jid and jid ~= "pending" then |
| 53 core_post_stanza(hosts[host], st.presence({type="unsubscribed", from=bare, to=jid})); | 53 if item.subscription == "both" or item.subscription == "from" or (roster.pending and roster.pending[jid]) then |
| 54 end | 54 core_post_stanza(hosts[host], st.presence({type="unsubscribed", from=bare, to=jid})); |
| 55 if item.subscription == "both" or item.subscription == "to" or item.ask then | 55 end |
| 56 core_post_stanza(hosts[host], st.presence({type="unsubscribe", from=bare, to=jid})); | 56 if item.subscription == "both" or item.subscription == "to" or item.ask then |
| 57 end | 57 core_post_stanza(hosts[host], st.presence({type="unsubscribe", from=bare, to=jid})); |
| 58 end | 58 end |
| 59 end | 59 end |
| 60 datamanager.store(username, host, "roster", nil); | 60 end |
| 61 datamanager.store(username, host, "privacy", nil); | 61 datamanager.store(username, host, "roster", nil); |
| 62 datamanager.store(username, host, "accounts", nil); -- delete accounts datastore at the end | 62 datamanager.store(username, host, "privacy", nil); |
| 63 module:log("info", "User removed their account: %s@%s", username, host); | 63 datamanager.store(username, host, "accounts", nil); -- delete accounts datastore at the end |
| 64 module:fire_event("user-deregistered", { username = username, host = host, source = "mod_register", session = session }); | 64 module:log("info", "User removed their account: %s@%s", username, host); |
| 65 else | 65 module:fire_event("user-deregistered", { username = username, host = host, source = "mod_register", session = session }); |
| 66 local username = query:child_with_name("username"); | 66 else |
| 67 local password = query:child_with_name("password"); | 67 local username = query:child_with_name("username"); |
| 68 if username and password then | 68 local password = query:child_with_name("password"); |
| 69 -- FIXME shouldn't use table.concat | 69 if username and password then |
| 70 username = nodeprep(table.concat(username)); | 70 -- FIXME shouldn't use table.concat |
| 71 password = table.concat(password); | 71 username = nodeprep(table.concat(username)); |
| 72 if username == session.username then | 72 password = table.concat(password); |
| 73 if usermanager_set_password(username, password, session.host) then | 73 if username == session.username then |
| 74 session.send(st.reply(stanza)); | 74 if usermanager_set_password(username, password, session.host) then |
| 75 else | 75 session.send(st.reply(stanza)); |
| 76 -- TODO unable to write file, file may be locked, etc, what's the correct error? | |
| 77 session.send(st.error_reply(stanza, "wait", "internal-server-error")); | |
| 78 end | |
| 79 else | 76 else |
| 80 session.send(st.error_reply(stanza, "modify", "bad-request")); | 77 -- TODO unable to write file, file may be locked, etc, what's the correct error? |
| 78 session.send(st.error_reply(stanza, "wait", "internal-server-error")); | |
| 81 end | 79 end |
| 82 else | 80 else |
| 83 session.send(st.error_reply(stanza, "modify", "bad-request")); | 81 session.send(st.error_reply(stanza, "modify", "bad-request")); |
| 84 end | 82 end |
| 83 else | |
| 84 session.send(st.error_reply(stanza, "modify", "bad-request")); | |
| 85 end | 85 end |
| 86 end | 86 end |
| 87 else | 87 end |
| 88 session.send(st.error_reply(stanza, "cancel", "service-unavailable")); | 88 return true; |
| 89 end; | |
| 90 end); | 89 end); |
| 91 | 90 |
| 92 local recent_ips = {}; | 91 local recent_ips = {}; |
| 93 local min_seconds_between_registrations = module:get_option("min_seconds_between_registrations"); | 92 local min_seconds_between_registrations = module:get_option("min_seconds_between_registrations"); |
| 94 local whitelist_only = module:get_option("whitelist_registration_only"); | 93 local whitelist_only = module:get_option("whitelist_registration_only"); |
| 96 local blacklisted_ips = module:get_option("registration_blacklist") or {}; | 95 local blacklisted_ips = module:get_option("registration_blacklist") or {}; |
| 97 | 96 |
| 98 for _, ip in ipairs(whitelisted_ips) do whitelisted_ips[ip] = true; end | 97 for _, ip in ipairs(whitelisted_ips) do whitelisted_ips[ip] = true; end |
| 99 for _, ip in ipairs(blacklisted_ips) do blacklisted_ips[ip] = true; end | 98 for _, ip in ipairs(blacklisted_ips) do blacklisted_ips[ip] = true; end |
| 100 | 99 |
| 101 module:add_iq_handler("c2s_unauthed", "jabber:iq:register", function (session, stanza) | 100 module:hook("stanza/iq/jabber:iq:register:query", function(event) |
| 102 if module:get_option("allow_registration") == false then | 101 local session, stanza = event.origin, event.stanza; |
| 102 | |
| 103 if module:get_option("allow_registration") == false or session.type ~= "c2s_unauthed" then | |
| 103 session.send(st.error_reply(stanza, "cancel", "service-unavailable")); | 104 session.send(st.error_reply(stanza, "cancel", "service-unavailable")); |
| 104 elseif stanza.tags[1].name == "query" then | 105 else |
| 105 local query = stanza.tags[1]; | 106 local query = stanza.tags[1]; |
| 106 if stanza.attr.type == "get" then | 107 if stanza.attr.type == "get" then |
| 107 local reply = st.reply(stanza); | 108 local reply = st.reply(stanza); |
| 108 reply:tag("query", {xmlns = "jabber:iq:register"}) | 109 reply:tag("query", {xmlns = "jabber:iq:register"}) |
| 109 :tag("instructions"):text("Choose a username and password for use with this service."):up() | 110 :tag("instructions"):text("Choose a username and password for use with this service."):up() |
| 120 -- Check that the user is not blacklisted or registering too often | 121 -- Check that the user is not blacklisted or registering too often |
| 121 if not session.ip then | 122 if not session.ip then |
| 122 module:log("debug", "User's IP not known; can't apply blacklist/whitelist"); | 123 module:log("debug", "User's IP not known; can't apply blacklist/whitelist"); |
| 123 elseif blacklisted_ips[session.ip] or (whitelist_only and not whitelisted_ips[session.ip]) then | 124 elseif blacklisted_ips[session.ip] or (whitelist_only and not whitelisted_ips[session.ip]) then |
| 124 session.send(st.error_reply(stanza, "cancel", "not-acceptable", "You are not allowed to register an account.")); | 125 session.send(st.error_reply(stanza, "cancel", "not-acceptable", "You are not allowed to register an account.")); |
| 125 return; | 126 return true; |
| 126 elseif min_seconds_between_registrations and not whitelisted_ips[session.ip] then | 127 elseif min_seconds_between_registrations and not whitelisted_ips[session.ip] then |
| 127 if not recent_ips[session.ip] then | 128 if not recent_ips[session.ip] then |
| 128 recent_ips[session.ip] = { time = os_time(), count = 1 }; | 129 recent_ips[session.ip] = { time = os_time(), count = 1 }; |
| 129 else | 130 else |
| 130 local ip = recent_ips[session.ip]; | 131 local ip = recent_ips[session.ip]; |
| 131 ip.count = ip.count + 1; | 132 ip.count = ip.count + 1; |
| 132 | 133 |
| 133 if os_time() - ip.time < min_seconds_between_registrations then | 134 if os_time() - ip.time < min_seconds_between_registrations then |
| 134 ip.time = os_time(); | 135 ip.time = os_time(); |
| 135 session.send(st.error_reply(stanza, "wait", "not-acceptable")); | 136 session.send(st.error_reply(stanza, "wait", "not-acceptable")); |
| 136 return; | 137 return true; |
| 137 end | 138 end |
| 138 ip.time = os_time(); | 139 ip.time = os_time(); |
| 139 end | 140 end |
| 140 end | 141 end |
| 141 -- FIXME shouldn't use table.concat | 142 -- FIXME shouldn't use table.concat |
| 161 else | 162 else |
| 162 session.send(st.error_reply(stanza, "modify", "not-acceptable")); | 163 session.send(st.error_reply(stanza, "modify", "not-acceptable")); |
| 163 end | 164 end |
| 164 end | 165 end |
| 165 end | 166 end |
| 166 else | 167 end |
| 167 session.send(st.error_reply(stanza, "cancel", "service-unavailable")); | 168 return true; |
| 168 end; | |
| 169 end); | 169 end); |
| 170 | 170 |