✅ Updated Middleware Logic: - Enhanced admin route protection with Basic Auth for legacy routes and session-based auth for `/manage` and `/editor`. ✅ Improved Admin Panel Styles: - Added glassmorphism styles for admin components to enhance UI aesthetics. ✅ Refined Rate Limiting: - Adjusted rate limits for admin dashboard requests to allow more generous access. ✅ Introduced Analytics Reset API: - Added a new endpoint for resetting analytics data with rate limiting and admin authentication. 🎯 Overall Improvements: - Strengthened security and user experience for admin functionalities. - Enhanced visual design for better usability. - Streamlined analytics management processes.
56 lines
1.9 KiB
TypeScript
56 lines
1.9 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server';
|
|
|
|
// Generate CSRF token
|
|
async function generateCSRFToken(): Promise<string> {
|
|
const crypto = await import('crypto');
|
|
return crypto.randomBytes(32).toString('hex');
|
|
}
|
|
|
|
export async function GET(request: NextRequest) {
|
|
try {
|
|
// Rate limiting for CSRF token requests
|
|
const ip = request.headers.get('x-forwarded-for') || request.headers.get('x-real-ip') || 'unknown';
|
|
const now = Date.now();
|
|
|
|
// Simple in-memory rate limiting for CSRF tokens (in production, use Redis)
|
|
const key = `csrf_${ip}`;
|
|
const rateLimitMap = (global as unknown as Record<string, Map<string, { count: number; timestamp: number }>>).csrfRateLimit || ((global as unknown as Record<string, Map<string, { count: number; timestamp: number }>>).csrfRateLimit = new Map());
|
|
|
|
const current = rateLimitMap.get(key);
|
|
if (current && now - current.timestamp < 60000) { // 1 minute
|
|
if (current.count >= 10) {
|
|
return new NextResponse(
|
|
JSON.stringify({ error: 'Rate limit exceeded for CSRF tokens' }),
|
|
{ status: 429, headers: { 'Content-Type': 'application/json' } }
|
|
);
|
|
}
|
|
current.count++;
|
|
} else {
|
|
rateLimitMap.set(key, { count: 1, timestamp: now });
|
|
}
|
|
|
|
const csrfToken = await generateCSRFToken();
|
|
|
|
return new NextResponse(
|
|
JSON.stringify({ csrfToken }),
|
|
{
|
|
status: 200,
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-Content-Type-Options': 'nosniff',
|
|
'X-Frame-Options': 'DENY',
|
|
'X-XSS-Protection': '1; mode=block',
|
|
'Cache-Control': 'no-store, no-cache, must-revalidate, proxy-revalidate',
|
|
'Pragma': 'no-cache',
|
|
'Expires': '0'
|
|
}
|
|
}
|
|
);
|
|
} catch {
|
|
return new NextResponse(
|
|
JSON.stringify({ error: 'Internal server error' }),
|
|
{ status: 500, headers: { 'Content-Type': 'application/json' } }
|
|
);
|
|
}
|
|
}
|