From 5d2a75c8e98effa326ed5c6b1e9dd4da21619f1d Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Fri, 29 Dec 2023 10:13:22 -0500 Subject: [PATCH] feat: Add missing comments.info endpoint, fix misnamed types --- .../__snapshots__/comments.test.ts.snap | 9 +++++ server/routes/api/comments/comments.test.ts | 38 +++++++++++++++++++ server/routes/api/comments/comments.ts | 25 +++++++++++- server/routes/api/comments/schema.ts | 31 ++++++++------- 4 files changed, 88 insertions(+), 15 deletions(-) diff --git a/server/routes/api/comments/__snapshots__/comments.test.ts.snap b/server/routes/api/comments/__snapshots__/comments.test.ts.snap index ca889ce85..dfb06a20a 100644 --- a/server/routes/api/comments/__snapshots__/comments.test.ts.snap +++ b/server/routes/api/comments/__snapshots__/comments.test.ts.snap @@ -9,6 +9,15 @@ exports[`#comments.create should require authentication 1`] = ` } `; +exports[`#comments.info should require authentication 1`] = ` +{ + "error": "authentication_required", + "message": "Authentication required", + "ok": false, + "status": 401, +} +`; + exports[`#comments.list should require authentication 1`] = ` { "error": "authentication_required", diff --git a/server/routes/api/comments/comments.test.ts b/server/routes/api/comments/comments.test.ts index 472e07081..7406e0b13 100644 --- a/server/routes/api/comments/comments.test.ts +++ b/server/routes/api/comments/comments.test.ts @@ -204,3 +204,41 @@ describe("#comments.create", () => { expect(res.status).toEqual(400); }); }); + +describe("#comments.info", () => { + it("should require authentication", async () => { + const res = await server.post("/api/comments.info"); + const body = await res.json(); + expect(res.status).toEqual(401); + expect(body).toMatchSnapshot(); + }); + + it("should return comment info", async () => { + const team = await buildTeam(); + const user = await buildUser({ teamId: team.id }); + const document = await buildDocument({ + userId: user.id, + teamId: user.teamId, + }); + const comment = await buildComment({ + userId: user.id, + teamId: team.id, + documentId: document.id, + }); + const res = await server.post("/api/comments.info", { + body: { + token: user.getJwtToken(), + id: comment.id, + }, + }); + const body = await res.json(); + + expect(res.status).toEqual(200); + expect(body.data.id).toEqual(comment.id); + expect(body.data.data).toEqual(comment.data); + expect(body.policies.length).toEqual(1); + expect(body.policies[0].abilities.read).toEqual(true); + expect(body.policies[0].abilities.update).toEqual(true); + expect(body.policies[0].abilities.delete).toEqual(true); + }); +}); diff --git a/server/routes/api/comments/comments.ts b/server/routes/api/comments/comments.ts index 8bc109c8b..901ef9dba 100644 --- a/server/routes/api/comments/comments.ts +++ b/server/routes/api/comments/comments.ts @@ -55,13 +55,34 @@ router.post( } ); +router.post( + "comments.info", + auth(), + checkCommentingEnabled(), + validate(T.CommentsInfoSchema), + async (ctx: APIContext) => { + const { id } = ctx.input.body; + const { user } = ctx.state.auth; + + const comment = await Comment.findByPk(id, { + rejectOnEmpty: true, + }); + authorize(user, "read", comment); + + ctx.body = { + data: presentComment(comment), + policies: presentPolicies(user, [comment]), + }; + } +); + router.post( "comments.list", auth(), pagination(), checkCommentingEnabled(), - validate(T.CollectionsListSchema), - async (ctx: APIContext) => { + validate(T.CommentsListSchema), + async (ctx: APIContext) => { const { sort, direction, documentId, collectionId } = ctx.input.body; const { user } = ctx.state.auth; diff --git a/server/routes/api/comments/schema.ts b/server/routes/api/comments/schema.ts index 4407e4f97..f5495766c 100644 --- a/server/routes/api/comments/schema.ts +++ b/server/routes/api/comments/schema.ts @@ -1,8 +1,13 @@ import { z } from "zod"; import { BaseSchema, ProsemirrorSchema } from "@server/routes/api/schema"; -const CollectionsSortParamsSchema = z.object({ - /** Specifies the attributes by which documents will be sorted in the list */ +const BaseIdSchema = z.object({ + /** Comment Id */ + id: z.string().uuid(), +}); + +const CommentsSortParamsSchema = z.object({ + /** Specifies the attributes by which comments will be sorted in the list */ sort: z .string() .refine((val) => ["createdAt", "updatedAt"].includes(val)) @@ -34,10 +39,7 @@ export const CommentsCreateSchema = BaseSchema.extend({ export type CommentsCreateReq = z.infer; export const CommentsUpdateSchema = BaseSchema.extend({ - body: z.object({ - /** Which comment to update */ - id: z.string().uuid(), - + body: BaseIdSchema.extend({ /** Update comment with this data */ data: ProsemirrorSchema, }), @@ -46,20 +48,23 @@ export const CommentsUpdateSchema = BaseSchema.extend({ export type CommentsUpdateReq = z.infer; export const CommentsDeleteSchema = BaseSchema.extend({ - body: z.object({ - /** Which comment to delete */ - id: z.string().uuid(), - }), + body: BaseIdSchema, }); export type CommentsDeleteReq = z.infer; -export const CollectionsListSchema = BaseSchema.extend({ - body: CollectionsSortParamsSchema.extend({ +export const CommentsListSchema = BaseSchema.extend({ + body: CommentsSortParamsSchema.extend({ /** Id of a document to list comments for */ documentId: z.string().optional(), collectionId: z.string().uuid().optional(), }), }); -export type CollectionsListReq = z.infer; +export type CommentsListReq = z.infer; + +export const CommentsInfoSchema = z.object({ + body: BaseIdSchema, +}); + +export type CommentsInfoReq = z.infer;