fix: 店铺管理接口超级管理员权限校验失效

改用 has_perm_code 替代 set(permissions) 交集判断,避免 _AllPermissions 被转成 set 后丢失超管放行能力。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-07-09 23:06:34 +08:00
parent 214b52badd
commit a92352f2b0

View File

@@ -50,6 +50,7 @@ from products.utils import update_shangpin_daily_stat
from orders.notice_tasks import dingdan_guangbo
from ..utils import (
verify_kefu_permission,
has_perm_code,
PERMISSION_TO_SHENFEN,
SHENFEN_PROFILE_MAP,
has_fadan_view_permission,
@@ -113,6 +114,7 @@ from ..serializers import PopupPageSerializer
# 全局常量、日志对象
logger = logging.getLogger('houtai')
SHOP_PRODUCT_PERMS = ['1199ab', '1199abc', '1199abd']
SHOP_MANAGE_PERMS = ('999a', '999b', '999c', '999d', '999e')
class ShopListView(APIView):
permission_classes = [IsAuthenticated]
@@ -125,8 +127,7 @@ class ShopListView(APIView):
return Response({'code': 403, 'msg': '身份验证失败,请检查登录状态'})
# 2. 检查是否拥有所需权限999a~999e 任意一个)
required_perms = {'999a', '999b', '999c', '999d', '999e'}
if not required_perms.intersection(set(permissions)):
if not has_perm_code(permissions, *SHOP_MANAGE_PERMS):
return Response({'code': 403, 'msg': '您没有权限访问店铺管理功能'})
# 3. 解析请求参数
@@ -220,21 +221,19 @@ class ShopModifyView(APIView):
if kefu is None:
return Response({'code': 403, 'msg': '身份验证失败,请检查登录状态'})
# 转换权限为集合方便判断
user_perms = set(permissions)
action = request.data.get('action', '')
# 2. 根据 action 分派任务
if action == 'update_dianpu':
return self._update_dianpu(request, user_perms)
return self._update_dianpu(request, permissions)
elif action == 'add_dianpu':
return self._add_dianpu(request, user_perms)
return self._add_dianpu(request, permissions)
elif action == 'update_default':
return self._update_default(request, user_perms)
return self._update_default(request, permissions)
else:
return Response({'code': 400, 'msg': '未知操作类型'})
def _update_dianpu(self, request, user_perms):
def _update_dianpu(self, request, permissions):
"""修改店铺信息,精确权限控制"""
dianpu_id = request.data.get('dianpu_id')
if not dianpu_id:
@@ -246,7 +245,7 @@ class ShopModifyView(APIView):
# 基础信息修改 (999e)
if any(k in request.data for k in ['dianpu_mingcheng', 'lianxi_dianhua', 'weixinhao']):
if '999e' not in user_perms:
if not has_perm_code(permissions, '999e'):
return Response({'code': 403, 'msg': '无权限修改店铺基本信息(999e)'})
if 'dianpu_mingcheng' in request.data:
dianpu.dianpu_mingcheng = request.data['dianpu_mingcheng']
@@ -257,7 +256,7 @@ class ShopModifyView(APIView):
# 店铺状态 (999a)
if 'zhuangtai' in request.data:
if '999a' not in user_perms:
if not has_perm_code(permissions, '999a'):
return Response({'code': 403, 'msg': '无权限修改店铺状态(999a)'})
new_status = int(request.data['zhuangtai'])
if new_status not in (0, 1):
@@ -266,13 +265,13 @@ class ShopModifyView(APIView):
# 可提现余额 (999b)
if 'ketixian_yue' in request.data:
if '999b' not in user_perms:
if not has_perm_code(permissions, '999b'):
return Response({'code': 403, 'msg': '无权限修改可提现余额(999b)'})
dianpu.ketixian_yue = request.data['ketixian_yue']
# 提现限额相关 (999c)
if 'kaiqi_meiri_xiane' in request.data or 'meiri_tixian_xiane' in request.data:
if '999c' not in user_perms:
if not has_perm_code(permissions, '999c'):
return Response({'code': 403, 'msg': '无权限修改提现限额配置(999c)'})
if 'kaiqi_meiri_xiane' in request.data:
dianpu.kaiqi_meiri_xiane = request.data['kaiqi_meiri_xiane']
@@ -281,7 +280,7 @@ class ShopModifyView(APIView):
# 抽成相关 (999d)
if 'kaiqi_shouyi_choucheng' in request.data or 'shouyi_choucheng_feilv' in request.data:
if '999d' not in user_perms:
if not has_perm_code(permissions, '999d'):
return Response({'code': 403, 'msg': '无权限修改抽成配置(999d)'})
if 'kaiqi_shouyi_choucheng' in request.data:
dianpu.kaiqi_shouyi_choucheng = request.data['kaiqi_shouyi_choucheng']
@@ -297,9 +296,9 @@ class ShopModifyView(APIView):
logger.exception("修改店铺失败")
return Response({'code': 500, 'msg': '修改失败,请稍后重试'})
def _add_dianpu(self, request, user_perms):
def _add_dianpu(self, request, permissions):
"""添加店铺,需要权限 999b"""
if '999b' not in user_perms:
if not has_perm_code(permissions, '999b'):
return Response({'code': 403, 'msg': '无权限添加店铺(999b)'})
yonghu_id = request.data.get('yonghu_id')
@@ -346,16 +345,16 @@ class ShopModifyView(APIView):
logger.exception("创建店铺失败")
return Response({'code': 500, 'msg': '创建失败,请稍后重试'})
def _update_default(self, request, user_perms):
def _update_default(self, request, permissions):
"""修改默认配置,按修改内容校验权限"""
feilv = request.data.get('moren_choucheng_feilv')
xiane = request.data.get('moren_tixian_xiane')
modify_commission = feilv is not None
modify_withdraw = xiane is not None
if modify_commission and '999d' not in user_perms:
if modify_commission and not has_perm_code(permissions, '999d'):
return Response({'code': 403, 'msg': '无权限修改默认抽成费率(999d)'})
if modify_withdraw and '999c' not in user_perms:
if modify_withdraw and not has_perm_code(permissions, '999c'):
return Response({'code': 403, 'msg': '无权限修改默认可提现限额(999c)'})
try:
@@ -394,7 +393,7 @@ class ShopPublicTypeAndAuditView(APIView):
return Response({'code': 403, 'msg': '身份验证失败,请检查登录状态'})
# 拥有 1199ab/1199abc/1199abd 任一个即可访问
if not set(permissions).intersection(SHOP_PRODUCT_PERMS):
if not has_perm_code(permissions, *SHOP_PRODUCT_PERMS):
return Response({'code': 403, 'msg': '无权访问店铺商品管理功能'})
# ---------- 查询公共商品类型(仅正常审核状态的) ----------
@@ -444,7 +443,7 @@ class ShopListForProductView(APIView):
kefu, permissions = verify_kefu_permission(request, username)
if kefu is None:
return Response({'code': 403, 'msg': '身份验证失败'})
if not set(permissions).intersection(SHOP_PRODUCT_PERMS):
if not has_perm_code(permissions, *SHOP_PRODUCT_PERMS):
return Response({'code': 403, 'msg': '无权访问店铺列表'})
# ---------- 安全解析分页参数 ----------
@@ -520,7 +519,7 @@ class ShopProductTypeMappingView(APIView):
kefu, permissions = verify_kefu_permission(request, username)
if kefu is None:
return Response({'code': 403, 'msg': '身份验证失败'})
if not set(permissions).intersection(SHOP_PRODUCT_PERMS):
if not has_perm_code(permissions, *SHOP_PRODUCT_PERMS):
return Response({'code': 403, 'msg': '无权访问商品类型映射'})
# ---------- 安全解析参数 ----------
@@ -611,7 +610,7 @@ class ShopProductModifyView(APIView):
if kefu is None:
return Response({'code': 403, 'msg': '身份验证失败'})
user_perms = set(permissions)
user_perms = permissions
action = request.data.get('action')
if action == 'update_audit_mode':
@@ -623,7 +622,7 @@ class ShopProductModifyView(APIView):
@transaction.atomic # ✅ 事务修复点
def _update_audit_mode(self, request, user_perms):
if '1199ab' not in user_perms:
if not has_perm_code(permissions, '1199ab'):
return Response({'code': 403, 'msg': '无权限修改审核模式'})
kaiqi = request.data.get('kaiqi_shenhe')
@@ -657,25 +656,25 @@ class ShopProductModifyView(APIView):
# 权限判断
if fengjin is not None:
if fengjin:
if '1199abc' not in user_perms:
if not has_perm_code(user_perms, '1199abc'):
return Response({'code': 403, 'msg': '无权限封禁'})
else:
if '1199abd' not in user_perms:
if not has_perm_code(user_perms, '1199abd'):
return Response({'code': 403, 'msg': '无权限解封'})
mapping.fengjin_zhuangtai = bool(fengjin)
if shangjia is not None:
if not shangjia:
if '1199abc' not in user_perms:
if not has_perm_code(user_perms, '1199abc'):
return Response({'code': 403, 'msg': '无权限下架'})
else:
if '1199abd' not in user_perms:
if not has_perm_code(user_perms, '1199abd'):
return Response({'code': 403, 'msg': '无权限上架'})
mapping.shangjia_zhuangtai = bool(shangjia)
if shenhe is not None:
if shenhe:
if '1199abd' not in user_perms:
if not has_perm_code(user_perms, '1199abd'):
return Response({'code': 403, 'msg': '无权限审核通过'})
mapping.shenhe_zhuangtai = bool(shenhe)
@@ -706,7 +705,7 @@ class ProductListView(APIView):
if kefu is None:
return Response({'code': 403, 'msg': '身份验证失败'})
if not set(permissions).intersection(PRODUCT_PERMS):
if not has_perm_code(permissions, *PRODUCT_PERMS):
return Response({'code': 403, 'msg': '无商品管理权限'})
# ----- 安全解析分页与筛选参数 -----
@@ -844,16 +843,15 @@ class ProductModifyView(APIView):
if kefu is None:
return Response({'code': 403, 'msg': '身份验证失败'})
user_perms = set(permissions)
action = request.data.get('action', '')
if action != 'update_product':
return Response({'code': 400, 'msg': '未知操作'})
return self._update_product(request, user_perms)
return self._update_product(request, permissions)
@transaction.atomic
def _update_product(self, request, user_perms):
def _update_product(self, request, permissions):
"""执行商品修改,严格校验权限"""
product_id = request.data.get('product_id')
if not product_id:
@@ -877,18 +875,18 @@ class ProductModifyView(APIView):
# ---------- 权限分类检查 ----------
# 1. 封禁/下架操作 (消极操作) -> 1199abc
if any(status_changes.get(k) is not None and status_changes[k] == False for k in ['shangjia', 'shenhe']):
if '1199abc' not in user_perms:
if not has_perm_code(permissions, '1199abc'):
return Response({'code': 403, 'msg': '无权限执行下架/封禁/驳回审核操作(1199abc)'})
if status_changes.get('fengjin') is not None and status_changes['fengjin'] == True:
if '1199abc' not in user_perms:
if not has_perm_code(permissions, '1199abc'):
return Response({'code': 403, 'msg': '无权限执行封禁操作(1199abc)'})
# 2. 解封/上架/过审 (积极操作) -> 1199abd
if any(status_changes.get(k) is not None and status_changes[k] == True for k in ['shangjia', 'shenhe']):
if '1199abd' not in user_perms:
if not has_perm_code(permissions, '1199abd'):
return Response({'code': 403, 'msg': '无权限执行上架/解封/审核通过操作(1199abd)'})
if status_changes.get('fengjin') is not None and status_changes['fengjin'] == False:
if '1199abd' not in user_perms:
if not has_perm_code(permissions, '1199abd'):
return Response({'code': 403, 'msg': '无权限执行解封操作(1199abd)'})
# 3. 修改其他数据(非状态字段)-> 1199abe
@@ -896,7 +894,7 @@ class ProductModifyView(APIView):
other_fields = [k for k in request.data.keys() if k not in ['action', 'product_id', 'username',
'shangjia_zhuangtai', 'fengjin_zhuangtai',
'shenhe_zhuangtai']]
if other_fields and '1199abe' not in user_perms:
if other_fields and not has_perm_code(permissions, '1199abe'):
return Response({'code': 403, 'msg': '无权限修改商品基本信息(1199abe)'})
# ---------- 应用修改 ----------
@@ -946,8 +944,7 @@ class ShopCopyCatalogView(APIView):
if kefu is None:
return Response({'code': 403, 'msg': '身份验证失败,请检查登录状态'})
required_perms = {'999a', '999b', '999c', '999d', '999e'}
if not required_perms.intersection(set(permissions)):
if not has_perm_code(permissions, *SHOP_MANAGE_PERMS):
return Response({'code': 403, 'msg': '您没有权限执行店铺商品复制操作'})
source_user_uid = str(request.data.get('source_user_uid', '')).strip()