From 26dcbc1dc9e24ac380e253898be984696b2a1429 Mon Sep 17 00:00:00 2001 From: XingQue Date: Sat, 4 Jul 2026 20:48:12 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=95=86=E5=AE=B6=E8=80=81=E6=9D=BF?= =?UTF-8?q?=E5=8F=AF=E7=BB=91=E5=AE=9A=E4=B8=BA=E5=85=B6=E4=BB=96=E5=BA=97?= =?UTF-8?q?=E5=AD=90=E5=AE=A2=E6=9C=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 允许已是商家老板的用户担任其他商家子客服,禁止绑自己的店。 Co-authored-by: Cursor --- merchant_ops/services/authz.py | 30 ++++++++++++++++-------------- merchant_ops/views_staff.py | 2 +- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/merchant_ops/services/authz.py b/merchant_ops/services/authz.py index 63f3676..d4db512 100644 --- a/merchant_ops/services/authz.py +++ b/merchant_ops/services/authz.py @@ -33,9 +33,7 @@ def get_active_staff_member(user): def require_active_staff_member(user): - """子客服接口鉴权:区分老板误入、未绑定、禁用、移除等场景。""" - if is_merchant_owner(user): - raise StaffAuthError(403, '您是商家老板,请使用商家端原接口') + """子客服接口鉴权:区分未绑定、禁用、移除等场景(已是商家老板也可担任其他店子客服)。""" member = MerchantStaffMember.query.filter( staff_user_id=user.UserUID, ).select_related('role').order_by('-id').first() @@ -132,9 +130,21 @@ def resolve_owner_or_staff(request, perm_code=None): return 'staff', member.merchant_id, member, user.UserUID -def assert_not_merchant_when_bind(user): - if is_merchant_owner(user): - raise StaffAuthError(403, '您已是商家,无法成为子客服') +def assert_not_self_merchant_when_bind(user, invite_merchant_id): + """不能绑定为自己店铺的客服;可以是其他商家的子客服。""" + if invite_merchant_id is not None and str(user.UserUID) == str(invite_merchant_id): + raise StaffAuthError(403, '不能绑定为自己商家的客服') + + +def assert_can_bind_staff(user, invite_merchant_id=None): + assert_not_self_merchant_when_bind(user, invite_merchant_id) + existing = MerchantStaffMember.query.filter( + staff_user_id=user.UserUID, status=MEMBER_STATUS_ACTIVE + ).first() + if existing: + if invite_merchant_id and str(existing.merchant_id) == str(invite_merchant_id): + raise StaffAuthError(400, '您已是该商家客服') + raise StaffAuthError(403, '您已绑定其他商家客服,请先联系原商家解除后再绑定') def assert_no_active_staff_when_merchant_register(user): @@ -144,14 +154,6 @@ def assert_no_active_staff_when_merchant_register(user): raise StaffAuthError(403, '您当前是商家客服,请先联系商家解除后再认证商家') -def assert_can_bind_staff(user): - assert_not_merchant_when_bind(user) - if MerchantStaffMember.query.filter( - staff_user_id=user.UserUID, status=MEMBER_STATUS_ACTIVE - ).exists(): - raise StaffAuthError(403, '您已绑定商家客服,无法重复绑定') - - def get_owner_permissions(): return list(OWNER_ALL_PERMISSIONS) diff --git a/merchant_ops/views_staff.py b/merchant_ops/views_staff.py index 0349376..8992918 100644 --- a/merchant_ops/views_staff.py +++ b/merchant_ops/views_staff.py @@ -35,7 +35,6 @@ class StaffBindView(APIView): def post(self, request): try: - assert_can_bind_staff(request.user) invite_code = str(request.data.get('inviteCode') or request.data.get('invite_code') or '').strip() if not invite_code or invite_code == 'XQKF2026': return Response({'code': 400, 'msg': '请使用商家提供的一次性邀请码', 'data': None}) @@ -44,6 +43,7 @@ class StaffBindView(APIView): inv = MerchantStaffInvite.objects.select_for_update().get( invite_code=invite_code, status=INVITE_STATUS_UNUSED, ) + assert_can_bind_staff(request.user, invite_merchant_id=inv.merchant_id) if inv.expire_at and inv.expire_at < timezone.now(): inv.status = 3 inv.save(update_fields=['status'])