""" Seed script — creates the initial admin user if it does not already exist. On first run the admin credentials are generated securely: - Username is read from ``ADMIN_USERNAME`` env var (default: ``admin``). - Password is read from ``ADMIN_PASSWORD`` env var. When the variable is **not set**, a cryptographically random 16-character password is generated automatically and printed to the startup logs so the operator can copy it. Usage: python -m app.seed """ import os import secrets import string from app.auth import hash_password from app.database import SessionLocal from app.models.user import User # Characters for auto-generated passwords (alphanumeric + safe symbols) _PW_ALPHABET = string.ascii_letters + string.digits + "!@#$%&*-_+" def _generate_password(length: int = 16) -> str: """Return a cryptographically random password of *length* characters.""" return "".join(secrets.choice(_PW_ALPHABET) for _ in range(length)) def seed_admin() -> None: """Create the initial admin user when it is missing. Reads ``ADMIN_USERNAME`` and ``ADMIN_PASSWORD`` from the environment. If ``ADMIN_PASSWORD`` is empty or unset a secure random password is generated and displayed in the logs. """ db = SessionLocal() try: admin_username = os.environ.get("ADMIN_USERNAME", "admin").strip() or "admin" existing = db.query(User).filter(User.username == admin_username).first() if existing: print(f"Admin user '{admin_username}' already exists — skipping.") return admin_password = os.environ.get("ADMIN_PASSWORD", "").strip() password_was_generated = False if not admin_password: admin_password = _generate_password() password_was_generated = True admin = User( username=admin_username, hashed_password=hash_password(admin_password), role="admin", ) db.add(admin) db.commit() # ── Display credentials in startup logs ────────────────────── print() print("=" * 60) print(" AEGIS — Initial Admin User Created") print("=" * 60) print(f" Username : {admin_username}") if password_was_generated: print(f" Password : {admin_password}") print() print(" ** This password was auto-generated because") print(" ADMIN_PASSWORD was not set in the environment. **") print(" ** Save it now — it will NOT be shown again. **") else: print(" Password : (set via ADMIN_PASSWORD env var)") print("=" * 60) print() finally: db.close() if __name__ == "__main__": seed_admin()