Skip to content

Commit

Permalink
Merge 5496634 into 9b39eea
Browse files Browse the repository at this point in the history
  • Loading branch information
deschantkn authored Jun 17, 2019
2 parents 9b39eea + 5496634 commit 7b2f774
Show file tree
Hide file tree
Showing 13 changed files with 272 additions and 40 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"scripts": {
"dev": "nodemon --exec babel-node src/index.js",
"build": "babel src --out-dir dist",
"serve": "node dist/index.js",
"start": "node dist/index.js",
"test": "nyc --reporter=html --reporter=text mocha ./test/*.js --timeout 80000 --exit --require @babel/register --require regenerator-runtime",
"coverage": "nyc report --reporter=text-lcov | coveralls",
Expand Down
64 changes: 60 additions & 4 deletions src/api/controllers/articlesController.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import articles from '../../helpers/articlesHelper';
import models from '../../sequelize/models';

const { article, User } = models;
const { Article, User } = models;

/**
* @Author - Audace Uhiriwe
Expand Down Expand Up @@ -49,7 +49,7 @@ class articlesController {
const { slug } = req.params;

// @check if the article's slug exist
const result = await article.findOne({ where: { slug } });
const result = await Article.findOne({ where: { slug } });
if (result === null) return res.status(404).send({ error: 'This Slug Not found!' });

const oneArticle = await articles.getOneSlug(slug);
Expand Down Expand Up @@ -83,7 +83,7 @@ class articlesController {
const newSlug = await articles.createSlug(updateSlug.title);

// @Updating the article's data in Database
await article.update(
await Article.update(
{
slug: newSlug,
title: updateSlug.title,
Expand All @@ -105,10 +105,66 @@ class articlesController {
const { slug } = req.params;

// @delete an article in Database
await article.destroy({ where: { slug } });
await Article.destroy({ where: { slug } });

// @returning the response
res.status(200).send({ message: 'Article deleted successfully!' });
}

static async likeArticle(req, res) {
const { articleId } = req.params;

try {
// Find the article
const query = await Article.findAll({ where: { id: articleId } });

if (!query[0]) {
return res.status(404).json({ message: `Article with id: ${articleId} not found` });
}

const { dataValues: foundArticle } = query[0];

// Increment like field by one
foundArticle.likes += 1;

// Update table
await Article.update(
foundArticle,
{ where: { id: articleId } }
);
} catch (error) {
return res.status(500).json({ error: `${error}` });
}

return res.status(200).json({ message: 'OK' });
}

static async dislikeArticle(req, res) {
const { articleId } = req.params;

try {
// Find the article
const query = await Article.findAll({ where: { id: articleId } });

if (!query[0]) {
return res.status(404).json({ message: `Article with id: ${articleId} not found` });
}

const { dataValues: foundArticle } = query[0];

// Decrement like field by one
foundArticle.dislikes += 1;

// Update table
await Article.update(
foundArticle,
{ where: { id: articleId } }
);
} catch (error) {
return res.status(500).json({ error: `${error}` });
}

return res.status(200).json({ message: 'OK' });
}
}
export default articlesController;
23 changes: 14 additions & 9 deletions src/api/routes/articlesRouter.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
import { Router } from 'express';
import articlesController from '../controllers/articlesController';
import isAuth from '../../middleware/auth';
import Auth from '../../middleware/auth';
import check from '../../middleware/checkOwner';
import validate from '../../middleware/validations';

const articlesRouter = Router();
const {
createArticle, getAllArticle, getOneArticle, updateArticle, deleteArticle
createArticle,
getAllArticle,
getOneArticle,
updateArticle,
deleteArticle,
likeArticle,
dislikeArticle,
} = articlesController;
const { verifyToken } = Auth;

articlesRouter.post('/', isAuth.verifyToken, validate.createValidations, createArticle);

articlesRouter.post('/', verifyToken, validate.createValidations, createArticle);
articlesRouter.get('/', getAllArticle);

articlesRouter.get('/:slug', getOneArticle);

articlesRouter.put('/:slug', isAuth.verifyToken, check.articleOwner, validate.updateValidations, updateArticle);

articlesRouter.delete('/:slug', isAuth.verifyToken, check.articleOwner, deleteArticle);
articlesRouter.put('/:slug', verifyToken, check.articleOwner, validate.updateValidations, updateArticle);
articlesRouter.delete('/:slug', verifyToken, check.articleOwner, deleteArticle);
articlesRouter.post('/like/:articleId', verifyToken, likeArticle);
articlesRouter.post('/dislike/:articleId', dislikeArticle);

export default articlesRouter;
10 changes: 5 additions & 5 deletions src/helpers/articlesHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import slug from 'slug';
import uniqid from 'uniqid';
import models from '../sequelize/models';

const { article, User } = models;
const { Article, User } = models;

/**
* @description Helpers for articles
Expand All @@ -30,13 +30,13 @@ class ArticlesHelper {
} = req.body;
const { id } = req.user;
const newSlug = this.createSlug(title);
const { dataValues } = await article.create({
const { dataValues } = await Article.create({
slug: newSlug,
title,
description,
body,
tagList: tagList.split(','),
authorid: parseInt(id, 10)
authorId: parseInt(id, 10)
});
const userInfo = await this.getUserInfo(id);
const { username, bio, image } = userInfo;
Expand All @@ -51,7 +51,7 @@ class ArticlesHelper {
}

static async getAllArticle() {
const result = await article.findAll({
const result = await Article.findAll({
include: [{
as: 'author',
model: User,
Expand All @@ -63,7 +63,7 @@ class ArticlesHelper {
}

static async getOneSlug(newSlug) {
const result = await article.findOne({
const result = await Article.findOne({
where: { slug: newSlug },
include: [{
as: 'author',
Expand Down
6 changes: 3 additions & 3 deletions src/middleware/checkOwner.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable valid-jsdoc */
import models from '../sequelize/models';

const { article, User } = models;
const { Article, User } = models;

/**
* @description Helpers for articles
Expand All @@ -21,11 +21,11 @@ class checkOwner {
if (dataValues.verified === false) return res.status(403).send({ error: 'Please Verify your account, first!' });

// @check if the article's slug exist
const result = await article.findOne({ where: { slug } });
const result = await Article.findOne({ where: { slug } });
if (result === null) return res.status(404).send({ error: 'Slug Not found!' });

// @check if the user who logged in - is the owner of that slug
const response = await article.findOne({ where: { slug, authorid: id } });
const response = await Article.findOne({ where: { slug, authorId: id } });
if (!response) return res.status(403).send({ error: 'Sorry!, you are not the owner of this slug' });

req.foundArticle = response.dataValues;
Expand Down
2 changes: 1 addition & 1 deletion src/sequelize/migrations/20190613355309-create-article.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ module.exports = {
type: Sequelize.STRING,
allowNull: true
},
authorid: {
authorId: {
type: Sequelize.INTEGER,
onUpdate: 'CASCADE',
onDelete: 'CASCADE',
Expand Down
13 changes: 13 additions & 0 deletions src/sequelize/migrations/20190617104354-rename-articles-table.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export default {
up: queryInterface => queryInterface.renameTable('articles', 'Articles'),

down: () => {
/*
Add reverting commands here.
Return a promise to correctly handle asynchronicity.
Example:
return queryInterface.dropTable('users');
*/
}
};
13 changes: 13 additions & 0 deletions src/sequelize/migrations/20190617122836-rename-authorid.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export default {
up: queryInterface => queryInterface.renameColumn('Articles', 'authorid', 'authorId'),

down: () => {
/*
Add reverting commands here.
Return a promise to correctly handle asynchronicity.
Example:
return queryInterface.dropTable('users');
*/
}
};
14 changes: 14 additions & 0 deletions src/sequelize/migrations/20190617151017-add-likes-field.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

export default {
up: (queryInterface, Sequelize) => queryInterface.addColumn('Articles', 'likes', Sequelize.INTEGER),

down: () => {
/*
Add reverting commands here.
Return a promise to correctly handle asynchronicity.
Example:
return queryInterface.dropTable('users');
*/
}
};
14 changes: 14 additions & 0 deletions src/sequelize/migrations/20190617151105-add-dislikes-field.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

export default {
up: (queryInterface, Sequelize) => queryInterface.addColumn('Articles', 'dislikes', Sequelize.INTEGER),

down: () => {
/*
Add reverting commands here.
Return a promise to correctly handle asynchronicity.
Example:
return queryInterface.dropTable('users');
*/
}
};
24 changes: 16 additions & 8 deletions src/sequelize/models/article.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable func-names */
module.exports = (sequelize, DataTypes) => {
const article = sequelize.define(
'article',
const Article = sequelize.define(
'Article',
{
slug: {
type: DataTypes.STRING,
Expand All @@ -27,22 +27,30 @@ module.exports = (sequelize, DataTypes) => {
type: DataTypes.TEXT,
allowNull: true
},
authorid: {
authorId: {
type: DataTypes.INTEGER,
allowNull: false
}
},
likes: {
type: DataTypes.INTEGER,
default: 0
},
dislikes: {
type: DataTypes.INTEGER,
default: 0
},
},
{}
);
article.associate = function (models) {
Article.associate = function (models) {
// associations can be defined here
article.belongsTo(models.User, {
Article.belongsTo(models.User, {
as: 'author',
foreignKey: 'authorid',
foreignKey: 'authorId',
targetKey: 'id',
onUpdate: 'CASCADE',
onDelete: 'CASCADE'
});
};
return article;
return Article;
};
4 changes: 2 additions & 2 deletions src/sequelize/models/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ module.exports = (sequelize, DataTypes) => {

User.associate = function (models) {
// associations can be defined here
User.hasMany(models.article, {
User.hasMany(models.Article, {
as: 'author',
foreignKey: 'authorid',
foreignKey: 'authorId',
onDelete: 'CASCADE',
onUpdate: 'CASCADE'
});
Expand Down
Loading

0 comments on commit 7b2f774

Please sign in to comment.