Enhance authentication handling

This commit is contained in:
2026-04-06 00:16:52 -04:00
parent 4b2b3d5a9f
commit c276f165f4
2 changed files with 37 additions and 12 deletions

View File

@@ -123,7 +123,12 @@ app.get('/me', async (req, res) => {
}
const user = userResult.rows[0];
// Check if user is active
if (!user.is_active) {
return res.status(403).json({ error: 'Account is inactive' });
}
// Get user permissions
let permissions = [];
if (!user.is_admin) {

View File

@@ -1,4 +1,4 @@
import { createContext, useState, useEffect, ReactNode, useCallback } from 'react';
import { createContext, useState, useEffect, useRef, ReactNode, useCallback } from 'react';
import config from '@/config';
export interface Permission {
@@ -61,14 +61,17 @@ export function AuthProvider({ children }: { children: ReactNode }) {
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(errorData.error || 'Failed to fetch user data');
console.error('Auth check failed:', response.status, errorData);
// Any failed /me response means the session is invalid — logout
logout();
return;
}
const userData = await response.json();
console.log("Fetched current user data:", userData);
console.log("User permissions:", userData.permissions);
console.log("User rocket_chat_user_id:", userData.rocket_chat_user_id);
setUser(userData);
// Ensure we have the sessionStorage isLoggedIn flag set
sessionStorage.setItem('isLoggedIn', 'true');
@@ -76,14 +79,7 @@ export function AuthProvider({ children }: { children: ReactNode }) {
const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred';
setError(errorMessage);
console.error('Auth error:', errorMessage);
// Clear token if authentication failed
if (err instanceof Error &&
(err.message.includes('authentication') ||
err.message.includes('token') ||
err.message.includes('401'))) {
logout();
}
// Network errors (server down, etc.) — don't logout, just show error
} finally {
setIsLoading(false);
}
@@ -99,6 +95,30 @@ export function AuthProvider({ children }: { children: ReactNode }) {
}
}, [token, fetchCurrentUser]);
// Re-validate auth when user returns to the tab after being away
const lastCheckRef = useRef(Date.now());
useEffect(() => {
const onVisibilityChange = () => {
if (document.visibilityState === 'visible' && token) {
const elapsed = Date.now() - lastCheckRef.current;
// Only re-check if at least 5 minutes have passed
if (elapsed > 5 * 60 * 1000) {
lastCheckRef.current = Date.now();
fetchCurrentUser();
}
}
};
document.addEventListener('visibilitychange', onVisibilityChange);
return () => document.removeEventListener('visibilitychange', onVisibilityChange);
}, [token, fetchCurrentUser]);
// Listen for auth:logout events from anywhere in the app (e.g. failed API calls)
useEffect(() => {
const onForceLogout = () => logout();
window.addEventListener('auth:logout', onForceLogout);
return () => window.removeEventListener('auth:logout', onForceLogout);
}, []);
const login = async (username: string, password: string) => {
try {
setIsLoading(true);