From a30bd69bf25598e614fe11dc89c1637967d5d8c1 Mon Sep 17 00:00:00 2001 From: XingQue Date: Sat, 20 Jun 2026 13:39:13 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AD=90=E5=AE=A2=E6=9C=8D=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E7=A6=81=E6=AD=A2=E5=AF=B9=E8=87=AA=E5=B7=B1?= =?UTF-8?q?=E5=88=92=E6=94=B6=E9=A2=9D=E5=BA=A6=E3=80=81=E6=8D=A2=E8=A7=92?= =?UTF-8?q?=E8=89=B2=E3=80=81=E5=B0=81=E7=A6=81=EF=BC=9B=E6=88=90=E5=91=98?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E8=BF=94=E5=9B=9E=20isSelf=EF=BC=9B=E5=85=B7?= =?UTF-8?q?=E5=A4=87=20staff=5Fmanage=20=E7=9A=84=E6=80=BB=E7=AE=A1?= =?UTF-8?q?=E5=8F=AF=E8=AF=BB=E8=A7=92=E8=89=B2=E5=88=97=E8=A1=A8=E7=94=A8?= =?UTF-8?q?=E4=BA=8E=E7=BB=99=E4=BB=96=E4=BA=BA=E6=8D=A2=E8=A7=92=E8=89=B2?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- merchant_ops/views_manage.py | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/merchant_ops/views_manage.py b/merchant_ops/views_manage.py index 131814a..e69098e 100644 --- a/merchant_ops/views_manage.py +++ b/merchant_ops/views_manage.py @@ -84,6 +84,12 @@ def _resolve_wallet_operator(request, perm_code): return member.merchant_id, member +def _assert_not_self_target(operator_member, target_member): + """子客服不得对自己做管理类操作(划收额度、换角色、封禁等)。""" + if operator_member and target_member.id == operator_member.id: + raise StaffAuthError(400, '不能对本人执行此操作') + + class StaffInviteCreateView(APIView): permission_classes = [IsAuthenticated] @@ -212,6 +218,7 @@ class StaffMemberListView(APIView): 'quota_available': str(wallet.quota_available), 'quota_total': str(wallet.quota_total), 'quota_used': str(wallet.quota_used), + 'isSelf': m.staff_user_id == request.user.UserUID, }) return Response({'code': 0, 'msg': '成功', 'data': {'list': result}}) except Exception as e: @@ -223,12 +230,13 @@ class StaffMemberUpdateRoleView(APIView): def post(self, request): try: - mid, _ = _resolve_manage_context(request, need_staff_manage=True) + mid, operator = _resolve_manage_context(request, need_staff_manage=True) member_id = request.data.get('member_id') role_id = request.data.get('role_id') m = MerchantStaffMember.query.get( id=member_id, merchant_id=mid, status=MEMBER_STATUS_ACTIVE, ) + _assert_not_self_target(operator, m) role = MerchantStaffRole.query.get(id=role_id, merchant_id=mid, status=1) old = m.role_id m.role = role @@ -271,10 +279,11 @@ class StaffMemberDisableView(APIView): def post(self, request): try: - mid, _ = _resolve_manage_context(request, need_staff_manage=True) + mid, operator = _resolve_manage_context(request, need_staff_manage=True) member_id = request.data.get('member_id') disable = request.data.get('disable', True) m = MerchantStaffMember.query.get(id=member_id, merchant_id=mid) + _assert_not_self_target(operator, m) m.status = MEMBER_STATUS_DISABLED if disable else MEMBER_STATUS_ACTIVE m.save(update_fields=['status']) action = 'MEMBER_DISABLE' if disable else 'MEMBER_ENABLE' @@ -290,8 +299,12 @@ class StaffRoleListView(APIView): def post(self, request): try: from merchant_ops.constants import PERMISSION_DEFINITIONS, SYSTEM_ROLE_TEMPLATES - ensure_owner_merchant(request.user.UserUID, request.user) - roles = MerchantStaffRole.query.filter(merchant_id=request.user.UserUID, status=1) + if is_merchant_owner(request.user): + mid = request.user.UserUID + ensure_owner_merchant(mid, request.user) + else: + mid, _ = _resolve_manage_context(request, need_staff_manage=True) + roles = MerchantStaffRole.query.filter(merchant_id=mid, status=1) tpl_desc = {t['role_code']: t['role_name'] for t in SYSTEM_ROLE_TEMPLATES} data = [] for r in roles: @@ -401,12 +414,13 @@ class StaffWalletAllocateView(APIView): def post(self, request): try: - mid, _ = _resolve_wallet_operator(request, 'wallet_allocate') + mid, operator = _resolve_wallet_operator(request, 'wallet_allocate') member_id = request.data.get('member_id') amount = request.data.get('amount') m = MerchantStaffMember.query.get( id=member_id, merchant_id=mid, status=MEMBER_STATUS_ACTIVE, ) + _assert_not_self_target(operator, m) get_or_create_wallet(m) wallet = allocate_quota(m, amount, request.user.UserUID, remark='划额度') audit_owner(mid, request.user.UserUID, 'WALLET_ALLOCATE', request, @@ -428,7 +442,7 @@ class StaffWalletRevokeView(APIView): def post(self, request): try: - mid, _ = _resolve_wallet_operator(request, 'wallet_revoke') + mid, operator = _resolve_wallet_operator(request, 'wallet_revoke') member_id = request.data.get('member_id') amount = request.data.get('amount') remark = (request.data.get('remark') or '').strip() or '收回未使用额度' @@ -437,6 +451,7 @@ class StaffWalletRevokeView(APIView): merchant_id=mid, status__in=[MEMBER_STATUS_ACTIVE, MEMBER_STATUS_DISABLED], ) + _assert_not_self_target(operator, m) wallet = revoke_quota(m, amount, request.user.UserUID, remark=remark) audit_owner(mid, request.user.UserUID, 'WALLET_REVOKE', request, resource_type='wallet', resource_id=member_id, amount=amount)