Skip to content

Commit

Permalink
Merge be8cf00 into 3d60bee
Browse files Browse the repository at this point in the history
  • Loading branch information
Adekoreday committed Aug 20, 2019
2 parents 3d60bee + be8cf00 commit 572d5dc
Show file tree
Hide file tree
Showing 10 changed files with 398 additions and 6 deletions.
46 changes: 46 additions & 0 deletions server/controllers/Articles.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ const createLikeOrDislike = async (userAction, userId, article) => {
* Adds dislike to an article
*
* @name addDislike
* @name update
* @async
* @static
* @memberof Articles
Expand Down Expand Up @@ -335,6 +336,51 @@ const createLikeOrDislike = async (userAction, userId, article) => {
return serverError(res);
}
}

/**
* Removes dislike from an article
*
* @name update
* @async
* @static
* @memberof Articles
* @param {Object} req express request object
* @param {Object} res express response object
* @returns {JSON} Details of the article and the updated
*/
static async update(req, res) {
try {
let image;
const {
file,
body,
user: { id }
} = req;
const { slug } = req.params;
if (file) image = await imageUpload(req);
const { status, articleBody } = body;
const publishedAt = status === 'draft' || articleBody === undefined ? null : Date.now();
const articleDetails = await Article.findBySlug(slug);
if (articleDetails === null || articleDetails.isArchived) {
return serverResponse(res, 404, { error: 'article not found' });
}
const updated = await Article.update(
{
...body,
publishedAt,
image
},
{ where: { slug, authorId: id } }
);
if (updated[0] === 0) {
return serverResponse(res, 403, { error: 'user unauthorized' });
}
const updatedArticle = await Article.findBySlug(slug);
return serverResponse(res, 200, updatedArticle.dataValues);
} catch (error) {
return serverError(res);
}
}
}

export default Articles;
101 changes: 101 additions & 0 deletions server/docs/authors-haven-api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,49 @@ paths:
application/json:
schema:
'$ref': '#/components/schemas/serverResponse'
/api/v1/articles/update/{slug}:
patch:
summary: A user can create update article
description: update Articles
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
title:
type: string
articleBody:
type: string
description:
type: string
status:
type: string
image:
type: string
format: binary
security:
- ApiKeyAuth: []
parameters:
- in: path
name: slug
required: true
schema:
type: string
description: Article Slug
responses:
"200":
description: user article created successfully
content:
application/json:
schema:
"$ref": "#/components/schemas/updateArticleResponse"
"422":
description: validaton errors
content:
application/json:
schema:
"$ref": "#/components/schemas/updateArticleErrorResponse"

components:
securitySchemes:
Expand Down Expand Up @@ -1329,3 +1372,61 @@ components:
type: string
format: date-time
example: 2017-07-21T17:32:28Z
updateArticleResponse:
type: object
properties:
likesCount:
type: integer
example: 1
dislikesCount:
type: integer
example: 2
isArchived:
type: boolean
example: true
id:
type: integer
example: 1
articleBody:
type: string
example: loremhipsondossantos
titile:
type: string
example: loremhipsondossantos
description:
type: string
example: loremhipsondossantos
image:
type: string
example: 'https://res.cloudinary.com/teamrambo50/image/upload/v1565160704/avatar-1577909_1280_xsoxql.png'
authorId:
type: integer
example: 3
publishedAt:
type: string
format: date-time
example: 2017-07-21T17:32:28Z
updatedAt:
type: string
format: date-time
example: 2017-07-21T17:32:28Z
createdAt:
type: string
format: date-time
example: 2017-07-21T17:32:28Z
slug:
type: string
format: date-time
example: title-1
updateArticleErrorResponse:
type: object
properties:
error:
type: object
properties:
title:
type: string
example: title should not be less than 3 characters
status:
type: string
example: status is required
20 changes: 20 additions & 0 deletions server/middlewares/articleEditValidation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import Joi from '@hapi/joi';
import { articleEdit } from '../schemas';
import { validateInputs } from '../helpers';

const options = {
abortEarly: false
};

/**
* Validates user article input
*
* @param {string} req - ExpressJs request object
* @param {string} res - ExpressJs response object
* @param {string} next - ExpressJs next function
* @returns {(JSON|function)} HTTP JSON response or ExpressJs next function
*/
const articleEditValidation = (req, res, next) => {
Joi.validate(req.body, articleEdit, options, validateInputs(res, next));
};
export default articleEditValidation;
4 changes: 3 additions & 1 deletion server/middlewares/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import validateArticle from './articleValidation';
import authorizeUser from './authorizeUser';
import validateCommentBody from './commentValidation';
import createCategoryValidation from './createCategoryValidation';
import articleEditValidation from './articleEditValidation';

const middlewares = {
verifyToken,
Expand All @@ -24,7 +25,8 @@ const middlewares = {
validatePagination,
authorizeUser,
validateCommentBody,
createCategoryValidation
createCategoryValidation,
articleEditValidation
};

export default middlewares;
12 changes: 11 additions & 1 deletion server/routes/article.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ const {
getSessionFromToken,
verifyToken,
validateArticle,
checkUserVerification
checkUserVerification,
articleEditValidation
} = middlewares;

const protectedRoutesMiddlewares = [
Expand All @@ -36,4 +37,13 @@ router.delete(
Articles.removeDislike
);

router.patch(
'/update/:slug',
verifyToken,
getSessionFromToken,
checkUserVerification,
articleEditValidation,
multerUploads('image'),
Articles.update
);
export default router;
27 changes: 27 additions & 0 deletions server/schemas/articleEdit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import Joi from '@hapi/joi';
import { setCustomMessage } from '../helpers';

export default {
description: Joi.string()
.min(20)
.max(500)
.error(setCustomMessage('description')),
title: Joi.string()
.min(3)
.max(250)
.error(setCustomMessage('title')),
status: Joi.string()
.valid('publish', 'draft')
.error(setCustomMessage('status', 'valid status')),
articleBody: Joi.string()
.min(2)
.error(setCustomMessage('articleBody')),
image: Joi.string()
.uri()
.error(setCustomMessage('image')),
tags: Joi.string()
.optional()
.min(2)
.max(250)
.error(setCustomMessage('tags'))
};
4 changes: 3 additions & 1 deletion server/schemas/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import userSignup from './userSignup';
import profileEdit from './profileEdit';
import paginationSchema from './pagination';
import article from './article';
import articleEdit from './articleEdit';
import comment from './comment';
import category from './category';

Expand All @@ -11,5 +12,6 @@ export {
category,
article,
paginationSchema,
comment
comment,
articleEdit
};
16 changes: 14 additions & 2 deletions test/articles/__mocks__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ const ArticleData2 = {
tags: 'tech,business'
};

const updateArticleData = {
title: ' is simply dummy text of the printing and typesetting ',
description: 'ext ever since the 1500s, when an unknown printer',
articleBody: 'ext ever since the 1500s, when an unknown printer took a ga',
status: 'publish'
};

const noTagArticleData = {
title: ' is simply dummy text of the printing and typesetting ',
description: 'ext ever since the 1500s, when an unknown printer',
Expand Down Expand Up @@ -70,7 +77,10 @@ const request = {
articleBody: 'ext ever since the 1500s, when an unknown printer took a ga',
tags: 'tech, business'
},
user: { id: 1 }
user: { id: 1 },
params: {
slug: 'unkown'
}
};
const fakeoutput = {
likesCount: 0,
Expand All @@ -82,7 +92,8 @@ const fakeoutput = {
image:
'http://res.cloudinary.com/teamrambo50/image/upload/v1565734710/k5fspd6uo4b4fw2upxlq.png',
authorId: 17,
slug: 'title'
slug: 'title',
isArchived: false
};

const badImage = {
Expand All @@ -106,6 +117,7 @@ export {
ArticleData,
ArticleData2,
noTagArticleData,
updateArticleData,
newArticleData,
myfile,
request,
Expand Down
5 changes: 4 additions & 1 deletion test/articles/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import * as createArticle from './create.test';
import * as likeOrDislikeArticle from './likeOrDislikeArticle.test';
import * as removeArticleLikeOrDislike from './removeArticleLikeOrDislike.test';
import * as updateArticle from './update.test';

export { createArticle, likeOrDislikeArticle, removeArticleLikeOrDislike };
export {
createArticle, likeOrDislikeArticle, removeArticleLikeOrDislike, updateArticle
};
Loading

0 comments on commit 572d5dc

Please sign in to comment.