Skip to content

Commit

Permalink
#162414275 Perform CRUD operation on comment (#31)
Browse files Browse the repository at this point in the history
* feat(comment): perform crud operation on comment

- create comment controller
- create routes for CRUD
- create method for CRUD
- implement crud on comment
- write test

finishes: 162414275
  • Loading branch information
tejiri4 authored and seunkoko committed Jan 22, 2019
1 parent f6be691 commit 74a3ccb
Show file tree
Hide file tree
Showing 17 changed files with 569 additions and 59 deletions.
10 changes: 6 additions & 4 deletions server/controllers/ArticleController.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class ArticleController {
banner,
tagsList,
} = req.body;
const tagsArray = tagsList ? Util.createArrayOfStrings(tagsList) : '';
const tagsArray = tagsList ? Util.createArrayOfStrings(tagsList) : [];

const articleData = {
userId,
Expand All @@ -42,16 +42,18 @@ class ArticleController {
isReported: false,
};

const article = await Article.create(articleData);
let article = await Article.create(articleData);

if (article) {
article = article.toJSON();
article.tags = articleData.tagsList;
const {
createdAt,
updatedAt
} = article;
await TagHelper.findOrAddTag(article.id, tagsArray);
articleData.createdAt = Util.formatDate(createdAt);
articleData.updatedAt = Util.formatDate(updatedAt);
article.createdAt = Util.formatDate(createdAt);
article.updatedAt = Util.formatDate(updatedAt);

return response(
res, 201, 'success',
Expand Down
211 changes: 211 additions & 0 deletions server/controllers/CommentController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
import db from '../models';
import response from '../helpers/response';


const { Article, Comment, User } = db;

/**
* @class CommentController
*/
class CommentController {
/**
*
* @description Allow user to comment on an article
* @static
* @param {*} req Express Request object
* @param {*} res Express Response object
* @returns {object} Json response
* @memberof CommentController
*/
static async addComment(req, res) {
try {
const { userId } = req.user;
const { content } = req.body;
const { slug } = req.params;
if (!content) {
return response(res, 400, 'failure', 'Enter a comment', null, null);
}
const articleFound = await Article.findOne({
where: {
slug
}
});
if (articleFound) {
const commentCreated = await Comment.create({
content,
userId,
articleId: slug
});
if (commentCreated) {
return response(res, 201, 'success', 'Comment created', null, commentCreated.dataValues);
}
} else {
return response(res, 404, 'failure', 'Article with the id not found', null, null);
}
} catch (error) {
return response(
res, 500, 'failure',
'server error',
{ message: 'Something went wrong on the server' }, null
);
}
}

/**
*
* @description Retrive all comments for an article
* @static
* @param {*} req Express Request object
* @param {*} res Express Response object
* @returns {object} Json response
* @memberof CommentController
*/
static async getComments(req, res) {
try {
const { slug } = req.params;
const commentsQuery = await Comment.findAll({
include: [{
model: User,
attributes: ['userName', 'img']
}],
where: {
articleId: slug
},
});
if (commentsQuery.length === 0) {
return response(res, 404, 'failure', 'Comment with the articleId not found', null, null);
}
const comments = [];
commentsQuery.map(comment => comments.push(comment.dataValues));
return response(res, 200, 'success', 'Comment found', null, comments);
} catch (error) {
return response(
res, 500, 'failure',
'server error',
{ message: 'Something went wrong on the server' }, null
);
}
}

/**
*
* @description Retrive all comments for an article
* @static
* @param {*} req Express Request object
* @param {*} res Express Response object
* @returns {object} Json response
* @memberof CommentController
*/
static async getSingleComments(req, res) {
try {
const { slug, commentId } = req.params;
const comment = await Comment.findAndCount({
include: [{
model: User,
attributes: ['userName', 'img']
}],
where: {
articleId: slug,
id: commentId
},
});
if (comment) {
return response(res, 200, 'success', 'Comment found', null, comment.dataValues);
}
} catch (error) {
if (error.name === 'SequelizeDatabaseError') {
return response(res, 404, 'failure', 'Comment not found', null, null);
}
return response(
res, 500, 'failure',
'server error',
{ message: 'Something went wrong on the server' }, null
);
}
}

/**
*
* @description Update a comment
* @static
* @param {*} req Express Request object
* @param {*} res Express Response object
* @returns {object} Json response
* @memberof CommentController
*/
static async updateComment(req, res) {
try {
const { userId } = req.user;
const { slug, commentId } = req.params;
const { content } = req.body;
const getCommentUpdate = await Comment.findOne({
where: {
id: commentId
}
});
if (getCommentUpdate.dataValues.articleId !== slug) {
return response(res, 404, 'failure', 'Comment not found for article id', null, null);
}
if (getCommentUpdate.dataValues.userId !== userId) {
return response(res, 403, 'failure', 'You are not allowed to update another user\'s comment', null, null);
}
const updateComment = await getCommentUpdate.update({
content
});
if (updateComment) {
return response(res, 200, 'success', 'Comment updated', null, updateComment.dataValues);
}
} catch (error) {
if (error.name === 'SequelizeDatabaseError') {
return response(res, 404, 'failure', 'Comment not found', null, null);
}
return response(
res, 500, 'failure',
'server error',
{ message: 'Something went wrong on the server' }, null
);
}
}

/**
*
* @description Delete a comment
* @static
* @param {*} req Express Request object
* @param {*} res Express Response object
* @returns {object} Json response
* @memberof CommentController
*/
static async deleteComment(req, res) {
try {
const { userId } = req.user;
const { slug: articleId, commentId } = req.params;
const getCommentDelete = await Comment.findOne({
where: {
id: commentId
}
});
if (getCommentDelete.dataValues.articleId !== articleId) {
return response(res, 404, 'failure', 'Comment not found for article id', null, null);
}
if (getCommentDelete.dataValues.userId !== userId) {
return response(res, 403, 'failure', 'You are not allowed to delete another user\'s comment', null, null);
}
const deleteComment = await getCommentDelete.destroy();
if (deleteComment) {
return response(res, 200, 'success', 'Comment deleted', null, null);
}
} catch (error) {
if (error.name === 'SequelizeDatabaseError') {
return response(res, 404, 'failure', 'Comment not found', null, null);
}
return response(
res, 500, 'failure',
'server error',
{ message: 'Something went wrong on the server' }, null
);
}
}
}

export default CommentController;
14 changes: 6 additions & 8 deletions server/helpers/response.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,13 @@
*/

export default (res, code, status, message, error, payload) => {
const responseData = error ? {
message,
error,
} : {
message,
payload
};
res.status(code).json({
status,
data: responseData
data: {
statusCode: code,
message,
error,
payload
}
});
};
2 changes: 1 addition & 1 deletion server/middlewares/AuthMiddleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class AuthMiddleware {
if (!authorization) {
return response(
res, 401, 'failure', 'authentication error',
{ message: 'You are not logged in, Token is needed!' },
{ message: 'You are not logged in.' },
null
);
}
Expand Down
12 changes: 12 additions & 0 deletions server/middlewares/ContentValidator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import response from '../helpers/response';

const ContentValidate = (req, res, next) => {
const { content } = req.body;
if (content.trim().length > 0) {
next();
} else {
return response(res, 400, 'failure', 'Comment content must not be empty', null, null);
}
};

export default ContentValidate;
2 changes: 1 addition & 1 deletion server/migrations/20190111130326-create-comment.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default {
allowNull: false
},
articleId: {
type: Sequelize.UUID,
type: Sequelize.STRING,
allowNull: false
},
createdAt: {
Expand Down
14 changes: 0 additions & 14 deletions server/migrations/20190115104506-add-userId-constraint-Comments.js

This file was deleted.

14 changes: 14 additions & 0 deletions server/routes/api/comment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Router } from 'express';
import CommentController from '../../controllers/CommentController';
import AuthMiddleware from '../../middlewares/AuthMiddleware';
import ContentValidate from '../../middlewares/ContentValidator';

const commentRoutes = Router();

commentRoutes.post('/articles/:slug/comments', AuthMiddleware.checkIfUserIsAuthenticated, ContentValidate, CommentController.addComment);
commentRoutes.get('/articles/:slug/comments', AuthMiddleware.checkIfUserIsAuthenticated, CommentController.getComments);
commentRoutes.get('/articles/:slug/comments/:commentId', AuthMiddleware.checkIfUserIsAuthenticated, CommentController.getSingleComments);
commentRoutes.put('/articles/:slug/comments/:commentId', AuthMiddleware.checkIfUserIsAuthenticated, CommentController.updateComment);
commentRoutes.delete('/articles/:slug/comments/:commentId', AuthMiddleware.checkIfUserIsAuthenticated, CommentController.deleteComment);

export default commentRoutes;
2 changes: 2 additions & 0 deletions server/routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import { Router } from 'express';
import userRoutes from './api/user';
import authRoutes from './api/auth';
import articleRoutes from './api/article';
import commentRoutes from './api/comment';

const routes = Router();

routes.use(userRoutes);
routes.use(authRoutes);
routes.use(articleRoutes);
routes.use(commentRoutes);

export default routes;
1 change: 0 additions & 1 deletion server/seeders/20190111141811-roles.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,5 @@ export default {
],
{}
),

down: (queryInterface, Sequelize) => queryInterface.bulkDelete('Roles', null, {})
};
Loading

0 comments on commit 74a3ccb

Please sign in to comment.