| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- from __future__ import annotations
- import argparse
- import getpass
- import logging
- import os
- import re
- from sqlalchemy import text
- from app import create_app, db
- from app.core.common.identifiers import new_governance_uid
- from app.core.system.auth import hash_password
- logger = logging.getLogger(__name__)
- def validate_password(password: str) -> None:
- if len(password) < 10:
- raise ValueError("password must contain at least 10 characters")
- if not re.search(r"[a-z]", password):
- raise ValueError("password must contain a lowercase letter")
- if not re.search(r"[A-Z]", password):
- raise ValueError("password must contain an uppercase letter")
- if not re.search(r"[0-9]", password):
- raise ValueError("password must contain a digit")
- def log_bootstrap_result(username: str, *, created: bool) -> None:
- if created:
- logger.info("Created first platform administrator: %s", username)
- else:
- logger.info("Platform administrator already exists; bootstrap skipped")
- def bootstrap_first_admin(session, *, username: str, password: str) -> str:
- validate_password(password)
- existing = session.execute(
- text(
- "SELECT COUNT(*) FROM public.users u "
- "JOIN public.user_roles ur ON ur.user_id = u.id "
- "JOIN public.roles r ON r.id = ur.role_id "
- "WHERE r.name = 'admin' AND u.status = 'active'"
- )
- ).scalar_one()
- if existing:
- raise RuntimeError("an active administrator already exists")
- user_id = new_governance_uid()
- session.execute(
- text(
- "INSERT INTO public.users "
- "(id, username, display_name, password_hash) "
- "VALUES (CAST(:id AS uuid), :username, :username, :password_hash)"
- ),
- {"id": user_id, "username": username.strip(), "password_hash": hash_password(password)},
- )
- session.execute(
- text(
- "INSERT INTO public.user_roles (user_id, role_id, assigned_by) "
- "SELECT CAST(:id AS uuid), id, CAST(:id AS uuid) "
- "FROM public.roles WHERE name = 'admin'"
- ),
- {"id": user_id},
- )
- return user_id
- def main() -> None:
- parser = argparse.ArgumentParser(description="Create the first DataOps administrator")
- parser.add_argument("--username", default=os.environ.get("BOOTSTRAP_ADMIN_USERNAME"))
- parser.add_argument("--password", default=os.environ.get("BOOTSTRAP_ADMIN_PASSWORD"))
- parser.add_argument("--if-missing", action="store_true")
- args = parser.parse_args()
- username = args.username or input("Administrator username: ").strip()
- password = args.password or getpass.getpass("Administrator password: ")
- app = create_app()
- with app.app_context():
- try:
- bootstrap_first_admin(db.session, username=username, password=password)
- db.session.commit()
- log_bootstrap_result(username, created=True)
- except RuntimeError:
- db.session.rollback()
- if not args.if_missing:
- raise
- log_bootstrap_result(username, created=False)
- if __name__ == "__main__":
- main()
|