diff --git a/ircd/m_room.cc b/ircd/m_room.cc index f4a42ed53..e160d563c 100644 --- a/ircd/m_room.cc +++ b/ircd/m_room.cc @@ -94,7 +94,7 @@ ircd::m::room::state::rebuild::rebuild(const room::id &room_id) }); ssize_t added(0); - history.for_each([&opts, &txn, &added] + history.for_each([&opts, &txn, &added, &room_id] (const auto &type, const auto &state_key, const auto &depth, const auto &event_idx) { const m::event::fetch &event @@ -105,6 +105,24 @@ ircd::m::room::state::rebuild::rebuild(const room::id &room_id) if(!event.valid) return true; + const auto &[pass, fail] + { + auth::check_present(event) + }; + + if(!pass) + { + log::dwarning + { + log, "%s fails for present state in %s :%s", + string_view{event.event_id}, + string_view{room_id}, + what(fail), + }; + + return true; + } + auto _opts(opts); _opts.op = db::op::SET; _opts.event_idx = event_idx; @@ -3028,18 +3046,34 @@ ircd::m::room::state::space::rebuild::rebuild(const room::id &room_id) ++state_count; const m::event &event{*it}; - const auto &[pass, reason] + const auto &[pass_static, reason_static] { - m::room::auth::check_static(event) + room::auth::check_static(event) }; - if(!pass) + if(!pass_static) log::dwarning { - log, "%s in %s erased from state space :%s", + log, "%s in %s erased from state space (static) :%s", string_view{event.event_id}, string_view{room_id}, - what(reason), + what(reason_static), + }; + + const auto &[pass_relative, reason_relative] + { + pass_static? + room::auth::check_relative(event): + room::auth::passfail{false, {}}, + }; + + if(pass_static && !pass_relative) + log::dwarning + { + log, "%s in %s erased from state space (relative) :%s", + string_view{event.event_id}, + string_view{room_id}, + what(reason_relative), }; dbs::write_opts opts; @@ -3048,8 +3082,8 @@ ircd::m::room::state::space::rebuild::rebuild(const room::id &room_id) opts.appendix.reset(); opts.appendix.set(dbs::appendix::ROOM_STATE_SPACE); - opts.op = pass? db::op::SET : db::op::DELETE; - state_deleted += !pass; + opts.op = pass_static && pass_relative? db::op::SET : db::op::DELETE; + state_deleted += opts.op == db::op::DELETE; dbs::write(txn, event, opts); } diff --git a/modules/m_room_auth.cc b/modules/m_room_auth.cc index 659c2f4a3..3db31bb8e 100644 --- a/modules/m_room_auth.cc +++ b/modules/m_room_auth.cc @@ -144,66 +144,69 @@ void IRCD_MODULE_EXPORT ircd::m::room::auth::check(const event &event) { - passfail pf; - auto &[pass, fail] {pf}; - - pf = check_static(event); - - if(!pass) try + const bool check_static { - assert(bool(fail)); - std::rethrow_exception(fail); - __builtin_unreachable(); - } - catch(const FAIL &e) + true + }; + + const bool check_relative { - throw FAIL + m::exists(event.event_id) + }; + + const bool check_present + { + true + }; + + if(check_static) + { + const auto &[pass, fail] { - "Fails against provided auth_events :%s", e.what() + auth::check_static(event) }; - } - if(!m::exists(room(at<"room_id"_>(event)))) - if(at<"type"_>(event) == "m.room.create") + if(pass) return; - pf = check_present(event); - - if(!pass) try - { - assert(bool(fail)); - std::rethrow_exception(fail); - __builtin_unreachable(); - } - catch(const FAIL &e) - { throw FAIL { - "Fails against present state of %s :%s", - json::get<"room_id"_>(event), - e.what() + "Fails against provided auth_events :%s", + what(fail), }; } - if(!m::exists(event.event_id)) - return; - - pf = check_relative(event); - - if(!pass) try - { - assert(bool(fail)); - std::rethrow_exception(fail); - __builtin_unreachable(); - } - catch(const FAIL &e) + if(check_relative) { + const auto &[pass, fail] + { + auth::check_relative(event) + }; + + if(pass) + return; + throw FAIL { - "Fails against state of %s relative to %s :%s", - json::get<"room_id"_>(event), - string_view{event.event_id}, - e.what() + "Fails against the state of the room at the event :%s", + what(fail), + }; + } + + if(check_present) + { + const auto &[pass, fail] + { + auth::check_present(event) + }; + + if(pass) + return; + + throw FAIL + { + "Fails against the present state of the room :%s", + what(fail), }; } } @@ -237,6 +240,18 @@ try { using json::at; + if(at<"type"_>(event) == "m.room.create") + return {true, {}}; + + const bool is_leave_event + { + at<"type"_>(event) == "m.room.member" && + (m::membership(event) == "leave" || m::membership(event) == "ban") + }; + + if(is_leave_event) + return {true, {}}; + const m::room room { at<"room_id"_>(event)