Add admin command to list last-active local users.
Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
20
Cargo.lock
generated
20
Cargo.lock
generated
@@ -3680,7 +3680,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma"
|
||||
version = "0.13.0"
|
||||
source = "git+https://github.com/matrix-construct/ruma?rev=ff66bdd9975152f0382d753120dddddf3577ad51#ff66bdd9975152f0382d753120dddddf3577ad51"
|
||||
source = "git+https://github.com/matrix-construct/ruma?rev=54f56d7df454f7b4036386ff2ade6e11ab8af7de#54f56d7df454f7b4036386ff2ade6e11ab8af7de"
|
||||
dependencies = [
|
||||
"assign",
|
||||
"js_int",
|
||||
@@ -3699,7 +3699,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-appservice-api"
|
||||
version = "0.13.0"
|
||||
source = "git+https://github.com/matrix-construct/ruma?rev=ff66bdd9975152f0382d753120dddddf3577ad51#ff66bdd9975152f0382d753120dddddf3577ad51"
|
||||
source = "git+https://github.com/matrix-construct/ruma?rev=54f56d7df454f7b4036386ff2ade6e11ab8af7de#54f56d7df454f7b4036386ff2ade6e11ab8af7de"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"ruma-common",
|
||||
@@ -3711,7 +3711,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-client-api"
|
||||
version = "0.21.0"
|
||||
source = "git+https://github.com/matrix-construct/ruma?rev=ff66bdd9975152f0382d753120dddddf3577ad51#ff66bdd9975152f0382d753120dddddf3577ad51"
|
||||
source = "git+https://github.com/matrix-construct/ruma?rev=54f56d7df454f7b4036386ff2ade6e11ab8af7de#54f56d7df454f7b4036386ff2ade6e11ab8af7de"
|
||||
dependencies = [
|
||||
"as_variant",
|
||||
"assign",
|
||||
@@ -3736,7 +3736,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-common"
|
||||
version = "0.16.0"
|
||||
source = "git+https://github.com/matrix-construct/ruma?rev=ff66bdd9975152f0382d753120dddddf3577ad51#ff66bdd9975152f0382d753120dddddf3577ad51"
|
||||
source = "git+https://github.com/matrix-construct/ruma?rev=54f56d7df454f7b4036386ff2ade6e11ab8af7de#54f56d7df454f7b4036386ff2ade6e11ab8af7de"
|
||||
dependencies = [
|
||||
"as_variant",
|
||||
"base64",
|
||||
@@ -3770,7 +3770,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-events"
|
||||
version = "0.31.0"
|
||||
source = "git+https://github.com/matrix-construct/ruma?rev=ff66bdd9975152f0382d753120dddddf3577ad51#ff66bdd9975152f0382d753120dddddf3577ad51"
|
||||
source = "git+https://github.com/matrix-construct/ruma?rev=54f56d7df454f7b4036386ff2ade6e11ab8af7de#54f56d7df454f7b4036386ff2ade6e11ab8af7de"
|
||||
dependencies = [
|
||||
"as_variant",
|
||||
"indexmap",
|
||||
@@ -3797,7 +3797,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-federation-api"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/matrix-construct/ruma?rev=ff66bdd9975152f0382d753120dddddf3577ad51#ff66bdd9975152f0382d753120dddddf3577ad51"
|
||||
source = "git+https://github.com/matrix-construct/ruma?rev=54f56d7df454f7b4036386ff2ade6e11ab8af7de#54f56d7df454f7b4036386ff2ade6e11ab8af7de"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"headers",
|
||||
@@ -3820,7 +3820,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-identifiers-validation"
|
||||
version = "0.11.0"
|
||||
source = "git+https://github.com/matrix-construct/ruma?rev=ff66bdd9975152f0382d753120dddddf3577ad51#ff66bdd9975152f0382d753120dddddf3577ad51"
|
||||
source = "git+https://github.com/matrix-construct/ruma?rev=54f56d7df454f7b4036386ff2ade6e11ab8af7de#54f56d7df454f7b4036386ff2ade6e11ab8af7de"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"thiserror 2.0.18",
|
||||
@@ -3829,7 +3829,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-macros"
|
||||
version = "0.16.0"
|
||||
source = "git+https://github.com/matrix-construct/ruma?rev=ff66bdd9975152f0382d753120dddddf3577ad51#ff66bdd9975152f0382d753120dddddf3577ad51"
|
||||
source = "git+https://github.com/matrix-construct/ruma?rev=54f56d7df454f7b4036386ff2ade6e11ab8af7de#54f56d7df454f7b4036386ff2ade6e11ab8af7de"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"proc-macro-crate",
|
||||
@@ -3844,7 +3844,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-push-gateway-api"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/matrix-construct/ruma?rev=ff66bdd9975152f0382d753120dddddf3577ad51#ff66bdd9975152f0382d753120dddddf3577ad51"
|
||||
source = "git+https://github.com/matrix-construct/ruma?rev=54f56d7df454f7b4036386ff2ade6e11ab8af7de#54f56d7df454f7b4036386ff2ade6e11ab8af7de"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"ruma-common",
|
||||
@@ -3856,7 +3856,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-signatures"
|
||||
version = "0.18.0"
|
||||
source = "git+https://github.com/matrix-construct/ruma?rev=ff66bdd9975152f0382d753120dddddf3577ad51#ff66bdd9975152f0382d753120dddddf3577ad51"
|
||||
source = "git+https://github.com/matrix-construct/ruma?rev=54f56d7df454f7b4036386ff2ade6e11ab8af7de#54f56d7df454f7b4036386ff2ade6e11ab8af7de"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"ed25519-dalek",
|
||||
|
||||
@@ -327,7 +327,7 @@ default-features = false
|
||||
|
||||
[workspace.dependencies.ruma]
|
||||
git = "https://github.com/matrix-construct/ruma"
|
||||
rev = "ff66bdd9975152f0382d753120dddddf3577ad51"
|
||||
rev = "54f56d7df454f7b4036386ff2ade6e11ab8af7de"
|
||||
features = [
|
||||
"__compat",
|
||||
"appservice-api-c",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::{cmp, collections::BTreeMap};
|
||||
|
||||
use futures::{FutureExt, StreamExt};
|
||||
use futures::{FutureExt, StreamExt, TryStreamExt};
|
||||
use ruma::{
|
||||
Int, OwnedDeviceId, OwnedEventId, OwnedRoomId, OwnedRoomOrAliasId, OwnedUserId, UserId,
|
||||
events::{
|
||||
@@ -11,11 +11,12 @@ use ruma::{
|
||||
},
|
||||
tag::{TagEvent, TagEventContent, TagInfo},
|
||||
},
|
||||
uint,
|
||||
};
|
||||
use tuwunel_core::{
|
||||
Err, Result, debug_warn, info,
|
||||
matrix::{Event, pdu::PduBuilder},
|
||||
utils::{self, ReadyExt},
|
||||
utils::{self, ReadyExt, stream::IterStream},
|
||||
};
|
||||
use tuwunel_service::{Services, users::Register};
|
||||
|
||||
@@ -885,3 +886,39 @@ pub(super) async fn redact_event(&self, event_id: OwnedEventId) -> Result {
|
||||
))
|
||||
.await
|
||||
}
|
||||
|
||||
#[admin_command]
|
||||
pub(super) async fn last_active(&self, limit: Option<usize>) -> Result {
|
||||
self.services
|
||||
.users
|
||||
.list_local_users()
|
||||
.map(ToOwned::to_owned)
|
||||
.then(async |user_id| {
|
||||
self.services
|
||||
.users
|
||||
.all_devices_metadata(&user_id)
|
||||
.ready_filter_map(|device| device.last_seen_ts)
|
||||
.ready_fold_default(cmp::max)
|
||||
.map(|last_seen_ts| (last_seen_ts, user_id.clone()))
|
||||
.await
|
||||
})
|
||||
.ready_filter(|(ts, _)| ts.get() > uint!(0))
|
||||
.collect::<Vec<_>>()
|
||||
.map(|mut vec| {
|
||||
vec.sort_by(|a, b| b.0.cmp(&a.0));
|
||||
vec
|
||||
})
|
||||
.map(Vec::into_iter)
|
||||
.map(IterStream::try_stream)
|
||||
.flatten_stream()
|
||||
.take(limit.unwrap_or(48))
|
||||
.try_for_each(async |(last_seen_ts, user_id)| {
|
||||
let ago = last_seen_ts;
|
||||
let user_id = user_id.localpart();
|
||||
let line = format!("{ago:?} {user_id}\n");
|
||||
|
||||
self.write_str(&line).await
|
||||
})
|
||||
.boxed()
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -65,6 +65,12 @@ pub(super) enum UserCommand {
|
||||
device_id: OwnedDeviceId,
|
||||
},
|
||||
|
||||
/// - List local users by recent activity.
|
||||
LastActive {
|
||||
#[arg(short, long)]
|
||||
limit: Option<usize>,
|
||||
},
|
||||
|
||||
/// - List local users in the database
|
||||
#[clap(alias = "list")]
|
||||
ListUsers,
|
||||
|
||||
Reference in New Issue
Block a user