fix(#1012): guard ensure_user_email with marker; add login_name to PATCH body
sync_agent called ensure_user_email on every tick, which sent
PATCH /api/v1/admin/users/{name} without the required login_name
field. Forgejo's EditUserOption handler was resetting use_custom_avatar
to false on each call, clobbering the avatar uploaded by the
forge-avatar-sync one-shot service.
Two-part fix:
- add login_name to the PATCH body (Forgejo EditUserOption requires it)
- write EMAIL_ALIGNED_MARKER_PREFIX{name} on first success; skip the
PATCH on all subsequent sync_agent ticks
Marker follows the same one-shot pattern as CORE_AVATAR_MARKER and
CONFIG_ORG_AVATAR_MARKER. Delete the marker to force re-alignment.
This commit is contained in:
parent
16f13e3b25
commit
0850128090
1 changed files with 25 additions and 8 deletions
|
|
@ -28,6 +28,12 @@ const CORE_AVATAR_MARKER: &str = "/var/lib/hyperhive/forge-core-avatar-set";
|
|||
/// Sibling marker for the `agent-configs` org avatar. Same one-shot
|
||||
/// semantics — delete to force the upload to re-run.
|
||||
const CONFIG_ORG_AVATAR_MARKER: &str = "/var/lib/hyperhive/forge-agent-configs-avatar-set";
|
||||
/// Per-agent marker written once the account email has been aligned to
|
||||
/// `{name}@hyperhive`. Skips the `PATCH /api/v1/admin/users/{name}`
|
||||
/// call on every subsequent `sync_agent` tick — that PATCH was resetting
|
||||
/// Forgejo's `use_custom_avatar` flag and clobbering the avatar uploaded
|
||||
/// by `forge-avatar-sync` (#1012). Delete to force re-alignment.
|
||||
const EMAIL_ALIGNED_MARKER_PREFIX: &str = "/var/lib/hyperhive/forge-email-aligned-";
|
||||
// Avatar PNGs are loaded at runtime from
|
||||
// `$HIVE_ASSETS_DIR/branding/{hyperhive,agent-configs}.png` via the
|
||||
// helpers in `hive_sh4re::assets`. The `agent-configs.png` is
|
||||
|
|
@ -231,27 +237,38 @@ async fn change_user_password(name: &str, password: &str) -> Result<()> {
|
|||
|
||||
/// Idempotently align the Forgejo account email to `agent_email(name)`.
|
||||
/// Existing agents were created with `{name}@hive.local`; this corrects
|
||||
/// that so git commits (which use `{name}@hyperhive.local`) link to profiles.
|
||||
/// that so git commits (which use `{name}@hyperhive`) link to profiles.
|
||||
/// Best-effort: failures are warned, not propagated.
|
||||
///
|
||||
/// Marker-guarded: writes `EMAIL_ALIGNED_MARKER_PREFIX{name}` on first
|
||||
/// success and skips the PATCH on all subsequent calls. This prevents
|
||||
/// Forgejo's admin-user-edit endpoint from resetting `use_custom_avatar`
|
||||
/// on every `sync_agent` tick (root cause of #1012 — wrong forge avatar
|
||||
/// after container rebuild). Delete the marker to force re-alignment.
|
||||
///
|
||||
/// Uses the admin REST API (`PATCH /api/v1/admin/users/{name}`) rather
|
||||
/// than `forgejo admin user edit` because the CLI dropped the `edit`
|
||||
/// subcommand somewhere between forgejo 8 and current (the bare CLI
|
||||
/// surfaced as "flag provided but not defined: -username"). Body sets
|
||||
/// `source_id = 0` (local auth, the default for users hive-c0re
|
||||
/// creates) which forgejo's PATCH validator requires even when the
|
||||
/// only thing changing is the email.
|
||||
/// subcommand somewhere between forgejo 8 and current. Body includes
|
||||
/// `login_name` (required by Forgejo's `EditUserOption` validator) and
|
||||
/// `source_id = 0` (local auth, the default for users hive-c0re creates).
|
||||
async fn ensure_user_email(name: &str) {
|
||||
let marker = format!("{EMAIL_ALIGNED_MARKER_PREFIX}{name}");
|
||||
if std::path::Path::new(&marker).exists() {
|
||||
return;
|
||||
}
|
||||
let Some(token) = core_token() else {
|
||||
tracing::debug!(%name, "forge: skipping ensure_user_email — no core token yet");
|
||||
return;
|
||||
};
|
||||
let email = agent_email(name);
|
||||
let body = format!(r#"{{"email":"{email}","source_id":0}}"#);
|
||||
// `login_name` is required by Forgejo's EditUserOption validator.
|
||||
// Omitting it caused Forgejo to reset use_custom_avatar on each call (#1012).
|
||||
let body = format!(r#"{{"email":"{email}","login_name":"{name}","source_id":0}}"#);
|
||||
let url = format!("{FORGE_HTTP}/api/v1/admin/users/{name}");
|
||||
match forge_http(reqwest::Method::PATCH, &url, &token, &body).await {
|
||||
Ok(status) if status.is_success() => {
|
||||
tracing::debug!(%name, %email, "forge: user email aligned");
|
||||
std::fs::write(&marker, "").ok();
|
||||
tracing::info!(%name, %email, "forge: user email aligned");
|
||||
}
|
||||
Ok(status) if status == reqwest::StatusCode::FORBIDDEN => {
|
||||
// Core token missing admin scope — see
|
||||
|
|
|
|||
Loading…
Reference in a new issue