From bb95af49bf96dc80a8c32b8f68f8108a8390ae54 Mon Sep 17 00:00:00 2001 From: dengjun Date: Sun, 20 Jun 2021 12:29:45 +0800 Subject: [PATCH 01/20] output from part2 API change --- config/custom-environment-variables.js | 1 + .../Community APP.postman_collection.json | 656 ++++++++++++++++++ .../Community APP.postman_environment.json | 39 ++ docs/postman/resume.txt | 1 + docs/swagger.yaml | 178 +++++ package-lock.json | 436 ++++++++---- package.json | 1 + src/server/routes/recruitCRM.js | 8 +- src/server/services/recruitCRM.js | 159 +++++ 9 files changed, 1354 insertions(+), 125 deletions(-) create mode 100644 docs/postman/Community APP.postman_collection.json create mode 100644 docs/postman/Community APP.postman_environment.json create mode 100644 docs/postman/resume.txt create mode 100644 docs/swagger.yaml diff --git a/config/custom-environment-variables.js b/config/custom-environment-variables.js index 75e275d959..75169457dd 100644 --- a/config/custom-environment-variables.js +++ b/config/custom-environment-variables.js @@ -83,6 +83,7 @@ module.exports = { JWT_AUTH: { SECRET: 'AUTH_SECRET', + AUTH_SECRET: 'AUTH_SECRET', VALID_ISSUERS: 'VALID_ISSUERS', }, diff --git a/docs/postman/Community APP.postman_collection.json b/docs/postman/Community APP.postman_collection.json new file mode 100644 index 0000000000..051b83d80a --- /dev/null +++ b/docs/postman/Community APP.postman_collection.json @@ -0,0 +1,656 @@ +{ + "info": { + "_postman_id": "cc8d34ce-b72f-4340-a4c1-737f89157b31", + "name": "Community APP", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "Recruit Api", + "item": [ + { + "name": "Profile", + "item": [ + { + "name": "get profile successfully", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 200', function () {\r", + " pm.response.to.have.status(200);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token}}", + "type": "text" + } + ], + "url": { + "raw": "{{URL}}/recruit/profile", + "host": [ + "{{URL}}" + ], + "path": [ + "recruit", + "profile" + ] + } + }, + "response": [] + }, + { + "name": "get profile with invalid token 1", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{invalid_token_1}}", + "type": "text" + } + ], + "url": { + "raw": "{{URL}}/recruit/profile", + "host": [ + "{{URL}}" + ], + "path": [ + "recruit", + "profile" + ] + } + }, + "response": [] + }, + { + "name": "get profile with invalid token 2", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{invalid_token_2}}", + "type": "text" + } + ], + "url": { + "raw": "{{URL}}/recruit/profile", + "host": [ + "{{URL}}" + ], + "path": [ + "recruit", + "profile" + ] + } + }, + "response": [] + }, + { + "name": "get profile with invalid token 3", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{invalid_token_3}}", + "type": "text" + } + ], + "url": { + "raw": "{{URL}}/recruit/profile", + "host": [ + "{{URL}}" + ], + "path": [ + "recruit", + "profile" + ] + } + }, + "response": [] + }, + { + "name": "get profile with invalid token 4", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{invalid_token_4}}", + "type": "text" + } + ], + "url": { + "raw": "{{URL}}/recruit/profile", + "host": [ + "{{URL}}" + ], + "path": [ + "recruit", + "profile" + ] + } + }, + "response": [] + }, + { + "name": "update profile successfully", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 204', function () {\r", + " pm.response.to.have.status(204);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token}}", + "type": "text" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "resume", + "type": "file", + "src": "./docs/postman/resume.txt" + }, + { + "key": "phone", + "value": "+1123226666", + "type": "text" + }, + { + "key": "availability", + "value": "true", + "type": "text" + } + ] + }, + "url": { + "raw": "{{URL}}/recruit/profile", + "host": [ + "{{URL}}" + ], + "path": [ + "recruit", + "profile" + ] + } + }, + "response": [] + }, + { + "name": "update profile with invalid token 1", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{invalid_token_1}}", + "type": "text" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "resume", + "type": "file", + "src": "./docs/postman/resume.txt" + }, + { + "key": "phone", + "value": "+1123226666", + "type": "text" + }, + { + "key": "availability", + "value": "true", + "type": "text" + } + ] + }, + "url": { + "raw": "{{URL}}/recruit/profile", + "host": [ + "{{URL}}" + ], + "path": [ + "recruit", + "profile" + ] + } + }, + "response": [] + }, + { + "name": "update profile with invalid token 2", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{invalid_token_2}}", + "type": "text" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "resume", + "type": "file", + "src": "./docs/postman/resume.txt" + }, + { + "key": "phone", + "value": "+1123226666", + "type": "text" + }, + { + "key": "availability", + "value": "true", + "type": "text" + } + ] + }, + "url": { + "raw": "{{URL}}/recruit/profile", + "host": [ + "{{URL}}" + ], + "path": [ + "recruit", + "profile" + ] + } + }, + "response": [] + }, + { + "name": "update profile with invalid token 3", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{invalid_token_3}}", + "type": "text" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "resume", + "type": "file", + "src": "./docs/postman/resume.txt" + }, + { + "key": "phone", + "value": "+1123226666", + "type": "text" + }, + { + "key": "availability", + "value": "true", + "type": "text" + } + ] + }, + "url": { + "raw": "{{URL}}/recruit/profile", + "host": [ + "{{URL}}" + ], + "path": [ + "recruit", + "profile" + ] + } + }, + "response": [] + }, + { + "name": "update profile with invalid token 4", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('Status code is 403', function () {\r", + " pm.response.to.have.status(403);\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{invalid_token_4}}", + "type": "text" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "resume", + "type": "file", + "src": "./docs/postman/resume.txt" + }, + { + "key": "phone", + "value": "+1123226666", + "type": "text" + }, + { + "key": "availability", + "value": "true", + "type": "text" + } + ] + }, + "url": { + "raw": "{{URL}}/recruit/profile", + "host": [ + "{{URL}}" + ], + "path": [ + "recruit", + "profile" + ] + } + }, + "response": [] + }, + { + "name": "update profile with invalid field", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "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(\"\\\"availability\\\" must be a boolean\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token}}", + "type": "text" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "resume", + "type": "file", + "src": "./docs/postman/resume.txt" + }, + { + "key": "phone", + "value": "+1123226666", + "type": "text" + }, + { + "key": "availability", + "value": "asdd", + "type": "text" + } + ] + }, + "url": { + "raw": "{{URL}}/recruit/profile", + "host": [ + "{{URL}}" + ], + "path": [ + "recruit", + "profile" + ] + } + }, + "response": [] + }, + { + "name": "update profile with missing field 1", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "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(\"\\\"phone\\\" is required\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token}}", + "type": "text" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "resume", + "type": "file", + "src": "./docs/postman/resume.txt" + }, + { + "key": "availability", + "value": "asdd", + "type": "text" + } + ] + }, + "url": { + "raw": "{{URL}}/recruit/profile", + "host": [ + "{{URL}}" + ], + "path": [ + "recruit", + "profile" + ] + } + }, + "response": [] + }, + { + "name": "update profile with missing field 2", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "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(\"\\\"availability\\\" is required\")\r", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{token}}", + "type": "text" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "resume", + "type": "file", + "src": "./docs/postman/resume.txt" + }, + { + "key": "phone", + "value": "+1123226666", + "type": "text" + } + ] + }, + "url": { + "raw": "{{URL}}/recruit/profile", + "host": [ + "{{URL}}" + ], + "path": [ + "recruit", + "profile" + ] + } + }, + "response": [] + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/docs/postman/Community APP.postman_environment.json b/docs/postman/Community APP.postman_environment.json new file mode 100644 index 0000000000..5e5fc77710 --- /dev/null +++ b/docs/postman/Community APP.postman_environment.json @@ -0,0 +1,39 @@ +{ + "id": "c92b4b6b-ed64-4879-91de-e293128256b0", + "name": "Community APP", + "values": [ + { + "key": "URL", + "value": "localhost:3000/api", + "enabled": true + }, + { + "key": "token", + "value": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ik5VSkZORGd4UlRVME5EWTBOVVkzTlRkR05qTXlRamxETmpOQk5UYzVRVUV3UlRFeU56TTJRUSJ9.eyJodHRwczovL3RvcGNvZGVyLWRldi5jb20vcm9sZXMiOlsiVG9wY29kZXIgVXNlciJdLCJodHRwczovL3RvcGNvZGVyLWRldi5jb20vdXNlcklkIjoiODg3NzQ2MzQiLCJodHRwczovL3RvcGNvZGVyLWRldi5jb20vaGFuZGxlIjoiaXNiaWxpciIsImh0dHBzOi8vdG9wY29kZXItZGV2LmNvbS91c2VyX2lkIjoiYXV0aDB8ODg3NzQ2MzQiLCJodHRwczovL3RvcGNvZGVyLWRldi5jb20vdGNzc28iOiI4ODc3NDYzNHw0ZDczMWRjODNiZTk5OThkOWE1MmUyOTA2OThmNGIwNGZiMmVjNjE1OTliODIxZmYxNjRjYWEzYzhhNmU3IiwiaHR0cHM6Ly90b3Bjb2Rlci1kZXYuY29tL2FjdGl2ZSI6dHJ1ZSwibmlja25hbWUiOiJpc2JpbGlyIiwibmFtZSI6ImVtcmUuaXNiaWxpckBnbWFpbC5jb20iLCJwaWN0dXJlIjoiaHR0cHM6Ly9zLmdyYXZhdGFyLmNvbS9hdmF0YXIvODE3NjNjMzE0ZGU0Y2ZiNGUxNDRhYzU3M2U1NmMxZjY_cz00ODAmcj1wZyZkPWh0dHBzJTNBJTJGJTJGY2RuLmF1dGgwLmNvbSUyRmF2YXRhcnMlMkZlbS5wbmciLCJ1cGRhdGVkX2F0IjoiMjAyMS0wNi0xOVQxNzowNjoyMi4yMzVaIiwiZW1haWwiOiJlbXJlLmlzYmlsaXJAZ21haWwuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImlzcyI6Imh0dHBzOi8vYXV0aC50b3Bjb2Rlci1kZXYuY29tLyIsInN1YiI6ImF1dGgwfDg4Nzc0NjM0IiwiYXVkIjoiQlhXWFVXbmlsVlVQZE4wMXQyU2UyOVR3MlpZTkdadkgiLCJpYXQiOjE2MjQxMjUzMzYsImV4cCI6MTYyNDEyODMzNiwibm9uY2UiOiJjVE5DTFVwRlpXMVJhMm94WkhSdE5WaGpVbk5IVkZGVFdWTjRiRzFCYVVaQ1dHZGpSVWhZVTB0RVZnPT0ifQ.SfKTYecx7A2qbqM3v8lJaC1GSdctNhkTx6laAhe2BJYVX5LdVL82ZM3_9yWqqZDPWHS9ku408Jt1DUMo5vRev34Av0iwJpYIT_4BbmMLeWQGQ3aRB78zp_emkZ5TE1vOnfSJvfsPoQoiLIwohyOUaDzz9MGdjrgYuSEAA1RGdjhVcamFlNNbR-lNMffnWYs0oWi89N5kgvv37JZjpDPAvQbotNT80Vs0JrLr1p71JLFcLFTQJ-bthFmt0922dj47-1MSjUQgOzFMN4JNjZKGtExyLGR7s_ipCQxg9lxHjMD-JNwg0liI20YGfTXZv9QQQ_K2jPkXiatHBQq_v2_Qjg", + "enabled": true + }, + { + "key": "invalid_token_1", + "value": "eyJ", + "enabled": true + }, + { + "key": "invalid_token_2", + "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlcyI6WyJjb3BpbG90IiwiQ29ubmVjdCBTdXBwb3J0Il0sImlzcyI6Imh0dHBzOi8vYXBpLnRvcGNvZGVyLWRldi5jb20iLCJoYW5kbGUiOiJHaG9zdGFyIiwiZXhwIjoxNTQ5ODAwMDc3LCJ1c2VySWQiOiIxNTE3NDMiLCJpYXQiOjE1NDk3OTk0NzcsImVtYWlsIjoiZW1haWxAZG9tYWluLmNvbS56IiwianRpIjoiMTJjMWMxMGItOTNlZi00NTMxLTgzMDUtYmE2NjVmYzRlMWI0In0.2n8k9pb16sE7LOLF_7mjAvEVKgggzS-wS3_8n2-R4RU", + "enabled": true + }, + { + "key": "invalid_token_3", + "value": "", + "enabled": true + }, + { + "key": "invalid_token_4", + "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlcyI6WyJjb3BpbG90IiwiQ29ubmVjdCBTdXBwb3J0Il0sImlzcyI6Imh0dHBzOi8vYXBpLnRvcGNvZGVyLWRldi5jb20iLCJoYW5kbGUiOiJHaG9zdGFyIiwiZXhwIjoxNTQ5ODAwMDc3LCJ1c2VySWQiOiIxNTE3NDMiLCJpYXQiOjE1NDk3OTk0NzcsImVtYWlsIjoiZW1haWxAZG9tYWluLmNvbS56IiwianRpIjoiMTJjMWMxMGItOTNlZi00NTMxLTgzMDUtYmE2NjVmYzRlMWI0In0.2n8k9pb16sE7LOLF_7mjAvEVKgggzS-wS3_8n2-R4RU", + "enabled": true + } + ], + "_postman_variable_scope": "environment", + "_postman_exported_at": "2021-06-19T18:52:31.778Z", + "_postman_exported_using": "Postman/8.6.2" +} \ No newline at end of file diff --git a/docs/postman/resume.txt b/docs/postman/resume.txt new file mode 100644 index 0000000000..a0d9880d43 --- /dev/null +++ b/docs/postman/resume.txt @@ -0,0 +1 @@ +My Resume \ No newline at end of file diff --git a/docs/swagger.yaml b/docs/swagger.yaml new file mode 100644 index 0000000000..8c79142edc --- /dev/null +++ b/docs/swagger.yaml @@ -0,0 +1,178 @@ +openapi: 3.0.0 +info: + title: Community APP + description: Community APP + version: 1.0.0 +servers: + - url: http://local.topcoder-dev.com:3000 +tags: + - name: Profile +paths: + /api/recruit/profile: + get: + tags: + - Profile + description: | + Get Profile of current user + + **Authorization** All topcoder members are allowed. + security: + - bearerAuth: [] + responses: + "200": + description: OK + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/Profile" + "401": + description: Not authenticated + content: + application/json: + schema: + $ref: "#/components/schemas/AuthError" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: "#/components/schemas/AuthError" + "404": + description: Not Found + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "500": + description: Internal Server Error + content: + text/plain:: + schema: + type: string + post: + tags: + - Profile + description: | + Update Profile details of current user + **Authorization** All topcoder members are allowed. + security: + - bearerAuth: [] + requestBody: + content: + multipart/form-data: + schema: + $ref: "#/components/schemas/ProfileUpdate" + responses: + "204": + description: OK + "400": + description: Bad request + content: + application/json: + schema: + oneOf: + - $ref: "#/components/schemas/JoiError" + - $ref: "#/components/schemas/Error" + "401": + description: Not authenticated + content: + application/json: + schema: + $ref: "#/components/schemas/AuthError" + "403": + description: Forbidden + content: + application/json: + schema: + $ref: "#/components/schemas/AuthError" + "404": + description: Not Found + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "500": + description: Internal Server Error + content: + text/plain:: + schema: + type: string +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + schemas: + Profile: + required: + - availability + properties: + phone: + type: string + description: "The phone number of the user" + example: "+1123226666" + resume: + type: string + description: "The resume of the user" + availability: + type: boolean + description: "The availability of the user" + default: true + example: true + ProfileUpdate: + required: + - phone + - availability + properties: + phone: + type: string + description: "The phone number of the user" + example: "(123) 456-7890" + resume: + type: string + format: binary + description: "The resume file of the user" + availability: + type: boolean + description: "The availability of the user" + example: true + Error: + properties: + error: + type: boolean + example: true + status: + type: integer + example: 404 + url: + type: string + format: uri + errObj: + type: object + JoiError: + required: + - message + properties: + message: + type: string + AuthError: + properties: + version: + type: string + result: + type: object + properties: + success: + type: boolean + example: false + status: + type: integer + example: 403 + content: + type: object + properties: + message: + type: string diff --git a/package-lock.json b/package-lock.json index d0f67f50af..d69bbb5673 100644 --- a/package-lock.json +++ b/package-lock.json @@ -729,8 +729,8 @@ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "buffer-from": "1.1.1", + "source-map": "0.6.1" } } } @@ -1333,6 +1333,144 @@ "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", "dev": true }, + "@optimizely/js-sdk-datafile-manager": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@optimizely/js-sdk-datafile-manager/-/js-sdk-datafile-manager-0.8.1.tgz", + "integrity": "sha512-zMfyXQUqJlPoFGTNvreGSneGRnr5hn4jp03ofipIpA/RONNsf7DEi/H/uC4pAZxlYm1r5eHZRwKU6gwZTB31LQ==", + "requires": { + "@optimizely/js-sdk-logging": "0.1.0", + "@optimizely/js-sdk-utils": "0.4.0", + "decompress-response": "4.2.1" + }, + "dependencies": { + "@optimizely/js-sdk-utils": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@optimizely/js-sdk-utils/-/js-sdk-utils-0.4.0.tgz", + "integrity": "sha512-QG2oytnITW+VKTJK+l0RxjaS5VrA6W+AZMzpeg4LCB4Rn4BEKtF+EcW/5S1fBDLAviGq/0TLpkjM3DlFkJ9/Gw==", + "requires": { + "uuid": "3.4.0" + } + }, + "decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "requires": { + "mimic-response": "2.1.0" + } + }, + "mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==" + } + } + }, + "@optimizely/js-sdk-event-processor": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@optimizely/js-sdk-event-processor/-/js-sdk-event-processor-0.8.2.tgz", + "integrity": "sha512-5sVcQFqgKF0R+vJbBXy6ykKTlEfll0Ti0xGeKU3TLILRNvPDxTpVAlyrLfBC/yfF/hopjRPusGp3z9lZnVej0w==", + "requires": { + "@optimizely/js-sdk-logging": "0.1.0", + "@optimizely/js-sdk-utils": "0.4.0" + }, + "dependencies": { + "@optimizely/js-sdk-utils": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@optimizely/js-sdk-utils/-/js-sdk-utils-0.4.0.tgz", + "integrity": "sha512-QG2oytnITW+VKTJK+l0RxjaS5VrA6W+AZMzpeg4LCB4Rn4BEKtF+EcW/5S1fBDLAviGq/0TLpkjM3DlFkJ9/Gw==", + "requires": { + "uuid": "3.4.0" + } + } + } + }, + "@optimizely/js-sdk-logging": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@optimizely/js-sdk-logging/-/js-sdk-logging-0.1.0.tgz", + "integrity": "sha512-Bs2zHvsdNIk2QSg05P6mKIlROHoBIRNStbrVwlePm603CucojKRPlFJG4rt7sFZQOo8xS8I7z1BmE4QI3/ZE9A==", + "requires": { + "@optimizely/js-sdk-utils": "0.1.0" + } + }, + "@optimizely/js-sdk-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@optimizely/js-sdk-utils/-/js-sdk-utils-0.1.0.tgz", + "integrity": "sha512-p7499GgVaX94YmkrwOiEtLgxgjXTPbUQsvETaAil5J7zg1TOA4Wl8ClalLSvCh+AKWkxGdkL4/uM/zfbxPSNNw==", + "requires": { + "uuid": "3.4.0" + } + }, + "@optimizely/optimizely-sdk": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@optimizely/optimizely-sdk/-/optimizely-sdk-4.6.0.tgz", + "integrity": "sha512-xhTWe3Jg4YFCy8VG0c0depur0wumhgD3AnlSnHrTnaDNjuCvmBVrYV3cV3RMt8OJoZZxwQvJ2SJKjj73LMplBQ==", + "requires": { + "@optimizely/js-sdk-datafile-manager": "0.8.1", + "@optimizely/js-sdk-event-processor": "0.8.2", + "@optimizely/js-sdk-logging": "0.1.0", + "@optimizely/js-sdk-utils": "0.4.0", + "json-schema": "0.2.3", + "murmurhash": "0.0.2" + }, + "dependencies": { + "@optimizely/js-sdk-utils": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@optimizely/js-sdk-utils/-/js-sdk-utils-0.4.0.tgz", + "integrity": "sha512-QG2oytnITW+VKTJK+l0RxjaS5VrA6W+AZMzpeg4LCB4Rn4BEKtF+EcW/5S1fBDLAviGq/0TLpkjM3DlFkJ9/Gw==", + "requires": { + "uuid": "3.4.0" + } + } + } + }, + "@optimizely/react-sdk": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@optimizely/react-sdk/-/react-sdk-2.6.0.tgz", + "integrity": "sha512-+f7RCbZ0VmtvbAAA4APq5fglj9gSiP+ibaAEKsBa5rTaWaN5I/SH2+4ywpfjpRNvYXobjAN7YxEXSvXPPTGeig==", + "requires": { + "@optimizely/js-sdk-logging": "0.1.0", + "@optimizely/optimizely-sdk": "4.6.0", + "hoist-non-react-statics": "3.3.2", + "prop-types": "15.7.2", + "utility-types": "3.10.0" + }, + "dependencies": { + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "16.13.1" + } + } + } + }, + "@sideway/address": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.2.tgz", + "integrity": "sha512-idTz8ibqWFrPU8kMirL0CoPH/A29XOzzAzpyN3zQ4kAWnzmNfFmRaoMNN6VI8ske5M73HZyhIaW4OuSFIdM4oA==", + "requires": { + "@hapi/hoek": "9.2.0" + }, + "dependencies": { + "@hapi/hoek": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.0.tgz", + "integrity": "sha512-sqKVVVOe5ivCaXDWivIJYVSaEgdQK9ul7a4Kity5Iw7u9+wBAPbX1RMSnLLmp7O4Vzj0WOWwMAJsTL00xwaNug==" + } + } + }, + "@sideway/formula": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", + "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==" + }, + "@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, "@tanem/svg-injector": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@tanem/svg-injector/-/svg-injector-1.2.1.tgz", @@ -13163,19 +13301,29 @@ } }, "joi": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-13.7.0.tgz", - "integrity": "sha512-xuY5VkHfeOYK3Hdi91ulocfuFopwgbSORmIwzcwHKESQhC7w1kD5jaVSPnqDxS2I8t3RZ9omCKAxNwXN5zG1/Q==", + "version": "17.4.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.4.0.tgz", + "integrity": "sha512-F4WiW2xaV6wc1jxete70Rw4V/VuMd6IN+a5ilZsxG4uYtUXWu2kq9W5P2dz30e7Gmw8RCbY/u/uk+dMPma9tAg==", "requires": { - "hoek": "5.0.4", - "isemail": "3.2.0", - "topo": "3.0.3" + "@hapi/hoek": "9.2.0", + "@hapi/topo": "5.0.0", + "@sideway/address": "4.1.2", + "@sideway/formula": "3.0.0", + "@sideway/pinpoint": "2.0.0" }, "dependencies": { - "hoek": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-5.0.4.tgz", - "integrity": "sha512-Alr4ZQgoMlnere5FZJsIyfIjORBqZll5POhDsF4q64dPuJR6rNxXdDxtHSQq8OXRurhmx+PWYEE8bXRROY8h0w==" + "@hapi/hoek": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.0.tgz", + "integrity": "sha512-sqKVVVOe5ivCaXDWivIJYVSaEgdQK9ul7a4Kity5Iw7u9+wBAPbX1RMSnLLmp7O4Vzj0WOWwMAJsTL00xwaNug==" + }, + "@hapi/topo": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.0.0.tgz", + "integrity": "sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw==", + "requires": { + "@hapi/hoek": "9.2.0" + } } } }, @@ -14256,8 +14404,8 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.2.tgz", "integrity": "sha1-HRdnnAac2l0ECZGgnbwsDbN35V4=", "requires": { - "pseudomap": "^1.0.1", - "yallist": "^2.0.0" + "pseudomap": "1.0.2", + "yallist": "2.1.2" } } } @@ -14965,6 +15113,11 @@ "xtend": "4.0.2" } }, + "murmurhash": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/murmurhash/-/murmurhash-0.0.2.tgz", + "integrity": "sha1-bwe9ihEF5wnCb8iUIMtZMMJFhf4=" + }, "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", @@ -15056,7 +15209,7 @@ "dev": true }, "navigation-component": { - "version": "github:topcoder-platform/navigation-component#ad2d6101c4fe10cc98b6ac1389c28b8b80941de7", + "version": "github:topcoder-platform/navigation-component#a8855ad57a4e6dcb569a244bc5ad4aff083c7a3c", "requires": { "classnames": "2.2.6", "lodash": "4.17.15", @@ -15067,9 +15220,9 @@ }, "dependencies": { "config": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/config/-/config-3.3.3.tgz", - "integrity": "sha512-T3RmZQEAji5KYqUQpziWtyGJFli6Khz7h0rpxDwYNjSkr5ynyTWwO7WpfjHzTXclNCDfSWQRcwMb+NwxJesCKw==", + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/config/-/config-3.3.6.tgz", + "integrity": "sha512-Hj5916C5HFawjYJat1epbyY2PlAgLpBtDUlr0MxGLgo3p5+7kylyvnRY18PqJHgnNWXcdd0eWDemT7eYWuFgwg==", "requires": { "json5": "2.2.0" } @@ -15104,12 +15257,11 @@ } }, "redux": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz", - "integrity": "sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.0.tgz", + "integrity": "sha512-uI2dQN43zqLWCt6B/BMGRMY6db7TTY4qeHHfGeKb3EOhmOKjU3KdWvNLJyqaHRksv/ErdNH7cFZWg9jXtewy4g==", "requires": { - "loose-envify": "1.4.0", - "symbol-observable": "1.2.0" + "@babel/runtime": "7.9.6" } }, "serialize-javascript": { @@ -15128,7 +15280,7 @@ "command-line-args": "5.1.1", "command-line-usage": "5.0.5", "compression": "1.7.4", - "config": "3.3.3", + "config": "3.3.6", "cookie-parser": "1.4.5", "cross-env": "5.2.1", "express": "4.17.1", @@ -15145,7 +15297,7 @@ "react-helmet": "5.2.1", "react-redux": "6.0.1", "react-router-dom": "4.3.1", - "redux": "4.0.5", + "redux": "4.1.0", "redux-actions": "2.6.5", "redux-devtools": "3.5.0", "redux-devtools-dock-monitor": "1.1.3", @@ -23614,13 +23766,13 @@ "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" }, "topcoder-react-lib": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/topcoder-react-lib/-/topcoder-react-lib-1.1.6.tgz", - "integrity": "sha512-i9Btnbd9k6dq569avQA4vz0fIxz/nIUxJ9hMldN+n71JY3Qv9rNL6nVCk3ou/j7mMLwTY3zNajJsUAogjD4uIA==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/topcoder-react-lib/-/topcoder-react-lib-1.1.8.tgz", + "integrity": "sha512-+Op873W6dVze1IpgevXgVN/ikw0IQm00D5GJTI19cD8drx8dZgMgZLk/LP6ydpcL2OQVxCDEYiwOf+VdIigfrg==", "requires": { "@topcoder-platform/tc-auth-lib": "git+https://github.com/topcoder-platform/tc-auth-lib.git#68fdc22464810c51b703a33e529cdbd6d09437de", "auth0-js": "6.8.4", - "config": "3.3.3", + "config": "3.3.6", "isomorphic-fetch": "2.2.1", "le_node": "1.8.0", "lodash": "4.17.15", @@ -23641,13 +23793,13 @@ "@topcoder-platform/tc-auth-lib": { "version": "git+https://github.com/topcoder-platform/tc-auth-lib.git#68fdc22464810c51b703a33e529cdbd6d09437de", "requires": { - "lodash": "4.17.20" + "lodash": "4.17.21" }, "dependencies": { "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" } } }, @@ -23656,19 +23808,18 @@ "resolved": "https://registry.npmjs.org/auth0-js/-/auth0-js-6.8.4.tgz", "integrity": "sha1-Qw3Uystk2NFdabHmIRhPmipkCmE=", "requires": { - "Base64": "~0.1.3", + "Base64": "0.1.4", "json-fallback": "0.0.1", - "jsonp": "~0.0.4", - "qs": "git+https://github.com/jfromaniello/node-querystring.git#fix_ie7_bug_with_arrays", - "reqwest": "^1.1.4", - "trim": "~0.0.1", - "winchan": "^0.1.1", - "xtend": "~2.1.1" + "jsonp": "0.0.4", + "qs": "git+https://github.com/jfromaniello/node-querystring.git#5d96513991635e3e22d7aa54a8584d6ce97cace8", + "reqwest": "1.1.6", + "trim": "0.0.1", + "winchan": "0.1.4", + "xtend": "2.1.2" }, "dependencies": { "qs": { - "version": "git+https://github.com/jfromaniello/node-querystring.git#5d96513991635e3e22d7aa54a8584d6ce97cace8", - "from": "git+https://github.com/jfromaniello/node-querystring.git#fix_ie7_bug_with_arrays" + "version": "git+https://github.com/jfromaniello/node-querystring.git#5d96513991635e3e22d7aa54a8584d6ce97cace8" } } }, @@ -23681,9 +23832,9 @@ } }, "config": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/config/-/config-3.3.3.tgz", - "integrity": "sha512-T3RmZQEAji5KYqUQpziWtyGJFli6Khz7h0rpxDwYNjSkr5ynyTWwO7WpfjHzTXclNCDfSWQRcwMb+NwxJesCKw==", + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/config/-/config-3.3.6.tgz", + "integrity": "sha512-Hj5916C5HFawjYJat1epbyY2PlAgLpBtDUlr0MxGLgo3p5+7kylyvnRY18PqJHgnNWXcdd0eWDemT7eYWuFgwg==", "requires": { "json5": "2.2.0" } @@ -23701,8 +23852,8 @@ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-0.0.7.tgz", "integrity": "sha1-NLkLqyqRGqNHVx2pDyK9NuzYqRk=", "requires": { - "debug": "^2.2.0", - "stream-consume": "^0.1.0" + "debug": "2.6.9", + "stream-consume": "0.1.1" }, "dependencies": { "debug": { @@ -23725,7 +23876,20 @@ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", "requires": { - "react-is": "^16.7.0" + "react-is": "16.13.1" + } + }, + "idtoken-verifier": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/idtoken-verifier/-/idtoken-verifier-2.2.0.tgz", + "integrity": "sha512-D+KZkWx+4fDsLXrWIfwWOUAdEQczkqzs0REN0qpJ+9axG4kOeFFXXAFEmSfDErGh8dvM4vY8dQRROw9g8ZnNbw==", + "requires": { + "base64-js": "1.3.1", + "crypto-js": "3.3.0", + "es6-promise": "4.2.8", + "jsbn": "1.1.0", + "unfetch": "4.2.0", + "url-join": "4.0.1" } }, "json5": { @@ -23745,9 +23909,9 @@ } }, "mime": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.0.tgz", - "integrity": "sha512-ft3WayFSFUVBuJj7BMLKAQcSlItKtfjsKDDsii3rqFDAZ7t11zRe8ASw/GlmivGwVUYtwkQrxiGGpL6gFvB0ag==" + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==" }, "ms": { "version": "2.1.2", @@ -23764,12 +23928,12 @@ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-6.0.1.tgz", "integrity": "sha512-T52I52Kxhbqy/6TEfBv85rQSDz6+Y28V/pf52vDWs1YRXG19mcFOGfHnY2HsNFHyhP+ST34Aih98fvt6tqwVcQ==", "requires": { - "@babel/runtime": "^7.3.1", - "hoist-non-react-statics": "^3.3.0", - "invariant": "^2.2.4", - "loose-envify": "^1.4.0", - "prop-types": "^15.7.2", - "react-is": "^16.8.2" + "@babel/runtime": "7.9.6", + "hoist-non-react-statics": "3.3.2", + "invariant": "2.2.4", + "loose-envify": "1.4.0", + "prop-types": "15.7.2", + "react-is": "16.13.1" } }, "readable-stream": { @@ -23783,9 +23947,9 @@ } }, "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "requires": { "lru-cache": "6.0.0" } @@ -23800,23 +23964,23 @@ "resolved": "https://registry.npmjs.org/superagent/-/superagent-5.3.1.tgz", "integrity": "sha512-wjJ/MoTid2/RuGCOFtlacyGNxN9QLMgcpYLDQlWFIhhdJ93kNscFonGvrpAHSCVjRVj++DGCglocF7Aej1KHvQ==", "requires": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.2", - "debug": "^4.1.1", - "fast-safe-stringify": "^2.0.7", - "form-data": "^3.0.0", - "formidable": "^1.2.2", - "methods": "^1.1.2", - "mime": "^2.4.6", - "qs": "^6.9.4", - "readable-stream": "^3.6.0", - "semver": "^7.3.2" + "component-emitter": "1.3.0", + "cookiejar": "2.1.2", + "debug": "4.3.1", + "fast-safe-stringify": "2.0.7", + "form-data": "3.0.0", + "formidable": "1.2.2", + "methods": "1.1.2", + "mime": "2.5.2", + "qs": "6.9.4", + "readable-stream": "3.6.0", + "semver": "7.3.5" } }, "tc-core-library-js": { "version": "github:appirio-tech/tc-core-library-js#d16413db30b1eed21c0cf426e185bedb2329ddab", "requires": { - "auth0-js": "9.14.3", + "auth0-js": "9.16.2", "axios": "0.12.0", "bunyan": "1.8.15", "jsonwebtoken": "8.5.1", @@ -23828,17 +23992,17 @@ }, "dependencies": { "auth0-js": { - "version": "9.14.3", - "resolved": "https://registry.npmjs.org/auth0-js/-/auth0-js-9.14.3.tgz", - "integrity": "sha512-UO/fGv9641PUpYjz2nkPaUHzzrhNaJKupJOqt8blj1pD6wBgpZtxUSXBox6Y8md3eTBzpxeWxV+6RKzzERvr1g==", + "version": "9.16.2", + "resolved": "https://registry.npmjs.org/auth0-js/-/auth0-js-9.16.2.tgz", + "integrity": "sha512-cF1nRjmMDezmhJ+ZwwYp23F0gPqU0zNmF/VvTpcwvCrEMl9lAvkCd4iburN1I7G8SYaaIYEfcGedCphpDZw6OQ==", "requires": { - "base64-js": "^1.3.0", - "idtoken-verifier": "^2.0.3", - "js-cookie": "^2.2.0", - "qs": "^6.7.0", - "superagent": "^5.3.1", - "url-join": "^4.0.1", - "winchan": "^0.2.2" + "base64-js": "1.3.1", + "idtoken-verifier": "2.2.0", + "js-cookie": "2.2.1", + "qs": "6.9.4", + "superagent": "5.3.1", + "url-join": "4.0.1", + "winchan": "0.2.2" } }, "winchan": { @@ -23853,38 +24017,38 @@ "resolved": "https://registry.npmjs.org/topcoder-react-utils/-/topcoder-react-utils-0.7.5.tgz", "integrity": "sha512-/jolO/UUCC/FL/MniBMFi9d7Wc1KbzwvgT5STGs4T+7u7R26bQugGPpGVISEPuglsmW0Xybh6iRi+pT/muOkbg==", "requires": { - "babel-runtime": "^6.26.0", - "body-parser": "^1.18.3", - "command-line-args": "^5.0.2", - "command-line-usage": "^5.0.5", - "compression": "^1.7.2", - "config": "^1.30.0", - "cookie-parser": "^1.4.3", - "express": "^4.16.3", - "helmet": "^3.12.1", - "lodash": "^4.17.10", - "moment": "^2.22.2", - "morgan": "^1.9.0", - "node-forge": "^0.7.5", - "prop-types": "^15.6.2", - "raf": "^3.4.0", - "react": "^16.4.1", - "react-css-super-themr": "^2.2.0", - "react-dom": "^16.4.1", - "react-helmet": "^5.2.0", - "react-redux": "^5.0.7", - "react-router-dom": "^4.3.1", - "redux": "^3.7.2", - "redux-actions": "^2.4.0", - "redux-devtools": "^3.4.1", - "redux-devtools-dock-monitor": "^1.1.3", - "redux-devtools-log-monitor": "^1.4.0", - "redux-promise": "^0.6.0", - "request-ip": "^2.0.2", - "serialize-javascript": "^1.5.0", - "serve-favicon": "^2.5.0", - "shortid": "^2.2.8", - "url-parse": "^1.4.1" + "babel-runtime": "6.26.0", + "body-parser": "1.19.0", + "command-line-args": "5.1.1", + "command-line-usage": "5.0.5", + "compression": "1.7.4", + "config": "1.31.0", + "cookie-parser": "1.4.5", + "express": "4.17.1", + "helmet": "3.22.0", + "lodash": "4.17.15", + "moment": "2.25.3", + "morgan": "1.10.0", + "node-forge": "0.7.6", + "prop-types": "15.7.2", + "raf": "3.4.1", + "react": "16.13.1", + "react-css-super-themr": "2.3.0", + "react-dom": "16.13.1", + "react-helmet": "5.2.1", + "react-redux": "5.1.2", + "react-router-dom": "4.3.1", + "redux": "3.7.2", + "redux-actions": "2.6.5", + "redux-devtools": "3.5.0", + "redux-devtools-dock-monitor": "1.1.3", + "redux-devtools-log-monitor": "1.4.0", + "redux-promise": "0.6.0", + "request-ip": "2.1.3", + "serialize-javascript": "1.9.1", + "serve-favicon": "2.5.0", + "shortid": "2.2.15", + "url-parse": "1.4.7" }, "dependencies": { "config": { @@ -23892,7 +24056,7 @@ "resolved": "https://registry.npmjs.org/config/-/config-1.31.0.tgz", "integrity": "sha512-Ep/l9Rd1J9IPueztJfpbOqVzuKHQh4ZODMNt9xqTYdBBNRXbV4oTu34kCkkfdRVcDq0ohtpaeXGgb+c0LQxFRA==", "requires": { - "json5": "^1.0.1" + "json5": "1.0.1" } }, "json5": { @@ -23900,7 +24064,7 @@ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "requires": { - "minimist": "^1.2.0" + "minimist": "1.2.5" } }, "react-redux": { @@ -23908,13 +24072,13 @@ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.1.2.tgz", "integrity": "sha512-Ns1G0XXc8hDyH/OcBHOxNgQx9ayH3SPxBnFCOidGKSle8pKihysQw2rG/PmciUQRoclhVBO8HMhiRmGXnDja9Q==", "requires": { - "@babel/runtime": "^7.1.2", - "hoist-non-react-statics": "^3.3.0", - "invariant": "^2.2.4", - "loose-envify": "^1.1.0", - "prop-types": "^15.6.1", - "react-is": "^16.6.0", - "react-lifecycles-compat": "^3.0.0" + "@babel/runtime": "7.9.6", + "hoist-non-react-statics": "3.3.2", + "invariant": "2.2.4", + "loose-envify": "1.4.0", + "prop-types": "15.7.2", + "react-is": "16.13.1", + "react-lifecycles-compat": "3.0.4" } } } @@ -23929,7 +24093,7 @@ "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", "requires": { - "object-keys": "~0.4.0" + "object-keys": "0.4.0" } }, "yallist": { @@ -24480,6 +24644,11 @@ "object.getownpropertydescriptors": "2.1.0" } }, + "utility-types": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", + "integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==" + }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -26205,6 +26374,25 @@ "hoek": "4.2.1", "joi": "13.7.0", "node-expat": "2.3.18" + }, + "dependencies": { + "joi": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-13.7.0.tgz", + "integrity": "sha512-xuY5VkHfeOYK3Hdi91ulocfuFopwgbSORmIwzcwHKESQhC7w1kD5jaVSPnqDxS2I8t3RZ9omCKAxNwXN5zG1/Q==", + "requires": { + "hoek": "5.0.4", + "isemail": "3.2.0", + "topo": "3.0.3" + }, + "dependencies": { + "hoek": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-5.0.4.tgz", + "integrity": "sha512-Alr4ZQgoMlnere5FZJsIyfIjORBqZll5POhDsF4q64dPuJR6rNxXdDxtHSQq8OXRurhmx+PWYEE8bXRROY8h0w==" + } + } + } } }, "xmlbuilder": { diff --git a/package.json b/package.json index 8f0d6fee5a..7c188001fd 100644 --- a/package.json +++ b/package.json @@ -74,6 +74,7 @@ "i18n-iso-countries": "^3.7.1", "immutable": "^3.8.2", "isomorphic-fetch": "^2.2.1", + "joi": "^17.4.0", "js-beautify": "^1.10.3", "le_node": "^1.7.0", "localStorage": "^1.0.4", diff --git a/src/server/routes/recruitCRM.js b/src/server/routes/recruitCRM.js index 34c1831539..7db1257558 100644 --- a/src/server/routes/recruitCRM.js +++ b/src/server/routes/recruitCRM.js @@ -3,8 +3,13 @@ */ import express from 'express'; +import { middleware } from 'tc-core-library-js'; +import config from 'config'; +import _ from 'lodash'; import RecruitCRMService from '../services/recruitCRM'; +const authenticator = middleware.jwtAuthenticator; +const authenticatorOptions = _.pick(config.SECRET.JWT_AUTH, ['AUTH_SECRET', 'VALID_ISSUERS']); const cors = require('cors'); const multer = require('multer'); @@ -27,5 +32,6 @@ routes.get('/jobs/search', (req, res, next) => new RecruitCRMService().getJobs(r routes.get('/jobs/:id', (req, res, next) => new RecruitCRMService().getJob(req, res, next)); routes.post('/jobs/:id/apply', upload.single('resume'), (req, res, next) => new RecruitCRMService().applyForJob(req, res, next)); routes.get('/candidates/search', (req, res, next) => new RecruitCRMService().searchCandidates(req, res, next)); - +routes.get('/profile', (req, res, next) => authenticator(authenticatorOptions)(req, res, next), (req, res, next) => new RecruitCRMService().getProfile(req, res, next)); +routes.post('/profile', (req, res, next) => authenticator(authenticatorOptions)(req, res, next), upload.single('resume'), (req, res, next) => new RecruitCRMService().updateProfile(req, res, next)); export default routes; diff --git a/src/server/services/recruitCRM.js b/src/server/services/recruitCRM.js index c352dd0dc5..8010ee5f64 100644 --- a/src/server/services/recruitCRM.js +++ b/src/server/services/recruitCRM.js @@ -6,6 +6,7 @@ import config from 'config'; import qs from 'qs'; import _ from 'lodash'; import { logger } from 'topcoder-react-lib'; +import Joi from 'joi'; import GrowsurfService from './growsurf'; import { sendEmailDirect } from './sendGrid'; @@ -62,6 +63,11 @@ function notifyKirilAndNick(error) { }); } +const updateProfileSchema = Joi.object().keys({ + phone: Joi.string().required(), + availability: Joi.boolean().required(), +}).required(); + /** * Auxiliary class that handles communication with recruitCRM */ @@ -449,4 +455,157 @@ export default class RecruitCRMService { return next(err); } } + + /** + * Get user profile endpoint. + * @return {Promise} + * @param {Object} the request. + */ + async getProfile(req, res, next) { + try { + // get candidate by email + const candidate = await this.getCandidateByEmail(req.authUser.email); + // return error if getCandidateByEmail operation failed + if (candidate.error) { + const error = candidate; + logger.error(error); + return res.status(error.status).send(error); + } + // apply desired response format + const responseMapping = { + phone: candidate.contact_number, + resume: candidate.resume, + availability: _.isNill(candidate.available_from) ? true + : new Date(candidate.available_from) <= new Date(), + }; + return res.send(responseMapping); + } catch (err) { + return next(err); + } + } + + /** + * Update user profile endpoint. + * @return {Promise} + * @param {Object} the request. + */ + async updateProfile(req, res, next) { + const { body, file } = req; + // validate provided data + const validationResult = updateProfileSchema.validate(body); + if (validationResult.error) { + return res.status(400).send({ message: validationResult.error.message }); + } + const fileData = new FormData(); + if (file) { + fileData.append('resume', file.buffer, file.originalname); + } + try { + // get candidate by email + const candidate = await this.getCandidateByEmail(req.authUser.email); + // return error if getCandidateByEmail operation failed + if (candidate.error) { + const error = candidate; + logger.error(error); + return res.status(error.status).send(error); + } + const candidateSlug = candidate.slug; + const form = { + contact_number: body.phone, + available_from: body.availability ? new Date().toISOString() : new Date('2100-01-01').toISOString(), + }; + // assign required fields for update operation + _.assign(form, _.pick(candidate, ['first_name', 'last_name', 'email', 'language_skills'])); + // update candidate profile + const response = await fetch(`${this.private.baseUrl}/v1/candidates/${candidateSlug}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: this.private.authorization, + }, + body: JSON.stringify(form), + }); + if (response.status >= 300) { + const error = { + error: true, + status: response.status, + url: `${this.private.baseUrl}/v1/candidates${candidateSlug}`, + form, + errorObj: await response.json(), + }; + logger.error(error); + return res.status(error.status).send(error); + } + // Attach resume to candidate if uploaded + if (file) { + const formHeaders = fileData.getHeaders(); + const fileResponse = await fetch(`${this.private.baseUrl}/v1/candidates/${candidateSlug}`, { + method: 'POST', + headers: { + Authorization: this.private.authorization, + ...formHeaders, + }, + body: fileData, + }); + if (fileResponse.status >= 300) { + const error = { + error: true, + status: fileResponse.status, + url: `${this.private.baseUrl}/v1/candidates/${candidateSlug}`, + file, + formHeaders, + errorObj: await fileResponse.json(), + }; + logger.error(error); + return res.status(error.status).send(error); + } + } + return res.status(204).end(); + } catch (err) { + return next(err); + } + } + + /** + * Get candidate by email + * @return {object} result of the search operation + * @param {string} email email address of the user. + */ + async getCandidateByEmail(email) { + const url = `${this.private.baseUrl}/v1/candidates/search?email=${email}`; + const response = await fetch(url, { + method: 'GET', + headers: { + Authorization: this.private.authorization, + }, + }); + if (response.status === 429) { + await new Promise(resolve => setTimeout(resolve, 30000)); // wait 30sec + return this.getCandidateByEmail(email); + } + if (response.status >= 300) { + const error = { + error: true, + status: response.status, + url, + errObj: await response.json(), + }; + return error; + } + const data = await response.json(); + // return error object if candidate with provided email not found + if (data.data.length === 0) { + const error = { + error: true, + status: 404, + url, + errObj: { + message: `No candidate was found with email: ${email}`, + }, + }; + return error; + } + // return first candidate + return data.data[0]; + } } From e479b4af1a0a4e7c609314e86033a48fe5f21663 Mon Sep 17 00:00:00 2001 From: dengjun Date: Sun, 20 Jun 2021 12:30:16 +0800 Subject: [PATCH 02/20] ci:deploying recurit proxy api --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 101a1bc599..9644a5dbfc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -340,7 +340,7 @@ workflows: filters: branches: only: - - develop + - recruit-proxy-api # This is alternate dev env for parallel testing - "build-test": context : org-global From ef375f91ece0943a8a20a3d6026e115ce63f2aa1 Mon Sep 17 00:00:00 2001 From: dengjun Date: Sun, 20 Jun 2021 15:34:48 +0800 Subject: [PATCH 03/20] ci:redeploying --- src/server/routes/recruitCRM.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/server/routes/recruitCRM.js b/src/server/routes/recruitCRM.js index 7db1257558..5e9f70a658 100644 --- a/src/server/routes/recruitCRM.js +++ b/src/server/routes/recruitCRM.js @@ -32,6 +32,7 @@ routes.get('/jobs/search', (req, res, next) => new RecruitCRMService().getJobs(r routes.get('/jobs/:id', (req, res, next) => new RecruitCRMService().getJob(req, res, next)); routes.post('/jobs/:id/apply', upload.single('resume'), (req, res, next) => new RecruitCRMService().applyForJob(req, res, next)); routes.get('/candidates/search', (req, res, next) => new RecruitCRMService().searchCandidates(req, res, next)); +// new router added routes.get('/profile', (req, res, next) => authenticator(authenticatorOptions)(req, res, next), (req, res, next) => new RecruitCRMService().getProfile(req, res, next)); routes.post('/profile', (req, res, next) => authenticator(authenticatorOptions)(req, res, next), upload.single('resume'), (req, res, next) => new RecruitCRMService().updateProfile(req, res, next)); export default routes; From 9cf3eb486fb6104243374856f79da5d19acb817c Mon Sep 17 00:00:00 2001 From: dengjun Date: Sun, 20 Jun 2021 23:40:30 +0800 Subject: [PATCH 04/20] ci:addvalid_issues --- Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dockerfile b/Dockerfile index 902b754e09..72ffa4d939 100644 --- a/Dockerfile +++ b/Dockerfile @@ -64,6 +64,7 @@ ARG TC_M2M_GRANT_TYPE ARG TC_M2M_AUTH0_PROXY_SERVER_URL ARG TC_M2M_AUTH0_URL ARG AUTH_SECRET +ARG VALID_ISSUERS ARG COMMUNITY_APP_URL ARG GSHEETS_API_KEY @@ -124,6 +125,7 @@ ENV TC_M2M_GRANT_TYPE=$TC_M2M_GRANT_TYPE ENV TC_M2M_AUTH0_PROXY_SERVER_URL=$TC_M2M_AUTH0_PROXY_SERVER_URL ENV TC_M2M_AUTH0_URL=$TC_M2M_AUTH0_URL ENV AUTH_SECRET=$AUTH_SECRET +ENV VALID_ISSUERS=$VALID_ISSUERS ENV CONTENTFUL_MANAGEMENT_TOKEN=$CONTENTFUL_MANAGEMENT_TOKEN ENV CONTENTFUL_EDU_SPACE_ID=$CONTENTFUL_EDU_SPACE_ID From d88cf881cf024361b30286fb8e6f2477b9f6d9f7 Mon Sep 17 00:00:00 2001 From: Sushil Shinde Date: Mon, 21 Jun 2021 08:55:29 +0530 Subject: [PATCH 05/20] fix: adding VALID_ISSUERS env var --- build.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.sh b/build.sh index 725701d465..23730d8013 100755 --- a/build.sh +++ b/build.sh @@ -51,7 +51,8 @@ docker build -t $TAG \ --build-arg GROWSURF_CAMPAIGN_ID=$GROWSURF_CAMPAIGN_ID \ --build-arg GSHEETS_API_KEY=$GSHEETS_API_KEY \ --build-arg OPTIMIZELY_SDK_KEY=$OPTIMIZELY_SDK_KEY \ - --build-arg COMMUNITY_APP_URL=$COMMUNITY_APP_URL . + --build-arg COMMUNITY_APP_URL=$COMMUNITY_APP_URL \ + --build-arg VALID_ISSUERS=$VALID_ISSUERS . # Copies "node_modules" from the created image, if necessary for caching. docker create --name app $TAG From ed9f08599d71b9a6b72c19af175944bdb3b4a39c Mon Sep 17 00:00:00 2001 From: dengjun Date: Mon, 21 Jun 2021 23:17:45 +0800 Subject: [PATCH 06/20] ci:adding issuers --- config/development.js | 5 +++++ config/production.js | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/config/development.js b/config/development.js index 7991e1a4c9..c0c8b05b0e 100644 --- a/config/development.js +++ b/config/development.js @@ -5,4 +5,9 @@ module.exports = { USER_SETTINGS: '', /* No dev server is available for saved searches */ }, PLATFORM_SITE_URL: 'https://platform.topcoder-dev.com', + JWT_AUTH: { + SECRET: 'mysecret', + AUTH_SECRET: 'mysecret', + VALID_ISSUERS: '["https://api.topcoder-dev.com", "https://api.topcoder.com", "https://topcoder-dev.auth0.com/", "https://auth.topcoder-dev.com/"]', + }, }; diff --git a/config/production.js b/config/production.js index f83da0fbc1..92a5369ec1 100644 --- a/config/production.js +++ b/config/production.js @@ -214,4 +214,9 @@ module.exports = { TC_EDU_SEARCH_PATH: '/search', TC_EDU_SEARCH_BAR_MAX_RESULTS_EACH_GROUP: 3, ENABLE_RECOMMENDER: true, + JWT_AUTH: { + SECRET: 'mysecret', + AUTH_SECRET: 'mysecret', + VALID_ISSUERS: '["https://api.topcoder-dev.com", "https://api.topcoder.com", "https://topcoder-dev.auth0.com/", "https://auth.topcoder-dev.com/"]', + }, }; From ee57934be9939d5d0ecd0c3098330a6f7d87e1ed Mon Sep 17 00:00:00 2001 From: dengjun Date: Tue, 22 Jun 2021 00:05:13 +0800 Subject: [PATCH 07/20] ci:deploying proxy api --- config/default.js | 6 ++++++ config/development.js | 5 ----- config/production.js | 5 ----- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/config/default.js b/config/default.js index e2946ddf77..d3c0b2e681 100644 --- a/config/default.js +++ b/config/default.js @@ -251,6 +251,12 @@ module.exports = { RECRUITCRM_API_KEY: '', GROWSURF_API_KEY: '', SENDGRID_API_KEY: '', + + JWT_AUTH: { + SECRET: 'mysecret', + AUTH_SECRET: 'mysecret', + VALID_ISSUERS: '["https://api.topcoder-dev.com", "https://api.topcoder.com", "https://topcoder-dev.auth0.com/", "https://auth.topcoder-dev.com/"]', + }, }, GROWSURF_CAMPAIGN_ID: '', diff --git a/config/development.js b/config/development.js index c0c8b05b0e..7991e1a4c9 100644 --- a/config/development.js +++ b/config/development.js @@ -5,9 +5,4 @@ module.exports = { USER_SETTINGS: '', /* No dev server is available for saved searches */ }, PLATFORM_SITE_URL: 'https://platform.topcoder-dev.com', - JWT_AUTH: { - SECRET: 'mysecret', - AUTH_SECRET: 'mysecret', - VALID_ISSUERS: '["https://api.topcoder-dev.com", "https://api.topcoder.com", "https://topcoder-dev.auth0.com/", "https://auth.topcoder-dev.com/"]', - }, }; diff --git a/config/production.js b/config/production.js index 92a5369ec1..f83da0fbc1 100644 --- a/config/production.js +++ b/config/production.js @@ -214,9 +214,4 @@ module.exports = { TC_EDU_SEARCH_PATH: '/search', TC_EDU_SEARCH_BAR_MAX_RESULTS_EACH_GROUP: 3, ENABLE_RECOMMENDER: true, - JWT_AUTH: { - SECRET: 'mysecret', - AUTH_SECRET: 'mysecret', - VALID_ISSUERS: '["https://api.topcoder-dev.com", "https://api.topcoder.com", "https://topcoder-dev.auth0.com/", "https://auth.topcoder-dev.com/"]', - }, }; From a2ce444524df872a33d65204734c7dbd0d93a51f Mon Sep 17 00:00:00 2001 From: dengjun Date: Wed, 23 Jun 2021 22:54:28 +0800 Subject: [PATCH 08/20] ci:deploying proxy api --- src/server/services/recruitCRM.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/server/services/recruitCRM.js b/src/server/services/recruitCRM.js index 8010ee5f64..bced83d2cd 100644 --- a/src/server/services/recruitCRM.js +++ b/src/server/services/recruitCRM.js @@ -475,7 +475,7 @@ export default class RecruitCRMService { const responseMapping = { phone: candidate.contact_number, resume: candidate.resume, - availability: _.isNill(candidate.available_from) ? true + availability: _.isNil(candidate.available_from) ? true : new Date(candidate.available_from) <= new Date(), }; return res.send(responseMapping); @@ -512,10 +512,8 @@ export default class RecruitCRMService { const candidateSlug = candidate.slug; const form = { contact_number: body.phone, - available_from: body.availability ? new Date().toISOString() : new Date('2100-01-01').toISOString(), + available_from: body.availability === 'true' ? new Date().toISOString() : new Date('2100-01-01').toISOString(), }; - // assign required fields for update operation - _.assign(form, _.pick(candidate, ['first_name', 'last_name', 'email', 'language_skills'])); // update candidate profile const response = await fetch(`${this.private.baseUrl}/v1/candidates/${candidateSlug}`, { method: 'POST', @@ -572,7 +570,10 @@ export default class RecruitCRMService { * @param {string} email email address of the user. */ async getCandidateByEmail(email) { - const url = `${this.private.baseUrl}/v1/candidates/search?email=${email}`; + const query = { + email, + }; + const url = `${this.private.baseUrl}/v1/candidates/search?${qs.stringify(query)}`; const response = await fetch(url, { method: 'GET', headers: { From f255d1b5439701da023154059b0e93d19937d624 Mon Sep 17 00:00:00 2001 From: dengjun Date: Fri, 25 Jun 2021 11:09:37 +0800 Subject: [PATCH 09/20] ci:adjust proxy api --- docs/swagger.yaml | 5 ++++- src/server/services/recruitCRM.js | 8 ++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 8c79142edc..0783d9f0a9 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -44,7 +44,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/Error" + $ref: "#/components/schemas/Profile" "500": description: Internal Server Error content: @@ -122,6 +122,9 @@ components: description: "The availability of the user" default: true example: true + hasProfile: + type: boolean + description: "Whether has profile for the user" ProfileUpdate: required: - phone diff --git a/src/server/services/recruitCRM.js b/src/server/services/recruitCRM.js index bced83d2cd..8a8345275c 100644 --- a/src/server/services/recruitCRM.js +++ b/src/server/services/recruitCRM.js @@ -469,10 +469,14 @@ export default class RecruitCRMService { if (candidate.error) { const error = candidate; logger.error(error); - return res.status(error.status).send(error); + const responseNoProfileMapping = { + hasProfile: false, + }; + return res.send(responseNoProfileMapping); } // apply desired response format const responseMapping = { + hasProfile: true, phone: candidate.contact_number, resume: candidate.resume, availability: _.isNil(candidate.available_from) ? true @@ -595,7 +599,7 @@ export default class RecruitCRMService { } const data = await response.json(); // return error object if candidate with provided email not found - if (data.data.length === 0) { + if ((_.isArray(data) && data.length === 0) || data.data.length === 0) { const error = { error: true, status: 404, From c220bafa67e6448419297790629aa300c889c0bb Mon Sep 17 00:00:00 2001 From: dengjun Date: Sat, 26 Jun 2021 13:38:11 +0800 Subject: [PATCH 10/20] ci:deploying proxy api --- src/server/services/recruitCRM.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/server/services/recruitCRM.js b/src/server/services/recruitCRM.js index 8a8345275c..f55c63d029 100644 --- a/src/server/services/recruitCRM.js +++ b/src/server/services/recruitCRM.js @@ -515,6 +515,8 @@ export default class RecruitCRMService { } const candidateSlug = candidate.slug; const form = { + city: body.city, + locality: body.countryName, contact_number: body.phone, available_from: body.availability === 'true' ? new Date().toISOString() : new Date('2100-01-01').toISOString(), }; From b09a8260ff4898a0851cc806d1f921a27cf31149 Mon Sep 17 00:00:00 2001 From: dengjun Date: Sat, 26 Jun 2021 13:54:46 +0800 Subject: [PATCH 11/20] ci:update profile endpoint --- .../Community APP.postman_collection.json | 161 +++--------------- docs/swagger.yaml | 8 + src/server/services/recruitCRM.js | 2 + 3 files changed, 37 insertions(+), 134 deletions(-) diff --git a/docs/postman/Community APP.postman_collection.json b/docs/postman/Community APP.postman_collection.json index 051b83d80a..d0b3586dcb 100644 --- a/docs/postman/Community APP.postman_collection.json +++ b/docs/postman/Community APP.postman_collection.json @@ -1,8 +1,8 @@ { "info": { - "_postman_id": "cc8d34ce-b72f-4340-a4c1-737f89157b31", + "_postman_id": "95d8a75d-2520-494b-becd-f9f2e8537707", "name": "Community APP", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" }, "item": [ { @@ -35,16 +35,7 @@ "type": "text" } ], - "url": { - "raw": "{{URL}}/recruit/profile", - "host": [ - "{{URL}}" - ], - "path": [ - "recruit", - "profile" - ] - } + "url": "{{URL}}/recruit/profile" }, "response": [] }, @@ -72,16 +63,7 @@ "type": "text" } ], - "url": { - "raw": "{{URL}}/recruit/profile", - "host": [ - "{{URL}}" - ], - "path": [ - "recruit", - "profile" - ] - } + "url": "{{URL}}/recruit/profile" }, "response": [] }, @@ -109,16 +91,7 @@ "type": "text" } ], - "url": { - "raw": "{{URL}}/recruit/profile", - "host": [ - "{{URL}}" - ], - "path": [ - "recruit", - "profile" - ] - } + "url": "{{URL}}/recruit/profile" }, "response": [] }, @@ -146,16 +119,7 @@ "type": "text" } ], - "url": { - "raw": "{{URL}}/recruit/profile", - "host": [ - "{{URL}}" - ], - "path": [ - "recruit", - "profile" - ] - } + "url": "{{URL}}/recruit/profile" }, "response": [] }, @@ -183,16 +147,7 @@ "type": "text" } ], - "url": { - "raw": "{{URL}}/recruit/profile", - "host": [ - "{{URL}}" - ], - "path": [ - "recruit", - "profile" - ] - } + "url": "{{URL}}/recruit/profile" }, "response": [] }, @@ -226,7 +181,7 @@ { "key": "resume", "type": "file", - "src": "./docs/postman/resume.txt" + "src": [] }, { "key": "phone", @@ -235,21 +190,22 @@ }, { "key": "availability", - "value": "true", + "value": "false", + "type": "text" + }, + { + "key": "city", + "value": "ABC", + "type": "text" + }, + { + "key": "countryName", + "value": "India", "type": "text" } ] }, - "url": { - "raw": "{{URL}}/recruit/profile", - "host": [ - "{{URL}}" - ], - "path": [ - "recruit", - "profile" - ] - } + "url": "{{URL}}/recruit/profile" }, "response": [] }, @@ -297,16 +253,7 @@ } ] }, - "url": { - "raw": "{{URL}}/recruit/profile", - "host": [ - "{{URL}}" - ], - "path": [ - "recruit", - "profile" - ] - } + "url": "{{URL}}/recruit/profile" }, "response": [] }, @@ -354,16 +301,7 @@ } ] }, - "url": { - "raw": "{{URL}}/recruit/profile", - "host": [ - "{{URL}}" - ], - "path": [ - "recruit", - "profile" - ] - } + "url": "{{URL}}/recruit/profile" }, "response": [] }, @@ -411,16 +349,7 @@ } ] }, - "url": { - "raw": "{{URL}}/recruit/profile", - "host": [ - "{{URL}}" - ], - "path": [ - "recruit", - "profile" - ] - } + "url": "{{URL}}/recruit/profile" }, "response": [] }, @@ -468,16 +397,7 @@ } ] }, - "url": { - "raw": "{{URL}}/recruit/profile", - "host": [ - "{{URL}}" - ], - "path": [ - "recruit", - "profile" - ] - } + "url": "{{URL}}/recruit/profile" }, "response": [] }, @@ -527,16 +447,7 @@ } ] }, - "url": { - "raw": "{{URL}}/recruit/profile", - "host": [ - "{{URL}}" - ], - "path": [ - "recruit", - "profile" - ] - } + "url": "{{URL}}/recruit/profile" }, "response": [] }, @@ -581,16 +492,7 @@ } ] }, - "url": { - "raw": "{{URL}}/recruit/profile", - "host": [ - "{{URL}}" - ], - "path": [ - "recruit", - "profile" - ] - } + "url": "{{URL}}/recruit/profile" }, "response": [] }, @@ -635,16 +537,7 @@ } ] }, - "url": { - "raw": "{{URL}}/recruit/profile", - "host": [ - "{{URL}}" - ], - "path": [ - "recruit", - "profile" - ] - } + "url": "{{URL}}/recruit/profile" }, "response": [] } diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 0783d9f0a9..abd8729743 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -129,11 +129,19 @@ components: required: - phone - availability + - city + - countryName properties: phone: type: string description: "The phone number of the user" example: "(123) 456-7890" + city: + type: string + description: "The member's city" + countryName: + type: string + description: "The member's country" resume: type: string format: binary diff --git a/src/server/services/recruitCRM.js b/src/server/services/recruitCRM.js index f55c63d029..8eb1b0fc51 100644 --- a/src/server/services/recruitCRM.js +++ b/src/server/services/recruitCRM.js @@ -66,6 +66,8 @@ function notifyKirilAndNick(error) { const updateProfileSchema = Joi.object().keys({ phone: Joi.string().required(), availability: Joi.boolean().required(), + city: Joi.string().required(), + countryName: Joi.string().required(), }).required(); /** From bc8180b82920227936404f7c1f65a768c7a84e48 Mon Sep 17 00:00:00 2001 From: dengjun Date: Sat, 26 Jun 2021 22:51:30 +0800 Subject: [PATCH 12/20] ci:adding buttons --- src/shared/components/Gigs/GigApply/index.jsx | 5 +- .../components/Gigs/GigApply/style.scss | 3 + .../components/Gigs/GigHeader/index.jsx | 27 ++++++ .../components/Gigs/GigHeader/style.scss | 83 +++++++++++++++++++ src/shared/containers/Gigs/RecruitCRMJobs.jsx | 2 + 5 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 src/shared/components/Gigs/GigHeader/index.jsx create mode 100644 src/shared/components/Gigs/GigHeader/style.scss diff --git a/src/shared/components/Gigs/GigApply/index.jsx b/src/shared/components/Gigs/GigApply/index.jsx index c7ef512a77..3c801ae2d2 100644 --- a/src/shared/components/Gigs/GigApply/index.jsx +++ b/src/shared/components/Gigs/GigApply/index.jsx @@ -108,7 +108,10 @@ export default function GigApply(props) { VIEW OTHER GIGS ) : ( - GO TO GIGS LIST + + GO TO GIGS LIST + CHECK GIG APPLICATION STATUS + ) } diff --git a/src/shared/components/Gigs/GigApply/style.scss b/src/shared/components/Gigs/GigApply/style.scss index ec860228fc..abcea04f97 100644 --- a/src/shared/components/Gigs/GigApply/style.scss +++ b/src/shared/components/Gigs/GigApply/style.scss @@ -313,6 +313,9 @@ margin-left: 20px; } } + .gig-list-btn { + margin-right: 12px; + } } /* stylelint-enable */ } diff --git a/src/shared/components/Gigs/GigHeader/index.jsx b/src/shared/components/Gigs/GigHeader/index.jsx new file mode 100644 index 0000000000..34db150a7b --- /dev/null +++ b/src/shared/components/Gigs/GigHeader/index.jsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { config, Link } from 'topcoder-react-utils'; +import BannerInfoIcon from 'assets/images/banner-info.svg'; +import './style.scss'; + +const GigHeader = () => { + return ( +
+
+
+ +
+ + You have 3 applied Gigs in the system + +
+ +
+ CHECK GIG APPLICATION STATUS +
+
+ ); +}; + +export default GigHeader; diff --git a/src/shared/components/Gigs/GigHeader/style.scss b/src/shared/components/Gigs/GigHeader/style.scss new file mode 100644 index 0000000000..c7334850d9 --- /dev/null +++ b/src/shared/components/Gigs/GigHeader/style.scss @@ -0,0 +1,83 @@ +@import "~styles/mixins"; +@import "~components/GUIKit/Assets/Styles/default"; +@import "~components/Contentful/default"; + +.gig-header { + @include roboto-medium; + + @include xs-to-sm { + height: 81px; + line-height: 22px; + padding-left: 20px; + } + + display: flex; + justify-content: space-between; + flex-direction: row; + align-items: center; + margin-top: 15px; + height: 70px; + background: linear-gradient(90deg, #6F308B 0%, #1470AC 100%); + border-radius: 10px; + color: #fff; + font-size: 16px; + + .content { + display: flex; + justify-content: space-between; + flex-direction: row; + align-items: center; + color: #fff; + + .banner-info { + width: 24px; + height: 24px; + margin-left: 20px; + margin-right: 10px; + + @include xs-to-sm { + display: none; + } + } + + @include xs-to-sm { + width: 80%; + } + } + + .row-btn { + display: flex; + justify-content: flex-end; + flex: 1; + padding-right: 20px; + + @include xs-to-sm { + justify-content: flex-start; + } + + button.primary-white-md { + outline: none; + + @include primary-white; + @include md; + + &:hover { + @include primary-white; + } + } + } + + .banner-close { + width: 14px; + height: 14px; + margin-right: 30px; + + &:hover { + cursor: pointer; + } + + @include xs-to-sm { + margin-bottom: 20px; + } + } +} diff --git a/src/shared/containers/Gigs/RecruitCRMJobs.jsx b/src/shared/containers/Gigs/RecruitCRMJobs.jsx index 337bef5414..d29fe6a816 100644 --- a/src/shared/containers/Gigs/RecruitCRMJobs.jsx +++ b/src/shared/containers/Gigs/RecruitCRMJobs.jsx @@ -17,6 +17,7 @@ import IconBlackLocation from 'assets/images/icon-black-location.svg'; import { config, Link, isomorphy } from 'topcoder-react-utils'; import { getQuery, updateQuery } from 'utils/url'; import { withOptimizely } from '@optimizely/react-sdk'; +import GigHeader from 'components/Gigs/GigHeader'; import './jobLisingStyles.scss'; const cookies = require('browser-cookies'); @@ -249,6 +250,7 @@ class RecruitCRMJobsContainer extends React.Component { +
{ jobsToDisplay.length From 0628f2eecbd614e7ea9d7e7761c3c6cf3646649b Mon Sep 17 00:00:00 2001 From: dengjun Date: Sat, 26 Jun 2021 23:21:52 +0800 Subject: [PATCH 13/20] ci:deploying to stage --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9644a5dbfc..6e199861ba 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -368,7 +368,7 @@ workflows: filters: &filters-staging branches: only: - - develop + - recruit-proxy-api # Production builds are exectuted # when PR is merged to the master # Don't change anything in this configuration From 0cb00e773809d96612f079e8abd057d1881d13b7 Mon Sep 17 00:00:00 2001 From: dengjun Date: Sat, 26 Jun 2021 23:29:50 +0800 Subject: [PATCH 14/20] =?UTF-8?q?ci:=E4=BF=AE=E5=A4=8Dlint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/Gigs/GigHeader/index.jsx | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/shared/components/Gigs/GigHeader/index.jsx b/src/shared/components/Gigs/GigHeader/index.jsx index 34db150a7b..8b545a15fd 100644 --- a/src/shared/components/Gigs/GigHeader/index.jsx +++ b/src/shared/components/Gigs/GigHeader/index.jsx @@ -3,25 +3,23 @@ import { config, Link } from 'topcoder-react-utils'; import BannerInfoIcon from 'assets/images/banner-info.svg'; import './style.scss'; -const GigHeader = () => { - return ( -
-
-
- -
- - You have 3 applied Gigs in the system - +const GigHeader = () => ( +
+
+
+
+ + You have 3 applied Gigs in the system + +
-
- CHECK GIG APPLICATION STATUS -
+
+ CHECK GIG APPLICATION STATUS
- ); -}; +
+); export default GigHeader; From cbe5685bf93af1dc1e1051f7b876bbabf0bea2c8 Mon Sep 17 00:00:00 2001 From: dengjun Date: Sat, 26 Jun 2021 23:33:35 +0800 Subject: [PATCH 15/20] ci:fixing css lint --- src/shared/components/Gigs/GigHeader/style.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/components/Gigs/GigHeader/style.scss b/src/shared/components/Gigs/GigHeader/style.scss index c7334850d9..8c51a60079 100644 --- a/src/shared/components/Gigs/GigHeader/style.scss +++ b/src/shared/components/Gigs/GigHeader/style.scss @@ -17,7 +17,7 @@ align-items: center; margin-top: 15px; height: 70px; - background: linear-gradient(90deg, #6F308B 0%, #1470AC 100%); + background: linear-gradient(90deg, #6f308b 0%, #1470ac 100%); border-radius: 10px; color: #fff; font-size: 16px; From 7a1127594fef37dd87601a48ff03390889d6c6f1 Mon Sep 17 00:00:00 2001 From: dengjun Date: Sun, 27 Jun 2021 13:11:06 +0800 Subject: [PATCH 16/20] ci:deploying api integration --- .circleci/config.yml | 4 ++-- src/shared/actions/recruitCRM.js | 14 +++++++++++ .../components/Gigs/GigHeader/index.jsx | 12 ++++++++-- src/shared/containers/Gigs/RecruitCRMJobs.jsx | 21 +++++++++++++++- src/shared/reducers/recruitCRM.js | 16 +++++++++++++ src/shared/services/recruitCRM.js | 24 +++++++++++++++++++ 6 files changed, 86 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6e199861ba..7985d4ba23 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -340,7 +340,7 @@ workflows: filters: branches: only: - - recruit-proxy-api + - recruit-proxy-api-aggapi # This is alternate dev env for parallel testing - "build-test": context : org-global @@ -368,7 +368,7 @@ workflows: filters: &filters-staging branches: only: - - recruit-proxy-api + - recruit-proxy-api-aggapi # Production builds are exectuted # when PR is merged to the master # Don't change anything in this configuration diff --git a/src/shared/actions/recruitCRM.js b/src/shared/actions/recruitCRM.js index cdcb6d2260..2d6bf63d24 100644 --- a/src/shared/actions/recruitCRM.js +++ b/src/shared/actions/recruitCRM.js @@ -22,6 +22,18 @@ async function getJobsDone(query) { }; } +function getJobApplicationsInit() { + return {}; +} + +async function getJobApplicationsDone(tokenV3) { + const ss = new Service(); + const res = await ss.getJobApplications(tokenV3); + return { + data: res, + }; +} + /** * Job fetch init */ @@ -163,5 +175,7 @@ export default redux.createActions({ APPLY_FOR_JOB_DONE: applyForJobDone, SEARCH_CANDIDATES_INIT: searchCandidatesInit, SEARCH_CANDIDATES_DONE: searchCandidatesDone, + GET_JOB_APPLICATIONS_INIT: getJobApplicationsInit, + GET_JOB_APPLICATIONS_DONE: getJobApplicationsDone, }, }); diff --git a/src/shared/components/Gigs/GigHeader/index.jsx b/src/shared/components/Gigs/GigHeader/index.jsx index 8b545a15fd..519415c88b 100644 --- a/src/shared/components/Gigs/GigHeader/index.jsx +++ b/src/shared/components/Gigs/GigHeader/index.jsx @@ -1,9 +1,10 @@ import React from 'react'; import { config, Link } from 'topcoder-react-utils'; +import PT from 'prop-types'; import BannerInfoIcon from 'assets/images/banner-info.svg'; import './style.scss'; -const GigHeader = () => ( +const GigHeader = ({ appNum }) => (
@@ -12,7 +13,7 @@ const GigHeader = () => (
- You have 3 applied Gigs in the system + You have {appNum} applied Gigs in the system
@@ -22,4 +23,11 @@ const GigHeader = () => (
); +GigHeader.defaultProps = { + appNum: 0, +}; + +GigHeader.propTypes = { + appNum: PT.number, +}; export default GigHeader; diff --git a/src/shared/containers/Gigs/RecruitCRMJobs.jsx b/src/shared/containers/Gigs/RecruitCRMJobs.jsx index d29fe6a816..0e23dfbccd 100644 --- a/src/shared/containers/Gigs/RecruitCRMJobs.jsx +++ b/src/shared/containers/Gigs/RecruitCRMJobs.jsx @@ -56,6 +56,8 @@ class RecruitCRMJobsContainer extends React.Component { const { getJobs, jobs, + getJobApplications, + auth, } = this.props; const { state } = this; const q = getQuery(); @@ -74,6 +76,9 @@ class RecruitCRMJobsContainer extends React.Component { }; this.setState(stateUpdate); } + if (auth.tokenV3) { + getJobApplications(auth.tokenV3); + } } /** @@ -138,6 +143,7 @@ class RecruitCRMJobsContainer extends React.Component { loading, jobs, optimizely, + applications, } = this.props; const { term, @@ -250,7 +256,7 @@ class RecruitCRMJobsContainer extends React.Component {
- +
{ jobsToDisplay.length @@ -290,6 +296,8 @@ class RecruitCRMJobsContainer extends React.Component { RecruitCRMJobsContainer.defaultProps = { jobs: [], loading: true, + applications: 0, + auth: {}, }; RecruitCRMJobsContainer.propTypes = { @@ -297,6 +305,9 @@ RecruitCRMJobsContainer.propTypes = { loading: PT.bool, jobs: PT.arrayOf(PT.shape), optimizely: PT.shape().isRequired, + getJobApplications: PT.func.isRequired, + applications: PT.number, + auth: PT.object, }; function mapStateToProps(state) { @@ -304,6 +315,10 @@ function mapStateToProps(state) { return { jobs: data ? data.jobs : [], loading: data ? data.loading : true, + applications: data.applications, + auth: { + ...state.auth, + }, }; } @@ -314,6 +329,10 @@ function mapDispatchToActions(dispatch) { dispatch(a.getJobsInit(ownProps)); dispatch(a.getJobsDone(ownProps)); }, + getJobApplications: (tokenV3) => { + dispatch(a.getJobApplicationsInit()); + dispatch(a.getJobApplicationsDone(tokenV3)); + }, }; } diff --git a/src/shared/reducers/recruitCRM.js b/src/shared/reducers/recruitCRM.js index 4a7bbfa629..9942cb2602 100644 --- a/src/shared/reducers/recruitCRM.js +++ b/src/shared/reducers/recruitCRM.js @@ -112,6 +112,20 @@ function onSearchCandidatesDone(state, { payload }) { return r; } +function onGetJobApplicationsInit(state) { + return { + ...state, + applications: 0, + }; +} + +function onGetJobApplicationsDone(state, { payload }) { + return { + ...state, + applications: payload.data, + }; +} + /** * Creates recruitCRM reducer with the specified initial state. * @param {Object} state Optional. If not given, the default one is @@ -128,6 +142,8 @@ function create(state = {}) { [actions.recruit.applyForJobDone]: onApplyForJobDone, [actions.recruit.searchCandidatesInit]: onSearchCandidatesInit, [actions.recruit.searchCandidatesDone]: onSearchCandidatesDone, + [actions.recruit.getJobApplicationsInit]: onGetJobApplicationsInit, + [actions.recruit.getJobApplicationsDone]: onGetJobApplicationsDone, }, state); } diff --git a/src/shared/services/recruitCRM.js b/src/shared/services/recruitCRM.js index c71bae877b..f8b60be687 100644 --- a/src/shared/services/recruitCRM.js +++ b/src/shared/services/recruitCRM.js @@ -1,5 +1,6 @@ import fetch from 'isomorphic-fetch'; import { logger } from 'topcoder-react-lib'; +import { config } from 'topcoder-react-utils'; import qs from 'qs'; import _ from 'lodash'; @@ -47,6 +48,29 @@ export default class Service { return res.json(); } + /** + * get member applications + * @param {*} tokenV3 + * @returns + */ + /* eslint-disable class-methods-use-this */ + async getJobApplications(tokenV3) { + const res = await fetch( + `${config.PLATFORM_SITE_URL}/earn-app/api/my-gigs/myJobApplications?page=1&perPage=1`, + { + method: 'GET', + headers: new Headers({ + Authorization: `Bearer ${tokenV3}`, + }), + }, + ); + if (!res.ok) { + const error = new Error('Failed to get job applications'); + logger.error(error, res); + } + return parseInt(res.headers.get('x-total'), 10) || 0; + } + /** * applyForJob for candidate * @param {string} id The job id to apply to From 972b46b0d49c5ac1ac22717dd845d454d8ffc5a4 Mon Sep 17 00:00:00 2001 From: dengjun Date: Mon, 28 Jun 2021 13:07:36 +0800 Subject: [PATCH 17/20] ci:hide the banner accordingly --- src/shared/containers/Gigs/RecruitCRMJobs.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/shared/containers/Gigs/RecruitCRMJobs.jsx b/src/shared/containers/Gigs/RecruitCRMJobs.jsx index 0e23dfbccd..14afad81dc 100644 --- a/src/shared/containers/Gigs/RecruitCRMJobs.jsx +++ b/src/shared/containers/Gigs/RecruitCRMJobs.jsx @@ -144,6 +144,7 @@ class RecruitCRMJobsContainer extends React.Component { jobs, optimizely, applications, + auth, } = this.props; const { term, @@ -256,7 +257,7 @@ class RecruitCRMJobsContainer extends React.Component {
- + {auth.tokenV3 && applications > 0 && }
{ jobsToDisplay.length From a858e200778104bf74df26d6fe31a9b89c613e7a Mon Sep 17 00:00:00 2001 From: Sushil Shinde Date: Mon, 28 Jun 2021 12:15:43 +0530 Subject: [PATCH 18/20] fix: fixing platform url --- config/default.js | 2 +- config/production.js | 204 ++++++++++++++++++++++--------------------- 2 files changed, 104 insertions(+), 102 deletions(-) diff --git a/config/default.js b/config/default.js index d3c0b2e681..fdb588fe6d 100644 --- a/config/default.js +++ b/config/default.js @@ -435,5 +435,5 @@ module.exports = { OPTIMIZELY: { SDK_KEY: '7V4CJhurXT3Y3bnzv1hv1', }, - PLATFORM_SITE_URL: 'https://platform.topcoder.com', + PLATFORM_SITE_URL: 'https://platform.topcoder-dev.com', }; diff --git a/config/production.js b/config/production.js index f83da0fbc1..5f31f0ce5e 100644 --- a/config/production.js +++ b/config/production.js @@ -1,217 +1,219 @@ module.exports = { API: { - V2: 'https://api.topcoder.com/v2', - V3: 'https://api.topcoder.com/v3', - V4: 'https://api.topcoder.com/v4', - V5: 'https://api.topcoder.com/v5', + V2: "https://api.topcoder.com/v2", + V3: "https://api.topcoder.com/v3", + V4: "https://api.topcoder.com/v4", + V5: "https://api.topcoder.com/v5", }, AUTH0: { - DOMAIN: 'topcoder.auth0.com', + DOMAIN: "topcoder.auth0.com", }, CDN: { - PUBLIC: 'https://community-app-cdn.topcoder.com', + PUBLIC: "https://community-app-cdn.topcoder.com", }, COOKIES: { MAXAGE: 7, SECURE: true, }, - LOG_ENTRIES_TOKEN: '', - SERVER_API_KEY: 'aa9ccf36-3936-450c-9983-097ddba51bef', - GOOGLE_ANALYTICS_ID: 'UA-6340959-1', + LOG_ENTRIES_TOKEN: "", + SERVER_API_KEY: "aa9ccf36-3936-450c-9983-097ddba51bef", + GOOGLE_ANALYTICS_ID: "UA-6340959-1", URL: { - ARENA: 'https://arena.topcoder.com', - APP: 'https://community-app.topcoder.com', + ARENA: "https://arena.topcoder.com", + APP: "https://community-app.topcoder.com", /* This is the same value as above, but it is used by topcoder-react-lib, * as a more verbose name for the param. */ - COMMUNITY_APP: 'https://community-app.topcoder.com', + COMMUNITY_APP: "https://community-app.topcoder.com", - AUTH: 'https://accounts-auth0.topcoder.com', - BASE: 'https://www.topcoder.com', - HOME: '/my-dashboard', - COMMUNITY: 'https://community.topcoder.com', - FORUMS: 'https://apps.topcoder.com/forums', - FORUMS_VANILLA: 'https://discussions.topcoder.com', - HELP: 'https://www.topcoder.com/thrive/tracks?track=Topcoder&tax=Help%20Articles', - SUBMISSION_REVIEW: 'https://submission-review.topcoder.com', - MEMBER: 'https://member.topcoder.com', - ONLINE_REVIEW: 'https://software.topcoder.com', - PAYMENT_TOOL: 'https://payment.topcoder.com', - STUDIO: 'https://studio.topcoder.com', - IOS: 'https://ios.topcoder.com', + AUTH: "https://accounts-auth0.topcoder.com", + BASE: "https://www.topcoder.com", + HOME: "/my-dashboard", + COMMUNITY: "https://community.topcoder.com", + FORUMS: "https://apps.topcoder.com/forums", + FORUMS_VANILLA: "https://discussions.topcoder.com", + HELP: "https://www.topcoder.com/thrive/tracks?track=Topcoder&tax=Help%20Articles", + SUBMISSION_REVIEW: "https://submission-review.topcoder.com", + MEMBER: "https://member.topcoder.com", + ONLINE_REVIEW: "https://software.topcoder.com", + PAYMENT_TOOL: "https://payment.topcoder.com", + STUDIO: "https://studio.topcoder.com", + IOS: "https://ios.topcoder.com", /* Connector URL of the TC accounts App. */ - ACCOUNTS_APP_CONNECTOR: 'https://accounts-auth0.topcoder.com/', - TCO17: 'https://tco17.topcoder.com/', - TCO19: 'https://tco19.topcoder.com/', + ACCOUNTS_APP_CONNECTOR: "https://accounts-auth0.topcoder.com/", + TCO17: "https://tco17.topcoder.com/", + TCO19: "https://tco19.topcoder.com/", - TOPGEAR: 'https://topgear-app.wipro.com', + TOPGEAR: "https://topgear-app.wipro.com", - COMMUNITY_API: 'http://localhost:8000', + COMMUNITY_API: "http://localhost:8000", COMMUNITIES: { - BLOCKCHAIN: 'https://blockchain.topcoder.com', - COGNITIVE: 'https://cognitive.topcoder.com', - ZURICH: 'https://zurich.topcoder.com', - COMCAST: 'https://comcast.topcoder.com', - CS: 'https://cs.topcoder.com', + BLOCKCHAIN: "https://blockchain.topcoder.com", + COGNITIVE: "https://cognitive.topcoder.com", + ZURICH: "https://zurich.topcoder.com", + COMCAST: "https://comcast.topcoder.com", + CS: "https://cs.topcoder.com", }, - EMAIL_VERIFY_URL: 'http://www.topcoder.com/settings/account/changeEmail', + EMAIL_VERIFY_URL: "http://www.topcoder.com/settings/account/changeEmail", }, /* Filestack configuration for uploading Submissions * These are for the production back end */ FILESTACK: { - SUBMISSION_CONTAINER: 'topcoder-submissions-dmz', + SUBMISSION_CONTAINER: "topcoder-submissions-dmz", }, ACCOUNT_MENU_SWITCH_TEXT: { - title: 'Switch to BUSINESS', - href: 'https://connect.topcoder.com', + title: "Switch to BUSINESS", + href: "https://connect.topcoder.com", }, HEADER_MENU: [ { - id: 'business', - title: 'BUSINESS', - href: 'https://www.topcoder.com', + id: "business", + title: "BUSINESS", + href: "https://www.topcoder.com", }, { - id: 'community', // required for 'Switch to BUSINESS' to work - title: 'COMMUNITY', + id: "community", // required for 'Switch to BUSINESS' to work + title: "COMMUNITY", secondaryMenu: [ { - title: 'Dashboard', - href: '/my-dashboard', + title: "Dashboard", + href: "/my-dashboard", logged: true, }, { - id: 'myprofile', - title: 'My Profile', - href: '/members/willFilledByUserName', + id: "myprofile", + title: "My Profile", + href: "/members/willFilledByUserName", logged: true, }, { - title: 'Payments', - href: 'https://community.topcoder.com/PactsMemberServlet?module=PaymentHistory&full_list=false', + title: "Payments", + href: "https://community.topcoder.com/PactsMemberServlet?module=PaymentHistory&full_list=false", logged: true, openNewTab: true, }, { - title: 'Overview', - href: '/community/learn', + title: "Overview", + href: "/community/learn", logged: false, }, { - title: 'How It Works', - href: '/thrive/tracks?track=Topcoder', + title: "How It Works", + href: "/thrive/tracks?track=Topcoder", logged: false, }, ], subMenu: [ { - title: 'Compete', + title: "Compete", subMenu: [ { - title: 'All Challenges', - href: '/challenges', + title: "All Challenges", + href: "/challenges", }, { - title: 'Competitive Programming', - href: '/community/arena', + title: "Competitive Programming", + href: "/community/arena", }, { - title: 'Gig Work', - href: '/gigs', + title: "Gig Work", + href: "/gigs", }, { - title: 'Practice', - href: '/community/practice', + title: "Practice", + href: "/community/practice", }, ], }, { - title: 'Tracks', + title: "Tracks", subMenu: [ { - title: 'Competitive Programming', - href: '/thrive/tracks?track=Competitive%20Programming', + title: "Competitive Programming", + href: "/thrive/tracks?track=Competitive%20Programming", }, { - title: 'Data Science', - href: '/thrive/tracks?track=Data%20Science&tax=', + title: "Data Science", + href: "/thrive/tracks?track=Data%20Science&tax=", }, { - title: 'Design', - href: '/thrive/tracks?track=Design&tax=', + title: "Design", + href: "/thrive/tracks?track=Design&tax=", }, { - title: 'Development', - href: '/thrive/tracks?track=Development&tax=', + title: "Development", + href: "/thrive/tracks?track=Development&tax=", }, { - title: 'QA', - href: '/thrive/tracks?track=QA&tax=', + title: "QA", + href: "/thrive/tracks?track=QA&tax=", }, ], }, { - title: 'Explore', + title: "Explore", subMenu: [ { - title: 'TCO', - href: '/community/member-programs/topcoder-open', + title: "TCO", + href: "/community/member-programs/topcoder-open", }, { - title: 'Programs', - href: '/community/member-programs', + title: "Programs", + href: "/community/member-programs", }, { - title: 'Forums', - href: 'https://discussions.topcoder.com', + title: "Forums", + href: "https://discussions.topcoder.com", }, { - title: 'Statistics', - href: '/community/statistics', + title: "Statistics", + href: "/community/statistics", }, { - title: 'Blog', - href: 'https://www.topcoder.com/blog', + title: "Blog", + href: "https://www.topcoder.com/blog", openNewTab: true, }, { - title: 'Thrive', - href: '/thrive', + title: "Thrive", + href: "/thrive", }, ], }, ], }, ], - HEADER_MENU_THEME: 'light', + HEADER_MENU_THEME: "light", HEADER_AUTH_URLS: { - href: 'https://accounts-auth0.topcoder.com?utm_source=community-app-main', - location: 'https://accounts-auth0.topcoder.com?retUrl=%S&utm_source=community-app-main', + href: "https://accounts-auth0.topcoder.com?utm_source=community-app-main", + location: + "https://accounts-auth0.topcoder.com?retUrl=%S&utm_source=community-app-main", }, ACCOUNT_MENU: [ { - title: 'Settings', - href: '/settings/profile', + title: "Settings", + href: "/settings/profile", }, { separator: true }, { - title: 'Help', - href: 'https://www.topcoder.com/thrive/tracks?track=Topcoder&tax=Help%20Articles', + title: "Help", + href: "https://www.topcoder.com/thrive/tracks?track=Topcoder&tax=Help%20Articles", }, { separator: true }, { - title: 'Log Out', - href: 'https://www.topcoder.com/logout', + title: "Log Out", + href: "https://www.topcoder.com/logout", }, ], // Config for TC EDU - THRIVE - TC_EDU_BASE_PATH: '/thrive', - TC_EDU_TRACKS_PATH: '/tracks', - TC_EDU_ARTICLES_PATH: '/articles', - TC_EDU_SEARCH_PATH: '/search', + TC_EDU_BASE_PATH: "/thrive", + TC_EDU_TRACKS_PATH: "/tracks", + TC_EDU_ARTICLES_PATH: "/articles", + TC_EDU_SEARCH_PATH: "/search", TC_EDU_SEARCH_BAR_MAX_RESULTS_EACH_GROUP: 3, ENABLE_RECOMMENDER: true, + PLATFORM_SITE_URL: "https://platform.topcoder.com", }; From f78873040c9df0cbf4f8464c2d80381231e84b0f Mon Sep 17 00:00:00 2001 From: Sushil Shinde Date: Mon, 28 Jun 2021 12:17:11 +0530 Subject: [PATCH 19/20] fix: fixing quotes --- config/production.js | 205 +++++++++++++++++++++---------------------- 1 file changed, 102 insertions(+), 103 deletions(-) diff --git a/config/production.js b/config/production.js index 5f31f0ce5e..16c2c1be3d 100644 --- a/config/production.js +++ b/config/production.js @@ -1,219 +1,218 @@ module.exports = { API: { - V2: "https://api.topcoder.com/v2", - V3: "https://api.topcoder.com/v3", - V4: "https://api.topcoder.com/v4", - V5: "https://api.topcoder.com/v5", + V2: 'https://api.topcoder.com/v2', + V3: 'https://api.topcoder.com/v3', + V4: 'https://api.topcoder.com/v4', + V5: 'https://api.topcoder.com/v5', }, AUTH0: { - DOMAIN: "topcoder.auth0.com", + DOMAIN: 'topcoder.auth0.com', }, CDN: { - PUBLIC: "https://community-app-cdn.topcoder.com", + PUBLIC: 'https://community-app-cdn.topcoder.com', }, COOKIES: { MAXAGE: 7, SECURE: true, }, - LOG_ENTRIES_TOKEN: "", - SERVER_API_KEY: "aa9ccf36-3936-450c-9983-097ddba51bef", - GOOGLE_ANALYTICS_ID: "UA-6340959-1", + LOG_ENTRIES_TOKEN: '', + SERVER_API_KEY: 'aa9ccf36-3936-450c-9983-097ddba51bef', + GOOGLE_ANALYTICS_ID: 'UA-6340959-1', URL: { - ARENA: "https://arena.topcoder.com", - APP: "https://community-app.topcoder.com", + ARENA: 'https://arena.topcoder.com', + APP: 'https://community-app.topcoder.com', /* This is the same value as above, but it is used by topcoder-react-lib, * as a more verbose name for the param. */ - COMMUNITY_APP: "https://community-app.topcoder.com", + COMMUNITY_APP: 'https://community-app.topcoder.com', - AUTH: "https://accounts-auth0.topcoder.com", - BASE: "https://www.topcoder.com", - HOME: "/my-dashboard", - COMMUNITY: "https://community.topcoder.com", - FORUMS: "https://apps.topcoder.com/forums", - FORUMS_VANILLA: "https://discussions.topcoder.com", - HELP: "https://www.topcoder.com/thrive/tracks?track=Topcoder&tax=Help%20Articles", - SUBMISSION_REVIEW: "https://submission-review.topcoder.com", - MEMBER: "https://member.topcoder.com", - ONLINE_REVIEW: "https://software.topcoder.com", - PAYMENT_TOOL: "https://payment.topcoder.com", - STUDIO: "https://studio.topcoder.com", - IOS: "https://ios.topcoder.com", + AUTH: 'https://accounts-auth0.topcoder.com', + BASE: 'https://www.topcoder.com', + HOME: '/my-dashboard', + COMMUNITY: 'https://community.topcoder.com', + FORUMS: 'https://apps.topcoder.com/forums', + FORUMS_VANILLA: 'https://discussions.topcoder.com', + HELP: 'https://www.topcoder.com/thrive/tracks?track=Topcoder&tax=Help%20Articles', + SUBMISSION_REVIEW: 'https://submission-review.topcoder.com', + MEMBER: 'https://member.topcoder.com', + ONLINE_REVIEW: 'https://software.topcoder.com', + PAYMENT_TOOL: 'https://payment.topcoder.com', + STUDIO: 'https://studio.topcoder.com', + IOS: 'https://ios.topcoder.com', /* Connector URL of the TC accounts App. */ - ACCOUNTS_APP_CONNECTOR: "https://accounts-auth0.topcoder.com/", - TCO17: "https://tco17.topcoder.com/", - TCO19: "https://tco19.topcoder.com/", + ACCOUNTS_APP_CONNECTOR: 'https://accounts-auth0.topcoder.com/', + TCO17: 'https://tco17.topcoder.com/', + TCO19: 'https://tco19.topcoder.com/', - TOPGEAR: "https://topgear-app.wipro.com", + TOPGEAR: 'https://topgear-app.wipro.com', - COMMUNITY_API: "http://localhost:8000", + COMMUNITY_API: 'http://localhost:8000', COMMUNITIES: { - BLOCKCHAIN: "https://blockchain.topcoder.com", - COGNITIVE: "https://cognitive.topcoder.com", - ZURICH: "https://zurich.topcoder.com", - COMCAST: "https://comcast.topcoder.com", - CS: "https://cs.topcoder.com", + BLOCKCHAIN: 'https://blockchain.topcoder.com', + COGNITIVE: 'https://cognitive.topcoder.com', + ZURICH: 'https://zurich.topcoder.com', + COMCAST: 'https://comcast.topcoder.com', + CS: 'https://cs.topcoder.com', }, - EMAIL_VERIFY_URL: "http://www.topcoder.com/settings/account/changeEmail", + EMAIL_VERIFY_URL: 'http://www.topcoder.com/settings/account/changeEmail', }, /* Filestack configuration for uploading Submissions * These are for the production back end */ FILESTACK: { - SUBMISSION_CONTAINER: "topcoder-submissions-dmz", + SUBMISSION_CONTAINER: 'topcoder-submissions-dmz', }, ACCOUNT_MENU_SWITCH_TEXT: { - title: "Switch to BUSINESS", - href: "https://connect.topcoder.com", + title: 'Switch to BUSINESS', + href: 'https://connect.topcoder.com', }, HEADER_MENU: [ { - id: "business", - title: "BUSINESS", - href: "https://www.topcoder.com", + id: 'business', + title: 'BUSINESS', + href: 'https://www.topcoder.com', }, { - id: "community", // required for 'Switch to BUSINESS' to work - title: "COMMUNITY", + id: 'community', // required for 'Switch to BUSINESS' to work + title: 'COMMUNITY', secondaryMenu: [ { - title: "Dashboard", - href: "/my-dashboard", + title: 'Dashboard', + href: '/my-dashboard', logged: true, }, { - id: "myprofile", - title: "My Profile", - href: "/members/willFilledByUserName", + id: 'myprofile', + title: 'My Profile', + href: '/members/willFilledByUserName', logged: true, }, { - title: "Payments", - href: "https://community.topcoder.com/PactsMemberServlet?module=PaymentHistory&full_list=false", + title: 'Payments', + href: 'https://community.topcoder.com/PactsMemberServlet?module=PaymentHistory&full_list=false', logged: true, openNewTab: true, }, { - title: "Overview", - href: "/community/learn", + title: 'Overview', + href: '/community/learn', logged: false, }, { - title: "How It Works", - href: "/thrive/tracks?track=Topcoder", + title: 'How It Works', + href: '/thrive/tracks?track=Topcoder', logged: false, }, ], subMenu: [ { - title: "Compete", + title: 'Compete', subMenu: [ { - title: "All Challenges", - href: "/challenges", + title: 'All Challenges', + href: '/challenges', }, { - title: "Competitive Programming", - href: "/community/arena", + title: 'Competitive Programming', + href: '/community/arena', }, { - title: "Gig Work", - href: "/gigs", + title: 'Gig Work', + href: '/gigs', }, { - title: "Practice", - href: "/community/practice", + title: 'Practice', + href: '/community/practice', }, ], }, { - title: "Tracks", + title: 'Tracks', subMenu: [ { - title: "Competitive Programming", - href: "/thrive/tracks?track=Competitive%20Programming", + title: 'Competitive Programming', + href: '/thrive/tracks?track=Competitive%20Programming', }, { - title: "Data Science", - href: "/thrive/tracks?track=Data%20Science&tax=", + title: 'Data Science', + href: '/thrive/tracks?track=Data%20Science&tax=', }, { - title: "Design", - href: "/thrive/tracks?track=Design&tax=", + title: 'Design', + href: '/thrive/tracks?track=Design&tax=', }, { - title: "Development", - href: "/thrive/tracks?track=Development&tax=", + title: 'Development', + href: '/thrive/tracks?track=Development&tax=', }, { - title: "QA", - href: "/thrive/tracks?track=QA&tax=", + title: 'QA', + href: '/thrive/tracks?track=QA&tax=', }, ], }, { - title: "Explore", + title: 'Explore', subMenu: [ { - title: "TCO", - href: "/community/member-programs/topcoder-open", + title: 'TCO', + href: '/community/member-programs/topcoder-open', }, { - title: "Programs", - href: "/community/member-programs", + title: 'Programs', + href: '/community/member-programs', }, { - title: "Forums", - href: "https://discussions.topcoder.com", + title: 'Forums', + href: 'https://discussions.topcoder.com', }, { - title: "Statistics", - href: "/community/statistics", + title: 'Statistics', + href: '/community/statistics', }, { - title: "Blog", - href: "https://www.topcoder.com/blog", + title: 'Blog', + href: 'https://www.topcoder.com/blog', openNewTab: true, }, { - title: "Thrive", - href: "/thrive", + title: 'Thrive', + href: '/thrive', }, ], }, ], }, ], - HEADER_MENU_THEME: "light", + HEADER_MENU_THEME: 'light', HEADER_AUTH_URLS: { - href: "https://accounts-auth0.topcoder.com?utm_source=community-app-main", - location: - "https://accounts-auth0.topcoder.com?retUrl=%S&utm_source=community-app-main", + href: 'https://accounts-auth0.topcoder.com?utm_source=community-app-main', + location: 'https://accounts-auth0.topcoder.com?retUrl=%S&utm_source=community-app-main', }, ACCOUNT_MENU: [ { - title: "Settings", - href: "/settings/profile", + title: 'Settings', + href: '/settings/profile', }, { separator: true }, { - title: "Help", - href: "https://www.topcoder.com/thrive/tracks?track=Topcoder&tax=Help%20Articles", + title: 'Help', + href: 'https://www.topcoder.com/thrive/tracks?track=Topcoder&tax=Help%20Articles', }, { separator: true }, { - title: "Log Out", - href: "https://www.topcoder.com/logout", + title: 'Log Out', + href: 'https://www.topcoder.com/logout', }, ], // Config for TC EDU - THRIVE - TC_EDU_BASE_PATH: "/thrive", - TC_EDU_TRACKS_PATH: "/tracks", - TC_EDU_ARTICLES_PATH: "/articles", - TC_EDU_SEARCH_PATH: "/search", + TC_EDU_BASE_PATH: '/thrive', + TC_EDU_TRACKS_PATH: '/tracks', + TC_EDU_ARTICLES_PATH: '/articles', + TC_EDU_SEARCH_PATH: '/search', TC_EDU_SEARCH_BAR_MAX_RESULTS_EACH_GROUP: 3, ENABLE_RECOMMENDER: true, - PLATFORM_SITE_URL: "https://platform.topcoder.com", + PLATFORM_SITE_URL: 'https://platform.topcoder.com', }; From 4eeb45cd0f113f374670682ca6ddd351ff948954 Mon Sep 17 00:00:00 2001 From: Sushil Shinde Date: Mon, 28 Jun 2021 12:21:46 +0530 Subject: [PATCH 20/20] fix: lint error --- config/default.js | 6 ------ config/production.js | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/config/default.js b/config/default.js index fdb588fe6d..bc183806e0 100644 --- a/config/default.js +++ b/config/default.js @@ -251,12 +251,6 @@ module.exports = { RECRUITCRM_API_KEY: '', GROWSURF_API_KEY: '', SENDGRID_API_KEY: '', - - JWT_AUTH: { - SECRET: 'mysecret', - AUTH_SECRET: 'mysecret', - VALID_ISSUERS: '["https://api.topcoder-dev.com", "https://api.topcoder.com", "https://topcoder-dev.auth0.com/", "https://auth.topcoder-dev.com/"]', - }, }, GROWSURF_CAMPAIGN_ID: '', diff --git a/config/production.js b/config/production.js index 16c2c1be3d..002b8340d8 100644 --- a/config/production.js +++ b/config/production.js @@ -214,5 +214,5 @@ module.exports = { TC_EDU_SEARCH_PATH: '/search', TC_EDU_SEARCH_BAR_MAX_RESULTS_EACH_GROUP: 3, ENABLE_RECOMMENDER: true, - PLATFORM_SITE_URL: 'https://platform.topcoder.com', + PLATFORM_SITE_URL: 'https://platform.topcoder.com', };