Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 90 additions & 2 deletions crates/cli/src/commands/manage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,17 @@ use mas_data_model::{Clock, Device, SystemClock, TokenType, Ulid, UpstreamOAuthP
use mas_email::Address;
use mas_matrix::HomeserverConnection;
use mas_storage::{
RepositoryAccess,
Pagination, RepositoryAccess,
compat::{CompatAccessTokenRepository, CompatSessionFilter, CompatSessionRepository},
oauth2::OAuth2SessionFilter,
queue::{
DeactivateUserJob, ProvisionUserJob, QueueJobRepositoryExt as _, ReactivateUserJob,
SyncDevicesJob,
},
user::{BrowserSessionFilter, UserEmailRepository, UserPasswordRepository, UserRepository},
user::{
BrowserSessionFilter, UserEmailRepository, UserFilter, UserPasswordRepository,
UserRepository,
},
};
use mas_storage_pg::{DatabaseError, PgRepository};
use rand::{
Expand Down Expand Up @@ -85,6 +88,15 @@ enum Subcommand {
ignore_complexity: bool,
},

/// Make a user admin
PromoteAdmin { username: String },

/// Make a user non-admin
DemoteAdmin { username: String },

/// List all users with admin privileges
ListAdminUsers,

/// Issue a compatibility token
IssueCompatibilityToken {
/// User for which to issue the token
Expand Down Expand Up @@ -315,6 +327,82 @@ impl Options {
Ok(ExitCode::SUCCESS)
}

SC::PromoteAdmin { username } => {
let _span =
info_span!("cli.manage.promote_admin", user.username = username,).entered();

let database_config = DatabaseConfig::extract_or_default(figment)
.map_err(anyhow::Error::from_boxed)?;
let mut conn = database_connection_from_config(&database_config).await?;
let txn = conn.begin().await?;
let mut repo = PgRepository::from_conn(txn);

let user = repo
.user()
.find_by_username(&username)
.await?
.context("User not found")?;

let user = repo.user().set_can_request_admin(user, true).await?;

repo.into_inner().commit().await?;
info!(%user.id, %user.username, "User promoted to admin");

Ok(ExitCode::SUCCESS)
}

SC::DemoteAdmin { username } => {
let _span =
info_span!("cli.manage.demote_admin", user.username = username,).entered();

let database_config = DatabaseConfig::extract_or_default(figment)
.map_err(anyhow::Error::from_boxed)?;
let mut conn = database_connection_from_config(&database_config).await?;
let txn = conn.begin().await?;
let mut repo = PgRepository::from_conn(txn);

let user = repo
.user()
.find_by_username(&username)
.await?
.context("User not found")?;

let user = repo.user().set_can_request_admin(user, false).await?;

repo.into_inner().commit().await?;
info!(%user.id, %user.username, "User is no longer admin");

Ok(ExitCode::SUCCESS)
}

SC::ListAdminUsers => {
let _span = info_span!("cli.manage.list_admins").entered();
let database_config = DatabaseConfig::extract_or_default(figment)
.map_err(anyhow::Error::from_boxed)?;
let mut conn = database_connection_from_config(&database_config).await?;
let txn = conn.begin().await?;
let mut repo = PgRepository::from_conn(txn);

let mut cursor = Pagination::first(1000);
let filter = UserFilter::new().can_request_admin_only();
let total = repo.user().count(filter).await?;

info!("The following users can request admin privileges ({total} total):");
loop {
let page = repo.user().list(filter, cursor).await?;
for user in page.edges {
info!(%user.id, username = %user.username);
cursor = cursor.after(user.id);
}

if !page.has_next_page {
break;
}
}

Ok(ExitCode::SUCCESS)
}

SC::IssueCompatibilityToken {
username,
admin,
Expand Down
26 changes: 26 additions & 0 deletions docs/reference/cli/manage.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,32 @@ $ mas-cli manage add-email <username> <email>
$ mas-cli manage verify-email <username> <email>
```

## `manage promote-admin`

Make a user admin.

```
$ mas-cli manage promote-admin <username>
```

**This doesn't make all the users sessions admin, but rather lets the user request admin access in administration tools.**

## `manage demote-admin`

Make a user non-admin.

```
$ mas-cli manage demote-admin <username>
```

## `manage list-admin-users`

List all users with admin privileges.

```
$ mas-cli manage list-admins
```

## `manage set-password`

Set a user password.
Expand Down
Loading