#!/usr/bin/env python3 """校验指定用户的 Web menuCodes 是否包含前端侧栏所需的 :list 权限。""" from __future__ import annotations import argparse import os import sys from pathlib import Path from sqlalchemy import create_engine, text from sqlalchemy.orm import Session BACKEND_ROOT = Path(__file__).resolve().parents[1] if str(BACKEND_ROOT) not in sys.path: sys.path.insert(0, str(BACKEND_ROOT)) TENANT_NO = "shanxia2.0" # 前端侧栏关键 :list(与 sqxp.ts / pl.ts meta.menuCode 对齐) REQUIRED_LIST_CODES = [ "crm:clue:list", "crm:customer:list", "crm:customerPool:list", "bx:expenseItem:list", "db:dashboard:list", "pl:plan:list", ] def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("--env-file", default=".env.production") parser.add_argument("--user-no", default="方金强") args = parser.parse_args() if args.env_file: os.environ["ENV_FILE"] = args.env_file from dotenv import load_dotenv path = Path(args.env_file) if not path.is_absolute(): path = BACKEND_ROOT / path if path.is_file(): load_dotenv(path, override=True) from app.core.config import Settings from app.services.web_auth_roles import iter_user_menu_perm_codes engine = create_engine(Settings().DATABASE_URL, pool_pre_ping=True) with Session(engine) as db: row = db.execute( text( """ SELECT id, nick_name FROM sys_user WHERE tenant_no = :tenant AND user_no = :user_no AND del_flag = 0 LIMIT 1 """ ), {"tenant": TENANT_NO, "user_no": args.user_no}, ).first() if not row: print(f"用户不存在: {args.user_no}") return 1 uid, nick = str(row[0]), row[1] codes = iter_user_menu_perm_codes(db, uid, TENANT_NO) print(f"用户: {args.user_no} ({nick}) id={uid}") print(f"menuCodes 总数: {len(codes)}") list_codes = sorted(c for c in codes if c.endswith(":list")) print(f":list 数量: {len(list_codes)}") missing = [c for c in REQUIRED_LIST_CODES if c not in codes] if missing: print(f"缺少关键 :list ({len(missing)}): {', '.join(missing)}") return 1 print("关键 :list 均已具备,前端侧栏应可正常展示(需配合最新 web-admin 构建)。") return 0 if __name__ == "__main__": raise SystemExit(main())