From 66871bd598d096dbcc89e8642184673b240318a1 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Mon, 2 Apr 2018 22:36:49 -0700 Subject: [PATCH] modules/federation: Add invite endpoint; functional response w/o eval. --- modules/Makefile.am | 2 + modules/federation/invite.cc | 163 +++++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 modules/federation/invite.cc diff --git a/modules/Makefile.am b/modules/Makefile.am index 602cd94bc..2eb00b8bb 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -242,6 +242,7 @@ federation_federation_get_groups_publicised_la_SOURCES = federation/get_groups_p federation_federation_version_la_SOURCES = federation/version.cc federation_federation_sender_la_SOURCES = federation/sender.cc federation_federation_query_la_SOURCES = federation/query.cc +federation_federation_invite_la_SOURCES = federation/invite.cc federation_module_LTLIBRARIES = \ federation/federation_send.la \ @@ -251,6 +252,7 @@ federation_module_LTLIBRARIES = \ federation/federation_version.la \ federation/federation_sender.la \ federation/federation_query.la \ + federation/federation_invite.la \ ### ############################################################################### diff --git a/modules/federation/invite.cc b/modules/federation/invite.cc new file mode 100644 index 000000000..15a126f6c --- /dev/null +++ b/modules/federation/invite.cc @@ -0,0 +1,163 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2018 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +using namespace ircd; + +mapi::header +IRCD_MODULE +{ + "Federation 10 :Inviting to a room" +}; + +const string_view +invite_description +{R"( +When a user wishes to invite an other user to a local room and the other +user is on a different server, the inviting server will send a request to +the invited server. +)"}; + +resource +invite_resource +{ + "/_matrix/federation/v1/invite/", + { + invite_description, + resource::DIRECTORY + } +}; + +static void +check_event(const resource::request &request, + const m::event &event); + +resource::response +put__invite(client &client, + const resource::request &request) +{ + if(request.parv.size() < 1) + throw m::NEED_MORE_PARAMS + { + "room_id path parameter required" + }; + + m::room::id::buf room_id + { + url::decode(request.parv[0], room_id) + }; + + if(request.parv.size() < 2) + throw m::NEED_MORE_PARAMS + { + "event_id path parameter required" + }; + + m::event::id::buf event_id + { + url::decode(request.parv[1], event_id) + }; + + const m::event event + { + request + }; + + check_event(request, event); + + //TODO: eval() + + const json::strung event_strung + { + event + }; + + const json::member revent + { + "event", event_strung + }; + + const json::value response[] + { + json::value { 200L }, + json::value { &revent, 1 }, + }; + + return resource::response + { + client, json::value + { + response, 2 + } + }; +} + +resource::method +method_put +{ + invite_resource, "PUT", put__invite, + { + method_put.VERIFY_ORIGIN + } +}; + +void +check_event(const resource::request &request, + const m::event &event) +{ + if(at<"type"_>(event) != "m.room.member") + throw m::error + { + http::NOT_MODIFIED, "M_INVALID_TYPE", + "event.type must be m.room.member" + }; + + if(at<"membership"_>(event) != "invite") + throw m::error + { + http::NOT_MODIFIED, "M_INVALID_MEMBERSHIP", + "event.membership must be invite." + }; + + if(unquote(at<"content"_>(event).at("membership")) != "invite") + throw m::error + { + http::NOT_MODIFIED, "M_INVALID_CONTENT_MEMBERSHIP", + "event.content.membership must be invite." + }; + + if(at<"origin"_>(event) != request.origin) + throw m::error + { + http::FORBIDDEN, "M_INVALID_ORIGIN", + "event.origin must be you." + }; + + if(!my_host(m::user::id(at<"state_key"_>(event)).host())) + throw m::error + { + http::FORBIDDEN, "M_INVALID_STATE_KEY", + "event.state_key must be my user." + }; + + m::event::conforms non_conforms; + non_conforms |= non_conforms.MISSING_PREV_STATE; + const m::event::conforms report + { + event, non_conforms.report + }; + + if(!report.clean()) + throw m::error + { + http::NOT_MODIFIED, "M_INVALID_EVENT", + "Proffered event has the following problems: %s", + string(report) + }; +}