40 lines
1.2 KiB
Python
40 lines
1.2 KiB
Python
|
|
"""Space queries scoped by tenant membership."""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from django.db.models import Q, QuerySet
|
||
|
|
|
||
|
|
from coulomb_social.apps.members.models import Member
|
||
|
|
|
||
|
|
from .models import Space, SpaceMembership
|
||
|
|
|
||
|
|
|
||
|
|
def spaces_for_member(member: Member | None) -> QuerySet[Space]:
|
||
|
|
"""Spaces visible to this member (same tenant, active).
|
||
|
|
|
||
|
|
Explicit SpaceMembership grants access; if none exist for the tenant yet,
|
||
|
|
all active tenant spaces are listed (operator-seeded MVP). Once any
|
||
|
|
memberships exist for the tenant, only membership + created_by apply.
|
||
|
|
"""
|
||
|
|
if member is None:
|
||
|
|
return Space.objects.none()
|
||
|
|
|
||
|
|
qs = Space.objects.filter(tenant_id=member.tenant_id, is_active=True)
|
||
|
|
tenant_has_memberships = SpaceMembership.objects.filter(
|
||
|
|
space__tenant_id=member.tenant_id
|
||
|
|
).exists()
|
||
|
|
if not tenant_has_memberships:
|
||
|
|
return qs.order_by("title", "slug")
|
||
|
|
|
||
|
|
return (
|
||
|
|
qs.filter(Q(memberships__member=member) | Q(created_by=member))
|
||
|
|
.distinct()
|
||
|
|
.order_by("title", "slug")
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def get_space_for_member(member: Member | None, slug: str) -> Space | None:
|
||
|
|
if member is None:
|
||
|
|
return None
|
||
|
|
return spaces_for_member(member).filter(slug=slug).first()
|