Mercurial > prosody-modules
comparison mod_privacy/mod_privacy.lua @ 20:2675dc25445b
mod_privacy: overworked error returns while creating, editing, deleting or de/activating lists.
| author | Thilo Cestonaro <thilo@cestona.ro> |
|---|---|
| date | Wed, 30 Sep 2009 21:35:29 +0200 |
| parents | e400ee8471b0 |
| children | d91cb13ef0ee |
comparison
equal
deleted
inserted
replaced
| 19:e400ee8471b0 | 20:2675dc25445b |
|---|---|
| 32 end | 32 end |
| 33 end | 33 end |
| 34 return ret; | 34 return ret; |
| 35 end | 35 end |
| 36 | 36 |
| 37 function isListUsed(origin, name, privacy_lists) | |
| 38 if bare_sessions[origin.username.."@"..origin.host].sessions ~= nil then | |
| 39 for resource, session in pairs(bare_sessions[origin.username.."@"..origin.host].sessions) do | |
| 40 if resource ~= origin.resource then | |
| 41 if session.activePrivacyList == name then | |
| 42 module:log("debug", "List {0} is in use.", name); | |
| 43 return true; | |
| 44 elseif session.activePrivacyList == nil and privacy_lists.default == name then | |
| 45 module:log("debug", "List {0} is in use.", name); | |
| 46 return true; | |
| 47 end | |
| 48 end | |
| 49 end | |
| 50 end | |
| 51 module:log("debug", "List {0} is in NOT use.", name); | |
| 52 return false; | |
| 53 end | |
| 54 | |
| 55 function isAnotherSessionUsingDefaultList(origin) | |
| 56 local ret = false | |
| 57 if bare_sessions[origin.username.."@"..origin.host].sessions ~= nil then | |
| 58 for resource, session in pairs(bare_sessions[origin.username.."@"..origin.host].sessions) do | |
| 59 if resource ~= origin.resource and session.activePrivacyList == nil then | |
| 60 module:log("debug", "Default list is used by another resource."); | |
| 61 ret = true; | |
| 62 break; | |
| 63 end | |
| 64 end | |
| 65 end | |
| 66 return ret; | |
| 67 end | |
| 68 | |
| 37 function declineList (privacy_lists, origin, stanza, which) | 69 function declineList (privacy_lists, origin, stanza, which) |
| 38 module:log("info", "User requests to decline the use of privacy list: %s", which); | 70 module:log("info", "User requests to decline the use of privacy list: %s", which); |
| 39 if which == "default" then | 71 if which == "default" then |
| 40 privacy_lists.default = nil; -- TODO check if used! | 72 if isAnotherSessionUsingDefaultList(origin) then |
| 73 return { "cancel", "conflict", "Another session is online and using the default list."}; | |
| 74 end | |
| 75 privacy_lists.default = nil; | |
| 76 origin.send(st.reply(stanza)); | |
| 41 elseif which == "active" then | 77 elseif which == "active" then |
| 42 origin.activePrivacyList = nil; | 78 origin.activePrivacyList = nil; |
| 43 end | 79 origin.send(st.reply(stanza)); |
| 44 origin.send(st.reply(stanza)); | 80 else |
| 81 return {"modify", "bad-request", "Neither default nor active list specifed to decline."}; | |
| 82 end | |
| 45 return true; | 83 return true; |
| 46 end | 84 end |
| 47 | 85 |
| 48 function activateList (privacy_lists, origin, stanza, which, name) | 86 function activateList (privacy_lists, origin, stanza, which, name) |
| 49 module:log("info", "User requests to change the privacy list: %s, to be list named %s", which, name); | 87 module:log("info", "User requests to change the privacy list: %s, to be list named %s", which, name); |
| 50 local ret = false; | |
| 51 local idx = findNamedList(privacy_lists, name); | 88 local idx = findNamedList(privacy_lists, name); |
| 52 | 89 |
| 53 if privacy_lists[which] == nil then | 90 if privacy_lists.default == nil then |
| 54 privacy_lists[which] = ""; | 91 privacy_lists.default = ""; |
| 55 end | 92 end |
| 56 | 93 if origin.activePrivacyList == nil then |
| 57 if which == "default" and privacy_lists.default ~= name and idx ~= nil then | 94 origin.activePrivacyList = ""; |
| 58 privacy_lists.default = name; -- TODO check if used! | 95 end |
| 59 ret = true; | 96 |
| 60 elseif which == "active" and origin.activePrivacyList ~= name and idx ~= nil then | 97 if which == "default" and idx ~= nil then |
| 98 if isAnotherSessionUsingDefaultList(origin) then | |
| 99 return {"cancel", "conflict", "Another session is online and using the default list."}; | |
| 100 end | |
| 101 privacy_lists.default = name; | |
| 102 origin.send(st.reply(stanza)); | |
| 103 elseif which == "active" and idx ~= nil then | |
| 61 origin.activePrivacyList = name; | 104 origin.activePrivacyList = name; |
| 62 ret = true; | |
| 63 end | |
| 64 if ret == true then | |
| 65 origin.send(st.reply(stanza)); | 105 origin.send(st.reply(stanza)); |
| 66 end | 106 else |
| 67 return ret; | 107 return {"modify", "bad-request", "Either not active or default given or unknown list name specified."}; |
| 108 end | |
| 109 return true; | |
| 68 end | 110 end |
| 69 | 111 |
| 70 function deleteList (privacy_lists, origin, stanza, name) | 112 function deleteList (privacy_lists, origin, stanza, name) |
| 71 module:log("info", "User requests to delete privacy list: %s", name); | 113 module:log("info", "User requests to delete privacy list: %s", name); |
| 72 local ret = false; | |
| 73 local idx = findNamedList(privacy_lists, name); | 114 local idx = findNamedList(privacy_lists, name); |
| 74 | 115 |
| 75 if idx ~= nil then | 116 if idx ~= nil then |
| 76 table.remove(privacy_lists.lists, idx); -- TODO check if used! | 117 if isListUsed(origin, name, privacy_lists) then |
| 118 return {"cancel", "conflict", "Another session is online and using the list which should be deleted."}; | |
| 119 end | |
| 120 table.remove(privacy_lists.lists, idx); | |
| 77 origin.send(st.reply(stanza)); | 121 origin.send(st.reply(stanza)); |
| 78 ret = true; | 122 return true; |
| 79 end | 123 end |
| 80 return ret; | 124 return {"modify", "bad-request", "Not existing list specifed to be deleted."}; |
| 81 end | 125 end |
| 82 | 126 |
| 83 local function sortByOrder(a, b) | 127 local function sortByOrder(a, b) |
| 84 if a.order < b.order then | 128 if a.order < b.order then |
| 85 return true; | 129 return true; |
| 87 return false; | 131 return false; |
| 88 end | 132 end |
| 89 | 133 |
| 90 function createOrReplaceList (privacy_lists, origin, stanza, name, entries, roster) | 134 function createOrReplaceList (privacy_lists, origin, stanza, name, entries, roster) |
| 91 module:log("info", "User requests to create / replace list named %s, item count: %d", name, #entries); | 135 module:log("info", "User requests to create / replace list named %s, item count: %d", name, #entries); |
| 92 local ret = true; | |
| 93 local idx = findNamedList(privacy_lists, name); | 136 local idx = findNamedList(privacy_lists, name); |
| 94 local bare_jid = origin.username.."@"..origin.host; | 137 local bare_jid = origin.username.."@"..origin.host; |
| 95 | 138 |
| 96 if privacy_lists.lists == nil then | 139 if privacy_lists.lists == nil then |
| 97 privacy_lists.lists = {}; | 140 privacy_lists.lists = {}; |
| 106 list.name = name; | 149 list.name = name; |
| 107 list.items = {}; | 150 list.items = {}; |
| 108 | 151 |
| 109 for _,item in ipairs(entries) do | 152 for _,item in ipairs(entries) do |
| 110 if to_number(item.attr.order) == nil or to_number(item.attr.order) < 0 or orderCheck[item.attr.order] ~= nil then | 153 if to_number(item.attr.order) == nil or to_number(item.attr.order) < 0 or orderCheck[item.attr.order] ~= nil then |
| 111 return "bad-request"; | 154 return {"modify", "bad-request", "Order attribute not valid."}; |
| 112 end | 155 end |
| 156 | |
| 157 if item.attr.type ~= nil and item.attr.type ~= "jid" and item.attr.type ~= "subscription" and item.attr.type ~= "group" then | |
| 158 return {"modify", "bad-request", "Type attribute not valid."}; | |
| 159 end | |
| 160 | |
| 113 local tmp = {}; | 161 local tmp = {}; |
| 114 orderCheck[item.attr.order] = true; | 162 orderCheck[item.attr.order] = true; |
| 115 | 163 |
| 116 tmp["type"] = item.attr.type; | 164 tmp["type"] = item.attr.type; |
| 117 tmp["value"] = item.attr.value; | 165 tmp["value"] = item.attr.value; |
| 131 if tmp.type == "group" then | 179 if tmp.type == "group" then |
| 132 local found = false; | 180 local found = false; |
| 133 local roster = load_roster(origin.username, origin.host); | 181 local roster = load_roster(origin.username, origin.host); |
| 134 local groups = roster.groups; | 182 local groups = roster.groups; |
| 135 if groups == nil then | 183 if groups == nil then |
| 136 return "item-not-found"; | 184 return {"cancel", "item-not-found", "Specifed roster group not existing."}; |
| 137 end | 185 end |
| 138 for _,group in ipairs(groups) do | 186 for _,group in ipairs(groups) do |
| 139 if group == tmp.value then | 187 if group == tmp.value then |
| 140 found = true; | 188 found = true; |
| 141 end | 189 end |
| 142 end | 190 end |
| 143 if found == false then | 191 if found == false then |
| 144 return "item-not-found"; | 192 return {"cancel", "item-not-found", "Specifed roster group not existing."}; |
| 145 end | 193 end |
| 146 elseif tmp.type == "subscription" then | 194 elseif tmp.type == "subscription" then |
| 147 if tmp.value ~= "both" and | 195 if tmp.value ~= "both" and |
| 148 tmp.value ~= "to" and | 196 tmp.value ~= "to" and |
| 149 tmp.value ~= "from" and | 197 tmp.value ~= "from" and |
| 150 tmp.value ~= "none" then | 198 tmp.value ~= "none" then |
| 151 return "bad-request"; | 199 return {"cancel", "bad-request", "Subscription value must be both, to, from or none."}; |
| 152 end | 200 end |
| 153 end | 201 end |
| 154 | 202 |
| 155 if tmp.action ~= "deny" and tmp.action ~= "allow" then | 203 if tmp.action ~= "deny" and tmp.action ~= "allow" then |
| 156 return "bad-request"; | 204 return {"cancel", "bad-request", "Action must be either deny or allow."}; |
| 157 end | 205 end |
| 158 | 206 |
| 159 list.items[#list.items + 1] = tmp; | 207 list.items[#list.items + 1] = tmp; |
| 160 end | 208 end |
| 161 | 209 |
| 170 iq:up(); | 218 iq:up(); |
| 171 for resource, session in pairs(bare_sessions[bare_jid].sessions) do | 219 for resource, session in pairs(bare_sessions[bare_jid].sessions) do |
| 172 iq.attr.to = bare_jid.."/"..resource | 220 iq.attr.to = bare_jid.."/"..resource |
| 173 session.send(iq); | 221 session.send(iq); |
| 174 end | 222 end |
| 223 else | |
| 224 return {"cancel", "bad-request", "internal error."}; | |
| 175 end | 225 end |
| 176 return true; | 226 return true; |
| 177 end | 227 end |
| 178 | 228 |
| 179 function getList(privacy_lists, origin, stanza, name) | 229 function getList(privacy_lists, origin, stanza, name) |
| 180 module:log("info", "User requests list named: %s", name or "nil"); | 230 module:log("info", "User requests list named: %s", name or "nil"); |
| 181 local ret = false; | |
| 182 local reply = st.reply(stanza); | 231 local reply = st.reply(stanza); |
| 183 reply:tag("query", {xmlns="jabber:iq:privacy"}); | 232 reply:tag("query", {xmlns="jabber:iq:privacy"}); |
| 184 | 233 |
| 185 if name == nil then | 234 if name == nil then |
| 186 reply:tag("active", {name=origin.activePrivacyList or ""}):up(); | 235 reply:tag("active", {name=origin.activePrivacyList or ""}):up(); |
| 188 if privacy_lists.lists then | 237 if privacy_lists.lists then |
| 189 for _,list in ipairs(privacy_lists.lists) do | 238 for _,list in ipairs(privacy_lists.lists) do |
| 190 reply:tag("list", {name=list.name}):up(); | 239 reply:tag("list", {name=list.name}):up(); |
| 191 end | 240 end |
| 192 end | 241 end |
| 193 ret = true; | |
| 194 else | 242 else |
| 195 local idx = findNamedList(privacy_lists, name); | 243 local idx = findNamedList(privacy_lists, name); |
| 196 module:log("debug", "list idx: %d", idx or -1); | 244 module:log("debug", "list idx: %d", idx or -1); |
| 197 if idx ~= nil then | 245 if idx ~= nil then |
| 198 list = privacy_lists.lists[idx]; | 246 list = privacy_lists.lists[idx]; |
| 203 if item["iq"] then reply:tag("iq"):up(); end | 251 if item["iq"] then reply:tag("iq"):up(); end |
| 204 if item["presence-in"] then reply:tag("presence-in"):up(); end | 252 if item["presence-in"] then reply:tag("presence-in"):up(); end |
| 205 if item["presence-out"] then reply:tag("presence-out"):up(); end | 253 if item["presence-out"] then reply:tag("presence-out"):up(); end |
| 206 reply:up(); | 254 reply:up(); |
| 207 end | 255 end |
| 208 ret = true; | 256 else |
| 209 end | 257 return {"cancel", "item-not-found", "Unknown list specified."}; |
| 210 end | 258 end |
| 211 | 259 end |
| 212 if ret then | 260 |
| 213 origin.send(reply); | 261 origin.send(reply); |
| 214 end | 262 return true; |
| 215 return ret; | |
| 216 end | 263 end |
| 217 | 264 |
| 218 module:hook("iq/bare/jabber:iq:privacy:query", function(data) | 265 module:hook("iq/bare/jabber:iq:privacy:query", function(data) |
| 219 local origin, stanza = data.origin, data.stanza; | 266 local origin, stanza = data.origin, data.stanza; |
| 220 | 267 |
| 221 if stanza.attr.to == nil then -- only service requests to own bare JID | 268 if stanza.attr.to == nil then -- only service requests to own bare JID |
| 222 local err_reply = nil; | |
| 223 local query = stanza.tags[1]; -- the query element | 269 local query = stanza.tags[1]; -- the query element |
| 224 local valid = false; | 270 local valid = false; |
| 225 local privacy_lists = datamanager.load(origin.username, origin.host, "privacy") or {}; | 271 local privacy_lists = datamanager.load(origin.username, origin.host, "privacy") or {}; |
| 226 | 272 |
| 227 if stanza.attr.type == "set" then | 273 if stanza.attr.type == "set" then |
| 230 if tag.name == "active" or tag.name == "default" then | 276 if tag.name == "active" or tag.name == "default" then |
| 231 if tag.attr.name == nil then -- Client declines the use of active / default list | 277 if tag.attr.name == nil then -- Client declines the use of active / default list |
| 232 valid = declineList(privacy_lists, origin, stanza, tag.name); | 278 valid = declineList(privacy_lists, origin, stanza, tag.name); |
| 233 else -- Client requests change of active / default list | 279 else -- Client requests change of active / default list |
| 234 valid = activateList(privacy_lists, origin, stanza, tag.name, tag.attr.name); | 280 valid = activateList(privacy_lists, origin, stanza, tag.name, tag.attr.name); |
| 235 if valid ~= true and valid ~= false then | |
| 236 err_reply = st.error_reply(stanza, "cancel", valid); | |
| 237 valid = false; | |
| 238 end | |
| 239 end | 281 end |
| 240 elseif tag.name == "list" and tag.attr.name then -- Client adds / edits a privacy list | 282 elseif tag.name == "list" and tag.attr.name then -- Client adds / edits a privacy list |
| 241 if #tag.tags == 0 then -- Client removes a privacy list | 283 if #tag.tags == 0 then -- Client removes a privacy list |
| 242 valid = deleteList(privacy_lists, origin, stanza, tag.attr.name); | 284 valid = deleteList(privacy_lists, origin, stanza, tag.attr.name); |
| 243 else -- Client edits a privacy list | 285 else -- Client edits a privacy list |
| 244 valid = createOrReplaceList(privacy_lists, origin, stanza, tag.attr.name, tag.tags); -- TODO check if used! | 286 valid = createOrReplaceList(privacy_lists, origin, stanza, tag.attr.name, tag.tags); -- TODO check if used! |
| 245 if valid ~= true and valid ~= false then | |
| 246 err_reply = st.error_reply(stanza, "cancel", valid); | |
| 247 valid = false; | |
| 248 end | |
| 249 end | 287 end |
| 250 end | 288 end |
| 251 end | 289 end |
| 252 end | 290 end |
| 253 elseif stanza.attr.type == "get" then | 291 elseif stanza.attr.type == "get" then |
| 261 end | 299 end |
| 262 end | 300 end |
| 263 end | 301 end |
| 264 if listsToRetrieve == 0 or listsToRetrieve == 1 then | 302 if listsToRetrieve == 0 or listsToRetrieve == 1 then |
| 265 valid = getList(privacy_lists, origin, stanza, name); | 303 valid = getList(privacy_lists, origin, stanza, name); |
| 266 err_reply = st.error_reply(stanza, "cancel", "item-not-found"); | 304 end |
| 267 end | 305 end |
| 268 end | 306 |
| 269 | 307 if valid ~= true then |
| 270 if valid == false then | 308 if valid[0] == nil then |
| 271 if err_reply == nil then | 309 valid[0] = "cancel"; |
| 272 err_reply = st.error_reply(stanza, "modify", "bad-request"); | 310 end |
| 273 end | 311 if valid[1] == nil then |
| 274 origin.send(err_reply); | 312 valid[1] = "bad-request"; |
| 313 end | |
| 314 origin.send(st.error_reply(stanza, valid[0], valid[1], valid[2])); | |
| 275 else | 315 else |
| 276 datamanager.store(origin.username, origin.host, "privacy", privacy_lists); | 316 datamanager.store(origin.username, origin.host, "privacy", privacy_lists); |
| 277 end | 317 end |
| 278 return true; | 318 return true; |
| 279 end | 319 end |
