65 lines
2.6 KiB
TypeScript
65 lines
2.6 KiB
TypeScript
import { queryClient } from '../lib/queryClient';
|
|
|
|
export const LOCAL_STORAGE_TOKEN_KEY = 'pfm_access_token';
|
|
export const LOCAL_STORAGE_USER_KEY = 'pfm_auth_user';
|
|
export const LOCAL_STORAGE_SUB_KEY = 'pfm_user_sub';
|
|
export const LOCAL_STORAGE_CLAIMS_KEY = 'pfm_user_claims';
|
|
export const LOCAL_STORAGE_USER_SYNC_KEY = 'pfm_user_sync_record';
|
|
export const LOCAL_STORAGE_ACTIVATION_PENDING_KEY = 'pfm_user_pending_activation';
|
|
export const LOCAL_STORAGE_ACTIVATION_REASON_KEY = 'pfm_user_pending_activation_reason';
|
|
|
|
export function isUserSyncEndpoint(url?: string): boolean {
|
|
if (!url) return false;
|
|
const clean = url.toLowerCase().split('?')[0];
|
|
return clean.includes('/users/sync') || clean.includes('/integration/sync') || clean.includes('/user/sync');
|
|
}
|
|
|
|
export function isTenantEndpoint(url?: string): boolean {
|
|
if (!url) return false;
|
|
return url.toLowerCase().includes('/governance/tenants');
|
|
}
|
|
|
|
type SessionExpiredListener = (reason?: string) => void;
|
|
const listeners = new Set<SessionExpiredListener>();
|
|
let hasTriggeredSessionExpired = false;
|
|
|
|
export function triggerSessionExpired(reason?: string, requestUrl?: string): void {
|
|
if (requestUrl && isUserSyncEndpoint(requestUrl)) return;
|
|
if (typeof window !== 'undefined' && localStorage.getItem(LOCAL_STORAGE_ACTIVATION_PENDING_KEY)) return;
|
|
if (hasTriggeredSessionExpired) return;
|
|
|
|
const hasExistingToken = typeof window !== 'undefined' && !!localStorage.getItem(LOCAL_STORAGE_TOKEN_KEY);
|
|
if (!hasExistingToken) return;
|
|
|
|
hasTriggeredSessionExpired = true;
|
|
if (typeof window !== 'undefined') {
|
|
window.dispatchEvent(new CustomEvent('pfm:session-expired', { detail: { reason: reason || 'HTTP 401 Unauthorized' } }));
|
|
}
|
|
listeners.forEach((cb) => cb(reason));
|
|
}
|
|
|
|
export function onSessionExpired(listener: SessionExpiredListener): () => void {
|
|
listeners.add(listener);
|
|
return () => { listeners.delete(listener); };
|
|
}
|
|
|
|
export function resetSessionExpiredState(): void {
|
|
hasTriggeredSessionExpired = false;
|
|
}
|
|
|
|
export function clearSessionAndRedirectToLanding(): void {
|
|
if (typeof window === 'undefined') return;
|
|
try {
|
|
localStorage.removeItem(LOCAL_STORAGE_TOKEN_KEY);
|
|
localStorage.removeItem(LOCAL_STORAGE_USER_KEY);
|
|
localStorage.removeItem(LOCAL_STORAGE_SUB_KEY);
|
|
localStorage.removeItem(LOCAL_STORAGE_CLAIMS_KEY);
|
|
localStorage.removeItem(LOCAL_STORAGE_USER_SYNC_KEY);
|
|
localStorage.removeItem(LOCAL_STORAGE_ACTIVATION_PENDING_KEY);
|
|
localStorage.removeItem(LOCAL_STORAGE_ACTIVATION_REASON_KEY);
|
|
} catch {}
|
|
try { queryClient.clear(); } catch {}
|
|
resetSessionExpiredState();
|
|
window.location.replace('/');
|
|
}
|