"""Einmaliges Anlegen des ersten Administration-Benutzers (idempotent). Deployment-Regel (Prompt 19): nur Skript-Datei hier, Ausführung auf Zielsystem. Aufruf (im aktivierten venv auf dem Server): python -m scripts.create_admin --login admin --name "Administrator" --password "..." """ from __future__ import annotations import argparse import asyncio from sqlalchemy import select import app.models # noqa: F401 (alle ORM-Modelle registrieren, sonst schlägt # db.flush() mit NoReferencedTableError fehl, sobald ein Modell eine FK auf # eine Tabelle hat, deren Modell hier nicht importiert wurde - Fund beim # Live-Testlauf, Benutzer.einheit_id -> einheit war nicht mitregistriert) from app.core.security import hash_password from app.db.session import SessionLocal from app.models.auth import Benutzer, BenutzerRolle, RolleTyp async def erstelle_admin(login: str, name: str, password: str, email: str | None) -> None: async with SessionLocal() as db: bestehender = (await db.execute(select(Benutzer).where(Benutzer.login == login))).scalar_one_or_none() if bestehender is not None: print(f"Übersprungen (Login existiert bereits): {login}") return benutzer = Benutzer(name=name, login=login, passwort_hash=hash_password(password), email=email) db.add(benutzer) await db.flush() db.add(BenutzerRolle(benutzer_id=benutzer.id, rolle=RolleTyp.administration)) await db.commit() print(f"Angelegt: {login} (id={benutzer.id}, Rolle administration)") def main() -> None: parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument("--login", required=True) parser.add_argument("--name", required=True) parser.add_argument("--password", required=True) parser.add_argument("--email", default=None) argumente = parser.parse_args() asyncio.run(erstelle_admin(argumente.login, argumente.name, argumente.password, argumente.email)) if __name__ == "__main__": main()