mod_invites_adhoc: Fail contact invite if user is not on current host
Only the username was being used, and the host of the requester ignored.
Luckily this only affects admins of the host. If they want to create an
account they can use the other command. If they want to create a contact
they should request from their account on this host.
module:depends("http");
local st = require "util.stanza";
local json = require "util.json";
local hashes = require "util.hashes";
local from_hex = require "util.hex".from;
local hmacs = {
sha1 = hashes.hmac_sha1;
sha256 = hashes.hmac_sha256;
sha384 = hashes.hmac_sha384;
sha512 = hashes.hmac_sha512;
};
local pubsub_service = module:depends("pubsub").service;
-- configuration
local default_node = module:get_option("github_node", "github");
local node_prefix = module:get_option_string("github_node_prefix", "github/");
local node_mapping = module:get_option_string("github_node_mapping");
local github_actor = module:get_option_string("github_actor") or true;
local github_secret = module:get_option("github_secret");
-- validation
assert(github_secret, "Please set 'github_secret'");
local error_mapping = {
["forbidden"] = 403;
["item-not-found"] = 404;
["internal-server-error"] = 500;
["conflict"] = 409;
};
local function verify_signature(secret, body, signature)
if not signature then return false; end
local algo, digest = signature:match("^([^=]+)=(%x+)");
if not algo then return false; end
local hmac = hmacs[algo];
if not algo then return false; end
return hmac(secret, body) == from_hex(digest);
end
function handle_POST(event)
local request, response = event.request, event.response;
if not verify_signature(github_secret, request.body, request.headers.x_hub_signature) then
module:log("debug", "Signature validation failed");
return 401;
end
local data = json.decode(request.body);
if not data then
response.status_code = 400;
return "Invalid JSON. From you of all people...";
end
local node = default_node;
if node_mapping then
node = node_prefix .. data.repository[node_mapping];
end
local github_event = request.headers.x_github_event or data.object_kind;
if not github_event and data.commits then
github_event = "push"; -- curl?
end
module:log("debug", "Handling '%s' event: \n%s\n", github_event, tostring(request.body));
if github_event == "push" then
for _, commit in ipairs(data.commits) do
local ok, err = pubsub_service:publish(node, github_actor, commit.id,
st.stanza("item", { id = commit.id, xmlns = "http://jabber.org/protocol/pubsub" })
:tag("entry", { xmlns = "http://www.w3.org/2005/Atom" })
:tag("id"):text(commit.id):up()
:tag("title"):text(commit.message:match("^[^\r\n]*")):up()
:tag("summary"):text(("Commit to %s by %s: %s"):format(data.repository.name, commit.author.name, commit.message:match("^[^\r\n]*"))):up()
:tag("content"):text(commit.message):up()
:tag("link", { rel = "alternate", href = commit.url }):up()
:tag("published"):text(commit.author.date):up()
:tag("author")
:tag("name"):text(commit.author.name):up()
:tag("email"):text(commit.author.email):up()
:up()
);
if not ok then
return error_mapping[err] or 500;
end
end
elseif github_event then
module:log("debug", "Unsupported Github event %q", github_event);
return 501;
end
response.status_code = 202;
return "Thank you Github!";
end
module:provides("http", {
route = {
POST = handle_POST;
};
});
if not node_mapping then
function module.load()
if not pubsub_service.nodes[default_node] then
local ok, err = pubsub_service:create(default_node, true);
if not ok then
module:log("error", "Error creating node: %s", err);
else
module:log("debug", "Node %q created", default_node);
end
end
end
end