Skip to content

Commit

Permalink
Merge f66bfe5 into f07deb1
Browse files Browse the repository at this point in the history
  • Loading branch information
LordUche committed Mar 18, 2019
2 parents f07deb1 + f66bfe5 commit fa12dd7
Show file tree
Hide file tree
Showing 13 changed files with 484 additions and 182 deletions.
41 changes: 30 additions & 11 deletions package-lock.json

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

48 changes: 19 additions & 29 deletions server/controllers/auth-controller.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import '@babel/polyfill';
import db from '../models';
import { registerSchema } from '../utils/validators';
import { registerSchema, loginSchema } from '../utils/validators';
import env from '../config/env-config';
import mailer from '../utils/mailer';
import {
Expand All @@ -11,7 +10,8 @@ import {
comparePassword,
generateToken,
generateVerificationLink,
verifyToken
verifyToken,
dbErrorResponse
} from '../utils/helpers';

const { User } = db;
Expand Down Expand Up @@ -66,15 +66,7 @@ class UsersController {
successResponse(res, { user, emailSent: false }, 201);
});
} catch (err) {
const errors = err.errors
? err.errors.map(e => {
if (e.validatorKey === 'not_unique') {
return `${e.path} already exists`;
}
return e.message;
})
: [err.message];
errorResponse(res, errors, 409);
dbErrorResponse(res, err);
}
})
.catch(({ details }) => {
Expand Down Expand Up @@ -138,23 +130,21 @@ class UsersController {
static async login(req, res) {
const { email, password } = req.body;
try {
if (!(email && password)) {
return errorResponse(res, 'missing Email/Password', 400);
}
const rows = await User.findOne({ where: { email } });
if (!rows) {
return errorResponse(res, 'incorrect Email/Password', 400);
}
const { id, username, hash } = rows.dataValues;
if (!comparePassword(password, hash)) {
return errorResponse(res, 'incorrect Email/Password', 400);
}
const token = generateToken({ id, username });
rows.dataValues.token = token;
delete rows.dataValues.hash;
successResponse(res, { user: rows.dataValues }, 200);
} catch (error) {
return errorResponse(res, error.message);
await validate(req.body, loginSchema);
User.findOne({ where: { email } })
.then(({ dataValues: user }) => {
if (comparePassword(password, user.hash)) {
user.token = generateToken({
id: user.id,
username: user.username
});
delete user.hash;
successResponse(res, { user });
} else errorResponse(res, 'Incorrect password');
})
.catch(err => dbErrorResponse(res, err));
} catch (err) {
validationErrorResponse(res, err.details);
}
}
}
Expand Down
66 changes: 42 additions & 24 deletions server/controllers/recipe-controller.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import db from '../models';
import {
successResponse,
errorResponse,
validate,
validationErrorResponse
validationErrorResponse,
dbErrorResponse,
stringArrayToLowerCase
} from '../utils/helpers';
import { recipeSchema } from '../utils/validators';
import { recipeSchema, tagSchema } from '../utils/validators';
import slugifyTitle from '../utils/slugify';

const { Recipe } = db;
Expand All @@ -22,38 +23,55 @@ class RecipeController {
* @static
* @param {*} req
* @param {*} res
* @param {Funtion} next
* @memberof RecipeController
* @returns {undefined}
*/
static async create(req, res) {
const {
title,
ingredients,
steps,
cookingTime,
preparationTime
} = req.body;
const { body, user } = req;
try {
await validate(req.body, recipeSchema);
const slug = slugifyTitle(title);
Recipe.create({
userId: req.user.id,
title,
slug,
ingredients,
steps,
cookingTime,
preparationTime
})
.then(({ dataValues }) => {
successResponse(res, { recipe: dataValues }, 201);
const slug = slugifyTitle(body.title);
Recipe.create({ ...body, slug, userId: user.id })
.then(({ dataValues: recipe }) => {
successResponse(res, { recipe }, 201);
})
.catch(err => errorResponse(res, err, 400));
.catch(err => dbErrorResponse(res, err));
} catch (error) {
validationErrorResponse(res, error.details);
}
}

/**
* Tag recipe controller
* @param {Request} req request object
* @param {Response} res response object
* @returns {undefined}
*/
static async tag(req, res) {
const { user, recipe, body } = req;
try {
await validate(body, tagSchema);
Recipe.update(
{
tags: [
...new Set([
...stringArrayToLowerCase(body.tags),
...stringArrayToLowerCase(recipe.tags || [])
])
]
},
{ where: { id: recipe.id, userId: user.id }, returning: true }
)
.then(data => {
successResponse(res, { recipe: data[1][0] });
})
.catch(err => {
dbErrorResponse(res, err);
});
} catch (err) {
return validationErrorResponse(res, err.details);
}
}
}

export default RecipeController;
21 changes: 7 additions & 14 deletions server/middlewares/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import db from '../models';
import { errorResponse, verifyToken } from '../utils/helpers';
import { errorResponse, verifyToken, getBearerToken } from '../utils/helpers';

const { User } = db;
/**
*Users endpoint middlewares
*Users endpoint middleware
*
* @export
* @class UsersMiddleware
Expand All @@ -19,23 +19,16 @@ export default class UsersMiddleware {
* @memberof UsersMiddleware
*/
static async validUser(req, res, next) {
const token = req.headers.authorization;
if (!token) {
return errorResponse(res, 'Token is not provided', 400);
}
try {
const decoded = await verifyToken(token, process.env.SECRET);
const data = await User.findOne({
const decoded = await verifyToken(getBearerToken(req));
const { dataValues: user } = await User.findOne({
where: { id: decoded.id }
});
if (!data) {
return errorResponse(res, 'User does not exist', 404);
}
delete data.dataValues.hash;
req.user = data.dataValues;
delete user.hash;
req.user = user;
return next();
} catch (error) {
return errorResponse(res, error, 401);
return errorResponse(res, 'Authentication failed', 401);
}
}
}
21 changes: 21 additions & 0 deletions server/middlewares/recipe-middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { dbErrorResponse, errorResponse } from '../utils/helpers';
import db from '../models';

const { Recipe } = db;

export const loadRecipe = (req, res, next) => {
const { params } = req;
Recipe.findOne({ where: { slug: params.slug } })
.then(({ dataValues: recipe }) => {
req.recipe = recipe;
next();
})
.catch(err => dbErrorResponse(res, err));
};

export const isRecipeOwner = (req, res, next) => {
const { user, recipe } = req;
return user.id === recipe.userId
? next()
: errorResponse(res, 'You are not authorized', 403);
};
8 changes: 8 additions & 0 deletions server/migrations/20190315135503-add-tags-to-recipes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
up: (queryInterface, Sequelize) =>
queryInterface.addColumn('Recipes', 'tags', {
type: Sequelize.ARRAY(Sequelize.STRING),
defaultValue: []
}),
down: queryInterface => queryInterface.removeColumn('Recipes', 'tags')
};
Loading

0 comments on commit fa12dd7

Please sign in to comment.