AI Implementation feature(841): First-Start Create Admin Modal 1.00 (#3)

This commit was merged in pull request #3.
This commit is contained in:
2026-07-21 15:07:44 +00:00
parent 9f67ec8c50
commit 960516a7bc
18 changed files with 518 additions and 112 deletions
@@ -0,0 +1,14 @@
export type AdminGuardDecision =
| { kind: 'allow' }
| { kind: 'redirect'; path: '/bootstrap' | '/login' | '/' };
export function decideAdminGuard(input: {
initialized: boolean;
isAuthenticated: boolean;
role: 'admin' | 'player' | undefined;
}): AdminGuardDecision {
if (!input.initialized) return { kind: 'redirect', path: '/bootstrap' };
if (!input.isAuthenticated) return { kind: 'redirect', path: '/login' };
if (input.role !== 'admin') return { kind: 'redirect', path: '/' };
return { kind: 'allow' };
}
@@ -0,0 +1,23 @@
import { inject } from '@angular/core';
import { CanActivateFn, Router } from '@angular/router';
import { AuthService } from '../services/auth.service';
import { BootstrapService } from '../services/bootstrap.service';
import { decideAdminGuard } from './admin.guard.decision';
export { decideAdminGuard } from './admin.guard.decision';
export type { AdminGuardDecision } from './admin.guard.decision';
export const adminGuard: CanActivateFn = () => {
const auth = inject(AuthService);
const bootstrap = inject(BootstrapService);
const router = inject(Router);
const decision = decideAdminGuard({
initialized: bootstrap.initialized(),
isAuthenticated: auth.isAuthenticated(),
role: auth.currentUser()?.role,
});
if (decision.kind === 'allow') return true;
return router.createUrlTree([decision.path]);
};
@@ -0,0 +1,20 @@
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { firstValueFrom } from 'rxjs';
export interface AdminUser {
id: string;
username: string;
role: 'admin' | 'player';
}
@Injectable({ providedIn: 'root' })
export class AdminService {
private readonly http = inject(HttpClient);
async listUsers(): Promise<AdminUser[]> {
return firstValueFrom(
this.http.get<AdminUser[]>('/api/v1/admin/users', { withCredentials: true }),
);
}
}