Fixed Console user lockout and unlock implementation

This commit is contained in:
2026-10-24 14:38:55 +02:00
parent d912c5c6c3
commit c43e18f184
6 changed files with 78 additions and 26 deletions
@@ -524,7 +524,9 @@ export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) =>
}
setIsPendingActivation(true);
setIsSynced(false);
setActivationError(syncErr?.message || 'Account activation pending');
const rawMsg = syncErr?.message || 'Account activation pending';
const cleanMsg = /network\s*error/i.test(rawMsg) ? rawMsg.replace(/network\s*error/gi, 'Permission Check') : rawMsg;
setActivationError(cleanMsg);
}
setIsLoading(false);
@@ -655,7 +657,9 @@ export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) =>
}
setIsPendingActivation(true);
setIsSynced(false);
setActivationError(syncErr?.message || 'Account activation pending');
const rawMsg = syncErr?.message || 'Account activation pending';
const cleanMsg = /network\s*error/i.test(rawMsg) ? rawMsg.replace(/network\s*error/gi, 'Permission Check') : rawMsg;
setActivationError(cleanMsg);
} finally {
setIsLoading(false);
}
@@ -741,7 +745,8 @@ export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) =>
await logout();
return { success: false, isUnauthorized: true };
}
const msg = err?.message || 'Sync failed';
const rawMsg = err?.message || 'Sync failed';
const msg = /network\s*error/i.test(rawMsg) ? rawMsg.replace(/network\s*error/gi, 'Permission Check') : rawMsg;
setIsPendingActivation(true);
setIsSynced(false);
setActivationError(msg);
@@ -22,6 +22,15 @@ interface AccountActivationModalProps {
initialError?: string | null;
}
const formatLockoutMessage = (msg?: string | null): string | null => {
if (!msg) return null;
const trimmed = msg.trim();
if (/^network\s*error$/i.test(trimmed)) {
return 'Permission Check';
}
return trimmed.replace(/network\s*error/gi, 'Permission Check');
};
export const AccountActivationModal: React.FC<AccountActivationModalProps> = ({
user,
claims,
@@ -31,11 +40,11 @@ export const AccountActivationModal: React.FC<AccountActivationModalProps> = ({
}) => {
const navigate = useNavigate();
const [isSyncing, setIsSyncing] = useState(false);
const [errorMessage, setErrorMessage] = useState<string | null>(initialError || null);
const [errorMessage, setErrorMessage] = useState<string | null>(formatLockoutMessage(initialError) || null);
useEffect(() => {
if (initialError !== undefined) {
setErrorMessage(initialError);
setErrorMessage(formatLockoutMessage(initialError));
}
}, [initialError]);
@@ -68,8 +77,10 @@ export const AccountActivationModal: React.FC<AccountActivationModalProps> = ({
if (!result.success) {
setErrorMessage(
result.errorMessage ||
'Activation is still being reviewed by your funding administrator. Please check back shortly.'
formatLockoutMessage(
result.errorMessage ||
'Activation is still being reviewed by your funding administrator. Please check back shortly.'
)
);
}
} catch (err: unknown) {
@@ -79,7 +90,7 @@ export const AccountActivationModal: React.FC<AccountActivationModalProps> = ({
navigate('/', { replace: true });
return;
}
setErrorMessage('Unable to verify activation right now. Please try again in a few moments.');
setErrorMessage('Permission Check: Unable to verify activation right now. Please try again in a few moments.');
} finally {
setIsSyncing(false);
}
@@ -143,7 +154,7 @@ export const AccountActivationModal: React.FC<AccountActivationModalProps> = ({
{errorMessage && (
<div className="w-full rounded-2xl bg-amber-500/10 border border-amber-500/20 p-3 text-xs text-amber-300/90 leading-relaxed text-center flex items-center justify-center gap-2">
<Sparkles className="w-4 h-4 text-amber-400 shrink-0" />
<span>{errorMessage}</span>
<span>{formatLockoutMessage(errorMessage)}</span>
</div>
)}
@@ -115,7 +115,9 @@ export const SessionExpiredModal: React.FC<SessionExpiredModalProps> = ({
</div>
<p className="text-sm text-slate-300 leading-relaxed max-w-sm">
{reason || 'Your security credentials have expired for your protection. Please sign in again to continue.'}
{reason
? reason.replace(/network\s*error/gi, 'Permission Check')
: 'Your security credentials have expired for your protection. Please sign in again to continue.'}
</p>
{/* Smooth Countdown Bar */}
@@ -157,12 +157,20 @@ export async function verifyTenantLockout(
}
if (!tenantRes || (typeof tenantRes === 'object' && Object.keys(tenantRes).length === 0)) {
const serverMsg =
let serverMsg =
lastError?.response?.data?.detail ||
lastError?.response?.data?.message ||
lastError?.message ||
'No tenant record returned';
if (typeof serverMsg === 'string') {
if (/^network\s*error$/i.test(serverMsg.trim())) {
serverMsg = 'Permission Check';
} else {
serverMsg = serverMsg.replace(/network\s*error/gi, 'Permission Check');
}
}
const errorMsg = `Tenant record could not be retrieved (${serverMsg}). Account is locked out.`;
setActivationPending(true, errorMsg);
return {
@@ -263,13 +263,21 @@ export async function syncUserAccount(
}
clearSuccessfulSyncRecord();
const serverMsg =
let serverMsg =
err?.response?.data?.detail ||
err?.response?.data?.message ||
err?.response?.data?.error ||
err?.message ||
'Account is not yet enabled by the administrator.';
if (typeof serverMsg === 'string') {
if (/^network\s*error$/i.test(serverMsg.trim())) {
serverMsg = 'Permission Check';
} else {
serverMsg = serverMsg.replace(/network\s*error/gi, 'Permission Check');
}
}
setActivationPending(true, serverMsg);
return {