@@ -154,7 +154,7 @@ async function searchChallenges (currentUser, criteria) {
154154 _ . forIn ( _ . omit ( criteria , [ 'types' , 'tracks' , 'typeIds' , 'trackIds' , 'type' , 'name' , 'trackId' , 'typeId' , 'description' , 'page' , 'perPage' , 'tag' ,
155155 'group' , 'groups' , 'memberId' , 'ids' , 'createdDateStart' , 'createdDateEnd' , 'updatedDateStart' , 'updatedDateEnd' , 'startDateStart' , 'startDateEnd' , 'endDateStart' , 'endDateEnd' ,
156156 'tags' , 'registrationStartDateStart' , 'registrationStartDateEnd' , 'currentPhaseName' , 'submissionStartDateStart' , 'submissionStartDateEnd' ,
157- 'registrationEndDateStart' , 'registrationEndDateEnd' , 'submissionEndDateStart' , 'submissionEndDateEnd' ,
157+ 'registrationEndDateStart' , 'registrationEndDateEnd' , 'submissionEndDateStart' , 'submissionEndDateEnd' , 'includeAllEvents' , 'events' ,
158158 'forumId' , 'track' , 'reviewType' , 'confidentialityType' , 'directProjectId' , 'sortBy' , 'sortOrder' , 'isLightweight' , 'isTask' , 'taskIsAssigned' , 'taskMemberId' ] ) , ( value , key ) => {
159159 if ( ! _ . isUndefined ( value ) ) {
160160 const filter = { match_phrase : { } }
@@ -251,7 +251,10 @@ async function searchChallenges (currentUser, criteria) {
251251 if ( criteria . endDateEnd ) {
252252 boolQuery . push ( { range : { endDate : { lte : criteria . endDateEnd } } } )
253253 }
254- const sortByProp = criteria . sortBy ? criteria . sortBy : 'created'
254+
255+ let sortByProp = criteria . sortBy ? criteria . sortBy : 'created'
256+ // If property to sort is text, then use its sub-field 'keyword' for sorting
257+ sortByProp = _ . includes ( constants . challengeTextSortField , sortByProp ) ? sortByProp + '.keyword' : sortByProp
255258 const sortOrderProp = criteria . sortOrder ? criteria . sortOrder : 'desc'
256259
257260 const mustQuery = [ ]
@@ -271,6 +274,18 @@ async function searchChallenges (currentUser, criteria) {
271274 }
272275 }
273276
277+ if ( criteria . events ) {
278+ if ( criteria . includeAllEvents ) {
279+ for ( const e of criteria . events ) {
280+ boolQuery . push ( { match_phrase : { 'events.key' : e } } )
281+ }
282+ } else {
283+ for ( const e of criteria . events ) {
284+ shouldQuery . push ( { match : { 'events.key' : e } } )
285+ }
286+ }
287+ }
288+
274289 const mustNotQuery = [ ]
275290
276291 let groupsToFilter = [ ]
@@ -339,6 +354,29 @@ async function searchChallenges (currentUser, criteria) {
339354 }
340355 }
341356
357+ const accessQuery = [ ]
358+ let memberChallengeIds
359+
360+ // FIXME: This is wrong!
361+ // if (!_.isUndefined(currentUser) && currentUser.handle) {
362+ // accessQuery.push({ match_phrase: { createdBy: currentUser.handle } })
363+ // }
364+
365+ if ( criteria . memberId ) {
366+ // logger.error(`memberId ${criteria.memberId}`)
367+ memberChallengeIds = await helper . listChallengesByMember ( criteria . memberId )
368+ // logger.error(`response ${JSON.stringify(ids)}`)
369+ accessQuery . push ( { terms : { _id : memberChallengeIds } } )
370+ }
371+
372+ if ( accessQuery . length > 0 ) {
373+ mustQuery . push ( {
374+ bool : {
375+ should : accessQuery
376+ }
377+ } )
378+ }
379+
342380 // FIXME: Tech Debt
343381 let excludeTasks = true
344382 // if you're an admin or m2m, security rules wont be applied
@@ -369,6 +407,8 @@ async function searchChallenges (currentUser, criteria) {
369407 mustQuery . push ( {
370408 bool : {
371409 should : [
410+ ...( _ . get ( memberChallengeIds , 'length' , 0 ) > 0 ? [ { terms : { _id : memberChallengeIds } } ] : [ ] ) ,
411+ { bool : { must_not : { exists : { field : 'task.isTask' } } } } ,
372412 { match_phrase : { 'task.isTask' : false } } ,
373413 {
374414 bool : {
@@ -396,28 +436,6 @@ async function searchChallenges (currentUser, criteria) {
396436 } )
397437 }
398438
399- const accessQuery = [ ]
400-
401- // FIXME: This is wrong!
402- // if (!_.isUndefined(currentUser) && currentUser.handle) {
403- // accessQuery.push({ match_phrase: { createdBy: currentUser.handle } })
404- // }
405-
406- if ( criteria . memberId ) {
407- // logger.error(`memberId ${criteria.memberId}`)
408- const ids = await helper . listChallengesByMember ( criteria . memberId )
409- // logger.error(`response ${JSON.stringify(ids)}`)
410- accessQuery . push ( { terms : { _id : ids } } )
411- }
412-
413- if ( accessQuery . length > 0 ) {
414- mustQuery . push ( {
415- bool : {
416- should : accessQuery
417- }
418- } )
419- }
420-
421439 if ( boolQuery . length > 0 ) {
422440 mustQuery . push ( {
423441 bool : {
@@ -465,7 +483,7 @@ async function searchChallenges (currentUser, criteria) {
465483 docs = await esClient . search ( esQuery )
466484 } catch ( e ) {
467485 // Catch error when the ES is fresh and has no data
468- // logger.error(`Query Error from ES ${JSON.stringify(e)}`)
486+ logger . error ( `Query Error from ES ${ JSON . stringify ( e ) } ` )
469487 docs = {
470488 hits : {
471489 total : 0 ,
@@ -573,7 +591,9 @@ searchChallenges.schema = {
573591 ids : Joi . array ( ) . items ( Joi . optionalId ( ) ) . unique ( ) . min ( 1 ) ,
574592 isTask : Joi . boolean ( ) ,
575593 taskIsAssigned : Joi . boolean ( ) ,
576- taskMemberId : Joi . string ( )
594+ taskMemberId : Joi . string ( ) ,
595+ events : Joi . array ( ) . items ( Joi . number ( ) ) ,
596+ includeAllEvents : Joi . boolean ( ) . default ( true )
577597 } )
578598}
579599
@@ -718,6 +738,12 @@ async function createChallenge (currentUser, challenge, userToken) {
718738 const { track, type } = await validateChallengeData ( challenge )
719739 if ( _ . get ( type , 'isTask' ) ) {
720740 _ . set ( challenge , 'task.isTask' , true )
741+ if ( _ . isUndefined ( _ . get ( challenge , 'task.isAssigned' ) ) ) {
742+ _ . set ( challenge , 'task.isAssigned' , false )
743+ }
744+ if ( _ . isUndefined ( _ . get ( challenge , 'task.memberId' ) ) ) {
745+ _ . set ( challenge , 'task.memberId' , null )
746+ }
721747 }
722748 if ( challenge . phases && challenge . phases . length > 0 ) {
723749 await helper . validatePhases ( challenge . phases )
@@ -921,25 +947,27 @@ async function getChallenge (currentUser, id) {
921947 // }
922948 // delete challenge.typeId
923949
924- // Check if challenge is task and apply security rules
925- if ( _ . get ( challenge , 'task.isTask' , false ) && _ . get ( challenge , 'task.isAssigned' , false ) ) {
926- if ( ! currentUser || ( ! currentUser . isMachine && ! helper . hasAdminRole ( currentUser ) && _ . toString ( currentUser . userId ) !== _ . toString ( _ . get ( challenge , 'task.memberId' ) ) ) ) {
927- throw new errors . ForbiddenError ( `You don't have access to view this challenge` )
928- }
929- }
930-
950+ let memberChallengeIds
931951 // Remove privateDescription for unregistered users
932952 if ( currentUser ) {
933953 if ( ! currentUser . isMachine ) {
934- const ids = await helper . listChallengesByMember ( currentUser . userId )
935- if ( ! _ . includes ( ids , challenge . id ) ) {
954+ memberChallengeIds = await helper . listChallengesByMember ( currentUser . userId )
955+ if ( ! _ . includes ( memberChallengeIds , challenge . id ) ) {
936956 _ . unset ( challenge , 'privateDescription' )
937957 }
938958 }
939959 } else {
940960 _ . unset ( challenge , 'privateDescription' )
941961 }
942962
963+ // Check if challenge is task and apply security rules
964+ if ( _ . get ( challenge , 'task.isTask' , false ) && _ . get ( challenge , 'task.isAssigned' , false ) ) {
965+ const canAccesChallenge = _ . isUndefined ( currentUser ) ? false : _ . includes ( ( memberChallengeIds || [ ] ) , challenge . id ) || currentUser . isMachine || helper . hasAdminRole ( currentUser )
966+ if ( ! canAccesChallenge ) {
967+ throw new errors . ForbiddenError ( `You don't have access to view this challenge` )
968+ }
969+ }
970+
943971 if ( challenge . phases && challenge . phases . length > 0 ) {
944972 await getPhasesAndPopulate ( challenge )
945973 }
0 commit comments