updates
This commit is contained in:
@@ -14,6 +14,7 @@ import sys
|
||||
import secrets
|
||||
import os
|
||||
import re
|
||||
import logging
|
||||
from .config.settings import settings
|
||||
from .config.logging_config import setup_logging, get_logger
|
||||
from .config.database import engine, Base, get_db
|
||||
@@ -26,6 +27,9 @@ from .middleware.request_id import RequestIDMiddleware
|
||||
from .middleware.security import SecurityHeadersMiddleware
|
||||
from .middleware.timeout import TimeoutMiddleware
|
||||
from .middleware.cookie_consent import CookieConsentMiddleware
|
||||
from .middleware.csrf import CSRFProtectionMiddleware
|
||||
from .middleware.request_size_limit import RequestSizeLimitMiddleware
|
||||
from .middleware.admin_ip_whitelist import AdminIPWhitelistMiddleware
|
||||
if settings.is_development:
|
||||
logger.info('Creating database tables (development mode)')
|
||||
Base.metadata.create_all(bind=engine)
|
||||
@@ -48,6 +52,14 @@ app.add_middleware(CookieConsentMiddleware)
|
||||
if settings.REQUEST_TIMEOUT > 0:
|
||||
app.add_middleware(TimeoutMiddleware)
|
||||
app.add_middleware(SecurityHeadersMiddleware)
|
||||
app.add_middleware(RequestSizeLimitMiddleware, max_size=settings.MAX_REQUEST_BODY_SIZE)
|
||||
logger.info(f'Request size limiting enabled: {settings.MAX_REQUEST_BODY_SIZE // 1024 // 1024}MB max body size')
|
||||
if settings.CSRF_PROTECTION_ENABLED:
|
||||
app.add_middleware(CSRFProtectionMiddleware)
|
||||
logger.info('CSRF protection enabled')
|
||||
if settings.IP_WHITELIST_ENABLED:
|
||||
app.add_middleware(AdminIPWhitelistMiddleware)
|
||||
logger.info(f'Admin IP whitelisting enabled with {len(settings.ADMIN_IP_WHITELIST)} IP(s)/CIDR range(s)')
|
||||
if settings.RATE_LIMIT_ENABLED:
|
||||
limiter = Limiter(key_func=get_remote_address, default_limits=[f'{settings.RATE_LIMIT_PER_MINUTE}/minute'])
|
||||
app.state.limiter = limiter
|
||||
@@ -57,8 +69,17 @@ if settings.is_development:
|
||||
app.add_middleware(CORSMiddleware, allow_origin_regex='http://(localhost|127\\.0\\.0\\.1)(:\\d+)?', allow_credentials=True, allow_methods=['*'], allow_headers=['*'])
|
||||
logger.info('CORS configured for development (allowing localhost)')
|
||||
else:
|
||||
app.add_middleware(CORSMiddleware, allow_origins=settings.CORS_ORIGINS, allow_credentials=True, allow_methods=['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'], allow_headers=['*'])
|
||||
logger.info(f'CORS configured for production with {len(settings.CORS_ORIGINS)} allowed origins')
|
||||
# Validate CORS_ORIGINS in production
|
||||
if not settings.CORS_ORIGINS or len(settings.CORS_ORIGINS) == 0:
|
||||
logger.warning('CORS_ORIGINS is empty in production. This may block legitimate requests.')
|
||||
logger.warning('Please set CORS_ORIGINS environment variable with allowed origins.')
|
||||
else:
|
||||
# Log CORS configuration for security audit
|
||||
logger.info(f'CORS configured for production with {len(settings.CORS_ORIGINS)} allowed origin(s)')
|
||||
if logger.isEnabledFor(logging.DEBUG):
|
||||
logger.debug(f'Allowed CORS origins: {", ".join(settings.CORS_ORIGINS)}')
|
||||
|
||||
app.add_middleware(CORSMiddleware, allow_origins=settings.CORS_ORIGINS or [], allow_credentials=True, allow_methods=['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'], allow_headers=['*'])
|
||||
uploads_dir = Path(__file__).parent.parent / settings.UPLOAD_DIR
|
||||
uploads_dir.mkdir(exist_ok=True)
|
||||
app.mount('/uploads', StaticFiles(directory=str(uploads_dir)), name='uploads')
|
||||
@@ -93,93 +114,85 @@ async def health_check(db: Session=Depends(get_db)):
|
||||
@app.get('/metrics', tags=['monitoring'])
|
||||
async def metrics():
|
||||
return {'status': 'success', 'service': settings.APP_NAME, 'version': settings.APP_VERSION, 'environment': settings.ENVIRONMENT, 'timestamp': datetime.utcnow().isoformat()}
|
||||
app.include_router(auth_routes.router, prefix='/api')
|
||||
app.include_router(auth_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
from .routes import room_routes, booking_routes, payment_routes, invoice_routes, banner_routes, favorite_routes, service_routes, service_booking_routes, promotion_routes, report_routes, review_routes, user_routes, audit_routes, admin_privacy_routes, system_settings_routes, contact_routes, page_content_routes, home_routes, about_routes, contact_content_routes, footer_routes, chat_routes, privacy_routes, terms_routes, refunds_routes, cancellation_routes, accessibility_routes, faq_routes, loyalty_routes, guest_profile_routes, analytics_routes, workflow_routes, task_routes, notification_routes, group_booking_routes, advanced_room_routes, rate_plan_routes, package_routes, security_routes, email_campaign_routes
|
||||
app.include_router(room_routes.router, prefix='/api')
|
||||
app.include_router(booking_routes.router, prefix='/api')
|
||||
app.include_router(group_booking_routes.router, prefix='/api')
|
||||
app.include_router(payment_routes.router, prefix='/api')
|
||||
app.include_router(invoice_routes.router, prefix='/api')
|
||||
app.include_router(banner_routes.router, prefix='/api')
|
||||
app.include_router(favorite_routes.router, prefix='/api')
|
||||
app.include_router(service_routes.router, prefix='/api')
|
||||
app.include_router(service_booking_routes.router, prefix='/api')
|
||||
app.include_router(promotion_routes.router, prefix='/api')
|
||||
app.include_router(report_routes.router, prefix='/api')
|
||||
app.include_router(review_routes.router, prefix='/api')
|
||||
app.include_router(user_routes.router, prefix='/api')
|
||||
app.include_router(audit_routes.router, prefix='/api')
|
||||
app.include_router(admin_privacy_routes.router, prefix='/api')
|
||||
app.include_router(system_settings_routes.router, prefix='/api')
|
||||
app.include_router(contact_routes.router, prefix='/api')
|
||||
app.include_router(home_routes.router, prefix='/api')
|
||||
app.include_router(about_routes.router, prefix='/api')
|
||||
app.include_router(contact_content_routes.router, prefix='/api')
|
||||
app.include_router(footer_routes.router, prefix='/api')
|
||||
app.include_router(privacy_routes.router, prefix='/api')
|
||||
app.include_router(terms_routes.router, prefix='/api')
|
||||
app.include_router(refunds_routes.router, prefix='/api')
|
||||
app.include_router(cancellation_routes.router, prefix='/api')
|
||||
app.include_router(accessibility_routes.router, prefix='/api')
|
||||
app.include_router(faq_routes.router, prefix='/api')
|
||||
app.include_router(chat_routes.router, prefix='/api')
|
||||
app.include_router(loyalty_routes.router, prefix='/api')
|
||||
app.include_router(guest_profile_routes.router, prefix='/api')
|
||||
app.include_router(analytics_routes.router, prefix='/api')
|
||||
app.include_router(workflow_routes.router, prefix='/api')
|
||||
app.include_router(task_routes.router, prefix='/api')
|
||||
app.include_router(notification_routes.router, prefix='/api')
|
||||
app.include_router(advanced_room_routes.router, prefix='/api')
|
||||
app.include_router(rate_plan_routes.router, prefix='/api')
|
||||
app.include_router(package_routes.router, prefix='/api')
|
||||
app.include_router(security_routes.router, prefix='/api')
|
||||
app.include_router(email_campaign_routes.router, prefix='/api')
|
||||
app.include_router(room_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(booking_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(payment_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(invoice_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(banner_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(favorite_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(service_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(service_booking_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(promotion_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(report_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(review_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(user_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(audit_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(admin_privacy_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(system_settings_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(contact_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(home_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(about_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(contact_content_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(footer_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(privacy_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(terms_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(refunds_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(cancellation_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(accessibility_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(faq_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(chat_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(loyalty_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(guest_profile_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(analytics_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(workflow_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(task_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(notification_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(advanced_room_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(rate_plan_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(package_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
app.include_router(page_content_routes.router, prefix='/api')
|
||||
app.include_router(page_content_routes.router, prefix=settings.API_V1_PREFIX)
|
||||
# Import all route modules
|
||||
from .routes import (
|
||||
room_routes, booking_routes, payment_routes, invoice_routes, banner_routes,
|
||||
favorite_routes, service_routes, service_booking_routes, promotion_routes,
|
||||
report_routes, review_routes, user_routes, audit_routes, admin_privacy_routes,
|
||||
system_settings_routes, contact_routes, page_content_routes, home_routes,
|
||||
about_routes, contact_content_routes, footer_routes, chat_routes, privacy_routes,
|
||||
terms_routes, refunds_routes, cancellation_routes, accessibility_routes,
|
||||
faq_routes, loyalty_routes, guest_profile_routes, analytics_routes,
|
||||
workflow_routes, task_routes, notification_routes, group_booking_routes,
|
||||
advanced_room_routes, rate_plan_routes, package_routes, security_routes,
|
||||
email_campaign_routes
|
||||
)
|
||||
|
||||
# Register all routes with /api prefix (removed duplicate registrations)
|
||||
# Using /api prefix as standard, API versioning can be handled via headers if needed
|
||||
api_prefix = '/api'
|
||||
app.include_router(auth_routes.router, prefix=api_prefix)
|
||||
app.include_router(room_routes.router, prefix=api_prefix)
|
||||
app.include_router(booking_routes.router, prefix=api_prefix)
|
||||
app.include_router(group_booking_routes.router, prefix=api_prefix)
|
||||
app.include_router(payment_routes.router, prefix=api_prefix)
|
||||
app.include_router(invoice_routes.router, prefix=api_prefix)
|
||||
app.include_router(banner_routes.router, prefix=api_prefix)
|
||||
app.include_router(favorite_routes.router, prefix=api_prefix)
|
||||
app.include_router(service_routes.router, prefix=api_prefix)
|
||||
app.include_router(service_booking_routes.router, prefix=api_prefix)
|
||||
app.include_router(promotion_routes.router, prefix=api_prefix)
|
||||
app.include_router(report_routes.router, prefix=api_prefix)
|
||||
app.include_router(review_routes.router, prefix=api_prefix)
|
||||
app.include_router(user_routes.router, prefix=api_prefix)
|
||||
app.include_router(audit_routes.router, prefix=api_prefix)
|
||||
app.include_router(admin_privacy_routes.router, prefix=api_prefix)
|
||||
app.include_router(system_settings_routes.router, prefix=api_prefix)
|
||||
app.include_router(contact_routes.router, prefix=api_prefix)
|
||||
app.include_router(home_routes.router, prefix=api_prefix)
|
||||
app.include_router(about_routes.router, prefix=api_prefix)
|
||||
app.include_router(contact_content_routes.router, prefix=api_prefix)
|
||||
app.include_router(footer_routes.router, prefix=api_prefix)
|
||||
app.include_router(privacy_routes.router, prefix=api_prefix)
|
||||
app.include_router(terms_routes.router, prefix=api_prefix)
|
||||
app.include_router(refunds_routes.router, prefix=api_prefix)
|
||||
app.include_router(cancellation_routes.router, prefix=api_prefix)
|
||||
app.include_router(accessibility_routes.router, prefix=api_prefix)
|
||||
app.include_router(faq_routes.router, prefix=api_prefix)
|
||||
app.include_router(chat_routes.router, prefix=api_prefix)
|
||||
app.include_router(loyalty_routes.router, prefix=api_prefix)
|
||||
app.include_router(guest_profile_routes.router, prefix=api_prefix)
|
||||
app.include_router(analytics_routes.router, prefix=api_prefix)
|
||||
app.include_router(workflow_routes.router, prefix=api_prefix)
|
||||
app.include_router(task_routes.router, prefix=api_prefix)
|
||||
app.include_router(notification_routes.router, prefix=api_prefix)
|
||||
app.include_router(advanced_room_routes.router, prefix=api_prefix)
|
||||
app.include_router(rate_plan_routes.router, prefix=api_prefix)
|
||||
app.include_router(package_routes.router, prefix=api_prefix)
|
||||
app.include_router(security_routes.router, prefix=api_prefix)
|
||||
app.include_router(email_campaign_routes.router, prefix=api_prefix)
|
||||
app.include_router(page_content_routes.router, prefix=api_prefix)
|
||||
logger.info('All routes registered successfully')
|
||||
|
||||
def ensure_jwt_secret():
|
||||
"""Generate and save JWT secret if it's using the default value."""
|
||||
"""Generate and save JWT secret if it's using the default value.
|
||||
|
||||
In production, fail fast if default secret is used for security.
|
||||
In development, auto-generate a secure secret if needed.
|
||||
"""
|
||||
default_secret = 'dev-secret-key-change-in-production-12345'
|
||||
current_secret = settings.JWT_SECRET
|
||||
|
||||
# Security check: Fail fast in production if using default secret
|
||||
if settings.is_production and (not current_secret or current_secret == default_secret):
|
||||
error_msg = (
|
||||
'CRITICAL SECURITY ERROR: JWT_SECRET is using default value in production! '
|
||||
'Please set a secure JWT_SECRET in your environment variables.'
|
||||
)
|
||||
logger.error(error_msg)
|
||||
raise ValueError(error_msg)
|
||||
|
||||
# Development mode: Auto-generate if needed
|
||||
if not current_secret or current_secret == default_secret:
|
||||
new_secret = secrets.token_urlsafe(64)
|
||||
|
||||
@@ -219,6 +232,14 @@ def ensure_jwt_secret():
|
||||
async def startup_event():
|
||||
ensure_jwt_secret()
|
||||
|
||||
# Validate encryption key configuration
|
||||
try:
|
||||
settings.validate_encryption_key()
|
||||
except ValueError as e:
|
||||
logger.error(str(e))
|
||||
if settings.is_production:
|
||||
raise # Fail fast in production
|
||||
|
||||
logger.info(f'{settings.APP_NAME} started successfully')
|
||||
logger.info(f'Environment: {settings.ENVIRONMENT}')
|
||||
logger.info(f'Debug mode: {settings.DEBUG}')
|
||||
|
||||
Reference in New Issue
Block a user