matrix: create accounts as the appservice, and promote the admin explicitly
Account creation stops presenting a shared registration token in a UIAA
flow and starts acting as the hive's appservice: one POST, typed
`m.login.application_service`, authorised by the `as_token` the
registration file names. The account that comes out is an ordinary user
with its own device and its own access token — nothing about what an agent
holds changes.
Three things get better than "one fewer round-trip":
- An account whose token file was lost is re-tokened by an appservice
login, which needs neither its password nor admin rights. That was
previously a stored-password login, and failing that an admin-room
password reset. Both are kept behind it, for accounts created before
this existed or named outside the appservice's namespace.
- The hive admin no longer has to be the first account ever registered.
It could not be, in fact: tuwunel excludes appservice-created users from
the automatic first-user grant, and on a homeserver that already had
users the rule never fired anyway. Rights now come from an explicit
`make_user_admin` — performed by `admin_execute` at homeserver startup,
and verified here each sweep by reading the account's own joined-rooms
list. Absent rights are reported with the one command that grants them,
and are not fatal: agent accounts, the Space and the chat room all work
without them.
- hive-c0re reads the appservice token and never mints it. The old token
was the whole agreement, so whoever wrote it first was right; this one
is also named by a registration file that only the nix side writes, and
a token minted here would be one the homeserver has never heard of.
Also fixes the `make-user-admin` reply matcher, which recognised neither
spelling tuwunel v1.9.0 uses ("<user> has been granted admin
privileges.") — a promotion that had already taken effect was reported as
a 15-second timeout.
Refs #4402
This commit is contained in:
parent
5809077924
commit
43cd8607ba
3 changed files with 379 additions and 153 deletions
|
|
@ -558,8 +558,8 @@ async fn handle_matrix_create_user(
|
|||
password: Option<&str>,
|
||||
) -> Result<HostResponse> {
|
||||
require_matrix_present()?;
|
||||
let register_token =
|
||||
crate::matrix::ensure_register_token().context("read matrix register token")?;
|
||||
let as_token =
|
||||
crate::matrix::read_appservice_token().context("read matrix appservice token")?;
|
||||
let client = matrix_http_client()?;
|
||||
let mut out = Vec::new();
|
||||
if agent_exists(name)? {
|
||||
|
|
@ -571,7 +571,7 @@ async fn handle_matrix_create_user(
|
|||
"matrix create-user: a password is for non-agent (operator) accounts only; '{name}' is an agent which authenticates via access_token"
|
||||
);
|
||||
}
|
||||
crate::matrix::ensure_user_for(&client, name.as_str(), ®ister_token)
|
||||
crate::matrix::ensure_user_for(&client, name.as_str(), &as_token)
|
||||
.await
|
||||
.with_context(|| format!("matrix create-user {name}"))?;
|
||||
let path = Coordinator::agent_notes_dir(name).join("matrix-token");
|
||||
|
|
@ -585,7 +585,7 @@ async fn handle_matrix_create_user(
|
|||
let token = crate::matrix::provision_user_token(
|
||||
&client,
|
||||
name.as_str(),
|
||||
®ister_token,
|
||||
&as_token,
|
||||
&effective_password,
|
||||
)
|
||||
.await
|
||||
|
|
@ -770,10 +770,10 @@ async fn handle_push_snapshot(
|
|||
|
||||
async fn handle_matrix_sync_admin() -> Result<HostResponse> {
|
||||
require_matrix_present()?;
|
||||
let register_token =
|
||||
crate::matrix::ensure_register_token().context("read matrix register token")?;
|
||||
let as_token =
|
||||
crate::matrix::read_appservice_token().context("read matrix appservice token")?;
|
||||
let client = matrix_http_client()?;
|
||||
crate::matrix::ensure_admin_user(&client, ®ister_token)
|
||||
crate::matrix::ensure_admin_user(&client, &as_token)
|
||||
.await
|
||||
.context("matrix sync-admin")?;
|
||||
let path = crate::matrix::admin_token_path();
|
||||
|
|
|
|||
Loading…
Reference in a new issue