Spaces:
Runtime error
Runtime error
| """ | |
| Django settings for hiresync_backend project. | |
| Generated by 'django-admin startproject' using Django 5.2.14. | |
| """ | |
| import os | |
| import sys | |
| from pathlib import Path | |
| from urllib.parse import urlparse | |
| from dotenv import load_dotenv | |
| from datetime import timedelta | |
| # Build paths inside the project like this: BASE_DIR / 'subdir'. | |
| BASE_DIR = Path(__file__).resolve().parent.parent | |
| # Load .env file | |
| load_dotenv(os.path.join(BASE_DIR, '.env')) | |
| # Add apps to Python path | |
| sys.path.insert(0, os.path.join(BASE_DIR, 'apps')) | |
| # Quick-start development settings - unsuitable for production | |
| SECRET_KEY = os.environ.get('SECRET_KEY', 'django-insecure-fallback-key') | |
| DEBUG = os.environ.get('DEBUG', 'True').lower() in ('true', '1', 't') | |
| ALLOWED_HOSTS = [host.strip() for host in os.environ.get('ALLOWED_HOSTS', 'localhost,127.0.0.1').split(',') if host.strip()] | |
| # Application definition | |
| INSTALLED_APPS = [ | |
| # Daphne must be at the top of INSTALLED_APPS for Channels integration | |
| 'daphne', | |
| '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', | |
| 'channels', | |
| # Local apps | |
| 'authentication', | |
| 'companies', | |
| 'jobs', | |
| 'candidates', | |
| 'assessments', | |
| 'interviews', | |
| ] | |
| MIDDLEWARE = [ | |
| 'corsheaders.middleware.CorsMiddleware', # Put CORS first | |
| 'django.middleware.security.SecurityMiddleware', | |
| 'django.contrib.sessions.middleware.SessionMiddleware', | |
| 'django.middleware.common.CommonMiddleware', | |
| 'django.middleware.csrf.CsrfViewMiddleware', | |
| 'django.contrib.auth.middleware.AuthenticationMiddleware', | |
| 'companies.middleware.TenantMiddleware', # Custom multi-tenant workspace context resolver | |
| 'django.contrib.messages.middleware.MessageMiddleware', | |
| 'django.middleware.clickjacking.XFrameOptionsMiddleware', | |
| ] | |
| ROOT_URLCONF = 'hiresync_backend.urls' | |
| TEMPLATES = [ | |
| { | |
| 'BACKEND': 'django.template.backends.django.DjangoTemplates', | |
| 'DIRS': [], | |
| 'APP_DIRS': True, | |
| 'OPTIONS': { | |
| 'context_processors': [ | |
| 'django.template.context_processors.request', | |
| 'django.contrib.auth.context_processors.auth', | |
| 'django.contrib.messages.context_processors.messages', | |
| ], | |
| }, | |
| }, | |
| ] | |
| WSGI_APPLICATION = 'hiresync_backend.wsgi.application' | |
| ASGI_APPLICATION = 'hiresync_backend.asgi.application' | |
| # Database Connection (Mandatory production-ready Supabase PostgreSQL) | |
| db_url = os.environ.get('DATABASE_URL', '') | |
| if not db_url or not (db_url.startswith('postgres://') or db_url.startswith('postgresql://')): | |
| from django.core.exceptions import ImproperlyConfigured | |
| raise ImproperlyConfigured( | |
| "\n" + "="*80 + "\n" | |
| " ❌ CONFIGURATION ERROR: DATABASE_URL environment variable is missing or invalid!\n" | |
| " Production-ready Supabase PostgreSQL is MANDATORY for Tarvax.\n\n" | |
| " 👉 TO CONFIGURE SUPABASE:\n" | |
| " 1. Copy 'backend/.env.example' to 'backend/.env'\n" | |
| " 2. Set the following environment variables in '.env':\n" | |
| " DATABASE_URL=postgresql://postgres:Yash9897422911@db.kntarabupposhjhlqwob.supabase.co:5432/postgres\n" | |
| " SUPABASE_URL=https://kntarabupposhjhlqwob.supabase.co\n" | |
| " SUPABASE_JWT_SECRET=kcwYMVIO/tp2KTwydJqHc7XnsnvIoYBGVe3LGvl7BAEVIZi25FmsFo70uaRRjmxwBIRYJl5qGX1nJYSJwD5Thw==\n" | |
| "="*80 + "\n" | |
| ) | |
| url = urlparse(db_url) | |
| DATABASES = { | |
| 'default': { | |
| 'ENGINE': 'django.db.backends.postgresql', | |
| 'NAME': url.path[1:], | |
| 'USER': url.username, | |
| 'PASSWORD': url.password, | |
| 'HOST': url.hostname, | |
| 'PORT': url.port or 5432, | |
| 'OPTIONS': { | |
| 'sslmode': 'prefer', | |
| } | |
| } | |
| } | |
| # 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'}, | |
| ] | |
| # DRF configuration | |
| REST_FRAMEWORK = { | |
| 'DEFAULT_AUTHENTICATION_CLASSES': ( | |
| 'authentication.authentication.SupabaseJWTAuthentication', # Custom Supabase authentication | |
| 'authentication.authentication.RecruiterJWTAuthentication', # Custom Recruiter SimpleJWT authentication | |
| ), | |
| 'DEFAULT_PERMISSION_CLASSES': ( | |
| 'rest_framework.permissions.IsAuthenticated', | |
| ), | |
| } | |
| # Simple JWT Settings | |
| SIMPLE_JWT = { | |
| 'ACCESS_TOKEN_LIFETIME': timedelta(hours=8), # 8-hour expiry for Recruiters | |
| 'REFRESH_TOKEN_LIFETIME': timedelta(days=1), | |
| 'ROTATE_REFRESH_TOKENS': True, | |
| 'BLACKLIST_AFTER_ROTATION': True, | |
| 'ALGORITHM': 'HS256', | |
| 'SIGNING_KEY': SECRET_KEY, | |
| } | |
| # Supabase Auth Settings | |
| SUPABASE_URL = os.environ.get('SUPABASE_URL', '').strip().strip('\'"') | |
| if not SUPABASE_URL or not SUPABASE_URL.startswith('http') or SUPABASE_URL == 'SUPABASE_URL' or 'your-project' in SUPABASE_URL: | |
| SUPABASE_URL = 'https://kntarabupposhjhlqwob.supabase.co' | |
| SUPABASE_JWT_SECRET = os.environ.get('SUPABASE_JWT_SECRET', '').strip().strip('\'"') | |
| if not SUPABASE_JWT_SECRET or SUPABASE_JWT_SECRET == 'SUPABASE_JWT_SECRET' or 'your-supabase-jwt-secret' in SUPABASE_JWT_SECRET: | |
| SUPABASE_JWT_SECRET = 'kcwYMVIO/tp2KTwydJqHc7XnsnvIoYBGVe3LGvl7BAEVIZi25FmsFo70uaRRjmxwBIRYJl5qGX1nJYSJwD5Thw==' | |
| # CORS Settings | |
| CORS_ALLOW_ALL_ORIGINS = True # For dev purposes | |
| CORS_ALLOW_CREDENTIALS = True | |
| # CSRF Settings | |
| CSRF_TRUSTED_ORIGINS = [ | |
| 'http://localhost:5173', | |
| 'http://127.0.0.1:5173', | |
| ] + [origin.strip() for origin in os.environ.get('CSRF_TRUSTED_ORIGINS', '').split(',') if origin.strip()] | |
| # If not in debug mode, append wildcard to ALLOWED_HOSTS to prevent host header blocking in Hugging Face Spaces proxy | |
| if not DEBUG: | |
| ALLOWED_HOSTS.append('*') | |
| # Internationalization | |
| LANGUAGE_CODE = 'en-us' | |
| TIME_ZONE = 'UTC' | |
| USE_I18N = True | |
| USE_TZ = True | |
| # Static files | |
| STATIC_URL = 'static/' | |
| DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' | |
| # WebSockets Channel Layers | |
| # Use in-memory layer as dev fallback if redis config is not complete | |
| CHANNEL_LAYERS = { | |
| 'default': { | |
| 'BACKEND': 'channels.layers.InMemoryChannelLayer', | |
| }, | |
| } | |
| # Media files (for resume uploads, profile photos) | |
| MEDIA_URL = '/media/' | |
| MEDIA_ROOT = os.path.join(BASE_DIR, 'media') | |
| # Setup logging | |
| LOGGING = { | |
| 'version': 1, | |
| 'disable_existing_loggers': False, | |
| 'handlers': { | |
| 'console': { | |
| 'class': 'logging.StreamHandler', | |
| }, | |
| }, | |
| 'root': { | |
| 'handlers': ['console'], | |
| 'level': 'INFO', | |
| }, | |
| } | |