""" Настройки портала администрирования. Все секреты и параметры окружения читаются через python-decouple. При запуске под systemd переменные передаются через EnvironmentFile (/etc/admin-portal/admin-portal.env, см. systemd/admin-portal.service), поэтому наличие .env-файла рядом с manage.py не обязательно, но поддерживается для локальной разработки/отладки на самой ВМ. """ import ldap from django_auth_ldap.config import LDAPSearch, GroupOfNamesType, LDAPGroupQuery from decouple import Config, RepositoryEnv, config as env_config, Csv from pathlib import Path import os BASE_DIR = Path(__file__).resolve().parent.parent # Если рядом лежит .env (локальная разработка) — используем его, иначе # полагаемся на переменные окружения процесса (боевой режим, systemd). _dotenv_path = BASE_DIR / ".env" config = Config(RepositoryEnv(_dotenv_path)) if _dotenv_path.exists() else env_config SECRET_KEY = config("DJANGO_SECRET_KEY") DEBUG = config("DJANGO_DEBUG", default=False, cast=bool) ALLOWED_HOSTS = config("DJANGO_ALLOWED_HOSTS", cast=Csv(), default="*") INSTALLED_APPS = [ "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", "portal", ] MIDDLEWARE = [ "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", ] ROOT_URLCONF = "config.urls" TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "DIRS": [BASE_DIR / "portal" / "templates"], "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 = "config.wsgi.application" # --------------------------------------------------------------------------- # База данных — локальный PostgreSQL на этой же ВМ (или указанный хост) # --------------------------------------------------------------------------- DATABASES = { "default": { "ENGINE": "django.db.backends.postgresql", "NAME": config("POSTGRES_DB"), "USER": config("POSTGRES_USER"), "PASSWORD": config("POSTGRES_PASSWORD"), "HOST": config("POSTGRES_HOST", default="127.0.0.1"), "PORT": config("POSTGRES_PORT", default="5432"), } } # --------------------------------------------------------------------------- # Кэш и сессии — локальный Redis на этой же ВМ (или указанный хост) # --------------------------------------------------------------------------- CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": config("REDIS_URL", default="redis://127.0.0.1:6379/1"), "OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"}, } } SESSION_ENGINE = "django.contrib.sessions.backends.cache" SESSION_CACHE_ALIAS = "default" SESSION_COOKIE_NAME = "sessionid" SESSION_COOKIE_AGE = 60 * 60 * 8 # 8 часов SESSION_COOKIE_SECURE = True SESSION_COOKIE_HTTPONLY = True SESSION_COOKIE_SAMESITE = "Lax" CSRF_COOKIE_SECURE = True # --------------------------------------------------------------------------- # Авторизация через Active Directory (LDAP) # --------------------------------------------------------------------------- AUTH_LDAP_SERVER_URI = config("AD_SERVER_URI") AUTH_LDAP_BIND_DN = config("AD_BIND_DN") AUTH_LDAP_BIND_PASSWORD = config("AD_BIND_PASSWORD") AUTH_LDAP_USER_SEARCH = LDAPSearch( config("AD_USER_SEARCH_BASE"), ldap.SCOPE_SUBTREE, "(sAMAccountName=%(user)s)", ) AUTH_LDAP_GROUP_SEARCH = LDAPSearch( config("AD_GROUP_SEARCH_BASE"), ldap.SCOPE_SUBTREE, "(objectClass=group)", ) AUTH_LDAP_GROUP_TYPE = GroupOfNamesType(name_attr="cn") # Атрибуты, которые тянем из AD в модель User при первом логине/обновлении AUTH_LDAP_USER_ATTR_MAP = { "first_name": "givenName", "last_name": "sn", "email": "mail", } # В Django группы AD не мапятся на Django Group автоматически (нам это не нужно — # группы читаются напрямую из LDAP через .ldap_user.group_names при построении # каталога ресурсов, см. portal/services.py), но кэшируем сам LDAP-объект юзера. AUTH_LDAP_ALWAYS_UPDATE_USER = True AUTH_LDAP_CACHE_TIMEOUT = config("AD_GROUP_CACHE_TTL_SECONDS", default=600, cast=int) AUTH_LDAP_CONNECTION_OPTIONS = { ldap.OPT_REFERRALS: 0, ldap.OPT_NETWORK_TIMEOUT: 5, } AUTHENTICATION_BACKENDS = [ "django_auth_ldap.backend.LDAPBackend", "django.contrib.auth.backends.ModelBackend", # для локального суперпользователя ] LOGIN_URL = "/login/" LOGIN_REDIRECT_URL = "/" LOGOUT_REDIRECT_URL = "/login/" # --------------------------------------------------------------------------- # Токен для backend admin panels (см. docs/architecture.md, раздел 6) # --------------------------------------------------------------------------- RESOURCE_TOKEN_SECRET = config("RESOURCE_TOKEN_SECRET") RESOURCE_TOKEN_TTL_SECONDS = config("RESOURCE_TOKEN_TTL_SECONDS", default=60, cast=int) RESOURCE_TOKEN_COOKIE_NAME = "resource_token" STATIC_URL = "static/" STATIC_ROOT = BASE_DIR / "staticfiles" STORAGES = { "staticfiles": { "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage", }, } DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" LANGUAGE_CODE = "ru-ru" TIME_ZONE = "Europe/Moscow" USE_I18N = True USE_TZ = True