comms: use synapse admin token

This commit is contained in:
Brad Stein 2026-01-27 04:49:15 -03:00
parent b3386c633a
commit 00aaf23b54
3 changed files with 24 additions and 11 deletions

View File

@ -102,6 +102,10 @@ class CommsService:
def _client(self) -> httpx.Client:
return self._client_factory(timeout=settings.comms_timeout_sec)
def _admin_token(self, fallback: str) -> str:
token = settings.comms_synapse_admin_token
return token if token else fallback
def _mas_admin_token(self, client: httpx.Client) -> str:
if not settings.comms_mas_admin_client_id or not settings.comms_mas_admin_client_secret:
raise RuntimeError("mas admin client credentials missing")
@ -218,13 +222,14 @@ class CommsService:
def _synapse_list_users(self, client: httpx.Client, token: str) -> list[dict[str, Any]]:
users: list[dict[str, Any]] = []
from_token = None
admin_token = self._admin_token(token)
while True:
url = "{}/_synapse/admin/v2/users?local=true&deactivated=false&limit=100".format(
settings.comms_synapse_base
)
if from_token:
url += f"&from={urllib.parse.quote(from_token)}"
resp = client.get(url, headers=_auth(token))
resp = client.get(url, headers=_auth(admin_token))
resp.raise_for_status()
payload = resp.json()
users.extend([item for item in payload.get("users", []) if isinstance(item, dict)])
@ -247,10 +252,11 @@ class CommsService:
return now_ms - last_seen > stale_ms
def _prune_guest(self, client: httpx.Client, token: str, user_id: str) -> bool:
admin_token = self._admin_token(token)
try:
resp = client.delete(
f"{settings.comms_synapse_base}/_synapse/admin/v2/users/{urllib.parse.quote(user_id)}",
headers=_auth(token),
headers=_auth(admin_token),
params={"erase": "true"},
)
except Exception as exc: # noqa: BLE001
@ -280,9 +286,10 @@ class CommsService:
return resp.json().get("displayname")
def _get_displayname_admin(self, client: httpx.Client, token: str, user_id: str) -> str | None:
admin_token = self._admin_token(token)
resp = client.get(
f"{settings.comms_synapse_base}/_synapse/admin/v2/users/{urllib.parse.quote(user_id)}",
headers=_auth(token),
headers=_auth(admin_token),
)
if resp.status_code == HTTP_NOT_FOUND:
return None
@ -314,9 +321,10 @@ class CommsService:
)
def _set_displayname_admin(self, client: httpx.Client, token: str, user_id: str, name: str) -> bool:
admin_token = self._admin_token(token)
resp = client.put(
f"{settings.comms_synapse_base}/_synapse/admin/v2/users/{urllib.parse.quote(user_id)}",
headers=_auth(token),
headers=_auth(admin_token),
json={"displayname": name},
)
return resp.status_code in (HTTP_OK, HTTP_CREATED, HTTP_NO_CONTENT)
@ -843,13 +851,14 @@ class CommsService:
}
def _ensure_user(self, client: httpx.Client, token: str, localpart: str, password: str, admin: bool) -> None:
admin_token = self._admin_token(token)
user_id = _canon_user(localpart, settings.comms_server_name)
url = f"{settings.comms_synapse_base}/_synapse/admin/v2/users/{urllib.parse.quote(user_id)}"
resp = client.get(url, headers=_auth(token))
resp = client.get(url, headers=_auth(admin_token))
if resp.status_code == HTTP_OK:
return
payload = {"password": password, "admin": admin, "deactivated": False}
create = client.put(url, headers=_auth(token), json=payload)
create = client.put(url, headers=_auth(admin_token), json=payload)
if create.status_code not in (HTTP_OK, HTTP_CREATED):
raise RuntimeError(f"create user {user_id} failed: {create.status_code} {create.text}")
@ -906,20 +915,22 @@ class CommsService:
return room_id
def _join_user(self, client: httpx.Client, token: str, room_id: str, user_id: str) -> None:
admin_token = self._admin_token(token)
client.post(
f"{settings.comms_synapse_base}/_synapse/admin/v1/join/{urllib.parse.quote(room_id)}",
headers=_auth(token),
headers=_auth(admin_token),
json={"user_id": user_id},
)
def _join_all_locals(self, client: httpx.Client, token: str, room_id: str) -> None:
users: list[str] = []
from_token = None
admin_token = self._admin_token(token)
while True:
url = f"{settings.comms_synapse_base}/_synapse/admin/v2/users?local=true&deactivated=false&limit=100"
if from_token:
url += f"&from={from_token}"
resp = client.get(url, headers=_auth(token))
resp = client.get(url, headers=_auth(admin_token))
payload = resp.json()
users.extend([u["name"] for u in payload.get("users", []) if isinstance(u, dict) and u.get("name")])
from_token = payload.get("next_token")

View File

@ -166,7 +166,7 @@ _K8S_ROLES: list[dict[str, str]] = [
"namespace": "maintenance",
"service_accounts": "ariadne,maintenance-vault-sync",
"read_paths": "maintenance/ariadne-db portal/bstein-dev-home-keycloak-admin mailu/mailu-db-secret "
"mailu/mailu-initial-account-secret shared/harbor-pull",
"mailu/mailu-initial-account-secret comms/synapse-admin shared/harbor-pull",
"write_paths": "",
},
{
@ -225,8 +225,8 @@ _K8S_ROLES: list[dict[str, str]] = [
"service_accounts": "comms-secrets-ensure,mas-db-ensure,mas-admin-client-secret-writer,othrys-synapse-signingkey-job",
"read_paths": "",
"write_paths": "comms/turn-shared-secret comms/livekit-api comms/synapse-redis comms/synapse-macaroon "
"comms/atlasbot-credentials-runtime comms/synapse-db comms/mas-db comms/mas-admin-client-runtime "
"comms/mas-secrets-runtime comms/othrys-synapse-signingkey",
"comms/atlasbot-credentials-runtime comms/synapse-db comms/synapse-admin comms/synapse-registration "
"comms/mas-db comms/mas-admin-client-runtime comms/mas-secrets-runtime comms/othrys-synapse-signingkey",
},
]

View File

@ -152,6 +152,7 @@ class Settings:
comms_synapse_db_name: str
comms_synapse_db_user: str
comms_synapse_db_password: str
comms_synapse_admin_token: str
comms_timeout_sec: float
comms_guest_stale_days: int
@ -403,6 +404,7 @@ class Settings:
"comms_synapse_db_name": _env("COMMS_SYNAPSE_DB_NAME", "synapse"),
"comms_synapse_db_user": _env("COMMS_SYNAPSE_DB_USER", "synapse"),
"comms_synapse_db_password": _env("COMMS_SYNAPSE_DB_PASSWORD", ""),
"comms_synapse_admin_token": _env("COMMS_SYNAPSE_ADMIN_TOKEN", ""),
"comms_timeout_sec": _env_float("COMMS_TIMEOUT_SEC", 30.0),
"comms_guest_stale_days": _env_int("COMMS_GUEST_STALE_DAYS", 14),
}