133 lines
7.3 KiB
Python
133 lines
7.3 KiB
Python
import os
|
|
from pathlib import Path
|
|
from urllib.parse import parse_qsl, unquote, urlparse
|
|
|
|
from config.env import load_project_environment
|
|
|
|
BASE_DIR = Path(__file__).resolve().parents[2]
|
|
load_project_environment(BASE_DIR)
|
|
|
|
|
|
def env_bool(name, default=False):
|
|
return os.getenv(name, str(default)).strip().lower() in {"1", "true", "yes", "on"}
|
|
|
|
|
|
def env_list(name, default=""):
|
|
return [item.strip() for item in os.getenv(name, default).split(",") if item.strip()]
|
|
|
|
|
|
SECRET_KEY = os.getenv("DJANGO_SECRET_KEY", "dev-only-change-me")
|
|
DEBUG = env_bool("DJANGO_DEBUG")
|
|
ALLOWED_HOSTS = list(dict.fromkeys(env_list("DJANGO_ALLOWED_HOSTS") + ["localhost", "127.0.0.1"]))
|
|
INSTALLED_APPS = [
|
|
"django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes",
|
|
"django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", "django.contrib.humanize",
|
|
"apps.core", "apps.accounts", "apps.customers", "apps.staff", "apps.tickets",
|
|
"apps.messaging", "apps.attachments", "apps.notifications", "apps.phone_contacts_api", "apps.payments",
|
|
]
|
|
MIDDLEWARE = [
|
|
"django.middleware.security.SecurityMiddleware", "django.contrib.sessions.middleware.SessionMiddleware",
|
|
"django.middleware.locale.LocaleMiddleware", "django.middleware.common.CommonMiddleware",
|
|
"django.middleware.csrf.CsrfViewMiddleware", "django.contrib.auth.middleware.AuthenticationMiddleware",
|
|
"django.contrib.messages.middleware.MessageMiddleware", "apps.accounts.customer_access.CustomerLoginAccessMiddleware",
|
|
"apps.payments.middleware.FinancialGrantAuditMiddleware", "apps.core.middleware.NoStoreHTMLMiddleware",
|
|
"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.request", "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", "apps.core.context_processors.static_asset_version", "apps.core.context_processors.site_branding", "apps.core.context_processors.staff_operations_access", "apps.payments.context_processors.payment_navigation"]}}]
|
|
WSGI_APPLICATION = "config.wsgi.application"
|
|
ASGI_APPLICATION = "config.asgi.application"
|
|
database_url = os.getenv("DATABASE_URL", "").strip()
|
|
if database_url:
|
|
parsed_database_url = urlparse(database_url)
|
|
database_options = dict(parse_qsl(parsed_database_url.query))
|
|
database_options.setdefault("connect_timeout", os.getenv("DB_CONNECT_TIMEOUT", "10"))
|
|
DATABASES = {"default": {
|
|
"ENGINE": "django.db.backends.postgresql",
|
|
"NAME": unquote(parsed_database_url.path.lstrip("/")),
|
|
"USER": unquote(parsed_database_url.username or ""),
|
|
"PASSWORD": unquote(parsed_database_url.password or ""),
|
|
"HOST": parsed_database_url.hostname or "",
|
|
"PORT": str(parsed_database_url.port or 5432),
|
|
"CONN_MAX_AGE": int(os.getenv("DB_CONN_MAX_AGE", "60")),
|
|
"CONN_HEALTH_CHECKS": True,
|
|
"OPTIONS": database_options,
|
|
}}
|
|
else:
|
|
database_options = {
|
|
"connect_timeout": os.getenv("DB_CONNECT_TIMEOUT", "10"),
|
|
"sslmode": os.getenv("DB_SSLMODE", "prefer"),
|
|
}
|
|
DATABASES = {"default": {
|
|
"ENGINE": "django.db.backends.postgresql",
|
|
"NAME": os.getenv("POSTGRES_DB", "customerTicket"),
|
|
"USER": os.getenv("POSTGRES_USER", "postgres"),
|
|
"PASSWORD": os.getenv("POSTGRES_PASSWORD", ""),
|
|
"HOST": os.getenv("POSTGRES_HOST", ""),
|
|
"PORT": os.getenv("POSTGRES_PORT", "5432"),
|
|
"CONN_MAX_AGE": int(os.getenv("DB_CONN_MAX_AGE", "60")),
|
|
"CONN_HEALTH_CHECKS": True,
|
|
"OPTIONS": database_options,
|
|
}}
|
|
AUTH_PASSWORD_VALIDATORS = [{"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"}, {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"}]
|
|
AUTH_USER_MODEL = "accounts.User"
|
|
LANGUAGE_CODE = "fa-ir"
|
|
TIME_ZONE = os.getenv("TIME_ZONE", "Asia/Tehran")
|
|
USE_I18N = True
|
|
USE_TZ = True
|
|
STATIC_URL = "/static/"
|
|
STATIC_ROOT = BASE_DIR / "staticfiles"
|
|
STATICFILES_DIRS = [BASE_DIR / "static"]
|
|
MEDIA_ROOT = Path(os.getenv("MEDIA_ROOT", BASE_DIR / "media"))
|
|
MEDIA_URL = "/media/"
|
|
MEDIA_SIGNING_SECRET = os.getenv("MEDIA_SIGNING_SECRET", SECRET_KEY)
|
|
USE_NGINX_MEDIA = env_bool("USE_NGINX_MEDIA", False)
|
|
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
|
LOGIN_URL = "/login/"
|
|
OTP_LENGTH = int(os.getenv("OTP_LENGTH", "6"))
|
|
OTP_EXPIRE_SECONDS = int(os.getenv("OTP_EXPIRE_SECONDS", "120"))
|
|
OTP_RESEND_SECONDS = int(os.getenv("OTP_RESEND_SECONDS", "60"))
|
|
OTP_MAX_ATTEMPTS = int(os.getenv("OTP_MAX_ATTEMPTS", "5"))
|
|
OTP_RATE_LIMIT_WINDOW_SECONDS = int(os.getenv("OTP_RATE_LIMIT_WINDOW_SECONDS", "3600"))
|
|
OTP_RATE_LIMIT_PER_MOBILE = int(os.getenv("OTP_RATE_LIMIT_PER_MOBILE", "10"))
|
|
OTP_RATE_LIMIT_PER_IP = int(os.getenv("OTP_RATE_LIMIT_PER_IP", "30"))
|
|
# Empty by default: fixed OTP must never be active in production accidentally.
|
|
DEV_OTP_MOBILE = ""
|
|
DEV_OTP_CODE = ""
|
|
MAGIC_LINK_TTL_DAYS = int(os.getenv("MAGIC_LINK_TTL_DAYS", "7"))
|
|
PAYMENT_LINK_TTL_DAYS = int(os.getenv("PAYMENT_LINK_TTL_DAYS", str(MAGIC_LINK_TTL_DAYS)))
|
|
MAX_NOTIFICATION_ATTEMPTS = int(os.getenv("MAX_NOTIFICATION_ATTEMPTS", "5"))
|
|
SMS_MAX_RETRIES = int(os.getenv("SMS_MAX_RETRIES", "3"))
|
|
SMS_RETRY_DELAY_SECONDS = int(os.getenv("SMS_RETRY_DELAY_SECONDS", "180"))
|
|
SMS_DELIVERY_CHECK_DELAY_SECONDS = int(os.getenv("SMS_DELIVERY_CHECK_DELAY_SECONDS", "180"))
|
|
SMS_DELIVERY_MAX_CHECKS = int(os.getenv("SMS_DELIVERY_MAX_CHECKS", "15"))
|
|
SMS_DEFINITIVE_DELIVERY_RETRY_AFTER_SECONDS = int(os.getenv("SMS_DEFINITIVE_DELIVERY_RETRY_AFTER_SECONDS", "2700"))
|
|
SMS_HISTORICAL_DELIVERY_RETRY_STAGGER_SECONDS = int(os.getenv("SMS_HISTORICAL_DELIVERY_RETRY_STAGGER_SECONDS", "30"))
|
|
PUBLIC_BASE_URL = os.getenv("PUBLIC_BASE_URL", "http://127.0.0.1:8000").rstrip("/")
|
|
COMPANY_NAME = os.getenv("COMPANY_NAME", "لوله گستر گلپایگان")
|
|
WEBOTP_HOST = os.getenv("WEBOTP_HOST", "")
|
|
SMS_PROVIDER_CLASS = os.getenv("SMS_PROVIDER_CLASS", "apps.integrations.sms.sms0098.ZeroZeroNinetyEightSMSProvider")
|
|
SMS_API_URL = os.getenv("SMS_API_URL", "")
|
|
SMS_API_TOKEN = os.getenv("SMS_API_TOKEN", "")
|
|
SMS_SENDER = os.getenv("SMS_SENDER", "")
|
|
BEHIN_SMS_USERNAME = os.getenv("BEHIN_SMS_USERNAME", "")
|
|
BEHIN_SMS_PASSWORD = os.getenv("BEHIN_SMS_PASSWORD", "")
|
|
BEHIN_SMS_SPECIAL_NUMBER = os.getenv("BEHIN_SMS_SPECIAL_NUMBER", "")
|
|
BEHIN_SMS_WSDL_URL = os.getenv("BEHIN_SMS_WSDL_URL", "http://panel.behinsms.com/SMSWS/SOAP.asmx?wsdl")
|
|
SMS0098_USERNAME = os.getenv("SMS0098_USERNAME", "")
|
|
SMS0098_PASSWORD = os.getenv("SMS0098_PASSWORD", "")
|
|
SMS0098_FROM = os.getenv("SMS0098_FROM", "")
|
|
SMS0098_WSDL_URL = os.getenv("SMS0098_WSDL_URL", "https://webservice.0098sms.com/service.asmx?WSDL")
|
|
SMS_TEST_ALLOWED_MOBILES = ("+989202202129", "+989384999655")
|
|
BALE_API_BASE = os.getenv("BALE_API_BASE", "https://tapi.bale.ai")
|
|
BALE_BOT_TOKEN = os.getenv("BALE_BOT_TOKEN", "")
|
|
INTEGRATION_HTTP_TIMEOUT_SECONDS = int(os.getenv("INTEGRATION_HTTP_TIMEOUT_SECONDS", "10"))
|
|
STAFF_REPLY_SMS_THROTTLE_SECONDS = int(os.getenv("STAFF_REPLY_SMS_THROTTLE_SECONDS", "180"))
|
|
X_FRAME_OPTIONS = "DENY"
|
|
SECURE_REFERRER_POLICY = "same-origin"
|
|
SESSION_COOKIE_HTTPONLY = True
|
|
SESSION_COOKIE_SAMESITE = "Lax"
|
|
CSRF_COOKIE_SAMESITE = "Lax"
|
|
CSRF_TRUSTED_ORIGINS = env_list("CSRF_TRUSTED_ORIGINS")
|