Skip to content

Commit 815ce17

Browse files
committed
Simple CLI commands to manage server admins
1 parent 5d1dc0b commit 815ce17

File tree

2 files changed

+116
-2
lines changed

2 files changed

+116
-2
lines changed

crates/cli/src/commands/manage.rs

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,17 @@ use mas_data_model::{Clock, Device, SystemClock, TokenType, Ulid, UpstreamOAuthP
1919
use mas_email::Address;
2020
use mas_matrix::HomeserverConnection;
2121
use mas_storage::{
22-
RepositoryAccess,
22+
Pagination, RepositoryAccess,
2323
compat::{CompatAccessTokenRepository, CompatSessionFilter, CompatSessionRepository},
2424
oauth2::OAuth2SessionFilter,
2525
queue::{
2626
DeactivateUserJob, ProvisionUserJob, QueueJobRepositoryExt as _, ReactivateUserJob,
2727
SyncDevicesJob,
2828
},
29-
user::{BrowserSessionFilter, UserEmailRepository, UserPasswordRepository, UserRepository},
29+
user::{
30+
BrowserSessionFilter, UserEmailRepository, UserFilter, UserPasswordRepository,
31+
UserRepository,
32+
},
3033
};
3134
use mas_storage_pg::{DatabaseError, PgRepository};
3235
use rand::{
@@ -85,6 +88,15 @@ enum Subcommand {
8588
ignore_complexity: bool,
8689
},
8790

91+
/// Make a user admin
92+
PromoteAdmin { username: String },
93+
94+
/// Make a user non-admin
95+
DemoteAdmin { username: String },
96+
97+
/// List all users with admin privileges
98+
ListAdminUsers,
99+
88100
/// Issue a compatibility token
89101
IssueCompatibilityToken {
90102
/// User for which to issue the token
@@ -315,6 +327,82 @@ impl Options {
315327
Ok(ExitCode::SUCCESS)
316328
}
317329

330+
SC::PromoteAdmin { username } => {
331+
let _span =
332+
info_span!("cli.manage.promote_admin", user.username = username,).entered();
333+
334+
let database_config = DatabaseConfig::extract_or_default(figment)
335+
.map_err(anyhow::Error::from_boxed)?;
336+
let mut conn = database_connection_from_config(&database_config).await?;
337+
let txn = conn.begin().await?;
338+
let mut repo = PgRepository::from_conn(txn);
339+
340+
let user = repo
341+
.user()
342+
.find_by_username(&username)
343+
.await?
344+
.context("User not found")?;
345+
346+
let user = repo.user().set_can_request_admin(user, true).await?;
347+
348+
repo.into_inner().commit().await?;
349+
info!(%user.id, %user.username, "User promoted to admin");
350+
351+
Ok(ExitCode::SUCCESS)
352+
}
353+
354+
SC::DemoteAdmin { username } => {
355+
let _span =
356+
info_span!("cli.manage.demote_admin", user.username = username,).entered();
357+
358+
let database_config = DatabaseConfig::extract_or_default(figment)
359+
.map_err(anyhow::Error::from_boxed)?;
360+
let mut conn = database_connection_from_config(&database_config).await?;
361+
let txn = conn.begin().await?;
362+
let mut repo = PgRepository::from_conn(txn);
363+
364+
let user = repo
365+
.user()
366+
.find_by_username(&username)
367+
.await?
368+
.context("User not found")?;
369+
370+
let user = repo.user().set_can_request_admin(user, false).await?;
371+
372+
repo.into_inner().commit().await?;
373+
info!(%user.id, %user.username, "User is no longer admin");
374+
375+
Ok(ExitCode::SUCCESS)
376+
}
377+
378+
SC::ListAdminUsers => {
379+
let _span = info_span!("cli.manage.list_admins").entered();
380+
let database_config = DatabaseConfig::extract_or_default(figment)
381+
.map_err(anyhow::Error::from_boxed)?;
382+
let mut conn = database_connection_from_config(&database_config).await?;
383+
let txn = conn.begin().await?;
384+
let mut repo = PgRepository::from_conn(txn);
385+
386+
let mut cursor = Pagination::first(1000);
387+
let filter = UserFilter::new().can_request_admin_only();
388+
let total = repo.user().count(filter).await?;
389+
390+
info!("The following users can request admin privileges ({total} total):");
391+
loop {
392+
let page = repo.user().list(filter, cursor).await?;
393+
for user in page.edges {
394+
info!(%user.id, username = %user.username);
395+
cursor = cursor.after(user.id);
396+
}
397+
398+
if !page.has_next_page {
399+
break;
400+
}
401+
}
402+
403+
Ok(ExitCode::SUCCESS)
404+
}
405+
318406
SC::IssueCompatibilityToken {
319407
username,
320408
admin,

docs/reference/cli/manage.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,32 @@ $ mas-cli manage add-email <username> <email>
2323
$ mas-cli manage verify-email <username> <email>
2424
```
2525

26+
## `manage promote-admin`
27+
28+
Make a user admin.
29+
30+
```
31+
$ mas-cli manage promote-admin <username>
32+
```
33+
34+
**This doesn't make all the users sessions admin, but rather lets the user request admin access in administration tools.**
35+
36+
## `manage demote-admin`
37+
38+
Make a user non-admin.
39+
40+
```
41+
$ mas-cli manage demote-admin <username>
42+
```
43+
44+
## `manage list-admin-users`
45+
46+
List all users with admin privileges.
47+
48+
```
49+
$ mas-cli manage list-admins
50+
```
51+
2652
## `manage set-password`
2753

2854
Set a user password.

0 commit comments

Comments
 (0)