Add Space metadata model and provisional Forgejo content ADR
Introduce tenant-scoped Space/SpaceMembership with list and detail views. Document markdown-in-Forgejo as content SoR (ADR-0002). Run migrations on container start so app.coulomb.social picks up the new tables.
This commit is contained in:
parent
bb6bc6093a
commit
be32432d39
22 changed files with 697 additions and 12 deletions
39
coulomb_social/apps/spaces/services.py
Normal file
39
coulomb_social/apps/spaces/services.py
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
"""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()
|
||||
Loading…
Add table
Add a link
Reference in a new issue