子客服管理接口禁止对自己划收额度、换角色、封禁;成员列表返回 isSelf;具备 staff_manage 的总管可读角色列表用于给他人换角色。

This commit is contained in:
XingQue
2026-06-20 13:39:13 +08:00
parent 42af45f92c
commit a30bd69bf2

View File

@@ -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)