diff --git a/ircd/m.cc b/ircd/m.cc index b3c3184de..a237f7b01 100644 --- a/ircd/m.cc +++ b/ircd/m.cc @@ -207,6 +207,7 @@ ircd::m::module_names "m_rooms_summary", "m_users", "m_user", + "m_user_filter", "m_user_rooms", "m_user_mitsein", "m_user_events", @@ -2619,122 +2620,6 @@ ircd::m::user::room::room(const m::user &user, }; } -// -// user::filter -// - -ircd::string_view -ircd::m::user::filter::set(const mutable_buffer &buf, - const json::object &val) -const -{ - return set(buf, user, val); -} - -std::string -ircd::m::user::filter::get(const string_view &id) -const -{ - std::string ret; - get(std::nothrow, id, [&ret] - (const string_view &id, const json::object &val) - { - ret = val; - }); - - return ret; -} - -ircd::json::object -ircd::m::user::filter::get(const mutable_buffer &out, - const string_view &id) -const -{ - json::object ret; - get(std::nothrow, id, [&out, &ret] - (const string_view &id, const json::object &val) - { - ret = string_view { data(out), copy(out, val) }; - }); - - return ret; -} - -void -ircd::m::user::filter::get(const string_view &id, - const closure &closure) -const -{ - if(!get(std::nothrow, user, id, closure)) - throw m::NOT_FOUND - { - "filter id '%s' for user %s not found", - id, - string_view{user.user_id} - }; -} - -bool -ircd::m::user::filter::get(std::nothrow_t, - const string_view &id, - const closure &closure) -const -{ - return get(std::nothrow, user, id, closure); -} - -bool -ircd::m::user::filter::for_each(const closure_bool &closure) -const -{ - return for_each(user, closure); -} - -ircd::string_view -ircd::m::user::filter::set(const mutable_buffer &buf, - const m::user &u, - const json::object &v) -{ - using prototype = string_view (const mutable_buffer &, const m::user &, const json::object &); - - static mods::import function - { - "client_user", "ircd::m::user::filter::set" - }; - - return function(buf, u, v); -} - -bool -ircd::m::user::filter::get(std::nothrow_t, - const m::user &u, - const string_view &id, - 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::filter::get" - }; - - return function(std::nothrow, u, id, c); -} - -bool -ircd::m::user::filter::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::filter::for_each" - }; - - return function(u, c); -} - /////////////////////////////////////////////////////////////////////////////// // // m/txn.h diff --git a/modules/Makefile.am b/modules/Makefile.am index 90e2683d0..b29aebbc4 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -104,6 +104,7 @@ m_event_append_la_SOURCES = m_event_append.cc m_user_la_SOURCES = m_user.cc m_user_events_la_SOURCES = m_user_events.cc m_user_rooms_la_SOURCES = m_user_rooms.cc +m_user_filter_la_SOURCES = m_user_filter.cc m_user_mitsein_la_SOURCES = m_user_mitsein.cc m_user_highlight_la_SOURCES = m_user_highlight.cc m_user_profile_la_SOURCES = m_user_profile.cc @@ -150,6 +151,7 @@ m_module_LTLIBRARIES = \ m_user.la \ m_user_events.la \ m_user_rooms.la \ + m_user_filter.la \ m_user_mitsein.la \ m_user_highlight.la \ m_user_profile.la \ diff --git a/modules/client/user/filter.cc b/modules/client/user/filter.cc index d1233767f..65e571d49 100644 --- a/modules/client/user/filter.cc +++ b/modules/client/user/filter.cc @@ -128,107 +128,3 @@ post__filter(client &client, } }; } - -string_view -IRCD_MODULE_EXPORT -ircd::m::user::filter::set(const mutable_buffer &idbuf, - const m::user &user, - const json::object &filter) -{ - const user::room user_room - { - user - }; - - const sha256::buf hash - { - sha256{filter} - }; - - const string_view filter_id - { - b64tob64url(idbuf, b64encode_unpadded(idbuf, hash)) - }; - - //TODO: ABA - if(user_room.has("ircd.filter", filter_id)) - return {}; - - //TODO: ABA - send(user_room, user.user_id, "ircd.filter", filter_id, filter); - return filter_id; -} - -bool -IRCD_MODULE_EXPORT -ircd::m::user::filter::get(std::nothrow_t, - const m::user &user, - const string_view &filter_id, - const closure &closure) -{ - static const event::fetch::opts fopts - { - event::keys::include {"content"} - }; - - const user::room user_room - { - user, nullptr, &fopts - }; - - return user_room.get(std::nothrow, "ircd.filter", filter_id, [&filter_id, &closure] - (const m::event &event) - { - const json::object &content - { - at<"content"_>(event) - }; - - closure(filter_id, content); - }); -} - -bool -IRCD_MODULE_EXPORT -ircd::m::user::filter::for_each(const m::user &user, - const closure_bool &closure) -{ - const user::room user_room - { - user - }; - - const room::state state - { - user_room - }; - - return state.for_each("ircd.filter", event::closure_idx_bool{[&closure] - (const m::event::idx &event_idx) - { - static const event::fetch::opts fopts - { - event::keys::include {"state_key", "content"} - }; - - const event::fetch event - { - event_idx, std::nothrow, fopts - }; - - if(!event.valid) - return true; - - const auto &filter_id - { - at<"state_key"_>(event) - }; - - const json::object &content - { - at<"content"_>(event) - }; - - return closure(filter_id, content); - }}); -} diff --git a/modules/m_user_filter.cc b/modules/m_user_filter.cc new file mode 100644 index 000000000..897bd5f21 --- /dev/null +++ b/modules/m_user_filter.cc @@ -0,0 +1,192 @@ +// Matrix Construct +// +// Copyright (C) Matrix Construct Developers, Authors & Contributors +// Copyright (C) 2016-2019 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. + +ircd::mapi::header +IRCD_MODULE +{ + "Matrix user filter." +}; + +ircd::string_view +IRCD_MODULE_EXPORT +ircd::m::user::filter::set(const mutable_buffer &buf, + const json::object &val) +const +{ + return set(buf, user, val); +} + +ircd::string_view +IRCD_MODULE_EXPORT +ircd::m::user::filter::set(const mutable_buffer &idbuf, + const m::user &user, + const json::object &filter) +{ + const user::room user_room + { + user + }; + + const sha256::buf hash + { + sha256{filter} + }; + + const string_view filter_id + { + b64tob64url(idbuf, b64encode_unpadded(idbuf, hash)) + }; + + //TODO: ABA + if(user_room.has("ircd.filter", filter_id)) + return {}; + + //TODO: ABA + send(user_room, user.user_id, "ircd.filter", filter_id, filter); + return filter_id; +} + +std::string +IRCD_MODULE_EXPORT +ircd::m::user::filter::get(const string_view &id) +const +{ + std::string ret; + get(std::nothrow, id, [&ret] + (const string_view &id, const json::object &val) + { + ret = val; + }); + + return ret; +} + +ircd::json::object +IRCD_MODULE_EXPORT +ircd::m::user::filter::get(const mutable_buffer &out, + const string_view &id) +const +{ + json::object ret; + get(std::nothrow, id, [&out, &ret] + (const string_view &id, const json::object &val) + { + ret = string_view { data(out), copy(out, val) }; + }); + + return ret; +} + +void +IRCD_MODULE_EXPORT +ircd::m::user::filter::get(const string_view &id, + const closure &closure) +const +{ + if(!get(std::nothrow, user, id, closure)) + throw m::NOT_FOUND + { + "filter id '%s' for user %s not found", + id, + string_view{user.user_id} + }; +} + +bool +IRCD_MODULE_EXPORT +ircd::m::user::filter::get(std::nothrow_t, + const string_view &id, + const closure &closure) +const +{ + return get(std::nothrow, user, id, closure); +} + +bool +IRCD_MODULE_EXPORT +ircd::m::user::filter::for_each(const closure_bool &closure) +const +{ + return for_each(user, closure); +} + +bool +IRCD_MODULE_EXPORT +ircd::m::user::filter::get(std::nothrow_t, + const m::user &user, + const string_view &filter_id, + const closure &closure) +{ + static const event::fetch::opts fopts + { + event::keys::include {"content"} + }; + + const user::room user_room + { + user, nullptr, &fopts + }; + + return user_room.get(std::nothrow, "ircd.filter", filter_id, [&filter_id, &closure] + (const m::event &event) + { + const json::object &content + { + at<"content"_>(event) + }; + + closure(filter_id, content); + }); +} + +bool +IRCD_MODULE_EXPORT +ircd::m::user::filter::for_each(const m::user &user, + const closure_bool &closure) +{ + const user::room user_room + { + user + }; + + const room::state state + { + user_room + }; + + return state.for_each("ircd.filter", event::closure_idx_bool{[&closure] + (const m::event::idx &event_idx) + { + static const event::fetch::opts fopts + { + event::keys::include {"state_key", "content"} + }; + + const event::fetch event + { + event_idx, std::nothrow, fopts + }; + + if(!event.valid) + return true; + + const auto &filter_id + { + at<"state_key"_>(event) + }; + + const json::object &content + { + at<"content"_>(event) + }; + + return closure(filter_id, content); + }}); +}