"""Public, read-only viewing surface. Optional auth (anonymous allowed). Every response is built by ``public_view_service``, which routes through the privacy engine and redacts possibly-living people. No create/update/delete here. """ import uuid from fastapi import APIRouter from app.api.deps import CurrentUserOrNone, SessionDep from app.schemas.event import EventRead from app.schemas.name import NameRead from app.schemas.person import PersonRead from app.schemas.relationship import RelationshipRead from app.schemas.tree import PublicTreeRead from app.services import public_view_service router = APIRouter(prefix="/public", tags=["public"]) def _vid(viewer: CurrentUserOrNone) -> uuid.UUID | None: return viewer.id if viewer else None @router.get("/trees", response_model=list[PublicTreeRead]) async def public_directory( session: SessionDep, viewer: CurrentUserOrNone, q: str | None = None, limit: int = 50, offset: int = 0, ) -> list[PublicTreeRead]: trees = await public_view_service.list_public_trees( session, viewer_id=_vid(viewer), q=q, limit=limit, offset=offset ) return [PublicTreeRead.model_validate(t) for t in trees] @router.get("/trees/{tree_id}", response_model=PublicTreeRead) async def public_tree( tree_id: uuid.UUID, session: SessionDep, viewer: CurrentUserOrNone ) -> PublicTreeRead: tree = await public_view_service.get_public_tree( session, viewer_id=_vid(viewer), tree_id=tree_id ) return PublicTreeRead.model_validate(tree) @router.get("/trees/{tree_id}/persons", response_model=list[PersonRead]) async def public_persons( tree_id: uuid.UUID, session: SessionDep, viewer: CurrentUserOrNone ) -> list[PersonRead]: tree = await public_view_service.get_public_tree( session, viewer_id=_vid(viewer), tree_id=tree_id ) persons = await public_view_service.list_public_persons( session, viewer_id=_vid(viewer), tree=tree ) return [PersonRead.model_validate(p) for p in persons] @router.get("/trees/{tree_id}/relationships", response_model=list[RelationshipRead]) async def public_relationships( tree_id: uuid.UUID, session: SessionDep, viewer: CurrentUserOrNone ) -> list[RelationshipRead]: tree = await public_view_service.get_public_tree( session, viewer_id=_vid(viewer), tree_id=tree_id ) rels = await public_view_service.list_public_relationships( session, viewer_id=_vid(viewer), tree=tree ) return [RelationshipRead.model_validate(r) for r in rels] @router.get("/trees/{tree_id}/events", response_model=list[EventRead]) async def public_events( tree_id: uuid.UUID, session: SessionDep, viewer: CurrentUserOrNone ) -> list[EventRead]: tree = await public_view_service.get_public_tree( session, viewer_id=_vid(viewer), tree_id=tree_id ) events = await public_view_service.list_public_events( session, viewer_id=_vid(viewer), tree=tree ) return [EventRead.model_validate(e) for e in events] @router.get("/trees/{tree_id}/persons/{person_id}", response_model=PersonRead) async def public_person( tree_id: uuid.UUID, person_id: uuid.UUID, session: SessionDep, viewer: CurrentUserOrNone, ) -> PersonRead: tree = await public_view_service.get_public_tree( session, viewer_id=_vid(viewer), tree_id=tree_id ) person = await public_view_service.get_public_person( session, viewer_id=_vid(viewer), tree=tree, person_id=person_id ) return PersonRead.model_validate(person) @router.get("/trees/{tree_id}/persons/{person_id}/names", response_model=list[NameRead]) async def public_person_names( tree_id: uuid.UUID, person_id: uuid.UUID, session: SessionDep, viewer: CurrentUserOrNone, ) -> list[NameRead]: tree = await public_view_service.get_public_tree( session, viewer_id=_vid(viewer), tree_id=tree_id ) names = await public_view_service.list_public_person_names( session, viewer_id=_vid(viewer), tree=tree, person_id=person_id ) return [NameRead.model_validate(n) for n in names] @router.get("/trees/{tree_id}/persons/{person_id}/events", response_model=list[EventRead]) async def public_person_events( tree_id: uuid.UUID, person_id: uuid.UUID, session: SessionDep, viewer: CurrentUserOrNone, ) -> list[EventRead]: tree = await public_view_service.get_public_tree( session, viewer_id=_vid(viewer), tree_id=tree_id ) events = await public_view_service.list_public_person_events( session, viewer_id=_vid(viewer), tree=tree, person_id=person_id ) return [EventRead.model_validate(e) for e in events]