Skip to content
This repository has been archived by the owner on Jul 26, 2024. It is now read-only.

Commit

Permalink
fix: return appropriate HTTP status codes
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanmalonzo committed May 31, 2024
1 parent e6ee516 commit 5178592
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 25 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ name: Node.js CI

on:
push:
branches: ["main", "develop"]
branches: ["main"]
pull_request:
branches: ["main", "develop"]
branches: ["main"]

jobs:
backend:
Expand Down
2 changes: 1 addition & 1 deletion backend/.mocharc.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ process.env.NODE_NO_WARNINGS = 1;

module.exports = {
require: ['esm', 'tsx'],
timeout: '10000',
timeout: '30000',
};
2 changes: 1 addition & 1 deletion backend/app/services/SessionService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export class SessionService {

const isPasswordCorrect = await bcrypt.compare(password, user.password);
if (!isPasswordCorrect) {
throw new RequestError(StatusCodes.UNAUTHORIZED, 'wrong_password');
throw new RequestError(StatusCodes.UNAUTHORIZED, 'invalid_credentials');
}

return {
Expand Down
23 changes: 16 additions & 7 deletions backend/app/services/UserService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,16 @@ export class UserService {

static async registerUser(email: string, password: string): Promise<User> {
if (!UserService._isValidEmail(email)) {
throw new RequestError(StatusCodes.BAD_REQUEST, 'invalid_email');
throw new RequestError(StatusCodes.UNPROCESSABLE_ENTITY, 'invalid_email');
}
if (await UserRepository.findByEmail(email)) {
throw new RequestError(StatusCodes.BAD_REQUEST, 'user_already_exists');
throw new RequestError(StatusCodes.UNAUTHORIZED, 'user_already_exists');
}
if (!UserService._checkPasswordStrength(password)) {
throw new RequestError(StatusCodes.BAD_REQUEST, 'invalid_password');
throw new RequestError(
StatusCodes.UNPROCESSABLE_ENTITY,
'invalid_password',
);
}

const hash = await bcrypt.hash(password, SALT_ROUNDS);
Expand All @@ -43,7 +46,7 @@ export class UserService {

static async sendVerificationEmail(user: User, email: string): Promise<void> {
if (!UserService._isValidEmail(email)) {
throw new RequestError(StatusCodes.BAD_REQUEST, 'invalid_email');
throw new RequestError(StatusCodes.UNPROCESSABLE_ENTITY, 'invalid_email');
}

const challenge = await ChallengeRepository.findByUserAndType(
Expand All @@ -52,7 +55,10 @@ export class UserService {
);

if (challenge?.disabled) {
throw new RequestError(StatusCodes.BAD_REQUEST, 'email_already_verified');
throw new RequestError(
StatusCodes.UNAUTHORIZED,
'email_already_verified',
);
}

const emailVerificationToken = crypto.randomBytes(32).toString('hex');
Expand Down Expand Up @@ -103,7 +109,7 @@ export class UserService {

static async sendPasswordResetEmail(email: string): Promise<void> {
if (!UserService._isValidEmail(email)) {
throw new RequestError(StatusCodes.BAD_REQUEST, 'invalid_email');
throw new RequestError(StatusCodes.UNPROCESSABLE_ENTITY, 'invalid_email');
}

const user = await UserRepository.findByEmail(email);
Expand Down Expand Up @@ -160,7 +166,10 @@ export class UserService {
}

if (!UserService._checkPasswordStrength(password)) {
throw new RequestError(StatusCodes.BAD_REQUEST, 'invalid_password');
throw new RequestError(
StatusCodes.UNPROCESSABLE_ENTITY,
'invalid_password',
);
}

await this.changePassword(user.id, password);
Expand Down
23 changes: 10 additions & 13 deletions backend/tests/integration/UserRouter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,38 +22,35 @@ describe('UserRouter', () => {
expect(response.status).to.equal(StatusCodes.CREATED);
});

it('should return a 400 status code if email is already in use', async () => {
it('should return a 401 status code if email is already in use', async () => {
const email = uniqueEmail();

await User.create({
email,
password: PASSWORD,
});
await UserService.registerUser(email, PASSWORD);

const response = await request(app).post('/users').send({
email,
password: PASSWORD,
});

expect(response.status).to.equal(StatusCodes.BAD_REQUEST);
expect(response.status).to.equal(StatusCodes.UNAUTHORIZED);
});

it('should return a 400 status code if email is invalid', async () => {
it('should return a 422 status code if email is invalid', async () => {
const response = await request(app).post('/users').send({
email: 'invalid-email',
password: PASSWORD,
});

expect(response.status).to.equal(StatusCodes.BAD_REQUEST);
expect(response.status).to.equal(StatusCodes.UNPROCESSABLE_ENTITY);
});

it('should return a 400 status code if password is invalid', async () => {
it('should return a 422 status code if password is invalid', async () => {
const response = await request(app).post('/users').send({
email: uniqueEmail(),
password: 'invalid-password',
});

expect(response.status).to.equal(StatusCodes.BAD_REQUEST);
expect(response.status).to.equal(StatusCodes.UNPROCESSABLE_ENTITY);
});
});

Expand Down Expand Up @@ -141,12 +138,12 @@ describe('UserRouter', () => {
expect(response.status).to.equal(StatusCodes.OK);
});

it('should return a 400 status code if email is invalid', async () => {
it('should return a 422 status code if email is invalid', async () => {
const response = await request(app).post('/users/password-reset').send({
email: 'invalid-email',
});

expect(response.status).to.equal(StatusCodes.BAD_REQUEST);
expect(response.status).to.equal(StatusCodes.UNPROCESSABLE_ENTITY);
});

it('should return a 200 satus code even if user is not found', async () => {
Expand All @@ -158,7 +155,7 @@ describe('UserRouter', () => {
});
});

describe('POST /users/:id/password', () => {
describe('PUT /users/:id/password', () => {
const registerUser = async (): Promise<User> => {
return await UserService.registerUser(uniqueEmail(), PASSWORD);
};
Expand Down
2 changes: 1 addition & 1 deletion backend/tests/unit/SessionService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ describe('SessionService', () => {

await expect(
SessionService.login(USER.email, USER.password),
).to.be.rejectedWith('wrong_password');
).to.be.rejectedWith('invalid_credentials');
});
});
});

0 comments on commit 5178592

Please sign in to comment.