Skip to content

Commit 56484f5

Browse files
committed
Merge branch dev into feature/roles-backend-repost
2 parents 83b994c + 79e7783 commit 56484f5

File tree

9 files changed

+167
-29
lines changed

9 files changed

+167
-29
lines changed

config/default.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ module.exports = {
4040

4141
TOPCODER_USERS_API: process.env.TOPCODER_USERS_API || 'https://api.topcoder-dev.com/v3/users',
4242
// the api to find topcoder members
43-
TOPCODER_MEMBERS_API: process.env.TOPCODER_MEMBERS_API || 'https://api.topcoder-dev.com/v3/members',
43+
TOPCODER_MEMBERS_API: process.env.TOPCODER_MEMBERS_API || 'https://api.topcoder-dev.com/v5/members',
4444
// rate limit of requests to user api
4545
MAX_PARALLEL_REQUEST_TOPCODER_USERS_API: process.env.MAX_PARALLEL_REQUEST_TOPCODER_USERS_API || 100,
4646

docs/Topcoder-bookings-api.postman_collection.json

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,113 @@
491491
},
492492
"response": []
493493
},
494+
{
495+
"name": "search jobs with request body",
496+
"protocolProfileBehavior": {
497+
"disableBodyPruning": true
498+
},
499+
"request": {
500+
"method": "GET",
501+
"header": [
502+
{
503+
"key": "Authorization",
504+
"type": "text",
505+
"value": "Bearer {{token_bookingManager}}"
506+
}
507+
],
508+
"body": {
509+
"mode": "raw",
510+
"raw": "{\r\n \"jobIds\": [\"{{jobId}}\",\"{{jobIdCreatedByM2M}}\"]\r\n}",
511+
"options": {
512+
"raw": {
513+
"language": "json"
514+
}
515+
}
516+
},
517+
"url": {
518+
"raw": "{{URL}}/jobs",
519+
"host": [
520+
"{{URL}}"
521+
],
522+
"path": [
523+
"jobs"
524+
],
525+
"query": [
526+
{
527+
"key": "page",
528+
"value": "0",
529+
"disabled": true
530+
},
531+
{
532+
"key": "perPage",
533+
"value": "3",
534+
"disabled": true
535+
},
536+
{
537+
"key": "sortBy",
538+
"value": "id",
539+
"disabled": true
540+
},
541+
{
542+
"key": "sortOrder",
543+
"value": "asc",
544+
"disabled": true
545+
},
546+
{
547+
"key": "projectId",
548+
"value": "21",
549+
"disabled": true
550+
},
551+
{
552+
"key": "externalId",
553+
"value": "1212",
554+
"disabled": true
555+
},
556+
{
557+
"key": "description",
558+
"value": "Dummy",
559+
"disabled": true
560+
},
561+
{
562+
"key": "startDate",
563+
"value": "2020-09-27T04:17:23.131Z",
564+
"disabled": true
565+
},
566+
{
567+
"key": "resourceType",
568+
"value": "Dummy Resource Type",
569+
"disabled": true
570+
},
571+
{
572+
"key": "skill",
573+
"value": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
574+
"disabled": true
575+
},
576+
{
577+
"key": "rateType",
578+
"value": "hourly",
579+
"disabled": true
580+
},
581+
{
582+
"key": "status",
583+
"value": "sourcing",
584+
"disabled": true
585+
},
586+
{
587+
"key": "workload",
588+
"value": "full-time",
589+
"disabled": true
590+
},
591+
{
592+
"key": "title",
593+
"value": "dummy",
594+
"disabled": true
595+
}
596+
]
597+
}
598+
},
599+
"response": []
600+
},
494601
{
495602
"name": "search jobs with with m2m all",
496603
"request": {

docs/swagger.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,11 @@ paths:
183183
type: string
184184
enum: ["sourcing", "in-review", "assigned", "closed", "cancelled"]
185185
description: The rate type.
186+
requestBody:
187+
content:
188+
application/json:
189+
schema:
190+
$ref: "#/components/schemas/JobSearchBody"
186191
responses:
187192
"200":
188193
description: OK
@@ -605,6 +610,12 @@ paths:
605610
"cancelled",
606611
"interview",
607612
"topcoder-rejected",
613+
"applied",
614+
"rejected-pre-screen",
615+
"skills-test",
616+
"phone-screen",
617+
"job-closed",
618+
"offered"
608619
]
609620
description: The job candidate status.
610621
- in: query
@@ -3633,6 +3644,15 @@ components:
36333644
type: string
36343645
example: "topcoder user"
36353646
description: "The user who updated the job last time.(Will get the user info from the token)"
3647+
JobSearchBody:
3648+
properties:
3649+
jobIds:
3650+
type: array
3651+
items:
3652+
type: string
3653+
format: uuid
3654+
description: "The array of job ids"
3655+
36363656
JobRequestBody:
36373657
required:
36383658
- projectId

src/bootstrap.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Joi.rateType = () => Joi.string().valid('hourly', 'daily', 'weekly', 'monthly')
1616
Joi.jobStatus = () => Joi.string().valid('sourcing', 'in-review', 'assigned', 'closed', 'cancelled')
1717
Joi.resourceBookingStatus = () => Joi.string().valid('placed', 'closed', 'cancelled')
1818
Joi.workload = () => Joi.string().valid('full-time', 'fractional')
19-
Joi.jobCandidateStatus = () => Joi.string().valid('open', 'placed', 'selected', 'client rejected - screening', 'client rejected - interview', 'rejected - other', 'cancelled', 'interview', 'topcoder-rejected', 'applied', 'rejected-pre-screen', 'skills-test', 'skills-test', 'phone-screen', 'job-closed')
19+
Joi.jobCandidateStatus = () => Joi.string().valid('open', 'placed', 'selected', 'client rejected - screening', 'client rejected - interview', 'rejected - other', 'cancelled', 'interview', 'topcoder-rejected', 'applied', 'rejected-pre-screen', 'skills-test', 'skills-test', 'phone-screen', 'job-closed', 'offered')
2020
Joi.title = () => Joi.string().max(128)
2121
Joi.paymentStatus = () => Joi.string().valid('pending', 'partially-completed', 'completed', 'cancelled')
2222
Joi.xaiTemplate = () => Joi.string().valid(...allowedXAITemplate)

src/common/helper.js

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,21 +1333,18 @@ async function getMemberDetailsByHandles (handles) {
13331333
}
13341334
const token = await getM2MToken()
13351335
const res = await request
1336-
.get(`${config.TOPCODER_MEMBERS_API}/_search`)
1336+
.get(`${config.TOPCODER_MEMBERS_API}/`)
13371337
.query({
1338-
query: _.map(
1339-
handles,
1340-
(handle) => `handleLower:${handle.toLowerCase()}`
1341-
).join(' OR '),
1342-
fields: 'userId,handle,firstName,lastName,email'
1338+
'handlesLower[]': handles.map(handle => handle.toLowerCase()),
1339+
fields: 'userId,handle,handleLower,firstName,lastName,email'
13431340
})
13441341
.set('Authorization', `Bearer ${token}`)
13451342
.set('Accept', 'application/json')
13461343
localLogger.debug({
13471344
context: 'getMemberDetailsByHandles',
13481345
message: `response body: ${JSON.stringify(res.body)}`
13491346
})
1350-
return _.get(res.body, 'result.content')
1347+
return res.body
13511348
}
13521349

13531350
/**
@@ -1356,17 +1353,14 @@ async function getMemberDetailsByHandles (handles) {
13561353
* @param {String} handle the user handle
13571354
* @returns {Object} the member details
13581355
*/
1359-
async function getV3MemberDetailsByHandle (handle) {
1360-
const token = await getM2MToken()
1361-
const res = await request
1362-
.get(`${config.TOPCODER_MEMBERS_API}/${handle}`)
1363-
.set('Authorization', `Bearer ${token}`)
1364-
.set('Accept', 'application/json')
1365-
localLogger.debug({
1366-
context: 'getV3MemberDetailsByHandle',
1367-
message: `response body: ${JSON.stringify(res.body)}`
1368-
})
1369-
return _.get(res.body, 'result.content')
1356+
async function getMemberDetailsByHandle (handle) {
1357+
const [memberDetails] = await getMemberDetailsByHandles([handle])
1358+
1359+
if (!memberDetails) {
1360+
throw new errors.NotFoundError(`Member details are not found by handle "${handle}".`)
1361+
}
1362+
1363+
return memberDetails
13701364
}
13711365

13721366
/**
@@ -1785,7 +1779,7 @@ module.exports = {
17851779
getAuditM2Muser,
17861780
checkIsMemberOfProject,
17871781
getMemberDetailsByHandles,
1788-
getV3MemberDetailsByHandle,
1782+
getMemberDetailsByHandle,
17891783
getMemberDetailsByEmails,
17901784
createProjectMember,
17911785
listProjectMembers,

src/controllers/JobController.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ async function deleteJob (req, res) {
5757
* @param res the response
5858
*/
5959
async function searchJobs (req, res) {
60+
if (req.body && req.body.jobIds) {
61+
req.query.jobIds = req.body.jobIds
62+
}
6063
const result = await service.searchJobs(req.authUser, req.query)
6164
helper.setResHeaders(req, res, result)
6265
res.send(result.result)

src/services/JobService.js

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,8 @@ async function searchJobs (currentUser, criteria, options = { returnAll: false }
376376
body: {
377377
query: {
378378
bool: {
379-
must: []
379+
must: [],
380+
filter: []
380381
}
381382
},
382383
from: (page - 1) * perPage,
@@ -425,11 +426,19 @@ async function searchJobs (currentUser, criteria, options = { returnAll: false }
425426
})
426427
// If criteria contains projectIds, filter projectId with this value
427428
if (criteria.projectIds) {
428-
esQuery.body.query.bool.filter = [{
429+
esQuery.body.query.bool.filter.push({
429430
terms: {
430431
projectId: criteria.projectIds
431432
}
432-
}]
433+
})
434+
}
435+
// if criteria contains jobIds, filter jobIds with this value
436+
if (criteria.jobIds && criteria.jobIds.length > 0) {
437+
esQuery.body.query.bool.filter.push({
438+
terms: {
439+
_id: criteria.jobIds
440+
}
441+
})
433442
}
434443
logger.debug({ component: 'JobService', context: 'searchJobs', message: `Query: ${JSON.stringify(esQuery)}` })
435444

@@ -454,7 +463,7 @@ async function searchJobs (currentUser, criteria, options = { returnAll: false }
454463
logger.logFullError(err, { component: 'JobService', context: 'searchJobs' })
455464
}
456465
logger.info({ component: 'JobService', context: 'searchJobs', message: 'fallback to DB query' })
457-
const filter = {}
466+
const filter = { [Op.and]: [] }
458467
_.each(_.pick(criteria, [
459468
'projectId',
460469
'externalId',
@@ -481,6 +490,9 @@ async function searchJobs (currentUser, criteria, options = { returnAll: false }
481490
[Op.contains]: [criteria.skill]
482491
}
483492
}
493+
if (criteria.jobIds && criteria.jobIds.length > 0) {
494+
filter[Op.and].push({ id: criteria.jobIds })
495+
}
484496
const jobs = await Job.findAll({
485497
where: filter,
486498
offset: ((page - 1) * perPage),
@@ -518,7 +530,8 @@ searchJobs.schema = Joi.object().keys({
518530
rateType: Joi.rateType(),
519531
workload: Joi.workload(),
520532
status: Joi.jobStatus(),
521-
projectIds: Joi.array().items(Joi.number().integer()).single()
533+
projectIds: Joi.array().items(Joi.number().integer()).single(),
534+
jobIds: Joi.array().items(Joi.string().uuid())
522535
}).required(),
523536
options: Joi.object()
524537
}).required()

src/services/PaymentService.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ async function activateChallenge (id, token) {
153153
async function closeChallenge (id, userHandle, token) {
154154
localLogger.info({ context: 'closeChallenge', message: `Closing challenge ${id}` })
155155
try {
156-
const { userId } = await helper.getV3MemberDetailsByHandle(userHandle)
156+
const { userId } = await helper.getMemberDetailsByHandle(userHandle)
157157
const body = {
158158
status: constants.ChallengeStatus.COMPLETED,
159159
winners: [{

src/services/WorkPeriodService.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,9 @@ async function getWorkPeriod (currentUser, id, fromDb = false) {
177177
if (!resourceBooking.body.hits.total.value) {
178178
throw new errors.NotFoundError()
179179
}
180-
await _checkUserPermissionForGetWorkPeriod(currentUser, resourceBooking.body.hits.hits[0]._source.workPeriods.projectId) // check user permission
181-
return _.find(resourceBooking.body.hits.hits[0]._source.workPeriods, { id })
180+
const workPeriod = _.find(resourceBooking.body.hits.hits[0]._source.workPeriods, { id })
181+
await _checkUserPermissionForGetWorkPeriod(currentUser, workPeriod.projectId) // check user permission
182+
return workPeriod
182183
} catch (err) {
183184
if (helper.isDocumentMissingException(err)) {
184185
throw new errors.NotFoundError(`id: ${id} "WorkPeriod" not found`)

0 commit comments

Comments
 (0)