Browse Source

Updates rayo filter to add user token info to dial messages.

Adds option to limit number of outgoing calls per user.
master
damencho 5 years ago
parent
commit
5cd351a46f
1 changed files with 117 additions and 1 deletions
  1. 117
    1
      resources/prosody-plugins/mod_filter_iq_rayo.lua

+ 117
- 1
resources/prosody-plugins/mod_filter_iq_rayo.lua View File

@@ -10,6 +10,13 @@ if token_util == nil then
10 10
     return;
11 11
 end
12 12
 
13
+-- configuration to limit number of outgoing calls
14
+local LIMIT_OUTGOING_CALLS = module:get_option_number("max_number_outgoing_calls", -1);
15
+
16
+-- Header names to use to push extra data extracted from token, if any
17
+local OUT_INITIATOR_USER_ATTR_NAME = "X-outbound-call-initiator-user";
18
+local OUT_INITIATOR_GROUP_ATTR_NAME = "X-outbound-call-initiator-group";
19
+
13 20
 -- filters rayo iq in case of requested from not jwt authenticated sessions
14 21
 -- or if the session has features in user context and it doesn't mention
15 22
 -- feature "outbound-call" to be enabled
@@ -39,11 +46,120 @@ module:hook("pre-iq/full", function(event)
39 46
                             (dial.attr.to == 'jitsi_meet_transcribe' and 'transcription'
40 47
                                 or 'outbound-call'))
41 48
             then
42
-                module:log("info",
49
+                module:log("warn",
43 50
                     "Filtering stanza dial, stanza:%s", tostring(stanza));
44 51
                 session.send(st.error_reply(stanza, "auth", "forbidden"));
45 52
                 return true;
46 53
             end
54
+
55
+            -- now lets check any limits if configured
56
+            if LIMIT_OUTGOING_CALLS > 0
57
+                and get_concurrent_outgoing_count(
58
+                        session.jitsi_meet_context_user["id"],
59
+                        session.jitsi_meet_context_group) >= LIMIT_OUTGOING_CALLS
60
+            then
61
+                module:log("warn",
62
+                    "Filtering stanza dial, stanza:%s, outgoing calls limit reached", tostring(stanza));
63
+                session.send(st.error_reply(stanza, "cancel", "resource-constraint"));
64
+                return true;
65
+            end
66
+
67
+            -- now lets insert token information if any
68
+            if session and session.jitsi_meet_context_user then
69
+                -- First remove any 'header' element if it already
70
+                -- exists, so it cannot be spoofed by a client
71
+                stanza:maptags(
72
+                    function(tag)
73
+                        if tag.name == "header"
74
+                                and (tag.attr.name == OUT_INITIATOR_USER_ATTR_NAME
75
+                                        or tag.attr.name == OUT_INITIATOR_GROUP_ATTR_NAME) then
76
+                            return nil
77
+                        end
78
+                        return tag
79
+                    end
80
+                )
81
+
82
+                local dial = stanza:get_child('dial', 'urn:xmpp:rayo:1');
83
+                -- adds initiator user id from token
84
+                dial:tag("header", {
85
+                    xmlns = "urn:xmpp:rayo:1",
86
+                    name = OUT_INITIATOR_USER_ATTR_NAME,
87
+                    value = session.jitsi_meet_context_user["id"] });
88
+                dial:up();
89
+
90
+                -- Add the initiator group information if it is present
91
+                if session.jitsi_meet_context_group then
92
+                    dial:tag("header", {
93
+                        xmlns = "urn:xmpp:rayo:1",
94
+                        name = OUT_INITIATOR_GROUP_ATTR_NAME,
95
+                        value = session.jitsi_meet_context_group });
96
+                    dial:up();
97
+                end
98
+            end
47 99
         end
48 100
     end
49 101
 end);
102
+
103
+--- Finds and returns the number of concurrent outgoing calls for a user
104
+-- @param context_user the user id extracted from the token
105
+-- @param context_group the group id extracted from the token
106
+-- @return returns the count of concurrent calls
107
+function get_concurrent_outgoing_count(context_user, context_group)
108
+    local count = 0;
109
+    for _, host in pairs(hosts) do
110
+        local component = host;
111
+        if component then
112
+            local muc = component.modules.muc
113
+            local rooms = nil;
114
+            if muc and rawget(muc,"rooms") then
115
+                -- We're running 0.9.x or 0.10 (old MUC API)
116
+                return muc.rooms;
117
+            elseif muc and rawget(muc,"live_rooms") then
118
+                -- We're running >=0.11 (new MUC API)
119
+                rooms = muc.live_rooms();
120
+            elseif muc and rawget(muc,"each_room") then
121
+                -- We're running trunk<0.11 (each_room is later [DEPRECATED])
122
+                rooms = muc.each_room(true);
123
+            end
124
+
125
+            -- now lets iterate over rooms and occupants and search for
126
+            -- call initiated by the user
127
+            if rooms then
128
+                for room in rooms do
129
+                    for _, occupant in room:each_occupant() do
130
+                        for _, presence in occupant:each_session() do
131
+
132
+                            local initiator = presence:get_child('initiator', 'http://jitsi.org/protocol/jigasi');
133
+
134
+                            local found_user = false;
135
+                            local found_group = false;
136
+
137
+                            if initiator then
138
+                                initiator:maptags(function (tag)
139
+                                    if tag.name == "header"
140
+                                        and tag.attr.name == OUT_INITIATOR_USER_ATTR_NAME then
141
+                                        found_user = tag.attr.value == context_user;
142
+                                    elseif tag.name == "header"
143
+                                        and tag.attr.name == OUT_INITIATOR_GROUP_ATTR_NAME then
144
+                                        found_group = tag.attr.value == context_group;
145
+                                    end
146
+
147
+                                    return tag;
148
+                                end );
149
+                                -- if found a jigasi participant initiated by the concurrent
150
+                                -- participant, count it
151
+                                if found_user
152
+                                    and (context_group == nil or found_group) then
153
+                                    count = count + 1;
154
+                                end
155
+                            end
156
+                        end
157
+                    end
158
+                end
159
+            end
160
+        end
161
+    end
162
+
163
+    return count;
164
+end
165
+

Loading…
Cancel
Save