All files / src/pages/auth AuthCallback.tsx

100% Statements 56/56
100% Branches 7/7
100% Functions 1/1
100% Lines 56/56

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 571x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 1x 1x 1x 4x 2x 2x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 1x 1x  
/**
 * @file AuthCallback.tsx
 * @description 
 * -OAuth2 redirect target. Verifies session via api/me, hydrates AuthContext,
 * then redirects to /dashboard. On failure goes abck to /login with error.
 */
import * as React from 'react';
import { useEffect } from 'react';
import { Box, CircularProgress, Typography } from '@mui/material';
import { useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import httpClient from '../../api/httpClient';
import { useAuth } from '../../hooks/useAuth';
 
/**
 * AuthCallback component
 * Handles the OAuth2 authentication callback and verifies the user session.
 */
const AuthCallback: React.FC = () => {
  const navigate = useNavigate();
  const { setUser } = useAuth();
  const { t } = useTranslation('auth');
 
  // On mount, verify the session by calling /api/me
  useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const { data } = await httpClient.get('/api/me');
        if (!cancelled) {
          setUser({ email: data.email, fullName: data.fullName, role: data.role });
          navigate('/dashboard', { replace: true });
        }
      } catch {
        if (!cancelled) navigate('/login?error=session', { replace: true });
      }
    })();
    return () => { cancelled = true; };
  }, [navigate, setUser]);
 
  /**
   * Render the loading state while verifying the user session.
   */
  return (
    <Box sx={{ minHeight: '100vh', display: 'grid', placeItems: 'center' }}>
      <Box textAlign="center">
        <CircularProgress />
        <Typography variant="body2" mt={2}>
          {t('verifying', { defaultValue: 'Verifying your login…' })}
        </Typography>
      </Box>
    </Box>
  );
};
 
export default AuthCallback;