@@ -109,6 +109,15 @@ async function searchChallenges (currentUser, criteria) {
109109 const page = criteria . page || 1
110110 const perPage = criteria . perPage || 20
111111 const boolQuery = [ ]
112+ const matchPhraseKeys = [
113+ 'id' ,
114+ 'timelineTemplateId' ,
115+ 'projectId' ,
116+ 'legacyId' ,
117+ 'status' ,
118+ 'createdBy' ,
119+ 'updatedBy'
120+ ]
112121
113122 const includedTrackIds = _ . isArray ( criteria . trackIds ) ? criteria . trackIds : [ ]
114123
@@ -151,18 +160,24 @@ async function searchChallenges (currentUser, criteria) {
151160 includedTrackIds . push ( criteria . trackId )
152161 }
153162
154- _ . forIn ( _ . omit ( criteria , [ 'types' , 'tracks' , 'typeIds' , 'trackIds' , 'type' , 'name' , 'trackId' , 'typeId' , 'description' , 'page' , 'perPage' , 'tag' ,
155- 'group' , 'groups' , 'memberId' , 'ids' , 'createdDateStart' , 'createdDateEnd' , 'updatedDateStart' , 'updatedDateEnd' , 'startDateStart' , 'startDateEnd' , 'endDateStart' , 'endDateEnd' ,
156- 'tags' , 'registrationStartDateStart' , 'registrationStartDateEnd' , 'currentPhaseName' , 'submissionStartDateStart' , 'submissionStartDateEnd' ,
157- 'registrationEndDateStart' , 'registrationEndDateEnd' , 'submissionEndDateStart' , 'submissionEndDateEnd' , 'includeAllEvents' , 'events' ,
158- 'forumId' , 'track' , 'reviewType' , 'confidentialityType' , 'directProjectId' , 'sortBy' , 'sortOrder' , 'isLightweight' , 'isTask' , 'taskIsAssigned' , 'taskMemberId' ] ) , ( value , key ) => {
163+ _ . forIn ( _ . pick ( criteria , matchPhraseKeys ) , ( value , key ) => {
159164 if ( ! _ . isUndefined ( value ) ) {
160165 const filter = { match_phrase : { } }
161166 filter . match_phrase [ key ] = value
162167 boolQuery . push ( filter )
163168 }
164169 } )
165170
171+ _ . forEach ( _ . keys ( criteria ) , ( key ) => {
172+ if ( _ . toString ( key ) . indexOf ( 'meta.' ) > - 1 ) {
173+ // Parse and use metadata key
174+ if ( ! _ . isUndefined ( criteria [ key ] ) ) {
175+ const metaKey = key . split ( 'meta.' ) [ 1 ]
176+ boolQuery . push ( { match_phrase : { [ `metadata.${ metaKey } ` ] : criteria [ key ] } } )
177+ }
178+ }
179+ } )
180+
166181 if ( includedTypeIds . length > 0 ) {
167182 boolQuery . push ( {
168183 bool : {
@@ -594,7 +609,7 @@ searchChallenges.schema = {
594609 taskMemberId : Joi . string ( ) ,
595610 events : Joi . array ( ) . items ( Joi . number ( ) ) ,
596611 includeAllEvents : Joi . boolean ( ) . default ( true )
597- } )
612+ } ) . unknown ( true )
598613}
599614
600615/**
@@ -743,6 +758,8 @@ async function createChallenge (currentUser, challenge, userToken) {
743758 }
744759 if ( _ . isUndefined ( _ . get ( challenge , 'task.memberId' ) ) ) {
745760 _ . set ( challenge , 'task.memberId' , null )
761+ } else {
762+ throw new errors . BadRequestError ( `Cannot assign a member before the challenge gets created.` )
746763 }
747764 }
748765 if ( challenge . phases && challenge . phases . length > 0 ) {
@@ -1164,8 +1181,9 @@ async function update (currentUser, challengeId, data, userToken, isFull) {
11641181 newAttachments = await helper . getByIds ( 'Attachment' , data . attachmentIds || [ ] )
11651182 }
11661183
1167- if ( ! currentUser . isMachine && ! helper . hasAdminRole ( currentUser ) && challenge . createdBy . toLowerCase ( ) !== currentUser . handle . toLowerCase ( ) ) {
1168- throw new errors . ForbiddenError ( `Only M2M, admin or challenge's copilot can perform modification.` )
1184+ const userHasFullAccess = await helper . userHasFullAccess ( challengeId , currentUser . userId )
1185+ if ( ! currentUser . isMachine && ! helper . hasAdminRole ( currentUser ) && challenge . createdBy . toLowerCase ( ) !== currentUser . handle . toLowerCase ( ) && ! userHasFullAccess ) {
1186+ throw new errors . ForbiddenError ( `Only M2M, admin, challenge's copilot or users with full access can perform modification.` )
11691187 }
11701188
11711189 // Validate the challenge terms
@@ -1424,6 +1442,18 @@ async function update (currentUser, challengeId, data, userToken, isFull) {
14241442 data . winners = null
14251443 }
14261444
1445+ const { track, type } = await validateChallengeData ( _ . pick ( challenge , [ 'trackId' , 'typeId' ] ) )
1446+
1447+ if ( _ . get ( type , 'isTask' ) ) {
1448+ if ( ! _ . isEmpty ( _ . get ( data , 'task.memberId' ) ) ) {
1449+ const challengeResources = await helper . getChallengeResources ( challengeId )
1450+ const registrants = _ . filter ( challengeResources , r => r . roleId === config . SUBMITTER_ROLE_ID )
1451+ if ( ! _ . find ( registrants , r => _ . toString ( r . memberId ) === _ . toString ( _ . get ( data , 'task.memberId' ) ) ) ) {
1452+ throw new errors . BadRequestError ( `Member ${ _ . get ( data , 'task.memberId' ) } is not a submitter resource of challenge ${ challengeId } ` )
1453+ }
1454+ }
1455+ }
1456+
14271457 logger . debug ( `Challenge.update id: ${ challengeId } Details: ${ JSON . stringify ( updateDetails ) } ` )
14281458 await models . Challenge . update ( { id : challengeId } , updateDetails )
14291459
@@ -1464,7 +1494,6 @@ async function update (currentUser, challengeId, data, userToken, isFull) {
14641494 }
14651495
14661496 // Populate challenge.track and challenge.type based on the track/type IDs
1467- const { track, type } = await validateChallengeData ( _ . pick ( challenge , [ 'trackId' , 'typeId' ] ) )
14681497
14691498 if ( track ) {
14701499 challenge . track = track . name
0 commit comments