""" Script to create a shop account with an operator-supplied strong password. Usage: python -m app.db.create_shop_account Provide SHOP_ACCOUNT_PASSWORD for non-interactive execution, or enter the password securely via getpass(). """ from __future__ import annotations import os import sys from getpass import getpass from sqlalchemy import select from app.core.security import get_password_hash from app.db.session import SessionLocal, engine from app.models import Base, RoleEnum, User SHOP_USERNAME = "shop" MIN_PASSWORD_LENGTH = 12 def _validate_password_strength(password: str) -> None: if len(password) < MIN_PASSWORD_LENGTH or len(password) > 72: raise ValueError("Password must be between 12 and 72 characters long.") has_upper = any(char.isupper() for char in password) has_lower = any(char.islower() for char in password) has_digit = any(char.isdigit() for char in password) has_special = any(not char.isalnum() for char in password) if not all((has_upper, has_lower, has_digit, has_special)): raise ValueError( "Password must include upper, lower, digit, and special characters." ) def _get_shop_password() -> str: env_password = os.getenv("SHOP_ACCOUNT_PASSWORD", "").strip() if env_password: _validate_password_strength(env_password) return env_password if not sys.stdin.isatty(): raise RuntimeError( "Interactive password input is unavailable. Set SHOP_ACCOUNT_PASSWORD to create the account safely." ) while True: password = getpass("Enter a strong password for the shop account: ") confirm_password = getpass("Confirm the password: ") if password != confirm_password: print("Passwords do not match. Please try again.", file=sys.stderr) continue _validate_password_strength(password) return password def create_shop_account() -> None: """Create a shop account with a strong password if it doesn't exist.""" Base.metadata.create_all(bind=engine) with SessionLocal() as db: existing = db.scalar( select(User).where(User.username == SHOP_USERNAME) ) if existing is not None: print(f"Shop account '{SHOP_USERNAME}' already exists (id={existing.id}).") print("No new account was created.") return password = _get_shop_password() password_hash = get_password_hash(password) shop = User( username=SHOP_USERNAME, password_hash=password_hash, role=RoleEnum.shop, is_active=True, ) db.add(shop) db.commit() db.refresh(shop) print("=" * 60) print("SHOP ACCOUNT CREATED SUCCESSFULLY") print("=" * 60) print(f"Username: {SHOP_USERNAME}") print("=" * 60) print("Password was accepted and hashed without being printed to stdout.") print("=" * 60) if __name__ == "__main__": try: create_shop_account() except Exception as exc: print(f"Error: {exc}", file=sys.stderr) sys.exit(1)