There are modules that will not work with prosody 0.10 as they depend on util.async. Adds a safeguard and print error about it in the logs. And others that just do not work because of the muc module API that they use.
198 lines
5.8 KiB
Lua
198 lines
5.8 KiB
Lua
-- 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 have_async = pcall(require, "util.async");
|
|
if not have_async then
|
|
module:log("error", "requires a version of Prosody with util.async");
|
|
return;
|
|
end
|
|
|
|
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
|
|
|