diff --git a/modules/client/rooms/state.cc b/modules/client/rooms/state.cc index 87dc56a07..91b4b8f8c 100644 --- a/modules/client/rooms/state.cc +++ b/modules/client/rooms/state.cc @@ -13,72 +13,29 @@ using namespace ircd::m; using namespace ircd; -static resource::response -get__state(client &client, - const resource::request &request, - const room::id &room_id, - const string_view &event_id); - -static resource::response -get__state(client &client, - const resource::request &request, - const room::id &room_id, - const string_view &event_id, - const string_view &type); - -static resource::response -get__state(client &client, - const resource::request &request, - const room::id &room_id, - const string_view &event_id, - const string_view &type, - const string_view &state_key); - -resource::response -get__state(client &client, - const resource::request &request, - const room::id &room_id) -{ - char type_buf[m::event::TYPE_MAX_SIZE]; - const string_view &type - { - url::decode(type_buf, request.parv[2]) - }; - - char skey_buf[m::event::STATE_KEY_MAX_SIZE]; - const string_view &state_key - { - url::decode(skey_buf, request.parv[3]) - }; - - // (non-standard) Allow an event_id to be passed in the query string - // for reference framing. - char evid_buf[m::id::MAX_SIZE]; - const string_view &event_id - { - url::decode(evid_buf, request.query["event_id"]) - }; - - if(type && state_key) - return get__state(client, request, room_id, event_id, type, state_key); - - if(type) - return get__state(client, request, room_id, event_id, type); - - return get__state(client, request, room_id, event_id); -} - resource::response put__state(client &client, const resource::request &request, const room::id &room_id) { + if(request.parv.size() < 3) + throw m::NEED_MORE_PARAMS + { + "'type' path parameter required." + }; + char type_buf[m::event::TYPE_MAX_SIZE]; const string_view &type { url::decode(type_buf, request.parv[2]) }; + if(request.parv.size() < 3) + throw m::NEED_MORE_PARAMS + { + "'state_key' path parameter required." + }; + char skey_buf[m::event::STATE_KEY_MAX_SIZE]; const string_view &state_key { @@ -104,89 +61,109 @@ put__state(client &client, }; } +static resource::response +get__state(client &client, + const resource::request &request, + const m::room::state &state); + resource::response get__state(client &client, const resource::request &request, - const room::id &room_id, - const string_view &event_id) + const room::id &room_id) { - const room::state state + char type_buf[m::event::TYPE_MAX_SIZE]; + const string_view &type { - room{room_id, event_id} + url::decode(type_buf, request.parv[2]) }; - std::vector ret; - ret.reserve(32); - - state.for_each([&ret] - (const event &event) + char skey_buf[m::event::STATE_KEY_MAX_SIZE]; + const string_view &state_key { - ret.emplace_back(event); + url::decode(skey_buf, request.parv[3]) + }; + + // (non-standard) Allow an event_id to be passed in the query string + // for reference framing. + m::event::id::buf event_id; + if(request.query["event_id"]) + url::decode(event_id, request.query["event_id"]); + + const m::room room + { + room_id, event_id + }; + + if(!exists(room)) + throw m::NOT_FOUND + { + "Room %s not found.", + string_view{room_id} + }; + + if(!room.visible(request.user_id)) + throw m::ACCESS_DENIED + { + "You are not permitted to view %s", + string_view{room_id} + }; + + const m::room::state state + { + room + }; + + if(!type) + return get__state(client, request, state); + + m::event::fetch::opts fopts; + fopts.query_json_force = true; + const m::event::fetch event + { + state.get(type, state_key), fopts + }; + + if(!visible(event, request.user_id)) + throw m::ACCESS_DENIED + { + "You are not permitted to view this state in %s", + string_view{room_id} + }; + + return resource::response + { + client, event.source + }; +} + +resource::response +get__state(client &client, + const resource::request &request, + const m::room::state &state) +{ + resource::response::chunked response + { + client, http::OK + }; + + json::stack out + { + response.buf, response.flusher() + }; + + json::stack::array top + { + out + }; + + state.for_each([&request, &top] + (const m::event &event) + { + if(!visible(event, request.user_id)) + return; + + top.append(event); }); - return resource::response - { - client, json::value - { - ret.data(), ret.size() - } - }; -} - -resource::response -get__state(client &client, - const resource::request &request, - const room::id &room_id, - const string_view &event_id, - const string_view &type) -{ - const room::state state - { - room{room_id, event_id} - }; - - std::vector ret; - ret.reserve(32); - state.for_each(type, [&ret] - (const event &event) - { - ret.emplace_back(event); - }); - - return resource::response - { - client, json::value - { - ret.data(), ret.size() - } - }; -} - -resource::response -get__state(client &client, - const resource::request &request, - const room::id &room_id, - const string_view &event_id, - const string_view &type, - const string_view &state_key) -{ - const room::state state - { - room{room_id, event_id} - }; - - std::array ret; - const bool i{state.get(std::nothrow, type, state_key, [&ret] - (const event &event) - { - ret[0] = event; - })}; - - return resource::response - { - client, json::value - { - ret.data(), i - } - }; + return response; }