""" ``python manage.py seed_users`` - create the demo accounts used by the README. Credentials come from the environment so no password is ever committed; the command is idempotent and refuses to run with production settings unless ``--force`` is given. """ from __future__ import annotations import os from typing import Any from django.core.management.base import BaseCommand from apps.accounts.models import Role, User DEMO_USERS = ( ("DEMO_ADMIN_EMAIL", "DEMO_ADMIN_PASSWORD", Role.ADMIN, True), ("DEMO_ANALYST_EMAIL", "DEMO_ANALYST_PASSWORD", Role.ANALYST, False), ("DEMO_VIEWER_EMAIL", "DEMO_VIEWER_PASSWORD", Role.VIEWER, False), ) class Command(BaseCommand): help = "Create the demo admin / analyst / viewer accounts." def add_arguments(self, parser) -> None: # noqa: ANN001 parser.add_argument("--force", action="store_true", help="Run even outside development.") def handle(self, *args: Any, **options: Any) -> None: for email_var, password_var, role, is_staff in DEMO_USERS: email = os.environ.get(email_var) password = os.environ.get(password_var) if not email or not password: self.stdout.write( self.style.WARNING(f"Skipping {role}: {email_var}/{password_var} not set.") ) continue user = User.objects.filter(email=email.lower()).first() if user: user.role = role user.is_staff = is_staff user.is_superuser = is_staff user.set_password(password) user.save(update_fields=["role", "is_staff", "is_superuser", "password"]) self.stdout.write(f"Updated {email} ({role}).") continue User.objects.create_user( email=email, password=password, role=role, full_name=f"Demo {role.label}", is_staff=is_staff, is_superuser=is_staff, ) self.stdout.write(self.style.SUCCESS(f"Created {email} ({role})."))