Quellcode durchsuchen

no message

master
Ursprung
Commit
d6af9543fd
3 geänderte Dateien mit 122 neuen und 36 gelöschten Zeilen
  1. +52
    -0
      src/components/Require2FA.js
  2. +29
    -15
      src/routes/ClientRoutes.js
  3. +41
    -21
      src/routes/SettingRoutes.js

+ 52
- 0
src/components/Require2FA.js Datei anzeigen

@@ -0,0 +1,52 @@
// src/components/Require2FA.jsx
import React, { useState, useEffect } from 'react';
import { Navigate } from 'react-router-dom';
import { Box, CircularProgress, Typography } from '@mui/material';
import axios from 'axios';
import { apiPath } from '../auth/utils';

const Require2FA = ({ children }) => {
const [is2FAEnabled, setIs2FAEnabled] = useState(null); // null = loading
const [error, setError] = useState(false);

useEffect(() => {
const check2FA = async () => {
try {
const response = await axios.get(`${apiPath}/2fa/status`, {
headers: { Authorization: `Bearer ${localStorage.getItem('accessToken')}` }
});
setIs2FAEnabled(response.data.enabled);
} catch (err) {
// Fallback to localStorage (same logic as in Profile page)
try {
const userData = JSON.parse(localStorage.getItem('userData') || '{}');
setIs2FAEnabled(!!userData.twoFactorEnabled);
} catch {
setError(true);
}
}
};

check2FA();
}, []);

if (is2FAEnabled === null) {
// Still loading
return (
<Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh' }}>
<CircularProgress />
<Typography sx={{ ml: 2 }}>Checking security settings...</Typography>
</Box>
);
}

if (!is2FAEnabled || error) {
// Redirect to profile page with a clear message
return <Navigate to="/profile" replace state={{ require2FA: true }} />;
}

// 2FA is enabled → allow access
return children;
};

export default Require2FA;

+ 29
- 15
src/routes/ClientRoutes.js Datei anzeigen

@@ -1,6 +1,6 @@
import {lazy, useContext} from 'react';

// project import
import Require2FA from '../components/Require2FA';
import Loadable from 'components/Loadable';
import MainLayout from "../layout/MainLayout";
import {handleRouteAbility} from "../utils/CommonFunction";
@@ -26,64 +26,78 @@ const ClientRoutes =() => {
path: '/',
element: <MainLayout />,
children: [
{
path: 'client',
element: (
handleRouteAbility(
<Require2FA>
{handleRouteAbility(
ability.can('VIEW', 'CLIENT'),
<ClientSearchPage />,
<Navigate to="/" />
)
)}
</Require2FA>
),
},
{
path: 'client/maintain/:id',
element: (
<Require2FA>
{
handleRouteAbility(
ability.can('VIEW', 'CLIENT'),
<ClientMaintainPage />,
<Navigate to="/" />
)
)}
</Require2FA>
),
},
{
path: '/pdf/:id',
element: (
handleRouteAbility(
ability.can('VIEW', 'CLIENT'),
<PdfSearchPage />,
<Navigate to="/" />
)
<Require2FA>
{handleRouteAbility(
ability.can('VIEW', 'CLIENT'),
<PdfSearchPage />,
<Navigate to="/" />
)}
</Require2FA>
),
},
{
path: '/pdf/maintain/:id',
element: (
handleRouteAbility(
<Require2FA>
{handleRouteAbility(
ability.can('VIEW', 'CLIENT'),
<PdfMaintainPage />,
<Navigate to="/" />
)
)}
</Require2FA>
),
},
{
path: '/template/',
element: (
handleRouteAbility(
<Require2FA>
{handleRouteAbility(
ability.can('VIEW', 'TEMPLATE'),
<TemplateSearchPage />,
<Navigate to="/" />
)
)}
</Require2FA>
),
},
{
path: '/pdf/form-up-down/:id',
element: (
handleRouteAbility(
<Require2FA>
{handleRouteAbility(
ability.can('VIEW', 'CLIENT'),
<PdfFormUpAndDown />,
<Navigate to="/" />
)
)}
</Require2FA>
),
},
{


+ 41
- 21
src/routes/SettingRoutes.js Datei anzeigen

@@ -1,6 +1,6 @@
import {lazy, useContext} from 'react';

// project import
import Require2FA from '../components/Require2FA';
import Loadable from 'components/Loadable';
import MainLayout from "../layout/MainLayout";
import AbilityContext from "../components/AbilityProvider";
@@ -102,102 +102,122 @@ const SettingRoutes = () => {
{
path: 'usergroupSearchview',
element: (
handleRouteAbility(
<Require2FA>
{handleRouteAbility(
ability.can('MAINTAIN', 'USER_GROUP'),
<UserGroupSearchPage />,
<Navigate to="/" />
)
)}
</Require2FA>
),
},
{
path: 'userGroup/:id',
element:(
handleRouteAbility(
<Require2FA>
{handleRouteAbility(
ability.can('MAINTAIN', 'USER_GROUP'),
<UserGroupDetailPage />,
<Navigate to="/" />
)
)}
</Require2FA>
),
},
{
path: 'user/:id',
element: (
handleRouteAbility(
<Require2FA>
{handleRouteAbility(
ability.can('VIEW', 'USER'),
<UserMaintainPage />,
<Navigate to="/" />
)
)}
</Require2FA>
),
},
{
path: 'userSearchview',
element:(
handleRouteAbility(
<Require2FA>
{handleRouteAbility(
ability.can('VIEW', 'USER'),
<UserSearchPage />,
<Navigate to="/" />
)
)}
</Require2FA>
),
},
{
path: 'consultant',
element: (
handleRouteAbility(
<Require2FA>
{handleRouteAbility(
ability.can('VIEW', 'USER'),
<ConsultantSearchPage />,
<Navigate to="/" />
)
)}
</Require2FA>
),
},
{
path: 'consultant/:id',
element: (
handleRouteAbility(
<Require2FA>
{handleRouteAbility(
ability.can('VIEW', 'USER'),
<ConsultantMaintainPage />,
<Navigate to="/" />
)
)}
</Require2FA>
),
},
{
path: 'setting',
element: (
handleRouteAbility(
<Require2FA>
{handleRouteAbility(
ability.can('MANAGE', 'SYSTEM_CONFIGURATION'),
<SettingPage />,
<Navigate to="/" />
)
)}
</Require2FA>
),
},
{
path: 'auditLog',
element:(
handleRouteAbility(
<Require2FA>
{handleRouteAbility(
ability.can('VIEW', 'AUDIT_LOG'),
<AuditLogPage />,
<Navigate to="/" />
)
)}
</Require2FA>
),
},
{
path: 'userActionLog',
element: (
handleRouteAbility(
<Require2FA>
{handleRouteAbility(
ability.can('VIEW', 'USER'),
<UserActionLogPage />,
<Navigate to="/" />
)
)}
</Require2FA>
),
},
{
path: 'loginLog',
element: (
handleRouteAbility(
<Require2FA>
{handleRouteAbility(
ability.can('VIEW', 'LOGIN_LOG'),
<LoginLogPage />,
<Navigate to="/" />
)
)}
</Require2FA>
),
},
{


Laden…
Abbrechen
Speichern