From 8c31b290125d5b873b435693a8e05d39f43a6e6e Mon Sep 17 00:00:00 2001 From: jswheeler Date: Fri, 14 Aug 2020 07:30:28 -0500 Subject: [PATCH 01/13] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 0a0558aa..83cb4904 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Topcoder Challenge API This microservice provides access and interaction with all sorts of Challenge data. +## Devlopment status +[![Total alerts](https://img.shields.io/lgtm/alerts/g/topcoder-platform/challenge-api.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/topcoder-platform/challenge-api/alerts/) ### Deployment status Dev: [![CircleCI](https://circleci.com/gh/topcoder-platform/challenge-api/tree/develop.svg?style=svg)](https://circleci.com/gh/topcoder-platform/challenge-api/tree/develop) Prod: [![CircleCI](https://circleci.com/gh/topcoder-platform/challenge-api/tree/master.svg?style=svg)](https://circleci.com/gh/topcoder-platform/challenge-api/tree/master) From a8dafc1a637724a21e53683e4ddaaa4392f0eada Mon Sep 17 00:00:00 2001 From: jswheeler Date: Fri, 14 Aug 2020 07:31:20 -0500 Subject: [PATCH 02/13] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 83cb4904..98818de2 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ This microservice provides access and interaction with all sorts of Challenge data. ## Devlopment status -[![Total alerts](https://img.shields.io/lgtm/alerts/g/topcoder-platform/challenge-api.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/topcoder-platform/challenge-api/alerts/) +[![Total alerts](https://img.shields.io/lgtm/alerts/g/topcoder-platform/challenge-api.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/topcoder-platform/challenge-api/alerts/)[![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/topcoder-platform/challenge-api.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/topcoder-platform/challenge-api/context:javascript) ### Deployment status Dev: [![CircleCI](https://circleci.com/gh/topcoder-platform/challenge-api/tree/develop.svg?style=svg)](https://circleci.com/gh/topcoder-platform/challenge-api/tree/develop) Prod: [![CircleCI](https://circleci.com/gh/topcoder-platform/challenge-api/tree/master.svg?style=svg)](https://circleci.com/gh/topcoder-platform/challenge-api/tree/master) From 0af7a24aa256b57d628ff4630a70ae4d8891831b Mon Sep 17 00:00:00 2001 From: James Cori Date: Sun, 16 Aug 2020 21:20:58 -0400 Subject: [PATCH 03/13] Updated in db, just changing the seed file for future --- src/scripts/seed/ChallengeType.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/seed/ChallengeType.json b/src/scripts/seed/ChallengeType.json index 6f2a07fc..3656f645 100644 --- a/src/scripts/seed/ChallengeType.json +++ b/src/scripts/seed/ChallengeType.json @@ -21,6 +21,6 @@ "description": "A piece of work assigned to one person", "isActive": true, "isTask": true, - "abbreviation": "T" + "abbreviation": "TSK" } ] From d66fbfa9ec2d4197bcd4f6c8419cf5af73f38230 Mon Sep 17 00:00:00 2001 From: Thomas Kranitsas Date: Thu, 20 Aug 2020 19:31:43 +0300 Subject: [PATCH 04/13] Add some logging to debug the sorting issue --- src/services/ChallengeService.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/ChallengeService.js b/src/services/ChallengeService.js index c0f1d93b..58533490 100644 --- a/src/services/ChallengeService.js +++ b/src/services/ChallengeService.js @@ -465,7 +465,7 @@ async function searchChallenges (currentUser, criteria) { docs = await esClient.search(esQuery) } catch (e) { // Catch error when the ES is fresh and has no data - // logger.error(`Query Error from ES ${JSON.stringify(e)}`) + logger.error(`Query Error from ES ${JSON.stringify(e)}`) docs = { hits: { total: 0, From ffacdd1e95bdea6aa3e7e47e3289aa9de432691d Mon Sep 17 00:00:00 2001 From: vikasrohit Date: Mon, 24 Aug 2020 18:06:47 +0530 Subject: [PATCH 05/13] Fixing query for returning both task and challenges Seems like `task.isTask : false` is not enough for the cases where task json is null or task.isTask does not exist. --- src/services/ChallengeService.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/services/ChallengeService.js b/src/services/ChallengeService.js index 58533490..059e9809 100644 --- a/src/services/ChallengeService.js +++ b/src/services/ChallengeService.js @@ -369,6 +369,7 @@ async function searchChallenges (currentUser, criteria) { mustQuery.push({ bool: { should: [ + { bool: { must_not: { exists: { field: 'task.isTask' } } } }, { match_phrase: { 'task.isTask': false } }, { bool: { From 3e8741039f7d4d0c70cccc065bd1c5f34102e583 Mon Sep 17 00:00:00 2001 From: James Cori Date: Thu, 27 Aug 2020 19:35:10 -0400 Subject: [PATCH 06/13] Updating route security to add manager --- app-constants.js | 5 +++-- src/routes.js | 32 ++++++++++++++++---------------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/app-constants.js b/app-constants.js index 3a48084d..f7e92075 100644 --- a/app-constants.js +++ b/app-constants.js @@ -2,8 +2,9 @@ * App constants */ const UserRoles = { - Admin: 'Administrator', - Copilot: 'Copilot', + Admin: 'administrator', + Copilot: 'copilot', + Manager: 'Connect Manager', User: 'Topcoder User' } diff --git a/src/routes.js b/src/routes.js index fd04d997..f7ed7d27 100644 --- a/src/routes.js +++ b/src/routes.js @@ -16,14 +16,14 @@ module.exports = { get: { controller: 'ChallengeController', method: 'searchChallenges', - access: [constants.UserRoles.Admin, constants.UserRoles.Copilot, constants.UserRoles.User], + access: [constants.UserRoles.Admin, constants.UserRoles.Copilot, constants.UserRoles.Manager, constants.UserRoles.User], scopes: [READ, ALL] }, post: { controller: 'ChallengeController', method: 'createChallenge', auth: 'jwt', - access: [constants.UserRoles.Admin, constants.UserRoles.Copilot], + access: [constants.UserRoles.Admin, constants.UserRoles.Copilot, constants.UserRoles.Manager], scopes: [CREATE, ALL] } }, @@ -43,14 +43,14 @@ module.exports = { controller: 'ChallengeController', method: 'fullyUpdateChallenge', auth: 'jwt', - access: [constants.UserRoles.Admin, constants.UserRoles.Copilot], + access: [constants.UserRoles.Admin, constants.UserRoles.Copilot, constants.UserRoles.Manager], scopes: [UPDATE, ALL] }, patch: { controller: 'ChallengeController', method: 'partiallyUpdateChallenge', auth: 'jwt', - access: [constants.UserRoles.Admin, constants.UserRoles.Copilot], + access: [constants.UserRoles.Admin, constants.UserRoles.Copilot, constants.UserRoles.Manager], scopes: [UPDATE, ALL] } }, @@ -63,7 +63,7 @@ module.exports = { controller: 'ChallengeTypeController', method: 'createChallengeType', auth: 'jwt', - access: [constants.UserRoles.Admin, constants.UserRoles.Copilot], + access: [constants.UserRoles.Admin, constants.UserRoles.Copilot, constants.UserRoles.Manager], scopes: [CREATE, ALL] } }, @@ -76,14 +76,14 @@ module.exports = { controller: 'ChallengeTypeController', method: 'fullyUpdateChallengeType', auth: 'jwt', - access: [constants.UserRoles.Admin, constants.UserRoles.Copilot], + access: [constants.UserRoles.Admin, constants.UserRoles.Copilot, constants.UserRoles.Manager], scopes: [UPDATE, ALL] }, patch: { controller: 'ChallengeTypeController', method: 'partiallyUpdateChallengeType', auth: 'jwt', - access: [constants.UserRoles.Admin, constants.UserRoles.Copilot], + access: [constants.UserRoles.Admin, constants.UserRoles.Copilot, constants.UserRoles.Manager], scopes: [UPDATE, ALL] } }, @@ -96,7 +96,7 @@ module.exports = { controller: 'ChallengeTrackController', method: 'createChallengeTrack', auth: 'jwt', - access: [constants.UserRoles.Admin, constants.UserRoles.Copilot], + access: [constants.UserRoles.Admin, constants.UserRoles.Copilot, constants.UserRoles.Manager], scopes: [CREATE, ALL] } }, @@ -109,14 +109,14 @@ module.exports = { controller: 'ChallengeTrackController', method: 'fullyUpdateChallengeTrack', auth: 'jwt', - access: [constants.UserRoles.Admin, constants.UserRoles.Copilot], + access: [constants.UserRoles.Admin, constants.UserRoles.Copilot, constants.UserRoles.Manager], scopes: [UPDATE, ALL] }, patch: { controller: 'ChallengeTrackController', method: 'partiallyUpdateChallengeTrack', auth: 'jwt', - access: [constants.UserRoles.Admin, constants.UserRoles.Copilot], + access: [constants.UserRoles.Admin, constants.UserRoles.Copilot, constants.UserRoles.Manager], scopes: [UPDATE, ALL] } }, @@ -132,7 +132,7 @@ module.exports = { controller: 'ChallengeTimelineTemplateController', method: 'createChallengeTimelineTemplate', auth: 'jwt', - access: [constants.UserRoles.Admin, constants.UserRoles.Copilot], + access: [constants.UserRoles.Admin, constants.UserRoles.Copilot, constants.UserRoles.Manager], scopes: [CREATE, ALL] } }, @@ -148,14 +148,14 @@ module.exports = { controller: 'ChallengeTimelineTemplateController', method: 'fullyUpdateChallengeTimelineTemplate', auth: 'jwt', - access: [constants.UserRoles.Admin, constants.UserRoles.Copilot], + access: [constants.UserRoles.Admin, constants.UserRoles.Copilot, constants.UserRoles.Manager], scopes: [UPDATE, ALL] }, delete: { controller: 'ChallengeTimelineTemplateController', method: 'deleteChallengeTimelineTemplate', auth: 'jwt', - access: [constants.UserRoles.Admin, constants.UserRoles.Copilot], + access: [constants.UserRoles.Admin, constants.UserRoles.Copilot, constants.UserRoles.Manager], scopes: [DELETE, ALL] } }, @@ -187,7 +187,7 @@ module.exports = { controller: 'ChallengePhaseController', method: 'getPhase', auth: 'jwt', - access: [constants.UserRoles.Admin, constants.UserRoles.Copilot], + access: [constants.UserRoles.Admin, constants.UserRoles.Copilot, constants.UserRoles.Manager], scopes: [READ, ALL] }, put: { @@ -231,7 +231,7 @@ module.exports = { controller: 'TimelineTemplateController', method: 'getTimelineTemplate', auth: 'jwt', - access: [constants.UserRoles.Admin, constants.UserRoles.Copilot], + access: [constants.UserRoles.Admin, constants.UserRoles.Copilot, constants.UserRoles.Manager], scopes: [READ, ALL] }, put: { @@ -261,7 +261,7 @@ module.exports = { controller: 'AttachmentController', method: 'uploadAttachment', auth: 'jwt', - access: [constants.UserRoles.Admin, constants.UserRoles.Copilot], + access: [constants.UserRoles.Admin, constants.UserRoles.Copilot, constants.UserRoles.Manager], scopes: [CREATE, ALL] } }, From d149fa291ebc882e08b6ed61fa741131d96631df Mon Sep 17 00:00:00 2001 From: Thomas Kranitsas Date: Fri, 28 Aug 2020 23:17:20 +0300 Subject: [PATCH 07/13] fix sorting issue --- app-constants.js | 8 +++++++- src/services/ChallengeService.js | 5 ++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app-constants.js b/app-constants.js index 3a48084d..59a6e15e 100644 --- a/app-constants.js +++ b/app-constants.js @@ -70,6 +70,11 @@ const challengeTracks = { QA: 'QA' } +const challengeTextSortField = { + Name: 'name', + TypeId: 'typeId' +} + module.exports = { UserRoles, prizeSetTypes, @@ -78,5 +83,6 @@ module.exports = { EVENT_ORIGINATOR, EVENT_MIME_TYPE, Topics, - challengeTracks + challengeTracks, + challengeTextSortField } diff --git a/src/services/ChallengeService.js b/src/services/ChallengeService.js index 059e9809..cd0adcfc 100644 --- a/src/services/ChallengeService.js +++ b/src/services/ChallengeService.js @@ -251,7 +251,10 @@ async function searchChallenges (currentUser, criteria) { if (criteria.endDateEnd) { boolQuery.push({ range: { endDate: { lte: criteria.endDateEnd } } }) } - const sortByProp = criteria.sortBy ? criteria.sortBy : 'created' + + let sortByProp = criteria.sortBy ? criteria.sortBy : 'created' + // If property to sort is text, then use its sub-field 'keyword' for sorting + sortByProp = _.includes(constants.challengeTextSortField, sortByProp) ? sortByProp + '.keyword' : sortByProp const sortOrderProp = criteria.sortOrder ? criteria.sortOrder : 'desc' const mustQuery = [] From 58a5cb0116ac9a49b9028dc898e662cb061f352a Mon Sep 17 00:00:00 2001 From: Thomas Kranitsas Date: Tue, 1 Sep 2020 16:54:49 +0300 Subject: [PATCH 08/13] add support for filtering on events --- docs/swagger.yaml | 23 +++++++++++++++++++++++ src/services/ChallengeService.js | 18 ++++++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 76b2d4db..9a2715a2 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -174,6 +174,29 @@ paths: type: array items: type: string + - name: includeAllTags + in: query + description: >- + Require all provided tags to be present on a challenge for a match + required: false + default: true + type: boolean + - name: events + in: query + description: >- + Filter by multiple event names, case-insensitive, partial matches are + allowed. + required: false + type: array + items: + type: string + - name: includeAllEvents + in: query + description: >- + Require all provided events to be present on a challenge for a match + required: false + default: true + type: boolean - name: projectId in: query description: 'Filter by v5 project id, exact match.' diff --git a/src/services/ChallengeService.js b/src/services/ChallengeService.js index cd0adcfc..4db7ea81 100644 --- a/src/services/ChallengeService.js +++ b/src/services/ChallengeService.js @@ -154,7 +154,7 @@ async function searchChallenges (currentUser, criteria) { _.forIn(_.omit(criteria, ['types', 'tracks', 'typeIds', 'trackIds', 'type', 'name', 'trackId', 'typeId', 'description', 'page', 'perPage', 'tag', 'group', 'groups', 'memberId', 'ids', 'createdDateStart', 'createdDateEnd', 'updatedDateStart', 'updatedDateEnd', 'startDateStart', 'startDateEnd', 'endDateStart', 'endDateEnd', 'tags', 'registrationStartDateStart', 'registrationStartDateEnd', 'currentPhaseName', 'submissionStartDateStart', 'submissionStartDateEnd', - 'registrationEndDateStart', 'registrationEndDateEnd', 'submissionEndDateStart', 'submissionEndDateEnd', + 'registrationEndDateStart', 'registrationEndDateEnd', 'submissionEndDateStart', 'submissionEndDateEnd', 'includeAllEvents', 'events', 'forumId', 'track', 'reviewType', 'confidentialityType', 'directProjectId', 'sortBy', 'sortOrder', 'isLightweight', 'isTask', 'taskIsAssigned', 'taskMemberId']), (value, key) => { if (!_.isUndefined(value)) { const filter = { match_phrase: {} } @@ -274,6 +274,18 @@ async function searchChallenges (currentUser, criteria) { } } + if (criteria.events) { + if (criteria.includeAllEvents) { + for (const e of criteria.events) { + boolQuery.push({ match_phrase: { 'events.name': e } }) + } + } else { + for (const e of criteria.events) { + shouldQuery.push({ match: { 'events.name': e } }) + } + } + } + const mustNotQuery = [] let groupsToFilter = [] @@ -577,7 +589,9 @@ searchChallenges.schema = { ids: Joi.array().items(Joi.optionalId()).unique().min(1), isTask: Joi.boolean(), taskIsAssigned: Joi.boolean(), - taskMemberId: Joi.string() + taskMemberId: Joi.string(), + events: Joi.array().items(Joi.string()), + includeAllEvents: Joi.boolean().default(true) }) } From c2abdef57cf489124d31ab0d3dd5b921b1b6384e Mon Sep 17 00:00:00 2001 From: Thomas Kranitsas Date: Tue, 1 Sep 2020 17:00:07 +0300 Subject: [PATCH 09/13] Update to filter on events.id instead of events.name --- docs/swagger.yaml | 5 ++--- src/services/ChallengeService.js | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 9a2715a2..10a77970 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -184,12 +184,11 @@ paths: - name: events in: query description: >- - Filter by multiple event names, case-insensitive, partial matches are - allowed. + Filter by multiple event IDs required: false type: array items: - type: string + type: number - name: includeAllEvents in: query description: >- diff --git a/src/services/ChallengeService.js b/src/services/ChallengeService.js index 4db7ea81..ee16830c 100644 --- a/src/services/ChallengeService.js +++ b/src/services/ChallengeService.js @@ -277,11 +277,11 @@ async function searchChallenges (currentUser, criteria) { if (criteria.events) { if (criteria.includeAllEvents) { for (const e of criteria.events) { - boolQuery.push({ match_phrase: { 'events.name': e } }) + boolQuery.push({ match_phrase: { 'events.id': e } }) } } else { for (const e of criteria.events) { - shouldQuery.push({ match: { 'events.name': e } }) + shouldQuery.push({ match: { 'events.id': e } }) } } } @@ -590,7 +590,7 @@ searchChallenges.schema = { isTask: Joi.boolean(), taskIsAssigned: Joi.boolean(), taskMemberId: Joi.string(), - events: Joi.array().items(Joi.string()), + events: Joi.array().items(Joi.number()), includeAllEvents: Joi.boolean().default(true) }) } From 746dfc7421b29204bb2789ab7c8fc45008515b44 Mon Sep 17 00:00:00 2001 From: James Cori Date: Tue, 1 Sep 2020 14:31:34 -0400 Subject: [PATCH 10/13] Fixing it to filter on key, not id --- docs/swagger.yaml | 2 +- src/services/ChallengeService.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 10a77970..5abf2b5d 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -184,7 +184,7 @@ paths: - name: events in: query description: >- - Filter by multiple event IDs + Filter by multiple event keys (ie: tco21) required: false type: array items: diff --git a/src/services/ChallengeService.js b/src/services/ChallengeService.js index ee16830c..c9a7bf41 100644 --- a/src/services/ChallengeService.js +++ b/src/services/ChallengeService.js @@ -277,11 +277,11 @@ async function searchChallenges (currentUser, criteria) { if (criteria.events) { if (criteria.includeAllEvents) { for (const e of criteria.events) { - boolQuery.push({ match_phrase: { 'events.id': e } }) + boolQuery.push({ match_phrase: { 'events.key': e } }) } } else { for (const e of criteria.events) { - shouldQuery.push({ match: { 'events.id': e } }) + shouldQuery.push({ match: { 'events.key': e } }) } } } From 73852ff7a76cdc94a6a03c49ced86ffc2167b3ab Mon Sep 17 00:00:00 2001 From: Thomas Kranitsas Date: Thu, 3 Sep 2020 16:34:25 +0300 Subject: [PATCH 11/13] Fix issues with tasks on listings --- src/services/ChallengeService.js | 52 ++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/src/services/ChallengeService.js b/src/services/ChallengeService.js index cd0adcfc..dfecb36c 100644 --- a/src/services/ChallengeService.js +++ b/src/services/ChallengeService.js @@ -342,6 +342,29 @@ async function searchChallenges (currentUser, criteria) { } } + const accessQuery = [] + let memberChallengeIds + + // FIXME: This is wrong! + // if (!_.isUndefined(currentUser) && currentUser.handle) { + // accessQuery.push({ match_phrase: { createdBy: currentUser.handle } }) + // } + + if (criteria.memberId) { + // logger.error(`memberId ${criteria.memberId}`) + memberChallengeIds = await helper.listChallengesByMember(criteria.memberId) + // logger.error(`response ${JSON.stringify(ids)}`) + accessQuery.push({ terms: { _id: memberChallengeIds } }) + } + + if (accessQuery.length > 0) { + mustQuery.push({ + bool: { + should: accessQuery + } + }) + } + // FIXME: Tech Debt let excludeTasks = true // if you're an admin or m2m, security rules wont be applied @@ -372,6 +395,7 @@ async function searchChallenges (currentUser, criteria) { mustQuery.push({ bool: { should: [ + ...(_.get(memberChallengeIds, 'length', 0) > 0 ? { terms: { _id: memberChallengeIds } } : {}), { bool: { must_not: { exists: { field: 'task.isTask' } } } }, { match_phrase: { 'task.isTask': false } }, { @@ -400,28 +424,6 @@ async function searchChallenges (currentUser, criteria) { }) } - const accessQuery = [] - - // FIXME: This is wrong! - // if (!_.isUndefined(currentUser) && currentUser.handle) { - // accessQuery.push({ match_phrase: { createdBy: currentUser.handle } }) - // } - - if (criteria.memberId) { - // logger.error(`memberId ${criteria.memberId}`) - const ids = await helper.listChallengesByMember(criteria.memberId) - // logger.error(`response ${JSON.stringify(ids)}`) - accessQuery.push({ terms: { _id: ids } }) - } - - if (accessQuery.length > 0) { - mustQuery.push({ - bool: { - should: accessQuery - } - }) - } - if (boolQuery.length > 0) { mustQuery.push({ bool: { @@ -722,6 +724,12 @@ async function createChallenge (currentUser, challenge, userToken) { const { track, type } = await validateChallengeData(challenge) if (_.get(type, 'isTask')) { _.set(challenge, 'task.isTask', true) + if (_.isUndefined(_.get(challenge, 'task.isAssigned'))) { + _.set(challenge, 'task.isAssigned', false) + } + if (_.isUndefined(_.get(challenge, 'task.memberId'))) { + _.set(challenge, 'task.memberId', null) + } } if (challenge.phases && challenge.phases.length > 0) { await helper.validatePhases(challenge.phases) From 1d0ca0707dfc3dacf85a98e6827fac2ec333173e Mon Sep 17 00:00:00 2001 From: Thomas Kranitsas Date: Thu, 3 Sep 2020 17:12:49 +0300 Subject: [PATCH 12/13] fix query --- src/services/ChallengeService.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/ChallengeService.js b/src/services/ChallengeService.js index 552ffd74..cdac520f 100644 --- a/src/services/ChallengeService.js +++ b/src/services/ChallengeService.js @@ -407,7 +407,7 @@ async function searchChallenges (currentUser, criteria) { mustQuery.push({ bool: { should: [ - ...(_.get(memberChallengeIds, 'length', 0) > 0 ? { terms: { _id: memberChallengeIds } } : {}), + ...(_.get(memberChallengeIds, 'length', 0) > 0 ? [{ terms: { _id: memberChallengeIds } }] : []), { bool: { must_not: { exists: { field: 'task.isTask' } } } }, { match_phrase: { 'task.isTask': false } }, { From e0cc722a3d26c70190473ee15b1d742931a535c2 Mon Sep 17 00:00:00 2001 From: Thomas Kranitsas Date: Thu, 3 Sep 2020 19:37:09 +0300 Subject: [PATCH 13/13] fix /challenges/:uuid --- src/services/ChallengeService.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/services/ChallengeService.js b/src/services/ChallengeService.js index cdac520f..88bb4c26 100644 --- a/src/services/ChallengeService.js +++ b/src/services/ChallengeService.js @@ -947,18 +947,12 @@ async function getChallenge (currentUser, id) { // } // delete challenge.typeId - // Check if challenge is task and apply security rules - if (_.get(challenge, 'task.isTask', false) && _.get(challenge, 'task.isAssigned', false)) { - if (!currentUser || (!currentUser.isMachine && !helper.hasAdminRole(currentUser) && _.toString(currentUser.userId) !== _.toString(_.get(challenge, 'task.memberId')))) { - throw new errors.ForbiddenError(`You don't have access to view this challenge`) - } - } - + let memberChallengeIds // Remove privateDescription for unregistered users if (currentUser) { if (!currentUser.isMachine) { - const ids = await helper.listChallengesByMember(currentUser.userId) - if (!_.includes(ids, challenge.id)) { + memberChallengeIds = await helper.listChallengesByMember(currentUser.userId) + if (!_.includes(memberChallengeIds, challenge.id)) { _.unset(challenge, 'privateDescription') } } @@ -966,6 +960,14 @@ async function getChallenge (currentUser, id) { _.unset(challenge, 'privateDescription') } + // Check if challenge is task and apply security rules + if (_.get(challenge, 'task.isTask', false) && _.get(challenge, 'task.isAssigned', false)) { + const canAccesChallenge = _.isUndefined(currentUser) ? false : _.includes((memberChallengeIds || []), challenge.id) || currentUser.isMachine || helper.hasAdminRole(currentUser) + if (!canAccesChallenge) { + throw new errors.ForbiddenError(`You don't have access to view this challenge`) + } + } + if (challenge.phases && challenge.phases.length > 0) { await getPhasesAndPopulate(challenge) }