feat: update controls in the admin, release token scope, build info in CI images

The versions page shows each node's update state with update buttons, API
tokens get a release scope that can only register releases (used by CI), and
the CI image and release builds now pass the tag, commit and build time.
This commit is contained in:
justme committed 2026-10-06 22:56:56 +08:00
1 parent 22a98f2eb0
commit 7a71bf57f9
17 files changed
+470 -141

No files matched your search

@@ -7,12 +7,13 @@ public enum PrincipalKind
Token,
}
/// <summary>访问级别:作用域为 read 的令牌只读,admin 可以管理。</summary>
/// <summary>访问级别:作用域为 read 的令牌只读,admin 可以管理,release 只能登记发布清单(给 CI 用,什么都读不了)。</summary>
public enum ApiScope
{
None = 0,
Read = 1,
Admin = 2,
Release = 1,
Read = 2,
Admin = 3,
}
public sealed record Principal(PrincipalKind Kind, ApiScope Scope, string? UserId, string? Username, string? CsrfToken, string? TokenId)
@@ -22,6 +23,8 @@ public sealed record Principal(PrincipalKind Kind, ApiScope Scope, string? UserI
public bool CanRead => Scope >= ApiScope.Read;
public bool IsAdmin => Scope >= ApiScope.Admin;
public bool CanPublishRelease => Scope is ApiScope.Release or ApiScope.Admin;
}
public sealed record LoginResult(string SessionToken, string CsrfToken, long ExpiresAtMs, string UserId, string Username);
@@ -77,7 +77,7 @@ public sealed partial class AuthService
await _store.TouchApiTokenAsync(token.Id, now, ct);
}
ApiScope scope = token.Scope == "admin" ? ApiScope.Admin : ApiScope.Read;
ApiScope scope = token.Scope switch { "admin" => ApiScope.Admin, "release" => ApiScope.Release, _ => ApiScope.Read };
return new Principal(PrincipalKind.Token, scope, null, token.Name, null, token.Id);
}
@@ -135,9 +135,9 @@ public sealed partial class AuthService
return ValidationError.Fail<CreatedApiToken>("name", "must be 1-64 characters");
}
if (scope is not ("read" or "admin"))
if (scope is not ("read" or "admin" or "release"))
{
return ValidationError.Fail<CreatedApiToken>("scope", "must be read or admin");
return ValidationError.Fail<CreatedApiToken>("scope", "must be read, admin or release");
}
string plaintext = TokenHash.NewToken("mon");