From 7618e58398ca9712d25cca5811c89bf8392945a7 Mon Sep 17 00:00:00 2001 From: joel-joseph-george Date: Fri, 19 Jun 2026 11:03:03 +0530 Subject: [PATCH 1/3] Fixing the failed password reset workflow --- src/server/server.test.ts | 40 ++++++++++++++++++++++++++------------- src/server/server.ts | 29 +++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 14 deletions(-) diff --git a/src/server/server.test.ts b/src/server/server.test.ts index 0bd0273f..88e7eca6 100644 --- a/src/server/server.test.ts +++ b/src/server/server.test.ts @@ -15,6 +15,7 @@ const { mockDb, mockDbQueryBuilder } = vi.hoisted(() => { builder.where = vi.fn(() => builder); builder.limit = vi.fn(() => Promise.resolve(returnValue)); builder.values = vi.fn(() => Promise.resolve()); + builder.set = vi.fn(() => builder); return builder; }; @@ -22,6 +23,7 @@ const { mockDb, mockDbQueryBuilder } = vi.hoisted(() => { select: vi.fn(), delete: vi.fn(), insert: vi.fn(), + update: vi.fn(), }; return { mockDb, mockDbQueryBuilder }; @@ -31,7 +33,10 @@ const { mockDb, mockDbQueryBuilder } = vi.hoisted(() => { vi.mock('@/lib/auth', () => ({ auth: { - api: { getSession: vi.fn() }, + api: { + getSession: vi.fn(), + setPassword: vi.fn(), + }, handler: vi.fn(), }, })); @@ -41,6 +46,7 @@ vi.mock('@/db', () => ({ db: mockDb })); vi.mock('@/db/schema', () => ({ authSession: { token: 'token', id: 'id', userId: 'userId' }, authAuditLog: {}, + users: { email: 'email' }, })); vi.mock('@/lib/logger', () => ({ @@ -97,13 +103,14 @@ describe('server Route Handlers', () => { // ─── POST /api/auth/password/set ─────────────────────────────────────────── describe('pOST /api/auth/password/set', () => { - it('should proxy to auth.handler with path rewritten to /api/auth/set-password', async () => { - (auth.handler as any).mockResolvedValue( - new Response(JSON.stringify({ status: true }), { - status: 200, - headers: { 'Content-Type': 'application/json' }, - }) - ); + it('should call auth.api.setPassword, fetch session, and update user status to verified', async () => { + (auth.api.setPassword as any).mockResolvedValue(undefined); + (auth.api.getSession as any).mockResolvedValue({ + user: { email: 'test@example.com' }, + }); + + const mockUpdateBuilder = mockDbQueryBuilder([]); + mockDb.update.mockReturnValue(mockUpdateBuilder); const res = await server.request('/api/auth/password/set', { method: 'POST', @@ -112,11 +119,18 @@ describe('server Route Handlers', () => { }); expect(res.status).toBe(200); - expect(auth.handler).toHaveBeenCalledOnce(); - - const proxiedRequest: Request = (auth.handler as any).mock.calls[0][0]; - expect(new URL(proxiedRequest.url).pathname).toBe('/api/auth/set-password'); - expect(proxiedRequest.headers.get('Authorization')).toBe('Bearer test-token'); + expect(await res.json()).toEqual({ success: true }); + expect(auth.api.setPassword).toHaveBeenCalledWith({ + body: { newPassword: 'hunter2' }, + headers: expect.any(Headers), + }); + expect(auth.api.getSession).toHaveBeenCalledWith({ + headers: expect.any(Headers), + }); + expect(mockDb.update).toHaveBeenCalled(); + expect(mockUpdateBuilder.set).toHaveBeenCalledWith( + expect.objectContaining({ status: 'verified' }) + ); }); }); diff --git a/src/server/server.ts b/src/server/server.ts index 227ff3d8..3d8caec5 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -91,7 +91,34 @@ export function createServer() { return auth.handler(new Request(url, c.req.raw)); } - app.post('/api/auth/password/set', (c) => proxyToAuth(c, '/api/auth/set-password')); + app.post('/api/auth/password/set', async (c) => { + const { newPassword } = await c.req.json(); + try { + await auth.api.setPassword({ + body: { newPassword }, + headers: c.req.raw.headers, + }); + + const session = await auth.api.getSession({ + headers: c.req.raw.headers, + }); + + if (session?.user?.email) { + await db + .update(schema.users) + .set({ status: 'verified', updatedAt: new Date() }) + .where(eq(schema.users.email, session.user.email)); + } + + return c.json({ success: true }); + } catch (err) { + logger.error('Failed to set password:', err); + return c.json( + { message: err instanceof Error ? err.message : 'Failed to set password' }, + 400 + ); + } + }); // POST /api/auth/forget-password app.post('/api/auth/forget-password', (c) => proxyToAuth(c, '/api/auth/request-password-reset')); From d9109623a3d485b9e4ea98ed3c6bfd77111d75e1 Mon Sep 17 00:00:00 2001 From: joel-joseph-george Date: Fri, 19 Jun 2026 11:19:46 +0530 Subject: [PATCH 2/3] Adding logs on the changes --- src/server/server.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/server/server.ts b/src/server/server.ts index 3d8caec5..3ac0ec04 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -108,6 +108,11 @@ export function createServer() { .update(schema.users) .set({ status: 'verified', updatedAt: new Date() }) .where(eq(schema.users.email, session.user.email)); + logger.info(`User status updated to verified for email: ${session.user.email}`); + } else { + logger.warn( + 'Password set succeeded, but session or user email is missing. Skipped updating user status to verified.' + ); } return c.json({ success: true }); From 2b4f6e34820799f56e52eee618e0fe9e7a8a4703 Mon Sep 17 00:00:00 2001 From: joel-joseph-george Date: Fri, 19 Jun 2026 11:22:06 +0530 Subject: [PATCH 3/3] fix(auth): move JSON parsing inside try block and add status update logging --- src/server/server.test.ts | 26 ++++++++++++++++++++++++++ src/server/server.ts | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/server/server.test.ts b/src/server/server.test.ts index 88e7eca6..8b9f51bc 100644 --- a/src/server/server.test.ts +++ b/src/server/server.test.ts @@ -132,6 +132,32 @@ describe('server Route Handlers', () => { expect.objectContaining({ status: 'verified' }) ); }); + + it('should return 400 when JSON body is malformed', async () => { + const res = await server.request('/api/auth/password/set', { + method: 'POST', + headers: { 'Content-Type': 'application/json', Authorization: 'Bearer test-token' }, + body: 'invalid-json-body', + }); + + expect(res.status).toBe(400); + const json = await res.json(); + expect(json.message).toBeDefined(); + }); + + it('should return 400 when auth.api.setPassword throws an error', async () => { + (auth.api.setPassword as any).mockRejectedValue(new Error('Invalid password strength')); + + const res = await server.request('/api/auth/password/set', { + method: 'POST', + headers: { 'Content-Type': 'application/json', Authorization: 'Bearer test-token' }, + body: JSON.stringify({ newPassword: '123' }), + }); + + expect(res.status).toBe(400); + const json = await res.json(); + expect(json.message).toBe('Invalid password strength'); + }); }); // ─── POST /api/auth/sign-out ──────────────────────────────────────────────── diff --git a/src/server/server.ts b/src/server/server.ts index 3ac0ec04..7fc29ae5 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -92,8 +92,8 @@ export function createServer() { } app.post('/api/auth/password/set', async (c) => { - const { newPassword } = await c.req.json(); try { + const { newPassword } = await c.req.json(); await auth.api.setPassword({ body: { newPassword }, headers: c.req.raw.headers,