- Implemented Logout and RefreshToken methods in AuthenticationController. - Added IMailingService and IMailingRepository to Program.cs. - Updated project structure in Surge365.MassEmailReact.API.csproj. - Modified API host address and endpoints in Server.http. - Introduced AuthAppCode in appsettings.json for context distinction. - Changed GenerateTokens method to async in IAuthService. - Initialized string properties in User.cs to avoid null values. - Added new Mailing mapping in DapperConfiguration.cs. - Created MailingsController for handling mailing operations. - Developed Mailing, MailingUpdateDto, IMailingService, and IMailingRepository classes. - Updated frontend with MailingEdit and NewMailings components. - Enhanced authentication handling in AuthCheck.tsx and AuthContext.tsx. - Introduced ProtectedPageWrapper for route protection based on roles. - Added EmailList component for email input validation. - Updated utils.ts for token and cookie management functions. - Modified vite.config.ts for new HTTPS certificate name. - Updated CHANGELOG.md to reflect recent changes.
71 lines
2.6 KiB
TypeScript
71 lines
2.6 KiB
TypeScript
// src/components/auth/ProtectedPageWrapper.tsx
|
|
import React, { useEffect } from "react";
|
|
import { useNavigate } from "react-router-dom";
|
|
import { useTitle } from "@/context/TitleContext";
|
|
import utils from '@/ts/utils';
|
|
|
|
// Define role requirements for routes
|
|
export const routeRoleRequirements: Record<string, string[]> = {
|
|
'/home': [], // No role required
|
|
'/servers': ['ServerTab'], // Only Admins
|
|
'/targets': ['TargetTab'], // Users or Admins
|
|
'/testEmailLists': ['TestListTab'],
|
|
'/blockedEmails': ['BlockedEmailTab'],
|
|
'/emailDomains': ['DomainTab'],
|
|
'/unsubscribeUrls': ['UnsubscribeUrlTab'],
|
|
'/templates': ['TemplateTab'],
|
|
'/newMailings': ['NewMailingTab'],
|
|
'/scheduledMailings': ['ScheduledMailingTab'],
|
|
'/activeMailings': ['ActiveMailingTab'],
|
|
'/completedMailings': ['CompletedMailingTab'],
|
|
};
|
|
|
|
const ProtectedPageWrapper: React.FC<{ title: string; children: React.ReactNode }> = ({ title, children }) => {
|
|
const navigate = useNavigate();
|
|
const { setTitle } = useTitle();
|
|
const accessToken = localStorage.getItem('accessToken');
|
|
const currentPath = window.location.pathname; // Or use useLocation().pathname
|
|
|
|
useEffect(() => {
|
|
setTitle(title);
|
|
}, [title, setTitle]);
|
|
|
|
useEffect(() => {
|
|
const checkAuthAndRoles = async () => {
|
|
if (!accessToken || utils.isTokenExpired(accessToken)) {
|
|
try {
|
|
const response = await fetch('/api/authentication/refreshtoken', {
|
|
method: 'POST',
|
|
credentials: 'include',
|
|
});
|
|
if (response.ok) {
|
|
const data = await response.json();
|
|
localStorage.setItem('accessToken', data.accessToken);
|
|
} else {
|
|
navigate('/login');
|
|
}
|
|
} catch {
|
|
navigate('/login');
|
|
}
|
|
} else {
|
|
// Check roles
|
|
const userRoles = utils.getUserRoles(accessToken);
|
|
const requiredRoles = routeRoleRequirements[currentPath] || [];
|
|
const hasRequiredRole = requiredRoles.length === 0 || requiredRoles.some(role => userRoles.includes(role));
|
|
|
|
if (!hasRequiredRole) {
|
|
navigate('/home'); // Redirect to home if unauthorized
|
|
}
|
|
}
|
|
};
|
|
checkAuthAndRoles();
|
|
}, [navigate, accessToken, currentPath]);
|
|
|
|
if (!accessToken || utils.isTokenExpired(accessToken)) {
|
|
return null; // Or a loading spinner
|
|
}
|
|
|
|
return <>{children}</>;
|
|
};
|
|
|
|
export default ProtectedPageWrapper; |