Major additions: - Territory manager system with application workflow - Custom pricing and page builder with Craft.js - Enhanced Stripe Connect onboarding - CodeReadr QR scanning integration - Kiosk mode for venue sales - Super admin dashboard and analytics - MCP integration for AI-powered operations Infrastructure improvements: - Centralized API client and routing system - Enhanced authentication with organization context - Comprehensive theme management system - Advanced event management with custom tabs - Performance monitoring and accessibility features Database schema updates: - Territory management tables - Custom pages and pricing structures - Kiosk PIN system - Enhanced organization profiles - CodeReadr integration tables 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
70 lines
2.2 KiB
TypeScript
70 lines
2.2 KiB
TypeScript
import { defineMiddleware } from 'astro/middleware';
|
|
|
|
export const onRequest = defineMiddleware(async (context, next) => {
|
|
// Security headers
|
|
const securityHeaders = {
|
|
// HTTPS enforcement
|
|
'Strict-Transport-Security': 'max-age=31536000; includeSubDomains; preload',
|
|
|
|
// XSS protection
|
|
'X-XSS-Protection': '1; mode=block',
|
|
|
|
// Content type sniffing protection
|
|
'X-Content-Type-Options': 'nosniff',
|
|
|
|
// Frame options disabled - Using CSP frame-ancestors instead for Stripe compatibility
|
|
// 'X-Frame-Options': 'SAMEORIGIN',
|
|
|
|
// Referrer policy
|
|
'Referrer-Policy': 'strict-origin-when-cross-origin',
|
|
|
|
// Content Security Policy - Temporarily relaxed for Stripe Connect debugging
|
|
'Content-Security-Policy': [
|
|
"default-src 'self' https:",
|
|
"script-src 'self' 'unsafe-inline' 'unsafe-eval' https:",
|
|
"style-src 'self' 'unsafe-inline' https:",
|
|
"font-src 'self' https:",
|
|
"img-src 'self' data: https: blob:",
|
|
"connect-src 'self' https: wss:",
|
|
"frame-src 'self' https:",
|
|
"frame-ancestors 'self' https:",
|
|
"form-action 'self'",
|
|
"base-uri 'self'",
|
|
"object-src 'none'",
|
|
"worker-src 'self' blob: https:"
|
|
].join('; '),
|
|
|
|
// Permissions policy
|
|
'Permissions-Policy': [
|
|
'camera=(),',
|
|
'microphone=(),',
|
|
'geolocation=(),',
|
|
'payment=(self "https://js.stripe.com" "https://connect-js.stripe.com" "https://*.stripe.com")',
|
|
'usb=(),',
|
|
'bluetooth=(),',
|
|
'magnetometer=(),',
|
|
'gyroscope=(),',
|
|
'accelerometer=()'
|
|
].join(' ')
|
|
};
|
|
|
|
// HTTPS redirect in production
|
|
if (process.env.NODE_ENV === 'production') {
|
|
const proto = context.request.headers.get('x-forwarded-proto');
|
|
const host = context.request.headers.get('host');
|
|
|
|
if (proto === 'http' && host) {
|
|
return Response.redirect(`https://${host}${context.url.pathname}${context.url.search}`, 301);
|
|
}
|
|
}
|
|
|
|
// Continue with the request
|
|
const response = await next();
|
|
|
|
// Add security headers to response
|
|
Object.entries(securityHeaders).forEach(([key, value]) => {
|
|
response.headers.set(key, value);
|
|
});
|
|
|
|
return response;
|
|
}); |