"""Management CLI (``mcma``). Commands: * ``mcma version`` โ€” print the backend version. * ``mcma create-admin`` โ€” create the first (or another) superuser. Private instance, so there is no public sign-up โ€” bootstrap admins here (plan ยง11 step 3). """ import argparse import asyncio import getpass from app import __version__ async def _create_admin(username: str, password: str) -> None: from app.application.user_service import UserService from app.core.security import Argon2PasswordHasher from app.infrastructure.db import session_scope from app.infrastructure.db.repositories import ( SqlAlchemyRefreshTokenRepository, SqlAlchemyUserRepository, ) async with session_scope() as session: service = UserService( users=SqlAlchemyUserRepository(session), refresh_tokens=SqlAlchemyRefreshTokenRepository(session), hasher=Argon2PasswordHasher(), ) user = await service.create_user(username=username, password=password, is_superuser=True) print(f"Created admin {user.username!r} ({user.id}).") def _cmd_create_admin(args: argparse.Namespace) -> None: username: str = args.username or input("Username: ").strip() if not username: raise SystemExit("Username is required.") password: str = args.password or getpass.getpass("Password: ") if len(password) < 8: raise SystemExit("Password must be at least 8 characters.") if args.password is None and getpass.getpass("Confirm password: ") != password: raise SystemExit("Passwords do not match.") from app.domain.errors import AlreadyExistsError try: asyncio.run(_create_admin(username, password)) except AlreadyExistsError as exc: raise SystemExit(str(exc)) from exc def main() -> None: parser = argparse.ArgumentParser(prog="mcma", description="mcma-backend management CLI") sub = parser.add_subparsers(dest="command") sub.add_parser("version", help="Print the backend version") admin = sub.add_parser("create-admin", help="Create a superuser") admin.add_argument("username", nargs="?", help="Username (prompted if omitted)") admin.add_argument( "--password", help="Password (prompted securely if omitted; avoid on shared shells)", ) args = parser.parse_args() if args.command == "version": print(__version__) elif args.command == "create-admin": _cmd_create_admin(args) else: parser.print_help() if __name__ == "__main__": main()