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

@@ -1,26 +1,47 @@
#!/bin/bash
set -e
echo "Waiting for PostgreSQL to be ready..."
while ! pg_isready -h db -U ${POSTGRES_USER:-postgres} -d ${POSTGRES_DB:-Zoneco_ORG}; do
DB_HOST="${POSTGRES_HOST:-db}"
DB_USER="${POSTGRES_USER:-postgres}"
DB_NAME="${POSTGRES_DB:-Zoneco_ORG}"
echo "Waiting for PostgreSQL to be ready at ${DB_HOST}..."
while ! pg_isready -h "${DB_HOST}" -U "${DB_USER}" -d "${DB_NAME}"; do
echo "PostgreSQL is unavailable - sleeping"
sleep 1
done
echo "PostgreSQL is up - executing command"
echo "PostgreSQL is up"
# Collect static files
echo "Collecting static files..."
python manage.py collectstatic --noinput
# Run migrations
echo "Running migrations..."
python manage.py migrate --noinput
# Create superuser if it doesn't exist (optional, can be removed in production)
# Uncomment and modify if needed:
# echo "from django.contrib.auth import get_user_model; User = get_user_model(); User.objects.filter(username='admin').exists() or User.objects.create_superuser('admin', 'admin@example.com', 'admin')" | python manage.py shell
# Create/update admin from environment variables (no hardcoded credentials).
# Set ADMIN_USERNAME and ADMIN_PASSWORD in the server .env / compose env.
if [ -n "${ADMIN_USERNAME:-}" ] && [ -n "${ADMIN_PASSWORD:-}" ]; then
echo "Ensuring admin user from environment variables..."
python manage.py shell <<EOF
from django.contrib.auth import get_user_model
User = get_user_model()
username = "${ADMIN_USERNAME}"
password = "${ADMIN_PASSWORD}"
user, created = User.objects.get_or_create(
username=username,
defaults={"is_staff": True, "is_superuser": True, "is_active": True},
)
user.is_staff = True
user.is_superuser = True
user.is_active = True
user.set_password(password)
user.save()
print("Admin user CREATED" if created else "Admin user UPDATED")
EOF
else
echo "ADMIN_USERNAME/ADMIN_PASSWORD not set — skipping admin bootstrap"
fi
echo "Starting application..."
exec "$@"