feat: 跨域访问从硬编码改为权限码crossDomain动态控制, 新增SQL迁移脚本
This commit is contained in:
@ -167,14 +167,33 @@ def permission_required(permission_code):
|
|||||||
return decorator
|
return decorator
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
def _has_cross_domain_permission(user_role, user_company=''):
|
||||||
|
"""
|
||||||
|
检查指定角色是否拥有「全局跨域访问」权限。
|
||||||
|
复用 AuthService.get_user_permissions 统一查询。
|
||||||
|
"""
|
||||||
|
if not user_role:
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
from app.services.auth_service import AuthService
|
||||||
|
perm_dict = AuthService.get_user_permissions(user_role, company_name=user_company)
|
||||||
|
all_perms = perm_dict.get('menus', []) + perm_dict.get('elements', [])
|
||||||
|
return 'crossDomain' in all_perms
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def get_current_company_filter():
|
def get_current_company_filter():
|
||||||
"""
|
"""
|
||||||
多租户数据权限隔离工具函数。
|
多租户数据权限隔离工具函数。
|
||||||
|
|
||||||
根据当前 JWT 中的 role 和 company_name 决定 SQL 查询应过滤到哪个公司。
|
权限逻辑(基于权限码 crossDomain,支持动态分配):
|
||||||
|
- SUPER_ADMIN → None(全量跨域)
|
||||||
|
- 拥有 crossDomain 权限 → None(全量跨域)
|
||||||
|
- 普通用户 → 强制隔离到 JWT 中记录的公司
|
||||||
|
|
||||||
返回值:
|
返回值:
|
||||||
None → 不限制公司(超级管理员全局视角,或显式传了 'ALL')
|
None → 不限制公司
|
||||||
str → 仅查询该公司数据
|
str → 仅查询该公司数据
|
||||||
|
|
||||||
使用示例:
|
使用示例:
|
||||||
@ -194,17 +213,21 @@ def get_current_company_filter():
|
|||||||
# 从请求参数获取前端指定的公司(兼容 company_name 和 company 两个参数名)
|
# 从请求参数获取前端指定的公司(兼容 company_name 和 company 两个参数名)
|
||||||
req_company = request.args.get('company_name', '') or request.args.get('company', '')
|
req_company = request.args.get('company_name', '') or request.args.get('company', '')
|
||||||
|
|
||||||
|
# 超级管理员 → 全局跨域
|
||||||
if user_role == 'SUPER_ADMIN':
|
if user_role == 'SUPER_ADMIN':
|
||||||
# 超级管理员:允许通过参数指定公司过滤
|
|
||||||
if req_company and req_company.strip().upper() != 'ALL':
|
if req_company and req_company.strip().upper() != 'ALL':
|
||||||
return req_company.strip()
|
return req_company.strip()
|
||||||
# 未指定或指定了 ALL → 返回 None(全量,不限制)
|
|
||||||
return None
|
return None
|
||||||
else:
|
|
||||||
# 其他角色(SUPERVISOR / FINANCE / WAREHOUSE_MGR 等):
|
# 动态权限码检查:拥有 crossDomain 权限 → 全局跨域
|
||||||
# 强制隔离到 JWT 中记录的公司,无视前端参数
|
user_company = claims.get('company_name', '')
|
||||||
user_company = claims.get('company_name', '')
|
if user_role and _has_cross_domain_permission(user_role, user_company):
|
||||||
return user_company if user_company else None
|
if req_company and req_company.strip().upper() != 'ALL':
|
||||||
|
return req_company.strip()
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 普通用户 → 强制隔离到本公司
|
||||||
|
return user_company if user_company else None
|
||||||
|
|
||||||
|
|
||||||
def audit_log(module: str = None, action: str = None, get_target_id_fn=None, get_target_name_fn=None, get_details_fn=None):
|
def audit_log(module: str = None, action: str = None, get_target_id_fn=None, get_target_name_fn=None, get_details_fn=None):
|
||||||
|
|||||||
47
inventory-backend/migrations_add_cross_domain_permission.sql
Normal file
47
inventory-backend/migrations_add_cross_domain_permission.sql
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
-- ============================================================
|
||||||
|
-- migrations_add_cross_domain_permission.sql
|
||||||
|
-- 新增「全局跨域访问」权限节点,支持基于权限码的动态跨公司数据访问控制
|
||||||
|
--
|
||||||
|
-- 逻辑:
|
||||||
|
-- - 拥有 crossDomain 权限的角色 → 可查看所有公司数据
|
||||||
|
-- - 无此权限的角色 → 只能看本公司数据
|
||||||
|
--
|
||||||
|
-- 执行方式:
|
||||||
|
-- psql -h <host> -U postgres -d inventory_system -f migrations_add_cross_domain_permission.sql
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
-- 1. 向 sys_element 插入跨域权限码(挂 system 菜单下)
|
||||||
|
INSERT INTO sys_element (menu_code, name, code, element_type)
|
||||||
|
SELECT 'system_mgmt', '全局跨域访问', 'crossDomain', 'button'
|
||||||
|
WHERE NOT EXISTS (
|
||||||
|
SELECT 1 FROM sys_element WHERE code = 'crossDomain'
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 2. 向 sys_menu 插入菜单节点(如果 system 菜单下还缺此菜单项)
|
||||||
|
-- 注意: 这是一个能力型权限,不一定需要前端菜单入口,
|
||||||
|
-- 如果需要在权限分配页面中可见,保留此 INSERT;
|
||||||
|
-- 如果纯后端控制,此行可注释。
|
||||||
|
INSERT INTO sys_menu (code, name, parent_code, is_visible)
|
||||||
|
SELECT 'system_cross_domain', '全局跨域访问', 'system_mgmt', true
|
||||||
|
WHERE NOT EXISTS (
|
||||||
|
SELECT 1 FROM sys_menu WHERE code = 'system_cross_domain'
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 3. 默认分配给 SUPER_ADMIN 角色
|
||||||
|
INSERT INTO sys_role_permission (role_code, target_code, type)
|
||||||
|
SELECT 'SUPER_ADMIN', 'crossDomain', 'element'
|
||||||
|
WHERE NOT EXISTS (
|
||||||
|
SELECT 1 FROM sys_role_permission
|
||||||
|
WHERE role_code = 'SUPER_ADMIN' AND target_code = 'crossDomain'
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 4. 验证
|
||||||
|
SELECT code, name, menu_code, element_type
|
||||||
|
FROM sys_element WHERE code = 'crossDomain';
|
||||||
|
|
||||||
|
SELECT role_code, target_code, type
|
||||||
|
FROM sys_role_permission WHERE target_code = 'crossDomain';
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
Reference in New Issue
Block a user