Initial commit: Agentic OS troubleshooting platform
Self-hosted, Docker-based agentic troubleshooting platform: FastAPI backend + LangGraph agent, Next.js UI, tiered LLM routing (local Ollama -> Gemini -> DeepSeek -> OpenRouter), MCP server manager, encrypted device credentials, RBAC, audit log, project-memory + Obsidian integrations, and editable troubleshooting decision rules tuned for the GeneseasX vessel stack. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
75
frontend/lib/auth.tsx
Normal file
75
frontend/lib/auth.tsx
Normal file
@@ -0,0 +1,75 @@
|
||||
"use client";
|
||||
|
||||
import { createContext, useCallback, useContext, useEffect, useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { api, login as apiLogin, setToken, getToken } from "./api";
|
||||
|
||||
type Me = {
|
||||
id: number;
|
||||
email: string;
|
||||
full_name: string | null;
|
||||
role: "admin" | "support" | "readonly";
|
||||
is_active: boolean;
|
||||
};
|
||||
|
||||
type AuthCtx = {
|
||||
user: Me | null;
|
||||
loading: boolean;
|
||||
login: (email: string, password: string) => Promise<void>;
|
||||
logout: () => void;
|
||||
};
|
||||
|
||||
const Ctx = createContext<AuthCtx>({
|
||||
user: null,
|
||||
loading: true,
|
||||
login: async () => {},
|
||||
logout: () => {},
|
||||
});
|
||||
|
||||
export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||||
const [user, setUser] = useState<Me | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const router = useRouter();
|
||||
|
||||
const loadMe = useCallback(async () => {
|
||||
if (!getToken()) {
|
||||
setUser(null);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const me = await api<Me>("/api/auth/me");
|
||||
setUser(me);
|
||||
} catch {
|
||||
setUser(null);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
loadMe();
|
||||
}, [loadMe]);
|
||||
|
||||
const login = async (email: string, password: string) => {
|
||||
const res = await apiLogin(email, password);
|
||||
setToken(res.access_token);
|
||||
await loadMe();
|
||||
router.push("/");
|
||||
};
|
||||
|
||||
const logout = () => {
|
||||
setToken(null);
|
||||
setUser(null);
|
||||
router.push("/login");
|
||||
};
|
||||
|
||||
return <Ctx.Provider value={{ user, loading, login, logout }}>{children}</Ctx.Provider>;
|
||||
}
|
||||
|
||||
export const useAuth = () => useContext(Ctx);
|
||||
|
||||
export function roleAtLeast(role: string | undefined, min: "readonly" | "support" | "admin") {
|
||||
const rank: Record<string, number> = { readonly: 0, support: 1, admin: 2 };
|
||||
return (rank[role || "readonly"] ?? 0) >= rank[min];
|
||||
}
|
||||
Reference in New Issue
Block a user