feat: 全模块公司隔离 + crossDomain权限码动态跨域控制

- get_current_company_filter: 新增_has_cross_domain_permission, 权限码替代硬编码
- 补全11个Service的get_current_company_filter调用(semi/product/service/outbound/bom/trans/scrap/summary)
- base/search修复: search_material此前无隔离, 已补全
- get_current_company_filter兜底: JWT缺company_name时返回__NO_COMPANY__防止放行
- permission.py: _get_operator_company补全返回值, 修复权限页保存逻辑
- 新增crossDomain迁移脚本, element_type=element挂system_mgmt下
This commit is contained in:
yueli
2026-07-15 11:11:40 +08:00
parent 56edb92d80
commit e1417d740a
14 changed files with 186 additions and 14 deletions

View File

@ -1,7 +1,7 @@
# inventory-backend/app/api/v1/scrap.py
from flask import Blueprint, request, jsonify
from flask_jwt_extended import jwt_required, get_jwt_identity, get_jwt
from app.utils.decorators import permission_required, audit_log
from app.utils.decorators import permission_required, audit_log, get_current_company_filter
from app.services.auth_service import AuthService
from app.extensions import db
from app.models.transaction import TransScrap, TransRepair
@ -322,6 +322,37 @@ class ScrapService:
if end_date:
query = query.filter(TransScrap.operation_time <= end_date + ' 23:59:59')
# 【行级数据隔离】基于 JWT 多租户公司过滤
# 通过 stock 表或 trans_repair 关联到 MaterialBase
company_limit = get_current_company_filter()
if company_limit is not None:
buy_subq = db.session.query(TransScrap.id).join(
StockBuy, db.and_(TransScrap.stock_id == StockBuy.id,
TransScrap.source_table == 'stock_buy')
).join(MaterialBase, StockBuy.base_id == MaterialBase.id).filter(
MaterialBase.company_name == company_limit
)
semi_subq = db.session.query(TransScrap.id).join(
StockSemi, db.and_(TransScrap.stock_id == StockSemi.id,
TransScrap.source_table == 'stock_semi')
).join(MaterialBase, StockSemi.base_id == MaterialBase.id).filter(
MaterialBase.company_name == company_limit
)
product_subq = db.session.query(TransScrap.id).join(
StockProduct, db.and_(TransScrap.stock_id == StockProduct.id,
TransScrap.source_table == 'stock_product')
).join(MaterialBase, StockProduct.base_id == MaterialBase.id).filter(
MaterialBase.company_name == company_limit
)
repair_subq = db.session.query(TransScrap.id).join(
TransRepair, db.and_(TransScrap.stock_id == TransRepair.id,
TransScrap.source_table == 'trans_repair')
).join(MaterialBase, TransRepair.base_id == MaterialBase.id).filter(
MaterialBase.company_name == company_limit
)
all_matches = buy_subq.union(semi_subq, product_subq, repair_subq).subquery()
query = query.filter(TransScrap.id.in_(all_matches))
# 按时间倒序
query = query.order_by(TransScrap.operation_time.desc())