From 8070486def93ba9f73e23f30f4ae2171dd89f82c Mon Sep 17 00:00:00 2001 From: Nishant Jain Date: Sat, 23 Jul 2022 01:54:24 +0530 Subject: [PATCH] =?UTF-8?q?add=20max=20length=20validations=20for=20summar?= =?UTF-8?q?y=20in=20challenge=20create=20and=20update=E2=80=A6=20(#14053)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add max length validations for summary in challenge create and update controllers * Add validation to group APIs * fix lint errors * add validation to group plan * fix imports * add tests * add max length validations for summary in challenge create and update controllers * Add validation to group APIs * fix lint errors * add validation to group plan * fix imports * add tests * lint checks --- .../challenges/POST-challenges.test.js | 17 +++++++++++++++++ .../PUT-challenges_challengeId.test.js | 12 ++++++++++++ .../v3/integration/groups/POST-groups.test.js | 15 +++++++++++++++ .../v3/integration/groups/PUT-groups.test.js | 12 ++++++++++++ .../common/script/errors/apiErrorMessages.js | 1 + website/server/controllers/api-v3/challenges.js | 6 ++++++ website/server/controllers/api-v3/groups.js | 9 ++++++++- 7 files changed, 71 insertions(+), 1 deletion(-) diff --git a/test/api/v3/integration/challenges/POST-challenges.test.js b/test/api/v3/integration/challenges/POST-challenges.test.js index e1b3dc63a0..3c566b76d9 100644 --- a/test/api/v3/integration/challenges/POST-challenges.test.js +++ b/test/api/v3/integration/challenges/POST-challenges.test.js @@ -4,6 +4,7 @@ import { createAndPopulateGroup, translate as t, } from '../../../../helpers/api-integration/v3'; +import { MAX_SUMMARY_SIZE_FOR_CHALLENGES } from '../../../../../website/common/script/constants'; describe('POST /challenges', () => { it('returns error when group is empty', async () => { @@ -60,6 +61,22 @@ describe('POST /challenges', () => { }); }); + it('return error when creating a challenge with summary with greater than MAX_SUMMARY_SIZE_FOR_CHALLENGES characters', async () => { + const user = await generateUser(); + const summary = 'A'.repeat(MAX_SUMMARY_SIZE_FOR_CHALLENGES + 1); + const group = createAndPopulateGroup({ + members: 1, + }); + await expect(user.post('/challenges', { + group: group._id, + summary, + })).to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('invalidReqParams'), + }); + }); + context('Creating a challenge for a valid group', () => { let groupLeader; let group; diff --git a/test/api/v3/integration/challenges/PUT-challenges_challengeId.test.js b/test/api/v3/integration/challenges/PUT-challenges_challengeId.test.js index 93e46a979d..22e1f38b18 100644 --- a/test/api/v3/integration/challenges/PUT-challenges_challengeId.test.js +++ b/test/api/v3/integration/challenges/PUT-challenges_challengeId.test.js @@ -4,6 +4,7 @@ import { createAndPopulateGroup, translate as t, } from '../../../../helpers/api-integration/v3'; +import { MAX_SUMMARY_SIZE_FOR_CHALLENGES } from '../../../../../website/common/script/constants'; describe('PUT /challenges/:challengeId', () => { let privateGuild; let user; let nonMember; let challenge; let @@ -91,4 +92,15 @@ describe('PUT /challenges/:challengeId', () => { expect(res.name).to.equal('New Challenge Name'); expect(res.description).to.equal('New challenge description.'); }); + + it('return error when challenge summary is greater than MAX_SUMMARY_SIZE_FOR_CHALLENGES characters', async () => { + const summary = 'A'.repeat(MAX_SUMMARY_SIZE_FOR_CHALLENGES + 1); + await expect(user.put(`/challenges/${challenge._id}`, { + summary, + })).to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('invalidReqParams'), + }); + }); }); diff --git a/test/api/v3/integration/groups/POST-groups.test.js b/test/api/v3/integration/groups/POST-groups.test.js index b507fc8165..e4b915f972 100644 --- a/test/api/v3/integration/groups/POST-groups.test.js +++ b/test/api/v3/integration/groups/POST-groups.test.js @@ -3,6 +3,7 @@ import { translate as t, } from '../../../../helpers/api-integration/v3'; import { model as Group } from '../../../../../website/server/models/group'; +import { MAX_SUMMARY_SIZE_FOR_GUILDS } from '../../../../../website/common/script/constants'; describe('POST /group', () => { let user; @@ -71,6 +72,20 @@ describe('POST /group', () => { expect(updatedGroup.summary).to.eql(summary); }); + + it('returns error when summary is longer than MAX_SUMMARY_SIZE_FOR_GUILDS characters', async () => { + const name = 'Test Group'; + const summary = 'A'.repeat(MAX_SUMMARY_SIZE_FOR_GUILDS + 1); + await expect(user.post('/groups', { + name, + type: 'guild', + summary, + })).to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('invalidReqParams'), + }); + }); }); context('Guilds', () => { diff --git a/test/api/v3/integration/groups/PUT-groups.test.js b/test/api/v3/integration/groups/PUT-groups.test.js index 1ff67958da..36bdfdd7d4 100644 --- a/test/api/v3/integration/groups/PUT-groups.test.js +++ b/test/api/v3/integration/groups/PUT-groups.test.js @@ -3,6 +3,7 @@ import { generateUser, translate as t, } from '../../../../helpers/api-integration/v3'; +import { MAX_SUMMARY_SIZE_FOR_GUILDS } from '../../../../../website/common/script/constants'; describe('PUT /group', () => { let leader; let nonLeader; let groupToUpdate; let @@ -130,4 +131,15 @@ describe('PUT /group', () => { expect(response.bannedWordsAllowed).to.eql(undefined); }); + + it('returns error when summary is longer than MAX_SUMMARY_SIZE_FOR_GUILDS characters', async () => { + const summary = 'A'.repeat(MAX_SUMMARY_SIZE_FOR_GUILDS + 1); + await expect(leader.put(`/groups/${groupToUpdate._id}`, { + summary, + })).to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('invalidReqParams'), + }); + }); }); diff --git a/website/common/script/errors/apiErrorMessages.js b/website/common/script/errors/apiErrorMessages.js index db44491357..531d7e8a04 100644 --- a/website/common/script/errors/apiErrorMessages.js +++ b/website/common/script/errors/apiErrorMessages.js @@ -39,4 +39,5 @@ export default { directionUpDown: '"direction" is required and must be "up" or "down".', invalidTaskIdentifier: 'A task is identified by its UUID or alias.', invalidTaskScorings: 'This API route expects a body in the form of [{id, direction}].', + summaryLengthExceedsMax: 'Summary length is too high.', }; diff --git a/website/server/controllers/api-v3/challenges.js b/website/server/controllers/api-v3/challenges.js index f2d0b09747..064d03962b 100644 --- a/website/server/controllers/api-v3/challenges.js +++ b/website/server/controllers/api-v3/challenges.js @@ -30,6 +30,10 @@ import { } from '../../libs/challenges'; import apiError from '../../libs/apiError'; +import common from '../../../common'; + +const { MAX_SUMMARY_SIZE_FOR_CHALLENGES } = common.constants; + const api = {}; /** @@ -200,6 +204,7 @@ api.createChallenge = { const { user } = res.locals; req.checkBody('group', apiError('groupIdRequired')).notEmpty(); + req.checkBody('summary', apiError('summaryLengthExceedsMax')).isLength({ max: MAX_SUMMARY_SIZE_FOR_CHALLENGES }); const validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -707,6 +712,7 @@ api.updateChallenge = { middlewares: [authWithHeaders()], async handler (req, res) { req.checkParams('challengeId', res.t('challengeIdRequired')).notEmpty().isUUID(); + req.checkBody('summary', apiError('summaryLengthExceedsMax')).isLength({ max: MAX_SUMMARY_SIZE_FOR_CHALLENGES }); const validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; diff --git a/website/server/controllers/api-v3/groups.js b/website/server/controllers/api-v3/groups.js index 44ae3349c1..7e0f22c0ff 100644 --- a/website/server/controllers/api-v3/groups.js +++ b/website/server/controllers/api-v3/groups.js @@ -28,6 +28,7 @@ import amzLib from '../../libs/payments/amazon'; import apiError from '../../libs/apiError'; import { model as UserNotification } from '../../models/userNotification'; +const { MAX_SUMMARY_SIZE_FOR_GUILDS } = common.constants; const MAX_EMAIL_INVITES_BY_USER = 200; const TECH_ASSISTANCE_EMAIL = nconf.get('EMAILS_TECH_ASSISTANCE_EMAIL'); @@ -118,6 +119,11 @@ api.createGroup = { const group = new Group(Group.sanitize(req.body)); group.leader = user._id; + req.checkBody('summary', apiError('summaryLengthExceedsMax')).isLength({ max: MAX_SUMMARY_SIZE_FOR_GUILDS }); + + const validationErrors = req.validationErrors(); + if (validationErrors) throw validationErrors; + if (group.type === 'guild') { if (group.privacy === 'public' && user.flags.chatRevoked) throw new NotAuthorized(res.t('chatPrivilegesRevoked')); if (user.balance < 1) throw new NotAuthorized(res.t('messageInsufficientGems')); @@ -191,7 +197,7 @@ api.createGroupPlan = { const group = new Group(Group.sanitize(req.body.groupToCreate)); req.checkBody('paymentType', res.t('paymentTypeRequired')).notEmpty(); - + req.checkBody('summary', apiError('summaryLengthExceedsMax')).isLength({ max: MAX_SUMMARY_SIZE_FOR_GUILDS }); const validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors; @@ -462,6 +468,7 @@ api.updateGroup = { const { user } = res.locals; req.checkParams('groupId', apiError('groupIdRequired')).notEmpty(); + req.checkBody('summary', apiError('summaryLengthExceedsMax')).isLength({ max: MAX_SUMMARY_SIZE_FOR_GUILDS }); const validationErrors = req.validationErrors(); if (validationErrors) throw validationErrors;