mirror of
https://github.com/matrix-construct/construct
synced 2024-05-20 11:53:46 +02:00
Compare commits
14 commits
a7a3275817
...
0624b69246
Author | SHA1 | Date | |
---|---|---|---|
0624b69246 | |||
e5ae70c521 | |||
759871ce8e | |||
3c9a4f8c57 | |||
f6b3b8b758 | |||
4fe85805bf | |||
b6cb1180f7 | |||
741304271e | |||
cd2b92b8fe | |||
feb4ac1fd3 | |||
d4ba215a3b | |||
8a705f77a9 | |||
f86fddc3a3 | |||
8eb10c5d1a |
|
@ -988,6 +988,7 @@ dnl Compiler specific
|
||||||
AM_COND_IF([CLANG],
|
AM_COND_IF([CLANG],
|
||||||
[
|
[
|
||||||
RB_MAYBE_CWARN([-Werror=return-stack-address], charybdis_cv_c_gcc_w_error_return_stack_address)
|
RB_MAYBE_CWARN([-Werror=return-stack-address], charybdis_cv_c_gcc_w_error_return_stack_address)
|
||||||
|
RB_MAYBE_CWARN([-Werror=abstract-final-class], charybdis_cv_c_gcc_w_error_abstract_final_class)
|
||||||
|
|
||||||
RB_MAYBE_CWARN([-Wundefined-reinterpret-cast], charybdis_cv_c_gcc_w_undefined_reinterpret_cast)
|
RB_MAYBE_CWARN([-Wundefined-reinterpret-cast], charybdis_cv_c_gcc_w_undefined_reinterpret_cast)
|
||||||
RB_MAYBE_CWARN([-Wconditional-uninitialized], charybdis_cv_c_gcc_w_conditional_uninitialized)
|
RB_MAYBE_CWARN([-Wconditional-uninitialized], charybdis_cv_c_gcc_w_conditional_uninitialized)
|
||||||
|
|
|
@ -29,6 +29,29 @@ struct ircd::m::event::append
|
||||||
{
|
{
|
||||||
struct opts;
|
struct opts;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const event::keys::exclude exclude_keys;
|
||||||
|
static const event::keys default_keys;
|
||||||
|
static conf::item<std::string> exclude_types;
|
||||||
|
static conf::item<bool> info;
|
||||||
|
static log::log log;
|
||||||
|
|
||||||
|
bool is_ignored(const event &, const opts &) const;
|
||||||
|
bool is_redacted(const event &, const opts &) const;
|
||||||
|
bool is_invisible(const event &, const opts &) const;
|
||||||
|
bool is_excluded(const event &, const opts &) const;
|
||||||
|
|
||||||
|
bool bundle_replace(json::stack::object &, const event &, const opts &);
|
||||||
|
void _relations(json::stack::object &, const event &, const opts &);
|
||||||
|
void _age(json::stack::object &, const event &, const opts &);
|
||||||
|
void _txnid(json::stack::object &, const event &, const opts &);
|
||||||
|
void _prev_state(json::stack::object &, const event &, const opts &);
|
||||||
|
void _unsigned(json::stack::object &, const event &, const opts &);
|
||||||
|
|
||||||
|
bool members(json::stack::object &, const event &, const opts &);
|
||||||
|
bool object(json::stack::array &, const event &, const opts &);
|
||||||
|
|
||||||
|
public:
|
||||||
append(json::stack::object &, const event &, const opts &);
|
append(json::stack::object &, const event &, const opts &);
|
||||||
append(json::stack::object &, const event &);
|
append(json::stack::object &, const event &);
|
||||||
append(json::stack::array &, const event &, const opts &);
|
append(json::stack::array &, const event &, const opts &);
|
||||||
|
@ -39,11 +62,11 @@ struct ircd::m::event::append
|
||||||
/// can provide the best result.
|
/// can provide the best result.
|
||||||
struct ircd::m::event::append::opts
|
struct ircd::m::event::append::opts
|
||||||
{
|
{
|
||||||
const event::idx *event_idx {nullptr};
|
event::idx event_idx {0};
|
||||||
const string_view *client_txnid {nullptr};
|
string_view client_txnid;
|
||||||
const id::user *user_id {nullptr};
|
id::user user_id;
|
||||||
const room *user_room {nullptr};
|
id::room user_room_id;
|
||||||
const int64_t *room_depth {nullptr};
|
int64_t room_depth {-1L};
|
||||||
const event::keys *keys {nullptr};
|
const event::keys *keys {nullptr};
|
||||||
const m::event_filter *event_filter {nullptr};
|
const m::event_filter *event_filter {nullptr};
|
||||||
long age {std::numeric_limits<long>::min()};
|
long age {std::numeric_limits<long>::min()};
|
||||||
|
@ -51,6 +74,8 @@ struct ircd::m::event::append::opts
|
||||||
bool query_prev_state {true};
|
bool query_prev_state {true};
|
||||||
bool query_redacted {true};
|
bool query_redacted {true};
|
||||||
bool query_visible {false};
|
bool query_visible {false};
|
||||||
|
bool bundle_all {false};
|
||||||
|
bool bundle_replace {false};
|
||||||
};
|
};
|
||||||
|
|
||||||
inline
|
inline
|
||||||
|
@ -64,3 +89,23 @@ ircd::m::event::append::append(json::stack::object &o,
|
||||||
const event &e)
|
const event &e)
|
||||||
:append{o, e, {}}
|
:append{o, e, {}}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
inline
|
||||||
|
ircd::m::event::append::append(json::stack::array &array,
|
||||||
|
const event &event,
|
||||||
|
const opts &opts)
|
||||||
|
:returns<bool>{[this, &array, &event, &opts]
|
||||||
|
{
|
||||||
|
return object(array, event, opts);
|
||||||
|
}}
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline
|
||||||
|
ircd::m::event::append::append(json::stack::object &object,
|
||||||
|
const event &event,
|
||||||
|
const opts &opts)
|
||||||
|
:returns<bool>{[this, &object, &event, &opts]
|
||||||
|
{
|
||||||
|
return members(object, event, opts);
|
||||||
|
}}
|
||||||
|
{}
|
||||||
|
|
|
@ -44,9 +44,11 @@ struct ircd::m::relates
|
||||||
const event::idx &, const json::object &, const m::relates_to &
|
const event::idx &, const json::object &, const m::relates_to &
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
static conf::item<std::string> latest_column;
|
||||||
|
|
||||||
event::refs refs;
|
event::refs refs;
|
||||||
bool match_sender {false};
|
bool match_sender {false};
|
||||||
bool prefetch_depth {false};
|
bool prefetch_latest {false};
|
||||||
bool prefetch_sender {false};
|
bool prefetch_sender {false};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -187,9 +187,11 @@ struct ircd::m::room
|
||||||
const vm::copts *const &copts,
|
const vm::copts *const &copts,
|
||||||
const event::fetch::opts *const &fopts = nullptr) noexcept;
|
const event::fetch::opts *const &fopts = nullptr) noexcept;
|
||||||
|
|
||||||
room(const id &room_id = {},
|
room(const id &room_id,
|
||||||
const event::fetch::opts *const &fopts = nullptr) noexcept;
|
const event::fetch::opts *const &fopts = nullptr) noexcept;
|
||||||
|
|
||||||
|
room() = default;
|
||||||
|
|
||||||
// Index of create event
|
// Index of create event
|
||||||
static event::idx index(const id &, std::nothrow_t);
|
static event::idx index(const id &, std::nothrow_t);
|
||||||
static event::idx index(const id &);
|
static event::idx index(const id &);
|
||||||
|
@ -229,7 +231,9 @@ ircd::m::room::room(const id &room_id,
|
||||||
,event_id{event_id? event::id{event_id} : event::id{}}
|
,event_id{event_id? event::id{event_id} : event::id{}}
|
||||||
,copts{copts}
|
,copts{copts}
|
||||||
,fopts{fopts}
|
,fopts{fopts}
|
||||||
{}
|
{
|
||||||
|
assert(room_id);
|
||||||
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
ircd::m::room::room(const id &room_id,
|
ircd::m::room::room(const id &room_id,
|
||||||
|
@ -239,7 +243,9 @@ noexcept
|
||||||
:room_id{room_id}
|
:room_id{room_id}
|
||||||
,copts{copts}
|
,copts{copts}
|
||||||
,fopts{fopts}
|
,fopts{fopts}
|
||||||
{}
|
{
|
||||||
|
assert(room_id);
|
||||||
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
ircd::m::room::room(const id &room_id,
|
ircd::m::room::room(const id &room_id,
|
||||||
|
@ -247,7 +253,9 @@ ircd::m::room::room(const id &room_id,
|
||||||
noexcept
|
noexcept
|
||||||
:room_id{room_id}
|
:room_id{room_id}
|
||||||
,fopts{fopts}
|
,fopts{fopts}
|
||||||
{}
|
{
|
||||||
|
assert(room_id);
|
||||||
|
}
|
||||||
|
|
||||||
inline ircd::m::room::operator
|
inline ircd::m::room::operator
|
||||||
const ircd::m::room::id &()
|
const ircd::m::room::id &()
|
||||||
|
|
|
@ -22,6 +22,7 @@ struct ircd::m::user::keys
|
||||||
|
|
||||||
void attach_sigs(json::stack::object &, const json::object &, const user::id &) const;
|
void attach_sigs(json::stack::object &, const json::object &, const user::id &) const;
|
||||||
bool attach_sigs(json::stack::object &, const event::idx &, const user::id &) const;
|
bool attach_sigs(json::stack::object &, const event::idx &, const user::id &) const;
|
||||||
|
void append_sigs(json::stack::object &, const json::object &, const user::id &) const;
|
||||||
void append_keys(json::stack::object &, const json::object &, const user::id &) const;
|
void append_keys(json::stack::object &, const json::object &, const user::id &) const;
|
||||||
bool append_keys(json::stack::object &, const event::idx &, const user::id &) const;
|
bool append_keys(json::stack::object &, const event::idx &, const user::id &) const;
|
||||||
|
|
||||||
|
|
|
@ -74,13 +74,17 @@ struct ircd::m::user
|
||||||
event::id::buf deoper();
|
event::id::buf deoper();
|
||||||
event::id::buf oper();
|
event::id::buf oper();
|
||||||
|
|
||||||
user(const id &user_id)
|
user(const id &user_id);
|
||||||
:user_id{user_id}
|
|
||||||
{}
|
|
||||||
|
|
||||||
user() = default;
|
user() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline
|
||||||
|
ircd::m::user::user(const id &user_id)
|
||||||
|
:user_id{user_id}
|
||||||
|
{
|
||||||
|
assert(user_id);
|
||||||
|
}
|
||||||
|
|
||||||
inline ircd::m::user::operator
|
inline ircd::m::user::operator
|
||||||
const ircd::m::user::id &()
|
const ircd::m::user::id &()
|
||||||
const
|
const
|
||||||
|
|
|
@ -73,16 +73,9 @@ struct ircd::versions
|
||||||
~versions() noexcept;
|
~versions() noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace ircd
|
template<>
|
||||||
{
|
decltype(ircd::versions::list)
|
||||||
template<>
|
ircd::instance_list<ircd::versions>::list;
|
||||||
decltype(versions::allocator)
|
|
||||||
instance_list<versions>::allocator;
|
|
||||||
|
|
||||||
template<>
|
|
||||||
decltype(versions::list)
|
|
||||||
instance_list<versions>::list;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ircd::versions::operator
|
inline ircd::versions::operator
|
||||||
const long &()
|
const long &()
|
||||||
|
|
|
@ -224,7 +224,9 @@ ircd::db::database::cache final
|
||||||
#else
|
#else
|
||||||
Status Insert(const Slice &key, void *value, size_t charge, deleter, Handle **, Priority) noexcept override;
|
Status Insert(const Slice &key, void *value, size_t charge, deleter, Handle **, Priority) noexcept override;
|
||||||
#endif
|
#endif
|
||||||
#ifdef IRCD_DB_HAS_CACHE_ITEMHELPER
|
#if defined(IRCD_DB_HAS_CACHE_ASYNC)
|
||||||
|
Handle *Lookup(const Slice &key, const CacheItemHelper *, CreateContext *, Priority, Statistics *) noexcept override;
|
||||||
|
#elif defined(IRCD_DB_HAS_CACHE_ITEMHELPER)
|
||||||
Handle *Lookup(const Slice &key, const CacheItemHelper *, CreateContext *, Priority, bool, Statistics *) noexcept override;
|
Handle *Lookup(const Slice &key, const CacheItemHelper *, CreateContext *, Priority, bool, Statistics *) noexcept override;
|
||||||
#else
|
#else
|
||||||
Handle *Lookup(const Slice &key, Statistics *) noexcept override;
|
Handle *Lookup(const Slice &key, Statistics *) noexcept override;
|
||||||
|
@ -263,6 +265,9 @@ ircd::db::database::cache final
|
||||||
#ifdef IRCD_DB_HAS_CACHE_ITEMHELPER
|
#ifdef IRCD_DB_HAS_CACHE_ITEMHELPER
|
||||||
const CacheItemHelper *GetCacheItemHelper(Handle *) const noexcept override;
|
const CacheItemHelper *GetCacheItemHelper(Handle *) const noexcept override;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef IRCD_DB_HAS_CACHE_ASYNC
|
||||||
|
Handle *CreateStandalone(const Slice &, ObjectPtr, const CacheItemHelper *, size_t, bool) noexcept override;
|
||||||
|
#endif
|
||||||
|
|
||||||
cache(database *const &,
|
cache(database *const &,
|
||||||
std::shared_ptr<struct database::stats>,
|
std::shared_ptr<struct database::stats>,
|
||||||
|
|
|
@ -3321,7 +3321,14 @@ noexcept
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef IRCD_DB_HAS_CACHE_ITEMHELPER
|
#if defined(IRCD_DB_HAS_CACHE_ASYNC)
|
||||||
|
rocksdb::Cache::Handle *
|
||||||
|
ircd::db::database::cache::Lookup(const Slice &key,
|
||||||
|
const CacheItemHelper *const helper,
|
||||||
|
CreateContext *const cc,
|
||||||
|
Priority pri,
|
||||||
|
Statistics *const statistics)
|
||||||
|
#elif defined(IRCD_DB_HAS_CACHE_ITEMHELPER)
|
||||||
rocksdb::Cache::Handle *
|
rocksdb::Cache::Handle *
|
||||||
ircd::db::database::cache::Lookup(const Slice &key,
|
ircd::db::database::cache::Lookup(const Slice &key,
|
||||||
const CacheItemHelper *const helper,
|
const CacheItemHelper *const helper,
|
||||||
|
@ -3355,7 +3362,9 @@ noexcept
|
||||||
|
|
||||||
auto *const &ret
|
auto *const &ret
|
||||||
{
|
{
|
||||||
#ifdef IRCD_DB_HAS_CACHE_ITEMHELPER
|
#if defined(IRCD_DB_HAS_CACHE_ASYNC)
|
||||||
|
c->Lookup(key, helper, cc, pri, statistics)
|
||||||
|
#elif defined(IRCD_DB_HAS_CACHE_ITEMHELPER)
|
||||||
c->Lookup(key, helper, cc, pri, wait, statistics)
|
c->Lookup(key, helper, cc, pri, wait, statistics)
|
||||||
#else
|
#else
|
||||||
c->Lookup(key, s)
|
c->Lookup(key, s)
|
||||||
|
@ -3559,6 +3568,20 @@ const noexcept
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(IRCD_DB_HAS_CACHE_ASYNC)
|
||||||
|
rocksdb::Cache::Handle *
|
||||||
|
ircd::db::database::cache::CreateStandalone(const Slice &key,
|
||||||
|
ObjectPtr ptr,
|
||||||
|
const CacheItemHelper *const helper,
|
||||||
|
size_t charge,
|
||||||
|
bool allow_uncharged)
|
||||||
|
noexcept
|
||||||
|
{
|
||||||
|
assert(bool(c));
|
||||||
|
return c->CreateStandalone(key, ptr, helper, charge, allow_uncharged);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// database::compaction_filter
|
// database::compaction_filter
|
||||||
|
|
|
@ -193,3 +193,9 @@
|
||||||
|| (ROCKSDB_MAJOR == 8 && ROCKSDB_MINOR == 0 && ROCKSDB_PATCH >= 0)
|
|| (ROCKSDB_MAJOR == 8 && ROCKSDB_MINOR == 0 && ROCKSDB_PATCH >= 0)
|
||||||
#define IRCD_DB_HAS_CACHE_WRAPPER
|
#define IRCD_DB_HAS_CACHE_WRAPPER
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ROCKSDB_MAJOR > 8 \
|
||||||
|
|| (ROCKSDB_MAJOR == 8 && ROCKSDB_MINOR > 1) \
|
||||||
|
|| (ROCKSDB_MAJOR == 8 && ROCKSDB_MINOR == 1 && ROCKSDB_PATCH >= 1)
|
||||||
|
#define IRCD_DB_HAS_CACHE_ASYNC
|
||||||
|
#endif
|
||||||
|
|
|
@ -13,12 +13,12 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
decltype(ircd::util::instance_list<ircd::versions>::allocator)
|
decltype(ircd::versions::allocator)
|
||||||
ircd::util::instance_list<ircd::versions>::allocator
|
ircd::util::instance_list<ircd::versions>::allocator
|
||||||
{};
|
{};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
decltype(ircd::util::instance_list<ircd::versions>::list)
|
decltype(ircd::versions::list)
|
||||||
ircd::util::instance_list<ircd::versions>::list
|
ircd::util::instance_list<ircd::versions>::list
|
||||||
{
|
{
|
||||||
allocator
|
allocator
|
||||||
|
|
|
@ -8,31 +8,25 @@
|
||||||
// copyright notice and this permission notice is present in all copies. The
|
// copyright notice and this permission notice is present in all copies. The
|
||||||
// full license for this software is available in the LICENSE file.
|
// full license for this software is available in the LICENSE file.
|
||||||
|
|
||||||
namespace ircd::m
|
[[gnu::visibility("hidden")]]
|
||||||
{
|
decltype(ircd::m::event::append::log)
|
||||||
extern const event::keys::exclude event_append_exclude_keys;
|
ircd::m::event::append::log
|
||||||
extern const event::keys event_append_default_keys;
|
|
||||||
extern conf::item<std::string> event_append_exclude_types;
|
|
||||||
extern conf::item<bool> event_append_info;
|
|
||||||
extern log::log event_append_log;
|
|
||||||
}
|
|
||||||
|
|
||||||
decltype(ircd::m::event_append_log)
|
|
||||||
ircd::m::event_append_log
|
|
||||||
{
|
{
|
||||||
"m.event.append"
|
"m.event.append"
|
||||||
};
|
};
|
||||||
|
|
||||||
decltype(ircd::m::event_append_info)
|
[[gnu::visibility("hidden")]]
|
||||||
ircd::m::event_append_info
|
decltype(ircd::m::event::append::info)
|
||||||
|
ircd::m::event::append::info
|
||||||
{
|
{
|
||||||
{ "name", "ircd.m.event.append.info" },
|
{ "name", "ircd.m.event.append.info" },
|
||||||
{ "default", false },
|
{ "default", false },
|
||||||
{ "persist", false },
|
{ "persist", false },
|
||||||
};
|
};
|
||||||
|
|
||||||
decltype(ircd::m::event_append_exclude_types)
|
[[gnu::visibility("hidden")]]
|
||||||
ircd::m::event_append_exclude_types
|
decltype(ircd::m::event::append::exclude_types)
|
||||||
|
ircd::m::event::append::exclude_types
|
||||||
{
|
{
|
||||||
{ "name", "ircd.m.event.append.exclude.types" },
|
{ "name", "ircd.m.event.append.exclude.types" },
|
||||||
{ "default", "org.matrix.dummy_event" },
|
{ "default", "org.matrix.dummy_event" },
|
||||||
|
@ -42,8 +36,9 @@ ircd::m::event_append_exclude_types
|
||||||
/// to the client. This mask is applied only if the caller of event::append{}
|
/// to the client. This mask is applied only if the caller of event::append{}
|
||||||
/// did not supply their mask to apply. It is also inferior to the user's
|
/// did not supply their mask to apply. It is also inferior to the user's
|
||||||
/// filter if supplied.
|
/// filter if supplied.
|
||||||
decltype(ircd::m::event_append_exclude_keys)
|
[[gnu::visibility("hidden")]]
|
||||||
ircd::m::event_append_exclude_keys
|
decltype(ircd::m::event::append::exclude_keys)
|
||||||
|
ircd::m::event::append::exclude_keys
|
||||||
{
|
{
|
||||||
"auth_events",
|
"auth_events",
|
||||||
"hashes",
|
"hashes",
|
||||||
|
@ -53,16 +48,17 @@ ircd::m::event_append_exclude_keys
|
||||||
"signatures",
|
"signatures",
|
||||||
};
|
};
|
||||||
|
|
||||||
decltype(ircd::m::event_append_default_keys)
|
[[gnu::visibility("hidden")]]
|
||||||
ircd::m::event_append_default_keys
|
decltype(ircd::m::event::append::default_keys)
|
||||||
|
ircd::m::event::append::default_keys
|
||||||
{
|
{
|
||||||
event_append_exclude_keys
|
event::append::exclude_keys
|
||||||
};
|
};
|
||||||
|
|
||||||
ircd::m::event::append::append(json::stack::array &array,
|
bool
|
||||||
const event &event_,
|
ircd::m::event::append::object(json::stack::array &array,
|
||||||
|
const event &event,
|
||||||
const opts &opts)
|
const opts &opts)
|
||||||
:returns<bool>{[&]
|
|
||||||
{
|
{
|
||||||
assert(array.s);
|
assert(array.s);
|
||||||
json::stack::checkpoint cp
|
json::stack::checkpoint cp
|
||||||
|
@ -70,29 +66,24 @@ ircd::m::event::append::append(json::stack::array &array,
|
||||||
*array.s
|
*array.s
|
||||||
};
|
};
|
||||||
|
|
||||||
json::stack::object object
|
json::stack::object _object
|
||||||
{
|
{
|
||||||
array
|
array
|
||||||
};
|
};
|
||||||
|
|
||||||
const bool ret
|
const bool ret
|
||||||
{
|
{
|
||||||
append
|
members(_object, event, opts)
|
||||||
{
|
|
||||||
object, event_, opts
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
cp.committing(ret);
|
cp.committing(ret);
|
||||||
return ret;
|
return ret;
|
||||||
}}
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ircd::m::event::append::append(json::stack::object &object,
|
bool
|
||||||
const event &event,
|
ircd::m::event::append::members(json::stack::object &out,
|
||||||
const opts &opts)
|
const event &event,
|
||||||
:returns<bool>{[&]
|
const opts &opts)
|
||||||
{
|
{
|
||||||
// Assertions that the event being appended has some required fields. This
|
// Assertions that the event being appended has some required fields. This
|
||||||
// is a central butt-end test of data coming through the system to here.
|
// is a central butt-end test of data coming through the system to here.
|
||||||
|
@ -101,150 +92,35 @@ ircd::m::event::append::append(json::stack::object &object,
|
||||||
assert(defined(json::get<"sender"_>(event)));
|
assert(defined(json::get<"sender"_>(event)));
|
||||||
//assert(json::get<"origin_server_ts"_>(event));
|
//assert(json::get<"origin_server_ts"_>(event));
|
||||||
//assert(json::get<"origin_server_ts"_>(event) != json::undefined_number);
|
//assert(json::get<"origin_server_ts"_>(event) != json::undefined_number);
|
||||||
#if defined(RB_DEBUG)
|
if constexpr(RB_DEBUG_LEVEL)
|
||||||
if(unlikely(!defined(json::get<"type"_>(event))))
|
{
|
||||||
return false;
|
if(unlikely(!defined(json::get<"type"_>(event))))
|
||||||
|
return false;
|
||||||
|
|
||||||
if(unlikely(!defined(json::get<"sender"_>(event))))
|
if(unlikely(!defined(json::get<"sender"_>(event))))
|
||||||
return false;
|
return false;
|
||||||
#endif
|
}
|
||||||
|
|
||||||
if(opts.event_filter && !m::match(*opts.event_filter, event))
|
if(opts.event_filter && !m::match(*opts.event_filter, event))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const auto ¬_types
|
if(is_excluded(event, opts))
|
||||||
{
|
|
||||||
event_append_exclude_types
|
|
||||||
};
|
|
||||||
|
|
||||||
if(!opts.event_filter && token_exists(not_types, ' ', json::get<"type"_>(event)))
|
|
||||||
{
|
|
||||||
log::debug
|
|
||||||
{
|
|
||||||
log, "Not sending event %s because type '%s' excluded by configuration.",
|
|
||||||
string_view{event.event_id},
|
|
||||||
json::get<"type"_>(event),
|
|
||||||
};
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if(opts.query_visible && opts.user_id && !visible(event, *opts.user_id))
|
|
||||||
{
|
|
||||||
log::debug
|
|
||||||
{
|
|
||||||
log, "Not sending event %s because not visible to %s.",
|
|
||||||
string_view{event.event_id},
|
|
||||||
string_view{*opts.user_id},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
if(is_invisible(event, opts))
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
const bool has_event_idx
|
|
||||||
{
|
|
||||||
opts.event_idx && *opts.event_idx
|
|
||||||
};
|
|
||||||
|
|
||||||
const bool is_state
|
|
||||||
{
|
|
||||||
defined(json::get<"state_key"_>(event))
|
|
||||||
};
|
|
||||||
|
|
||||||
const bool query_redacted
|
|
||||||
{
|
|
||||||
has_event_idx &&
|
|
||||||
opts.query_redacted &&
|
|
||||||
!is_state &&
|
|
||||||
(!opts.room_depth || *opts.room_depth > json::get<"depth"_>(event))
|
|
||||||
};
|
|
||||||
|
|
||||||
if(query_redacted && m::redacted(*opts.event_idx))
|
|
||||||
{
|
|
||||||
log::debug
|
|
||||||
{
|
|
||||||
log, "Not sending event %s because redacted.",
|
|
||||||
string_view{event.event_id},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
if(is_redacted(event, opts))
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
const bool has_user
|
if(is_ignored(event, opts))
|
||||||
{
|
return false;
|
||||||
opts.user_id && opts.user_room
|
|
||||||
};
|
|
||||||
|
|
||||||
const bool check_ignores
|
|
||||||
{
|
|
||||||
has_user && !is_state
|
|
||||||
};
|
|
||||||
|
|
||||||
if(check_ignores && *opts.user_id != json::get<"sender"_>(event))
|
|
||||||
{
|
|
||||||
const m::user::ignores ignores
|
|
||||||
{
|
|
||||||
*opts.user_id
|
|
||||||
};
|
|
||||||
|
|
||||||
if(ignores.enforce("events") && ignores.has(json::get<"sender"_>(event)))
|
|
||||||
{
|
|
||||||
log::debug
|
|
||||||
{
|
|
||||||
log, "Not sending event %s because %s is ignored by %s",
|
|
||||||
string_view{event.event_id},
|
|
||||||
json::get<"sender"_>(event),
|
|
||||||
string_view{*opts.user_id}
|
|
||||||
};
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool sender_is_user
|
|
||||||
{
|
|
||||||
has_user && json::get<"sender"_>(event) == *opts.user_id
|
|
||||||
};
|
|
||||||
|
|
||||||
const bool has_client_txnid
|
|
||||||
{
|
|
||||||
opts.client_txnid && *opts.client_txnid
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto txnid_idx
|
|
||||||
{
|
|
||||||
!has_client_txnid && sender_is_user && opts.query_txnid?
|
|
||||||
opts.user_room->get(std::nothrow, "ircd.client.txnid", event.event_id):
|
|
||||||
0UL
|
|
||||||
};
|
|
||||||
|
|
||||||
const bool query_prev_state
|
|
||||||
{
|
|
||||||
opts.query_prev_state && has_event_idx && is_state
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto prev_state_idx
|
|
||||||
{
|
|
||||||
query_prev_state?
|
|
||||||
room::state::prev(*opts.event_idx):
|
|
||||||
0UL
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined(RB_DEBUG) && 0
|
|
||||||
if(!has_client_txnid && !txnid_idx && sender_is_user && opts.query_txnid)
|
|
||||||
log::dwarning
|
|
||||||
{
|
|
||||||
log, "Could not find transaction_id for %s from %s in %s",
|
|
||||||
string_view{event.event_id},
|
|
||||||
json::get<"sender"_>(event),
|
|
||||||
json::get<"room_id"_>(event)
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
// For v3+ events
|
||||||
if(!json::get<"event_id"_>(event))
|
if(!json::get<"event_id"_>(event))
|
||||||
json::stack::member
|
json::stack::member
|
||||||
{
|
{
|
||||||
object, "event_id", event.event_id
|
out, "event_id", event.event_id
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the list of properties to send to the client so we can strip
|
// Get the list of properties to send to the client so we can strip
|
||||||
|
@ -254,11 +130,11 @@ ircd::m::event::append::append(json::stack::object &object,
|
||||||
{
|
{
|
||||||
opts.keys?
|
opts.keys?
|
||||||
*opts.keys:
|
*opts.keys:
|
||||||
event_append_default_keys
|
default_keys
|
||||||
};
|
};
|
||||||
|
|
||||||
// Append the event members
|
// Append the event members
|
||||||
for_each(event, [&keys, &object]
|
for_each(event, [&keys, &out]
|
||||||
(const auto &key, const auto &val_)
|
(const auto &key, const auto &val_)
|
||||||
{
|
{
|
||||||
if(!keys.has(key) && key != "redacts"_sv)
|
if(!keys.has(key) && key != "redacts"_sv)
|
||||||
|
@ -274,70 +150,77 @@ ircd::m::event::append::append(json::stack::object &object,
|
||||||
|
|
||||||
json::stack::member
|
json::stack::member
|
||||||
{
|
{
|
||||||
object, key, val
|
out, key, val
|
||||||
};
|
};
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
json::stack::object unsigned_
|
_unsigned(out, event, opts);
|
||||||
{
|
|
||||||
object, "unsigned"
|
|
||||||
};
|
|
||||||
|
|
||||||
const json::value age
|
if(unlikely(info))
|
||||||
{
|
log::info
|
||||||
// When the opts give an explicit age, use it.
|
|
||||||
opts.age != std::numeric_limits<long>::min()?
|
|
||||||
opts.age:
|
|
||||||
|
|
||||||
// If we have depth information, craft a value based on the
|
|
||||||
// distance to the head depth; if this is 0 in riot the event will
|
|
||||||
// "stick" at the bottom of the timeline. This may be advantageous
|
|
||||||
// in the future but for now we make sure the result is non-zero.
|
|
||||||
json::get<"depth"_>(event) >= 0 && opts.room_depth && *opts.room_depth >= 0L?
|
|
||||||
(*opts.room_depth + 1 - json::get<"depth"_>(event)) + 1:
|
|
||||||
|
|
||||||
// We don't have depth information, so we use the origin_server_ts.
|
|
||||||
// It is bad if it conflicts with other appends in the room which
|
|
||||||
// did have depth information.
|
|
||||||
!opts.room_depth && json::get<"origin_server_ts"_>(event)?
|
|
||||||
ircd::time<milliseconds>() - json::get<"origin_server_ts"_>(event):
|
|
||||||
|
|
||||||
// Finally, this special value will eliminate the age altogether
|
|
||||||
// during serialization.
|
|
||||||
json::undefined_number
|
|
||||||
};
|
|
||||||
|
|
||||||
json::stack::member
|
|
||||||
{
|
|
||||||
unsigned_, "age", age
|
|
||||||
};
|
|
||||||
|
|
||||||
if(has_client_txnid)
|
|
||||||
json::stack::member
|
|
||||||
{
|
{
|
||||||
unsigned_, "transaction_id", *opts.client_txnid
|
log, "%s %s idx:%lu in %s depth:%ld txnid:%s %s,%s",
|
||||||
|
string_view{opts.user_id},
|
||||||
|
string_view{event.event_id},
|
||||||
|
opts.event_idx,
|
||||||
|
json::get<"room_id"_>(event),
|
||||||
|
json::get<"depth"_>(event),
|
||||||
|
opts.client_txnid,
|
||||||
|
json::get<"type"_>(event),
|
||||||
|
json::get<"state_key"_>(event),
|
||||||
};
|
};
|
||||||
|
|
||||||
if(txnid_idx)
|
return true;
|
||||||
m::get(std::nothrow, txnid_idx, "content", [&unsigned_]
|
}
|
||||||
(const json::object &content)
|
|
||||||
{
|
void
|
||||||
json::stack::member
|
ircd::m::event::append::_unsigned(json::stack::object &out,
|
||||||
{
|
const event &event,
|
||||||
unsigned_, "transaction_id", unquote(content.get("transaction_id"))
|
const opts &opts)
|
||||||
};
|
{
|
||||||
});
|
json::stack::object object
|
||||||
|
{
|
||||||
|
out, "unsigned"
|
||||||
|
};
|
||||||
|
|
||||||
|
_age(object, event, opts);
|
||||||
|
_txnid(object, event, opts);
|
||||||
|
_relations(object, event, opts);
|
||||||
|
if(defined(json::get<"state_key"_>(event)))
|
||||||
|
_prev_state(object, event, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ircd::m::event::append::_prev_state(json::stack::object &out,
|
||||||
|
const event &event,
|
||||||
|
const opts &opts)
|
||||||
|
{
|
||||||
|
assert(defined(json::get<"state_key"_>(event)));
|
||||||
|
|
||||||
|
const bool query_prev_state
|
||||||
|
{
|
||||||
|
true
|
||||||
|
&& opts.event_idx
|
||||||
|
&& opts.query_prev_state
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto prev_state_idx
|
||||||
|
{
|
||||||
|
query_prev_state?
|
||||||
|
room::state::prev(opts.event_idx):
|
||||||
|
0UL
|
||||||
|
};
|
||||||
|
|
||||||
if(prev_state_idx)
|
if(prev_state_idx)
|
||||||
{
|
{
|
||||||
m::get(std::nothrow, prev_state_idx, "content", [&unsigned_]
|
m::get(std::nothrow, prev_state_idx, "content", [&out]
|
||||||
(const json::object &content)
|
(const json::object &content)
|
||||||
{
|
{
|
||||||
json::stack::member
|
json::stack::member
|
||||||
{
|
{
|
||||||
unsigned_, "prev_content", content
|
out, "prev_content", content
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -348,7 +231,7 @@ ircd::m::event::append::append(json::stack::object &object,
|
||||||
|
|
||||||
json::stack::member
|
json::stack::member
|
||||||
{
|
{
|
||||||
unsigned_, "replaces_state", json::value
|
out, "replaces_state", json::value
|
||||||
{
|
{
|
||||||
replaces_state_id?
|
replaces_state_id?
|
||||||
string_view{replaces_state_id}:
|
string_view{replaces_state_id}:
|
||||||
|
@ -356,24 +239,279 @@ ircd::m::event::append::append(json::stack::object &object,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(unlikely(event_append_info))
|
void
|
||||||
log::info
|
ircd::m::event::append::_txnid(json::stack::object &out,
|
||||||
|
const event &event,
|
||||||
|
const opts &opts)
|
||||||
|
{
|
||||||
|
const bool sender_is_user
|
||||||
|
{
|
||||||
|
json::get<"sender"_>(event) == opts.user_id
|
||||||
|
};
|
||||||
|
|
||||||
|
const bool query_txnid
|
||||||
|
{
|
||||||
|
true
|
||||||
|
&& !opts.client_txnid
|
||||||
|
&& opts.query_txnid
|
||||||
|
&& opts.user_room_id
|
||||||
|
&& sender_is_user
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto txnid_idx
|
||||||
|
{
|
||||||
|
query_txnid?
|
||||||
|
m::room(opts.user_room_id).get(std::nothrow, "ircd.client.txnid", event.event_id):
|
||||||
|
0UL
|
||||||
|
};
|
||||||
|
|
||||||
|
if constexpr(RB_DEBUG_LEVEL)
|
||||||
|
{
|
||||||
|
const bool missing_txnid
|
||||||
{
|
{
|
||||||
event_append_log, "%s %s idx:%lu in %s depth:%ld txnid:%s idx:%lu age:%ld %s,%s",
|
true
|
||||||
opts.user_id? string_view{*opts.user_id} : string_view{},
|
&& !opts.client_txnid
|
||||||
string_view{event.event_id},
|
&& !txnid_idx
|
||||||
opts.event_idx? *opts.event_idx : 0UL,
|
&& sender_is_user
|
||||||
json::get<"room_id"_>(event),
|
&& opts.query_txnid
|
||||||
json::get<"depth"_>(event),
|
|
||||||
has_client_txnid? *opts.client_txnid : string_view{},
|
|
||||||
txnid_idx,
|
|
||||||
int64_t(age),
|
|
||||||
json::get<"type"_>(event),
|
|
||||||
json::get<"state_key"_>(event),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return true;
|
if(unlikely(missing_txnid))
|
||||||
}}
|
log::dwarning
|
||||||
{
|
{
|
||||||
|
log, "Could not find transaction_id for %s from %s in %s",
|
||||||
|
string_view{event.event_id},
|
||||||
|
json::get<"sender"_>(event),
|
||||||
|
json::get<"room_id"_>(event)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if(opts.client_txnid)
|
||||||
|
json::stack::member
|
||||||
|
{
|
||||||
|
out, "transaction_id", opts.client_txnid
|
||||||
|
};
|
||||||
|
else if(txnid_idx)
|
||||||
|
m::get(std::nothrow, txnid_idx, "content", [&out]
|
||||||
|
(const json::object &content)
|
||||||
|
{
|
||||||
|
json::stack::member
|
||||||
|
{
|
||||||
|
out, "transaction_id", content.get("transaction_id")
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ircd::m::event::append::_age(json::stack::object &out,
|
||||||
|
const event &event,
|
||||||
|
const opts &opts)
|
||||||
|
{
|
||||||
|
const json::value age
|
||||||
|
{
|
||||||
|
// When the opts give an explicit age, use it.
|
||||||
|
opts.age != std::numeric_limits<long>::min()?
|
||||||
|
opts.age:
|
||||||
|
|
||||||
|
// If we have depth information, craft a value based on the
|
||||||
|
// distance to the head depth; if this is 0 in riot the event will
|
||||||
|
// "stick" at the bottom of the timeline. This may be advantageous
|
||||||
|
// in the future but for now we make sure the result is non-zero.
|
||||||
|
json::get<"depth"_>(event) >= 0 && opts.room_depth >= 0L?
|
||||||
|
(opts.room_depth + 1 - json::get<"depth"_>(event)) + 1:
|
||||||
|
|
||||||
|
// We don't have depth information, so we use the origin_server_ts.
|
||||||
|
// It is bad if it conflicts with other appends in the room which
|
||||||
|
// did have depth information.
|
||||||
|
opts.room_depth < 0 && json::get<"origin_server_ts"_>(event)?
|
||||||
|
ircd::time<milliseconds>() - json::get<"origin_server_ts"_>(event):
|
||||||
|
|
||||||
|
// Finally, this special value will eliminate the age altogether
|
||||||
|
// during serialization.
|
||||||
|
json::undefined_number
|
||||||
|
};
|
||||||
|
|
||||||
|
json::stack::member
|
||||||
|
{
|
||||||
|
out, "age", age
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ircd::m::event::append::_relations(json::stack::object &out,
|
||||||
|
const event &event,
|
||||||
|
const opts &opts)
|
||||||
|
{
|
||||||
|
assert(out.s);
|
||||||
|
json::stack::checkpoint cp
|
||||||
|
{
|
||||||
|
*out.s, false
|
||||||
|
};
|
||||||
|
|
||||||
|
json::stack::object object
|
||||||
|
{
|
||||||
|
out, "m.relations"
|
||||||
|
};
|
||||||
|
|
||||||
|
bool commit
|
||||||
|
{
|
||||||
|
cp.committing()
|
||||||
|
};
|
||||||
|
|
||||||
|
if(opts.bundle_all || opts.bundle_replace)
|
||||||
|
commit |= bundle_replace(object, event, opts);
|
||||||
|
|
||||||
|
cp.committing(commit);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ircd::m::event::append::bundle_replace(json::stack::object &out,
|
||||||
|
const event &event,
|
||||||
|
const opts &opts)
|
||||||
|
{
|
||||||
|
const m::replaced replaced
|
||||||
|
{
|
||||||
|
opts.event_idx, m::replaced::latest
|
||||||
|
};
|
||||||
|
|
||||||
|
const event::idx &replace_idx
|
||||||
|
{
|
||||||
|
replaced
|
||||||
|
};
|
||||||
|
|
||||||
|
if(likely(!replace_idx))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const m::event::fetch replace
|
||||||
|
{
|
||||||
|
std::nothrow, replace_idx
|
||||||
|
};
|
||||||
|
|
||||||
|
if(unlikely(!replace.valid))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
json::stack::object object
|
||||||
|
{
|
||||||
|
out, "m.replace"
|
||||||
|
};
|
||||||
|
|
||||||
|
object.append(replace);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ircd::m::event::append::is_excluded(const event &event,
|
||||||
|
const opts &opts)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
const auto ¬_types
|
||||||
|
{
|
||||||
|
exclude_types
|
||||||
|
};
|
||||||
|
|
||||||
|
const bool ret
|
||||||
|
{
|
||||||
|
true
|
||||||
|
&& !opts.event_filter
|
||||||
|
&& token_exists(not_types, ' ', json::get<"type"_>(event))
|
||||||
|
};
|
||||||
|
|
||||||
|
if(ret)
|
||||||
|
log::debug
|
||||||
|
{
|
||||||
|
log, "Not sending event %s because type '%s' excluded by configuration.",
|
||||||
|
string_view{event.event_id},
|
||||||
|
json::get<"type"_>(event),
|
||||||
|
};
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ircd::m::event::append::is_invisible(const event &event,
|
||||||
|
const opts &opts)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
const bool ret
|
||||||
|
{
|
||||||
|
true
|
||||||
|
&& opts.query_visible
|
||||||
|
&& opts.user_id
|
||||||
|
&& !visible(event, opts.user_id)
|
||||||
|
};
|
||||||
|
|
||||||
|
if(ret)
|
||||||
|
log::debug
|
||||||
|
{
|
||||||
|
log, "Not sending event %s because not visible to %s.",
|
||||||
|
string_view{event.event_id},
|
||||||
|
string_view{opts.user_id},
|
||||||
|
};
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ircd::m::event::append::is_redacted(const event &event,
|
||||||
|
const opts &opts)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
const bool ret
|
||||||
|
{
|
||||||
|
true
|
||||||
|
&& opts.event_idx
|
||||||
|
&& opts.query_redacted
|
||||||
|
&& !defined(json::get<"state_key"_>(event))
|
||||||
|
&& opts.room_depth > json::get<"depth"_>(event)
|
||||||
|
&& m::redacted(opts.event_idx)
|
||||||
|
};
|
||||||
|
|
||||||
|
if(ret)
|
||||||
|
log::debug
|
||||||
|
{
|
||||||
|
log, "Not sending event %s because redacted.",
|
||||||
|
string_view{event.event_id},
|
||||||
|
};
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ircd::m::event::append::is_ignored(const event &event,
|
||||||
|
const opts &opts)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
const bool check_ignores
|
||||||
|
{
|
||||||
|
true
|
||||||
|
&& !defined(json::get<"state_key"_>(event))
|
||||||
|
&& opts.user_id
|
||||||
|
&& opts.user_room_id
|
||||||
|
&& opts.user_id != json::get<"sender"_>(event)
|
||||||
|
};
|
||||||
|
|
||||||
|
if(!check_ignores)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const m::user::ignores ignores
|
||||||
|
{
|
||||||
|
opts.user_id
|
||||||
|
};
|
||||||
|
|
||||||
|
if(ignores.enforce("events") && ignores.has(json::get<"sender"_>(event)))
|
||||||
|
{
|
||||||
|
log::debug
|
||||||
|
{
|
||||||
|
log, "Not sending event %s because %s is ignored by %s",
|
||||||
|
string_view{event.event_id},
|
||||||
|
json::get<"sender"_>(event),
|
||||||
|
string_view{opts.user_id}
|
||||||
|
};
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,13 @@
|
||||||
// copyright notice and this permission notice is present in all copies. The
|
// copyright notice and this permission notice is present in all copies. The
|
||||||
// full license for this software is available in the LICENSE file.
|
// full license for this software is available in the LICENSE file.
|
||||||
|
|
||||||
|
decltype(ircd::m::relates::latest_column)
|
||||||
|
ircd::m::relates::latest_column
|
||||||
|
{
|
||||||
|
{ "name", "ircd.m.relates.latest_column" },
|
||||||
|
{ "default", "origin_server_ts" },
|
||||||
|
};
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ircd::m::relates::prefetch(const string_view &type)
|
ircd::m::relates::prefetch(const string_view &type)
|
||||||
const
|
const
|
||||||
|
@ -21,8 +28,8 @@ const
|
||||||
refs.for_each(dbs::ref::M_RELATES, [this, &ret]
|
refs.for_each(dbs::ref::M_RELATES, [this, &ret]
|
||||||
(const auto &event_idx, const auto &)
|
(const auto &event_idx, const auto &)
|
||||||
{
|
{
|
||||||
if(this->prefetch_depth)
|
if(this->prefetch_latest)
|
||||||
ret |= m::prefetch(event_idx, "depth");
|
ret |= m::prefetch(event_idx, string_view{latest_column});
|
||||||
|
|
||||||
if(this->prefetch_sender || this->match_sender)
|
if(this->prefetch_sender || this->match_sender)
|
||||||
ret |= m::prefetch(event_idx, "sender");
|
ret |= m::prefetch(event_idx, "sender");
|
||||||
|
@ -87,6 +94,11 @@ ircd::m::relates::latest(const string_view &type,
|
||||||
uint *const at)
|
uint *const at)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
|
const string_view &column
|
||||||
|
{
|
||||||
|
latest_column
|
||||||
|
};
|
||||||
|
|
||||||
if(at)
|
if(at)
|
||||||
*at = -1;
|
*at = -1;
|
||||||
|
|
||||||
|
@ -97,10 +109,10 @@ const
|
||||||
(const event::idx &event_idx, const json::object &, const m::relates_to &)
|
(const event::idx &event_idx, const json::object &, const m::relates_to &)
|
||||||
noexcept
|
noexcept
|
||||||
{
|
{
|
||||||
int64_t depth{0};
|
int64_t val{0};
|
||||||
if((depth = m::get(std::nothrow, event_idx, "depth", depth)) > best)
|
if((val = m::get(std::nothrow, event_idx, column, val)) > best)
|
||||||
{
|
{
|
||||||
best = depth;
|
best = val;
|
||||||
ret = event_idx;
|
ret = event_idx;
|
||||||
|
|
||||||
if(at)
|
if(at)
|
||||||
|
|
|
@ -246,6 +246,7 @@ const
|
||||||
};
|
};
|
||||||
|
|
||||||
attach_sigs(user_sigs, device_keys, user_id);
|
attach_sigs(user_sigs, device_keys, user_id);
|
||||||
|
|
||||||
const m::room::state state
|
const m::room::state state
|
||||||
{
|
{
|
||||||
user_room
|
user_room
|
||||||
|
@ -299,12 +300,29 @@ const
|
||||||
out, "signatures"
|
out, "signatures"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// signatures of the key's owner
|
||||||
|
assert(user_room.user.user_id);
|
||||||
|
append_sigs(sigs, device_keys, user_room.user.user_id);
|
||||||
|
|
||||||
|
// signatures of a cross-signer
|
||||||
|
assert(user_id);
|
||||||
|
if(user_id != user_room.user.user_id)
|
||||||
|
append_sigs(sigs, device_keys, user_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ircd::m::user::keys::append_sigs(json::stack::object &out,
|
||||||
|
const json::object &device_keys,
|
||||||
|
const user::id &user_id)
|
||||||
|
const
|
||||||
|
{
|
||||||
json::stack::object user_sigs
|
json::stack::object user_sigs
|
||||||
{
|
{
|
||||||
sigs, user_id
|
out, user_id
|
||||||
};
|
};
|
||||||
|
|
||||||
attach_sigs(user_sigs, device_keys, user_id);
|
attach_sigs(user_sigs, device_keys, user_id);
|
||||||
|
|
||||||
const json::object device_keys_keys
|
const json::object device_keys_keys
|
||||||
{
|
{
|
||||||
device_keys["keys"]
|
device_keys["keys"]
|
||||||
|
@ -318,6 +336,11 @@ const
|
||||||
state.for_each("ircd.keys.signatures", [this, &user_sigs, &user_id, &device_keys_keys]
|
state.for_each("ircd.keys.signatures", [this, &user_sigs, &user_id, &device_keys_keys]
|
||||||
(const string_view &, const string_view &state_key, const auto &event_idx)
|
(const string_view &, const string_view &state_key, const auto &event_idx)
|
||||||
{
|
{
|
||||||
|
const auto &[target, source]
|
||||||
|
{
|
||||||
|
unmake_sigs_state_key(state_key)
|
||||||
|
};
|
||||||
|
|
||||||
for(const auto &[key_id_, key] : device_keys_keys)
|
for(const auto &[key_id_, key] : device_keys_keys)
|
||||||
{
|
{
|
||||||
const auto &key_id
|
const auto &key_id
|
||||||
|
@ -325,11 +348,6 @@ const
|
||||||
split(key_id_, ':').second
|
split(key_id_, ':').second
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto &[target, source]
|
|
||||||
{
|
|
||||||
unmake_sigs_state_key(state_key)
|
|
||||||
};
|
|
||||||
|
|
||||||
if(target != key_id)
|
if(target != key_id)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -376,10 +376,10 @@ append_event(json::stack::array &out,
|
||||||
{
|
{
|
||||||
out, event,
|
out, event,
|
||||||
{
|
{
|
||||||
.event_idx = &event_idx,
|
.event_idx = event_idx,
|
||||||
.user_id = &user_room.user.user_id,
|
.user_id = user_room.user.user_id,
|
||||||
.user_room = &user_room,
|
.user_room_id = user_room.room_id,
|
||||||
.room_depth = &room_depth,
|
.room_depth = room_depth,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,9 +228,29 @@ recv_responses(const host_users_map &map,
|
||||||
}
|
}
|
||||||
|
|
||||||
// remote handle
|
// remote handle
|
||||||
for(auto &[remote, request] : queries)
|
while(!queries.empty())
|
||||||
{
|
{
|
||||||
assert(!failures.count(remote));
|
auto next
|
||||||
|
{
|
||||||
|
ctx::when_any(begin(queries), end(queries), []
|
||||||
|
(auto &it) -> m::fed::user::keys::claim &
|
||||||
|
{
|
||||||
|
return it->second;
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
const bool ok
|
||||||
|
{
|
||||||
|
next.wait_until(timeout, std::nothrow)
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto it(next.get());
|
||||||
|
const unwind remove{[&queries, &it]
|
||||||
|
{
|
||||||
|
queries.erase(it);
|
||||||
|
}};
|
||||||
|
|
||||||
|
auto &[remote, request] {*it};
|
||||||
recv_response(remote, request, failures, one_time_keys, timeout);
|
recv_response(remote, request, failures, one_time_keys, timeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,19 +48,21 @@ ircd::m::post_keys_signatures_upload(client &client,
|
||||||
user::tokens::device(std::nothrow, request.access_token)
|
user::tokens::device(std::nothrow, request.access_token)
|
||||||
};
|
};
|
||||||
|
|
||||||
for(const auto &[user_id, device_keys_] : request)
|
for(const auto &[user_id_, device_keys_] : request)
|
||||||
{
|
{
|
||||||
if(!valid(m::id::USER, user_id))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const json::object device_keys
|
const json::object device_keys
|
||||||
{
|
{
|
||||||
device_keys_
|
device_keys_
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const m::user::id user_id
|
||||||
|
{
|
||||||
|
user_id_
|
||||||
|
};
|
||||||
|
|
||||||
const user::room user_room
|
const user::room user_room
|
||||||
{
|
{
|
||||||
user::id{user_id}
|
user_id
|
||||||
};
|
};
|
||||||
|
|
||||||
for(const auto &[tgt_id, keys] : device_keys)
|
for(const auto &[tgt_id, keys] : device_keys)
|
||||||
|
@ -71,7 +73,7 @@ ircd::m::post_keys_signatures_upload(client &client,
|
||||||
user::keys::make_sigs_state_key(state_key_buf, tgt_id, src_dev)
|
user::keys::make_sigs_state_key(state_key_buf, tgt_id, src_dev)
|
||||||
};
|
};
|
||||||
|
|
||||||
send(user_room, user_id, "ircd.keys.signatures", state_key, keys);
|
send(user_room, request.user_id, "ircd.keys.signatures", state_key, keys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -206,7 +206,7 @@ ircd::m::get_notifications(client &client,
|
||||||
{
|
{
|
||||||
event_object, event,
|
event_object, event,
|
||||||
{
|
{
|
||||||
.event_idx = &event_idx,
|
.event_idx = event_idx,
|
||||||
.keys = ¬ification_event_keys,
|
.keys = ¬ification_event_keys,
|
||||||
//.query_txnid = false,
|
//.query_txnid = false,
|
||||||
//.query_prev_state = false,
|
//.query_prev_state = false,
|
||||||
|
|
|
@ -132,10 +132,10 @@ get__context(client &client,
|
||||||
{
|
{
|
||||||
_event, event,
|
_event, event,
|
||||||
{
|
{
|
||||||
.event_idx = &event.event_idx,
|
.event_idx = event.event_idx,
|
||||||
.user_id = &user_room.user.user_id,
|
.user_id = user_room.user.user_id,
|
||||||
.user_room = &user_room,
|
.user_room_id = user_room.room_id,
|
||||||
.room_depth = &room_depth,
|
.room_depth = room_depth,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -179,10 +179,10 @@ get__context(client &client,
|
||||||
{
|
{
|
||||||
array, event,
|
array, event,
|
||||||
{
|
{
|
||||||
.event_idx = &event_idx,
|
.event_idx = event_idx,
|
||||||
.user_id = &user_room.user.user_id,
|
.user_id = user_room.user.user_id,
|
||||||
.user_room = &user_room,
|
.user_room_id = user_room.room_id,
|
||||||
.room_depth = &room_depth,
|
.room_depth = room_depth,
|
||||||
.query_txnid = true,
|
.query_txnid = true,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -233,10 +233,10 @@ get__context(client &client,
|
||||||
{
|
{
|
||||||
array, event,
|
array, event,
|
||||||
{
|
{
|
||||||
.event_idx = &event_idx,
|
.event_idx = event_idx,
|
||||||
.user_id = &user_room.user.user_id,
|
.user_id = user_room.user.user_id,
|
||||||
.user_room = &user_room,
|
.user_room_id = user_room.room_id,
|
||||||
.room_depth = &room_depth,
|
.room_depth = room_depth,
|
||||||
.query_txnid = true,
|
.query_txnid = true,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -301,10 +301,10 @@ get__context(client &client,
|
||||||
{
|
{
|
||||||
array, event,
|
array, event,
|
||||||
{
|
{
|
||||||
.event_idx = &event_idx,
|
.event_idx = event_idx,
|
||||||
.user_id = &user_room.user.user_id,
|
.user_id = user_room.user.user_id,
|
||||||
.user_room = &user_room,
|
.user_room_id = user_room.room_id,
|
||||||
.room_depth = &room_depth,
|
.room_depth = room_depth,
|
||||||
.query_txnid = false,
|
.query_txnid = false,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -46,8 +46,32 @@ get__event(client &client,
|
||||||
event_id, fopts
|
event_id, fopts
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const unique_mutable_buffer buf
|
||||||
|
{
|
||||||
|
m::event::MAX_SIZE
|
||||||
|
};
|
||||||
|
|
||||||
|
json::stack out{buf};
|
||||||
|
{
|
||||||
|
json::stack::object top{out};
|
||||||
|
m::event::append
|
||||||
|
{
|
||||||
|
top, event,
|
||||||
|
{
|
||||||
|
.event_idx = event.event_idx,
|
||||||
|
.user_id = request.user_id,
|
||||||
|
.query_prev_state = false,
|
||||||
|
.query_redacted = false,
|
||||||
|
.query_visible = false,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
return m::resource::response
|
return m::resource::response
|
||||||
{
|
{
|
||||||
client, event.source
|
client, json::object
|
||||||
|
{
|
||||||
|
out.completed()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,10 +202,10 @@ get__initialsync_local(client &client,
|
||||||
{
|
{
|
||||||
state, state_event,
|
state, state_event,
|
||||||
{
|
{
|
||||||
.event_idx = &event_idx,
|
.event_idx = event_idx,
|
||||||
.user_id = &user.user_id,
|
.user_id = user.user_id,
|
||||||
.user_room = &user_room,
|
.user_room_id = user_room.room_id,
|
||||||
.room_depth = &room_depth,
|
.room_depth = room_depth,
|
||||||
.query_txnid = false,
|
.query_txnid = false,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -255,14 +255,17 @@ get__initialsync_local(client &client,
|
||||||
if(!visible(event, user.user_id))
|
if(!visible(event, user.user_id))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
m::event::append(chunk, event,
|
m::event::append
|
||||||
{
|
{
|
||||||
.event_idx = &event_idx,
|
chunk, event,
|
||||||
.user_id = &user.user_id,
|
{
|
||||||
.user_room = &user_room,
|
.event_idx = event_idx,
|
||||||
.room_depth = &room_depth,
|
.user_id = user.user_id,
|
||||||
.query_txnid = true,
|
.user_room_id = user_room.room_id,
|
||||||
});
|
.room_depth = room_depth,
|
||||||
|
.query_txnid = true,
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -165,8 +165,8 @@ get__members(client &client,
|
||||||
{
|
{
|
||||||
chunk, event,
|
chunk, event,
|
||||||
{
|
{
|
||||||
.event_idx = &event_idx,
|
.event_idx = event_idx,
|
||||||
.user_id = &request.user_id,
|
.user_id = request.user_id,
|
||||||
.query_txnid = false,
|
.query_txnid = false,
|
||||||
.query_prev_state = false,
|
.query_prev_state = false,
|
||||||
.query_redacted = false,
|
.query_redacted = false,
|
||||||
|
|
|
@ -152,10 +152,10 @@ get__messages(client &client,
|
||||||
{
|
{
|
||||||
chunk, event,
|
chunk, event,
|
||||||
{
|
{
|
||||||
.event_idx = &event_idx,
|
.event_idx = event_idx,
|
||||||
.user_id = &user_room.user.user_id,
|
.user_id = user_room.user.user_id,
|
||||||
.user_room = &user_room,
|
.user_room_id = user_room.room_id,
|
||||||
.room_depth = &room_depth,
|
.room_depth = room_depth,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -174,8 +174,8 @@ relations_chunk_append(client &client,
|
||||||
{
|
{
|
||||||
chunk, event,
|
chunk, event,
|
||||||
{
|
{
|
||||||
.event_idx = &event_idx,
|
.event_idx = event_idx,
|
||||||
.user_id = &request.user_id,
|
.user_id = request.user_id,
|
||||||
.query_txnid = false,
|
.query_txnid = false,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -206,8 +206,8 @@ append_event(const m::resource::request &request,
|
||||||
{
|
{
|
||||||
array, event,
|
array, event,
|
||||||
{
|
{
|
||||||
.event_idx = &event_idx,
|
.event_idx = event_idx,
|
||||||
.user_id = &request.user_id,
|
.user_id = request.user_id,
|
||||||
.query_txnid = false,
|
.query_txnid = false,
|
||||||
.query_prev_state = false,
|
.query_prev_state = false,
|
||||||
.query_redacted = false,
|
.query_redacted = false,
|
||||||
|
|
|
@ -550,8 +550,8 @@ try
|
||||||
{
|
{
|
||||||
result_event, event,
|
result_event, event,
|
||||||
{
|
{
|
||||||
.event_idx = &result.event_idx,
|
.event_idx = result.event_idx,
|
||||||
.user_id = &query.user_id,
|
.user_id = query.user_id,
|
||||||
.event_filter = &event_filter,
|
.event_filter = &event_filter,
|
||||||
.query_prev_state = false,
|
.query_prev_state = false,
|
||||||
.query_visible = true,
|
.query_visible = true,
|
||||||
|
@ -599,8 +599,8 @@ try
|
||||||
{
|
{
|
||||||
events_before, event,
|
events_before, event,
|
||||||
{
|
{
|
||||||
.event_idx = &event_idx,
|
.event_idx = event_idx,
|
||||||
.user_id = &query.user_id,
|
.user_id = query.user_id,
|
||||||
.event_filter = &event_filter,
|
.event_filter = &event_filter,
|
||||||
.query_prev_state = false,
|
.query_prev_state = false,
|
||||||
.query_visible = true,
|
.query_visible = true,
|
||||||
|
@ -628,8 +628,8 @@ try
|
||||||
{
|
{
|
||||||
events_after, event,
|
events_after, event,
|
||||||
{
|
{
|
||||||
.event_idx = &event_idx,
|
.event_idx = event_idx,
|
||||||
.user_id = &query.user_id,
|
.user_id = query.user_id,
|
||||||
.event_filter = &event_filter,
|
.event_filter = &event_filter,
|
||||||
.query_prev_state = false,
|
.query_prev_state = false,
|
||||||
.query_visible = true,
|
.query_visible = true,
|
||||||
|
|
|
@ -221,10 +221,10 @@ ircd::m::sync::room_state_linear_events(data &data)
|
||||||
{
|
{
|
||||||
array, event,
|
array, event,
|
||||||
{
|
{
|
||||||
.event_idx = &event_idx,
|
.event_idx = event_idx,
|
||||||
.user_id = &data.user.user_id,
|
.user_id = data.user.user_id,
|
||||||
.user_room = &data.user_room,
|
.user_room_id = data.user_room.room_id,
|
||||||
.room_depth = &data.room_depth,
|
.room_depth = data.room_depth,
|
||||||
.query_txnid = false,
|
.query_txnid = false,
|
||||||
.query_prev_state = true,
|
.query_prev_state = true,
|
||||||
}
|
}
|
||||||
|
@ -265,10 +265,10 @@ ircd::m::sync::room_state_linear_events(data &data)
|
||||||
{
|
{
|
||||||
array, *data.event,
|
array, *data.event,
|
||||||
{
|
{
|
||||||
.event_idx = &data.event_idx,
|
.event_idx = data.event_idx,
|
||||||
.user_id = &data.user.user_id,
|
.user_id = data.user.user_id,
|
||||||
.user_room = &data.user_room,
|
.user_room_id = data.user_room.room_id,
|
||||||
.room_depth = &data.room_depth,
|
.room_depth = data.room_depth,
|
||||||
.query_txnid = false,
|
.query_txnid = false,
|
||||||
.query_prev_state = true,
|
.query_prev_state = true,
|
||||||
}
|
}
|
||||||
|
@ -377,10 +377,10 @@ ircd::m::sync::room_state_polylog_events(data &data)
|
||||||
{
|
{
|
||||||
array, event,
|
array, event,
|
||||||
{
|
{
|
||||||
.event_idx = &event_idx,
|
.event_idx = event_idx,
|
||||||
.user_id = &data.user.user_id,
|
.user_id = data.user.user_id,
|
||||||
.user_room = &data.user_room,
|
.user_room_id = data.user_room.room_id,
|
||||||
.room_depth = &data.room_depth,
|
.room_depth = data.room_depth,
|
||||||
.query_txnid = false,
|
.query_txnid = false,
|
||||||
.query_prev_state = false,
|
.query_prev_state = false,
|
||||||
}
|
}
|
||||||
|
@ -517,10 +517,10 @@ ircd::m::sync::room_state_phased_events(data &data)
|
||||||
{
|
{
|
||||||
array, event,
|
array, event,
|
||||||
{
|
{
|
||||||
.event_idx = &event_idx,
|
.event_idx = event_idx,
|
||||||
.user_id = &data.user.user_id,
|
.user_id = data.user.user_id,
|
||||||
.user_room = &data.user_room,
|
.user_room_id = data.user_room.room_id,
|
||||||
.room_depth = &data.room_depth,
|
.room_depth = data.room_depth,
|
||||||
.query_txnid = false,
|
.query_txnid = false,
|
||||||
.query_prev_state = true,
|
.query_prev_state = true,
|
||||||
}
|
}
|
||||||
|
@ -664,10 +664,10 @@ ircd::m::sync::room_state_phased_member_events(data &data,
|
||||||
{
|
{
|
||||||
array, event,
|
array, event,
|
||||||
{
|
{
|
||||||
.event_idx = &sender_idx,
|
.event_idx = sender_idx,
|
||||||
.user_id = &data.user.user_id,
|
.user_id = data.user.user_id,
|
||||||
.user_room = &data.user_room,
|
.user_room_id = data.user_room.room_id,
|
||||||
.room_depth = &data.room_depth,
|
.room_depth = data.room_depth,
|
||||||
.query_txnid = false,
|
.query_txnid = false,
|
||||||
.query_prev_state = false,
|
.query_prev_state = false,
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,11 +212,11 @@ ircd::m::sync::room_timeline_linear(data &data)
|
||||||
{
|
{
|
||||||
array, *data.event,
|
array, *data.event,
|
||||||
{
|
{
|
||||||
.event_idx = &data.event_idx,
|
.event_idx = data.event_idx,
|
||||||
.client_txnid = &data.client_txnid,
|
.client_txnid = data.client_txnid,
|
||||||
.user_id = &data.user.user_id,
|
.user_id = data.user.user_id,
|
||||||
.user_room = &data.user_room,
|
.user_room_id = data.user_room.room_id,
|
||||||
.room_depth = &data.room_depth,
|
.room_depth = data.room_depth,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -289,11 +289,11 @@ ircd::m::sync::_room_timeline_linear_command(data &data)
|
||||||
{
|
{
|
||||||
array, *data.event,
|
array, *data.event,
|
||||||
{
|
{
|
||||||
.event_idx = &data.event_idx,
|
.event_idx = data.event_idx,
|
||||||
.client_txnid = &data.client_txnid,
|
.client_txnid = data.client_txnid,
|
||||||
.user_id = &data.user.user_id,
|
.user_id = data.user.user_id,
|
||||||
.user_room = &data.user_room,
|
.user_room_id = data.user_room.room_id,
|
||||||
.room_depth = &data.room_depth,
|
.room_depth = data.room_depth,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -400,11 +400,11 @@ ircd::m::sync::_room_timeline_polylog_events(data &data,
|
||||||
{
|
{
|
||||||
array, event,
|
array, event,
|
||||||
{
|
{
|
||||||
.event_idx = &event_idx,
|
.event_idx = event_idx,
|
||||||
.client_txnid = &data.client_txnid,
|
.client_txnid = data.client_txnid,
|
||||||
.user_id = &data.user.user_id,
|
.user_id = data.user.user_id,
|
||||||
.user_room = &data.user_room,
|
.user_room_id = data.user_room.room_id,
|
||||||
.room_depth = &data.room_depth,
|
.room_depth = data.room_depth,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,17 +43,17 @@ get_user(client &client,
|
||||||
url::decode(user_id, request.parv[0])
|
url::decode(user_id, request.parv[0])
|
||||||
};
|
};
|
||||||
|
|
||||||
if(request.user_id != user_id)
|
|
||||||
throw m::UNSUPPORTED
|
|
||||||
{
|
|
||||||
"Getting user data as someone else is not yet supported"
|
|
||||||
};
|
|
||||||
|
|
||||||
const string_view &cmd
|
const string_view &cmd
|
||||||
{
|
{
|
||||||
request.parv[1]
|
request.parv[1]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if(request.user_id != user_id && !request.bridge_id)
|
||||||
|
throw m::UNSUPPORTED
|
||||||
|
{
|
||||||
|
"Getting user data as someone else is only for bridges."
|
||||||
|
};
|
||||||
|
|
||||||
if(cmd == "filter")
|
if(cmd == "filter")
|
||||||
return get__filter(client, request, user_id);
|
return get__filter(client, request, user_id);
|
||||||
|
|
||||||
|
@ -93,10 +93,10 @@ post_user(client &client,
|
||||||
url::decode(user_id, request.parv[0])
|
url::decode(user_id, request.parv[0])
|
||||||
};
|
};
|
||||||
|
|
||||||
if(request.user_id != user_id)
|
if(request.user_id != user_id && !request.bridge_id)
|
||||||
throw m::UNSUPPORTED
|
throw m::UNSUPPORTED
|
||||||
{
|
{
|
||||||
"Posting user data as someone else is not yet supported"
|
"Posting user data as someone else is only for bridges."
|
||||||
};
|
};
|
||||||
|
|
||||||
const string_view &cmd
|
const string_view &cmd
|
||||||
|
@ -140,10 +140,10 @@ put_user(client &client,
|
||||||
url::decode(user_id, request.parv[0])
|
url::decode(user_id, request.parv[0])
|
||||||
};
|
};
|
||||||
|
|
||||||
if(request.user_id != user_id)
|
if(request.user_id != user_id && !request.bridge_id)
|
||||||
throw m::UNSUPPORTED
|
throw m::UNSUPPORTED
|
||||||
{
|
{
|
||||||
"Putting user data as someone else is not yet supported"
|
"Putting user data as someone else is only for bridges."
|
||||||
};
|
};
|
||||||
|
|
||||||
if(request.parv.size() < 2)
|
if(request.parv.size() < 2)
|
||||||
|
@ -193,10 +193,10 @@ delete_user(client &client,
|
||||||
url::decode(user_id, request.parv[0])
|
url::decode(user_id, request.parv[0])
|
||||||
};
|
};
|
||||||
|
|
||||||
if(request.user_id != user_id)
|
if(request.user_id != user_id && !request.bridge_id)
|
||||||
throw m::UNSUPPORTED
|
throw m::UNSUPPORTED
|
||||||
{
|
{
|
||||||
"Deleting user data as someone else is not yet supported"
|
"Deleting user data as someone else is only for bridges."
|
||||||
};
|
};
|
||||||
|
|
||||||
if(request.parv.size() < 2)
|
if(request.parv.size() < 2)
|
||||||
|
|
|
@ -677,14 +677,15 @@ ircd::m::bridge::append(const config &config,
|
||||||
const event::idx &event_idx,
|
const event::idx &event_idx,
|
||||||
const event &event)
|
const event &event)
|
||||||
{
|
{
|
||||||
event::append::opts opts;
|
|
||||||
opts.event_idx = &event_idx;
|
|
||||||
opts.query_txnid = false;
|
|
||||||
opts.query_prev_state = true;
|
|
||||||
opts.query_redacted = false;
|
|
||||||
event::append
|
event::append
|
||||||
{
|
{
|
||||||
events, event, opts
|
events, event, event::append::opts
|
||||||
|
{
|
||||||
|
.event_idx = event_idx,
|
||||||
|
.query_txnid = false,
|
||||||
|
.query_prev_state = true,
|
||||||
|
.query_redacted = false,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
log::debug
|
log::debug
|
||||||
|
|
|
@ -174,6 +174,10 @@ static bool
|
||||||
github_handle__push(std::ostream &,
|
github_handle__push(std::ostream &,
|
||||||
const json::object &content);
|
const json::object &content);
|
||||||
|
|
||||||
|
static bool
|
||||||
|
github_post_handle__push(const m::event::id &,
|
||||||
|
const json::object &content);
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
github_handle__pull_request(std::ostream &,
|
github_handle__pull_request(std::ostream &,
|
||||||
const json::object &content);
|
const json::object &content);
|
||||||
|
@ -355,6 +359,9 @@ github_handle(client &client,
|
||||||
m::msghtml(room_id, user_id, view(out, buf[0]), view(alt, buf[1]), "m.notice")
|
m::msghtml(room_id, user_id, view(out, buf[0]), view(alt, buf[1]), "m.notice")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if(type == "push")
|
||||||
|
github_post_handle__push(evid, request.content);
|
||||||
|
|
||||||
log::info
|
log::info
|
||||||
{
|
{
|
||||||
"Webhook [%s] '%s' delivered to %s %s",
|
"Webhook [%s] '%s' delivered to %s %s",
|
||||||
|
@ -933,6 +940,33 @@ github_hook_shot_retry(const string_view &repo,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
github_hook_shot_for_each_fail(const string_view &repo,
|
||||||
|
const string_view &hook,
|
||||||
|
const function_bool<json::object> &closure)
|
||||||
|
{
|
||||||
|
bool ret {true};
|
||||||
|
github_hook_shot_for_each(repo, hook, true, [&ret, &closure]
|
||||||
|
(const json::object &object)
|
||||||
|
{
|
||||||
|
if(object.at<bool>("redelivery"))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
const json::string status
|
||||||
|
{
|
||||||
|
object["status"]
|
||||||
|
};
|
||||||
|
|
||||||
|
if(status == "OK")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ret = closure(object);
|
||||||
|
return ret;
|
||||||
|
});
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
github_run_for_each_jobs(const string_view &repo,
|
github_run_for_each_jobs(const string_view &repo,
|
||||||
const string_view &run_id,
|
const string_view &run_id,
|
||||||
|
@ -992,6 +1026,59 @@ github_run_rerun_failed(const string_view &repo,
|
||||||
github_request(buf, "POST", repo, "actions/runs/%s/rerun-failed-jobs", run_id);
|
github_request(buf, "POST", repo, "actions/runs/%s/rerun-failed-jobs", run_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
github_run_dispatch(const string_view &repo,
|
||||||
|
const string_view &name,
|
||||||
|
const string_view &ref = "master",
|
||||||
|
const json::members inputs = {})
|
||||||
|
{
|
||||||
|
const json::strung content{json::members
|
||||||
|
{
|
||||||
|
{ "ref", ref },
|
||||||
|
{ "inputs", inputs },
|
||||||
|
}};
|
||||||
|
|
||||||
|
unique_const_buffer buf;
|
||||||
|
github_request(content, buf, "POST", repo, "actions/workflows/%s/dispatches", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
github_flow_for_each(const string_view &repo,
|
||||||
|
const function_bool<json::object> &closure,
|
||||||
|
const bool active_only = true)
|
||||||
|
{
|
||||||
|
unique_const_buffer buf;
|
||||||
|
const json::object response
|
||||||
|
{
|
||||||
|
github_request
|
||||||
|
(
|
||||||
|
//TODO: pagination token
|
||||||
|
buf, "GET", repo, "actions/workflows?per_page=100&page=1"
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
const json::array workflows
|
||||||
|
{
|
||||||
|
response["workflows"]
|
||||||
|
};
|
||||||
|
|
||||||
|
for(const json::object flow : workflows)
|
||||||
|
{
|
||||||
|
const json::string state
|
||||||
|
{
|
||||||
|
flow["state"]
|
||||||
|
};
|
||||||
|
|
||||||
|
if(active_only && state != "active")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(!closure(flow))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
github_handle__workflow_run(std::ostream &out,
|
github_handle__workflow_run(std::ostream &out,
|
||||||
std::ostream &alt,
|
std::ostream &alt,
|
||||||
|
@ -1511,40 +1598,77 @@ try
|
||||||
json::object{relates_content}.get("body")
|
json::object{relates_content}.get("body")
|
||||||
};
|
};
|
||||||
|
|
||||||
if(!startswith(relates_body, "job status table "))
|
if(startswith(relates_body, "job status table "))
|
||||||
return;
|
|
||||||
|
|
||||||
const auto suffix
|
|
||||||
{
|
{
|
||||||
lstrip(relates_body, "job status table ")
|
const auto suffix
|
||||||
};
|
{
|
||||||
|
lstrip(relates_body, "job status table ")
|
||||||
|
};
|
||||||
|
|
||||||
string_view token[3];
|
string_view token[3];
|
||||||
ircd::tokens(suffix, ' ', token);
|
ircd::tokens(suffix, ' ', token);
|
||||||
const auto &[repopath, run_id, attempt] {token};
|
const auto &[repopath, run_id, attempt] {token};
|
||||||
assert(repopath);
|
assert(repopath);
|
||||||
assert(run_id);
|
assert(run_id);
|
||||||
if(!repopath || !run_id)
|
if(!repopath || !run_id)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch(hash(key))
|
switch(hash(key))
|
||||||
|
{
|
||||||
|
case hash("🚮"_sv):
|
||||||
|
github_run_delete(repopath, run_id);
|
||||||
|
m::redact(room, user_id, relates_event_id, "deleted");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case hash("⭕"_sv):
|
||||||
|
github_run_cancel(repopath, run_id);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case hash("🔄"_sv):
|
||||||
|
github_run_rerun_failed(repopath, run_id);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case hash("↪️"_sv):
|
||||||
|
github_run_rerun(repopath, run_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(startswith(relates_body, "push by "))
|
||||||
{
|
{
|
||||||
case hash("🚮"_sv):
|
const auto suffix
|
||||||
github_run_delete(repopath, run_id);
|
{
|
||||||
m::redact(room, user_id, relates_event_id, "deleted");
|
lstrip(relates_body, "push by ")
|
||||||
break;
|
};
|
||||||
|
|
||||||
case hash("⭕"_sv):
|
string_view token[5];
|
||||||
github_run_cancel(repopath, run_id);
|
ircd::tokens(suffix, ' ', token);
|
||||||
break;
|
const auto &[pusher, _by_, repo, _at_, commit] {token};
|
||||||
|
assert(pusher);
|
||||||
|
assert(repo);
|
||||||
|
assert(commit);
|
||||||
|
if(!repo)
|
||||||
|
return;
|
||||||
|
|
||||||
case hash("🔄"_sv):
|
if(startswith(key, "▶️"))
|
||||||
github_run_rerun_failed(repopath, run_id);
|
{
|
||||||
break;
|
const auto id
|
||||||
|
{
|
||||||
|
between(key, '(', ')')
|
||||||
|
};
|
||||||
|
|
||||||
case hash("↪️"_sv):
|
const auto ref
|
||||||
github_run_rerun(repopath, run_id);
|
{
|
||||||
break;
|
// commit // hash not supported by github
|
||||||
|
"master"
|
||||||
|
};
|
||||||
|
|
||||||
|
github_run_dispatch(repo, id, ref, json::members
|
||||||
|
{
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(const ctx::interrupted &)
|
catch(const ctx::interrupted &)
|
||||||
|
@ -1864,6 +1988,54 @@ github_handle__push(std::ostream &out,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
github_post_handle__push(const m::event::id &push_event_id,
|
||||||
|
const json::object &content)
|
||||||
|
{
|
||||||
|
const m::user::id::buf _webhook_user
|
||||||
|
{
|
||||||
|
string_view{webhook_user}, my_host()
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto _webhook_room
|
||||||
|
{
|
||||||
|
m::room_id(string_view(webhook_room))
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto repo
|
||||||
|
{
|
||||||
|
github_repopath(content)
|
||||||
|
};
|
||||||
|
|
||||||
|
github_flow_for_each(repo, [&]
|
||||||
|
(const json::object &flow)
|
||||||
|
{
|
||||||
|
const json::string name
|
||||||
|
{
|
||||||
|
flow["name"]
|
||||||
|
};
|
||||||
|
|
||||||
|
const json::string id
|
||||||
|
{
|
||||||
|
flow["id"]
|
||||||
|
};
|
||||||
|
|
||||||
|
const fmt::bsprintf<128> key
|
||||||
|
{
|
||||||
|
"▶️ %s (%s)", name, id
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto annote_id
|
||||||
|
{
|
||||||
|
m::annotate(_webhook_room, _webhook_user, push_event_id, string_view(key))
|
||||||
|
};
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
github_handle__pull_request(std::ostream &out,
|
github_handle__pull_request(std::ostream &out,
|
||||||
const json::object &content)
|
const json::object &content)
|
||||||
|
|
Loading…
Reference in a new issue