-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6 from Mcdavid95/ft-signup-user-167043030
#167043030 Signup User
- Loading branch information
Showing
19 changed files
with
1,349 additions
and
56 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import moment from 'moment'; | ||
import db from './db'; | ||
import { | ||
createToken, | ||
// hasToken, | ||
hashPassword, | ||
// isPassword, | ||
handleServerError, | ||
handleServerResponse, | ||
handleServerResponseError | ||
} from '../helpers/utils'; | ||
|
||
const Auth = { | ||
async create(req, res) { | ||
const { | ||
email, firstname, lastname, password, userType | ||
} = req.body; | ||
try { | ||
const hash = await hashPassword(password); | ||
const createQuery = `INSERT INTO | ||
Users(email, first_name, last_name, password, is_admin, created_date, modified_date) | ||
VALUES($1, $2, $3, $4, $5, $6, $7) | ||
returning *`; | ||
const values = [ | ||
email.trim().toLowerCase(), | ||
firstname.trim().toLowerCase(), | ||
lastname.trim().toLowerCase(), | ||
hash, | ||
userType === 'admin', | ||
moment(new Date()), | ||
moment(new Date()) | ||
]; | ||
const { rows } = await db.query(createQuery, values); | ||
const token = createToken(rows[0].id); | ||
return handleServerResponse(res, 201, { | ||
user_id: rows[0].id, | ||
is_admin: rows[0].is_admin, | ||
token | ||
}); | ||
} catch (error) { | ||
if (error.routine === '_bt_check_unique') { | ||
return handleServerResponseError(res, 409, `User with Email:- ${email.trim().toLowerCase()} already exists`); | ||
} | ||
handleServerError(res, error); | ||
} | ||
} | ||
}; | ||
|
||
export default Auth; |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { Pool } from 'pg'; | ||
import dotenv from 'dotenv'; | ||
|
||
dotenv.config(); | ||
const pool = new Pool({ | ||
connectionString: process.env.DATABASE_URL | ||
}); | ||
export default { | ||
/** | ||
* DB Query | ||
* @param {string} text | ||
* @param {Array} params | ||
* @returns {object} object | ||
*/ | ||
query(text, params) { | ||
return new Promise((resolve, reject) => { | ||
pool.query(text, params) | ||
.then((res) => { | ||
resolve(res); | ||
}) | ||
.catch((err) => { | ||
reject(err); | ||
}); | ||
}); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,109 @@ | ||
import bunyan from 'bunyan'; | ||
import bcrypt from 'bcrypt'; | ||
import jwt from 'jsonwebtoken'; | ||
import dotenv from 'dotenv'; | ||
|
||
dotenv.config(); | ||
|
||
export const logger = () => { | ||
const log = bunyan.createLogger({ name: 'myapp' }); | ||
return log; | ||
}; | ||
|
||
/** | ||
* | ||
* @param {*} response response object from server | ||
* @param {*} status error message | ||
* @param {*} data meta-data | ||
* @returns {*} error response | ||
*/ | ||
// eslint-disable-next-line max-len | ||
export const handleServerResponse = (response, status, data) => response.status(status).send({ | ||
status: 'success', | ||
data | ||
}); | ||
|
||
/** | ||
* | ||
* @param {*} response response object from server | ||
* @param {*} status error status | ||
* @param {*} message error message | ||
* @returns {*} error response | ||
*/ | ||
// eslint-disable-next-line max-len | ||
export const handleServerResponseError = (response, status, message) => response.status(status).send({ | ||
status: 'error', | ||
message | ||
}); | ||
|
||
export const handleServerError = (res, error) => { | ||
logger().error(error); | ||
return res.status(500).send({ | ||
status: 'error', | ||
error: 'Internal Server Error' | ||
}); | ||
}; | ||
|
||
/** | ||
* @function hashPassword | ||
* @param {string} password password to be hashed | ||
* @description hashes a password with bcrypt | ||
* @returns {string} password hash form | ||
*/ | ||
export const hashPassword = async (password) => { | ||
const saltRounds = process.env.SALT; | ||
const hash = await bcrypt.hash(password, parseInt(saltRounds, 10)); | ||
return hash; | ||
}; | ||
|
||
/** | ||
* @function isPassword | ||
* @param {string} password in ordinary form | ||
* @param {string} hash password hash form | ||
* @description checks if a password corresponds with saved hash in db | ||
* @returns {boolean} true if correct of false if incorrect | ||
*/ | ||
export const isPassword = (password, hash) => bcrypt.compareSync(password, hash); | ||
|
||
/** | ||
* createToken | ||
* @param {Number} id user id gotten from DATABASE_URL | ||
* @description creates new jwt token for authentication | ||
* @returns {String} newly created jwt | ||
*/ | ||
export const createToken = (id) => { | ||
const token = jwt.sign( | ||
{ | ||
id | ||
}, | ||
process.env.SECRET, { expiresIn: '7d' } | ||
); | ||
return token; | ||
}; | ||
|
||
/** | ||
* @method hasToken | ||
* @param {*} req | ||
* @param {*} res | ||
* @param {*} next | ||
* @returns {Object} response object | ||
*/ | ||
export const hasToken = (req, res, next) => { | ||
const token = req.body.token || req.headers['x-access-token']; | ||
if (token) { | ||
jwt.verify(token, process.env.SECRET, (err, decoded) => { | ||
if (err) { | ||
return res.status(403).send({ | ||
success: false, | ||
message: err | ||
}); | ||
} | ||
req.decoded = decoded; | ||
return next(); | ||
}); | ||
} else { | ||
return res.status(403).send({ | ||
message: 'You have to be loggedin first' | ||
}); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import Joi from '@hapi/joi'; | ||
import { handleServerResponseError } from './utils'; | ||
|
||
/** | ||
* @function | ||
* @param {*} req | ||
* @param {*} res | ||
* @param {*} next | ||
* @description validates signup input | ||
* @returns {Response | RequestHandler} error or request handler | ||
*/ | ||
const signupInput = (req, res, next) => { | ||
const { | ||
firstname, lastname, email, password | ||
} = req.body; | ||
const schema = Joi.object().keys({ | ||
firstname: Joi.string().required(), | ||
lastname: Joi.string().required(), | ||
email: Joi.string().trim().email().required(), | ||
password: Joi.string().min(8).required() | ||
}); | ||
const result = Joi.validate({ | ||
firstname, lastname, email, password | ||
}, schema); | ||
if (result.error) { | ||
return handleServerResponseError(res, 401, result.error.details[0].message); | ||
} | ||
return next(); | ||
}; | ||
|
||
export default { | ||
validateSignup: signupInput | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
|
||
import { Pool } from 'pg'; | ||
import { logger } from '../helpers/utils'; | ||
|
||
const dotenv = require('dotenv'); | ||
|
||
dotenv.config(); | ||
|
||
const pool = new Pool({ | ||
connectionString: process.env.DATABASE_URL | ||
}); | ||
|
||
pool.on('connect', () => { | ||
logger().info('connected to the db'); | ||
}); | ||
|
||
/** | ||
* Create Tables | ||
* @returns {*} void | ||
*/ | ||
export const createBookingTable = async () => { | ||
const client = await pool.connect(); | ||
const queryText = ` | ||
CREATE TABLE IF NOT EXISTS | ||
Bookings( | ||
id SERIAL PRIMARY KEY, | ||
user_id INTEGER NOT NULL, | ||
trip_id INTEGER NOT NULL, | ||
created_on TIMESTAMP, | ||
modified_date TIMESTAMP | ||
FOREIGN KEY (user_id) REFERENCES User (id) ON DELETE CASCADE | ||
FOREIGN KEY (trip_id) REFERENCES Trip (id) ON DELETE CASCADE | ||
)`; | ||
try { | ||
const response = await client.query(queryText); | ||
logger().info(response); | ||
} catch (error) { | ||
logger().error(error); | ||
} finally { | ||
client.release(); | ||
} | ||
}; | ||
|
||
/** | ||
* Drop Tables | ||
* @returns {*} void | ||
*/ | ||
export const dropBookingTable = async () => { | ||
const client = await pool.connect(); | ||
const queryText = 'DROP TABLE IF EXISTS Bookings'; | ||
try { | ||
const response = await client.query(queryText); | ||
logger().info(response); | ||
} catch (error) { | ||
logger().error(error); | ||
} finally { | ||
client.release(); | ||
} | ||
}; | ||
|
||
pool.on('remove', () => { | ||
logger().info('client removed'); | ||
process.exit(0); | ||
}); |
Oops, something went wrong.