Skip to content

Commit

Permalink
[feature (create)]create article endpoint [finish 166240826]
Browse files Browse the repository at this point in the history
  • Loading branch information
murediane committed Jul 2, 2019
1 parent 448d216 commit 0fcca80
Show file tree
Hide file tree
Showing 30 changed files with 320 additions and 430 deletions.
25 changes: 13 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@
"main": "index.js",
"scripts": {
"start": "babel-node src/index.js",
"test": "NODE_ENV=test nyc --reporter=html --reporter=text --reporter=lcov ./node_modules/.bin/mocha ./tests/* --require @babel/register --timeout 4000 --exit",
"test": "npm run setup:test && NODE_ENV=test nyc --reporter=html --reporter=text --reporter=lcov ./node_modules/.bin/mocha ./tests/* --require @babel/register --timeout 5000 --exit",
"dev": "NODE_ENV=development nodemon --exec babel-node src/index.js",
"setup:test": "NODE_ENV=test npm run migrate:undo && NODE_ENV=test npm run migrate && NODE_ENV=test npm run seed",
"setup:dev": "NODE_ENV=development npm run migrate:undo && NODE_ENV=development npm run migrate && NODE_ENV=development npm run seed",
"pretest": "NODE_ENV=test sequelize db:migrate:undo:all && NODE_ENV=test sequelize db:migrate",
"coverage": "nyc report --reporter=text-lcov | coveralls",
"eslint": "eslint . --cache --fix",
"setup": "NODE_ENV=test npm run migrate:undo && NODE_ENV=test npm run migrate && NODE_ENV=test npm run seed",
"precommit": "lint-staged",
"migrate": "node_modules/.bin/sequelize db:migrate",
"seed": "node_modules/.bin/sequelize db:seed:all",
Expand Down Expand Up @@ -55,24 +54,24 @@
"expect": "^24.8.0",
"express": "^4.16.4",
"express-session": "^1.16.2",
"jsonwebtoken": "^8.5.1",
"lodash": "^4.17.11",
"moment": "^2.24.0",
"morgan": "^1.9.1",
"multer": "^1.4.1",
"passport": "^0.4.0",
"passport-facebook": "^3.0.0",
"passport-google-oauth": "^2.0.0",
"passport-jwt": "^4.0.0",
"passport-pinterest": "^1.0.0",
"passport-twitter": "^1.0.4",
"redis": "^2.8.0",
"sinon": "^7.3.2",
"sinon-chai": "^3.3.0",
"jsonwebtoken": "^8.5.1",
"lodash": "^4.17.11",
"morgan": "^1.9.1",
"pg": "^7.11.0",
"pino": "^5.12.6",
"redis": "^2.8.0",
"sequelize": "^5.8.7",
"sequelize-cli": "^5.5.0",
"moment": "^2.24.0",
"multer": "^1.4.1",
"passport-jwt": "^4.0.0",
"sinon": "^7.3.2",
"sinon-chai": "^3.3.0",
"slug": "^1.1.0",
"swagger-node-express": "^2.1.3",
"swagger-ui-express": "^4.0.6",
Expand All @@ -90,9 +89,11 @@
"src/api/models",
"src/configs/redisConfigs.js",
"src/configs/passport.js",
"src/middlewares/passport.js",
"src/index.js",
"src/middlewares/errorHandler.js",
"src/api/models"
"src/api/models",
"tests/*"
]
},
"author": "Andela Simulations Programme",
Expand Down
43 changes: 21 additions & 22 deletions src/api/controllers/articleController.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,31 +30,30 @@ export default class ArticleController {
* @returns {Object} res
*/
static async create(req, res) {
const { id: author } = req.user;
const valid = await articleValidator(req.body);
const { category: name } = req.body;
let image = '';
const { id: author } = req.user.user;

const articleValidInput = await articleValidator(req.body);
const { category: id } = req.body;
let coverImage;
if (req.file) {
const saved = await cloudinary.v2.uploader.upload(req.file.path);
image = saved.secure_url;
const savedFile = await cloudinary.v2.uploader.upload(req.file.path);
coverImage = savedFile.secure_url;
}
await Category.findOrCreate({ where: { name } }).spread(async (cat) => {
const { id: category } = cat.get();
const article = await Article.create({
...valid,
slug: '',
author,
category,
image
});
if (article) {
return res.status(CREATED).json({
message: errorMessage.articleCreate,
article: article.get()
});
}
const getCategory = await Category.findOne({ where: { id } });
const { id: category } = getCategory.dataValues;
const article = await Article.create({
...articleValidInput,
slug: '',
author,
category,
coverImage
});
if (article) {
return res.status(CREATED).json({
message: errorMessage.articleCreate,
article: article.get()
});
}
}

/**
Expand Down Expand Up @@ -89,13 +88,13 @@ export default class ArticleController {
tagList: tagList || req.Existing.tagList,
category: category || req.Existing.category
};

await Article.update({
slug: updateContent.slug,
title: updateContent.title,
description: updateContent.description,
body: updateContent.body,
coverImage,
tagList: updateContent.tagList,
category: updateContent.category
},
{
Expand Down
21 changes: 11 additions & 10 deletions src/api/controllers/verifyEmail.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,21 @@ import errorMessages from '../../helpers/constants/error.messages';
*/
export default class {
/**
* @description verification link controller
* @param {*} req
* @param {*} res
* @returns {*} void
*/
* @description verification link controller
* @param {*} req
* @param {*} res
* @returns {*} void
*/
static async verifyEmail(req, res) {
const { token } = req.params;
const result = decodejwt(token);
if (result !== undefined) {
const action = await models.User.update({ verified: true }, {
where: {
email: result.user.email,
}
});
const action = await models.User.update({ verified: true },
{
where: {
email: result.user.email
}
});
const ZERO = 0;
if (!action.includes(ZERO)) {
res.status(status.OK).json({
Expand Down
22 changes: 0 additions & 22 deletions src/api/migrations/20190620193548-create-token.js

This file was deleted.

4 changes: 2 additions & 2 deletions src/api/migrations/20190622195901-create-category.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export default {
up: (queryInterface, Sequelize) => queryInterface.createTable('categories', {
up: (queryInterface, Sequelize) => queryInterface.createTable('Categories', {
id: {
allowNull: false,
autoIncrement: true,
Expand All @@ -18,5 +18,5 @@ export default {
type: Sequelize.DATE
}
}),
down: (queryInterface, Sequelize) => queryInterface.dropTable('categories')
down: (queryInterface, Sequelize) => queryInterface.dropTable('Categories')
};
17 changes: 13 additions & 4 deletions src/api/migrations/20190622195902-create-article.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export default {
up: (queryInterface, Sequelize) => queryInterface.createTable('articles', {
up: (queryInterface, Sequelize) => queryInterface.createTable('Articles', {
id: {
allowNull: false,
autoIncrement: true,
Expand All @@ -10,7 +10,12 @@ export default {
description: { type: Sequelize.TEXT, allowNull: false },
body: { type: Sequelize.TEXT, allowNull: false },
slug: { type: Sequelize.STRING, allowNull: false },
image: { type: Sequelize.TEXT, allowNull: false },
coverImage: { type: Sequelize.TEXT, allowNull: false },
tagList: {
type: Sequelize.ARRAY(Sequelize.TEXT),
allowNull: true
},

author: {
allowNull: false,
type: Sequelize.INTEGER,
Expand All @@ -19,7 +24,7 @@ export default {
category: {
allowNull: false,
type: Sequelize.INTEGER,
references: { model: 'categories', key: 'id' }
references: { model: 'Categories', key: 'id' }
},
createdAt: {
allowNull: false,
Expand All @@ -28,7 +33,11 @@ export default {
updatedAt: {
allowNull: false,
type: Sequelize.DATE
},
deletedAt: {
allowNull: true,
type: Sequelize.DATE
}
}),
down: (queryInterface, Sequelize) => queryInterface.dropTable('articles')
down: (queryInterface, Sequelize) => queryInterface.dropTable('Articles')
};
59 changes: 0 additions & 59 deletions src/api/migrations/20190624184203-create-article.js

This file was deleted.

20 changes: 14 additions & 6 deletions src/api/models/article.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import slug from 'slug';

const THIRTY_SIX = 36;
const SIX = 6;
const ZERO = 0;
const slugRandomNumberOne = 36;
const slugRandomNumberTwo = 6;
const SlugDefaultNumber = 0;

export default (sequelize, DataTypes) => {
const Article = sequelize.define('Articles',
Expand All @@ -18,6 +18,11 @@ export default (sequelize, DataTypes) => {
body: { type: DataTypes.TEXT, allowNull: false },
slug: { type: DataTypes.STRING, allowNull: false },
coverImage: { type: DataTypes.TEXT, allowNull: false },
tagList: {
type: DataTypes.ARRAY(DataTypes.TEXT),
allowNull: true
},

author: {
allowNull: false,
type: DataTypes.INTEGER,
Expand All @@ -26,15 +31,18 @@ export default (sequelize, DataTypes) => {
category: {
allowNull: false,
type: DataTypes.INTEGER,
references: { model: 'categories', key: 'id' }
references: { model: 'Categories', key: 'id' }
}
},
{
tableName: 'articles',
tableName: 'Articles',
timestamps: true,
paranoid: true,
hooks: {
beforeCreate(article) {
article.slug = slug(`${article.title}-${(Math.random() * THIRTY_SIX ** SIX || ZERO).toString(THIRTY_SIX)}`).toLowerCase();
article.slug = slug(`${article.title}-${(
Math.random() * slugRandomNumberOne ** slugRandomNumberTwo || SlugDefaultNumber
).toString(slugRandomNumberOne)}`).toLowerCase();
}
}
});
Expand Down
6 changes: 3 additions & 3 deletions src/api/models/category.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export default (sequelize, DataTypes) => {
const Category = sequelize.define('Category',
const Category = sequelize.define('Categories',
{
id: {
allowNull: false,
Expand All @@ -10,7 +10,7 @@ export default (sequelize, DataTypes) => {
name: { type: DataTypes.STRING, allowNull: false }
},
{
tableName: 'categories',
tableName: 'Categories',
hooks: {
beforeCreate(category) {
category.name = category.name.toUpperCase();
Expand All @@ -19,7 +19,7 @@ export default (sequelize, DataTypes) => {
});

Category.associate = (models) => {
Category.hasMany(models.Article, {
Category.hasMany(models.Articles, {
foreignKey: 'categoryId',
as: 'category',
onDelete: 'CASCADE',
Expand Down
8 changes: 0 additions & 8 deletions src/api/models/token.js

This file was deleted.

5 changes: 5 additions & 0 deletions src/api/routes/articleRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import checkValidToken from '../../middlewares/checkValidToken';
import bodyVerifier from '../../middlewares/validations/body.verifier';
import checkArticle from '../../middlewares/getOneArticle';
import uploadImage from '../../middlewares/upload';
import errorHandler from '../../middlewares/errorHandler';

const articleRouter = new Router();

Expand All @@ -15,5 +16,9 @@ articleRouter.patch('/:slug',
checkArticle.getArticle,
checkArticleOwner.checkOwner,
articleController.updateArticle);
articleRouter.post('/',
checkValidToken,

uploadImage.single('coverImage'),
errorHandler(articleController.create));
export default articleRouter;
Loading

0 comments on commit 0fcca80

Please sign in to comment.