Add admin recovery option to bootstrap flow

This commit is contained in:
Jage9
2026-02-28 00:19:33 -05:00
parent 99d2b3c822
commit 71d6309efa

View File

@@ -2796,34 +2796,83 @@ def run() -> None:
"Password rules: " "Password rules: "
f"{auth_service.password_min_length}-{auth_service.password_max_length} chars." f"{auth_service.password_min_length}-{auth_service.password_max_length} chars."
) )
while True: if auth_service.has_admin():
username = input("Admin username: ").strip() print("An admin account already exists.")
normalized_username = auth_service._normalize_username(username) return
try:
auth_service._validate_username(normalized_username)
except AuthError as exc:
print(f"Invalid username: {exc}")
continue
password = getpass("Admin password: ") def prompt_create_admin() -> bool:
try: while True:
auth_service._validate_password(password) username = input("Admin username: ").strip()
except AuthError as exc: normalized_username = auth_service._normalize_username(username)
print(f"Invalid password: {exc}") try:
continue auth_service._validate_username(normalized_username)
except AuthError as exc:
print(f"Invalid username: {exc}")
continue
password_confirm = getpass("Re-enter admin password: ") password = getpass("Admin password: ")
if password != password_confirm: try:
print("Passwords do not match.") auth_service._validate_password(password)
continue except AuthError as exc:
print(f"Invalid password: {exc}")
continue
email = input("Admin email (optional): ").strip() or None password_confirm = getpass("Re-enter admin password: ")
try: if password != password_confirm:
created = auth_service.bootstrap_admin(normalized_username, password, email=email) print("Passwords do not match.")
print(f"Admin created: {created.username}") continue
break
except AuthError as exc: email = input("Admin email (optional): ").strip() or None
print(f"Could not create admin: {exc}") try:
created = auth_service.bootstrap_admin(normalized_username, password, email=email)
print(f"Admin created: {created.username}")
return True
except AuthError as exc:
print(f"Could not create admin: {exc}")
if auth_service.has_admin():
return False
def prompt_promote_existing_admin() -> bool:
users = auth_service.list_users_for_admin_menu()
if not users:
print("No existing users found; create a new admin instead.")
return False
print("Existing users:")
for user in users:
print(f" - {user['username']} ({user['role']}, {user['status']})")
while True:
username = input("Existing username to promote: ").strip()
if not username:
print("Username is required.")
continue
try:
normalized = auth_service._normalize_username(username)
auth_service.set_user_role(normalized, "admin")
print(f"Admin promoted: {normalized}")
return True
except AuthError as exc:
print(f"Could not promote user: {exc}")
if auth_service.list_users_for_admin_menu():
print("No admin account found. Choose bootstrap mode:")
print(" 1) Promote existing account to admin")
print(" 2) Create new admin account")
while True:
choice = input("Select [1/2]: ").strip()
if choice == "1":
if prompt_promote_existing_admin():
break
print("Falling back to new admin creation.")
if prompt_create_admin():
break
continue
if choice == "2":
if prompt_create_admin():
break
continue
print("Please select 1 or 2.")
else:
prompt_create_admin()
finally: finally:
auth_service.close() auth_service.close()
return return