ircd:Ⓜ️:push: Implement event_property_is. (matrix-org/matrix-spec-proposals#3758)

This commit is contained in:
Jason Volk 2023-03-06 18:28:15 -08:00
parent d5c2ff0e99
commit 9aaae46ead
4 changed files with 67 additions and 3 deletions

View File

@ -191,6 +191,7 @@ struct ircd::m::name
static constexpr const char *const pattern {"pattern"};
static constexpr const char *const is {"is"};
static constexpr const char *const cond {"cond"};
static constexpr const char *const value {"value"};
static constexpr const char *const actions {"actions"};
static constexpr const char *const default_ {"default"};

View File

@ -64,8 +64,8 @@ struct ircd::m::push::match
struct opts;
using cond_kind_func = bool (*)(const event &, const cond &, const opts &);
static const string_view cond_kind_name[6];
static const cond_kind_func cond_kind[7];
static const string_view cond_kind_name[];
static const cond_kind_func cond_kind[];
explicit match(const event &, const cond &, const opts &);
explicit match(const event &, const rule &, const opts &);
@ -217,7 +217,11 @@ struct ircd::m::push::cond
/// prefixed by one of, ==, <, >, >= or <=. A prefix of < matches rooms
/// where the member count is strictly less than the given number and so
/// forth. If no prefix is present, this parameter defaults to ==.
json::property<name::is, json::string>
json::property<name::is, json::string>,
/// Required for event_property conditions. The exact case-sensitive string
/// to match.
json::property<name::value, json::string>
>
{
using super_type::tuple;

View File

@ -170,6 +170,7 @@ constexpr const char *const ircd::m::name::key;
constexpr const char *const ircd::m::name::pattern;
constexpr const char *const ircd::m::name::is;
constexpr const char *const ircd::m::name::cond;
constexpr const char *const ircd::m::name::value;
constexpr const char *const ircd::m::name::actions;
constexpr const char *const ircd::m::name::default_;

View File

@ -77,6 +77,7 @@ namespace ircd::m::push
static bool state_key_user_mxid(const event &, const cond &, const match::opts &);
static bool contains_user_mxid(const event &, const cond &, const match::opts &);
static bool room_member_count(const event &, const cond &, const match::opts &);
static bool event_property_is(const event &, const cond &, const match::opts &);
static bool event_match(const event &, const cond &, const match::opts &);
}
@ -84,6 +85,7 @@ decltype(ircd::m::push::match::cond_kind)
ircd::m::push::match::cond_kind
{
event_match,
event_property_is,
room_member_count,
contains_user_mxid,
state_key_user_mxid,
@ -96,6 +98,7 @@ decltype(ircd::m::push::match::cond_kind_name)
ircd::m::push::match::cond_kind_name
{
"event_match",
"event_property_is",
"room_member_count",
"contains_user_mxid",
"state_key_user_mxid",
@ -220,6 +223,61 @@ catch(const std::exception &e)
return false;
}
bool
ircd::m::push::event_property_is(const event &event,
const cond &cond,
const match::opts &opts)
try
{
assert(json::get<"kind"_>(cond) == "event_property_is");
const auto &[top, path]
{
split(json::get<"key"_>(cond), '.')
};
string_view value
{
json::get(event, top, json::object{})
};
tokens(path, '.', [&value]
(const string_view &key)
{
if(!json::type(value, json::OBJECT))
return false;
value = json::object(value)[key];
if(likely(!json::type(value, json::STRING)))
return true;
value = json::string(value);
return false;
});
const json::value a{value}, b
{
json::get<"value"_>(cond)
};
return a == b;
}
catch(const ctx::interrupted &)
{
throw;
}
catch(const std::exception &e)
{
log::error
{
log, "Push condition 'event_property_is' %s :%s",
string_view{event.event_id},
e.what(),
};
return false;
}
bool
ircd::m::push::contains_user_mxid(const event &event,
const cond &cond,