from pathlib import Path import environ BASE_DIR = Path(__file__).resolve().parent.parent.parent APPS_DIR = BASE_DIR / "apps" env = environ.Env( DEBUG=(bool, False), ALLOWED_HOSTS=(list, []), CSRF_TRUSTED_ORIGINS=(list, []), CORS_ALLOWED_ORIGINS=(list, []), ) ENV_FILE = BASE_DIR / ".env" if ENV_FILE.exists(): environ.Env.read_env(ENV_FILE) SECRET_KEY = env("SECRET_KEY", default="unsafe-local-development-secret-key") DEBUG = env("DEBUG") ALLOWED_HOSTS = env("ALLOWED_HOSTS") CSRF_TRUSTED_ORIGINS = env("CSRF_TRUSTED_ORIGINS") DJANGO_APPS = [ "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", ] THIRD_PARTY_APPS = [ "corsheaders", "rest_framework", "drf_spectacular", ] LOCAL_APPS = [ "apps.core", "apps.reports", "apps.proxy", ] INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", "whitenoise.middleware.WhiteNoiseMiddleware", "corsheaders.middleware.CorsMiddleware", "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", ] ROOT_URLCONF = "config.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 = "config.wsgi.application" DATABASES = { "default": env.db("DATABASE_URL", default=f"sqlite:///{BASE_DIR / 'db.sqlite3'}"), } DATABASES["default"]["ATOMIC_REQUESTS"] = True 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", }, ] LANGUAGE_CODE = "en-us" TIME_ZONE = env("TIME_ZONE", default="UTC") USE_I18N = True USE_TZ = True STATIC_URL = "static/" STATIC_ROOT = BASE_DIR / "staticfiles" STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" MEDIA_URL = "media/" MEDIA_ROOT = BASE_DIR / "media" DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" CORS_ALLOWED_ORIGINS = env("CORS_ALLOWED_ORIGINS") CORS_ALLOW_CREDENTIALS = env.bool("CORS_ALLOW_CREDENTIALS", default=True) REST_FRAMEWORK = { "DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema", "DEFAULT_RENDERER_CLASSES": [ "rest_framework.renderers.JSONRenderer", ], "DEFAULT_PARSER_CLASSES": [ "rest_framework.parsers.JSONParser", "rest_framework.parsers.FormParser", "rest_framework.parsers.MultiPartParser", ], "DEFAULT_AUTHENTICATION_CLASSES": [], "DEFAULT_PERMISSION_CLASSES": [ "rest_framework.permissions.AllowAny", ], "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination", "PAGE_SIZE": env.int("DRF_PAGE_SIZE", default=20), "DEFAULT_THROTTLE_CLASSES": [ "rest_framework.throttling.AnonRateThrottle", "rest_framework.throttling.UserRateThrottle", ], "DEFAULT_THROTTLE_RATES": { "anon": env("DRF_ANON_THROTTLE_RATE", default="100/hour"), "user": env("DRF_USER_THROTTLE_RATE", default="1000/hour"), }, } SPECTACULAR_SETTINGS = { "TITLE": "CRM Backend API", "DESCRIPTION": ( "API for CRM report generation and health checks, plus a merged view of " "every proxied service's own API (see apps.proxy)." ), "VERSION": "1.0.0", "SERVE_INCLUDE_SCHEMA": False, "POSTPROCESSING_HOOKS": [ "drf_spectacular.hooks.postprocess_schema_enums", "apps.proxy.schema.merge_upstream_schemas", ], } SERVICE_REQUEST_TIMEOUT = env.int("SERVICE_REQUEST_TIMEOUT", default=30) OAUTH2_PROVIDER_PUBLIC_URL = env("OAUTH2_PROVIDER_PUBLIC_URL", default="") OAUTH2_PROVIDER_PRIVATE_URL = env("OAUTH2_PROVIDER_PRIVATE_URL", default="") OAUTH2_PROVIDER_BASE_PUBLIC_URL = env("OAUTH2_PROVIDER_BASE_PUBLIC_URL", default="") OAUTH2_PROVIDER_BASE_PRIVATE_URL = env("OAUTH2_PROVIDER_BASE_PRIVATE_URL", default="") OAUTH2_PROVIDER_CLIENT_ID = env("OAUTH2_PROVIDER_CLIENT_ID", default="") OAUTH2_PROVIDER_CLIENT_SECRET = env("OAUTH2_PROVIDER_CLIENT_SECRET", default="") OAUTH2_PROVIDER_SCOPES = env("OAUTH2_PROVIDER_SCOPES", default="") OAUTH2_CLIENT_ID = env("OAUTH2_CLIENT_ID", default="") OAUTH2_CLIENT_SECRET = env("OAUTH2_CLIENT_SECRET", default="") OAUTH2_SCOPES = env("OAUTH2_SCOPES", default="") ADVERTISING_BASE_PUBLIC_URL = env("ADVERTISING_BASE_PUBLIC_URL", default="") ACCOUNTS_BASE_PUBLIC_URL = env("ACCOUNTS_BASE_PUBLIC_URL", default="") WALLET_BASE_PUBLIC_URL = env("WALLET_BASE_PUBLIC_URL", default="") WALLET_RIAL = env("WALLET_RIAL", default="") WALLET_REWARD = env("WALLET_REWARD", default="") CHAT_BASE_PUBLIC_URL = env("CHAT_BASE_PUBLIC_URL", default="") NOTIFICATIONS_BASE_PUBLIC_URL = env("NOTIFICATIONS_BASE_PUBLIC_URL", default="") PROMOTIONS_BASE_PUBLIC_URL = env("PROMOTIONS_BASE_PUBLIC_URL", default="") CAMPAIGN_BASE_PUBLIC_URL = env("CAMPAIGN_BASE_PUBLIC_URL", default="") IPG_BASE_PUBLIC_URL = env("IPG_BASE_PUBLIC_URL", default="") # Maps the first path segment of a proxied request (thisprojectbaseurl//) # to the upstream service's base URL. See apps.proxy.views.ServiceProxyView. PROXY_SERVICE_BASE_URLS = { "accounts": ACCOUNTS_BASE_PUBLIC_URL, "wallet": WALLET_BASE_PUBLIC_URL, "advertising": ADVERTISING_BASE_PUBLIC_URL, "chat": CHAT_BASE_PUBLIC_URL, "notifications": NOTIFICATIONS_BASE_PUBLIC_URL, "promotions": PROMOTIONS_BASE_PUBLIC_URL, "campaign": CAMPAIGN_BASE_PUBLIC_URL, "ipg": IPG_BASE_PUBLIC_URL, } # Where each service publishes its own raw OpenAPI document (drf-spectacular's # SpectacularAPIView, mounted at different prefixes per service). Used by # apps.proxy.schema to fold every proxied endpoint into this service's swagger. PROXY_SERVICE_SCHEMA_PATHS = { "accounts": "/swagger/?format=json", "wallet": "/swagger/?format=json", "advertising": "/swagger/?format=json", "chat": "/swagger/?format=json", "notifications": "/swagger/?format=json", "promotions": "/swagger/?format=json", "campaign": "/api/swagger/schema/?format=json", "ipg": "/swagger/?format=json", }