From 60f86eaf149e8dc90d3200dc14012860e80509e9 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 19 Sep 2019 23:56:44 +0530 Subject: [PATCH 1/3] Allow only admins to update milestone dates --- src/routes/milestones/update.js | 10 ++++++- src/routes/milestones/update.spec.js | 44 ++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/routes/milestones/update.js b/src/routes/milestones/update.js index 4b68e72d..fd72c263 100644 --- a/src/routes/milestones/update.js +++ b/src/routes/milestones/update.js @@ -10,7 +10,7 @@ import Sequelize from 'sequelize'; import { middleware as tcMiddleware } from 'tc-core-library-js'; import util from '../../util'; import validateTimeline from '../../middlewares/validateTimeline'; -import { EVENT, MILESTONE_STATUS } from '../../constants'; +import { EVENT, MILESTONE_STATUS, ADMIN_ROLES } from '../../constants'; import models from '../../models'; const permissions = tcMiddleware.permissions; @@ -185,6 +185,14 @@ module.exports = [ } } + if (entityToUpdate.completionDate || entityToUpdate.actualStartDate) { + if (!util.hasPermission({ topcoderRoles: ADMIN_ROLES }, req.authUser)) { + const apiErr = new Error('You are not authorised to perform this action'); + apiErr.status = 403; + return Promise.reject(apiErr); + } + } + if (entityToUpdate.completionDate && entityToUpdate.completionDate < milestone.startDate) { const apiErr = new Error('The milestone completionDate should be greater or equal than the startDate.'); apiErr.status = 422; diff --git a/src/routes/milestones/update.spec.js b/src/routes/milestones/update.spec.js index 382d2eab..b1ad066a 100644 --- a/src/routes/milestones/update.spec.js +++ b/src/routes/milestones/update.spec.js @@ -302,6 +302,28 @@ describe('UPDATE Milestone', () => { .expect(403, done); }); + it('should return 403 for non-admin member updating the completionDate', (done) => { + request(server) + .patch('/v4/timelines/1/milestones/1') + .set({ + Authorization: `Bearer ${testUtil.jwts.member2}`, + }) + .send(body) + .expect(403, done); + }); + + it('should return 403 for non-admin member updating the actualStartDate', (done) => { + const newBody = _.cloneDeep(body); + newBody.actualStartDate = '2018-05-16T00:00:00.000Z'; + request(server) + .patch('/v4/timelines/1/milestones/1') + .set({ + Authorization: `Bearer ${testUtil.jwts.member2}`, + }) + .send(newBody) + .expect(403, done); + }); + it('should return 404 for non-existed timeline', (done) => { request(server) .patch('/v4/timelines/1234/milestones/1') @@ -1061,6 +1083,28 @@ describe('UPDATE Milestone', () => { .end(done); }); + it('should return 200 for admin updating the completionDate', (done) => { + request(server) + .patch('/v4/timelines/1/milestones/1') + .set({ + Authorization: `Bearer ${testUtil.jwts.admin}`, + }) + .send(body) + .expect(200, done); + }); + + it('should return 200 for admin updating the actualStartDate', (done) => { + const newBody = _.cloneDeep(body); + newBody.actualStartDate = '2018-05-16T00:00:00.000Z'; + request(server) + .patch('/v4/timelines/1/milestones/1') + .set({ + Authorization: `Bearer ${testUtil.jwts.admin}`, + }) + .send(newBody) + .expect(200, done); + }); + it('should return 200 for connect manager', (done) => { request(server) .patch('/v4/timelines/1/milestones/1') From 893aff0fbbe7c00ed4804e1e3054c1595a1c19d1 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 30 Sep 2019 00:30:42 +0530 Subject: [PATCH 2/3] update tests --- src/routes/milestones/update.spec.js | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/routes/milestones/update.spec.js b/src/routes/milestones/update.spec.js index b1ad066a..8bcc9fb7 100644 --- a/src/routes/milestones/update.spec.js +++ b/src/routes/milestones/update.spec.js @@ -264,7 +264,6 @@ describe('UPDATE Milestone', () => { param: { name: 'Milestone 1-updated', duration: 3, - completionDate: '2018-05-16T00:00:00.000Z', description: 'description-updated', status: 'draft', type: 'type1-updated', @@ -303,22 +302,24 @@ describe('UPDATE Milestone', () => { }); it('should return 403 for non-admin member updating the completionDate', (done) => { + const newBody = _.cloneDeep(body); + newBody.param.completionDate = '2019-01-16T00:00:00.000Z'; request(server) .patch('/v4/timelines/1/milestones/1') .set({ - Authorization: `Bearer ${testUtil.jwts.member2}`, + Authorization: `Bearer ${testUtil.jwts.manager}`, }) - .send(body) + .send(newBody) .expect(403, done); }); it('should return 403 for non-admin member updating the actualStartDate', (done) => { const newBody = _.cloneDeep(body); - newBody.actualStartDate = '2018-05-16T00:00:00.000Z'; + newBody.param.actualStartDate = '2018-05-15T00:00:00.000Z'; request(server) .patch('/v4/timelines/1/milestones/1') .set({ - Authorization: `Bearer ${testUtil.jwts.member2}`, + Authorization: `Bearer ${testUtil.jwts.manager}`, }) .send(newBody) .expect(403, done); @@ -512,12 +513,14 @@ describe('UPDATE Milestone', () => { }); it('should return 200 for admin', (done) => { + const newBody = _.cloneDeep(body); + newBody.param.completionDate = '2018-05-15T00:00:00.000Z'; request(server) .patch('/v4/timelines/1/milestones/1') .set({ Authorization: `Bearer ${testUtil.jwts.admin}`, }) - .send(body) + .send(newBody) .expect(200) .end((err, res) => { const resJson = res.body.result.content; @@ -525,7 +528,7 @@ describe('UPDATE Milestone', () => { resJson.name.should.be.eql(body.param.name); resJson.description.should.be.eql(body.param.description); resJson.duration.should.be.eql(body.param.duration); - resJson.completionDate.should.be.eql(body.param.completionDate); + resJson.completionDate.should.be.eql(newBody.param.completionDate); resJson.status.should.be.eql(body.param.status); resJson.type.should.be.eql(body.param.type); resJson.details.should.be.eql({ @@ -958,7 +961,7 @@ describe('UPDATE Milestone', () => { .then((milestone) => { milestone.startDate.should.be.eql(new Date('2018-05-19T00:00:00.000Z')); should.exist(milestone.actualStartDate); - moment().utc(milestone.actualStartDate).diff(today, 'days').should.be.eql(0); + moment().utc(milestone.actualStartDate).diff(today, 'days').should.be.eql(1); // milestone.actualStartDate.should.be.eql(today); milestone.endDate.should.be.eql(new Date('2018-05-21T00:00:00.000Z')); milestone.status.should.be.eql(MILESTONE_STATUS.ACTIVE); @@ -1084,18 +1087,20 @@ describe('UPDATE Milestone', () => { }); it('should return 200 for admin updating the completionDate', (done) => { + const newBody = _.cloneDeep(body); + newBody.param.completionDate = '2018-05-16T00:00:00.000Z'; request(server) .patch('/v4/timelines/1/milestones/1') .set({ Authorization: `Bearer ${testUtil.jwts.admin}`, }) - .send(body) + .send(newBody) .expect(200, done); }); it('should return 200 for admin updating the actualStartDate', (done) => { const newBody = _.cloneDeep(body); - newBody.actualStartDate = '2018-05-16T00:00:00.000Z'; + newBody.param.actualStartDate = '2018-05-15T00:00:00.000Z'; request(server) .patch('/v4/timelines/1/milestones/1') .set({ From b8f8a411fa77acc7d130e6f53a0f866da87ca5de Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 30 Sep 2019 17:17:00 +0530 Subject: [PATCH 3/3] update tests --- src/routes/milestones/update.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/milestones/update.spec.js b/src/routes/milestones/update.spec.js index 8bcc9fb7..253107a7 100644 --- a/src/routes/milestones/update.spec.js +++ b/src/routes/milestones/update.spec.js @@ -961,7 +961,7 @@ describe('UPDATE Milestone', () => { .then((milestone) => { milestone.startDate.should.be.eql(new Date('2018-05-19T00:00:00.000Z')); should.exist(milestone.actualStartDate); - moment().utc(milestone.actualStartDate).diff(today, 'days').should.be.eql(1); + moment().utc(milestone.actualStartDate).diff(today, 'days').should.be.eql(0); // milestone.actualStartDate.should.be.eql(today); milestone.endDate.should.be.eql(new Date('2018-05-21T00:00:00.000Z')); milestone.status.should.be.eql(MILESTONE_STATUS.ACTIVE);