Skip to content

Commit 1ae9393

Browse files
fix(auth): stop writing OAuth validation errors directly to res
1 parent 14f653d commit 1ae9393

2 files changed

Lines changed: 23 additions & 17 deletions

File tree

modules/auth/controllers/auth.controller.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ const oauthCall = (req, res, next) => {
113113
* @param {Object} providerUserProfile
114114
* @param {Function} done - done
115115
*/
116-
const checkOAuthUserProfile = async (profil, key, provider, res) => {
116+
const checkOAuthUserProfile = async (profil, key, provider) => {
117117
// check if user exist
118118
try {
119119
const query = {};
@@ -137,10 +137,11 @@ const checkOAuthUserProfile = async (profil, key, provider, res) => {
137137
const result = model.getResultFromZod(user, UsersSchema.User);
138138
// check error
139139
const error = model.checkError(result);
140-
if (error) return responses.error(res, 422, 'Schema validation error', error)(result.error);
140+
if (error) throw new AppError('Schema validation error', { code: 'VALIDATION_ERROR', details: { message: error } });
141141
// else return req.body with the data after Zod validation
142142
return await UserService.create(result.value);
143143
} catch (err) {
144+
if (err instanceof AppError) throw err;
144145
throw new AppError('oAuth', { code: 'CONTROLLER_ERROR', details: err.details || err });
145146
}
146147
};
@@ -163,7 +164,7 @@ const oauthCallback = async (req, res, next) => {
163164
providerData: {},
164165
};
165166
user.providerData[req.body.key] = req.body.value;
166-
user = await checkOAuthUserProfile(user, req.body.key, strategy, res);
167+
user = await checkOAuthUserProfile(user, req.body.key, strategy);
167168
const token = jwt.sign({ userId: user.id }, config.jwt.secret, {
168169
expiresIn: config.jwt.expiresIn,
169170
});
@@ -177,7 +178,12 @@ const oauthCallback = async (req, res, next) => {
177178
message: 'oAuth Ok',
178179
});
179180
} catch (err) {
180-
return responses.error(res, 422, 'Unprocessable Entity', errors.getMessage(err.details || err))(err);
181+
return responses.error(
182+
res,
183+
422,
184+
err instanceof AppError && err.code === 'VALIDATION_ERROR' ? errors.getMessage(err) : 'Unprocessable Entity',
185+
errors.getMessage(err.details || err),
186+
)(err);
181187
}
182188
}
183189
// classic web oAuth

modules/auth/tests/auth.integration.tests.js

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -486,28 +486,30 @@ describe('Auth integration tests:', () => {
486486
avatar: '',
487487
providerData: { id: 'google-fake-id-999' },
488488
};
489-
const mockRes = { status() { return this; }, json() {}, cookie() { return this; } };
490-
const result = await AuthController.checkOAuthUserProfile(profil, 'id', 'google', mockRes);
489+
const result = await AuthController.checkOAuthUserProfile(profil, 'id', 'google');
491490
expect(result).toBeDefined();
492491
expect(result.id).toBeDefined();
493492
expect(result.email).toBe(profil.email);
494493
oauthUsers.push(result);
495494
});
496495

497-
test('should return 422 when checkOAuthUserProfile receives an invalid profile', async () => {
496+
test('should throw validation AppError when checkOAuthUserProfile receives an invalid profile', async () => {
498497
const invalidProfil = {
499498
firstName: '', // invalid — fails min(1)
500499
lastName: 'Test',
501500
email: 'invalid-oauth@test.com',
502501
avatar: '',
503502
providerData: { id: 'google-invalid-999' },
504503
};
505-
const errors = [];
506-
const mockRes = { status() { return this; }, json(body) { errors.push(body); }, cookie() { return this; } };
507-
const result = await AuthController.checkOAuthUserProfile(invalidProfil, 'id', 'google', mockRes);
508-
expect(result).toBeDefined();
509-
expect(result.type).toBe('error');
510-
expect(errors[0]?.message).toBe('Schema validation error');
504+
await expect(
505+
AuthController.checkOAuthUserProfile(invalidProfil, 'id', 'google'),
506+
).rejects.toMatchObject({
507+
message: 'Schema validation error',
508+
code: 'VALIDATION_ERROR',
509+
details: {
510+
message: expect.any(String),
511+
},
512+
});
511513
});
512514

513515
test('should throw AppError when create fails inside checkOAuthUserProfile', async () => {
@@ -518,10 +520,9 @@ describe('Auth integration tests:', () => {
518520
avatar: '',
519521
providerData: { id: 'google-err-000' },
520522
};
521-
const mockRes = { status() { return this; }, json() {}, cookie() { return this; } };
522523
const createSpy = jest.spyOn(UserService, 'create').mockRejectedValueOnce(new Error('DB error'));
523524
await expect(
524-
AuthController.checkOAuthUserProfile(profil, 'id', 'google', mockRes),
525+
AuthController.checkOAuthUserProfile(profil, 'id', 'google'),
525526
).rejects.toThrow('oAuth');
526527
createSpy.mockRestore();
527528
});
@@ -590,9 +591,8 @@ describe('Auth integration tests:', () => {
590591
avatar: '',
591592
providerData: { id: 'google-find-id-777' },
592593
};
593-
const mockRes = { status() { return this; }, json() {}, cookie() { return this; } };
594594
// Second call — should find the existing user (search.length === 1 branch)
595-
const found = await AuthController.checkOAuthUserProfile(profil, 'id', 'google', mockRes);
595+
const found = await AuthController.checkOAuthUserProfile(profil, 'id', 'google');
596596
expect(found).toBeDefined();
597597

598598
// cleanup

0 commit comments

Comments
 (0)