Software /
code /
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 |
parent | 19:e400ee8471b0 |
child | 27: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 |