diff --git a/include/ircd/m/event/auth.h b/include/ircd/m/event/auth.h index a8596c14b..9ba3e6ba1 100644 --- a/include/ircd/m/event/auth.h +++ b/include/ircd/m/event/auth.h @@ -18,6 +18,7 @@ namespace ircd::m struct ircd::m::event::auth { + struct chain; event::idx idx; @@ -40,10 +41,17 @@ struct ircd::m::event::auth } }; -inline -ircd::m::event::auth::auth(const event::idx &idx) -noexcept -:idx{idx} +struct ircd::m::event::auth::chain { - assert(idx); -} + event::auth auth; + + public: + using closure = std::function; + + bool for_each(const string_view &type, const closure &) const; + bool for_each(const closure &) const; + + chain(const event::idx &idx) + :auth{idx} + {} +}; diff --git a/ircd/m_event.cc b/ircd/m_event.cc index b94535ff4..cdb13680b 100644 --- a/ircd/m_event.cc +++ b/ircd/m_event.cc @@ -1125,6 +1125,32 @@ ircd::m::is_power_event(const m::event &event) return false; } +// +// event::auth::chain +// + +bool +ircd::m::event::auth::chain::for_each(const closure &closure) +const +{ + return for_each(string_view{}, closure); +} + +bool +ircd::m::event::auth::chain::for_each(const string_view &type, + const closure &c) +const +{ + using prototype = bool (event::auth, const string_view &, const closure &); + + static mods::import auth_chain_for_each + { + "m_event", "auth_chain_for_each" + }; + + return auth_chain_for_each(auth, type, c); +} + // // event::auth // diff --git a/modules/console.cc b/modules/console.cc index 7decca92b..86c1ed874 100644 --- a/modules/console.cc +++ b/modules/console.cc @@ -5917,6 +5917,31 @@ console_cmd__event__auth(opt &out, const string_view &line) return true; } +bool +console_cmd__event__auth__chain(opt &out, const string_view &line) +{ + const params param{line, " ", + { + "event_id", "type" + }}; + + const m::event::id &event_id + { + param.at("event_id") + }; + + const string_view type + { + param.at("type", ""_sv) + }; + + const m::event::auth::chain auth + { + index(event_id) + }; + + auth.for_each(type, [&out] + (const m::event::idx &idx) { const m::event::fetch event { diff --git a/modules/m_event.cc b/modules/m_event.cc index 2ccbe4e6c..f97845db9 100644 --- a/modules/m_event.cc +++ b/modules/m_event.cc @@ -682,3 +682,35 @@ event_auth__rebuild() txn(); } + +extern "C" bool +auth_chain_for_each(event::auth auth, + const string_view &type, + const event::auth::chain::closure &closure) +{ + event::idx next(0); + uint64_t depth[2] {uint64_t(-1), 0}; do + { + auth.for_each(type, [&depth, &next] + (const event::idx &event_idx) + { + if(!m::get(event_idx, "depth", depth[1])) + return true; + + if(depth[1] >= depth[0]) + return true; + + depth[0] = depth[1]; + next = event_idx; + return true; + }); + + if(!closure(next)) + return false; + + auth.idx = next; + next = 0; + } + while(auth.idx); + return true; +}