102 lines
3.4 KiB
Rust
102 lines
3.4 KiB
Rust
//! `hivectl matrix` — matrix account provisioning verbs. hivectl forwards
|
|
//! each request to the daemon (which owns the register + admin tokens and
|
|
//! the matrix creds dir) and renders the reply; it no longer links the
|
|
//! matrix machinery itself.
|
|
|
|
use std::path::Path;
|
|
|
|
use anyhow::{Context as _, Result, bail};
|
|
|
|
use crate::cli::MatrixCmd;
|
|
use crate::util::resolve_password;
|
|
|
|
/// Route a `matrix` subcommand to its handler. Extracted from `main`'s
|
|
/// dispatch match so the top-level router stays small.
|
|
pub(crate) async fn run_matrix_cmd(socket: &Path, cmd: MatrixCmd) -> Result<()> {
|
|
match cmd {
|
|
MatrixCmd::CreateUser {
|
|
name,
|
|
password,
|
|
password_stdin,
|
|
} => matrix_create_user(socket, &name, password.as_deref(), password_stdin).await,
|
|
MatrixCmd::SyncAdmin => matrix_sync_admin(socket).await,
|
|
MatrixCmd::PromoteUser { name } => matrix_promote_user(socket, &name).await,
|
|
MatrixCmd::ResetPassword { name } => matrix_reset_password(socket, &name).await,
|
|
MatrixCmd::Invite { user, room } => matrix_invite(socket, &user, room.as_deref()).await,
|
|
}
|
|
}
|
|
|
|
/// Send a matrix provisioning request to the daemon and print the
|
|
/// operator-facing result lines it returns. The daemon owns the register +
|
|
/// admin tokens and the matrix creds dir, so hivectl no longer links the
|
|
/// matrix machinery — it just forwards the request and renders the reply.
|
|
async fn matrix_request(socket: &Path, req: hive_host_sock::HostRequest) -> Result<()> {
|
|
let resp = crate::client::request(socket, req)
|
|
.await
|
|
.with_context(|| format!("connect to daemon socket {}", socket.display()))?;
|
|
if !resp.ok {
|
|
bail!(
|
|
"matrix: {}",
|
|
resp.error.as_deref().unwrap_or("unknown error")
|
|
);
|
|
}
|
|
for line in &resp.messages {
|
|
println!("{line}");
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
async fn matrix_create_user(
|
|
socket: &Path,
|
|
name: &str,
|
|
password: Option<&str>,
|
|
password_stdin: bool,
|
|
) -> Result<()> {
|
|
// Resolve the password client-side (an inline flag or a stdin read);
|
|
// the daemon never touches this process's stdin. The agent-vs-operator
|
|
// branch + throwaway-password handling now live in the daemon handler.
|
|
let password = resolve_password(password, password_stdin)?;
|
|
matrix_request(
|
|
socket,
|
|
hive_host_sock::HostRequest::MatrixCreateUser {
|
|
name: crate::util::parse_ident(name)?,
|
|
password,
|
|
},
|
|
)
|
|
.await
|
|
}
|
|
|
|
async fn matrix_sync_admin(socket: &Path) -> Result<()> {
|
|
matrix_request(socket, hive_host_sock::HostRequest::MatrixSyncAdmin).await
|
|
}
|
|
|
|
async fn matrix_promote_user(socket: &Path, name: &str) -> Result<()> {
|
|
matrix_request(
|
|
socket,
|
|
hive_host_sock::HostRequest::MatrixPromoteUser {
|
|
name: crate::util::parse_ident(name)?,
|
|
},
|
|
)
|
|
.await
|
|
}
|
|
|
|
async fn matrix_invite(socket: &Path, user: &str, room: Option<&str>) -> Result<()> {
|
|
matrix_request(
|
|
socket,
|
|
hive_host_sock::HostRequest::MatrixInvite {
|
|
user: user.to_owned(),
|
|
room: room.map(str::to_owned),
|
|
},
|
|
)
|
|
.await
|
|
}
|
|
|
|
async fn matrix_reset_password(socket: &Path, name: &str) -> Result<()> {
|
|
matrix_request(
|
|
socket,
|
|
hive_host_sock::HostRequest::MatrixResetPassword {
|
|
name: crate::util::parse_ident(name)?,
|
|
},
|
|
)
|
|
.await
|
|
}
|