Add docker admin bootstrap for clean release
This commit is contained in:
@@ -31,10 +31,13 @@ from src.core.logger import logger, belief_scope
|
||||
#
|
||||
# @PARAM: username (str) - Admin username.
|
||||
# @PARAM: password (str) - Admin password.
|
||||
def create_admin(username, password):
|
||||
# @PARAM: email (str | None) - Optional admin email.
|
||||
def create_admin(username, password, email=None):
|
||||
with belief_scope("create_admin"):
|
||||
db = AuthSessionLocal()
|
||||
try:
|
||||
normalized_email = email.strip() if isinstance(email, str) and email.strip() else None
|
||||
|
||||
# 1. Ensure Admin role exists
|
||||
admin_role = db.query(Role).filter(Role.name == "Admin").first()
|
||||
if not admin_role:
|
||||
@@ -48,12 +51,13 @@ def create_admin(username, password):
|
||||
existing_user = db.query(User).filter(User.username == username).first()
|
||||
if existing_user:
|
||||
logger.warning(f"User {username} already exists.")
|
||||
return
|
||||
return "exists"
|
||||
|
||||
# 3. Create Admin user
|
||||
logger.info(f"Creating admin user: {username}")
|
||||
new_user = User(
|
||||
username=username,
|
||||
email=normalized_email,
|
||||
password_hash=get_password_hash(password),
|
||||
auth_source="LOCAL",
|
||||
is_active=True
|
||||
@@ -62,10 +66,12 @@ def create_admin(username, password):
|
||||
db.add(new_user)
|
||||
db.commit()
|
||||
logger.info(f"Admin user {username} created successfully.")
|
||||
|
||||
return "created"
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to create admin user: {e}")
|
||||
db.rollback()
|
||||
raise
|
||||
finally:
|
||||
db.close()
|
||||
# [/DEF:create_admin:Function]
|
||||
@@ -74,10 +80,15 @@ if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Create initial admin user")
|
||||
parser.add_argument("--username", required=True, help="Admin username")
|
||||
parser.add_argument("--password", required=True, help="Admin password")
|
||||
parser.add_argument("--email", required=False, help="Admin email")
|
||||
args = parser.parse_args()
|
||||
|
||||
# Ensure DB is initialized before creating admin
|
||||
init_db()
|
||||
create_admin(args.username, args.password)
|
||||
|
||||
try:
|
||||
# Ensure DB is initialized before creating admin
|
||||
init_db()
|
||||
create_admin(args.username, args.password, args.email)
|
||||
sys.exit(0)
|
||||
except Exception:
|
||||
sys.exit(1)
|
||||
|
||||
# [/DEF:backend.src.scripts.create_admin:Module]
|
||||
@@ -12,6 +12,7 @@ from src.models.auth import User, Role, Permission, ADGroupMapping
|
||||
from src.services.auth_service import AuthService
|
||||
from src.core.auth.repository import AuthRepository
|
||||
from src.core.auth.security import verify_password, get_password_hash
|
||||
from src.scripts.create_admin import create_admin
|
||||
|
||||
# Create in-memory SQLite database for testing
|
||||
SQLALCHEMY_DATABASE_URL = "sqlite:///:memory:"
|
||||
@@ -159,3 +160,32 @@ def test_ad_group_mapping(auth_repo):
|
||||
retrieved_mapping = auth_repo.db.query(ADGroupMapping).filter_by(ad_group="DOMAIN\\ADFS_Admins").first()
|
||||
assert retrieved_mapping is not None
|
||||
assert retrieved_mapping.role_id == role.id
|
||||
|
||||
|
||||
def test_create_admin_creates_user_with_optional_email(monkeypatch, db_session):
|
||||
"""Test bootstrap admin creation stores optional email and Admin role"""
|
||||
monkeypatch.setattr("src.scripts.create_admin.AuthSessionLocal", lambda: db_session)
|
||||
|
||||
result = create_admin("bootstrap-admin", "bootstrap-pass", "admin@example.com")
|
||||
|
||||
created_user = db_session.query(User).filter(User.username == "bootstrap-admin").first()
|
||||
assert result == "created"
|
||||
assert created_user is not None
|
||||
assert created_user.email == "admin@example.com"
|
||||
assert created_user.roles[0].name == "Admin"
|
||||
|
||||
|
||||
def test_create_admin_is_idempotent_for_existing_user(monkeypatch, db_session):
|
||||
"""Test bootstrap admin creation preserves existing user on repeated runs"""
|
||||
monkeypatch.setattr("src.scripts.create_admin.AuthSessionLocal", lambda: db_session)
|
||||
|
||||
first_result = create_admin("bootstrap-admin-2", "bootstrap-pass")
|
||||
second_result = create_admin("bootstrap-admin-2", "new-password", "changed@example.com")
|
||||
|
||||
created_user = db_session.query(User).filter(User.username == "bootstrap-admin-2").first()
|
||||
assert first_result == "created"
|
||||
assert second_result == "exists"
|
||||
assert created_user is not None
|
||||
assert created_user.email is None
|
||||
assert verify_password("bootstrap-pass", created_user.password_hash)
|
||||
assert not verify_password("new-password", created_user.password_hash)
|
||||
|
||||
Reference in New Issue
Block a user