CLI tool to issue user registration tokens

This commit is contained in:
Quentin Gliech
2025-06-03 12:12:34 +02:00
parent 4d1122533b
commit 3821c6550d
4 changed files with 84 additions and 2 deletions

1
Cargo.lock generated
View File

@@ -3141,6 +3141,7 @@ dependencies = [
"axum",
"bytes",
"camino",
"chrono",
"clap",
"console",
"dialoguer",

View File

@@ -18,6 +18,7 @@ anyhow.workspace = true
axum.workspace = true
bytes.workspace = true
camino.workspace = true
chrono.workspace = true
clap.workspace = true
console = "0.15.11"
dialoguer = { version = "0.11.0", default-features = false, features = [

View File

@@ -7,6 +7,7 @@
use std::{collections::BTreeMap, process::ExitCode};
use anyhow::Context;
use chrono::Duration;
use clap::{ArgAction, CommandFactory, Parser};
use console::{Alignment, Style, Term, pad_str, style};
use dialoguer::{Confirm, FuzzySelect, Input, Password, theme::ColorfulTheme};
@@ -28,7 +29,10 @@ use mas_storage::{
user::{BrowserSessionFilter, UserEmailRepository, UserPasswordRepository, UserRepository},
};
use mas_storage_pg::{DatabaseError, PgRepository};
use rand::{RngCore, SeedableRng};
use rand::{
RngCore, SeedableRng,
distributions::{Alphanumeric, DistString as _},
};
use sqlx::{Acquire, types::Uuid};
use tracing::{error, info, info_span, warn};
use zeroize::Zeroizing;
@@ -95,6 +99,29 @@ enum Subcommand {
admin: bool,
},
/// Create a new user registration token
IssueUserRegistrationToken {
/// Specific token string to use. If not provided, a random token will
/// be generated.
#[arg(long)]
token: Option<String>,
/// Maximum number of times this token can be used.
/// If not provided, the token can be used only once, unless the
/// `--unlimited` flag is set.
#[arg(long, group = "token-usage-limit")]
usage_limit: Option<u32>,
/// Allow the token to be used an unlimited number of times.
#[arg(long, action = ArgAction::SetTrue, group = "token-usage-limit")]
unlimited: bool,
/// Time in seconds after which the token expires.
/// If not provided, the token never expires.
#[arg(long)]
expires_in: Option<u32>,
},
/// Trigger a provisioning job for all users
ProvisionAllUsers,
@@ -330,6 +357,46 @@ impl Options {
Ok(ExitCode::SUCCESS)
}
SC::IssueUserRegistrationToken {
token,
usage_limit,
unlimited,
expires_in,
} => {
let _span = info_span!("cli.manage.add_user_registration_token").entered();
let usage_limit = match (usage_limit, unlimited) {
(Some(usage_limit), false) => Some(usage_limit),
(None, false) => Some(1),
(None, true) => None,
(Some(_), true) => unreachable!(), // This should be handled by the clap group
};
let database_config = DatabaseConfig::extract_or_default(figment)?;
let mut conn = database_connection_from_config(&database_config).await?;
let txn = conn.begin().await?;
let mut repo = PgRepository::from_conn(txn);
// Calculate expiration time if provided
let expires_at =
expires_in.map(|seconds| clock.now() + Duration::seconds(seconds.into()));
// Generate a token if not provided
let token_str = token.unwrap_or_else(|| Alphanumeric.sample_string(&mut rng, 12));
// Create the token
let registration_token = repo
.user_registration_token()
.add(&mut rng, &clock, token_str, usage_limit, expires_at)
.await?;
repo.into_inner().commit().await?;
info!(%registration_token.id, "Created user registration token: {}", registration_token.token);
Ok(ExitCode::SUCCESS)
}
SC::ProvisionAllUsers => {
let _span = info_span!("cli.manage.provision_all_users").entered();
let database_config = DatabaseConfig::extract_or_default(figment)?;

View File

@@ -46,6 +46,19 @@ Options:
$ mas-cli manage issue-compatibility-token <username> --device-id <device_id> --yes-i-want-to-grant-synapse-admin-privileges
```
## `manage issue-user-registration-token`
Create a new user registration token.
Options:
- `--token <token>`: Specific token string to use. If not provided, a random token will be generated.
- `--usage-limit <usage_limit>`: Limit the number of times the token can be used. If not provided, the token can be used an unlimited number of times.
- `--expires-in <expires_in>`: Time in seconds after which the token expires. If not provided, the token never expires.
```
$ mas-cli manage issue-user-registration-token --token <token> --usage-limit <usage_limit> --expires-in <expires_in>
```
## `manage provision-all-users`
Trigger a provisioning job for all users.
@@ -101,4 +114,4 @@ Options:
```
$ mas-cli manage register-user
```
```