fix: 店铺管理接口超级管理员权限校验失效
改用 has_perm_code 替代 set(permissions) 交集判断,避免 _AllPermissions 被转成 set 后丢失超管放行能力。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user