Files
accounting-backend/config/settings.py

127 lines
3.8 KiB
Python

"""
Settings for the standalone FunZone Accounting backend.
This service is fully decoupled from the main FunZone backend. It stores its own
accounting data in its own database and authorizes requests statelessly using
admin JWTs minted by the FunZone backend (validated with the shared SECRET_KEY).
"""
from datetime import timedelta
from pathlib import Path
from decouple import config
BASE_DIR = Path(__file__).resolve().parent.parent
# Must match the FunZone backend SECRET_KEY so admin JWTs validate here.
SECRET_KEY = config('SECRET_KEY', default='your-super-secret-key-change-in-production')
DEBUG = config('DEBUG', default=True, cast=bool)
ALLOWED_HOSTS = config(
'ALLOWED_HOSTS',
default='localhost,127.0.0.1,0.0.0.0,testserver',
).split(',')
INSTALLED_APPS = [
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework_simplejwt',
'corsheaders',
'accounting',
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.middleware.common.CommonMiddleware',
]
ROOT_URLCONF = 'config.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {'context_processors': []},
},
]
WSGI_APPLICATION = 'config.wsgi.application'
ASGI_APPLICATION = 'config.asgi.application'
# Database: SQLite by default for zero-setup standalone runs; override via env.
DATABASE_URL = config('DATABASE_URL', default=None)
if DATABASE_URL:
import re
match = re.match(r'postgresql://([^:]+):([^@]+)@([^:]+):(\d+)/(.+)', DATABASE_URL)
if match:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': match.group(5),
'USER': match.group(1),
'PASSWORD': match.group(2),
'HOST': match.group(3),
'PORT': match.group(4),
}
}
else:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': config('SQLITE_PATH', default=str(BASE_DIR / 'db.sqlite3')),
}
}
else:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': config('SQLITE_PATH', default=str(BASE_DIR / 'db.sqlite3')),
}
}
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
STATIC_URL = '/static/'
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': ['rest_framework.renderers.JSONRenderer'],
'DEFAULT_PARSER_CLASSES': ['rest_framework.parsers.JSONParser'],
# Stateless: build the user from token claims, never touch a user table.
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTTokenUserAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': ['rest_framework.permissions.IsAuthenticated'],
}
# Mirror the FunZone JWT settings so tokens validate identically.
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60),
'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
'ALGORITHM': 'HS256',
'SIGNING_KEY': SECRET_KEY,
'AUTH_HEADER_TYPES': ('Bearer',),
'USER_ID_FIELD': 'id',
'USER_ID_CLAIM': 'user_id',
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
'TOKEN_TYPE_CLAIM': 'token_type',
'TOKEN_USER_CLASS': 'rest_framework_simplejwt.models.TokenUser',
}
# CORS: allow the accounting frontend (and others) in development.
CORS_ALLOW_ALL_ORIGINS = config('CORS_ALLOW_ALL_ORIGINS', default=True, cast=bool)
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOWED_ORIGINS = config(
'CORS_ALLOWED_ORIGINS',
default='http://localhost:5176,http://127.0.0.1:5176',
).split(',')