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]]
|
[[package]]
|
||||||
name = "ruma"
|
name = "ruma"
|
||||||
version = "0.13.0"
|
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 = [
|
dependencies = [
|
||||||
"assign",
|
"assign",
|
||||||
"js_int",
|
"js_int",
|
||||||
@@ -3699,7 +3699,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-appservice-api"
|
name = "ruma-appservice-api"
|
||||||
version = "0.13.0"
|
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 = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"ruma-common",
|
"ruma-common",
|
||||||
@@ -3711,7 +3711,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-client-api"
|
name = "ruma-client-api"
|
||||||
version = "0.21.0"
|
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 = [
|
dependencies = [
|
||||||
"as_variant",
|
"as_variant",
|
||||||
"assign",
|
"assign",
|
||||||
@@ -3736,7 +3736,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-common"
|
name = "ruma-common"
|
||||||
version = "0.16.0"
|
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 = [
|
dependencies = [
|
||||||
"as_variant",
|
"as_variant",
|
||||||
"base64",
|
"base64",
|
||||||
@@ -3770,7 +3770,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-events"
|
name = "ruma-events"
|
||||||
version = "0.31.0"
|
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 = [
|
dependencies = [
|
||||||
"as_variant",
|
"as_variant",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
@@ -3797,7 +3797,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-federation-api"
|
name = "ruma-federation-api"
|
||||||
version = "0.12.0"
|
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 = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"headers",
|
"headers",
|
||||||
@@ -3820,7 +3820,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-identifiers-validation"
|
name = "ruma-identifiers-validation"
|
||||||
version = "0.11.0"
|
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 = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"thiserror 2.0.18",
|
"thiserror 2.0.18",
|
||||||
@@ -3829,7 +3829,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-macros"
|
name = "ruma-macros"
|
||||||
version = "0.16.0"
|
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 = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
@@ -3844,7 +3844,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-push-gateway-api"
|
name = "ruma-push-gateway-api"
|
||||||
version = "0.12.0"
|
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 = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"ruma-common",
|
"ruma-common",
|
||||||
@@ -3856,7 +3856,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-signatures"
|
name = "ruma-signatures"
|
||||||
version = "0.18.0"
|
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 = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"ed25519-dalek",
|
"ed25519-dalek",
|
||||||
|
|||||||
@@ -327,7 +327,7 @@ default-features = false
|
|||||||
|
|
||||||
[workspace.dependencies.ruma]
|
[workspace.dependencies.ruma]
|
||||||
git = "https://github.com/matrix-construct/ruma"
|
git = "https://github.com/matrix-construct/ruma"
|
||||||
rev = "ff66bdd9975152f0382d753120dddddf3577ad51"
|
rev = "54f56d7df454f7b4036386ff2ade6e11ab8af7de"
|
||||||
features = [
|
features = [
|
||||||
"__compat",
|
"__compat",
|
||||||
"appservice-api-c",
|
"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::{
|
use ruma::{
|
||||||
Int, OwnedDeviceId, OwnedEventId, OwnedRoomId, OwnedRoomOrAliasId, OwnedUserId, UserId,
|
Int, OwnedDeviceId, OwnedEventId, OwnedRoomId, OwnedRoomOrAliasId, OwnedUserId, UserId,
|
||||||
events::{
|
events::{
|
||||||
@@ -11,11 +11,12 @@ use ruma::{
|
|||||||
},
|
},
|
||||||
tag::{TagEvent, TagEventContent, TagInfo},
|
tag::{TagEvent, TagEventContent, TagInfo},
|
||||||
},
|
},
|
||||||
|
uint,
|
||||||
};
|
};
|
||||||
use tuwunel_core::{
|
use tuwunel_core::{
|
||||||
Err, Result, debug_warn, info,
|
Err, Result, debug_warn, info,
|
||||||
matrix::{Event, pdu::PduBuilder},
|
matrix::{Event, pdu::PduBuilder},
|
||||||
utils::{self, ReadyExt},
|
utils::{self, ReadyExt, stream::IterStream},
|
||||||
};
|
};
|
||||||
use tuwunel_service::{Services, users::Register};
|
use tuwunel_service::{Services, users::Register};
|
||||||
|
|
||||||
@@ -885,3 +886,39 @@ pub(super) async fn redact_event(&self, event_id: OwnedEventId) -> Result {
|
|||||||
))
|
))
|
||||||
.await
|
.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,
|
device_id: OwnedDeviceId,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// - List local users by recent activity.
|
||||||
|
LastActive {
|
||||||
|
#[arg(short, long)]
|
||||||
|
limit: Option<usize>,
|
||||||
|
},
|
||||||
|
|
||||||
/// - List local users in the database
|
/// - List local users in the database
|
||||||
#[clap(alias = "list")]
|
#[clap(alias = "list")]
|
||||||
ListUsers,
|
ListUsers,
|
||||||
|
|||||||
Reference in New Issue
Block a user