From 1f7c040f6584c9ffdb97c69fd59eae84d65af5f3 Mon Sep 17 00:00:00 2001 From: Mayuresh <163298868+Dev-Mayuresh@users.noreply.github.com> Date: Thu, 6 Aug 2026 16:20:00 +0530 Subject: [PATCH 1/2] fix(ci): update api.md and uploadPhoto tests to fix CI test failures --- backend/tests/uploadPhoto.test.js | 8 ++++---- docs/api.md | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/backend/tests/uploadPhoto.test.js b/backend/tests/uploadPhoto.test.js index 0fa23380..e7a864ab 100644 --- a/backend/tests/uploadPhoto.test.js +++ b/backend/tests/uploadPhoto.test.js @@ -167,7 +167,7 @@ describe("POST /api/users/upload-photo", () => { expect(res.status).toBe(200); expect(res.body.success).toBe(true); // Filename must contain the authenticated user's ID - expect(res.body.fileUrl).toMatch(new RegExp(`profile-${TEST_USER_ID}-`)); + expect(res.body.fileUrl).toContain(TEST_USER_ID); }); it("returns 200 when a valid JWT is supplied via HttpOnly cookie", async () => { @@ -221,9 +221,9 @@ describe("POST /api/users/upload-photo", () => { expect(res.body.error).toMatch(/no file/i); }); - it("returns 413 when the uploaded file exceeds the 5MB size limit", async () => { + it("returns 413 when the uploaded file exceeds the 2MB size limit", async () => { const token = makeToken(); - const oversized = Buffer.alloc(6 * 1024 * 1024, 0xff); // 6 MB of 0xFF bytes + const oversized = Buffer.alloc(3 * 1024 * 1024, 0xff); // 3 MB of 0xFF bytes const res = await request(app) .post("/api/users/upload-photo") .set("Authorization", `Bearer ${token}`) @@ -233,7 +233,7 @@ describe("POST /api/users/upload-photo", () => { }); expect(res.status).toBe(413); - expect(res.body.error).toMatch(/5mb/i); + expect(res.body.error).toMatch(/2mb/i); }); }); diff --git a/docs/api.md b/docs/api.md index d8cda768..8a65a868 100644 --- a/docs/api.md +++ b/docs/api.md @@ -130,3 +130,11 @@ Sends a browser push notification to all subscribed devices for a given `user_id ``` **Security**: Standard users may only send push notifications to themselves (IDOR prevention). Webhook callers authenticated via `WEBHOOK_SECRET` may send to any user. + +### `POST /api/upload` + +Uploads generic project resources with magic byte validation (accepted types: avatars, resources). + +### `POST /api/users/upload-photo` + +Uploads user profile photos (avatars) with magic byte validation. From 1afc2f890d45ceb7b32d70e3aa4747f7c13eef4a Mon Sep 17 00:00:00 2001 From: Mayuresh <163298868+Dev-Mayuresh@users.noreply.github.com> Date: Fri, 7 Aug 2026 13:36:33 +0530 Subject: [PATCH 2/2] docs(api): expand upload endpoints documentation and refine uploadPhoto path assertion --- backend/tests/uploadPhoto.test.js | 4 +++- docs/api.md | 34 ++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/backend/tests/uploadPhoto.test.js b/backend/tests/uploadPhoto.test.js index e7a864ab..73d86508 100644 --- a/backend/tests/uploadPhoto.test.js +++ b/backend/tests/uploadPhoto.test.js @@ -166,8 +166,10 @@ describe("POST /api/users/upload-photo", () => { expect(res.status).toBe(200); expect(res.body.success).toBe(true); - // Filename must contain the authenticated user's ID + // Filename/path must contain the authenticated user's ID expect(res.body.fileUrl).toContain(TEST_USER_ID); + const pathSegments = new URL(res.body.fileUrl).pathname.split("/").filter(Boolean); + expect(pathSegments).toContain(TEST_USER_ID); }); it("returns 200 when a valid JWT is supplied via HttpOnly cookie", async () => { diff --git a/docs/api.md b/docs/api.md index 8a65a868..2d1f0c03 100644 --- a/docs/api.md +++ b/docs/api.md @@ -131,10 +131,42 @@ Sends a browser push notification to all subscribed devices for a given `user_id **Security**: Standard users may only send push notifications to themselves (IDOR prevention). Webhook callers authenticated via `WEBHOOK_SECRET` may send to any user. +## Upload Routes (`/api/upload` & `/api/users/upload-photo`) + ### `POST /api/upload` -Uploads generic project resources with magic byte validation (accepted types: avatars, resources). +Uploads generic project resources with magic byte validation. + +**Auth**: Requires a valid Supabase JWT token in `Authorization: Bearer ` or `access_token` cookie. +**Content-Type**: `multipart/form-data` +**Form Fields**: +- `file` (File, required): The file to upload. +- `folder` (string, required): Permitted values are `avatars` or `resources`. + +**Response** (`200 OK`): +```json +{ + "success": true, + "data": { + "url": "https:///storage/v1/object/public/resources/user-id/filename.pdf" + } +} +``` ### `POST /api/users/upload-photo` Uploads user profile photos (avatars) with magic byte validation. + +**Auth**: Requires a valid Supabase JWT token in `Authorization: Bearer ` or `access_token` cookie. +**Content-Type**: `multipart/form-data` +**Form Fields**: +- `profilePhoto` (File, required): The profile image file (max size: 2 MiB). + +**Response** (`200 OK`): +```json +{ + "success": true, + "fileUrl": "https:///storage/v1/object/public/avatars/user-id/filename.png" +} +``` +