From fe4ccc12a1da75c400bd74647aeb79337ae4a965 Mon Sep 17 00:00:00 2001 From: Tom Sherman Date: Tue, 5 Nov 2024 10:12:44 +0000 Subject: [PATCH 1/3] Validate post length and url --- packages/frontpage/lib/data/atproto/post.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/frontpage/lib/data/atproto/post.ts b/packages/frontpage/lib/data/atproto/post.ts index 81d01fee..8d8f9309 100644 --- a/packages/frontpage/lib/data/atproto/post.ts +++ b/packages/frontpage/lib/data/atproto/post.ts @@ -7,12 +7,13 @@ import { import { z } from "zod"; import { DataLayerError } from "../error"; import { DID, getPdsUrl } from "./did"; +import { MAX_POST_TITLE_LENGTH, MAX_POST_URL_LENGTH } from "../db/constants"; export const PostCollection = "fyi.unravel.frontpage.post"; export const PostRecord = z.object({ - title: z.string(), - url: z.string(), + title: z.string().max(MAX_POST_TITLE_LENGTH), + url: z.string().url().max(MAX_POST_URL_LENGTH), createdAt: z.string(), }); @@ -25,7 +26,12 @@ type PostInput = { export async function createPost({ title, url }: PostInput) { const record = { title, url, createdAt: new Date().toISOString() }; - PostRecord.parse(record); + const parseResult = PostRecord.safeParse(record); + if (!parseResult.success) { + throw new DataLayerError("Invalid post record", { + cause: parseResult.error, + }); + } const result = await atprotoCreateRecord({ record, From 79075256feb41a1faa1c7306dcc516d235022f06 Mon Sep 17 00:00:00 2001 From: Tom Sherman Date: Tue, 5 Nov 2024 10:16:28 +0000 Subject: [PATCH 2/3] More comment validation also --- packages/frontpage/lib/data/atproto/comment.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/frontpage/lib/data/atproto/comment.ts b/packages/frontpage/lib/data/atproto/comment.ts index a1dff7b9..d9f23d92 100644 --- a/packages/frontpage/lib/data/atproto/comment.ts +++ b/packages/frontpage/lib/data/atproto/comment.ts @@ -9,11 +9,12 @@ import { DataLayerError } from "../error"; import { z } from "zod"; import { PostCollection } from "./post"; import { DID, getPdsUrl } from "./did"; +import { MAX_COMMENT_LENGTH } from "../db/constants"; export const CommentCollection = "fyi.unravel.frontpage.comment"; export const CommentRecord = z.object({ - content: z.string(), + content: z.string().max(MAX_COMMENT_LENGTH), parent: z .object({ cid: z.string(), @@ -53,7 +54,12 @@ export async function createComment({ parent, post, content }: CommentInput) { createdAt: new Date().toISOString(), }; - CommentRecord.parse(record); + const parseResult = CommentRecord.safeParse(record); + if (!parseResult.success) { + throw new DataLayerError("Invalid comment record", { + cause: parseResult.error, + }); + } const result = await atprotoCreateRecord({ record, From 6ba02e400e50f6a4c623195364b662c92459d342 Mon Sep 17 00:00:00 2001 From: Tom Sherman Date: Tue, 5 Nov 2024 10:18:37 +0000 Subject: [PATCH 3/3] Smol refactor --- packages/frontpage/app/api/receive_hook/route.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/frontpage/app/api/receive_hook/route.ts b/packages/frontpage/app/api/receive_hook/route.ts index 7ff14099..9d4c9704 100644 --- a/packages/frontpage/app/api/receive_hook/route.ts +++ b/packages/frontpage/app/api/receive_hook/route.ts @@ -4,7 +4,7 @@ import { atprotoGetRecord } from "@/lib/data/atproto/record"; import { Commit } from "@/lib/data/atproto/event"; import * as atprotoPost from "@/lib/data/atproto/post"; import * as dbPost from "@/lib/data/db/post"; -import { CommentCollection, getComment } from "@/lib/data/atproto/comment"; +import * as atprotoComment from "@/lib/data/atproto/comment"; import { VoteRecord } from "@/lib/data/atproto/vote"; import { getPdsUrl } from "@/lib/data/atproto/did"; import { @@ -64,9 +64,9 @@ export async function POST(request: Request) { } } // repo is actually the did of the user - if (collection === CommentCollection) { + if (collection === atprotoComment.CommentCollection) { if (op.action === "create") { - const comment = await getComment({ rkey, repo }); + const comment = await atprotoComment.getComment({ rkey, repo }); await unauthed_createComment({ cid: comment.cid, @@ -104,7 +104,8 @@ export async function POST(request: Request) { cid: hydratedRecord.cid, }); } else if ( - hydratedVoteRecordValue.subject.uri.collection === CommentCollection + hydratedVoteRecordValue.subject.uri.collection === + atprotoComment.CommentCollection ) { await unauthed_createCommentVote({ cid: hydratedRecord.cid,