// 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 :Request a prototype for creating a join event." }; const string_view make_join_description {R"( Sends a partial event to the remote with enough information for them to create a join event 'in the blind' for one of their users. )"}; resource make_join_resource { "/_matrix/federation/v1/make_join/", { make_join_description, resource::DIRECTORY } }; resource::response get__make_join(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 { "user_id path parameter required" }; m::user::id::buf user_id { url::decode(request.parv[1], user_id) }; int64_t depth; m::id::event::buf prev_event_id; std::tie(prev_event_id, depth, std::ignore) = m::top(room_id); const m::event::fetch evf { prev_event_id, std::nothrow }; const json::value prev[] { { string_view{prev_event_id} }, { json::get<"hashes"_>(evf) } }; const json::value prevs[] { { prev, 2 } }; const m::room::state state { room_id }; auto auth_event_id { state.get(std::nothrow, "m.room.member", user_id) }; if(!auth_event_id) auth_event_id = state.get("m.room.create"); const m::event::fetch aevf { auth_event_id, std::nothrow }; const json::value auth[] { { string_view{auth_event_id} }, { json::get<"hashes"_>(aevf) } }; const json::value auths[] { { auth, 2 } }; thread_local char bufs[96_KiB]; mutable_buffer buf{bufs}; json::iov content, event, wrapper; const json::iov::push push[] { { event, { "origin", request.origin }}, { event, { "origin_server_ts", time() }}, { event, { "room_id", room_id }}, { event, { "type", "m.room.member" }}, { event, { "state_key", user_id }}, { event, { "sender", user_id }}, { event, { "depth", depth + 1 }}, { event, { "membership", "join" }}, { content, { "membership", "join" }}, { event, { "auth_events", { auths, 1 } }}, { event, { "prev_state", "[]" }}, { event, { "prev_events", { prevs, 1 } }}, { event, { "content", stringify(buf, content) }}, { wrapper, { "event", stringify(buf, event) }}, }; return resource::response { client, wrapper }; } resource::method method_get { make_join_resource, "GET", get__make_join, { method_get.VERIFY_ORIGIN } };