fix: 单俱乐部视图下角色/用户/会员严格隔离,禁止泄露其他俱乐部

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-07-26 01:48:51 +08:00
parent 30c2dff040
commit c870e7e6e9
3 changed files with 110 additions and 35 deletions

View File

@@ -128,13 +128,17 @@ def build_member_list_payload(request):
for m in members:
member_list.append(_format_member(m))
else:
# 有本俱乐部专属价:只展示本店上架项;尚无专属价:回落集团默认会员定义。
# 绝不混入其他俱乐部的 ClubHuiyuanPrice。
has_club_prices = bool(price_map)
for m in members:
row = price_map.get(m.huiyuan_id)
if row is None and club_id != CLUB_ID_DEFAULT:
continue
if row is not None and not row.is_enabled:
continue
item = _format_member(m, row, club_id=club_id)
if has_club_prices:
if row is None or not row.is_enabled:
continue
item = _format_member(m, row, club_id=club_id)
else:
item = _format_member(m, club_id=club_id)
item['goumai_cishu'] = _sales_map.get(m.huiyuan_id, 0)
member_list.append(item)
@@ -143,7 +147,7 @@ def build_member_list_payload(request):
'club_id': club_id,
'scope': scope,
'price_note': (
f'当前俱乐部 {club_id} 专属售价club_huiyuan_price'
f'当前俱乐部 {club_id} 专属售价;未配置专属价时展示集团默认会员'
if scope != DATA_SCOPE_ALL else
'集团汇总:展示全局默认价;切换具体俱乐部可配置售价与体验会员。'
),

View File

@@ -13,26 +13,44 @@ def _global_role_q():
def resolve_role_club_id(request, explicit=None):
"""创建/筛选角色时使用的俱乐部;集团视图可显式指定 target_club_id。"""
"""
创建/筛选角色时使用的俱乐部。
单俱乐部视图:强制当前顶栏俱乐部,忽略跨店 target_club_id。
集团汇总视图可显式指定未指定则为全局club_id 空)。
"""
scope = resolve_club_scope(request)
if scope != DATA_SCOPE_ALL:
return resolve_club_id_from_request(request)
if explicit:
return (explicit or '').strip()
scope = resolve_club_scope(request)
if scope == DATA_SCOPE_ALL:
return ''
return resolve_club_id_from_request(request)
return ''
def filter_roles_for_request(request):
"""
子公司视图:仅本俱乐部角色。
集团汇总视图:全部角色(含各俱乐部 + 全局 club_id 为空)
子公司视图:优先本俱乐部角色;本俱乐部尚无角色时仅回落集团全局角色。
绝不混入其他俱乐部角色
集团汇总视图:全部角色(含各俱乐部 + 全局)。
"""
qs = Role.objects.filter(RoleStatus=1)
scope = resolve_club_scope(request)
if scope == DATA_SCOPE_ALL:
return qs
club_id = resolve_club_id_from_request(request)
return qs.filter(Q(ClubID=club_id) | _global_role_q())
club_qs = qs.filter(ClubID=club_id)
if club_qs.exists():
return club_qs
return qs.filter(_global_role_q())
def role_visible_in_scope(role_club_id, request):
"""列表展示用:单俱乐部视图只允许本俱乐部或全局(无本俱乐部角色时由调用方决定)。"""
scope = resolve_club_scope(request)
if scope == DATA_SCOPE_ALL:
return True
curr = (resolve_club_id_from_request(request) or '').strip()
cid = (role_club_id or '').strip()
return cid == '' or cid == curr
def filter_kefu_users_by_admin_scope(qs, request):