construct/matrix/membership.cc

158 lines
3.4 KiB
C++

// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
//
// 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.
decltype(ircd::m::membership_positive)
ircd::m::membership_positive
{
"join"_sv,
"invite"_sv,
};
decltype(ircd::m::membership_negative)
ircd::m::membership_negative
{
"leave"_sv,
"ban"_sv,
"knock"_sv,
""_sv,
};
bool
ircd::m::membership(const room &room,
const user::id &user_id,
const vector_view<const string_view> &membership)
{
const auto event_idx
{
room.get(std::nothrow, "m.room.member", user_id)
};
return m::membership(event_idx, membership);
}
bool
ircd::m::membership(const event::idx &event_idx,
const vector_view<const string_view> &membership)
{
bool ret;
const auto closure
{
[&membership, &ret](const json::object &content)
{
const json::string &content_membership
{
content["membership"]
};
const auto it
{
std::find(begin(membership), end(membership), content_membership)
};
ret = content_membership && it != end(membership);
}
};
// If the query was successful a membership state exists (even if the
// string found was illegally empty) thus we must return the value of ret.
if(m::get(std::nothrow, event_idx, "content", closure))
return ret;
// If the user included an empty string in the vector, they want us to
// return true for non-membership (i.e a failed query).
static const auto &empty{[](auto&& s) { return !s; }};
if(std::any_of(begin(membership), end(membership), empty))
return true;
// If the membership vector itself was empty that's also a non-membership.
if(membership.empty())
return true;
return false;
}
bool
ircd::m::membership(const m::event &event,
const vector_view<const string_view> &membership)
{
const auto matching
{
m::membership(event)
};
const auto it
{
std::find(begin(membership), end(membership), matching)
};
return it != end(membership);
}
ircd::string_view
ircd::m::membership(const mutable_buffer &out,
const room &room,
const user::id &user_id)
{
const auto event_idx
{
room.get(std::nothrow, "m.room.member", user_id)
};
return m::membership(out, event_idx);
}
ircd::string_view
ircd::m::membership(const mutable_buffer &out,
const event::idx &event_idx)
{
return m::query(std::nothrow, event_idx, "content", [&out]
(const json::object &content) -> string_view
{
const json::string &content_membership
{
content["membership"]
};
return strlcpy
{
out, content_membership
};
});
}
ircd::string_view
ircd::m::membership(const event &event)
{
// The caller should check event type; empty is allowed if they only have content.
assert(!json::get<"type"_>(event) || json::get<"type"_>(event) == "m.room.member");
const auto &membership
{
json::get<"membership"_>(event)
};
if(likely(!membership))
{
const auto &content
{
json::get<"content"_>(event)
};
const json::string &membership
{
content.get("membership")
};
return membership;
}
return membership;
}