diff --git a/backend/app.js b/backend/app.js index 28fb8e6f..2c6a34c5 100644 --- a/backend/app.js +++ b/backend/app.js @@ -4,6 +4,7 @@ const helmet = require('helmet'); const responseTime = require('response-time'); const routes = require('./app/routes'); const { errorHandler } = require('./helpers/error'); +const cookieParser = require('cookie-parser'); require('colors'); require('./helpers/dbConnection'); @@ -24,6 +25,9 @@ app.use(express.urlencoded({ limit: '50mb', extended: true })); // Response time app.use(responseTime({ suffix: false })); +// cookie +app.use(cookieParser()); + // Use routes app.use('/', routes); diff --git a/backend/app/routes/Q&A/question/downvoteQuestion.js b/backend/app/routes/Q&A/question/downvoteQuestion.js index 4fbb3731..d29b7869 100644 --- a/backend/app/routes/Q&A/question/downvoteQuestion.js +++ b/backend/app/routes/Q&A/question/downvoteQuestion.js @@ -2,6 +2,7 @@ const to = require('await-to-js').default; const question = require('../../../models/question'); const { ErrorHandler } = require('../../../../helpers/error'); const constants = require('../../../../constants'); +const { getVoteCookieName } = require('../../../../helpers/middlewares/cookie'); module.exports = async (req, res, next) => { const { questionId } = req.body; @@ -35,6 +36,7 @@ module.exports = async (req, res, next) => { return next(error); } + res.cookie(getVoteCookieName('question', questionId), true, { maxAge: 20 * 365 * 24 * 60 * 60 * 1000 }); res.status(200).send({ message: 'Question has been down voted', }); diff --git a/backend/app/routes/Q&A/question/index.js b/backend/app/routes/Q&A/question/index.js index 2f1c35dd..19df08db 100644 --- a/backend/app/routes/Q&A/question/index.js +++ b/backend/app/routes/Q&A/question/index.js @@ -9,6 +9,7 @@ const downvoteQuestion = require('./downvoteQuestion'); const updateQuestionStatus = require('./updateQuestionStatus'); const { authMiddleware } = require('../../../../helpers/middlewares/auth'); const deleteQuestion = require('./deleteQuestion'); +const { checkVoteCookie } = require('../../../../helpers/middlewares/cookie'); router.post('/', validation(QuestionValidationSchema), postQuestion); @@ -19,10 +20,10 @@ router.get('/getallquestions', getAllQuestion); router.get('/getQuestionById/:questionId', getQuestionById); // This route will increase upvote by one. -router.patch('/upvote', upvoteQuestion); +router.patch('/upvote',checkVoteCookie, upvoteQuestion); // This route will decrease upvote by one. -router.patch('/downvote', downvoteQuestion); +router.patch('/downvote',checkVoteCookie, downvoteQuestion); // route for updating the question status router.patch('/updateStatus', validation(updateQuestionStatusSchema), updateQuestionStatus); diff --git a/backend/app/routes/Q&A/question/upvoteQuestion.js b/backend/app/routes/Q&A/question/upvoteQuestion.js index 63b28fd6..77a1b2a2 100644 --- a/backend/app/routes/Q&A/question/upvoteQuestion.js +++ b/backend/app/routes/Q&A/question/upvoteQuestion.js @@ -2,6 +2,7 @@ const to = require('await-to-js').default; const question = require('../../../models/question'); const { ErrorHandler } = require('../../../../helpers/error'); const constants = require('../../../../constants'); +const { getVoteCookieName } = require('../../../../helpers/middlewares/cookie'); module.exports = async (req, res, next) => { const { questionId } = req.body; @@ -12,10 +13,11 @@ module.exports = async (req, res, next) => { message: 'Database Error', errStack: err, }); - return next(error); } + res.cookie(getVoteCookieName('question', questionId), true, { maxAge: 20 * 365 * 24 * 60 * 60 * 1000 }); + res.status(200).send({ message: 'Question has been upvoted', }); diff --git a/backend/helpers/middlewares/cookie.js b/backend/helpers/middlewares/cookie.js new file mode 100644 index 00000000..bf7bd680 --- /dev/null +++ b/backend/helpers/middlewares/cookie.js @@ -0,0 +1,16 @@ +const getVoteCookieName = (type, id) => `${type}_voted_${id}`; + +const checkVoteCookie = (req, res, next) => { + const { questionId, answerId } = req.body; + const voteType = questionId ? 'question' : 'answer'; + const voteId = questionId || answerId; + const voteCookieName = getVoteCookieName(voteType, voteId); + + if (req.cookies[voteCookieName]) { + return res.status(400).json({ error: 'You have already voted' }); + } + + next(); +}; + +module.exports = { checkVoteCookie, getVoteCookieName } \ No newline at end of file diff --git a/backend/package.json b/backend/package.json index e470d723..b9cb2775 100644 --- a/backend/package.json +++ b/backend/package.json @@ -28,6 +28,7 @@ "chai-http": "^4.3.0", "colors": "^1.4.0", "config": "^3.3.3", + "cookie-parser": "^1.4.6", "cors": "^2.8.5", "dotenv": "^8.2.0", "ejs": "^3.1.6", diff --git a/frontend/.env b/frontend/.env index c0da241b..ad1ac9f1 100644 --- a/frontend/.env +++ b/frontend/.env @@ -1 +1 @@ -REACT_APP_API="https://community-website-backend.onrender.com" \ No newline at end of file +REACT_APP_API="https://community-website-backend.onrender.com"