fix: drop --server flag from hivectl matrix; discover server_name from homeserver
Add matrix::discover_server_name() via GET /_matrix/key/v2/server (unauthenticated federation endpoint, always returns server_name). hivectl is always talking to the local hive — no reason to require the operator to spell out the server_name.
This commit is contained in:
parent
8757dc615d
commit
c4a8b90236
2 changed files with 42 additions and 35 deletions
|
|
@ -158,16 +158,11 @@ enum MatrixCmd {
|
||||||
SyncAdmin,
|
SyncAdmin,
|
||||||
/// Promote a matrix user to homeserver admin via the admin API.
|
/// Promote a matrix user to homeserver admin via the admin API.
|
||||||
/// Uses the hive system admin token at
|
/// Uses the hive system admin token at
|
||||||
/// `/var/lib/hyperhive/matrix-admin-token`. Requires `--server` to
|
/// `/var/lib/hyperhive/matrix-admin-token`. The server_name is
|
||||||
/// be the matrix `server_name` (e.g. `pr1ma.darkest.space`).
|
/// discovered automatically from the running homeserver.
|
||||||
PromoteUser {
|
PromoteUser {
|
||||||
/// Matrix localpart of the user to promote (e.g. `argus`).
|
/// Matrix localpart of the user to promote (e.g. `argus`).
|
||||||
name: String,
|
name: String,
|
||||||
/// Matrix server_name embedded in user IDs (`@user:<server>`).
|
|
||||||
/// Falls back to the `HYPERHIVE_MATRIX_SERVER_NAME` env var
|
|
||||||
/// when omitted.
|
|
||||||
#[arg(long)]
|
|
||||||
server: Option<String>,
|
|
||||||
},
|
},
|
||||||
/// Reset a matrix user's password via the admin API and persist the
|
/// Reset a matrix user's password via the admin API and persist the
|
||||||
/// new password to `/var/lib/hyperhive/matrix-creds/<name>-password`
|
/// new password to `/var/lib/hyperhive/matrix-creds/<name>-password`
|
||||||
|
|
@ -178,10 +173,6 @@ enum MatrixCmd {
|
||||||
ResetPassword {
|
ResetPassword {
|
||||||
/// Matrix localpart of the account to reset (e.g. `argus`).
|
/// Matrix localpart of the account to reset (e.g. `argus`).
|
||||||
name: String,
|
name: String,
|
||||||
/// Matrix server_name embedded in user IDs. Falls back to the
|
|
||||||
/// `HYPERHIVE_MATRIX_SERVER_NAME` env var when omitted.
|
|
||||||
#[arg(long)]
|
|
||||||
server: Option<String>,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -284,14 +275,8 @@ async fn main() -> Result<()> {
|
||||||
password_stdin,
|
password_stdin,
|
||||||
} => matrix_create_user(&name, password.as_deref(), password_stdin).await,
|
} => matrix_create_user(&name, password.as_deref(), password_stdin).await,
|
||||||
MatrixCmd::SyncAdmin => matrix_sync_admin().await,
|
MatrixCmd::SyncAdmin => matrix_sync_admin().await,
|
||||||
MatrixCmd::PromoteUser { name, server } => {
|
MatrixCmd::PromoteUser { name } => matrix_promote_user(&name).await,
|
||||||
let server_name = resolve_server_name(server.as_deref())?;
|
MatrixCmd::ResetPassword { name } => matrix_reset_password(&name).await,
|
||||||
matrix_promote_user(&name, &server_name).await
|
|
||||||
}
|
|
||||||
MatrixCmd::ResetPassword { name, server } => {
|
|
||||||
let server_name = resolve_server_name(server.as_deref())?;
|
|
||||||
matrix_reset_password(&name, &server_name).await
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Cmd::Gateway { cmd } => match cmd {
|
Cmd::Gateway { cmd } => match cmd {
|
||||||
GatewayCmd::CreateUser {
|
GatewayCmd::CreateUser {
|
||||||
|
|
@ -441,18 +426,6 @@ async fn matrix_create_user(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve matrix server_name from flag or env var.
|
|
||||||
fn resolve_server_name(flag: Option<&str>) -> Result<String> {
|
|
||||||
if let Some(s) = flag {
|
|
||||||
return Ok(s.to_owned());
|
|
||||||
}
|
|
||||||
std::env::var("HYPERHIVE_MATRIX_SERVER_NAME")
|
|
||||||
.map_err(|_| anyhow::anyhow!(
|
|
||||||
"matrix server_name required — pass --server <name> or \
|
|
||||||
set HYPERHIVE_MATRIX_SERVER_NAME"
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn matrix_sync_admin() -> Result<()> {
|
async fn matrix_sync_admin() -> Result<()> {
|
||||||
if !hive_c0re::matrix::is_present().await {
|
if !hive_c0re::matrix::is_present().await {
|
||||||
bail!(
|
bail!(
|
||||||
|
|
@ -477,7 +450,7 @@ async fn matrix_sync_admin() -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn matrix_promote_user(name: &str, server_name: &str) -> Result<()> {
|
async fn matrix_promote_user(name: &str) -> Result<()> {
|
||||||
if !hive_c0re::matrix::is_present().await {
|
if !hive_c0re::matrix::is_present().await {
|
||||||
bail!(
|
bail!(
|
||||||
"hive-matrix container not running — start it (services.hyperhive.matrix.enable = true) first"
|
"hive-matrix container not running — start it (services.hyperhive.matrix.enable = true) first"
|
||||||
|
|
@ -488,14 +461,17 @@ async fn matrix_promote_user(name: &str, server_name: &str) -> Result<()> {
|
||||||
.timeout(std::time::Duration::from_secs(30))
|
.timeout(std::time::Duration::from_secs(30))
|
||||||
.build()
|
.build()
|
||||||
.context("build reqwest client")?;
|
.context("build reqwest client")?;
|
||||||
hive_c0re::matrix::promote_user_to_admin(&client, &admin_token, name, server_name)
|
let server_name = hive_c0re::matrix::discover_server_name(&client)
|
||||||
|
.await
|
||||||
|
.context("discover matrix server_name")?;
|
||||||
|
hive_c0re::matrix::promote_user_to_admin(&client, &admin_token, name, &server_name)
|
||||||
.await
|
.await
|
||||||
.with_context(|| format!("matrix promote-user {name}"))?;
|
.with_context(|| format!("matrix promote-user {name}"))?;
|
||||||
println!("matrix: promoted @{name}:{server_name} to admin");
|
println!("matrix: promoted @{name}:{server_name} to admin");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn matrix_reset_password(name: &str, server_name: &str) -> Result<()> {
|
async fn matrix_reset_password(name: &str) -> Result<()> {
|
||||||
if !hive_c0re::matrix::is_present().await {
|
if !hive_c0re::matrix::is_present().await {
|
||||||
bail!(
|
bail!(
|
||||||
"hive-matrix container not running — start it (services.hyperhive.matrix.enable = true) first"
|
"hive-matrix container not running — start it (services.hyperhive.matrix.enable = true) first"
|
||||||
|
|
@ -508,11 +484,14 @@ async fn matrix_reset_password(name: &str, server_name: &str) -> Result<()> {
|
||||||
.timeout(std::time::Duration::from_secs(30))
|
.timeout(std::time::Duration::from_secs(30))
|
||||||
.build()
|
.build()
|
||||||
.context("build reqwest client")?;
|
.context("build reqwest client")?;
|
||||||
|
let server_name = hive_c0re::matrix::discover_server_name(&client)
|
||||||
|
.await
|
||||||
|
.context("discover matrix server_name")?;
|
||||||
hive_c0re::matrix::reset_user_password(
|
hive_c0re::matrix::reset_user_password(
|
||||||
&client,
|
&client,
|
||||||
&admin_token,
|
&admin_token,
|
||||||
name,
|
name,
|
||||||
server_name,
|
&server_name,
|
||||||
&new_password,
|
&new_password,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|
|
||||||
|
|
@ -598,6 +598,34 @@ pub async fn reset_user_password(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Discover the matrix `server_name` from the running homeserver via
|
||||||
|
/// `GET /_matrix/key/v2/server` (unauthenticated federation key endpoint).
|
||||||
|
/// The response JSON always includes `"server_name"` per the matrix spec.
|
||||||
|
pub async fn discover_server_name(client: &reqwest::Client) -> Result<String> {
|
||||||
|
let url = format!("{MATRIX_HTTP}/_matrix/key/v2/server");
|
||||||
|
let resp = client
|
||||||
|
.get(&url)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.context("matrix: GET /_matrix/key/v2/server")?;
|
||||||
|
let status = resp.status();
|
||||||
|
let body = resp
|
||||||
|
.json::<serde_json::Value>()
|
||||||
|
.await
|
||||||
|
.context("matrix: parse /_matrix/key/v2/server response")?;
|
||||||
|
if !status.is_success() {
|
||||||
|
anyhow::bail!(
|
||||||
|
"matrix: /_matrix/key/v2/server returned HTTP {status}, body: {body}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
body["server_name"]
|
||||||
|
.as_str()
|
||||||
|
.map(str::to_owned)
|
||||||
|
.with_context(|| {
|
||||||
|
format!("matrix: /_matrix/key/v2/server response missing server_name field: {body}")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Read the hive admin access token from disk. Returns an error if it
|
/// Read the hive admin access token from disk. Returns an error if it
|
||||||
/// is absent — callers should gate their admin-API calls on this.
|
/// is absent — callers should gate their admin-API calls on this.
|
||||||
pub fn read_admin_token() -> Result<String> {
|
pub fn read_admin_token() -> Result<String> {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue