Add admin login API and remove hardcoded secrets

- Add token-based admin login/logout/me endpoints
- Bootstrap admin from ADMIN_USERNAME/ADMIN_PASSWORD in Docker entrypoint
- Read ALLOWED_HOSTS and CORS from env only (no hardcoded server IPs)
- Keep docs/Postman/tests free of real credentials
- Cover login and auth flows with 31 local API tests

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Shayan Azadi
2026-07-16 17:29:47 +03:30
parent 7e71d922d3
commit 50c9cf613f
13 changed files with 791 additions and 141 deletions

View File

@@ -32,13 +32,11 @@ DEBUG = os.environ.get('DEBUG', 'False') == 'True'
if DEBUG:
ALLOWED_HOSTS = ['*'] # Allow all hosts in development only
else:
# Production: require ALLOWED_HOSTS to be set explicitly
allowed_hosts_env = os.environ.get('ALLOWED_HOSTS')
if allowed_hosts_env:
ALLOWED_HOSTS = allowed_hosts_env.split(',')
else:
# Fallback for production (should be overridden by env var)
ALLOWED_HOSTS = ['185.208.172.158'] # Your server IP
allowed_hosts_env = os.environ.get('ALLOWED_HOSTS', '')
ALLOWED_HOSTS = [h.strip() for h in allowed_hosts_env.split(',') if h.strip()]
if not ALLOWED_HOSTS:
# Fail safe: empty list rejects all hosts until env is configured
ALLOWED_HOSTS = []
# Application definition
@@ -52,6 +50,7 @@ INSTALLED_APPS = [
'django.contrib.staticfiles',
# Third party apps
'rest_framework',
'rest_framework.authtoken',
'corsheaders',
# Local apps
'api',
@@ -152,6 +151,11 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# REST Framework configuration
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
],
@@ -173,18 +177,8 @@ REST_FRAMEWORK = {
if DEBUG:
CORS_ALLOW_ALL_ORIGINS = True # Development only - allows all origins
else:
# Production: require CORS_ALLOWED_ORIGINS to be set explicitly
cors_origins_env = os.environ.get('CORS_ALLOWED_ORIGINS')
if cors_origins_env:
CORS_ALLOWED_ORIGINS = cors_origins_env.split(',')
else:
# Fallback for production (should be overridden by env var)
CORS_ALLOWED_ORIGINS = [
'http://185.208.172.158:9123',
'http://185.208.172.158',
'https://185.208.172.158:9123',
'https://185.208.172.158',
]
cors_origins_env = os.environ.get('CORS_ALLOWED_ORIGINS', '')
CORS_ALLOWED_ORIGINS = [o.strip() for o in cors_origins_env.split(',') if o.strip()]
CORS_ALLOW_CREDENTIALS = True