/
mod_muc_size.lua
190 lines (158 loc) · 5.67 KB
/
mod_muc_size.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
-- Prosody IM
-- Copyright (C) 2017 Atlassian
--
local jid = require "util.jid";
local it = require "util.iterators";
local json = require "util.json";
local iterators = require "util.iterators";
local array = require"util.array";
local wrap_async_run = module:require "util".wrap_async_run;
local tostring = tostring;
local neturl = require "net.url";
local parse = neturl.parseQuery;
-- option to enable/disable room API token verifications
local enableTokenVerification
= module:get_option_boolean("enable_roomsize_token_verification", false);
local token_util = module:require "token/util".new(module);
local get_room_from_jid = module:require "util".get_room_from_jid;
-- no token configuration but required
if token_util == nil and enableTokenVerification then
log("error", "no token configuration but it is required");
return;
end
-- required parameter for custom muc component prefix,
-- defaults to "conference"
local muc_domain_prefix
= module:get_option_string("muc_mapper_domain_prefix", "conference");
--- Verifies room name, domain name with the values in the token
-- @param token the token we received
-- @param room_address the full room address jid
-- @return true if values are ok or false otherwise
function verify_token(token, room_address)
if not enableTokenVerification then
return true;
end
-- if enableTokenVerification is enabled and we do not have token
-- stop here, cause the main virtual host can have guest access enabled
-- (allowEmptyToken = true) and we will allow access to rooms info without
-- a token
if token == nil then
log("warn", "no token provided");
return false;
end
local session = {};
session.auth_token = token;
local verified, reason = token_util:process_and_verify_token(session);
if not verified then
log("warn", "not a valid token %s", tostring(reason));
return false;
end
if not token_util:verify_room(session, room_address) then
log("warn", "Token %s not allowed to join: %s",
tostring(token), tostring(room_address));
return false;
end
return true;
end
--- Handles request for retrieving the room size
-- @param event the http event, holds the request query
-- @return GET response, containing a json with participants count,
-- tha value is without counting the focus.
function handle_get_room_size(event)
if (not event.request.url.query) then
return 400;
end
local params = parse(event.request.url.query);
local room_name = params["room"];
local domain_name = params["domain"];
local subdomain = params["subdomain"];
local room_address
= jid.join(room_name, muc_domain_prefix.."."..domain_name);
if subdomain and subdomain ~= "" then
room_address = "["..subdomain.."]"..room_address;
end
if not verify_token(params["token"], room_address) then
return 403;
end
local room = get_room_from_jid(room_address);
local participant_count = 0;
log("debug", "Querying room %s", tostring(room_address));
if room then
local occupants = room._occupants;
if occupants then
participant_count = iterators.count(room:each_occupant());
end
log("debug",
"there are %s occupants in room", tostring(participant_count));
else
log("debug", "no such room exists");
return 404;
end
if participant_count > 1 then
participant_count = participant_count - 1;
end
return [[{"participants":]]..participant_count..[[}]];
end
--- Handles request for retrieving the room participants details
-- @param event the http event, holds the request query
-- @return GET response, containing a json with participants details
function handle_get_room (event)
if (not event.request.url.query) then
return 400;
end
local params = parse(event.request.url.query);
local room_name = params["room"];
local domain_name = params["domain"];
local subdomain = params["subdomain"];
local room_address
= jid.join(room_name, muc_domain_prefix.."."..domain_name);
if subdomain ~= "" then
room_address = "["..subdomain.."]"..room_address;
end
if not verify_token(params["token"], room_address) then
return 403;
end
local room = get_room_from_jid(room_address);
local participant_count = 0;
local occupants_json = array();
log("debug", "Querying room %s", tostring(room_address));
if room then
local occupants = room._occupants;
if occupants then
participant_count = iterators.count(room:each_occupant());
for _, occupant in room:each_occupant() do
-- filter focus as we keep it as hidden participant
if string.sub(occupant.nick,-string.len("/focus"))~="/focus" then
for _, pr in occupant:each_session() do
local nick = pr:get_child_text("nick", "http://jabber.org/protocol/nick") or "";
local email = pr:get_child_text("email") or "";
occupants_json:push({
jid = tostring(occupant.nick),
email = tostring(email),
display_name = tostring(nick)});
end
end
end
end
log("debug",
"there are %s occupants in room", tostring(participant_count));
else
log("debug", "no such room exists");
return 404;
end
if participant_count > 1 then
participant_count = participant_count - 1;
end
return json.encode(occupants_json);
end;
function module.load()
module:depends("http");
module:provides("http", {
default_path = "/";
route = {
["GET room-size"] = function (event) return wrap_async_run(event,handle_get_room_size) end;
["GET sessions"] = function () return tostring(it.count(it.keys(prosody.full_sessions))); end;
["GET room"] = function (event) return wrap_async_run(event,handle_get_room) end;
};
});
end