diff --git a/include/ircd/m/membership.h b/include/ircd/m/membership.h index 01bbcbdfa..d5da58f83 100644 --- a/include/ircd/m/membership.h +++ b/include/ircd/m/membership.h @@ -20,13 +20,16 @@ namespace ircd::m // is not checked here, only content.membership is sought. string_view membership(const mutable_buffer &out, const event::idx &); - // Query and compare membership string to argument string. Returns - // true on equal; false on not equal; false on not found. - bool membership(const event::idx &, const string_view &); - // Query and copy membership string to buffer; queries room state. (also room.h) string_view membership(const mutable_buffer &out, const room &, const id::user &); + // Query and compare membership string to argument string. Returns true on + // equal; false on not equal; false on not found. Note in addition to this + // we allow the user to pass an empty membership string which will test for + // non-membership as well and return true. + bool membership(const event::idx &, const string_view &); + // Query and compare membership string; queries room state. (also room.h) + // also see overload notes. bool membership(const room &, const id::user &, const string_view &); } diff --git a/ircd/m.cc b/ircd/m.cc index b97c92dba..b51581c2f 100644 --- a/ircd/m.cc +++ b/ircd/m.cc @@ -2363,16 +2363,28 @@ bool ircd::m::membership(const event::idx &event_idx, const string_view &membership) { - return m::query(std::nothrow, event_idx, "content", [&membership] - (const json::object &content) + bool ret; // not initialized unless fetched=true below + const auto closure { - const json::string &content_membership + [&membership, &ret](const json::object &content) { - content["membership"] - }; + const json::string &content_membership + { + content["membership"] + }; - return content_membership == membership; - }); + ret = membership && content_membership == membership; + } + }; + + const bool fetched + { + m::get(std::nothrow, event_idx, "content", closure) + }; + + // In addition to the intuitive behavior of this function, we allow the + // user to pass an empty membership string to test non-membership as well. + return (fetched && ret) || (!fetched && !membership); } ircd::string_view