![]() Server : Apache/2 System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64 User : gositeme ( 1004) PHP Version : 8.2.29 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/gositeme/domains/lavocat.ca/public_html/src/hooks/ |
import { useState, useEffect } from 'react';
import { useSession } from 'next-auth/react';
import { toast } from 'react-hot-toast';
import { useRouter } from 'next/router';
export function useImpersonation() {
const { data: session, update } = useSession();
const [isImpersonating, setIsImpersonating] = useState(false);
const router = useRouter();
// Debug logging for session state changes
useEffect(() => {
console.log('đ useImpersonation - Session state changed:', {
hasSession: !!session,
userId: session?.user?.id,
email: session?.user?.email,
role: session?.user?.role,
isImpersonating: session?.user?.isImpersonating,
originalUser: session?.user?.originalUser,
isImpersonatingState: isImpersonating
});
}, [session, isImpersonating]);
const impersonateUser = async (userId: string, userName: string) => {
if (!session?.user) {
toast.error('Not authenticated');
return false;
}
// Check if we're already impersonating - if so, use original user's role
const effectiveRole = session.user.isImpersonating && session.user.originalUser
? session.user.originalUser.role
: session.user.role;
console.log('đ Impersonation check:', {
effectiveRole,
currentRole: session.user.role,
isImpersonating: session.user.isImpersonating,
originalUser: session.user.originalUser
});
if (effectiveRole !== 'SUPERADMIN' && effectiveRole !== 'ADMIN') {
toast.error('Only Super Admins and Admins can impersonate users');
return false;
}
// Check if already impersonating
if (session.user.isImpersonating) {
toast.error('Already impersonating a user. Please stop current impersonation first.');
return false;
}
setIsImpersonating(true);
try {
console.log('đ Starting impersonation request for userId:', userId);
console.log('đ Effective role for impersonation:', effectiveRole);
console.log('đ Current session:', {
userId: session.user.id,
email: session.user.email,
role: session.user.role,
isImpersonating: session.user.isImpersonating
});
const response = await fetch('/api/admin/impersonate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ userId }),
});
console.log('đ Response received:', {
status: response.status,
statusText: response.statusText,
ok: response.ok
});
if (!response.ok) {
let errorMessage = 'Failed to impersonate user';
let errorDetails = '';
try {
const errorData = await response.json();
errorMessage = errorData.error || errorData.message || errorMessage;
errorDetails = errorData.details || '';
} catch (parseError) {
console.error('Failed to parse error response:', parseError);
try {
const text = await response.text();
console.error('Raw error response:', text);
errorMessage = `Server error (${response.status}): ${text || 'Unknown error'}`;
} catch (textError) {
console.error('Failed to read response as text:', textError);
errorMessage = `Server error (${response.status}): Unable to read response`;
}
}
console.error('â Impersonation failed:', {
status: response.status,
errorMessage,
errorDetails
});
// Show more specific error messages
if (response.status === 429) {
toast.error('Rate limit exceeded. Please wait a moment and try again.');
} else if (response.status === 403) {
toast.error('Access denied. You may not have permission to impersonate this user.');
} else if (response.status === 404) {
toast.error('User not found.');
} else {
toast.error(errorMessage);
}
return false;
}
let data;
try {
data = await response.json();
console.log('â
Impersonation success data:', data);
} catch (parseError) {
console.error('Failed to parse success response:', parseError);
toast.error('Invalid response from server');
return false;
}
toast.success(`đ Impersonation initiated for ${userName}`, {
duration: 3000,
icon: 'đ¤',
});
// Force session update with trigger parameter
console.log('đ Forcing session update...');
await update({ trigger: 'update' });
// Wait longer for the session to update and ensure it's propagated
console.log('đ Waiting for session to update...');
await new Promise(resolve => setTimeout(resolve, 1500));
// Force a page reload to ensure all components get the new session
console.log('đ Reloading page to ensure session consistency...');
window.location.href = data.redirectUrl;
return true;
} catch (error) {
console.error('â Impersonation error:', error);
// Handle network errors specifically
if (error instanceof TypeError && error.message.includes('fetch')) {
toast.error('Network error. Please check your connection and try again.');
} else {
toast.error(error instanceof Error ? error.message : 'Failed to impersonate user');
}
return false;
} finally {
setIsImpersonating(false);
}
};
const stopImpersonation = async () => {
try {
console.log('đ stopImpersonation - Starting...');
console.log('đ Current session state:', {
isImpersonating: session?.user?.isImpersonating,
originalUser: session?.user?.originalUser
});
const response = await fetch('/api/admin/stop-impersonation', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
});
console.log('đ Stop impersonation response:', {
status: response.status,
statusText: response.statusText,
ok: response.ok
});
const data = await response.json();
if (response.ok) {
console.log('â
stopImpersonation - API success:', data);
toast.success('đ Impersonation stopped successfully', {
duration: 2000,
icon: 'đ¤',
});
// Force session update with trigger parameter
console.log('đ stopImpersonation - Updating session...');
await update({ trigger: 'update' });
// Wait longer for the session to update
console.log('đ stopImpersonation - Waiting for session to update...');
await new Promise(resolve => setTimeout(resolve, 1500));
// Force a page reload to ensure all components get the new session
console.log('đ stopImpersonation - Reloading page to ensure session consistency...');
window.location.href = '/admin/dashboard';
} else {
console.error('â stopImpersonation - API error:', data);
// Handle the case where user is not currently impersonating
if (data.error === 'Not currently impersonating' || data.error?.includes('not impersonating')) {
console.log('âšī¸ stopImpersonation - User is not currently impersonating, redirecting to admin dashboard');
toast('Not currently impersonating any user');
router.push('/admin/dashboard');
return;
}
toast.error(data.error || 'Failed to stop impersonation');
console.warn('â ī¸ stopImpersonation - Non-critical error, forcing hard reload');
window.location.href = '/admin/dashboard';
}
} catch (error) {
console.error('â stopImpersonation - Error:', error);
// Handle network errors or other issues gracefully
toast.error('Network error while stopping impersonation');
console.warn('â ī¸ stopImpersonation - Network error, forcing hard reload');
window.location.href = '/admin/dashboard';
}
};
// Enhanced return object with more debugging info
return {
impersonateUser,
stopImpersonation,
isImpersonating,
isCurrentlyImpersonating: session?.user?.isImpersonating || false,
originalUser: session?.user?.originalUser || null,
canImpersonate: !session?.user?.isImpersonating && !isImpersonating,
debugInfo: {
sessionExists: !!session,
userRole: session?.user?.role,
isImpersonating: session?.user?.isImpersonating,
originalUserRole: session?.user?.originalUser?.role
}
};
}