diff --git a/config/param-validation.js b/config/param-validation.js index fa7c0d86..d7a0557e 100644 --- a/config/param-validation.js +++ b/config/param-validation.js @@ -34,10 +34,17 @@ export default { email: Joi.string().email().allow('') } }, + + // POST + relatedLinkCreate: { + body: { + url: Joi.string().required() + } + }, + comment: { body: { - content: Joi.string().required(), - post: Joi.string().required(), + content: Joi.string().required() } } diff --git a/server/controllers/relatedLink.controller.js b/server/controllers/relatedLink.controller.js new file mode 100644 index 00000000..2812fff6 --- /dev/null +++ b/server/controllers/relatedLink.controller.js @@ -0,0 +1,68 @@ +import Promise from 'bluebird'; +import mongoose from 'mongoose'; +import map from 'lodash/map'; + +import RelatedLink from '../models/relatedLink.model'; + + +/** + * @swagger + * tags: + * - name: relatedLink + * description: Related links for episodes. + */ + +/** + * @swagger + * /posts/{postId}/relatedLink: + * post: + * summary: Create relatedLink for episode + * description: Create relatedLink for episode + * tags: [relatedLink] + * security: + * - Token: [] + * parameters: + * - $ref: '#/parameters/postId' + * - in: body + * name: URL + * type: string + * required: true + * description: URL for link + * responses: + * '201': + * description: successful created + * schema: + * $ref: '#/definitions/RelatedLink' + * '401': + * $ref: '#/responses/Unauthorized' + * '404': + * $ref: '#/responses/NotFound' + */ + + +function create(req, res, next) { + const { user } = req; + const { postId } = req.params; + const { url } = req.body; + + const relatedLink = new RelatedLink(); + relatedLink.url = url; + relatedLink.post = postId + relatedLink.author = user._id + relatedLink.save() + .then((relatedLink) => { + return res.status(201).json(relatedLink); + }) + .catch( (err) => next(err)); +} + +function list(req, res, next) { + const { postId } = req.params; + RelatedLink.find({post: postId}) + .then((relatedLinks) => { + res.json(relatedLinks); + }) + .catch( (err) => next(err)); +} + +export default {create, list}; diff --git a/server/models/relatedLink.model.js b/server/models/relatedLink.model.js new file mode 100644 index 00000000..7283ca03 --- /dev/null +++ b/server/models/relatedLink.model.js @@ -0,0 +1,68 @@ +import Promise from 'bluebird'; +import mongoose, {Schema} from 'mongoose'; +import httpStatus from 'http-status'; +import APIError from '../helpers/APIError'; +import Vote from './vote.model'; +/** + * @swagger + * definitions: + * RelatedLink: + * type: object + * properties: + * _id: + * $ref: '#/definitions/ObjectId' + * __v: + * $ref: '#/definitions/MongoVersion' + * url: + * type: string + * description: Related URL + * example: google.com + * clicks: + * type: number + * description: Number of clicks this url has received + * example: 10 + * dateCreated: + * type: string + * format: date-time + * description: Date link was created + * example: 2017-10-30T01:05:39.674Z + * author: + * $ref: '#/definitions/ObjectId' + * post: + * $ref: '#/definitions/ObjectId' + */ +const RelatedLinkSchema = new Schema({ + id: String, + url: { + type: String, + required: true + }, + clicks: { type: Number, default: 0 }, + dateCreated: { + type: Date, + default: Date.now + }, + deleted: { + type: Boolean, + default: false + }, + post: { + type: Schema.Types.ObjectId, + ref: 'Post' + }, + author: { + type: Schema.Types.ObjectId, + ref: 'User' + } +}); + + +/** + * Statics + */ +RelatedLinkSchema.statics = {}; + +// Indexes +RelatedLinkSchema.index({ 'url': 'text' }); + +export default mongoose.model('RelatedLink', RelatedLinkSchema); diff --git a/server/routes/post.route.js b/server/routes/post.route.js index b5293435..f97c5cb1 100644 --- a/server/routes/post.route.js +++ b/server/routes/post.route.js @@ -1,9 +1,12 @@ import express from 'express'; import expressJwt from 'express-jwt'; +import validate from 'express-validation'; +import paramValidation from '../../config/param-validation'; import postCtrl from '../controllers/post.controller'; import voteCtrl from '../controllers/vote.controller'; import transferField from '../middleware/transferField'; import commentCtrl from '../controllers/comment.controller'; +import relatedLinkCtrl from '../controllers/relatedLink.controller'; import favoriteCtrl from '../controllers/favorite.controller'; import listenedCtrl from '../controllers/listened.controller'; import config from '../../config/config'; @@ -11,23 +14,39 @@ import config from '../../config/config'; const router = express.Router(); // eslint-disable-line new-cap router.route('/') - .get(expressJwt({ secret: config.jwtSecret, credentialsRequired: false }), postCtrl.list); + .get(expressJwt({ secret: config.jwtSecret + , credentialsRequired: false }), postCtrl.list); router.route('/recommendations') - .get(expressJwt({ secret: config.jwtSecret }), postCtrl.recommendations); + .get(expressJwt({ secret: config.jwtSecret }) + , postCtrl.recommendations); router.route('/:postId') .get(postCtrl.get); router.route('/:postId/comments') - .get(expressJwt({ secret: config.jwtSecret, credentialsRequired: false }), commentCtrl.list); + .get(expressJwt({ secret: config.jwtSecret + , credentialsRequired: false }), commentCtrl.list); // Create a comment: router.route('/:postId/comment') .post( expressJwt({ secret: config.jwtSecret }) + , validate(paramValidation.comment) , commentCtrl.create); +// Get related links associated with postId +router.route('/:postId/related-links') + .get(expressJwt({ secret: config.jwtSecret, credentialsRequired: false }) + , relatedLinkCtrl.list); + +// Add a related-link to postId: +router.route('/:postId/related-link') + .post( + expressJwt({ secret: config.jwtSecret }) + , validate(paramValidation.relatedLinkCreate) + , relatedLinkCtrl.create); + router.route('/:postId/upvote') .post(expressJwt({ secret: config.jwtSecret }) , transferField({source: 'post', target: 'entity'})