'use client'; import api from '@/lib/api'; /** * Client-side "Login as user" (impersonation) helpers. * * The admin's own tokens are stashed under `admin*` keys while the active * `accessToken`/`refreshToken` are swapped for the impersonation tokens, so the * whole app (and the axios interceptor) transparently acts as the target user. * Both start and stop are recorded server-side in the audit log. */ const IMP_KEY = 'impersonation'; export interface ImpersonationInfo { targetUserId: string; targetName: string; } export function getImpersonation(): ImpersonationInfo | null { if (typeof window === 'undefined') return null; try { const raw = localStorage.getItem(IMP_KEY); return raw ? (JSON.parse(raw) as ImpersonationInfo) : null; } catch { return null; } } export function isImpersonating(): boolean { return getImpersonation() !== null; } /** Begin impersonating a user. Caller should hard-reload afterwards. */ export async function startImpersonation(targetUserId: string): Promise { const { data } = await api.post(`/admin/users/${targetUserId}/impersonate`); // Stash the admin session so we can return to it later. localStorage.setItem('adminAccessToken', localStorage.getItem('accessToken') ?? ''); localStorage.setItem('adminRefreshToken', localStorage.getItem('refreshToken') ?? ''); const info: ImpersonationInfo = { targetUserId, targetName: `${data.user?.firstName ?? ''} ${data.user?.lastName ?? ''}`.trim(), }; localStorage.setItem(IMP_KEY, JSON.stringify(info)); // Swap in the impersonation tokens. localStorage.setItem('accessToken', data.accessToken); localStorage.setItem('refreshToken', data.refreshToken); return info; } /** End impersonation, restoring the admin session. Caller should hard-reload. */ export async function stopImpersonation(): Promise { const info = getImpersonation(); const adminAccess = localStorage.getItem('adminAccessToken'); const adminRefresh = localStorage.getItem('adminRefreshToken'); // Restore the admin tokens first so the stop call is authorized as the admin. if (adminAccess) localStorage.setItem('accessToken', adminAccess); if (adminRefresh) localStorage.setItem('refreshToken', adminRefresh); localStorage.removeItem('adminAccessToken'); localStorage.removeItem('adminRefreshToken'); localStorage.removeItem(IMP_KEY); if (info?.targetUserId) { try { await api.post(`/admin/users/${info.targetUserId}/impersonation/stop`); } catch { // Best-effort audit; never block returning to the admin session. } } return info?.targetUserId ?? null; } /** Clear any impersonation artefacts (used on full logout). */ export function clearImpersonation(): void { if (typeof window === 'undefined') return; localStorage.removeItem('adminAccessToken'); localStorage.removeItem('adminRefreshToken'); localStorage.removeItem(IMP_KEY); }