perf: 综合安全加固 — RBAC严格映射+异步邮件+字段权限白名单+前端对齐+导入模板
本次提交包含本会话所有修改的最终统一提交 ## 权限系统重构 - permission_service.py: 添加入库/采购操作元素 + ensure_default_permissions - field_permissions.py: 严格1-to-1 Default Deny 字段映射(StockBuy/Semi/Product/MaterialBase) - decorators.py: _expand_operation_perms 双向粒度桥接 + prevent_double_submit - deploy_production.sql: 修复 sys_element 别名码(qty_inbound→in_quantity) ## 采购模块 - purchase.py: 权限驱动可见性 + inbound_purchase独立权限 + 价格字段过滤 - purchase_service.py: 异步邮件 + 三阶段批量模糊匹配防N+1 - purchase/index.vue: canApprove严格操作权限 + upload重复修复 ## 导出/入 - base_service.py: export_excel 流式写入防OOM + get_latest_specs 优化 - import_service.py + import_api.py: Excel批量导入(模板+预览+执行) - ImportDialog.vue: 三步骤导入弹窗 ## 异步邮件 - email_service.py: send_email_async (守护线程) - inventory_task.py: send_email→send_email_async ## 前端对齐 - product/semi/buy.vue: 列对齐in_quantity/stock_quantity/available_quantity + localStorage缓存V2 - buyOdoo.vue: 排序修复 + 导入按钮 + 移除点击展开加载 - BomManage.vue: 懒加载分组 + 导入按钮 - list.vue: 导入按钮 - Selection.vue + borrow/apply: BOM匹配修复 + 导入按钮 - outbound/create.vue: 出库类型必选 - AppMain.vue: 移除transition白屏修复 - material_base.ts, outbound.ts, bom.ts, stock.ts: 新增API函数
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
from flask import Blueprint, request, jsonify
|
||||
from flask import Blueprint, request, jsonify, current_app
|
||||
from app.services.outbound_service import OutboundService
|
||||
from flask_jwt_extended import jwt_required, get_jwt_identity, get_jwt
|
||||
from app.utils.decorators import permission_required, audit_log, prevent_double_submit
|
||||
@ -117,18 +117,24 @@ def scan_barcode():
|
||||
get_target_name_fn=lambda: request.get_json().get('order_no') if request.get_json() else None
|
||||
)
|
||||
def create_outbound():
|
||||
# 权限检查:需要 outbound_create:operation 或 outbound_selection:operation 之一
|
||||
# 权限检查:有 outbound_selection 菜单或操作权限即可提交
|
||||
claims = get_jwt()
|
||||
user_role = claims.get('role')
|
||||
user_company = claims.get('company_name', '')
|
||||
if not user_role:
|
||||
return jsonify({'code': 403, 'msg': '未授权'}), 403
|
||||
|
||||
# 超级管理员直接放行
|
||||
if user_role.upper() != 'SUPER_ADMIN':
|
||||
perm_dict = AuthService.get_user_permissions(user_role, company_name=user_company)
|
||||
perms = perm_dict.get('menus', []) + perm_dict.get('elements', [])
|
||||
if ('outbound_create:operation' not in perms) and ('outbound_selection:operation' not in perms):
|
||||
outbound_perms = [p for p in perms if 'outbound' in p.lower() or 'selection' in p.lower() or 'create' in p.lower()]
|
||||
current_app.logger.warning(
|
||||
f"[出库权限调试] role={user_role}, company={user_company}, "
|
||||
f"出库相关权限={outbound_perms}, 全部权限数={len(perms)}"
|
||||
)
|
||||
if 'outbound_selection' not in perms and not any(
|
||||
p.startswith('outbound_selection:') or p.startswith('outbound_create:') for p in perms
|
||||
):
|
||||
return jsonify({'code': 403, 'msg': '权限不足'}), 403
|
||||
|
||||
data = request.get_json()
|
||||
@ -340,7 +346,7 @@ def get_current_user_info():
|
||||
# --------------------------------------------------------
|
||||
@outbound_bp.route('/request', methods=['POST'])
|
||||
@jwt_required()
|
||||
@permission_required('outbound_approval')
|
||||
@permission_required('outbound_selection')
|
||||
def create_outbound_request():
|
||||
"""
|
||||
创建出库审批单(申请阶段,用户只需提交宏观物料信息,无需关联具体库存记录)
|
||||
|
||||
Reference in New Issue
Block a user