Comparison

plugins/muc/muc.lib.lua @ 1742:1483a62d69bb

MUC: Owners can now modify roles and affiliations
author Waqas Hussain <waqas20@gmail.com>
date Mon, 07 Sep 2009 20:30:16 +0500
parent 1740:b37ccf9bec89
child 1743:d00b144f4bcf
comparison
equal deleted inserted replaced
1741:2919f3b985fc 1742:1483a62d69bb
145 stanza:tag("x", {xmlns = "jabber:x:delay", from = muc_domain, stamp = datetime.legacy()}):up(); -- XEP-0091 (deprecated) 145 stanza:tag("x", {xmlns = "jabber:x:delay", from = muc_domain, stamp = datetime.legacy()}):up(); -- XEP-0091 (deprecated)
146 t_insert(history, st.clone(st.preserialize(stanza))); 146 t_insert(history, st.clone(st.preserialize(stanza)));
147 while #history > history_length do t_remove(history, 1) end 147 while #history > history_length do t_remove(history, 1) end
148 end 148 end
149 end 149 end
150 150 function room_mt:broadcast_except_nick(stanza, nick)
151 for nick, occupant in pairs(self._occupants) do
152 if nick ~= nick then
153 for jid in pairs(occupant.sessions) do
154 stanza.attr.to = jid;
155 self:route_stanza(stanza);
156 end
157 end
158 end
159 end
151 160
152 function room_mt:send_occupant_list(to) 161 function room_mt:send_occupant_list(to)
153 local current_nick = self._jid_nick[to]; 162 local current_nick = self._jid_nick[to];
154 for occupant, o_data in pairs(self._occupants) do 163 for occupant, o_data in pairs(self._occupants) do
155 if occupant ~= current_nick then 164 if occupant ~= current_nick then
307 elseif xmlns == "http://jabber.org/protocol/disco#items" then 316 elseif xmlns == "http://jabber.org/protocol/disco#items" then
308 origin.send(room_get_disco_items(self, stanza)); 317 origin.send(room_get_disco_items(self, stanza));
309 else 318 else
310 origin.send(st.error_reply(stanza, "cancel", "service-unavailable")); 319 origin.send(st.error_reply(stanza, "cancel", "service-unavailable"));
311 end 320 end
321 elseif stanza.name == "iq" and type == "set" and stanza.tags[1].attr.xmlns == "http://jabber.org/protocol/muc#admin" then
322 local actor = stanza.attr.from;
323 local affiliation = self:get_affiliation(actor);
324 local current_nick = self._jid_nick[actor];
325 local role = current_nick and self._occupants[current_nick].role or self:get_default_role(affiliation);
326 local item = stanza.tags[1].tags[1];
327 if item and item.name == "item" then
328 local callback = function() origin.send(st.reply(stanza)); end
329 if item.attr.affiliation and item.attr.jid and not item.attr.role and not item.attr.nick then
330 local success, errtype, err = self:set_affiliation(actor, item.attr.jid, item.attr.affiliation, callback);
331 if not success then origin.send(st.error_reply(stanza, errtype, err)); end
332 elseif item.attr.role and item.attr.nick and not item.attr.affiliation and not item.attr.jid then
333 local success, errtype, err = self:set_role(actor, item.attr.nick, item.attr.role, callback);
334 if not success then origin.send(st.error_reply(stanza, errtype, err)); end
335 else
336 origin.send(st.error_reply(stanza, "cancel", "bad-request"));
337 end
338 else
339 origin.send(st.error_reply(stanza, "cancel", "bad-request"));
340 end
312 elseif stanza.name == "message" and type == "groupchat" then 341 elseif stanza.name == "message" and type == "groupchat" then
313 local from, to = stanza.attr.from, stanza.attr.to; 342 local from, to = stanza.attr.from, stanza.attr.to;
314 local room = jid_bare(to); 343 local room = jid_bare(to);
315 local current_nick = self._jid_nick[from]; 344 local current_nick = self._jid_nick[from];
316 if not current_nick then -- not in room 345 if not current_nick then -- not in room
367 local bare = node and node.."@"..host or host; 396 local bare = node and node.."@"..host or host;
368 local result = self._affiliations[bare]; -- Affiliations are granted, revoked, and maintained based on the user's bare JID. 397 local result = self._affiliations[bare]; -- Affiliations are granted, revoked, and maintained based on the user's bare JID.
369 if not result and self._affiliations[host] == "outcast" then result = "outcast"; end -- host banned 398 if not result and self._affiliations[host] == "outcast" then result = "outcast"; end -- host banned
370 return result; 399 return result;
371 end 400 end
372 401 function room_mt:set_affiliation(actor, jid, affiliation, callback)
373 function room_mt:set_affiliation(jid, affiliation) 402 jid = jid_bare(jid);
374 local node, host, resource = jid_split(jid);
375 local bare = node and node.."@"..host or host;
376 if affiliation == "none" then affiliation = nil; end 403 if affiliation == "none" then affiliation = nil; end
377 if affiliation and affiliation ~= "outcast" and affiliation ~= "owner" and affiliation ~= "admin" and affiliation ~= "member" then return false; end 404 if affiliation and affiliation ~= "outcast" and affiliation ~= "owner" and affiliation ~= "admin" and affiliation ~= "member" then
378 self._affiliations[bare] = affiliation; 405 return nil, "modify", "not-acceptable";
379 -- TODO set roles based on new affiliation 406 end
407 if self:get_affiliation(actor) ~= "owner" then return nil, "cancel", "not-allowed"; end
408 if jid_bare(actor) == jid then return nil, "cancel", "not-allowed"; end
409 self._affiliations[jid] = affiliation;
410 local role = self:get_default_role(affiliation);
411 local p = st.presence({type = "unavailable"})
412 :tag("x", {xmlns = "http://jabber.org/protocol/muc#user"})
413 :tag("item", {affiliation=affiliation, role=role or "none"}):up();
414 local x = p.tags[1];
415 local item = x.tags[1];
416 if not role then -- getting kicked
417 if affiliation == "outcast" then
418 x:tag("status", {code="301"}):up(); -- banned
419 else
420 x:tag("status", {code="321"}):up(); -- affiliation change
421 end
422 end
423 local modified_nicks = {};
424 for nick, occupant in pairs(self._occupants) do
425 if jid_bare(occupant.jid) == jid then
426 if not role then -- getting kicked
427 self._occupants[nick] = nil;
428 else
429 t_insert(modified_nicks, nick);
430 occupant.affiliation, occupant.role = affiliation, role;
431 end
432 p.attr.from = nick;
433 for jid in pairs(occupant.sessions) do -- remove for all sessions of the nick
434 if not role then self._jid_nick[jid] = nil; end
435 p.attr.to = jid;
436 self:route_stanza(p);
437 end
438 end
439 end
440 if callback then callback(); end
441 for _, nick in ipairs(modified_nicks) do
442 p.attr.from = nick;
443 self:broadcast_except_nick(p, nick);
444 end
445 return true;
446 end
447
448 function room_mt:get_role(nick)
449 local session = self._occupants[nick];
450 return session and session.role or nil;
451 end
452 function room_mt:set_role(actor, nick, role, callback)
453 if role and role ~= "moderator" and role ~= "participant" and role ~= "visitor" then return nil, "modify", "not-acceptable"; end
454 if self:get_affiliation(actor) ~= "owner" then return nil, "cancel", "not-allowed"; end
455 local occupant = self._occupants[nick];
456 if not occupant then return nil, "modify", "not-acceptable"; end
457 if jid_bare(actor) == occupant.jid then return nil, "cancel", "not-allowed"; end
458 local p = st.presence({from = nick, type = "unavailable"})
459 :tag("x", {xmlns = "http://jabber.org/protocol/muc#user"})
460 :tag("item", {affiliation=occupant.affiliation, nick=nick, role=role or "none"}):up();
461 if not role then -- kick
462 self._occupants[nick] = nil;
463 for jid in pairs(occupant.sessions) do -- remove for all sessions of the nick
464 self._jid_nick[jid] = nil;
465 end
466 p:tag("status", {code = "307"}):up();
467 else
468 occupant.role = role;
469 end
470 for jid in pairs(occupant.sessions) do -- send to all sessions of the nick
471 p.attr.to = jid;
472 self:route_stanza(p);
473 end
474 if callback then callback(); end
475 self:broadcast_except_nick(p, nick);
380 return true; 476 return true;
381 end 477 end
382 478
383 local _M = {}; -- module "muc" 479 local _M = {}; -- module "muc"
384 480