mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-07 02:59:05 +00:00
Update page.tsx
This commit is contained in:
parent
36c971a6fd
commit
4de4e4af1a
1 changed files with 76 additions and 10 deletions
|
|
@ -41,8 +41,33 @@ import { UiLoadingSpinner } from "@/components/ui/ui-loading-spinner";
|
|||
import { cx } from "@/lib/cva.config";
|
||||
|
||||
function getCookie(name: string) {
|
||||
const cookieValue = document.cookie.split("; ").find((row) => row.startsWith(name + "="));
|
||||
return cookieValue ? cookieValue.split("=")[1] : null;
|
||||
// Safer cookie read + decoding; handles '=' inside values
|
||||
const match = document.cookie.split("; ").find((row) => row.startsWith(name + "="));
|
||||
if (!match) return null;
|
||||
const value = match.slice(name.length + 1);
|
||||
try {
|
||||
return decodeURIComponent(value);
|
||||
} catch {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function deleteCookie(name: string, path = "/") {
|
||||
// Best-effort client-side clear (works for non-HttpOnly cookies without Domain)
|
||||
document.cookie = `${name}=; Max-Age=0; Path=${path}`;
|
||||
}
|
||||
|
||||
function isJwtExpired(token: string): boolean {
|
||||
try {
|
||||
const decoded: any = jwtDecode(token);
|
||||
if (decoded && typeof decoded.exp === "number") {
|
||||
return decoded.exp * 1000 <= Date.now();
|
||||
}
|
||||
return false;
|
||||
} catch {
|
||||
// If we can't decode, treat as invalid/expired
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function formatUserRole(userRole: string) {
|
||||
|
|
@ -149,17 +174,42 @@ export default function CreateKeyPage() {
|
|||
const redirectToLogin = authLoading === false && token === null && invitation_id === null;
|
||||
|
||||
useEffect(() => {
|
||||
const token = getCookie("token");
|
||||
getUiConfig().then((data) => {
|
||||
// get the information for constructing the proxy base url, and then set the token and auth loading
|
||||
setToken(token);
|
||||
setAuthLoading(false);
|
||||
});
|
||||
let cancelled = false;
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
await getUiConfig(); // ensures proxyBaseUrl etc. are ready
|
||||
} catch {
|
||||
// proceed regardless; we still need to decide auth state
|
||||
}
|
||||
|
||||
if (cancelled) return;
|
||||
|
||||
const raw = getCookie("token");
|
||||
const valid = raw && !isJwtExpired(raw) ? raw : null;
|
||||
|
||||
// If token exists but is invalid/expired, clear it so downstream code
|
||||
// doesn't keep trying to use it and cause redirect spasms.
|
||||
if (raw && !valid) {
|
||||
deleteCookie("token", "/");
|
||||
}
|
||||
|
||||
if (!cancelled) {
|
||||
setToken(valid);
|
||||
setAuthLoading(false);
|
||||
}
|
||||
})();
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (redirectToLogin) {
|
||||
window.location.href = (proxyBaseUrl || "") + "/sso/key/generate";
|
||||
// Replace instead of assigning to avoid back-button loops
|
||||
const dest = (proxyBaseUrl || "") + "/sso/key/generate";
|
||||
window.location.replace(dest);
|
||||
}
|
||||
}, [redirectToLogin]);
|
||||
|
||||
|
|
@ -168,7 +218,23 @@ export default function CreateKeyPage() {
|
|||
return;
|
||||
}
|
||||
|
||||
const decoded = jwtDecode(token) as { [key: string]: any };
|
||||
// Defensive: re-check expiry in case cookie changed after mount
|
||||
if (isJwtExpired(token)) {
|
||||
deleteCookie("token", "/");
|
||||
setToken(null);
|
||||
return;
|
||||
}
|
||||
|
||||
let decoded: any = null;
|
||||
try {
|
||||
decoded = jwtDecode(token);
|
||||
} catch {
|
||||
// Malformed token → treat as unauthenticated
|
||||
deleteCookie("token", "/");
|
||||
setToken(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (decoded) {
|
||||
// set accessToken
|
||||
setAccessToken(decoded.key);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue