feat(auth): center-scoped single admin + GET /admin-email + cli #1

Merged
hzhang merged 2 commits from feat/admin-user into main 2026-05-22 21:59:15 +00:00
Showing only changes of commit bd53813391 - Show all commits

View File

@@ -226,10 +226,12 @@ export class AuthService {
if (!target) { if (!target) {
throw new UnauthorizedException(`user ${email} not found`); throw new UnauthorizedException(`user ${email} not found`);
} }
// Enforce at-most-one-admin: clear every other row first, then set // Enforce at-most-one-admin: clear every existing admin row first
// (TypeORM rejects an empty-where update, so target by isAdmin=true
// — the no-op cost when no rows match is one cheap query), then set
// the target. Two UPDATEs in one txn so a peer never sees two admins. // the target. Two UPDATEs in one txn so a peer never sees two admins.
await this.userRepo.manager.transaction(async (txn) => { await this.userRepo.manager.transaction(async (txn) => {
await txn.update(User, {}, { isAdmin: false }); await txn.update(User, { isAdmin: true }, { isAdmin: false });
await txn.update(User, { id: target.id }, { isAdmin: true }); await txn.update(User, { id: target.id }, { isAdmin: true });
}); });
await this.audit.write({ await this.audit.write({