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
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ module.exports = {
'!src/index.ts',
'!src/app.ts',
'!src/database/index.ts',
'!src/database/seeders',
'!src/modules/app/**',
'!src/config/**',
],
Expand Down
138 changes: 68 additions & 70 deletions src/modules/authentication/__test__/authentication.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ import logger from '../../../config/logger';

import {
signUpMock,
// loginMock,
// invalidLoginMock,
loginMock,
invalidLoginMock,
emptySignupNameField,
invalidSignupEmailInput,
invalidSignupPasswordInput,
allSignupFieldsEmpty,
// invalidLoginEmailInput,
// invalidLoginPasswordInput,
// allLoginFieldsEmpty,
invalidLoginEmailInput,
invalidLoginPasswordInput,
allLoginFieldsEmpty,
} from '../../user/__test__/__mocks__/mockUsers';

import User from '../../../database/models/User';
Expand Down Expand Up @@ -112,65 +112,63 @@ describe('TEST SUITE FOR USER ONBOARDING AND AUTHENTICATION', () => {
done();
});

// it('should successfully sign in a user', async (done) => {
// const response = await request.post(`${baseUrl}/auth`).send(loginMock);

// expect(response.status).toEqual(200);
// expect(response.body.success).toEqual(true);
// expect(response.body.message).toEqual('You have successfully logged in');
// expect(response.body.user.email).toEqual(loginMock.email);
// done();
// });

// it('should not sign in a non-existing user', async (done) => {
// const response = await request.post(`${baseUrl}/auth`).send(invalidLoginMock);

// expect(response.status).toEqual(404);
// expect(response.body.success).toEqual(false);
// expect(response.body.message).toEqual('The email or password is not correct');
// done();
// });

// it('should validate login email field', async (done) => {
// const response = await request
// .post(`${baseUrl}/auth`)
// .send(invalidLoginEmailInput);

// expect(response.status).toEqual(422);
// expect(response.body.success).toEqual(false);
// expect(response.body.message).toEqual('Validation Errors');
// expect(response.body.errors).toEqual({
// email: ['email is not allowed to be empty'],
// });
// done();
// });

// it('should validate login password field', async (done) => {
// const response = await request
// .post(`${baseUrl}/auth`)
// .send(invalidLoginPasswordInput);

// expect(response.status).toEqual(422);
// expect(response.body.success).toEqual(false);
// expect(response.body.message).toEqual('Validation Errors');
// expect(response.body.errors).toEqual({
// password: ['password is not allowed to be empty'],
// });
// done();
// });

// it('should validate signup all fields concurrently', async (done) => {
// const response = await request.post(`${baseUrl}/auth`).send(allLoginFieldsEmpty);

// expect(response.status).toEqual(422);
// expect(response.body.success).toEqual(false);
// expect(response.body.message).toEqual('Validation Errors');
// expect(response.body.errors).toEqual({
// email: ['email is not allowed to be empty'],
// password: ['password is not allowed to be empty'],
// });
// done();
// });
it('should successfully sign in a user', async (done) => {
const response = await request.post(`${baseUrl}/auth`).send(loginMock);

expect(response.status).toEqual(200);
expect(response.body.success).toEqual(true);
done();
});

it('should not sign in a non-existing user', async (done) => {
const response = await request.post(`${baseUrl}/auth`).send(invalidLoginMock);

expect(response.status).toEqual(400);
expect(response.body.success).toEqual(false);
expect(response.body.error).toEqual('Invalid login details');
done();
});

it('should validate login email field', async (done) => {
const response = await request
.post(`${baseUrl}/auth`)
.send(invalidLoginEmailInput);

expect(response.status).toEqual(422);
expect(response.body.success).toEqual(false);
expect(response.body.message).toEqual('Validation Errors');
expect(response.body.errors).toEqual({
email: ['email is not allowed to be empty'],
});
done();
});

it('should validate login password field', async (done) => {
const response = await request
.post(`${baseUrl}/auth`)
.send(invalidLoginPasswordInput);

expect(response.status).toEqual(422);
expect(response.body.success).toEqual(false);
expect(response.body.message).toEqual('Validation Errors');
expect(response.body.errors).toEqual({
password: ['password is not allowed to be empty'],
});
done();
});

it('should validate signup all fields concurrently', async (done) => {
const response = await request.post(`${baseUrl}/auth`).send(allLoginFieldsEmpty);

expect(response.status).toEqual(422);
expect(response.body.success).toEqual(false);
expect(response.body.message).toEqual('Validation Errors');
expect(response.body.errors).toEqual({
email: ['email is not allowed to be empty'],
password: ['password is not allowed to be empty'],
});
done();
});
});

describe('AUTHENTICATION CONTROLLER UNIT TESTS', () => {
Expand Down Expand Up @@ -209,10 +207,10 @@ describe('AUTHENTICATION CONTROLLER UNIT TESTS', () => {
done();
});

// it("calls status and json methods to generate response when login in", async (done) => {
// await UnmockedAuthController.loginUser(req, res);
// expect(status).toHaveBeenCalledTimes(1);
// expect(json).toHaveBeenCalledTimes(1);
// done();
// });
it("calls status and json methods to generate response when login in", async (done) => {
await UnmockedAuthController.loginUser(req, res);
expect(status).toHaveBeenCalledTimes(1);
expect(json).toHaveBeenCalledTimes(1);
done();
});
});
96 changes: 40 additions & 56 deletions src/modules/authentication/authentication.controller.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Request, Response } from 'express';
// import _ from 'underscore';
import _ from 'underscore';

import Utils from '../../utils/utils';
import Error from '../../utils/Error';
import UserRepository from '../user/user.repository';
import { User } from '../../@types/express';
// import { UserType } from '../user/interfaces/User';

const {
Expand Down Expand Up @@ -37,12 +38,11 @@ export default class AuthController {
request: Request,
response: Response,
): Promise<void | Response<any, Record<string, any>>> {
const { email, password } = request.body;
try {
const { email, password } = request.body;
const isUserExists = await UserRepository.findByEmail(email);

if (isUserExists) {
return Error.handleError("Email already in use", 403, response);
return Error.handleError('Email already in use', 403, response);
}

const hashedPassword = await hashPassword(password);
Expand All @@ -52,63 +52,47 @@ export default class AuthController {
password: hashedPassword,
});

return response.status(201).json({
message: "User added successfully",
token: Utils.generateAuthToken({ sub: user.email }),
success: true,
});
return response.status(201).json({
message: 'User added successfully',
token: Utils.generateAuthToken({ sub: user.email, admin: user.admin }),
success: true,
});
} catch (error) {
return Error.handleError('Server error', 500, response, error);
}
}

// /**
// * Returns success:true and token if verification was successful and error if not
// * @name /auth POST
// * @param request {Object} The request.
// * @param response {Object} The response.
// * @param req.body {Object} The JSON payload.
// * @remarks
// * - This function accepts two parameters, request, and response
// * You can follow the file trail to have a better understanding of how the function works.
// *
// * @function
// * @returns {Boolean} success
// *
// */
// static async loginUser(request: Request, response: Response): Promise<any> {
// const { email, password } = request.body;
// const user: any = await UserRepository.findByEmail(email);

// try {
// if (!user || !comparePassword(user.password, password)) {
// return response.status(404).json({
// success: false,
// message: 'The email or password is not correct',
// });
// }

// const token: string = generateToken({
// sub: user.email,
// admin: user.admin,
// });
/**
* Returns success:true and token if verification was successful and error if not
* @name /auth POST
* @param request {Object} The request.
* @param response {Object} The response.
* @param req.body {Object} The JSON payload.
* @remarks
* - This function accepts two parameters, request, and response
* You can follow the file trail to have a better understanding of how the function works.
*
* @function
* @returns {Boolean} success
*
*/
static async loginUser(request: Request, response: Response): Promise<any> {
try {
const { email, password } = request.body;
const user: User | null = await UserRepository.findByEmail(email);

// const authenticatedUser = _.omit(
// user.toJSON(),
// 'password',
// '__v',
// 'admin',
// 'date',
// );
if (!user || !Utils.passwordsMatch(password, user.password)) {
return Error.handleError("Invalid login details", 400, response);
}

// response.status(200).json({
// success: true,
// message: 'You have successfully logged in',
// user: authenticatedUser,
// token,
// });
// } catch (error) {
// return errorHandler(error, 500, response);
// }
// }
const token: string = Utils.generateAuthToken({
sub: user.email,
admin: user.admin,
});

return response.status(200).json({ success: true, token });
} catch (error) {
return Error.handleError('Server error', 500, response, error);
}
}
}
12 changes: 3 additions & 9 deletions src/modules/authentication/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,9 @@ import Middlewares from '../../middleware';

const authRouter: Router = Router();

const { createUser, loginUser } = AuthController;
const {
createUser,
// loginUser
} = AuthController;
const {
UserSchema: {
signupSchema,
// loginSchema
},
UserSchema: { signupSchema, loginSchema },
} = Schemas;
const {
Validator: { validateRequest },
Expand All @@ -26,6 +20,6 @@ authRouter.post(
createUser,
);

// authRouter.post('/auth', validateRequest(loginSchema(), 'body'), loginUser);
authRouter.post('/auth', validateRequest(loginSchema(), 'body'), loginUser);

export default authRouter;
2 changes: 1 addition & 1 deletion src/utils/schema/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import UserSchema from './user';
import UserSchema from './user.schema';
import SupportRequestSchema from './support-request.schema';
import CommentSchema from './comment.schema';

Expand Down
12 changes: 6 additions & 6 deletions src/utils/schema/user.ts → src/utils/schema/user.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ export default class UserSchema {
});
}

// static loginSchema() {
// return Joi.object({
// email: BaseSchema.email().required(),
// password: Joi.string().required(),
// });
// }
static loginSchema() {
return Joi.object({
email: BaseSchema.email().required(),
password: Joi.string().required(),
});
}
}