80 lines
2.8 KiB
Python
80 lines
2.8 KiB
Python
"""
|
|
control/cli.py
|
|
--------------
|
|
Thin operator CLI for the control plane. Schema changes go through Alembic
|
|
(`alembic -c control/migrations/alembic.ini upgrade head`); this CLI covers
|
|
the bootstrap actions on top of an already-migrated control DB.
|
|
|
|
python -m control.cli seed
|
|
python -m control.cli create-superadmin --username admin --email you@example.com
|
|
python -m control.cli list-plans
|
|
"""
|
|
|
|
import argparse
|
|
import getpass
|
|
import sys
|
|
|
|
from control.base import control_session
|
|
from control.models import Plan, Superadmin
|
|
from control.seed import seed_plans
|
|
|
|
|
|
def _cmd_seed(_args):
|
|
created, updated = seed_plans()
|
|
print(f'Plans seeded — created={created} updated={updated}')
|
|
|
|
|
|
def _cmd_list_plans(_args):
|
|
with control_session() as s:
|
|
plans = s.query(Plan).order_by(Plan.id).all()
|
|
if not plans:
|
|
print('No plans found. Run: python -m control.cli seed')
|
|
return
|
|
for p in plans:
|
|
print(f' [{p.code}] {p.name} '
|
|
f'users={p.max_users} facilities={p.max_facilities} '
|
|
f'insp/mo={p.max_inspections_month} issues/mo={p.max_issues_month} '
|
|
f'custom_domain={p.allow_custom_domain} mobile={p.allow_mobile_api} '
|
|
f'sched_reports={p.allow_scheduled_reports} branding={p.allow_branding}')
|
|
|
|
|
|
def _cmd_create_superadmin(args):
|
|
with control_session() as s:
|
|
if s.query(Superadmin).filter_by(username=args.username).first():
|
|
print(f"Superadmin '{args.username}' already exists.")
|
|
sys.exit(1)
|
|
if s.query(Superadmin).filter_by(email=args.email).first():
|
|
print(f"Email '{args.email}' already in use.")
|
|
sys.exit(1)
|
|
password = args.password or getpass.getpass('Password: ')
|
|
if not password:
|
|
print('Password cannot be empty.')
|
|
sys.exit(1)
|
|
sa = Superadmin(username=args.username, email=args.email, active=True)
|
|
sa.set_password(password)
|
|
s.add(sa)
|
|
print(f"Superadmin '{args.username}' created.")
|
|
|
|
|
|
def main(argv=None):
|
|
parser = argparse.ArgumentParser(prog='control.cli',
|
|
description='JQC control-plane CLI')
|
|
sub = parser.add_subparsers(dest='command', required=True)
|
|
|
|
sub.add_parser('seed', help='Seed/upsert baseline plans').set_defaults(func=_cmd_seed)
|
|
sub.add_parser('list-plans', help='List plans').set_defaults(func=_cmd_list_plans)
|
|
|
|
p_sa = sub.add_parser('create-superadmin', help='Create a superadmin account')
|
|
p_sa.add_argument('--username', required=True)
|
|
p_sa.add_argument('--email', required=True)
|
|
p_sa.add_argument('--password', default=None,
|
|
help='Omit to be prompted securely.')
|
|
p_sa.set_defaults(func=_cmd_create_superadmin)
|
|
|
|
args = parser.parse_args(argv)
|
|
args.func(args)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|