feat: P1-P3 全栈集成 — 数据库基础 + DWS 扩展 + 小程序鉴权 + 工程化体系
## P1 数据库基础 - zqyy_app: 创建 auth/biz schema、FDW 连接 etl_feiqiu - etl_feiqiu: 创建 app schema RLS 视图、商品库存预警表 - 清理 assistant_abolish 残留数据 ## P2 ETL/DWS 扩展 - 新增 DWS 助教订单贡献度表 (dws.assistant_order_contribution) - 新增 assistant_order_contribution_task 任务及 RLS 视图 - member_consumption 增加充值字段、assistant_daily 增加处罚字段 - 更新 ODS/DWD/DWS 任务文档及业务规则文档 - 更新 consistency_checker、flow_runner、task_registry 等核心模块 ## P3 小程序鉴权系统 - 新增 xcx_auth 路由/schema(微信登录 + JWT) - 新增 wechat/role/matching/application 服务层 - zqyy_app 鉴权表迁移 + 角色权限种子数据 - auth/dependencies.py 支持小程序 JWT 鉴权 ## 文档与审计 - 新增 DOCUMENTATION-MAP 文档导航 - 新增 7 份 BD_Manual 数据库变更文档 - 更新 DDL 基线快照(etl_feiqiu 6 schema + zqyy_app auth) - 新增全栈集成审计记录、部署检查清单更新 - 新增 BACKLOG 路线图、FDW→Core 迁移计划 ## Kiro 工程化 - 新增 5 个 Spec(P1/P2/P3/全栈集成/核心业务) - 新增审计自动化脚本(agent_on_stop/build_audit_context/compliance_prescan) - 新增 6 个 Hook(合规检查/会话日志/提交审计等) - 新增 doc-map steering 文件 ## 运维与测试 - 新增 ops 脚本:迁移验证/API 健康检查/ETL 监控/集成报告 - 新增属性测试:test_dws_contribution / test_auth_system - 清理过期 export 报告文件 - 更新 .gitignore 排除规则
This commit is contained in:
129
apps/backend/app/services/role.py
Normal file
129
apps/backend/app/services/role.py
Normal file
@@ -0,0 +1,129 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
角色权限服务 —— 查询用户在指定店铺下的角色和权限。
|
||||
|
||||
职责:
|
||||
- get_user_permissions():获取用户在指定 site_id 下的权限 code 列表
|
||||
- get_user_sites():获取用户关联的所有店铺及对应角色
|
||||
- check_user_has_site_role():检查用户在指定 site_id 下是否有任何角色绑定
|
||||
|
||||
所有数据库操作使用 psycopg2 原生 SQL,不引入 ORM。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from app.database import get_connection
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def get_user_permissions(user_id: int, site_id: int) -> list[str]:
|
||||
"""
|
||||
获取用户在指定 site_id 下的权限 code 列表。
|
||||
|
||||
通过 user_site_roles → role_permissions → permissions 三表联查,
|
||||
返回去重后的权限 code 列表。
|
||||
|
||||
参数:
|
||||
user_id: 用户 ID
|
||||
site_id: 门店 ID
|
||||
|
||||
返回:
|
||||
权限 code 字符串列表,如 ["view_tasks", "view_board"]
|
||||
"""
|
||||
conn = get_connection()
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"""
|
||||
SELECT DISTINCT p.code
|
||||
FROM auth.user_site_roles usr
|
||||
JOIN auth.role_permissions rp ON usr.role_id = rp.role_id
|
||||
JOIN auth.permissions p ON rp.permission_id = p.id
|
||||
WHERE usr.user_id = %s AND usr.site_id = %s
|
||||
""",
|
||||
(user_id, site_id),
|
||||
)
|
||||
rows = cur.fetchall()
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
return [row[0] for row in rows]
|
||||
|
||||
|
||||
async def get_user_sites(user_id: int) -> list[dict]:
|
||||
"""
|
||||
获取用户关联的所有店铺及对应角色。
|
||||
|
||||
查询 user_site_roles JOIN roles,LEFT JOIN site_code_mapping 获取店铺名称,
|
||||
按 site_id 分组聚合角色列表。
|
||||
|
||||
参数:
|
||||
user_id: 用户 ID
|
||||
|
||||
返回:
|
||||
[{"site_id": int, "site_name": str, "roles": [{"code": str, "name": str}]}]
|
||||
"""
|
||||
conn = get_connection()
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"""
|
||||
SELECT usr.site_id,
|
||||
COALESCE(scm.site_name, '') AS site_name,
|
||||
r.code,
|
||||
r.name
|
||||
FROM auth.user_site_roles usr
|
||||
JOIN auth.roles r ON usr.role_id = r.id
|
||||
LEFT JOIN auth.site_code_mapping scm ON usr.site_id = scm.site_id
|
||||
WHERE usr.user_id = %s
|
||||
ORDER BY usr.site_id, r.code
|
||||
""",
|
||||
(user_id,),
|
||||
)
|
||||
rows = cur.fetchall()
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
# 按 site_id 分组聚合
|
||||
sites_map: dict[int, dict] = {}
|
||||
for site_id, site_name, role_code, role_name in rows:
|
||||
if site_id not in sites_map:
|
||||
sites_map[site_id] = {
|
||||
"site_id": site_id,
|
||||
"site_name": site_name,
|
||||
"roles": [],
|
||||
}
|
||||
sites_map[site_id]["roles"].append({"code": role_code, "name": role_name})
|
||||
|
||||
return list(sites_map.values())
|
||||
|
||||
|
||||
async def check_user_has_site_role(user_id: int, site_id: int) -> bool:
|
||||
"""
|
||||
检查用户在指定 site_id 下是否有任何角色绑定。
|
||||
|
||||
参数:
|
||||
user_id: 用户 ID
|
||||
site_id: 门店 ID
|
||||
|
||||
返回:
|
||||
True 表示有角色绑定,False 表示无
|
||||
"""
|
||||
conn = get_connection()
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"""
|
||||
SELECT 1
|
||||
FROM auth.user_site_roles
|
||||
WHERE user_id = %s AND site_id = %s
|
||||
LIMIT 1
|
||||
""",
|
||||
(user_id, site_id),
|
||||
)
|
||||
return cur.fetchone() is not None
|
||||
finally:
|
||||
conn.close()
|
||||
Reference in New Issue
Block a user