dorfteich/apps/api/src/public/read-content.controller.ts
Claude Fable 5 e164370691 #154: Aufgabenübersicht als Kern-Block (Seite + Unterseiten)
Neuer Block-Atom task_overview (Markdown-Fence dorfteich-tasks,
HTML-Placeholder). Shared extractTaskRows liest Task-Zeilen mit Text,
Mentions (#150) und Start-/Zieldaten (#152); TasksService sammelt zur
Lesezeit den Teilbaum (rekursiv via collectSubtreeIds, canAccessPage-
Filter je Quellseite) aus Basis-State + page_updates-Log — KEINE
abgeleitete Tabelle nötig (Teilbäume sind klein, kein Drift). Neuer
auth-Endpoint GET /read/:pond/:slug/tasks; die öffentliche Ansicht
expandiert den Placeholder serverseitig zur statischen Tabelle
(Instanz-Sprache). NodeView mit Live-Tabelle und Rückschreib-Checkboxen
(optimistisch, Override bis der debounced Collab-Persist nachzieht);
Einfügen über die Block-Auswahl (eingebauter Eintrag). Unit- + DB-Tests,
neuer CI-Pack tasks.spec (voller Loop inkl. Rückschreiben end-to-end),
User-Guide-Doku en+de.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0155v2aT8AG1kZDQEZiCLBWC
2026-07-20 01:20:30 +02:00

49 lines
2.0 KiB
TypeScript

import { Controller, Get, Param, Req } from '@nestjs/common';
import type { TaskOverviewPage } from '@dorfteich/shared';
import { AuthedRequest } from '../auth/auth.guard';
import { TasksService } from '../pages/tasks.service';
import { AuthenticatedOnly } from '../permissions/permission.decorators';
import { PublicPageContent, PublicService } from './public.service';
/**
* Authenticated read-rendering (issue #135). Returns a page's rendered read
* HTML — plugin fallbacks, expanded page embeds, resolved media — for a
* signed-in viewer with read access. The transclusion node view fetches this to
* show an embedded page's content inline in the authenticated read view, which
* must also work for pages that are not public and so are out of reach of the
* `/public` endpoints. NOT `@Public`: the auth guard requires a session and the
* service enforces read permission (a non-readable page 404s, no leak).
*/
@Controller('read')
export class ReadContentController {
constructor(
private readonly publicPages: PublicService,
private readonly tasks: TasksService,
) {}
// The task collection (issue #154) — registered before the generic
// two-segment route so `tasks` is not read as a page slug.
@Get(':pondSlug/:pageSlug/tasks')
@AuthenticatedOnly()
async tasksOf(
@Param('pondSlug') pondSlug: string,
@Param('pageSlug') pageSlug: string,
@Req() request: AuthedRequest,
): Promise<TaskOverviewPage[]> {
return this.tasks.collect(request.user ?? null, pondSlug, pageSlug);
}
// Session required (explicit access rule, issue #52); per-page read
// permission is enforced in the service (resolve → canAccessPage → 404).
@Get(':pondSlug/:pageSlug')
@AuthenticatedOnly()
async content(
@Param('pondSlug') pondSlug: string,
@Param('pageSlug') pageSlug: string,
@Req() request: AuthedRequest,
): Promise<PublicPageContent> {
return this.publicPages.content(request.user ?? null, pondSlug, pageSlug);
}
}