From 6063b3ff44d2db72ea49b938a7d06cd9b59520cf Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Mon, 15 Apr 2024 15:02:25 -1000 Subject: [PATCH] fix(api): :bug: Fix string query values being incorrectly casted as booleans --- packages/request-parser/index.ts | 16 ++++++++++++++-- server/api/api/v1/timelines/public.test.ts | 6 +++--- server/api/api/v1/timelines/public.ts | 13 +++++++------ 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/packages/request-parser/index.ts b/packages/request-parser/index.ts index e9b4fd83..b0740abb 100644 --- a/packages/request-parser/index.ts +++ b/packages/request-parser/index.ts @@ -173,11 +173,23 @@ export class RequestParser { } (result[arrayKey] as string[]).push(decodeURIComponent(value)); } else { - result[key as keyof T] = decodeURIComponent( - value, + result[key as keyof T] = castBoolean( + decodeURIComponent(value), ) as T[keyof T]; } } return result; } } + +const castBoolean = (value: string) => { + if (["true"].includes(value)) { + return true; + } + + if (["false"].includes(value)) { + return false; + } + + return value; +}; diff --git a/server/api/api/v1/timelines/public.test.ts b/server/api/api/v1/timelines/public.test.ts index 7c2fc398..99d98cc9 100644 --- a/server/api/api/v1/timelines/public.test.ts +++ b/server/api/api/v1/timelines/public.test.ts @@ -93,11 +93,11 @@ describe(meta.route, () => { } }); - test("should only fetch remote statuses (0)", async () => { + test("should only fetch remote statuses", async () => { const response = await sendTestRequest( new Request( new URL( - `${meta.route}?limit=20&remote=true`, + `${meta.route}?remote=true&allow_local_only=false&only_media=false`, config.http.base_url, ), { @@ -113,7 +113,7 @@ describe(meta.route, () => { const objects = (await response.json()) as APIStatus[]; - expect(objects.length).toBe(0); + expect(objects).toBeArrayOfSize(1); }); describe("should paginate properly", async () => { diff --git a/server/api/api/v1/timelines/public.ts b/server/api/api/v1/timelines/public.ts index 44ebaa0c..fbc8c9af 100644 --- a/server/api/api/v1/timelines/public.ts +++ b/server/api/api/v1/timelines/public.ts @@ -26,9 +26,9 @@ export const schema = z.object({ since_id: z.string().regex(idValidator).optional(), min_id: z.string().regex(idValidator).optional(), limit: z.coerce.number().int().min(1).max(80).optional().default(20), - local: z.coerce.boolean().optional(), - remote: z.coerce.boolean().optional(), - only_media: z.coerce.boolean().optional(), + local: z.boolean().optional(), + remote: z.boolean().optional(), + only_media: z.boolean().optional(), }); export default apiRoute( @@ -53,9 +53,10 @@ export default apiRoute( // use authorId to grab user, then use user.instanceId to filter local/remote statuses remote ? sql`EXISTS (SELECT 1 FROM "User" WHERE "User"."id" = ${status.authorId} AND "User"."instanceId" IS NOT NULL)` - : local - ? sql`EXISTS (SELECT 1 FROM "User" WHERE "User"."id" = ${status.authorId} AND "User"."instanceId" IS NULL)` - : undefined, + : undefined, + local + ? sql`EXISTS (SELECT 1 FROM "User" WHERE "User"."id" = ${status.authorId} AND "User"."instanceId" IS NULL)` + : undefined, only_media ? sql`EXISTS (SELECT 1 FROM "Attachment" WHERE "Attachment"."statusId" = ${status.id})` : undefined,