""" Django settings for Dubai Analytics Platform. """ import os from pathlib import Path from datetime import timedelta import environ # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent # Environment variables env = environ.Env( DEBUG=(bool, False), SECRET_KEY=(str, 'django-insecure-change-this-in-production'), DATABASE_URL=(str, 'postgresql://user:password@localhost:5432/dubai_analytics'), REDIS_URL=(str, 'redis://localhost:6379/0'), CELERY_BROKER_URL=(str, 'redis://localhost:6379/1'), SENTRY_DSN=(str, ''), ) # Read .env file environ.Env.read_env(os.path.join(BASE_DIR, '.env')) # Try to import local settings for development try: from local_settings import * except ImportError: pass # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = env('SECRET_KEY') # SECURITY WARNING: don't run with debug turned on in production! DEBUG = env('DEBUG') ALLOWED_HOSTS = ['localhost', '127.0.0.1', '0.0.0.0', 'dubai-analytics.com'] # Application definition DJANGO_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ] THIRD_PARTY_APPS = [ 'rest_framework', 'rest_framework_simplejwt', 'corsheaders', 'django_filters', 'drf_spectacular', 'django_celery_beat', 'django_celery_results', ] LOCAL_APPS = [ 'apps.core', 'apps.users', 'apps.analytics', 'apps.reports', 'apps.integrations', 'apps.billing', 'apps.monitoring', ] INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', 'django.middleware.security.SecurityMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'apps.core.middleware.APIRateLimitMiddleware', 'apps.core.middleware.APILoggingMiddleware', ] ROOT_URLCONF = 'dubai_analytics.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [BASE_DIR / 'templates'], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 'dubai_analytics.wsgi.application' # Database DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': env('DB_NAME', default='data_analysis'), 'USER': env('DB_USER', default='postgres'), 'PASSWORD': env('DB_PASSWORD', default='Admin@123'), 'HOST': env('DB_HOST', default='localhost'), 'PORT': env('DB_PORT', default='5432'), 'OPTIONS': {} } } # Password validation AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Internationalization LANGUAGE_CODE = 'en-us' TIME_ZONE = 'Asia/Dubai' USE_I18N = True USE_TZ = True # Static files (CSS, JavaScript, Images) STATIC_URL = '/static/' STATIC_ROOT = BASE_DIR / 'staticfiles' STATICFILES_DIRS = [ BASE_DIR / 'static', ] # Media files MEDIA_URL = '/media/' MEDIA_ROOT = BASE_DIR / 'media' # Default primary key field type DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' # Custom User Model AUTH_USER_MODEL = 'users.User' # REST Framework Configuration REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework_simplejwt.authentication.JWTAuthentication', 'apps.core.authentication.APIKeyAuthentication', ], 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', ], 'DEFAULT_RENDERER_CLASSES': [ 'rest_framework.renderers.JSONRenderer', ], 'DEFAULT_PAGINATION_CLASS': 'apps.core.pagination.StandardResultsSetPagination', 'PAGE_SIZE': 50, 'DEFAULT_FILTER_BACKENDS': [ 'django_filters.rest_framework.DjangoFilterBackend', 'rest_framework.filters.SearchFilter', 'rest_framework.filters.OrderingFilter', ], 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema', 'EXCEPTION_HANDLER': 'apps.core.exceptions.custom_exception_handler', } # JWT Configuration SIMPLE_JWT = { 'ACCESS_TOKEN_LIFETIME': timedelta(hours=1), 'REFRESH_TOKEN_LIFETIME': timedelta(days=7), 'ROTATE_REFRESH_TOKENS': True, 'BLACKLIST_AFTER_ROTATION': True, 'UPDATE_LAST_LOGIN': True, 'ALGORITHM': 'HS256', 'SIGNING_KEY': SECRET_KEY, 'VERIFYING_KEY': None, 'AUDIENCE': None, 'ISSUER': None, 'JWK_URL': None, 'LEEWAY': 0, 'AUTH_HEADER_TYPES': ('Bearer',), 'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION', 'USER_ID_FIELD': 'id', 'USER_ID_CLAIM': 'user_id', 'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule', 'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',), 'TOKEN_TYPE_CLAIM': 'token_type', 'JTI_CLAIM': 'jti', 'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp', 'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5), 'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1), } # CORS Configuration CORS_ALLOWED_ORIGINS = [ "http://localhost:3000", "http://127.0.0.1:3000", "https://admin.dubai-analytics.com", ] CORS_ALLOW_CREDENTIALS = True # Cache Configuration CACHES = { 'default': { 'BACKEND': 'django_redis.cache.RedisCache', 'LOCATION': env('REDIS_URL'), 'OPTIONS': { 'CLIENT_CLASS': 'django_redis.client.DefaultClient', } } } # Celery Configuration CELERY_BROKER_URL = env('CELERY_BROKER_URL') CELERY_RESULT_BACKEND = 'django-db' CELERY_ACCEPT_CONTENT = ['json'] CELERY_TASK_SERIALIZER = 'json' CELERY_RESULT_SERIALIZER = 'json' CELERY_TIMEZONE = TIME_ZONE CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler' # API Documentation SPECTACULAR_SETTINGS = { 'TITLE': 'Dubai Analytics API', 'DESCRIPTION': 'Multi-tenant SaaS platform for Dubai Land Department data analytics', 'VERSION': '1.0.0', 'SERVE_INCLUDE_SCHEMA': False, 'COMPONENT_SPLIT_REQUEST': True, 'SCHEMA_PATH_PREFIX': '/api/v1/', } # Rate Limiting RATELIMIT_USE_CACHE = 'default' RATELIMIT_VIEW = 'apps.core.views.ratelimited_view' # Logging Configuration LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'verbose': { 'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}', 'style': '{', }, 'simple': { 'format': '{levelname} {message}', 'style': '{', }, }, 'handlers': { 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', 'formatter': 'simple', }, }, 'root': { 'handlers': ['console'], 'level': 'INFO', }, 'loggers': { 'django': { 'handlers': ['console'], 'level': 'INFO', 'propagate': False, }, 'apps': { 'handlers': ['console'], 'level': 'DEBUG', 'propagate': False, }, }, } # Security Settings SECURE_BROWSER_XSS_FILTER = True SECURE_CONTENT_TYPE_NOSNIFF = True X_FRAME_OPTIONS = 'DENY' SECURE_HSTS_SECONDS = 31536000 SECURE_HSTS_INCLUDE_SUBDOMAINS = True SECURE_HSTS_PRELOAD = True # Session Configuration SESSION_COOKIE_SECURE = not DEBUG SESSION_COOKIE_HTTPONLY = True SESSION_COOKIE_AGE = 3600 # CSRF Configuration CSRF_COOKIE_SECURE = not DEBUG CSRF_COOKIE_HTTPONLY = True # Email Configuration EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = env('EMAIL_HOST', default='localhost') EMAIL_PORT = env('EMAIL_PORT', default=587) EMAIL_USE_TLS = env('EMAIL_USE_TLS', default=True) EMAIL_HOST_USER = env('EMAIL_HOST_USER', default='') EMAIL_HOST_PASSWORD = env('EMAIL_HOST_PASSWORD', default='') DEFAULT_FROM_EMAIL = env('DEFAULT_FROM_EMAIL', default='noreply@dubai-analytics.com') # Sentry Configuration if env('SENTRY_DSN'): import sentry_sdk from sentry_sdk.integrations.django import DjangoIntegration from sentry_sdk.integrations.celery import CeleryIntegration sentry_sdk.init( dsn=env('SENTRY_DSN'), integrations=[ DjangoIntegration(), CeleryIntegration(), ], traces_sample_rate=0.1, send_default_pii=True, ) # Analytics Configuration ANALYTICS_SETTINGS = { 'FORECAST_PERIODS': 12, # months 'CONFIDENCE_INTERVAL': 0.95, 'MIN_DATA_POINTS': 10, 'CACHE_FORECASTS_HOURS': 24, } # Billing Configuration BILLING_SETTINGS = { 'FREE_TIER_LIMITS': { 'api_calls_per_month': 500, 'reports_per_month': 5, 'forecast_requests_per_month': 10, }, 'PAID_TIER_LIMITS': { 'api_calls_per_month': 10000, 'reports_per_month': 100, 'forecast_requests_per_month': 1000, }, 'PREMIUM_TIER_LIMITS': { 'api_calls_per_month': 100000, 'reports_per_month': 1000, 'forecast_requests_per_month': 10000, }, }