Skip to content

Commit

Permalink
feature-[167573212]: implement login feature
Browse files Browse the repository at this point in the history
- added login route
- tested login route
- created user model, migration and seeds file
- added a findUser helper function
- added a password helper function that compares password

[finishes #167573212]
  • Loading branch information
henryade committed Jul 31, 2019
1 parent fcb0918 commit c9ab9e3
Show file tree
Hide file tree
Showing 19 changed files with 480 additions and 11 deletions.
103 changes: 96 additions & 7 deletions package-lock.json

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

8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,20 @@
"author": "Andela Simulations Programme",
"license": "MIT",
"dependencies": {
"bcryptjs": "^2.4.3",
"coveralls": "^3.0.5",
"debug": "^4.1.1",
"dotenv": "^8.0.0",
"express": "^4.17.1",
"morgan": "^1.9.1",
"swagger-ui-express": "^4.0.7",
"yamljs": "^0.3.0",
"pg": "^7.11.0",
"pg-hstore": "^2.3.3",
"sequelize": "^5.10.2",
"sequelize-cli": "^5.5.0",
"sqlite3": "^4.0.9"
"sinon": "^7.3.2",
"sqlite3": "^4.0.9",
"swagger-ui-express": "^4.0.7",
"yamljs": "^0.3.0"
},
"devDependencies": {
"@babel/cli": "^7.5.5",
Expand Down
69 changes: 69 additions & 0 deletions server/controllers/Sessions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import bcrypt from 'bcryptjs';
import helpers from '../helpers';
// import models from '../database/models';

// const { Session } = models;
const {
findUser,
// generateToken,
serverResponse,
serverError
// expiryDate
} = helpers;
// const mobileDeviceIndicator =
// ['mobile', 'andriod', 'iphone', 'tablet', 'ipad', 'ipod'];
// const userAgent = req.headers['user-agent']
// const devicePlatform =
// mobileDeviceIndicator
// .some(device => userAgent.toLowerCase().indexOf(device) > 0) ? 'mobile' : 'browser';

/**
*
*
* @class Sessions
*/
class Sessions {
/**
*
*
* @static
* @param {object} req - request object
* @param {object} res - response object
* @memberof User
* @returns {json} object
*/
static async create(req, res) {
try {
const { userLogin, password } = req.body;
if (!/\D/.test(userLogin)) {
return serverResponse(res, 400, {
message: 'user login must be a string'
});
}
const user = await findUser(userLogin);
let verifyPassword;
if (user) verifyPassword = bcrypt.compareSync(password, user.password);
if (!user || !verifyPassword) {
return serverResponse(res, 403, {
message: 'incorrect username or password'
});
}
const { id, dataValues } = user;
// const token = generateToken(id);
// await Session.create({
// userId: id,
// token,
// expiresAt: expiryDate,
// userAgent,
// ipAddress: req.ip
// devicePlatform,
// });
delete dataValues.password;
return serverResponse(res, 200, { user: { ...dataValues } });
} catch (error) {
serverError(res);
}
}
}

export default Sessions;
1 change: 1 addition & 0 deletions server/database/models/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* istanbul ignore file */
import fs from 'fs';
import path from 'path';
import Sequelize from 'sequelize';
Expand Down
65 changes: 65 additions & 0 deletions server/docs/authors-haven-api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,74 @@ paths:
schema:
type: string
example: Welcome to Authors Haven
"/api/v1/sessions/create":
summary: Login Route
post:
description: Login Route
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- email
- password
properties:
userLogin:
type: string
minLength: 2
example: adechukwu
password:
type: string
minLength: 4
example: password
responses:
'200':
description: Login successful
content:
application/json:
schema:
"$ref": "#/components/schemas/loginResponse"
'400':
description: Bad request
content:
application/json:
schema:
"$ref": "#/components/schemas/errorResponse"
'403':
description: Incorrect username or password
content:
application/json:
schema:
"$ref": "#/components/schemas/errorResponse"
'500':
description: Server Error
content:
application/json:
schema:
"$ref": "#/components/schemas/serverResponse"



components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
schemas:
loginResponse:
type: object
properties:
user:
type: object
errorResponse:
type: object
properties:
message:
type: string
serverResponse:
type: object
properties:
error:
type: string
14 changes: 14 additions & 0 deletions server/helpers/dateHelper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* @name expiryDate
* @param {string} platform - platform that apps is accessed from
* @returns {date} date object
*/
const expiryDate = (platform) => {
const todaysDate = new Date(Date.now());
const expirationDate = new Date();
const timeExtension = platform === 'browser' ? 8 : 24;
expirationDate.setHours(todaysDate.getHours() + timeExtension);
return expirationDate;
};

export default { expiryDate };
21 changes: 21 additions & 0 deletions server/helpers/findUser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import models from '../database/models';

const { User } = models;
/**
* @name findUser
* @param {string} parameter - user input
* @returns {object} user object
*/
const findUser = async (parameter) => {
let param;
if (!/\D/.test(parameter)) {
param = { id: parameter };
} else if (/\D/.test(parameter) && /@.{2,9}\./.test(parameter)) {
param = { email: parameter };
} else {
param = { userName: parameter };
}
return User.findOne({ where: param });
};

export default findUser;
Loading

0 comments on commit c9ab9e3

Please sign in to comment.