Skip to content

Commit

Permalink
Merge pull request #56 from andela/166840926-article-comments
Browse files Browse the repository at this point in the history
166840926 article comments
  • Loading branch information
olorunwalawrence authored and codexempire committed Aug 21, 2019
2 parents a7ef34b + b340526 commit 1b779a9
Show file tree
Hide file tree
Showing 16 changed files with 659 additions and 87 deletions.
5 changes: 2 additions & 3 deletions src/controllers/article.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import db from '../database/models';
import Pagination from '../helpers/pagination';
import { articleTag } from '../helpers/tagArticle';

const { Report } = db;
/**
* @class UserController
*/
Expand Down Expand Up @@ -356,7 +355,7 @@ class ArticleController {
await articleTag(tag, publishedArticle.id);
return responseGenerator.sendSuccess(res, 201, publishedArticle);
} catch (error) {
return responseGenerator.sendError(res, 500, error.message);
return responseGenerator.sendError(response, 500, error.message);
}
}

Expand Down Expand Up @@ -409,7 +408,7 @@ class ArticleController {
description
};
try {
await BaseRepository.create(Report, options);
await BaseRepository.create(db.Report, options);
return responseGenerator.sendSuccess(
res,
201,
Expand Down
140 changes: 140 additions & 0 deletions src/controllers/comment.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/* eslint-disable require-jsdoc */
import models from '../database/models';
import commentHelpers from '../helpers/commentHelpers';
import Baserepository from '../repository/base.repository';
import responseGerator from '../helpers/responseGenerator';

const { Comments, User } = models;
const { updater } = commentHelpers;

class CommentsController {
static async getComments(req, res) {
const { articleId } = req.params;
try {
const getAllComent = await Baserepository.findAndCountAll(Comments, {
where: {
articleId
},
order: [['createdAt', 'DESC']],
include: [
{
model: User,
as: 'user',
attributes: ['id', 'username']
}
]
});
return responseGerator.sendSuccess(
res,
200,
getAllComent,
'Operation Successful'
);
} catch (e) {
return responseGerator.sendSuccess(
res,
500,
'There was a problem processing your request'
);
}
}

static async addComment(req, res) {
const { article } = req;
const { content } = req.body;
const userId = req.currentUser.id;

const userComment = {
content,
userId,
articleId: article.id
};
try {
const comment = await Baserepository.create(Comments, userComment);
return responseGerator.sendSuccess(
res,
201,
comment,
'Commented successfully'
);
} catch (error) {
return responseGerator.sendSuccess(
res,
500,
'There was a problem processing your request'
);
}
}

static async updateComment(req, res) {
try {
const commentExist = await Baserepository.find(Comments, {
where: {
id: req.params.commentId
}
});
if (!commentExist) {
return responseGerator.sendError(
res,
404,
'The specified comment is not found'
);
}

const reqData = {
content: req.body.content,
commentId: req.params.commentId
};

return updater(res, Comments, reqData, 'Comment');
} catch (e) {
return responseGerator.sendError(
res,
500,
'there is an internal server error'
);
}
}

/**
*
*
* @static
* @param {*} request - - express request parameter
* @param {*} response - - express response parameter
* @returns {object} - - article object
* @memberof ArticleController
*/
static async deleteComment(request, response) {
const { commentId } = request.params;
const { id, role } = request.currentUser;
try {
const comment = await Baserepository.findOneByField(Comments, {
id: commentId
});

if (comment) {
if (comment.userId !== id && role !== 'superadmin') {
return responseGerator.sendError(
response,
403,
'Unauthorized: You cannot delete this comment'
);
}

await Baserepository.remove(Comments, { id: commentId });
}

return responseGerator.sendSuccess(
response,
200,
null,
'Comment successfully deleted'
);
} catch (error) {
return responseGerator.sendError(response, 500, error.message);
}
}
}

export default CommentsController;
46 changes: 46 additions & 0 deletions src/database/migrations/20190716074627-create-comment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
module.exports = {
up: (queryInterface, Sequelize) =>
queryInterface.createTable(
'Comments',
{
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
content: {
type: Sequelize.STRING,
allowNull: false
},
articleId: {
type: Sequelize.INTEGER,
onDelete: 'CASCADE',
references: {
model: 'Articles',
key: 'id',
as: 'articleId'
}
},
userId: {
type: Sequelize.INTEGER,
onDelete: 'CASCADE',
references: {
model: 'Users',
key: 'id',
as: 'userId'
}
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
},
{ freezeTableName: true }
),
down: queryInterface => queryInterface.dropTable('Comments')
};
50 changes: 22 additions & 28 deletions src/database/models/comment.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,28 @@
const comments = (sequelize, DataTypes) => {
const Comments = sequelize.define(
'Comments',
{
content: {
type: DataTypes.STRING,
allowNull: false
},
userId: {
type: DataTypes.INTEGER,
allowNull: false
},
articleId: {
type: DataTypes.INTEGER,
allowNull: false
},
createdAt: {
allowNull: false,
defaultValue: new Date(),
type: DataTypes.DATE
},
updatedAt: {
allowNull: false,
defaultValue: new Date(),
type: DataTypes.DATE
}
const Comments = sequelize.define('Comments', {
content: {
type: DataTypes.STRING,
allowNull: false
},
{
freezeTableName: true
userId: {
type: DataTypes.INTEGER,
allowNull: false
},
articleId: {
type: DataTypes.INTEGER,
allowNull: false
},
createdAt: {
allowNull: false,
defaultValue: new Date(),
type: DataTypes.DATE
},
updatedAt: {
allowNull: false,
defaultValue: new Date(),
type: DataTypes.DATE
}
);
});

Comments.associate = models => {
Comments.belongsTo(models.User, {
Expand Down
1 change: 1 addition & 0 deletions src/helpers/passport/callback.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const callback = async (accessToken, refreshToken, payload, done) => {
};

export const respondCallback = (req, res) => {
console.log(req.user);
if (req.user) {
const {
user: { token }
Expand Down
3 changes: 2 additions & 1 deletion src/middleware/article.middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import responseGenerator from '../helpers/responseGenerator';
export const articleExist = async (req, res, next) => {
const { articleId } = req.params || req.body;
try {
const findArticle = await Baserepository.findOneByField(db.Article, {

const findArticle = await Baserepository.findOneByField(db.Article, {
id: articleId
});

Expand Down
49 changes: 46 additions & 3 deletions src/middleware/validation.schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ const followeeId = Joi.number()
.integer()
.required();

const articleId = Joi.number().required()
const articleId = Joi.number()
.required()
.integer()
.required();

Expand Down Expand Up @@ -81,6 +82,29 @@ const verifyTokenSchema = {
}
};

const commentSchema = {
body: {
content: Joi.string()
.min(3)
.trim()
.required()
.error(
new Error(
'Please provide body for your comment with minimum of 3 characters'
)
)
},
params: {
articleId: Joi.number()
.integer()
.positive()
.required()
.error(
new Error('Invalid CommentID, commentID must be a positive integer')
)
}
};

const updateProfileSchema = {
body: {
avatar: Joi.string()
Expand Down Expand Up @@ -135,6 +159,18 @@ const articleParamsSchema = {
}
};

const commentParamSchesma = {
params: {
commentId: Joi.number()
.integer()
.positive()
.required()
.error(
new Error('Invalid comment ID. comment ID must be a positive integer')
)
}
};

const updateArticleSchema = {
params: {
articleId: Joi.number()
Expand Down Expand Up @@ -405,9 +441,16 @@ export default [
schema: articleParamsSchema
},
{ route: '/:articleId/report', method: 'post', schema: reportArticle },

{ route: '/:articleId/comments/:commentId/like',

{
route: '/:articleId/comments/:commentId/like',
method: 'post',
schema: commentLikeSchema
},
{
route: '/:articleId',
method: 'post',
schema: commentSchema
// commentParamSchesma
}
];
12 changes: 12 additions & 0 deletions src/repository/base.repository.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable require-jsdoc */
import dotenv from 'dotenv';
import Sequelize from 'sequelize';

Expand Down Expand Up @@ -329,6 +330,17 @@ class BaseRepository {
{ replacements: { articleId }, type: sequelize.QueryTypes.SELECT }
);
}

/*
* @static
* @param {*} model
* @param {*} options
* @returns {object} - returns an database object
* @memberof BaseRepository
*/
static find(model, options) {
return model.findOne(options);
}
}

export default BaseRepository;
2 changes: 2 additions & 0 deletions src/routes/v1/article.route.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import articleMiddleware from '../../middleware/article.middleware';
import validationMiddleware from '../../middleware/validation.middleware';
import paginationValidations from '../../middleware/pagination.validation';



const validateRequest = validationMiddleware();

const router = Router();
Expand Down
Loading

0 comments on commit 1b779a9

Please sign in to comment.