changes made to fix the VAPT testing

This commit is contained in:
laxmanhalaki 2026-02-07 14:57:21 +05:30
parent c97053e0e3
commit 81565d294b
11 changed files with 229 additions and 221 deletions

View File

@ -1,61 +1,23 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head>
<head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<!-- CSP: Allows blob URLs for file previews and cross-origin API calls during development -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self' blob:; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; script-src 'self'; img-src 'self' data: https: blob:; connect-src 'self' blob: data: http://localhost:5000 http://localhost:3000 ws://localhost:5000 ws://localhost:3000 wss://localhost:5000 wss://localhost:3000; frame-src 'self' blob:; font-src 'self' https://fonts.gstatic.com data:; object-src 'none'; base-uri 'self'; form-action 'self';" />
<link rel="icon" type="image/svg+xml" href="/royal_enfield_logo.svg" /> <link rel="icon" type="image/svg+xml" href="/royal_enfield_logo.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Royal Enfield Approval & Request Management Portal - Streamlined approval workflows for enterprise operations" /> <meta name="description"
content="Royal Enfield Approval & Request Management Portal - Streamlined approval workflows for enterprise operations" />
<meta name="theme-color" content="#2d4a3e" /> <meta name="theme-color" content="#2d4a3e" />
<title>Royal Enfield | Approval Portal</title> <title>Royal Enfield | Approval Portal</title>
<!-- Preload critical fonts and icons --> <!-- Preload critical fonts and icons -->
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
</head>
<!-- Ensure proper icon rendering and layout --> <body>
<style>
/* Ensure Lucide icons render properly */
svg {
display: inline-block;
vertical-align: middle;
}
/* Fix for icon alignment in buttons */
button svg {
flex-shrink: 0;
}
/* Ensure proper text rendering */
body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
}
/* Fix for mobile viewport and sidebar */
@media (max-width: 768px) {
html {
overflow-x: hidden;
}
}
/* Ensure proper sidebar toggle behavior */
.sidebar-toggle {
transition: all 0.3s ease-in-out;
}
/* Fix for icon button hover states */
button:hover svg {
transform: scale(1.05);
transition: transform 0.2s ease;
}
</style>
</head>
<body>
<div id="root"></div> <div id="root"></div>
<script type="module" src="/src/main.tsx"></script> <script type="module" src="/src/main.tsx"></script>
</body> </body>
</html>
</html>

View File

@ -30,7 +30,7 @@ export function FormattedDescription({ content, className }: FormattedDescriptio
} }
// Wrap the table in a scrollable container // Wrap the table in a scrollable container
return `<div class="table-wrapper" style="overflow-x: auto; max-width: 100%; margin: 8px 0;">${match}</div>`; return `<div class="table-wrapper">${match}</div>`;
}); });
return processed; return processed;

View File

@ -169,9 +169,6 @@ export function RichTextEditor({
// Wrap table in scrollable container for mobile // Wrap table in scrollable container for mobile
const wrapper = document.createElement('div'); const wrapper = document.createElement('div');
wrapper.className = 'table-wrapper'; wrapper.className = 'table-wrapper';
wrapper.style.overflowX = 'auto';
wrapper.style.maxWidth = '100%';
wrapper.style.margin = '8px 0';
wrapper.appendChild(table); wrapper.appendChild(table);
fragment.appendChild(wrapper); fragment.appendChild(wrapper);
} }

View File

@ -5,6 +5,7 @@ import { AuthProvider } from './contexts/AuthContext';
import { AuthenticatedApp } from './pages/Auth'; import { AuthenticatedApp } from './pages/Auth';
import { store } from './redux/store'; import { store } from './redux/store';
import './styles/globals.css'; import './styles/globals.css';
import './styles/base-layout.css';
ReactDOM.createRoot(document.getElementById('root')!).render( ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode> <React.StrictMode>

View File

@ -33,8 +33,7 @@ export function CriticalAlertsSection({
}: CriticalAlertsSectionProps) { }: CriticalAlertsSectionProps) {
return ( return (
<Card <Card
className="lg:col-span-2 shadow-md hover:shadow-lg transition-shadow flex flex-col overflow-hidden" className="lg:col-span-2 shadow-md hover:shadow-lg transition-shadow flex flex-col overflow-hidden h-full"
style={{ height: '100%' }}
data-testid="critical-alerts-section" data-testid="critical-alerts-section"
> >
<CardHeader className="pb-3 sm:pb-4 flex-shrink-0"> <CardHeader className="pb-3 sm:pb-4 flex-shrink-0">
@ -60,8 +59,7 @@ export function CriticalAlertsSection({
</div> </div>
</CardHeader> </CardHeader>
<CardContent <CardContent
className="overflow-y-auto flex-1 p-4" className={`overflow-y-auto flex-1 p-4 ${pagination.totalPages > 1 ? 'max-h-[calc(100%-140px)]' : 'max-h-[calc(100%-80px)]'}`}
style={{ maxHeight: pagination.totalPages > 1 ? 'calc(100% - 140px)' : 'calc(100% - 80px)' }}
> >
<div className="space-y-3 sm:space-y-4"> <div className="space-y-3 sm:space-y-4">
{breachedRequests.length === 0 ? ( {breachedRequests.length === 0 ? (

View File

@ -84,11 +84,7 @@ export function PriorityDistributionReport({
fill="#1f2937" fill="#1f2937"
textAnchor={x > cx ? 'start' : 'end'} textAnchor={x > cx ? 'start' : 'end'}
dominantBaseline="central" dominantBaseline="central"
style={{ className="text-sm font-semibold pointer-events-none"
fontSize: '14px',
fontWeight: '600',
pointerEvents: 'none',
}}
> >
{`${name}: ${percentage}%`} {`${name}: ${percentage}%`}
</text> </text>
@ -102,13 +98,13 @@ export function PriorityDistributionReport({
onNavigate(`requests?priority=${data.priority}`); onNavigate(`requests?priority=${data.priority}`);
} }
}} }}
style={{ cursor: 'pointer' }} className="cursor-pointer"
> >
{priorityDistribution.map((priority, index) => ( {priorityDistribution.map((priority, index) => (
<Cell <Cell
key={`cell-${index}`} key={`cell-${index}`}
fill={priority.priority === 'express' ? '#ef4444' : '#3b82f6'} fill={priority.priority === 'express' ? '#ef4444' : '#3b82f6'}
style={{ cursor: 'pointer' }} className="cursor-pointer"
/> />
))} ))}
</Pie> </Pie>

View File

@ -40,8 +40,7 @@ export function RecentActivitySection({
}: RecentActivitySectionProps) { }: RecentActivitySectionProps) {
return ( return (
<Card <Card
className="lg:col-span-1 shadow-md hover:shadow-lg transition-shadow flex flex-col overflow-hidden" className="lg:col-span-1 shadow-md hover:shadow-lg transition-shadow flex flex-col overflow-hidden h-full"
style={{ height: '100%' }}
data-testid="recent-activity-section" data-testid="recent-activity-section"
> >
<CardHeader className="pb-3 sm:pb-4 flex-shrink-0"> <CardHeader className="pb-3 sm:pb-4 flex-shrink-0">
@ -73,8 +72,7 @@ export function RecentActivitySection({
</div> </div>
</CardHeader> </CardHeader>
<CardContent <CardContent
className="overflow-y-auto flex-1 p-4" className={`overflow-y-auto flex-1 p-4 ${pagination.totalPages > 1 ? 'max-h-[calc(100%-140px)]' : 'max-h-[calc(100%-80px)]'}`}
style={{ maxHeight: pagination.totalPages > 1 ? 'calc(100% - 140px)' : 'calc(100% - 80px)' }}
> >
<div className="space-y-2 sm:space-y-3"> <div className="space-y-2 sm:space-y-3">
{recentActivity.length === 0 ? ( {recentActivity.length === 0 ? (

View File

@ -17,22 +17,28 @@ import { formatDateDDMMYYYY } from '@/utils/dateFormatter';
const stripHtmlTags = (html: string): string => { const stripHtmlTags = (html: string): string => {
if (!html) return ''; if (!html) return '';
// Check if we're in a browser environment // 1. Replace block-level tags with a space to avoid merging words (e.g. </div><div> -> " ")
if (typeof document === 'undefined') { // This preserves readability for the card preview
// Fallback for SSR: use regex to strip HTML tags let text = html.replace(/<(address|article|aside|blockquote|canvas|dd|div|dl|dt|fieldset|figcaption|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hr|li|main|nav|noscript|ol|p|pre|section|table|tfoot|ul|video)[^>]*>/gi, ' ');
return html.replace(/<[^>]*>/g, '').replace(/\s+/g, ' ').trim();
}
// Create a temporary div to parse HTML // 2. Replace <br> with space
const tempDiv = document.createElement('div'); text = text.replace(/<br\s*\/?>/gi, ' ');
tempDiv.innerHTML = html;
// Get text content (automatically strips HTML tags) // 3. Strip all other tags
let text = tempDiv.textContent || tempDiv.innerText || ''; text = text.replace(/<[^>]*>/g, '');
// Clean up extra whitespace // 4. Clean up extra whitespace
text = text.replace(/\s+/g, ' ').trim(); text = text.replace(/\s+/g, ' ').trim();
// 5. Basic HTML entity decoding for common characters
text = text
.replace(/&nbsp;/g, ' ')
.replace(/&amp;/g, '&')
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
.replace(/&quot;/g, '"')
.replace(/&#039;/g, "'");
return text; return text;
}; };

View File

@ -16,22 +16,28 @@ import { formatDateDDMMYYYY } from '@/utils/dateFormatter';
const stripHtmlTags = (html: string): string => { const stripHtmlTags = (html: string): string => {
if (!html) return ''; if (!html) return '';
// Check if we're in a browser environment // 1. Replace block-level tags with a space to avoid merging words (e.g. </div><div> -> " ")
if (typeof document === 'undefined') { // This preserves readability for the card preview
// Fallback for SSR: use regex to strip HTML tags let text = html.replace(/<(address|article|aside|blockquote|canvas|dd|div|dl|dt|fieldset|figcaption|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hr|li|main|nav|noscript|ol|p|pre|section|table|tfoot|ul|video)[^>]*>/gi, ' ');
return html.replace(/<[^>]*>/g, '').replace(/\s+/g, ' ').trim();
}
// Create a temporary div to parse HTML // 2. Replace <br> with space
const tempDiv = document.createElement('div'); text = text.replace(/<br\s*\/?>/gi, ' ');
tempDiv.innerHTML = html;
// Get text content (automatically strips HTML tags) // 3. Strip all other tags
let text = tempDiv.textContent || tempDiv.innerText || ''; text = text.replace(/<[^>]*>/g, '');
// Clean up extra whitespace // 4. Clean up extra whitespace
text = text.replace(/\s+/g, ' ').trim(); text = text.replace(/\s+/g, ' ').trim();
// 5. Basic HTML entity decoding for common characters
text = text
.replace(/&nbsp;/g, ' ')
.replace(/&amp;/g, '&')
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
.replace(/&quot;/g, '"')
.replace(/&#039;/g, "'");
return text; return text;
}; };

View File

@ -0,0 +1,42 @@
/* Ensure Lucide icons render properly */
svg {
display: inline-block;
vertical-align: middle;
}
/* Fix for icon alignment in buttons */
button svg {
flex-shrink: 0;
}
/* Ensure proper text rendering */
body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
}
/* Fix for mobile viewport and sidebar */
@media (max-width: 768px) {
html {
overflow-x: hidden;
}
}
/* Ensure proper sidebar toggle behavior */
.sidebar-toggle {
transition: all 0.3s ease-in-out;
}
/* Fix for icon button hover states */
button:hover svg {
transform: scale(1.05);
transition: transform 0.2s ease;
}
/* Table wrapper for CSP-compliant horizontal scrolling */
.table-wrapper {
overflow-x: auto;
max-width: 100%;
margin: 8px 0;
}

View File

@ -75,8 +75,6 @@ export default defineConfig({
server: { server: {
port: 3000, port: 3000,
open: true, open: true,
host: true,
allowedHosts: ['9b89f4bfd360.ngrok-free.app','c6ba819712b5.ngrok-free.app'],
}, },
build: { build: {
outDir: 'dist', outDir: 'dist',
@ -173,6 +171,10 @@ export default defineConfig({
}, },
chunkSizeWarningLimit: 1500, // Increased limit since we have manual chunks chunkSizeWarningLimit: 1500, // Increased limit since we have manual chunks
}, },
esbuild: {
// CRITICAL: Strip all legal comments to prevent "Suspicious Comments" alerts (e.g. from Redux docs)
legalComments: 'none',
},
optimizeDeps: { optimizeDeps: {
include: [ include: [
'react', 'react',