Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions src/controllers/member.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,29 +72,31 @@ export const createAMember =
// Update an existing member
export const updateAMember =
(supabase: SupabaseClient) => async (req: Request, res: Response) => {
const { memberId } = req.params;

const { memberId } = req.params;

if(!memberId) throw new ApiError("No memberId provided", 400);

const body = req.body;
const parsedBody = JSON.parse(req.body.memberData);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add error handling for JSON parsing.

JSON.parse() can throw a SyntaxError if req.body.memberData is not valid JSON. This could crash the application if malformed data is sent.

-    const parsedBody = JSON.parse(req.body.memberData);
+    if (!req.body.memberData) {
+      throw new ApiError("No member data provided", 400);
+    }
+    
+    let parsedBody;
+    try {
+      parsedBody = JSON.parse(req.body.memberData);
+    } catch (error) {
+      throw new ApiError("Invalid JSON in member data", 400);
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const parsedBody = JSON.parse(req.body.memberData);
if (!req.body.memberData) {
throw new ApiError("No member data provided", 400);
}
let parsedBody;
try {
parsedBody = JSON.parse(req.body.memberData);
} catch (error) {
throw new ApiError("Invalid JSON in member data", 400);
}
🤖 Prompt for AI Agents
In src/controllers/member.controller.ts at line 80, the JSON.parse call on
req.body.memberData lacks error handling, which can cause the application to
crash if the input is malformed. Wrap the JSON.parse call in a try-catch block
to catch any SyntaxError, and handle the error gracefully by returning an
appropriate response or error message to the client.

let imageUrl: undefined | string;

if (req.file) {
const oldData = await memberService.getDetails(memberId);
const oldImage = oldData?.profilePhoto;

if(oldImage) await uploadImage(supabase, req.file, "members", oldImage);

const imageUrl = await uploadImage(supabase, req.file, "members");
body.profilePhoto = imageUrl;
else imageUrl = await uploadImage(supabase, req.file, "members");
}
if (imageUrl) parsedBody.profilePhoto = imageUrl;

await memberService.updateMember(memberId, body);
await memberService.updateMember(memberId, parsedBody);

const updatedData = await memberService.getDetails(memberId);
res
.status(200)
.json({ success: true, user: updatedData });
};
};


// Get all unapproved members
export const getUnapprovedMembers = async (req: Request, res: Response) => {
Expand Down
22 changes: 7 additions & 15 deletions tests/Member.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { createAMember, updateAMember } from '../src/controllers/member.controll
import * as memberService from '../src/services/member.service';
import { ApiError } from '../src/utils/apiError';
import { SupabaseClient } from '@supabase/supabase-js';
import { uploadImage, deleteImage } from '../src/utils/imageUtils';
import { uploadImage } from '../src/utils/imageUtils';

jest.mock('../src/db/client', () => ({
prisma: {
Expand Down Expand Up @@ -71,7 +71,7 @@ describe('Member Controller - updateAMember', () => {
it('should update member and return updated data (no image)', async () => {
const req = {
params: { memberId: 'abc-123' },
body: { github: 'https://github.com/shrutii' },
body: { memberData: JSON.stringify({ github: 'https://github.com/shrutii' }) },
file: undefined,
} as unknown as Request;

Expand Down Expand Up @@ -106,7 +106,7 @@ describe('Member Controller - updateAMember', () => {
const handler = updateAMember(mockSupabase);
await handler(req, res);

expect(spyUpdate).toHaveBeenCalledWith('abc-123', req.body);
expect(spyUpdate).toHaveBeenCalledWith('abc-123', { github: 'https://github.com/shrutii' });
expect(spyGet).toHaveBeenCalledTimes(1);
expect(res.status).toHaveBeenCalledWith(200);
expect(res.json).toHaveBeenCalledWith({
Expand All @@ -118,7 +118,7 @@ describe('Member Controller - updateAMember', () => {
it('should upload new image, handle old image, update member, and return updated data', async () => {
const req = {
params: { memberId: 'abc-123' },
body: {},
body: { memberData: JSON.stringify({}) },
file: { buffer: Buffer.from('fake-image-data') },
} as unknown as Request;

Expand Down Expand Up @@ -153,7 +153,6 @@ describe('Member Controller - updateAMember', () => {
};

(uploadImage as jest.Mock)
.mockResolvedValueOnce(undefined)
.mockResolvedValueOnce('https://new.url/image.png');

jest.spyOn(memberService, 'getDetails')
Expand All @@ -167,23 +166,16 @@ describe('Member Controller - updateAMember', () => {
const handler = updateAMember(mockSupabase);
await handler(req, res);

expect(uploadImage).toHaveBeenNthCalledWith(
1,
expect(uploadImage).toHaveBeenCalledWith(
mockSupabase,
req.file,
'members',
'https://old.url/image.png'
);

expect(uploadImage).toHaveBeenNthCalledWith(
2,
mockSupabase,
req.file,
'members'
);

expect(spyUpdate).toHaveBeenCalledWith('abc-123', {
profilePhoto: 'https://new.url/image.png',

});

expect(res.status).toHaveBeenCalledWith(200);
Expand All @@ -192,4 +184,4 @@ describe('Member Controller - updateAMember', () => {
user: updatedMember,
});
});
});
});