feat: multi-user UI login with admin and monitor roles
Add sac_users table, JWT roles, settings/users API guarded for admin, Users page in UI, and sac_manage_user.py CLI. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,15 +1,34 @@
|
||||
const TOKEN_KEY = "sac_token";
|
||||
const ROLE_KEY = "sac_role";
|
||||
|
||||
export function getToken(): string | null {
|
||||
return localStorage.getItem(TOKEN_KEY);
|
||||
}
|
||||
|
||||
export function getRole(): string | null {
|
||||
return localStorage.getItem(ROLE_KEY);
|
||||
}
|
||||
|
||||
export function isAdmin(): boolean {
|
||||
return getRole() === "admin";
|
||||
}
|
||||
|
||||
export function setToken(token: string): void {
|
||||
localStorage.setItem(TOKEN_KEY, token);
|
||||
}
|
||||
|
||||
export function setRole(role: string): void {
|
||||
localStorage.setItem(ROLE_KEY, role);
|
||||
}
|
||||
|
||||
export function setAuth(token: string, role: string): void {
|
||||
setToken(token);
|
||||
setRole(role);
|
||||
}
|
||||
|
||||
export function clearToken(): void {
|
||||
localStorage.removeItem(TOKEN_KEY);
|
||||
localStorage.removeItem(ROLE_KEY);
|
||||
}
|
||||
|
||||
export async function apiFetch<T>(path: string, init: RequestInit = {}): Promise<T> {
|
||||
@@ -27,6 +46,9 @@ export async function apiFetch<T>(path: string, init: RequestInit = {}): Promise
|
||||
window.location.href = "/login";
|
||||
throw new Error("Unauthorized");
|
||||
}
|
||||
if (res.status === 403) {
|
||||
throw new Error("Forbidden");
|
||||
}
|
||||
if (!res.ok) {
|
||||
const text = await res.text();
|
||||
throw new Error(text || res.statusText);
|
||||
@@ -37,6 +59,17 @@ export async function apiFetch<T>(path: string, init: RequestInit = {}): Promise
|
||||
export interface TokenResponse {
|
||||
access_token: string;
|
||||
token_type: string;
|
||||
username: string;
|
||||
role: string;
|
||||
}
|
||||
|
||||
export interface MeResponse {
|
||||
username: string;
|
||||
role: string;
|
||||
}
|
||||
|
||||
export function fetchMe(): Promise<MeResponse> {
|
||||
return apiFetch<MeResponse>("/api/v1/auth/me");
|
||||
}
|
||||
|
||||
export interface EventSummary {
|
||||
|
||||
Reference in New Issue
Block a user