# config/settings.py """ تنظیمات جنگو برای پروژه «شاپ‌شیپ». همه‌ی مقادیر حساس/محیطی از .env خوانده می‌شوند. """ import os from datetime import timedelta from pathlib import Path from decouple import Config, Csv, RepositoryEnv BASE_DIR = Path(__file__).resolve().parent.parent # ============================================ # بارگذاری فایل .env # ============================================ _env_path = BASE_DIR / ".env" if not _env_path.exists(): raise RuntimeError( f"❌ فایل .env پیدا نشد ({_env_path}) — لطفاً یک فایل .env ایجاد کنید." ) config = Config(RepositoryEnv(str(_env_path))) # ============================================ # امنیت و محیط اجرا # ============================================ SECRET_KEY = config("SECRET_KEY") DEBUG = False ALLOWED_HOSTS = config("ALLOWED_HOSTS", default="localhost,127.0.0.1", cast=Csv()) # ============================================ # اپلیکیشن‌ها # ============================================ 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", "rest_framework_simplejwt", "rest_framework_simplejwt.token_blacklist", ] LOCAL_APPS = [ "apps.account", "apps.banker", "apps.messaging", "apps.bizapps", "apps.billing", "apps.notifications", "apps.landing", "apps.orders", ] INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS # ============================================ # Middleware # ============================================ MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", "whitenoise.middleware.WhiteNoiseMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "corsheaders.middleware.CorsMiddleware", "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" WSGI_APPLICATION = "config.wsgi.application" # ============================================ # Templates # ============================================ TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "DIRS": [], "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", ], }, }, ] # ============================================ # Database # ============================================ DATABASES = { "default": { "ENGINE": config("DB_ENGINE", default="django.db.backends.sqlite3"), "NAME": config("DB_NAME", default=BASE_DIR / "db.sqlite3"), "USER": config("DB_USER", default=""), "PASSWORD": config("DB_PASSWORD", default=""), "HOST": config("DB_HOST", default=""), "PORT": config("DB_PORT", default=""), } } # ============================================ # Auth # ============================================ 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"}, ] AUTH_USER_MODEL = "account.User" # ============================================ # بین‌الملل # ============================================ LANGUAGE_CODE = "fa-ir" TIME_ZONE = "Asia/Tehran" USE_I18N = True USE_TZ = True # ============================================ # فایل‌های استاتیک # ============================================ STATIC_URL = "/static/" STATIC_ROOT = BASE_DIR / "staticfiles" STORAGES = { "staticfiles": { "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage", }, } # ============================================ # Landing Page # ============================================ WHITENOISE_ROOT = BASE_DIR / "landing" WHITENOISE_INDEX_FILE = True # ============================================ # فایل‌های رسانه # ============================================ MEDIA_URL = "/media/" MEDIA_ROOT = BASE_DIR / "media" DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" # ============================================ # CORS # ============================================ CORS_ALLOWED_ORIGINS = config("CORS_ALLOWED_ORIGINS", default="", cast=Csv()) CORS_ALLOW_ALL_ORIGINS = config("CORS_ALLOW_ALL_ORIGINS", default=False, cast=bool) CSRF_TRUSTED_ORIGINS = config("CSRF_TRUSTED_ORIGINS", default="", cast=Csv()) # ============================================ # Django REST Framework # ============================================ REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": ( "rest_framework_simplejwt.authentication.JWTAuthentication", ), "DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",), "DEFAULT_THROTTLE_CLASSES": [ "rest_framework.throttling.ScopedRateThrottle", ], "DEFAULT_THROTTLE_RATES": { "otp_send": "5/hour", "otp_verify": "10/hour", "backup": "30/hour", "messaging_send": "30/hour", "billing_write": "30/hour", }, } # ============================================ # Simple JWT # ============================================ SIMPLE_JWT = { "ACCESS_TOKEN_LIFETIME": timedelta(days=config("JWT_ACCESS_LIFETIME_DAYS", default=1, cast=int)), "REFRESH_TOKEN_LIFETIME": timedelta(days=config("JWT_REFRESH_LIFETIME_DAYS", default=30, cast=int)), "ROTATE_REFRESH_TOKENS": True, "BLACKLIST_AFTER_ROTATION": True, "USER_ID_FIELD": "id", "USER_ID_CLAIM": "user_id", } # ============================================ # ✅ تنظیمات پیامک (فقط OTP با کاوه‌نگار) # ============================================ KAVENEGAR_API_KEY = config("KAVENEGAR_API_KEY", default="") SMS_PATTERN_NAME = config("SMS_PATTERN_NAME", default="shopshipotp") # برای سازگاری با کدهای قدیمی (استفاده نمی‌شود) SMS_TOKEN_URL = config("SMS_TOKEN_URL", default="") # ============================================ # تنظیمات کانال‌های پیام‌رسان (در صورت نیاز) # ============================================ KAVENEGAR_SENDER_LINE = config("KAVENEGAR_SENDER_LINE", default="") WHATSAPP_ACCESS_TOKEN = config("WHATSAPP_ACCESS_TOKEN", default="") WHATSAPP_PHONE_NUMBER_ID = config("WHATSAPP_PHONE_NUMBER_ID", default="") WHATSAPP_TEMPLATE_NAME = config("WHATSAPP_TEMPLATE_NAME", default="") TELEGRAM_BOT_TOKEN = config("TELEGRAM_BOT_TOKEN", default="") BALE_BOT_TOKEN = config("BALE_BOT_TOKEN", default="") EITAA_BOT_TOKEN = config("EITAA_BOT_TOKEN", default="") # ============================================ # لاگینگ # ============================================ LOGGING = { "version": 1, "disable_existing_loggers": False, "handlers": { "console": { "class": "logging.StreamHandler", }, }, "loggers": { "apps.account": { "handlers": ["console"], "level": "DEBUG", "propagate": True, }, "django": { "handlers": ["console"], "level": "INFO", "propagate": True, }, }, "root": { "handlers": ["console"], "level": "INFO", }, }