@@ -109,6 +109,15 @@ async function searchChallenges (currentUser, criteria) {
109
109
const page = criteria . page || 1
110
110
const perPage = criteria . perPage || 20
111
111
const boolQuery = [ ]
112
+ const matchPhraseKeys = [
113
+ 'id' ,
114
+ 'timelineTemplateId' ,
115
+ 'projectId' ,
116
+ 'legacyId' ,
117
+ 'status' ,
118
+ 'createdBy' ,
119
+ 'updatedBy'
120
+ ]
112
121
113
122
const includedTrackIds = _ . isArray ( criteria . trackIds ) ? criteria . trackIds : [ ]
114
123
@@ -151,18 +160,24 @@ async function searchChallenges (currentUser, criteria) {
151
160
includedTrackIds . push ( criteria . trackId )
152
161
}
153
162
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 ) => {
159
164
if ( ! _ . isUndefined ( value ) ) {
160
165
const filter = { match_phrase : { } }
161
166
filter . match_phrase [ key ] = value
162
167
boolQuery . push ( filter )
163
168
}
164
169
} )
165
170
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
+
166
181
if ( includedTypeIds . length > 0 ) {
167
182
boolQuery . push ( {
168
183
bool : {
@@ -594,7 +609,7 @@ searchChallenges.schema = {
594
609
taskMemberId : Joi . string ( ) ,
595
610
events : Joi . array ( ) . items ( Joi . number ( ) ) ,
596
611
includeAllEvents : Joi . boolean ( ) . default ( true )
597
- } )
612
+ } ) . unknown ( true )
598
613
}
599
614
600
615
/**
@@ -743,6 +758,8 @@ async function createChallenge (currentUser, challenge, userToken) {
743
758
}
744
759
if ( _ . isUndefined ( _ . get ( challenge , 'task.memberId' ) ) ) {
745
760
_ . set ( challenge , 'task.memberId' , null )
761
+ } else {
762
+ throw new errors . BadRequestError ( `Cannot assign a member before the challenge gets created.` )
746
763
}
747
764
}
748
765
if ( challenge . phases && challenge . phases . length > 0 ) {
@@ -1164,8 +1181,9 @@ async function update (currentUser, challengeId, data, userToken, isFull) {
1164
1181
newAttachments = await helper . getByIds ( 'Attachment' , data . attachmentIds || [ ] )
1165
1182
}
1166
1183
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.` )
1169
1187
}
1170
1188
1171
1189
// Validate the challenge terms
@@ -1424,6 +1442,18 @@ async function update (currentUser, challengeId, data, userToken, isFull) {
1424
1442
data . winners = null
1425
1443
}
1426
1444
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
+
1427
1457
logger . debug ( `Challenge.update id: ${ challengeId } Details: ${ JSON . stringify ( updateDetails ) } ` )
1428
1458
await models . Challenge . update ( { id : challengeId } , updateDetails )
1429
1459
@@ -1464,7 +1494,6 @@ async function update (currentUser, challengeId, data, userToken, isFull) {
1464
1494
}
1465
1495
1466
1496
// Populate challenge.track and challenge.type based on the track/type IDs
1467
- const { track, type } = await validateChallengeData ( _ . pick ( challenge , [ 'trackId' , 'typeId' ] ) )
1468
1497
1469
1498
if ( track ) {
1470
1499
challenge . track = track . name
0 commit comments