view mod_http_muc_kick/mod_http_muc_kick.lua @ 4981:f0fe95f9e21c

mod_s2s_smacks_timeout: Use mod_smacks to close stale s2s connections
author Kim Alvefur <zash@zash.se>
date Wed, 03 Aug 2022 03:14:17 +0200
parents e524a97730eb
children
line wrap: on
line source

local jid_split = require "util.jid".prepped_split;
local json = require "util.json";

module:depends("http");

local authorization = assert(
    module:get_option_string("http_muc_kick_authorization_header", nil),
    "http_muc_kick_authorization_header setting is missing, please add it to the Prosody config before using mod_http_muc_kick"
);

local function is_authorized(request)
    return request.headers.authorization == authorization;
end

local function check_muc(jid)
	local muc_node, host = jid_split(jid);

	if not hosts[host] then
		return nil, nil, "No such host: "..host;
	elseif not hosts[host].modules.muc then
		return nil, nil, "Host '"..host.."' is not a MUC service";
	end

	return muc_node, host;
end

local function get_muc(muc_jid)
    local muc_node, host, err = check_muc(muc_jid);
    if not muc_node then
        return nil, host, err;
    end

    local muc = prosody.hosts[host].modules.muc.get_room_from_jid(muc_jid);
    if not muc then
        return nil, host, "No MUC '"..muc_node.."' found for host: "..host;
    end
    
    return muc;
end

local function handle_error(response, status_code, error)
    response.headers.content_type = "application/json";
    response.status_code = status_code;
    response:send(json.encode({error = error}));

    -- return true to keep the connection open, and prevent other handlers from executing.
    -- https://prosody.im/doc/developers/http#return_value
    return true;
end

module:provides("http", {
    route = {
        ["POST"] = function (event)
            local request, response = event.request, event.response;

            if not is_authorized(request) then
                return handle_error(response, 401, "Authorization failed");
            end

            local body = json.decode(request.body or "") or {};
            if not body then
                return handle_error(response, 400, "JSON body not found");
            end

            local nickname, muc_jid, reason = body.nickname, body.muc, body.reason or "";
            if not nickname or not muc_jid then
                return handle_error(response, 400, "Missing nickname and/or MUC");
            end

        	local muc, _, err = get_muc(muc_jid);
            if not muc then
                return handle_error(response, 404, "MUC not found: " .. err);
            end

            local occupant_jid = muc.jid .. "/" .. nickname;

            -- Kick user by giving them the "none" role
            -- https://xmpp.org/extensions/xep-0045.html#kick
            local success, error, condition = muc:set_role(true, occupant_jid, nil, reason);
            if not success then
                return handle_error(response, 400, "Couldn't kick user: ".. error .. ": " .. condition);
            end
            
            -- Kick was successful
        	return 200;
        end;
    };
});