"""First run: an account to sign in with. An instance started from the command line is given no environment, so the superuser a deployment sets in `.env` has to come from somewhere. The session key is the CLI's own business — it has to be set before this module can be imported at all. """ from __future__ import annotations import secrets from sqlmodel import Session, select from fluksio import crud from fluksio.models import User, UserCreate #: A generated admin's address. `example.com` is reserved for exactly this #: (RFC 2606) — `@localhost` and `.local` are too, and `EmailStr` refuses those. #: It is a name to sign in with, not somewhere mail is sent. DEFAULT_ADMIN = "admin@example.com" def ensure_superuser( session: Session, *, email: str | None = None, password: str | None = None ) -> tuple[User, str | None]: """The account to sign in with, made on first run. Returns the user and, when it was just created, the password in clear — the caller prints it once. An instance that already has a superuser is left alone: this is a first run, not a password reset. """ existing = session.exec( select(User).where(User.is_superuser == True) # noqa: E712 ).first() if existing is not None: return existing, None generated = password or secrets.token_urlsafe(12) user = crud.create_user( session=session, user_create=UserCreate( email=email or DEFAULT_ADMIN, password=generated, is_superuser=True ), ) return user, generated def pick_superuser(session: Session, email: str | None = None) -> User: """The account an enrolment acts as; a portal session arrives as this one.""" if email: user = session.exec(select(User).where(User.email == email)).first() if user is None: raise LookupError(f"No account here with the address {email}") return user users = session.exec( select(User).where(User.is_superuser == True) # noqa: E712 ).all() if not users: raise LookupError("This instance has no superuser to enrol as") if len(users) > 1: addresses = ", ".join(sorted(u.email for u in users)) raise LookupError(f"Several superusers here — name one with --as: {addresses}") return users[0]