diff --git a/app-routes.js b/app-routes.js index d3987ba2..1c407aee 100644 --- a/app-routes.js +++ b/app-routes.js @@ -59,6 +59,36 @@ module.exports = (app) => { next() } }) + } else { + // public API, but still try to authenticate token if provided, but allow missing/invalid token + actions.push((req, res, next) => { + const interceptRes = {} + interceptRes.status = () => interceptRes + interceptRes.json = () => interceptRes + interceptRes.send = () => next() + authenticator(_.pick(config, ['AUTH_SECRET', 'VALID_ISSUERS']))(req, interceptRes, next) + }) + + actions.push((req, res, next) => { + if (!req.authUser) { + next() + } else if (req.authUser.isMachine) { + if (!def.scopes || !req.authUser.scopes || !helper.checkIfExists(def.scopes, req.authUser.scopes)) { + req.authUser = undefined + } + next() + } else { + req.authUser.jwtToken = req.headers.authorization + // check if user has full manage permission + if (_.intersection(req.authUser.roles, constants.FullManagePermissionRoles).length) { + req.authUser.hasManagePermission = true + } + if (_.includes(req.authUser.roles, constants.UserRoles.ConnectManager)) { + req.authUser.isConnectManager = true + } + next() + } + }) } actions.push(method) diff --git a/docs/Topcoder-bookings-api.postman_collection.json b/docs/Topcoder-bookings-api.postman_collection.json index 845523ab..a3e40abe 100644 --- a/docs/Topcoder-bookings-api.postman_collection.json +++ b/docs/Topcoder-bookings-api.postman_collection.json @@ -1,6 +1,6 @@ { "info": { - "_postman_id": "6f274c86-24a5-412e-95e6-fafa34e2a936", + "_postman_id": "15f10b58-dda5-4aaf-96e5-061a5c901717", "name": "Topcoder-bookings-api", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" }, @@ -18153,16 +18153,14 @@ "response": [] }, { - "name": "send request with invalid token", + "name": "send request with public", "event": [ { "listen": "test", "script": { "exec": [ - "pm.test('Status code is 401', function () {\r", - " pm.response.to.have.status(401);\r", - " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"Invalid Token.\")\r", + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", "});" ], "type": "text/javascript" @@ -18171,16 +18169,10 @@ ], "request": { "method": "POST", - "header": [ - { - "key": "Authorization", - "value": "Bearer invalid_token", - "type": "text" - } - ], + "header": [], "body": { "mode": "raw", - "raw": "{\r\n \"jobDescription\": \"Should have these skills: Machine Learning, Dropwizard, NGINX, appcelerator\"\r\n}", + "raw": "{\r\n \"jobDescription\": \"Should have these skills: Machine Learning, Dropwizard, NGINX, appcelerator, C#\"\r\n}", "options": { "raw": { "language": "json" @@ -18210,7 +18202,7 @@ "pm.test('Status code is 400', function () {\r", " pm.response.to.have.status(400);\r", " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"\\\"data\\\" must have at least 1 key\")\r", + " pm.expect(response.message).to.eq(\"\\\"data\\\" must contain at least one of [roleId, jobDescription, skills]\")\r", "});" ], "type": "text/javascript" @@ -19211,71 +19203,7 @@ ], "request": { "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_administrator}}" - }, - { - "key": "Content-Type", - "type": "text", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{ \"description\": \"Description A global leading healthcare company is seeking a strong Databricks Engineer to join their development team as they build their new Databricks workspace. Development efforts will contribute to the migration of data from Hadoop to Databricks to prepare data for visualization. Candidate must be well-versed in Databricks components and best practices, be an excellent problem solver and be comfortable working in a fast-moving, rapidly changing, and dynamic environment via Agile, SCRUM, and DevOps. PREFERRED QUALIFICATIONS: 2+ years of Azure Data Stack experience: Azure Data Services using ADF, ADLS, Databricks with PySpark, Azure DevOps & Azure Key Vault. Strong knowledge of various data warehousing methodologies and data modeling concepts. Hands-on experience using Azure, Azure data lake, Azure functions & Databricks Minimum 2-3+ years of Python experience (PySpark) Design & Develop Azure native solutions for Data Platform Minimum 3+ years of experience using Big Data ecosystem (Cloudera/Hortonworks) using Oozie, Hive, Impala, and Spark Expert in SQL and performance tuning\" }", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{URL}}/taas-teams/getSkillsByJobDescription", - "host": [ - "{{URL}}" - ], - "path": [ - "taas-teams", - "getSkillsByJobDescription" - ] - } - }, - "response": [] - }, - { - "name": "get skills by invalid token", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test('Status code is 401', function () {\r", - " pm.response.to.have.status(401);\r", - " const response = pm.response.json()\r", - " pm.expect(response.message).to.eq(\"Invalid Token.\")\r", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer invalid_token" - }, - { - "key": "Content-Type", - "type": "text", - "value": "application/json" - } - ], + "header": [], "body": { "mode": "raw", "raw": "{ \"description\": \"Description A global leading healthcare company is seeking a strong Databricks Engineer to join their development team as they build their new Databricks workspace. Development efforts will contribute to the migration of data from Hadoop to Databricks to prepare data for visualization. Candidate must be well-versed in Databricks components and best practices, be an excellent problem solver and be comfortable working in a fast-moving, rapidly changing, and dynamic environment via Agile, SCRUM, and DevOps. PREFERRED QUALIFICATIONS: 2+ years of Azure Data Stack experience: Azure Data Services using ADF, ADLS, Databricks with PySpark, Azure DevOps & Azure Key Vault. Strong knowledge of various data warehousing methodologies and data modeling concepts. Hands-on experience using Azure, Azure data lake, Azure functions & Databricks Minimum 2-3+ years of Python experience (PySpark) Design & Develop Azure native solutions for Data Platform Minimum 3+ years of experience using Big Data ecosystem (Cloudera/Hortonworks) using Oozie, Hive, Impala, and Spark Expert in SQL and performance tuning\" }", @@ -19317,18 +19245,7 @@ ], "request": { "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_administrator}}" - }, - { - "key": "Content-Type", - "type": "text", - "value": "application/json" - } - ], + "header": [], "body": { "mode": "raw", "raw": "{ \"description\": \"\" }", @@ -19370,18 +19287,7 @@ ], "request": { "method": "POST", - "header": [ - { - "key": "Authorization", - "type": "text", - "value": "Bearer {{token_administrator}}" - }, - { - "key": "Content-Type", - "type": "text", - "value": "application/json" - } - ], + "header": [], "body": { "mode": "raw", "raw": "{}", diff --git a/src/common/helper.js b/src/common/helper.js index 773dde0f..5f9f13db 100644 --- a/src/common/helper.js +++ b/src/common/helper.js @@ -1960,8 +1960,8 @@ function removeTextFormatting (text) { // Remove footnotes text = _.replace(text, /\[\^.+?\](: .*?$)?/g, ' ') text = _.replace(text, /\s{0,2}\[.*?\]: .*?$/g, ' ') - // Remove images - text = _.replace(text, /!\[(.*?)\][[(].*?[\])]/g, ' $1 ') + // Remove images and keep description unless it is default description "image" + text = _.replace(text, /!(\[((?!image).*?)\]|\[.*?\])[[(].*?[\])]/g, ' $2 ') // Remove inline links text = _.replace(text, /\[(.*?)\][[(].*?[\])]/g, ' $1 ') // Remove blockquotes diff --git a/src/routes/TeamRoutes.js b/src/routes/TeamRoutes.js index a2183d36..b2415e17 100644 --- a/src/routes/TeamRoutes.js +++ b/src/routes/TeamRoutes.js @@ -23,7 +23,7 @@ module.exports = { '/taas-teams/skills': { get: { controller: 'TeamController', - method: 'searchSkills', + method: 'searchSkills' } }, '/taas-teams/me': { @@ -37,7 +37,7 @@ module.exports = { '/taas-teams/getSkillsByJobDescription': { post: { controller: 'TeamController', - method: 'getSkillsByJobDescription', + method: 'getSkillsByJobDescription' } }, '/taas-teams/:id': { @@ -89,7 +89,7 @@ module.exports = { '/taas-teams/sendRoleSearchRequest': { post: { controller: 'TeamController', - method: 'roleSearchRequest', + method: 'roleSearchRequest' } }, '/taas-teams/submitTeamRequest': { diff --git a/src/services/TeamService.js b/src/services/TeamService.js index 14723279..94865aae 100644 --- a/src/services/TeamService.js +++ b/src/services/TeamService.js @@ -13,7 +13,7 @@ const errors = require('../common/errors') const JobService = require('./JobService') const ResourceBookingService = require('./ResourceBookingService') const HttpStatus = require('http-status-codes') -const { Op, where, fn, col } = require('sequelize') +const { Op } = require('sequelize') const models = require('../models') const stopWords = require('../../data/stopWords.json') const { getAuditM2Muser } = require('../common/helper') @@ -769,7 +769,7 @@ async function roleSearchRequest (currentUser, data) { role = await getRoleBySkills(skills) } else { // if only job description is provided, collect skill names from description - const tags = await getSkillsByJobDescription(currentUser, { description: data.jobDescription }) + const tags = await getSkillsByJobDescription({ description: data.jobDescription }) const skills = _.map(tags, 'tag') // find the best matching role role = await getRoleBySkills(skills) @@ -777,7 +777,7 @@ async function roleSearchRequest (currentUser, data) { data.roleId = role.id // create roleSearchRequest entity with found roleId const { id: roleSearchRequestId, jobTitle } = await createRoleSearchRequest(currentUser, data) - const entity = jobTitle ? { jobTitle, roleSearchRequestId } : { roleSearchRequestId }; + const entity = jobTitle ? { jobTitle, roleSearchRequestId } : { roleSearchRequestId } // clean Role role = await _cleanRoleDTO(currentUser, role) // return Role @@ -985,7 +985,7 @@ createRoleSearchRequest.schema = Joi.object() */ async function _cleanRoleDTO (currentUser, role) { // if current user is machine, it means user is not logged in - if (currentUser.isMachine || await isExternalMember(currentUser.userId)) { + if (_.isNil(currentUser) || currentUser.isMachine || await isExternalMember(currentUser.userId)) { role.isExternalMember = true if (role.rates) { role.rates = _.map(role.rates, rate =>