plugins/muc: Add muc-occupant-groupchat event
authordaurnimator <quae@daurnimator.com>
Thu, 25 Sep 2014 21:43:00 +0000 (17:43 -0400)
committerdaurnimator <quae@daurnimator.com>
Thu, 25 Sep 2014 21:43:00 +0000 (17:43 -0400)
  - Plugins can cancel messages before they are broadcast; and while they still have real from jid
  - Use it for subject changes
  - Allows for custom roles (via role_rank)
  - Roles are now checked before subject
  - Removed muc-subject-change event

plugins/muc/muc.lib.lua
plugins/muc/subject.lib.lua

index f2dde69ecec66d7580e8243ac789fad5ccb1000b..35dd9eac6ca4c94d6ced53e468d84a66e09b0201 100644 (file)
@@ -804,26 +804,29 @@ function room_mt:handle_owner_query_set_to_room(origin, stanza)
 end
 
 function room_mt:handle_groupchat_to_room(origin, stanza)
-       -- Prosody has made the decision that messages with <subject/> are exclusively subject changes
-       -- e.g. body will be ignored; even if the subject change was not allowed
-       if stanza:get_child("subject") then
-               return module:fire_event("muc-subject-change", {room = self, origin = origin, stanza = stanza});
-       end
        local from = stanza.attr.from;
        local occupant = self:get_occupant_by_real_jid(from);
-       if not occupant then -- not in room
-               origin.send(st.error_reply(stanza, "cancel", "not-acceptable"));
-               return true;
-       elseif occupant.role == "visitor" then
-               origin.send(st.error_reply(stanza, "auth", "forbidden"));
-               return true;
-       end
+       if module:fire_event("muc-occupant-groupchat", {
+               room = self; origin = origin; stanza = stanza; from = from; occupant = occupant;
+       }) then return true; end
        stanza.attr.from = occupant.nick;
        self:broadcast_message(stanza);
        stanza.attr.from = from;
        return true;
 end
 
+-- Role check
+module:hook("muc-occupant-groupchat", function(event)
+       local role_rank = valid_roles[event.occupant and event.occupant.role or "none"];
+       if role_rank <= valid_roles.none then
+               event.origin.send(st.error_reply(event.stanza, "cancel", "not-acceptable"));
+               return true;
+       elseif role_rank <= valid_roles.visitor then
+               event.origin.send(st.error_reply(event.stanza, "auth", "forbidden"));
+               return true;
+       end
+end, 50);
+
 -- hack - some buggy clients send presence updates to the room rather than their nick
 function room_mt:handle_presence_to_room(origin, stanza)
        local current_nick = self:get_occupant_jid(stanza.attr.from);
index 34f9a5d4127a71c71c3d7934f49aedfea5fa8768..d1895b4d51e2180f3d9e8121fae061a471a5f454 100644 (file)
@@ -9,6 +9,9 @@
 
 local st = require "util.stanza";
 
+local muc_util = module:require "muc/util";
+local valid_roles = muc_util.valid_roles;
+
 local function create_subject_message(from, subject)
        return st.message({from = from; type = "groupchat"})
                :tag("subject"):text(subject):up();
@@ -70,20 +73,25 @@ module:hook("muc-occupant-session-new", function(event)
        send_subject(event.room, event.stanza.attr.from);
 end, 20);
 
--- Role check for subject changes
-module:hook("muc-subject-change", function(event)
-       local room, stanza = event.room, event.stanza;
-       local occupant = room:get_occupant_by_real_jid(stanza.attr.from);
-       if occupant.role == "moderator" or
-               ( occupant.role == "participant" and get_changesubject(room) ) then -- and participant
-               local subject = stanza:get_child_text("subject");
-               set_subject(room, occupant.nick, subject);
-               return true;
-       else
-               event.origin.send(st.error_reply(stanza, "auth", "forbidden"));
-               return true;
+-- Prosody has made the decision that messages with <subject/> are exclusively subject changes
+-- e.g. body will be ignored; even if the subject change was not allowed
+module:hook("muc-occupant-groupchat", function(event)
+       local stanza = event.stanza;
+       local subject = stanza:get_child("subject");
+       if subject then
+               local occupant = event.occupant;
+               -- Role check for subject changes
+               local role_rank = valid_roles[occupant and occupant.role or "none"];
+               if role_rank >= valid_roles.moderator or
+                       ( role_rank >= valid_roles.participant and get_changesubject(event.room) ) then -- and participant
+                       set_subject(event.room, occupant.nick, subject:get_text());
+                       return true;
+               else
+                       event.origin.send(st.error_reply(stanza, "auth", "forbidden"));
+                       return true;
+               end
        end
-end);
+end, 20);
 
 return {
        get_changesubject = get_changesubject;