2026-11-02 22:20:55 -05:00
|
|
|
|
"""每个受保护接口必须映射权限;未登记接口默认拒绝。"""
|
|
|
|
|
|
|
|
|
|
|
|
RESOURCE_MODULES = {
|
|
|
|
|
|
"base.personnel": "base:personnel", "base.products": "base:products",
|
|
|
|
|
|
"base.customers": "base:customers", "business.businesses": "business:businesses",
|
|
|
|
|
|
"business.shipments": "business:shipments", "business.receipts": "business:receipts",
|
|
|
|
|
|
"business.ratings": "business:ratings", "system.users": "system:users",
|
|
|
|
|
|
"system.roles": "system:roles", "system.business_roles": "system:business_roles",
|
|
|
|
|
|
"system.logs": "system:logs", "system.settings": "system:settings",
|
|
|
|
|
|
"system.monitor": "system:monitor",
|
|
|
|
|
|
}
|
|
|
|
|
|
REPORT_MODULES = {
|
|
|
|
|
|
"personal-detail": "reports:personal", "department-summary": "reports:department",
|
|
|
|
|
|
"business-stats": "reports:business", "payment-stats": "reports:payments",
|
|
|
|
|
|
}
|
|
|
|
|
|
PUBLIC_ENDPOINTS = {("auth", "get_captcha"), ("auth", "login"),
|
|
|
|
|
|
("system.settings", "get_settings_public"), ("system.settings", "get_logo_public")}
|
|
|
|
|
|
LOGIN_ENDPOINTS = {("auth", "me"), ("auth", "logout")}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def permission_for(module, name, method, *, params=None, body=None):
|
|
|
|
|
|
"""返回目录操作码;None 表示没有登记,空串仅用于显式登录态接口。"""
|
|
|
|
|
|
params, body = params or {}, body or {}
|
|
|
|
|
|
if (module, name) in PUBLIC_ENDPOINTS | LOGIN_ENDPOINTS:
|
|
|
|
|
|
return ""
|
|
|
|
|
|
if module == "dashboard":
|
|
|
|
|
|
return "dashboard:view"
|
|
|
|
|
|
if module == "system.authorization":
|
|
|
|
|
|
resource = "system:users" if name in ("user_authorization", "preview", "save_user") else "system:roles"
|
|
|
|
|
|
return resource + (":view" if method == "GET" or name == "preview" else ":update")
|
|
|
|
|
|
if module == "metadata":
|
|
|
|
|
|
return "" # 此端点按请求的参照资源执行独立的关联功能校验。
|
|
|
|
|
|
if module == "base.business_roles":
|
|
|
|
|
|
return "" # 下拉只返回选项;由端点校验人员查看/维护能力。
|
|
|
|
|
|
if module in RESOURCE_MODULES:
|
|
|
|
|
|
resource = RESOURCE_MODULES[module]
|
|
|
|
|
|
if module == "base.products" and name in ("extraction_preview", "extraction_apply", "restore_source"):
|
|
|
|
|
|
return resource + (":create" if name == "extraction_apply" else ":update" if name == "restore_source" else ":view")
|
|
|
|
|
|
if method == "GET":
|
|
|
|
|
|
return resource + ":view"
|
|
|
|
|
|
special = {"set_status": "status", "change_status": "status", "reset_password": "password",
|
2026-11-05 05:47:13 -05:00
|
|
|
|
"confirm_receipt": "confirm",
|
2026-11-02 22:20:55 -05:00
|
|
|
|
"replace_regions": "regions", "replace_plans": "plans", "rate_customer": "rating",
|
2026-11-05 05:47:13 -05:00
|
|
|
|
"change_ownership": "ownership", "batch_ownership": "ownership", "upload_logo": "update"}
|
2026-11-02 22:20:55 -05:00
|
|
|
|
action = special.get(name) or {"POST": "create", "PUT": "update", "DELETE": "delete"}.get(method)
|
|
|
|
|
|
return resource + ":" + action if action else None
|
|
|
|
|
|
if module == "system.params":
|
|
|
|
|
|
action = "view" if method == "GET" else {"submit_change": "update", "withdraw_batch": "withdraw", "preview": "preview"}.get(name)
|
|
|
|
|
|
if name == "export_changes":
|
|
|
|
|
|
action = "export"
|
|
|
|
|
|
return "system:params:" + action if action else None
|
|
|
|
|
|
if module == "system.coefficients":
|
|
|
|
|
|
return "system:params:" + ({"save": "update", "export": "export", "import_preview": "preview"}.get(name, "view"))
|
|
|
|
|
|
if module == "system.calc_templates":
|
|
|
|
|
|
return "system:params:" + ("view" if method == "GET" else "update")
|
|
|
|
|
|
if module == "system.monitor":
|
|
|
|
|
|
return "system:monitor:" + ("export" if name == "diagnostic" else "view")
|
|
|
|
|
|
if module == "system.tplus":
|
|
|
|
|
|
return "tplus:" + ("view" if method == "GET" else "retry" if name == "retry" else "collect")
|
|
|
|
|
|
if module == "system.tplus_workbench":
|
2026-11-05 06:31:01 -05:00
|
|
|
|
if name == "business_sync_preview":
|
|
|
|
|
|
return "tplus:preview"
|
2026-11-05 05:47:13 -05:00
|
|
|
|
if name.startswith("business_sync_"):
|
|
|
|
|
|
return "tplus:view" if method == "GET" else "tplus:import"
|
2026-11-02 22:20:55 -05:00
|
|
|
|
if name == "work_report":
|
|
|
|
|
|
return "tplus:export"
|
|
|
|
|
|
if method == "GET":
|
|
|
|
|
|
return "tplus:view"
|
2026-11-05 05:47:13 -05:00
|
|
|
|
if name in ("save_fact", "save_correction_pair"):
|
2026-11-02 22:20:55 -05:00
|
|
|
|
return "tplus:facts"
|
|
|
|
|
|
if name == "create_work":
|
|
|
|
|
|
return "tplus:import" if body.get("kind") in ("MASTER_APPLY", "BUSINESS_APPLY") else "tplus:preview"
|
|
|
|
|
|
if module in ("payroll", "calc"):
|
|
|
|
|
|
if name == "probation_adjustment":
|
|
|
|
|
|
return "adjustments:create"
|
|
|
|
|
|
if name in ("probation_export", "salary_export"):
|
|
|
|
|
|
return "reports:personal:export"
|
|
|
|
|
|
if method == "GET":
|
|
|
|
|
|
return "payroll:view"
|
|
|
|
|
|
return "adjustments:create" if name == "adjustment" else "payroll:prepare" if name == "save_input" else "payroll:calculate"
|
|
|
|
|
|
if module == "settlements":
|
|
|
|
|
|
if name in ("create_adjustment", "list_adjustments"):
|
|
|
|
|
|
return "adjustments:" + ("view" if method == "GET" else "create")
|
|
|
|
|
|
return "settlements:" + ("view" if method == "GET" else "generate" if name == "generate" else "submit")
|
|
|
|
|
|
if module == "system.approvals":
|
|
|
|
|
|
return "approvals:view" # 节点动作由服务层根据当前节点检查 finance/leader。
|
|
|
|
|
|
if module == "reports":
|
|
|
|
|
|
code = params.get("code") if name == "export_report" else {
|
|
|
|
|
|
"personal_detail": "personal-detail", "department_summary": "department-summary",
|
|
|
|
|
|
"business_stats": "business-stats", "payment_stats": "payment-stats",
|
|
|
|
|
|
"payment_detail": "payment-stats", "payment_day_buckets": "payment-stats",
|
|
|
|
|
|
}.get(name)
|
|
|
|
|
|
resource = REPORT_MODULES.get(code)
|
|
|
|
|
|
return resource + (":export" if name == "export_report" else ":view") if resource else None
|
|
|
|
|
|
return None
|
|
|
|
|
|
|