create_admin.py 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041
  1. """SEED_DEMO=false 的首个管理员由终端创建;密码交互读取,避免写入命令历史。"""
  2. import argparse
  3. import asyncio
  4. from getpass import getpass
  5. from pathlib import Path
  6. import sys
  7. sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
  8. from sqlalchemy import select
  9. from app.domain.models import Department, Role, User
  10. from app.infrastructure.database import initialize, transaction, engine
  11. from app.infrastructure.security import validate_password, hash_password
  12. from app.shared.schemas import UserCreate
  13. async def main(args):
  14. password = getpass('管理员密码(大小写、数字、符号,至少10位):')
  15. if password != getpass('再次输入密码:'):
  16. raise ValueError('两次密码不一致')
  17. validate_password(password)
  18. await initialize()
  19. async with transaction() as session:
  20. if await session.scalar(select(User).where(User.username == args.username)):
  21. raise ValueError('登录名已存在;本脚本不覆盖已有身份或密码')
  22. department = await session.scalar(select(Department).where(Department.name == args.department))
  23. if department is None:
  24. department = Department(name=args.department)
  25. session.add(department)
  26. await session.flush()
  27. if not department.active:
  28. raise ValueError('指定部门已停用')
  29. body = UserCreate(username=args.username, real_name=args.name, department_id=department.id, role='admin', password=password)
  30. role = await session.scalar(select(Role).where(Role.code == 'admin'))
  31. session.add(User(username=body.username, real_name=body.real_name, department_id=body.department_id, role_id=role.id, password_hash=hash_password(password)))
  32. await engine.dispose()
  33. print('管理员已创建;请登录后配置真实用户与审批链。')
  34. if __name__ == '__main__':
  35. parser = argparse.ArgumentParser(description='创建首个管理员,不覆盖同名账号')
  36. parser.add_argument('--username', required=True)
  37. parser.add_argument('--name', required=True)
  38. parser.add_argument('--department', required=True)
  39. asyncio.run(main(parser.parse_args()))