Wire production domain, CORS for tenant subdomains, celery volume mounts, and nginx reverse proxy configs for apex, API, identity, auth, and wildcard tenants. Co-authored-by: Cursor <cursoragent@cursor.com>
72 lines
1.6 KiB
TypeScript
72 lines
1.6 KiB
TypeScript
"use client";
|
|
|
|
import { useCallback, useEffect, useState } from "react";
|
|
import {
|
|
fetchAuthConfig,
|
|
fetchLoginUrl,
|
|
loginWithRedirect,
|
|
fetchMe,
|
|
getStoredToken,
|
|
clearTokens,
|
|
logout,
|
|
type AuthConfig,
|
|
} from "@/lib/auth";
|
|
|
|
interface AuthUser {
|
|
user_id: string;
|
|
email: string | null;
|
|
username: string | null;
|
|
roles: string[];
|
|
}
|
|
|
|
export function useAuth() {
|
|
const [config, setConfig] = useState<AuthConfig | null>(null);
|
|
const [user, setUser] = useState<AuthUser | null>(null);
|
|
const [loading, setLoading] = useState(true);
|
|
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
|
|
|
const load = useCallback(async () => {
|
|
setLoading(true);
|
|
try {
|
|
const cfg = await fetchAuthConfig();
|
|
setConfig(cfg);
|
|
const token = getStoredToken();
|
|
if (token) {
|
|
try {
|
|
const me = await fetchMe(token);
|
|
setUser(me);
|
|
setIsAuthenticated(true);
|
|
} catch {
|
|
clearTokens();
|
|
setUser(null);
|
|
setIsAuthenticated(false);
|
|
}
|
|
} else {
|
|
setUser(null);
|
|
setIsAuthenticated(false);
|
|
}
|
|
} catch {
|
|
clearTokens();
|
|
setUser(null);
|
|
setIsAuthenticated(false);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
load();
|
|
}, [load]);
|
|
|
|
const login = async (redirectPath?: string) => {
|
|
await loginWithRedirect(redirectPath);
|
|
};
|
|
|
|
const signOut = async () => {
|
|
const cfg = config || (await fetchAuthConfig());
|
|
await logout(cfg);
|
|
};
|
|
|
|
return { user, config, loading, isAuthenticated, login, signOut, reload: load };
|
|
}
|