diff --git a/include/ircd/m/user.h b/include/ircd/m/user.h index 084fea3e2..bfd33f4c7 100644 --- a/include/ircd/m/user.h +++ b/include/ircd/m/user.h @@ -28,6 +28,9 @@ struct ircd::m::user struct mitsein; struct events; struct profile; + struct account_data; + struct room_account_data; + using id = m::id::user; using closure = std::function; using closure_bool = std::function; @@ -48,17 +51,6 @@ struct ircd::m::user bool is_password(const string_view &password) const noexcept; event::id::buf password(const string_view &password); - using account_data_closure = std::function; - static string_view _account_data_type(const mutable_buffer &out, const m::room::id &); - void account_data(const string_view &type, const account_data_closure &) const; - void account_data(const m::room &, const string_view &type, const account_data_closure &) const; - bool account_data(std::nothrow_t, const string_view &type, const account_data_closure &) const; - bool account_data(std::nothrow_t, const m::room &, const string_view &type, const account_data_closure &) const; - json::object account_data(const mutable_buffer &out, const string_view &type) const; //nothrow - json::object account_data(const mutable_buffer &out, const m::room &, const string_view &type) const; //nothrow - event::id::buf account_data(const m::user &sender, const string_view &type, const json::object &value); - event::id::buf account_data(const m::room &, const m::user &sender, const string_view &type, const json::object &value); - using filter_closure = std::function; bool filter(std::nothrow_t, const string_view &filter_id, const filter_closure &) const; void filter(const string_view &filter_id, const filter_closure &) const; @@ -207,6 +199,55 @@ struct ircd::m::user::profile {} }; +struct ircd::m::user::account_data +{ + using closure_bool = std::function; + using closure = std::function; + + m::user user; + + static bool for_each(const m::user &, const closure_bool &); + static bool get(std::nothrow_t, const m::user &, const string_view &type, const closure &); + static event::id::buf set(const m::user &, const string_view &type, const json::object &value); + + public: + bool for_each(const closure_bool &) const; + bool get(std::nothrow_t, const string_view &type, const closure &) const; + void get(const string_view &type, const closure &) const; + json::object get(const mutable_buffer &out, const string_view &type) const; //nothrow + event::id::buf set(const string_view &type, const json::object &value) const; + + account_data(const m::user &user) + :user{user} + {} +}; + +struct ircd::m::user::room_account_data +{ + using closure_bool = std::function; + using closure = std::function; + + m::user user; + m::room room; + + static string_view _type(const mutable_buffer &out, const m::room::id &); + static bool for_each(const m::user &, const m::room &, const closure_bool &); + static bool get(std::nothrow_t, const m::user &, const m::room &, const string_view &type, const closure &); + static event::id::buf set(const m::user &, const m::room &, const string_view &type, const json::object &value); + + public: + bool for_each(const closure_bool &) const; + bool get(std::nothrow_t, const string_view &type, const closure &) const; + void get(const string_view &type, const closure &) const; + json::object get(const mutable_buffer &out, const string_view &type) const; //nothrow + event::id::buf set(const string_view &type, const json::object &value) const; + + room_account_data(const m::user &user, const m::room &room) + :user{user} + ,room{room} + {} +}; + inline ircd::m::user::operator const ircd::m::user::id &() const diff --git a/ircd/m.cc b/ircd/m.cc index 99d15f6e8..48ec535ef 100644 --- a/ircd/m.cc +++ b/ircd/m.cc @@ -2531,142 +2531,6 @@ const return function(std::nothrow, *this, filter_id, closure); } -ircd::m::event::id::buf -ircd::m::user::account_data(const m::room &room, - const m::user &sender, - const string_view &type, - const json::object &val) -{ - using prototype = event::id::buf (const m::user &, const m::room &, const m::user &, const string_view &, const json::object &); - - static mods::import function - { - "client_user", "room_account_data_set" - }; - - return function(*this, room, sender, type, val); -} - -ircd::m::event::id::buf -ircd::m::user::account_data(const m::user &sender, - const string_view &type, - const json::object &val) -{ - using prototype = event::id::buf (const m::user &, const m::user &, const string_view &, const json::object &); - - static mods::import function - { - "client_user", "account_data_set" - }; - - return function(*this, sender, type, val); -} - -ircd::json::object -ircd::m::user::account_data(const mutable_buffer &out, - const m::room &room, - const string_view &type) -const -{ - json::object ret; - account_data(std::nothrow, room, type, [&out, &ret] - (const json::object &val) - { - ret = string_view { data(out), copy(out, val) }; - }); - - return ret; -} - -ircd::json::object -ircd::m::user::account_data(const mutable_buffer &out, - const string_view &type) -const -{ - json::object ret; - account_data(std::nothrow, type, [&out, &ret] - (const json::object &val) - { - ret = string_view { data(out), copy(out, val) }; - }); - - return ret; -} - -bool -ircd::m::user::account_data(std::nothrow_t, - const m::room &room, - const string_view &type, - const account_data_closure &closure) -const try -{ - account_data(room, type, closure); - return true; -} -catch(const std::exception &e) -{ - return false; -} - -bool -ircd::m::user::account_data(std::nothrow_t, - const string_view &type, - const account_data_closure &closure) -const try -{ - account_data(type, closure); - return true; -} -catch(const std::exception &e) -{ - return false; -} - -void -ircd::m::user::account_data(const m::room &room, - const string_view &type, - const account_data_closure &closure) -const -{ - using prototype = void (const m::user &, const m::room &, const string_view &, const account_data_closure &); - - static mods::import function - { - "client_user", "room_account_data_get" - }; - - return function(*this, room, type, closure); -} - -void -ircd::m::user::account_data(const string_view &type, - const account_data_closure &closure) -const -{ - using prototype = void (const m::user &, const string_view &, const account_data_closure &); - - static mods::import function - { - "client_user", "account_data_get" - }; - - return function(*this, type, closure); -} - -ircd::string_view -ircd::m::user::_account_data_type(const mutable_buffer &out, - const m::room::id &room_id) -{ - using prototype = string_view (const mutable_buffer &, const m::room::id &); - - static mods::import function - { - "client_user", "room_account_data_type" - }; - - return function(out, room_id); -} - ircd::m::event::id::buf ircd::m::user::password(const string_view &password) { @@ -3262,12 +3126,234 @@ ircd::m::user::profile::for_each(const m::user &u, static mods::import function { - "m_user", "ircd::m::user::profile::for_each" + "client_profile", "ircd::m::user::profile::for_each" }; return function(u, c); } +// +// user::account_data +// + +ircd::m::event::id::buf +ircd::m::user::account_data::set(const string_view &type, + const json::object &val) +const +{ + return set(user, type, val); +} + +ircd::json::object +ircd::m::user::account_data::get(const mutable_buffer &out, + const string_view &type) +const +{ + json::object ret; + get(std::nothrow, type, [&out, &ret] + (const string_view &type, const json::object &val) + { + ret = string_view { data(out), copy(out, val) }; + }); + + return ret; +} + +void +ircd::m::user::account_data::get(const string_view &type, + const closure &closure) +const +{ + if(!get(std::nothrow, user, type, closure)) + throw m::NOT_FOUND + { + "account data type '%s' for user %s not found", + type, + string_view{user.user_id} + }; +} + +bool +ircd::m::user::account_data::get(std::nothrow_t, + const string_view &type, + const closure &closure) +const +{ + return get(std::nothrow, user, type, closure); +} + +bool +ircd::m::user::account_data::for_each(const closure_bool &closure) +const +{ + return for_each(user, closure); +} + +ircd::m::event::id::buf +ircd::m::user::account_data::set(const m::user &u, + const string_view &t, + const json::object &v) +{ + using prototype = event::id::buf (const m::user &, const string_view &, const json::object &); + + static mods::import function + { + "client_user", "ircd::m::user::account_data::set" + }; + + return function(u, t, v); +} + +bool +ircd::m::user::account_data::get(std::nothrow_t, + const m::user &u, + const string_view &t, + const closure &c) +{ + using prototype = bool (std::nothrow_t, const m::user &, const string_view &, const closure &); + + static mods::import function + { + "client_user", "ircd::m::user::account_data::get" + }; + + return function(std::nothrow, u, t, c); +} + +bool +ircd::m::user::account_data::for_each(const m::user &u, + const closure_bool &c) +{ + using prototype = bool (const m::user &, const closure_bool &); + + static mods::import function + { + "client_user", "ircd::m::user::account_data::for_each" + }; + + return function(u, c); +} + +// +// user::room_account_data +// + +ircd::m::event::id::buf +ircd::m::user::room_account_data::set(const string_view &type, + const json::object &val) +const +{ + return set(user, room, type, val); +} + +ircd::json::object +ircd::m::user::room_account_data::get(const mutable_buffer &out, + const string_view &type) +const +{ + json::object ret; + get(std::nothrow, type, [&out, &ret] + (const string_view &type, const json::object &val) + { + ret = string_view { data(out), copy(out, val) }; + }); + + return ret; +} + +void +ircd::m::user::room_account_data::get(const string_view &type, + const closure &closure) +const +{ + if(!get(std::nothrow, user, room, type, closure)) + throw m::NOT_FOUND + { + "account data type '%s' for user %s in room %s not found", + type, + string_view{user.user_id}, + string_view{room.room_id} + }; +} + +bool +ircd::m::user::room_account_data::get(std::nothrow_t, + const string_view &type, + const closure &closure) +const +{ + return get(std::nothrow, user, room, type, closure); +} + +bool +ircd::m::user::room_account_data::for_each(const closure_bool &closure) +const +{ + return for_each(user, room, closure); +} + +ircd::m::event::id::buf +ircd::m::user::room_account_data::set(const m::user &u, + const m::room &r, + const string_view &t, + const json::object &v) +{ + using prototype = event::id::buf (const m::user &, const m::room &, const string_view &, const json::object &); + + static mods::import function + { + "client_user", "ircd::m::user::room_account_data::set" + }; + + return function(u, r, t, v); +} + +bool +ircd::m::user::room_account_data::get(std::nothrow_t, + const m::user &u, + const m::room &r, + const string_view &t, + const closure &c) +{ + using prototype = bool (std::nothrow_t, const m::user &, const m::room &, const string_view &, const closure &); + + static mods::import function + { + "client_user", "ircd::m::user::room_account_data::get" + }; + + return function(std::nothrow, u, r, t, c); +} + +bool +ircd::m::user::room_account_data::for_each(const m::user &u, + const m::room &r, + const closure_bool &c) +{ + using prototype = bool (const m::user &, const m::room &, const closure_bool &); + + static mods::import function + { + "client_user", "ircd::m::user::room_account_data::for_each" + }; + + return function(u, r, c); +} + +ircd::string_view +ircd::m::user::room_account_data::_type(const mutable_buffer &out, + const m::room::id &room_id) +{ + using prototype = string_view (const mutable_buffer &, const m::room::id &); + + static mods::import function + { + "client_user", "ircd::m::user::room_account_data::_type" + }; + + return function(out, room_id); +} + /////////////////////////////////////////////////////////////////////////////// // // m/room.h diff --git a/modules/client/sync/account_data.cc b/modules/client/sync/account_data.cc index b74ad69c8..88b9445bb 100644 --- a/modules/client/sync/account_data.cc +++ b/modules/client/sync/account_data.cc @@ -50,9 +50,14 @@ ircd::m::sync::account_data_polylog(data &data) data.out, "events" }; - const m::room::state &state + static const m::event::fetch::opts fopts { - data.user_state + m::event::keys::include {"event_id", "state_key", "content"} + }; + + const m::room::state state + { + data.user_room, &fopts }; state.for_each("ircd.account_data", [&data, &array] diff --git a/modules/client/sync/rooms/account_data.cc b/modules/client/sync/rooms/account_data.cc index 61571d0ef..0ec2bdf21 100644 --- a/modules/client/sync/rooms/account_data.cc +++ b/modules/client/sync/rooms/account_data.cc @@ -49,16 +49,21 @@ ircd::m::sync::room_account_data_polylog_events(data &data) data.out, "events" }; - const m::room::state state - { - data.user_room - }; - assert(data.room); char typebuf[288]; //TODO: room_account_data_typebuf_size const auto type { - m::user::_account_data_type(typebuf, data.room->room_id) + m::user::room_account_data::_type(typebuf, data.room->room_id) + }; + + static const m::event::fetch::opts &fopts + { + m::event::keys::include {"event_id", "state_key", "content"} + }; + + const m::room::state state + { + data.user_room, &fopts }; state.for_each(type, [&data] diff --git a/modules/client/user/account_data.cc b/modules/client/user/account_data.cc index 389144538..3cd2b3821 100644 --- a/modules/client/user/account_data.cc +++ b/modules/client/user/account_data.cc @@ -12,17 +12,6 @@ using namespace ircd; -extern "C" void -account_data_get(const m::user &user, - const string_view &type, - const m::user::account_data_closure &closure); - -extern "C" m::event::id::buf -account_data_set(const m::user &user, - const m::user &sender, - const string_view &type, - const json::object &value); - resource::response put__account_data(client &client, const resource::request &request, @@ -47,7 +36,7 @@ put__account_data(client &client, const auto event_id { - account_data_set(user, user, type, value) + m::user::account_data{user}.set(type, value) }; return resource::response @@ -73,8 +62,8 @@ get__account_data(client &client, url::decode(typebuf, request.parv[2]) }; - account_data_get(user, type, [&client] - (const json::object &value) + m::user::account_data{user}.get(type, [&client] + (const string_view &type, const json::object &value) { resource::response { @@ -85,48 +74,70 @@ get__account_data(client &client, return {}; // responded from closure } -void -account_data_get(const m::user &user, - const string_view &type, - const m::user::account_data_closure &closure) -try +ircd::m::event::id::buf +IRCD_MODULE_EXPORT +ircd::m::user::account_data::set(const m::user &user, + const string_view &type, + const json::object &value) { const m::user::room user_room { user }; - user_room.get("ircd.account_data", type, [&closure] - (const m::event &event) - { - const json::object &value - { - at<"content"_>(event) - }; + return send(user_room, user, "ircd.account_data", type, value); +} - closure(value); +bool +IRCD_MODULE_EXPORT +ircd::m::user::account_data::get(std::nothrow_t, + const m::user &user, + const string_view &type, + const closure &closure) +{ + const user::room user_room{user}; + const room::state state{user_room}; + const event::idx &event_idx + { + state.get(std::nothrow, "ircd.account_data", type) + }; + + return event_idx && m::get(std::nothrow, event_idx, "content", [&type, &closure] + (const json::object &content) + { + closure(type, content); }); } -catch(const m::NOT_FOUND &e) -{ - throw m::NOT_FOUND - { - "Nothing about '%s' account_data for '%s'", - type, - string_view{user.user_id} - }; -} -m::event::id::buf -account_data_set(const m::user &user, - const m::user &sender, - const string_view &type, - const json::object &value) +bool +IRCD_MODULE_EXPORT +ircd::m::user::account_data::for_each(const m::user &user, + const closure_bool &closure) { - const m::user::room user_room + static const event::fetch::opts fopts { - user + event::keys::include {"state_key", "content"} }; - return send(user_room, sender, "ircd.account_data", type, value); + const user::room user_room{user}; + const room::state state + { + user_room, &fopts + }; + + return state.for_each("ircd.account_data", event::closure_bool{[&closure] + (const m::event &event) + { + const auto &key + { + at<"state_key"_>(event) + }; + + const auto &val + { + json::get<"content"_>(event) + }; + + return closure(key, val); + }}); } diff --git a/modules/client/user/rooms.cc b/modules/client/user/rooms.cc index 1307a1b95..eb3456102 100644 --- a/modules/client/user/rooms.cc +++ b/modules/client/user/rooms.cc @@ -12,19 +12,6 @@ using namespace ircd; -extern "C" void -room_account_data_get(const m::user &user, - const m::room &room, - const string_view &type, - const m::user::account_data_closure &closure); - -extern "C" m::event::id::buf -room_account_data_set(const m::user &user, - const m::room &room, - const m::user &sender, - const string_view &type, - const json::object &value); - static resource::response put__account_data(client &client, const resource::request &request, @@ -134,7 +121,7 @@ put__account_data(client &client, const auto event_id { - room_account_data_set(user, room, user, type, value) + m::user::room_account_data{user, room}.set(type, value) }; return resource::response @@ -162,8 +149,8 @@ get__account_data(client &client, url::decode(typebuf, request.parv[4]) }; - room_account_data_get(user, room, type, [&client] - (const json::object &value) + m::user::room_account_data{user, room}.get(type, [&client] + (const string_view &type, const json::object &value) { resource::response { @@ -186,9 +173,99 @@ room_account_data_typebuf_size m::room::id::MAX_SIZE + size(room_account_data_type_prefix) }; -extern "C" string_view -room_account_data_type(const mutable_buffer &out, - const m::room::id &room_id) +m::event::id::buf +IRCD_MODULE_EXPORT +ircd::m::user::room_account_data::set(const m::user &user, + const m::room &room, + const string_view &user_type, + const json::object &value) +{ + char typebuf[room_account_data_typebuf_size]; + const string_view type + { + _type(typebuf, room.room_id) + }; + + const m::user::room user_room + { + user + }; + + return send(user_room, user, type, user_type, value); +} + +bool +IRCD_MODULE_EXPORT +ircd::m::user::room_account_data::get(std::nothrow_t, + const m::user &user, + const m::room &room, + const string_view &user_type, + const closure &closure) +{ + char typebuf[room_account_data_typebuf_size]; + const string_view type + { + _type(typebuf, room.room_id) + }; + + const user::room user_room{user}; + const room::state state{user_room}; + const event::idx event_idx + { + state.get(std::nothrow, type, user_type) + }; + + return event_idx && m::get(std::nothrow, event_idx, "content", [&user_type, &closure] + (const json::object &content) + { + closure(user_type, content); + }); +} + +bool +IRCD_MODULE_EXPORT +ircd::m::user::room_account_data::for_each(const m::user &user, + const m::room &room, + const closure_bool &closure) +{ + char typebuf[room_account_data_typebuf_size]; + const string_view type + { + _type(typebuf, room.room_id) + }; + + static const event::fetch::opts fopts + { + event::keys::include {"state_key", "content"} + }; + + const user::room user_room{user}; + const room::state state + { + user_room, &fopts + }; + + return state.for_each(type, event::closure_bool{[&closure] + (const m::event &event) + { + const auto &user_type + { + at<"state_key"_>(event) + }; + + const auto &content + { + json::get<"content"_>(event) + }; + + return closure(user_type, content); + }}); +} + +ircd::string_view +IRCD_MODULE_EXPORT +ircd::m::user::room_account_data::_type(const mutable_buffer &out, + const m::room::id &room_id) { assert(size(out) >= room_account_data_typebuf_size); @@ -197,64 +274,3 @@ room_account_data_type(const mutable_buffer &out, ret = strlcat(out, room_id); return ret; } - -void -room_account_data_get(const m::user &user, - const m::room &room, - const string_view &user_type, - const m::user::account_data_closure &closure) -try -{ - char typebuf[room_account_data_typebuf_size]; - const string_view type - { - room_account_data_type(typebuf, room.room_id) - }; - - const m::user::room user_room - { - user - }; - - user_room.get(type, user_type, [&closure] - (const m::event &event) - { - const json::object &value - { - at<"content"_>(event) - }; - - closure(value); - }); -} -catch(const m::NOT_FOUND &e) -{ - throw m::NOT_FOUND - { - "Nothing about '%s' account_data for %s in room %s", - user_type, - string_view{user.user_id}, - string_view{room.room_id} - }; -} - -m::event::id::buf -room_account_data_set(const m::user &user, - const m::room &room, - const m::user &sender, - const string_view &user_type, - const json::object &value) -{ - char typebuf[room_account_data_typebuf_size]; - const string_view type - { - room_account_data_type(typebuf, room.room_id) - }; - - const m::user::room user_room - { - user - }; - - return send(user_room, sender, type, user_type, value); -}