Files
stiftung-management-system/app/core/settings.py
SysAdmin Agent f8f9dc3319 feat: Memory-Konzept für Agents implementieren (STI-21)
- REST API: 9 Read-Only-Endpunkte unter /api/v1/ für alle Kernmodelle
  (Destinatäre, Ländereien, Pächter, Förderungen, Konten,
  Verpachtungen, Verwaltungskosten, Kalender, Transaktionen)
- Token-Authentifizierung via DRF TokenAuthentication
- Management-Command `create_agent_token` für Agent-Tokens
- Wissensbasis: knowledge/ mit Satzung, Richtlinien, Verfahren,
  Kontakte, Historie
- Agent-Instructions: Datenzugriff-Sektion in AGENTS.md dokumentiert

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 22:45:11 +00:00

183 lines
6.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
from pathlib import Path
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
BASE_DIR = Path(__file__).resolve().parent.parent
SECRET_KEY = os.getenv("SECRET_KEY") or os.getenv("DJANGO_SECRET_KEY", "dev-secret")
DEBUG = os.getenv("DJANGO_DEBUG", "0") == "1"
# Support both ALLOWED_HOSTS (production) and DJANGO_ALLOWED_HOSTS (development)
allowed_hosts_env = os.getenv("ALLOWED_HOSTS") or os.getenv("DJANGO_ALLOWED_HOSTS", "*")
ALLOWED_HOSTS = [host.strip() for host in allowed_hosts_env.split(",")]
# CSRF settings for development and production
CSRF_TRUSTED_ORIGINS = [
"http://localhost:8081",
"http://127.0.0.1:8081",
"http://vhtv-stiftung.de",
"https://vhtv-stiftung.de",
"http://www.vhtv-stiftung.de",
"https://www.vhtv-stiftung.de",
]
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"django.contrib.humanize",
"rest_framework",
"rest_framework.authtoken",
"django_otp",
"django_otp.plugins.otp_totp",
"django_otp.plugins.otp_static",
"stiftung",
]
# Add this to app/core/settings.py
SESSION_COOKIE_NAME = 'stiftung_sessionid' # Different from default 'sessionid'
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django_otp.middleware.OTPMiddleware",
"stiftung.middleware.TwoFactorMiddleware", # 2FA enforcement middleware
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"stiftung.middleware.AuditMiddleware", # Audit logging middleware
]
ROOT_URLCONF = "core.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 = "core.wsgi.application"
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": os.getenv("POSTGRES_DB", "stiftung"),
"USER": os.getenv("POSTGRES_USER", "stiftung"),
"PASSWORD": os.getenv("POSTGRES_PASSWORD", "stiftungpass"),
"HOST": os.getenv("DB_HOST", "db"),
"PORT": os.getenv("DB_PORT", "5432"),
}
}
LANGUAGE_CODE = os.getenv("LANGUAGE_CODE", "de")
TIME_ZONE = os.getenv("TIME_ZONE", "Europe/Berlin")
USE_I18N = True
USE_TZ = True
STATIC_URL = "static/"
STATIC_ROOT = BASE_DIR / "staticfiles"
# Additional locations of static files
STATICFILES_DIRS = [
BASE_DIR / "static",
]
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": [
"rest_framework.authentication.TokenAuthentication",
],
"DEFAULT_PERMISSION_CLASSES": [
"rest_framework.permissions.IsAuthenticated",
],
}
MEDIA_URL = "/media/"
MEDIA_ROOT = BASE_DIR / "media"
# Celery
CELERY_BROKER_URL = os.getenv("REDIS_URL", "redis://redis:6379/0")
CELERY_RESULT_BACKEND = os.getenv("REDIS_URL", "redis://redis:6379/0")
# Celery Beat periodische Tasks
from celery.schedules import crontab # noqa: E402
CELERY_BEAT_SCHEDULE = {
# E-Mail-Postfach alle 15 Minuten auf neue Destinatär-Nachrichten prüfen
"poll-destinataer-emails": {
"task": "stiftung.tasks.poll_destinataer_emails",
"schedule": crontab(minute="*/15"),
},
}
# IMAP-Konfiguration für E-Mail-Eingang (Destinatäre)
# Pflichtfelder: IMAP_HOST, IMAP_USER, IMAP_PASSWORD
IMAP_HOST = os.getenv("IMAP_HOST", "")
IMAP_PORT = int(os.getenv("IMAP_PORT", "993"))
IMAP_USER = os.getenv("IMAP_USER", "paperless@vhtv-stiftung.de")
IMAP_PASSWORD = os.getenv("IMAP_PASSWORD", "")
IMAP_FOLDER = os.getenv("IMAP_FOLDER", "INBOX")
IMAP_USE_SSL = os.getenv("IMAP_USE_SSL", "true").lower() == "true"
# Paperless
PAPERLESS_API_URL = os.getenv("PAPERLESS_API_URL", "https://vhtv-stiftung.de/paperless")
PAPERLESS_API_TOKEN = os.getenv("PAPERLESS_API_TOKEN")
PAPERLESS_REQUIRED_TAG = os.getenv("PAPERLESS_REQUIRED_TAG", "Stiftung_Destinatäre")
PAPERLESS_LAND_TAG = os.getenv("PAPERLESS_LAND_TAG", "Stiftung_Land_und_Pächter")
PAPERLESS_ADMIN_TAG = os.getenv("PAPERLESS_ADMIN_TAG", "Stiftung_Administration")
PAPERLESS_DESTINATAERE_TAG_ID = os.getenv("PAPERLESS_DESTINATAERE_TAG_ID")
PAPERLESS_LAND_TAG_ID = os.getenv("PAPERLESS_LAND_TAG_ID")
PAPERLESS_ADMIN_TAG_ID = os.getenv("PAPERLESS_ADMIN_TAG_ID")
# Authentication
LOGIN_URL = "/login/"
LOGIN_REDIRECT_URL = "/"
LOGOUT_REDIRECT_URL = "/login/"
# Gramps integration
GRAMPS_URL = os.environ.get("GRAMPS_URL", "http://grampsweb:80")
GRAMPS_API_TOKEN = os.environ.get("GRAMPS_API_TOKEN", "")
GRAMPS_STIFTER_IDS = os.environ.get("GRAMPS_STIFTER_IDS", "") # comma-separated
GRAMPS_USERNAME = os.environ.get("GRAMPS_USERNAME", "")
GRAMPS_PASSWORD = os.environ.get("GRAMPS_PASSWORD", "")
# HTTPS Security Settings (production)
if not DEBUG:
SECURE_SSL_REDIRECT = True
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_HSTS_SECONDS = 31536000 # 1 year
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
# =============================================================================
# TWO-FACTOR AUTHENTICATION SETTINGS
# =============================================================================
# django-otp settings
OTP_TOTP_ISSUER = 'Stiftung Management System'
OTP_LOGIN_URL = '/two-factor/login/'
# Optional: Hide sensitive data in admin when not verified
OTP_ADMIN_HIDE_SENSITIVE_DATA = True