-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(comment): perform crud operation on comment
- create comment controller - create routes for CRUD - create method for CRUD - write test finishes: 162414275 feat(comment): fix travis ci feat(comment): implement feedback feat(comment): implement feedback from Timi feat(comment): add new line to demo user feat(comment): implement feedback from Onyeka feat(comment): implement slug on route feat(comment): implement crud on comment
- Loading branch information
Showing
20 changed files
with
584 additions
and
59 deletions.
There are no files selected for viewing
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
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,169 @@ | ||
import db from '../models'; | ||
import response from '../helpers/response'; | ||
|
||
const { Article, Comment } = 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, null); | ||
} | ||
} 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({ | ||
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 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, 401, '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, null); | ||
} | ||
} catch (error) { | ||
if (error.name === 'SequelizeDatabaseError') { | ||
return response(res, 404, 'failure', 'Comment with the commentId 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, 401, '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 with the commentId not found', null, null); | ||
} | ||
return response( | ||
res, 500, 'failure', | ||
'server error', | ||
{ message: 'Something went wrong on the server' }, null | ||
); | ||
} | ||
} | ||
} | ||
|
||
export default CommentController; |
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,23 @@ | ||
/** | ||
* | ||
* @description Method to send response in a generic format. | ||
* @param {*} res Express Response object | ||
* @param {number} code HTTP response status code | ||
* @param {string} status 'success' || 'failure' | ||
* @param {string} message Message to user | ||
* @param {object} error (optional) Error object | ||
* @param {object} payload (optional) Payload data to return with the response | ||
* @returns {object} Json response | ||
*/ | ||
|
||
export default (res, code, status, message, error, payload) => { | ||
res.status(code).json({ | ||
status, | ||
data: { | ||
statusCode: code, | ||
message, | ||
error, | ||
payload | ||
} | ||
}); | ||
}; |
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,53 @@ | ||
import TokenManager from '../helpers/TokenManager'; | ||
import response from '../helpers/response'; | ||
/** | ||
* @class AuthMiddleware | ||
* @description class contains function for implementing Authentication middleware | ||
*/ | ||
class AuthMiddleware { | ||
/** | ||
* @static | ||
* @description a middleware function checking if a user is authenticated | ||
* @param {object} req HTTP request object | ||
* @param {object} res HTTP response object | ||
* @param {function} next next middleware function | ||
* @returns {object} returns error message if user is not authenticated | ||
*/ | ||
static checkIfUserIsAuthenticated(req, res, next) { | ||
try { | ||
const { authorization } = req.headers; | ||
if (!authorization) { | ||
return response( | ||
res, 401, 'failure', 'authentication error', | ||
{ message: 'You are not logged in, Token is needed!' }, | ||
null | ||
); | ||
} | ||
|
||
const token = authorization.split(' ')[1]; | ||
const decoded = TokenManager.verify(token); | ||
|
||
if (decoded) { | ||
req.user = decoded; | ||
return next(); | ||
} | ||
} catch (error) { | ||
const { name } = error; | ||
if (name === 'TokenExpiredError' || name === 'JsonWebTokenError') { | ||
return response( | ||
res, 401, 'failure', 'authentication error', | ||
{ message: 'Token is invalid, You need to log in again' }, | ||
null | ||
); | ||
} | ||
|
||
return response( | ||
res, 500, 'failure', | ||
'server error', | ||
{ message: 'Something went wrong on the server' }, null | ||
); | ||
} | ||
} | ||
} | ||
|
||
export default AuthMiddleware; |
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,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; |
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
14 changes: 0 additions & 14 deletions
14
server/migrations/20190115104506-add-userId-constraint-Comments.js
This file was deleted.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
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.put('/articles/:slug/comments/:commentId', AuthMiddleware.checkIfUserIsAuthenticated, CommentController.updateComment); | ||
commentRoutes.delete('/articles/:slug/comments/:commentId', AuthMiddleware.checkIfUserIsAuthenticated, CommentController.deleteComment); | ||
|
||
export default commentRoutes; |
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,8 +1,10 @@ | ||
import { Router } from 'express'; | ||
import userRoutes from './api/user'; | ||
import commentRoutes from './api/comment'; | ||
|
||
const routes = Router(); | ||
|
||
routes.use(userRoutes); | ||
routes.use(commentRoutes); | ||
|
||
export default routes; |
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,17 +1,19 @@ | ||
export default { | ||
up: (queryInterface, Sequelize) => queryInterface.bulkInsert( | ||
'Roles', | ||
[ | ||
{ | ||
id: '3ceb546e-054d-4c1d-8860-e27c209d4ae3', | ||
type: 'user', | ||
}, | ||
{ | ||
id: '3ceb546e-054d-4c1d-8860-e27c209d4ae4', | ||
type: 'admin' | ||
} | ||
], | ||
{}), | ||
up: (queryInterface, Sequelize) => | ||
queryInterface.bulkInsert( | ||
'Roles', | ||
[ | ||
{ | ||
id: '3ceb546e-054d-4c1d-8860-e27c209d4ae3', | ||
type: 'user' | ||
}, | ||
{ | ||
id: '3ceb546e-054d-4c1d-8860-e27c209d4ae4', | ||
type: 'admin' | ||
} | ||
], | ||
{} | ||
), | ||
|
||
down: (queryInterface, Sequelize) => queryInterface.bulkDelete('Roles', null, {}) | ||
}; |
Oops, something went wrong.