Skip to content

Commit

Permalink
Merge f282de2 into beb918c
Browse files Browse the repository at this point in the history
  • Loading branch information
julietezekwe committed Jan 16, 2019
2 parents beb918c + f282de2 commit 89a0066
Show file tree
Hide file tree
Showing 12 changed files with 233 additions and 25 deletions.
9 changes: 9 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
"babel-preset-stage-2": "^6.24.1",
"bcryptjs": "^2.4.3",
"body-parser": "^1.18.3",
"chai": "^4.2.0",
"chai-http": "^4.2.1",
"cors": "^2.8.4",
"dotenv": "^6.0.0",
"ejs": "^2.6.1",
Expand All @@ -35,6 +37,7 @@
"express-jwt": "^5.3.1",
"express-request-id": "^1.4.1",
"express-session": "^1.15.6",
"express-validator": "^5.3.1",
"jsonwebtoken": "^8.3.0",
"method-override": "^2.3.10",
"methods": "^1.1.2",
Expand All @@ -55,8 +58,6 @@
"devDependencies": {
"@babel/plugin-proposal-class-properties": "^7.2.3",
"@babel/plugin-transform-regenerator": "^7.0.0",
"chai": "^4.2.0",
"chai-http": "^4.2.1",
"coveralls": "^3.0.2",
"eslint": "^5.12.0",
"eslint-config-airbnb-base": "^13.1.0",
Expand Down
3 changes: 2 additions & 1 deletion src/controllers/UsersController.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,11 @@ class UsersController {
};
const token = await TokenAuthenticate
.generateToken(userDetails, tokenExpireTime);
const path = basePath(req);
const recipient = registeredEmail;
const subject = 'Email Verification';
const message = `<h1>Verification link</h1><br>
<a href='http://localhost:9000/api/v1/user?token=${token}'>
<a href='${path}/api/v1/auth/user?token=${token}'>
<button style='font-size: 20px; background: orange;'>verify</button>
</a><br>
<p>Kindly click on the button above to verify your email.
Expand Down
1 change: 0 additions & 1 deletion src/helpers/EmailNotificationAPI.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ class EmailNotificationAPI {
});
}


/**
* @Represents sendEmail
* @return {string|Object} Success message | Error
Expand Down
6 changes: 6 additions & 0 deletions src/helpers/basepath.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const basePath = (req) => {
const path = `${req.protocol}://${req.headers.host}`;
return path;
};

export default basePath;
3 changes: 3 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import bodyParser from 'body-parser';
import cors from 'cors';
import morgan from 'morgan';
import requestId from 'express-request-id';
import expressValidator from 'express-validator';
import routes from './routes/index';
import Response from './helpers/response';

Expand All @@ -16,6 +17,8 @@ app.use(cors());

app.use(requestId());

app.use(expressValidator());

morgan.token('id', req => req.id);

const loggerFormat = ':id [:date[web]] ":method :url" :status :response-time';
Expand Down
58 changes: 58 additions & 0 deletions src/middlewares/UsersValidator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import Response from '../helpers/response';

const minPassLen = 5;
let response;
const userTypeOptions = ['user', 'artist'];
/**
* A module that checks if email already exists at sign up
* @module validateUserInputs
*/
class UserValidator {
/**
* @description - Checks the request parameters for user reg
* @param {Object} req - request
* @param {object} res - response
* @param {Object} next - Call back function
* @return {object} - status code and error message or next()
* @static
* @memberof UserValidator
*/
static UserSignUpValidator(req, res, next) {
req.check('firstName', 'First Name is required').trim().notEmpty();
req.check('lastName', 'Last Name is required').trim().notEmpty();
req.check('username', 'Username is required').trim().notEmpty();
req.check('userType', 'User type is required').trim().notEmpty();
req.check('email', 'Email is required').trim().notEmpty();
req.check('email', 'Email is not valid').trim().isEmail();
req.check('password', 'Password is required').trim().notEmpty();
req.check('password', 'Minimum password length is 5 characters')
.isLength({ min: minPassLen });
const errors = req.validationErrors();
const validationErrors = [];
if (errors) {
errors.map(err => validationErrors.push(err.msg));
response = new Response(
'Bad Request',
400,
'Invalid credentials',
validationErrors
);
return res.status(response.code).json(response);
}
const { userType } = req.body;
const userTypes = userTypeOptions.includes(userType);
if (!userTypes) {
response = new Response(
'Not found',
404,
'This user type does not exist'
);
return res.status(response.code).json(response);
}
const { email } = req.body;
req.body.email = email.replace(/\s{1,}/g, '').trim().toLowerCase();
return next();
}
}

export default UserValidator;
35 changes: 35 additions & 0 deletions src/middlewares/emailCheck.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import models from '../db/models';
import Response from '../helpers/response';

let response;
/**
* A module that checks if email already exists at sign up
* @module emailCheck
*/

/**
* @param {object} req The request object
* @param {object} res The response object
* @param {Function} next The next function to be executed
* @return {void}
*/
const emailCheck = async (req, res, next) => {
const { email } = req.body;

const emailExist = await models.User.find({
where: {
email,
},
});
if (emailExist) {
response = new Response(
'Unsuccessful',
409,
'Email already exists. Input a different email'
);
return res.status(response.code).json(response);
}
if (!emailExist) next();
};

export default emailCheck;
13 changes: 9 additions & 4 deletions src/routes/usersRoute.js → src/routes/authRouter.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import express from 'express';
import UserController from '../controllers/UsersController';
import emailCheck from '../middlewares/emailCheck';
import UserValidator from '../middlewares/UsersValidator';
import TokenAuthenticate from '../helpers/TokenAuthenticate';
import UserMiddleware from '../middlewares/UserMiddleware';

const authRouter = express.Router();

authRouter.post('/signup', UserController.signUp);
const authRouter = express.Router();

authRouter
.post('/signup',
UserValidator.UserSignUpValidator,
emailCheck,
UserController.signUp);
authRouter.post(
'/forgot-password',
UserMiddleware.VerifyEmail,
Expand All @@ -20,5 +26,4 @@ authRouter.put(
);
authRouter.post('/signin', UserController.signIn);

// eslint-disable-next-line import/prefer-default-export
export { authRouter };
export default authRouter;
2 changes: 1 addition & 1 deletion src/routes/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import express from 'express';
import { authRouter } from './usersRoute';
import authRouter from './authRouter';

const router = express.Router();

Expand Down
81 changes: 66 additions & 15 deletions test/controllers/userControllerTest.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable max-len */
import 'babel-polyfill';
import chai from 'chai';
import chaiHttp from 'chai-http';
Expand All @@ -9,17 +10,30 @@ chai.use(chaiHttp);
const { expect } = chai;
const {
validUser,
invalidUser
validUser1,
invalidUser,
invalidUserEmail,
invalidUserType,
spacedField,
} = userDetails;

let userToken;

describe('Users Endpoint API Test', () => {
// eslint-disable-next-line no-undef
before((done) => {
chai.request(app)
.post('/api/v1/auth/signup')
.send(validUser)
.end((err) => {
done(err);
});
});
describe('USERS POST REQUESTS', () => {
it('it should signup a valid user', (done) => {
chai.request(app)
.post('/api/v1/auth/signup')
.send(validUser)
.send(validUser1)
.end((err, res) => {
expect(res.body).to.be.a('object');
expect(res.body.messages)
Expand All @@ -29,22 +43,65 @@ describe('Users Endpoint API Test', () => {
done(err);
});
});
it('it should signup user if email exist', (done) => {
chai.request(app)
.post('/api/v1/auth/signup')
.send(validUser)
.end((err, res) => {
expect(res.body.status).to.equal('Unsuccessful');
expect(res.body.messages).eql('Email already exists. Input a different email');
expect(res.status).to.equal(409);
done();
});
});
it('it should not signup a user with invalid email', (done) => {
chai.request(app)
.post('/api/v1/auth/signup')
.send(invalidUserEmail)
.end((err, res) => {
expect(res.body.status).eql('Bad Request');
expect(res.body.messages).eql('Invalid credentials');
expect(res.body.data[0]).eql('Email is not valid');
done(err);
});
});
it('it should not signup an invalid user', (done) => {
chai.request(app)
.post('/api/v1/auth/signup')
.send({})
.end((err, res) => {
expect(res.body.status).eql('Not ok');
expect(res.body.status).eql('Bad Request');
expect(res.body.messages).eql('Invalid credentials');
expect(res.body.data[0]).eql('First Name is required');
expect(res.body.data[1]).eql('Last Name is required');
expect(res.body.data[2]).eql('Username is required');
expect(res.body.data[3]).eql('User type is required');
expect(res.body.data[4]).eql('Email is required');
expect(res.body.data[5]).eql('Email is not valid');
expect(res.body.data[6]).eql('Password is required');
expect(res.body.data[7]).eql('Minimum password length is 5 characters');
done(err);
});
});
it('it should not signup an invalid email', (done) => {
it('it should not signup an invalid usertype', (done) => {
chai.request(app)
.post('/api/v1/auth/signup')
.send(invalidUser)
.send(invalidUserType)
.end((err, res) => {
expect(res.body.status).eql('Bad request');
expect(res.body.messages).eql('There was a problem sending');
expect(res.body.status).eql('Not found');
expect(res.body.code).eql(404);
expect(res.body.messages).eql('This user type does not exist');
done(err);
});
});
it('it should not signup a user with any empty field', (done) => {
chai.request(app)
.post('/api/v1/auth/signup')
.send(spacedField)
.end((err, res) => {
expect(res.body.status).eql('Bad Request');
expect(res.body.code).eql(400);
expect(res.body.messages).eql('Invalid credentials');
done(err);
});
});
Expand Down Expand Up @@ -77,16 +134,10 @@ describe('Users Endpoint API Test', () => {
it('it should sign in a user with valid email and password', (done) => {
chai.request(app)
.post('/api/v1/auth/signin')
.send({
email: 'julietezekwe@gmail.com',
password: 'femi'
})
.send(validUser)
.end((err, res) => {
expect(res.body.messages).eql('User logged in successfully');
expect(res.body.data.token).to.be.a('string');
expect(res.body.data).to.have.property('token');
expect(res.status).to.equal(200);
expect(res.body.status).eql('Ok');
expect(res.body.messages).eql('User logged in successfully');
done(err);
});
});
Expand Down
Loading

0 comments on commit 89a0066

Please sign in to comment.