diff --git a/include/ircd/m/user/keys.h b/include/ircd/m/user/keys.h index 2a4939359..77796c008 100644 --- a/include/ircd/m/user/keys.h +++ b/include/ircd/m/user/keys.h @@ -18,10 +18,17 @@ struct ircd::m::user::keys m::user::room user_room; - void attach_sigs(json::stack::object &, const json::object &) const; - bool attach_sigs(json::stack::object &, const event::idx &) const; + void attach_sigs(json::stack::object &, const json::object &, const user::id &) const; + bool attach_sigs(json::stack::object &, const event::idx &, const user::id &) const; + void append_keys(json::stack::object &, const json::object &, const user::id &) const; + bool append_keys(json::stack::object &, const event::idx &, const user::id &) const; public: + bool has_device(const m::id::device &) const; + bool has_cross_master() const; + bool has_cross_self() const; + bool has_cross_user() const; + void device(json::stack::object &, const string_view &device_id) const; void cross_master(json::stack::object &) const; void cross_self(json::stack::object &) const; @@ -31,3 +38,68 @@ struct ircd::m::user::keys :user_room{user} {} }; + +inline void +ircd::m::user::keys::cross_user(json::stack::object &out) +const +{ + const auto event_idx + { + user_room.get(std::nothrow, "ircd.cross_signing.user", "") + }; + + append_keys(out, event_idx, user_room.user.user_id); +} + +inline void +ircd::m::user::keys::cross_self(json::stack::object &out) +const +{ + const auto event_idx + { + user_room.get(std::nothrow, "ircd.cross_signing.self", "") + }; + + append_keys(out, event_idx, user_room.user.user_id); +} + +inline void +ircd::m::user::keys::cross_master(json::stack::object &out) +const +{ + const auto event_idx + { + user_room.get(std::nothrow, "ircd.cross_signing.master", "") + }; + + append_keys(out, event_idx, user_room.user.user_id); +} + +inline bool +ircd::m::user::keys::has_cross_user() +const +{ + return user_room.has("ircd.cross_signing.user", ""); +} + +inline bool +ircd::m::user::keys::has_cross_self() +const +{ + return user_room.has("ircd.cross_signing.self", ""); +} + +inline bool +ircd::m::user::keys::has_cross_master() +const +{ + return user_room.has("ircd.cross_signing.master", ""); +} + +inline bool +ircd::m::user::keys::has_device(const m::id::device &device_id) +const +{ + const m::user::devices devices{user_room.user}; + return devices.has(device_id, "keys"); +} diff --git a/matrix/user_keys.cc b/matrix/user_keys.cc index 067b07442..481b3fa25 100644 --- a/matrix/user_keys.cc +++ b/matrix/user_keys.cc @@ -9,131 +9,7 @@ // full license for this software is available in the LICENSE file. void -ircd::m::user::keys::cross_user(json::stack::object &out) -const -{ - const auto &user_id - { - user_room.user.user_id - }; - - const auto event_idx - { - user_room.get(std::nothrow, "ircd.cross_signing.user", "") - }; - - m::get(std::nothrow, event_idx, "content", [&out, &user_id] - (const json::object &content) - { - json::stack::member - { - out, user_id, content - }; - }); -} - -void -ircd::m::user::keys::cross_self(json::stack::object &out) -const -{ - const auto &user_id - { - user_room.user.user_id - }; - - const auto event_idx - { - user_room.get(std::nothrow, "ircd.cross_signing.self", "") - }; - - m::get(std::nothrow, event_idx, "content", [&out, &user_id] - (const json::object &content) - { - json::stack::member - { - out, user_id, content - }; - }); -} - -void -ircd::m::user::keys::cross_master(json::stack::object &out) -const -{ - const auto event_idx - { - user_room.get(std::nothrow, "ircd.cross_signing.master", "") - }; - - m::get(std::nothrow, event_idx, "content", [this, &out] - (const json::object &device_keys) - { - const auto &user_id - { - user_room.user.user_id - }; - - json::stack::object object - { - out, user_id - }; - - for(const auto &member : device_keys) - if(member.first != "signatures") - json::stack::member - { - object, member - }; - - json::stack::object sigs - { - object, "signatures" - }; - - json::stack::object user_sigs - { - sigs, user_id - }; - - attach_sigs(user_sigs, device_keys); - const json::object device_keys_keys - { - device_keys["keys"] - }; - - const m::room::state state - { - user_room - }; - - state.for_each("ircd.keys.signatures", [this, &user_sigs, &device_keys_keys] - (const string_view &, const string_view &state_key, const auto &event_idx) - { - for(const auto &[key_id_, key] : device_keys_keys) - { - const auto &key_id - { - split(key_id_, ':').second - }; - - const auto &[target, source] - { - unmake_sigs_state_key(state_key) - }; - - if(target != key_id) - continue; - - attach_sigs(user_sigs, event_idx); - } - - return true; - }); - }); -} - -void -ircd::m::user::keys::device(json::stack::object &object, +ircd::m::user::keys::device(json::stack::object &out, const string_view &device_id) const { @@ -142,7 +18,7 @@ const user_room.user }; - devices.get(std::nothrow, device_id, "keys", [this, &object, &device_id] + devices.get(std::nothrow, device_id, "keys", [this, &out, &device_id] (const auto &, const json::object &device_keys) { const auto &user_id @@ -154,12 +30,12 @@ const if(member.first != "signatures") json::stack::member { - object, member + out, member }; json::stack::object sigs { - object, "signatures" + out, "signatures" }; json::stack::object user_sigs @@ -167,13 +43,13 @@ const sigs, user_id }; - attach_sigs(user_sigs, device_keys); + attach_sigs(user_sigs, device_keys, user_id); const m::room::state state { user_room }; - state.for_each("ircd.keys.signatures", [this, &user_sigs, &device_id] + state.for_each("ircd.keys.signatures", [this, &user_sigs, &user_id, &device_id] (const string_view &, const string_view &state_key, const auto &event_idx) { const auto &[target, source] @@ -184,34 +60,103 @@ const if(target && target != device_id) return true; - attach_sigs(user_sigs, event_idx); + attach_sigs(user_sigs, event_idx, user_id); return true; }); }); } bool -ircd::m::user::keys::attach_sigs(json::stack::object &user_sigs, - const event::idx &event_idx) +ircd::m::user::keys::append_keys(json::stack::object &out, + const event::idx &event_idx, + const user::id &user_id) const { - return m::get(std::nothrow, event_idx, "content", [this, &user_sigs] + return m::get(std::nothrow, event_idx, "content", [this, &out, &user_id] + (const json::object &device_keys) + { + append_keys(out, device_keys, user_id); + }); +} + +void +ircd::m::user::keys::append_keys(json::stack::object &out, + const json::object &device_keys, + const user::id &user_id) +const +{ + for(const auto &member : device_keys) + if(member.first != "signatures") + json::stack::member + { + out, member + }; + + json::stack::object sigs + { + out, "signatures" + }; + + json::stack::object user_sigs + { + sigs, user_id + }; + + attach_sigs(user_sigs, device_keys, user_id); + const json::object device_keys_keys + { + device_keys["keys"] + }; + + const m::room::state state + { + user_room + }; + + state.for_each("ircd.keys.signatures", [this, &user_sigs, &user_id, &device_keys_keys] + (const string_view &, const string_view &state_key, const auto &event_idx) + { + for(const auto &[key_id_, key] : device_keys_keys) + { + const auto &key_id + { + split(key_id_, ':').second + }; + + const auto &[target, source] + { + unmake_sigs_state_key(state_key) + }; + + if(target != key_id) + continue; + + attach_sigs(user_sigs, event_idx, user_id); + } + + return true; + }); +} + +bool +ircd::m::user::keys::attach_sigs(json::stack::object &user_sigs, + const event::idx &event_idx, + const user::id &user_id) +const +{ + return m::get(std::nothrow, event_idx, "content", [this, &user_sigs, &user_id] (const json::object &device_sigs) { - attach_sigs(user_sigs, device_sigs); + attach_sigs(user_sigs, device_sigs, user_id); }); } void ircd::m::user::keys::attach_sigs(json::stack::object &user_sigs, - const json::object &device_sigs) + const json::object &device_sigs, + const user::id &user_id) const { - const auto &user_id - { - user_room.user.user_id - }; - const json::object device_sigs_sigs { device_sigs["signatures"] diff --git a/modules/federation/user_keys_query.cc b/modules/federation/user_keys_query.cc index 544e47414..0fc86e5f4 100644 --- a/modules/federation/user_keys_query.cc +++ b/modules/federation/user_keys_query.cc @@ -160,7 +160,15 @@ _query_master_keys(client &client, user_id }; - keys.cross_master(response_keys); + if(!keys.has_cross_master()) + continue; + + json::stack::object object + { + response_keys, user_id + }; + + keys.cross_master(object); } } @@ -191,7 +199,15 @@ _query_self_keys(client &client, user_id }; - keys.cross_self(response_keys); + if(!keys.has_cross_self()) + continue; + + json::stack::object object + { + response_keys, user_id + }; + + keys.cross_self(object); } } @@ -222,7 +238,15 @@ _query_user_keys(client &client, user_id }; - keys.cross_user(response_keys); + if(!keys.has_cross_user()) + continue; + + json::stack::object object + { + response_keys, user_id + }; + + keys.cross_user(object); } } @@ -233,7 +257,12 @@ _query_user_device(client &client, const string_view &device_id, json::stack::object &out) { - if(!devices.has(device_id, "keys")) + const m::user::keys keys + { + devices.user + }; + + if(!keys.has_device(device_id)) return; json::stack::object object @@ -241,11 +270,6 @@ _query_user_device(client &client, out, device_id }; - const m::user::keys keys - { - devices.user - }; - keys.device(object, device_id); devices.get(std::nothrow, device_id, "display_name", [&device_id, &object]