import { Body, Controller, Delete, Get, HttpCode, Param, Patch, Post, Query, Req, } from '@nestjs/common'; import { commentListQuerySchema, createCommentInputSchema, updateCommentInputSchema, type CommentListQuery, type CommentView, type CreateCommentInput, type PageCommentsView, type UpdateCommentInput, } from '@dorfteich/shared'; import { AuthedRequest } from '../auth/auth.guard'; import { ZodValidationPipe } from '../common/zod-validation.pipe'; import { AuthenticatedOnly, RequiresPagePermission } from '../permissions/permission.decorators'; import { CommentsService } from './comments.service'; /** * Threaded page comments (issue #91). The page-scoped routes prove page * read through the shared guard; the comment-scoped ones resolve their * page (and the 404-vs-403 semantics) inside the service. */ @Controller() export class CommentsController { constructor(private readonly comments: CommentsService) {} @Get('pages/:pageId/comments') @RequiresPagePermission('read', { idParam: 'pageId' }) async list( @Param('pageId') pageId: string, @Query(new ZodValidationPipe(commentListQuerySchema)) query: CommentListQuery, ): Promise { return this.comments.list(pageId, query.filter); } @Post('pages/:pageId/comments') @RequiresPagePermission('read', { idParam: 'pageId' }) // write policy: service async create( @Param('pageId') pageId: string, @Body(new ZodValidationPipe(createCommentInputSchema)) input: CreateCommentInput, @Req() request: AuthedRequest, ): Promise { return this.comments.create(request.user!, pageId, input); } @Patch('comments/:id') @AuthenticatedOnly() async update( @Param('id') id: string, @Body(new ZodValidationPipe(updateCommentInputSchema)) input: UpdateCommentInput, @Req() request: AuthedRequest, ): Promise { return this.comments.update(request.user!, id, input.body); } @Delete('comments/:id') @HttpCode(204) @AuthenticatedOnly() async remove(@Param('id') id: string, @Req() request: AuthedRequest): Promise { await this.comments.delete(request.user!, id); } @Post('comments/:id/resolve') @AuthenticatedOnly() async resolve(@Param('id') id: string, @Req() request: AuthedRequest): Promise { return this.comments.setResolved(request.user!, id, true); } @Delete('comments/:id/resolve') @AuthenticatedOnly() async unresolve(@Param('id') id: string, @Req() request: AuthedRequest): Promise { return this.comments.setResolved(request.user!, id, false); } }