diff --git a/Dockerfile b/Dockerfile index 2872abdf..4c8ab73e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,6 +2,7 @@ FROM node:12 WORKDIR /usr/src/app RUN mkdir -p /usr/src/app/user_upload +RUN mkdir -p /usr/src/app/logs COPY package*.json ./ RUN npm install --only=production diff --git a/Jenkinsfile-sun b/Jenkinsfile-sun index 467274d8..173a8194 100644 --- a/Jenkinsfile-sun +++ b/Jenkinsfile-sun @@ -21,7 +21,7 @@ node('build-slave') { build_tag = sh(script: "echo " + params.github_release_tag.split('/')[-1] + "_" + commit_hash + "_" + env.BUILD_NUMBER, returnStdout: true).trim() echo "build_tag: " + build_tag - stage('docker-pre-build') { + stage('docker-pre-build') { sh ''' pwd docker build -f ./Dockerfile.build -t $docker_pre_build . @@ -38,21 +38,22 @@ node('build-slave') { env.NODE_ENV = "build" print "Environment will be : ${env.NODE_ENV}" sh('chmod 777 build.sh') - sh("bash -x build.sh ${build_tag} ${env.NODE_NAME} ${hub_org}") + sh("bash -x build.sh ${build_tag} ${env.NODE_NAME} ${docker_server}") } + stage('ArchiveArtifacts') { + sh ("echo ${build_tag} > build_tag.txt") archiveArtifacts "metadata.json" - sh ("echo ${build_tag} > build_tag.txt") archiveArtifacts "build_tag.txt" currentBuild.description = "${build_tag}" } - + } } catch (err) { currentBuild.result = "FAILURE" throw err } - + } diff --git a/images/Hexagon.png b/images/Hexagon.png new file mode 100644 index 00000000..e60e1e5b Binary files /dev/null and b/images/Hexagon.png differ diff --git a/images/Login_background.png b/images/Login_background.png new file mode 100644 index 00000000..d7f598e5 Binary files /dev/null and b/images/Login_background.png differ diff --git a/images/dopt_logo.png b/images/dopt_logo.png new file mode 100644 index 00000000..7672d637 Binary files /dev/null and b/images/dopt_logo.png differ diff --git a/images/igot_karmayogi.svg b/images/igot_karmayogi.svg new file mode 100644 index 00000000..652d97bc --- /dev/null +++ b/images/igot_karmayogi.svg @@ -0,0 +1,19 @@ + + + igot_karmayogi + + + + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 00000000..afc11a8d --- /dev/null +++ b/index.html @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + +
+
+
+ logo +
+
+ slider1 +
+
+
+
+
+ logo +
+
+

You are logged out!

+
+
+ + +
+
+ +
+
+ + \ No newline at end of file diff --git a/logs/2021_06_29.log b/logs/2021_06_29.log new file mode 100644 index 00000000..c3320ae7 --- /dev/null +++ b/logs/2021_06_29.log @@ -0,0 +1 @@ +{"level":30,"time":1624971983174,"pid":9772,"hostname":"DESKTOP-QH9UV1F","msg":"In WhilteList Call========/proxies/v8/api/user/v2/read"} diff --git a/nodemon/nodemon-igot-stage.json b/nodemon/nodemon-igot-stage.json index 39a05837..da5a3aeb 100644 --- a/nodemon/nodemon-igot-stage.json +++ b/nodemon/nodemon-igot-stage.json @@ -14,7 +14,7 @@ "ES_PASSWORD": "", "ES_USERNAME": "", "FALLBACK_APIS_TO_LEX": false, - "HTTPS_HOST": "https://igot-sunbird.idc.tarento.com", + "HTTPS_HOST": "https://igot-dev.in", "CERT_AUTH_TOKEN": "bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJRekw4VVA1dUtqUFdaZVpMd1ZtTFJvNHdqWTg2a2FrcSJ9.TPjV0xLacSbp3FbJ7XeqHoKFN35Rl4YHx3DZNN9pm0o", "IAP_CLIENT_SECRET": "qWEH1rbrFmDd3V6D", "IAP_CODE_API_BASE": "", @@ -26,7 +26,7 @@ "KEYCLOAK_ADMIN_PASSWORD": "admin", "KEYCLOAK_ADMIN_USERNAME": "admin", "KC_NEW_USER_DEFAULT_PWD": "User@123", - "MULTI_TENANT_KEYCLOAK": "igot;https://igot-sunbird.idc.tarento.com/auth;sunbird", + "MULTI_TENANT_KEYCLOAK": "igot;https://igot-dev.in/auth;sunbird", "LA_HOST_PROXY": "http://IP-ADDR", "NAVIGATOR_JSON_HOST": "http://IP-ADDR:3007/web-hosted/navigator/json", "NODE_API_BASE_2_CLIENT_ID": "admin", diff --git a/package-lock.json b/package-lock.json index ea9108e9..ff126ca8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -237,15 +237,6 @@ "@types/node": "*" } }, - "@types/keycloak-connect": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@types/keycloak-connect/-/keycloak-connect-4.5.1.tgz", - "integrity": "sha512-ioHJ+cZ3r8tfiaP/7aZv1ZJjx3WIA6bwexap7aTa5ioQDiLLHnJzwSeUZNfFm1Cj4J4KVsDsDBy33cY3iaelmg==", - "dev": true, - "requires": { - "@types/express": "*" - } - }, "@types/lodash": { "version": "4.14.170", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.170.tgz", @@ -392,12 +383,29 @@ "@types/vinyl": "*" } }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "requires": { + "event-target-shim": "^5.0.0" + } + }, "accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", @@ -416,6 +424,29 @@ "printj": "~1.1.0" } }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "ajv": { "version": "6.10.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", @@ -528,8 +559,7 @@ "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" }, "arr-filter": { "version": "1.1.2", @@ -543,8 +573,7 @@ "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" }, "arr-map": { "version": "2.0.2", @@ -558,8 +587,7 @@ "arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" }, "array-each": { "version": "1.0.1", @@ -650,8 +678,12 @@ "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==" }, "asn1": { "version": "0.2.4", @@ -662,13 +694,14 @@ } }, "asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", "requires": { "bn.js": "^4.0.0", "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" } }, "assert-plus": { @@ -676,11 +709,20 @@ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" + }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, + "async": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" }, "async-done": { "version": "1.3.1", @@ -725,8 +767,12 @@ "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + }, + "atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==" }, "aws-sign2": { "version": "0.7.0", @@ -746,6 +792,32 @@ "follow-redirects": "1.5.10" } }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "requires": { + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "regenerator-runtime": "^0.10.5" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + } + } + }, "bach": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", @@ -773,7 +845,6 @@ "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, "requires": { "cache-base": "^1.0.1", "class-utils": "^0.3.5", @@ -788,7 +859,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, "requires": { "is-descriptor": "^1.0.0" } @@ -797,7 +867,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -806,7 +875,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -815,7 +883,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -827,8 +894,12 @@ "base64-js": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", - "dev": true + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" + }, + "base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==" }, "basic-auth": { "version": "2.0.1", @@ -846,6 +917,11 @@ "tweetnacl": "^0.14.3" } }, + "bignumber.js": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.2.tgz", + "integrity": "sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==" + }, "binary-extensions": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", @@ -868,9 +944,9 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, "body-parser": { "version": "1.19.0", @@ -933,7 +1009,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, "requires": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", @@ -951,7 +1026,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -1001,6 +1075,11 @@ "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", "dev": true }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "buffer-fill": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", @@ -1059,7 +1138,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, "requires": { "collection-visit": "^1.0.0", "component-emitter": "^1.2.1", @@ -1220,6 +1298,19 @@ "printj": "~1.1.2" } }, + "chai": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz", + "integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==", + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + } + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -1230,6 +1321,16 @@ "supports-color": "^5.3.0" } }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" + }, + "check-types": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-1.4.0.tgz", + "integrity": "sha1-7tY7usnqSaDiagljFAWLA7CN1is=" + }, "chokidar": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz", @@ -1260,7 +1361,6 @@ "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, "requires": { "arr-union": "^3.1.0", "define-property": "^0.2.5", @@ -1272,7 +1372,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -1408,7 +1507,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, "requires": { "map-visit": "^1.0.0", "object-visit": "^1.0.0" @@ -1455,8 +1553,7 @@ "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" }, "composable-middleware": { "version": "0.3.0", @@ -1620,8 +1717,7 @@ "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" }, "copy-props": { "version": "2.0.4", @@ -1633,6 +1729,11 @@ "is-plain-object": "^2.0.1" } }, + "core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -1726,6 +1827,11 @@ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.0.1.tgz", "integrity": "sha512-C14oTzTZy8DH1Eq8N78owrCWvf3+cnJw88BTK/N3DYWVxDJuJzPaNdplzYxDYuuXXGvqBcO4Vy5SOrwAooXSWw==" }, + "dateformat": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.5.1.tgz", + "integrity": "sha512-OD0TZ+B7yP7ZgpJf5K2DIbj3FZvFvxgFUuaqA/V5zTjAtAAXZ1E8bktHxmAGs4x5b7PflqA9LeQ84Og7wYtF7Q==" + }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", @@ -1743,8 +1849,7 @@ "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" }, "decompress": { "version": "4.2.0", @@ -1874,6 +1979,19 @@ } } }, + "deep-diff": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-0.3.8.tgz", + "integrity": "sha1-wB3mPvsO7JeYgB1Ax+Da4ltYLIQ=" + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "requires": { + "type-detect": "^4.0.0" + } + }, "deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -1916,7 +2034,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, "requires": { "is-descriptor": "^1.0.2", "isobject": "^3.0.1" @@ -1926,7 +2043,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -1935,7 +2051,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -1944,7 +2059,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -2176,23 +2290,38 @@ "safer-buffer": "^2.1.0" } }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "elliptic": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz", - "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", + "bn.js": "^4.11.9", + "brorand": "^1.1.0", "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + } } }, "encodeurl": { @@ -2289,6 +2418,11 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + }, "eventemitter3": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", @@ -2318,7 +2452,6 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, "requires": { "debug": "^2.3.3", "define-property": "^0.2.5", @@ -2333,7 +2466,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -2342,7 +2474,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -2351,7 +2482,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -2416,6 +2546,47 @@ "requires": { "ms": "2.0.0" } + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + } + } + }, + "express-cassandra": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/express-cassandra/-/express-cassandra-2.1.0.tgz", + "integrity": "sha1-+1vpZoEhPTxx5tQ4AMIDqbwAzM8=", + "requires": { + "JSONStream": "^1.3.1", + "async": "^1.5.2", + "babel-polyfill": "^6.26.0", + "bluebird": "^3.4.6", + "cassandra-driver": "^3.3.0", + "chai": "^4.1.2", + "check-types": "^1.4.0", + "debug": "^3.1.0", + "deep-diff": "^0.3.4", + "lodash": "^4.14.2", + "object-hash": "1.1.4", + "readdirp": "^2.1.0", + "readline-sync": "^1.4.4", + "semver": "^5.4.1" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "cassandra-driver": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/cassandra-driver/-/cassandra-driver-3.6.0.tgz", + "integrity": "sha512-CkN3V+oPaF5RvakUjD3uUjEm8f6U8S0aT1+YqeQsVT3UDpPT2K8SOdNDEHA1KjamakHch6zkDgHph1xWyqBGGw==", + "requires": { + "long": "^2.2.0" + } } } }, @@ -2495,7 +2666,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, "requires": { "assign-symbols": "^1.0.0", "is-extendable": "^1.0.1" @@ -2505,7 +2675,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, "requires": { "is-plain-object": "^2.0.4" } @@ -2516,7 +2685,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, "requires": { "array-unique": "^0.3.2", "define-property": "^1.0.0", @@ -2532,7 +2700,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, "requires": { "is-descriptor": "^1.0.0" } @@ -2541,7 +2708,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -2550,7 +2716,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -2559,7 +2724,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -2568,7 +2732,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -2604,6 +2767,21 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, + "fast-redact": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.0.1.tgz", + "integrity": "sha512-kYpn4Y/valC9MdrISg47tZOpYBNoTXKgT9GYXFpHN/jYFs+lFkPoisY+LcBODdKVMY96ATzvzsWv+ES/4Kmufw==" + }, + "fast-safe-stringify": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" + }, + "fast-text-encoding": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.4.tgz", + "integrity": "sha512-x6lDDm/tBAzX9kmsPcZsNbvDs3Zey3+scsxaZElS8xWLgUMAg/oFLeewfUz0mu1CblHhhsu15jGkraldkFh8KQ==" + }, "fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -2645,7 +2823,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, "requires": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", @@ -2657,7 +2834,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -2728,6 +2904,11 @@ "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", "dev": true }, + "flatstr": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.12.tgz", + "integrity": "sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==" + }, "flush-write-stream": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", @@ -2749,8 +2930,7 @@ "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" }, "for-own": { "version": "1.0.0", @@ -2790,7 +2970,6 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, "requires": { "map-cache": "^0.2.2" } @@ -3391,12 +3570,45 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "gaxios": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-2.3.4.tgz", + "integrity": "sha512-US8UMj8C5pRnao3Zykc4AAVr+cffoNKRTg9Rsf2GiuZCW69vgJj38VK2PzlPuQU73FZ/nTk9/Av6/JGcE1N9vA==", + "requires": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.3.0" + }, + "dependencies": { + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + } + } + }, + "gcp-metadata": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-3.5.0.tgz", + "integrity": "sha512-ZQf+DLZ5aKcRpLzYUyBS3yo3N0JSa82lNDO8rj3nMSlovLcz2riKFBsYgDzeXcv75oo5eqB2lx+B14UvPoCRnA==", + "requires": { + "gaxios": "^2.1.0", + "json-bigint": "^0.3.0" + } + }, "get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", "dev": true }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" + }, "get-proxy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", @@ -3421,8 +3633,7 @@ "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" }, "getpass": { "version": "0.1.7", @@ -3562,6 +3773,74 @@ "sparkles": "^1.0.0" } }, + "google-auth-library": { + "version": "5.10.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-5.10.1.tgz", + "integrity": "sha512-rOlaok5vlpV9rSiUu5EpR0vVpc+PhN62oF4RyX/6++DG1VsaulAFEMlDYBLjJDDPI6OcNOCGAKy9UVB/3NIDXg==", + "requires": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^2.1.0", + "gcp-metadata": "^3.4.0", + "gtoken": "^4.1.0", + "jws": "^4.0.0", + "lru-cache": "^5.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + } + } + }, + "google-p12-pem": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-2.0.5.tgz", + "integrity": "sha512-7RLkxwSsMsYh9wQ5Vb2zRtkAHvqPvfoMGag+nugl1noYO7gf0844Yr9TIFA5NEBMAeVt2Z+Imu7CQMp3oNatzQ==", + "requires": { + "node-forge": "^0.10.0" + } + }, + "googleapis": { + "version": "45.0.0", + "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-45.0.0.tgz", + "integrity": "sha512-v5+4Cw+MnG3z9FRNTdOCcOWBvzhp0zcbapI3D1E1ndykIRA7tE8oflSBRyyVpX6BDhRGSqNu2lU8G15Fe+Ih4g==", + "requires": { + "google-auth-library": "^5.2.0", + "googleapis-common": "^3.1.0" + } + }, + "googleapis-common": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-3.2.2.tgz", + "integrity": "sha512-sTEXlauVce4eMX0S6hVoiWgxVzQZ7dc16KcGF7eh+A+uIyDgXqnuwOMZw+svX4gOJv6w4ACecm23Qh9UDaldsw==", + "requires": { + "extend": "^3.0.2", + "gaxios": "^2.0.1", + "google-auth-library": "^5.6.1", + "qs": "^6.7.0", + "url-template": "^2.0.8", + "uuid": "^7.0.0" + }, + "dependencies": { + "uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==" + } + } + }, "got": { "version": "6.7.1", "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", @@ -3584,8 +3863,7 @@ "graceful-fs": { "version": "4.1.15", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", - "dev": true + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" }, "graceful-readlink": { "version": "1.0.1", @@ -3593,6 +3871,24 @@ "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", "dev": true }, + "gtoken": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-4.1.4.tgz", + "integrity": "sha512-VxirzD0SWoFUo5p8RDP8Jt2AGyOmyYcT/pOUgDKJCK+iSw0TMqwrVfY37RXTNmoKwrzmDHSk0GMT9FsgVmnVSA==", + "requires": { + "gaxios": "^2.1.0", + "google-p12-pem": "^2.0.0", + "jws": "^4.0.0", + "mime": "^2.2.0" + }, + "dependencies": { + "mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==" + } + } + }, "gulp": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", @@ -3747,7 +4043,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, "requires": { "get-value": "^2.0.6", "has-values": "^1.0.0", @@ -3758,7 +4053,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, "requires": { "is-number": "^3.0.0", "kind-of": "^4.0.0" @@ -3767,14 +4061,12 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -3923,6 +4215,30 @@ "sshpk": "^1.7.0" } }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "husky": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/husky/-/husky-2.3.0.tgz", @@ -4116,7 +4432,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -4124,14 +4439,12 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -4171,7 +4484,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -4179,14 +4491,12 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -4197,7 +4507,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, "requires": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", @@ -4207,8 +4516,7 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" } } }, @@ -4221,8 +4529,7 @@ "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" }, "is-extglob": { "version": "2.1.1", @@ -4277,7 +4584,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -4285,14 +4591,12 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -4356,7 +4660,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, "requires": { "isobject": "^3.0.1" } @@ -4417,14 +4720,12 @@ "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isexe": { "version": "2.0.0", @@ -4435,8 +4736,7 @@ "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, "isstream": { "version": "0.1.2", @@ -4474,6 +4774,14 @@ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, + "json-bigint": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-0.3.1.tgz", + "integrity": "sha512-DGWnSzmusIreWlEupsUelHrhwmPPE+FiQvg+drKfk2p+bdEYa5mp4PJ8JsCWqae0M2jQNb0HPvnwvf1qOTThzQ==", + "requires": { + "bignumber.js": "^9.0.0" + } + }, "json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", @@ -4507,6 +4815,54 @@ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" + }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "dependencies": { + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -4524,16 +4880,40 @@ "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", "dev": true }, + "jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, "jwk-to-pem": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/jwk-to-pem/-/jwk-to-pem-1.2.6.tgz", - "integrity": "sha1-1QfOzkAInFJI4J7GgmaiAwqcYyU=", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/jwk-to-pem/-/jwk-to-pem-2.0.5.tgz", + "integrity": "sha512-L90jwellhO8jRKYwbssU9ifaMVqajzj3fpRjDKcsDzrslU9syRbFqfkXtT4B89HYAap+xsxNcxgBSB09ig+a7A==", + "requires": { + "asn1.js": "^5.3.0", + "elliptic": "^6.5.4", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", "requires": { - "asn1.js": "^4.5.2", - "elliptic": "^6.2.3", + "jwa": "^2.0.0", "safe-buffer": "^5.0.1" } }, + "jwt-decode": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz", + "integrity": "sha512-86GgN2vzfUu7m9Wcj63iUkuDzFNYFVmjeDm2GzWpUk+opB0pEpMsw6ePCMrhYkumz2C1ihqtZzOMAg7FiXcNoQ==" + }, "keycloak-admin": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/keycloak-admin/-/keycloak-admin-1.13.0.tgz", @@ -4561,11 +4941,10 @@ } }, "keycloak-connect": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/keycloak-connect/-/keycloak-connect-3.4.3.tgz", - "integrity": "sha1-Z3W1mRJdJNUk9uZKXlEv2gBpLE4=", + "version": "git+https://github.com/sunbird-cb/keycloak-nodejs-connect.git#536a6816b990257ec77bd8f576538aff8ba10283", + "from": "git+https://github.com/sunbird-cb/keycloak-nodejs-connect.git#release-2.5.0", "requires": { - "jwk-to-pem": "^1.2.6" + "jwk-to-pem": "^2.0.0" } }, "keyv": { @@ -4580,8 +4959,7 @@ "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" }, "last-run": { "version": "1.1.1", @@ -4696,6 +5074,41 @@ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -4750,14 +5163,12 @@ "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, "requires": { "object-visit": "^1.0.0" } @@ -4822,7 +5233,6 @@ "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, "requires": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", @@ -4892,7 +5302,6 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, "requires": { "for-in": "^1.0.2", "is-extendable": "^1.0.1" @@ -4902,7 +5311,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, "requires": { "is-plain-object": "^2.0.4" } @@ -4970,7 +5378,6 @@ "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, "requires": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", @@ -5007,6 +5414,19 @@ "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.1.0.tgz", "integrity": "sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q==" }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==" + }, "node-xlsx": { "version": "0.15.0", "resolved": "https://registry.npmjs.org/node-xlsx/-/node-xlsx-0.15.0.tgz", @@ -5137,7 +5557,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, "requires": { "copy-descriptor": "^0.1.0", "define-property": "^0.2.5", @@ -5148,7 +5567,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -5156,20 +5574,23 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } } } }, + "object-hash": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.1.4.tgz", + "integrity": "sha1-E28H8aSK9fa5BoEkUa5OQ5eMlKo=" + }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -5180,7 +5601,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, "requires": { "isobject": "^3.0.0" } @@ -5223,7 +5643,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, "requires": { "isobject": "^3.0.1" } @@ -5408,8 +5827,7 @@ "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" }, "path-dirname": { "version": "1.0.2", @@ -5463,9 +5881,9 @@ "dev": true }, "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.0.tgz", + "integrity": "sha512-f66KywYG6+43afgE/8j/GoiNyygk/bnoCbps++3ErRKsIYkGGupyv07R2Ok5m9i67Iqc+T2g1eAUGUPzWhYTyg==" }, "path-type": { "version": "1.1.0", @@ -5486,6 +5904,11 @@ } } }, + "pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==" + }, "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -5518,6 +5941,24 @@ "pinkie": "^2.0.0" } }, + "pino": { + "version": "6.11.3", + "resolved": "https://registry.npmjs.org/pino/-/pino-6.11.3.tgz", + "integrity": "sha512-drPtqkkSf0ufx2gaea3TryFiBHdNIdXKf5LN0hTM82SXI4xVIve2wLwNg92e1MT6m3jASLu6VO7eGY6+mmGeyw==", + "requires": { + "fast-redact": "^3.0.0", + "fast-safe-stringify": "^2.0.7", + "flatstr": "^1.0.12", + "pino-std-serializers": "^3.1.0", + "quick-format-unescaped": "^4.0.3", + "sonic-boom": "^1.0.2" + } + }, + "pino-std-serializers": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-3.2.0.tgz", + "integrity": "sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg==" + }, "pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -5580,8 +6021,7 @@ "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, "prepend-http": { "version": "1.0.4", @@ -5603,8 +6043,7 @@ "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" }, "progress": { "version": "2.0.3", @@ -5698,6 +6137,11 @@ "strict-uri-encode": "^1.0.0" } }, + "quick-format-unescaped": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.3.tgz", + "integrity": "sha512-MaL/oqh02mhEo5m5J2rwsVL23Iw2PEaGVHgT2vFt8AAsr0lfvQA5dpXo9TPu0rz7tSBdUPgkbam0j/fj5ZM8yg==" + }, "random-bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", @@ -5789,7 +6233,6 @@ "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -5804,13 +6247,17 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, "requires": { "graceful-fs": "^4.1.11", "micromatch": "^3.1.10", "readable-stream": "^2.0.2" } }, + "readline-sync": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz", + "integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==" + }, "rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", @@ -5831,11 +6278,15 @@ "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", "dev": true }, + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" + }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, "requires": { "extend-shallow": "^3.0.2", "safe-regex": "^1.1.0" @@ -5898,14 +6349,12 @@ "repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, "replace-ext": { "version": "1.0.0", @@ -6022,8 +6471,7 @@ "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" }, "responselike": { "version": "1.0.2", @@ -6037,8 +6485,7 @@ "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" }, "rimraf": { "version": "2.6.3", @@ -6064,7 +6511,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, "requires": { "ret": "~0.1.10" } @@ -6097,8 +6543,7 @@ "semver": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", - "dev": true + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" }, "semver-compare": { "version": "1.0.0", @@ -6187,7 +6632,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, "requires": { "extend-shallow": "^2.0.1", "is-extendable": "^0.1.1", @@ -6199,7 +6643,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -6248,7 +6691,6 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, "requires": { "base": "^0.11.1", "debug": "^2.2.0", @@ -6264,7 +6706,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -6273,7 +6714,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -6282,7 +6722,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -6293,7 +6732,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, "requires": { "define-property": "^1.0.0", "isobject": "^3.0.0", @@ -6304,7 +6742,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, "requires": { "is-descriptor": "^1.0.0" } @@ -6313,7 +6750,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -6322,7 +6758,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -6331,7 +6766,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -6344,7 +6778,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, "requires": { "kind-of": "^3.2.0" }, @@ -6352,14 +6785,12 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -6438,6 +6869,15 @@ } } }, + "sonic-boom": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz", + "integrity": "sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg==", + "requires": { + "atomic-sleep": "^1.0.0", + "flatstr": "^1.0.12" + } + }, "sort-keys": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", @@ -6459,14 +6899,12 @@ "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" }, "source-map-resolve": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "dev": true, "requires": { "atob": "^2.1.1", "decode-uri-component": "^0.2.0", @@ -6496,8 +6934,7 @@ "source-map-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" }, "sparkles": { "version": "1.0.1", @@ -6541,7 +6978,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, "requires": { "extend-shallow": "^3.0.0" } @@ -6586,7 +7022,6 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, "requires": { "define-property": "^0.2.5", "object-copy": "^0.1.0" @@ -6596,7 +7031,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -6645,7 +7079,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "requires": { "safe-buffer": "~5.1.0" } @@ -6743,8 +7176,7 @@ "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "through2": { "version": "2.0.5", @@ -6798,7 +7230,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -6806,14 +7237,12 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -6824,7 +7253,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, "requires": { "define-property": "^2.0.2", "extend-shallow": "^3.0.2", @@ -6836,7 +7264,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, "requires": { "is-number": "^3.0.0", "repeat-string": "^1.6.1" @@ -6881,6 +7308,11 @@ } } }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "trim-repeated": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", @@ -7039,6 +7471,11 @@ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + }, "type-fest": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.4.1.tgz", @@ -7137,7 +7574,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, "requires": { "arr-union": "^3.1.0", "get-value": "^2.0.6", @@ -7173,7 +7609,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, "requires": { "has-value": "^0.3.1", "isobject": "^3.0.0" @@ -7183,7 +7618,6 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, "requires": { "get-value": "^2.0.3", "has-values": "^0.1.4", @@ -7194,7 +7628,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, "requires": { "isarray": "1.0.0" } @@ -7204,8 +7637,7 @@ "has-values": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" } } }, @@ -7250,8 +7682,7 @@ "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" }, "url-join": { "version": "4.0.1", @@ -7281,14 +7712,12 @@ "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "utils-merge": { "version": "1.0.1", @@ -7405,6 +7834,20 @@ } } }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", diff --git a/package.json b/package.json index a7ac59ea..223727b1 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,9 @@ "dependencies": { "@types/cors": "^2.8.6", "@types/node-xlsx": "^0.15.0", + "async": "^3.2.0", "axios": "^0.19.1", + "base64url": "^3.0.1", "cassandra-driver": "^4.1.0", "cassandra-store": "^5.0.0", "chalk": "^2.4.2", @@ -30,18 +32,25 @@ "cookie-parser": "^1.4.5", "cors": "^2.8.5", "date-fns": "^2.0.1", + "dateformat": "^4.5.1", "express": "^4.17.1", + "express-cassandra": "2.1.0", "express-fileupload": "^1.1.4", "express-healthcheck": "^0.1.0", "express-session": "^1.16.1", "form-data": "^3.0.0", + "googleapis": "45.0.0", "helmet": "^3.21.2", "http-proxy": "^1.17.0", + "jsonwebtoken": "^8.5.1", + "jwt-decode": "^2.2.0", "keycloak-admin": "^1.13.0", - "keycloak-connect": "^3.4.3", + "keycloak-connect": "git+https://github.com/sunbird-cb/keycloak-nodejs-connect.git#release-2.5.0", "lodash": "^4.17.21", "morgan": "^1.9.1", "node-xlsx": "^0.15.0", + "path-to-regexp": "^6.2.0", + "pino": "^6.11.3", "request": "^2.88.0", "uuid": "^3.3.2" }, @@ -55,7 +64,6 @@ "@types/express-session": "^1.15.12", "@types/helmet": "0.0.43", "@types/http-proxy": "^1.17.0", - "@types/keycloak-connect": "^4.5.1", "@types/lodash": "^4.14.170", "@types/morgan": "^1.7.35", "@types/node": "^12.0.4", diff --git a/src/authoring/content/index.ts b/src/authoring/content/index.ts index bf4ad3b0..e6390f5b 100644 --- a/src/authoring/content/index.ts +++ b/src/authoring/content/index.ts @@ -1,8 +1,10 @@ import axios from 'axios' import { Request, Response, Router } from 'express' +import { axiosRequestConfig } from '../../configs/request.config' import { AxiosRequestConfig } from '../../models/axios-request-config.model' -import { logError } from '../../utils/logger' -import { ERROR } from '../constants/error' +import { logError} from '../../utils/logger' +import { ERROR } from '../../utils/message' +import { extractUserIdFromRequest , extractUserToken} from '../../utils/requestExtract' import { IUploadS3Request, IUploadS3Response } from '../models/response/custom-s3-upload' import { decoder } from '../utils/decode' import { getOrg, getRootOrg } from '../utils/header' @@ -16,7 +18,25 @@ import { getHierarchy, getMultipleHierarchyV2 } from './hierarchy' import { getHierarchyV2WithContent, getMultipleHierarchyV2WithContent } from './hierarchy-and-content' import { searchForOtherLanguage } from './language-search' +const _ = require('lodash') + export const authApi = Router() +const failedToProcess = 'Failed to process the request. ' +const actionConst = '/action' + +const API_END_POINTS = { + addCertToCourseBatch: `${CONSTANTS.KONG_API_BASE}/course/batch/cert/v1/template/add`, + batchAddUser: `${CONSTANTS.KONG_API_BASE}/course/v1/admin/enrol`, + batchRemoveUser: `${CONSTANTS.KONG_API_BASE}/course/v1/admin/unenrol`, + createBatch: `${CONSTANTS.KONG_API_BASE}/course/v1/batch/create`, + downloadCert: `${CONSTANTS.KONG_API_BASE}/certreg/v1/certs/download`, + getUserProgress: `${CONSTANTS.KONG_API_BASE}/v1/batch/getUserProgress`, + issueCertToCourseBatch: `${CONSTANTS.KONG_API_BASE}/course/batch/cert/v1/issue?reIssue=true`, + readBatch: (batchId: string) => `${CONSTANTS.KONG_API_BASE}/course/v1/batch/read/${batchId}`, + readCert: (certId: string) => `${CONSTANTS.KONG_API_BASE}/certreg/v2/certs/download/${certId}`, + removeCertFromCourseBatch: `${CONSTANTS.KONG_API_BASE}/course/batch/cert/v1/template/remove`, + updateBatch: `${CONSTANTS.KONG_API_BASE}/course/v1/batch/update`, +} authApi.all('*', (req, _res, next) => { if (req.body && req.body.data && typeof req.body.data === 'string') { @@ -34,7 +54,7 @@ authApi.get('/hierarchy/:id', async (req: Request, res: Response) => { } catch (ex) { logError(ex) res.status(400).send({ - msg: ERROR.GENERAL, + msg: ERROR.GENERAL_ERR_MSG, }) } }) @@ -48,7 +68,7 @@ authApi.get('/hierarchy/content/:id', async (req: Request, res: Response) => { } catch (ex) { logError(ex) res.status(400).send({ - msg: ERROR.GENERAL, + msg: ERROR.GENERAL_ERR_MSG, }) } }) @@ -62,7 +82,7 @@ authApi.get('/hierarchy/multiple/:ids', async (req: Request, res: Response) => { } catch (ex) { logError(ex) res.status(400).send({ - msg: ERROR.GENERAL, + msg: ERROR.GENERAL_ERR_MSG, }) } }) @@ -77,7 +97,7 @@ authApi.get('/hierarchy/multiple/content/:ids', async (req: Request, res: Respon } catch (ex) { logError(ex) res.status(400).send({ - msg: ERROR.GENERAL, + msg: ERROR.GENERAL_ERR_MSG, }) } }) @@ -97,7 +117,7 @@ authApi.get('/hierarchy/content/translation/:id', async (req, res) => { } catch (ex) { logError(ex) res.status(400).send({ - msg: ERROR.GENERAL, + msg: ERROR.GENERAL_ERR_MSG, }) } }) @@ -170,9 +190,17 @@ authApi.post('/download/s3', async (req: Request, res: Response) => { authApi.post('/content/v3/create', async (request: Request, res: Response) => { axios({ data: request.body, - headers: request.headers, - method: request.method, - url: CONSTANTS.SUNBIRD_PROXY_URL + request.url, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: no-duplicate-string + 'X-Channel-Id' : (_.get(request, 'session.rootOrgId')) ? _.get(request, 'session.rootOrgId') : CONSTANTS.X_Channel_Id, + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-user-token': extractUserToken(request), + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-userid' : extractUserIdFromRequest(request), + }, + method: request.method, + url: CONSTANTS.KNOWLEDGE_MW_API_BASE + actionConst + request.url, } as AxiosRequestConfig) .then((response) => { res.status(response.status).send(response.data) @@ -184,9 +212,18 @@ authApi.post('/content/v3/create', async (request: Request, res: Response) => { authApi.get('/content/v3/read/:id', async (req: Request, res: Response) => { axios({ - headers: req.headers, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: no-duplicate-string + 'X-Channel-Id' : (_.get(req, 'session.rootOrgId')) ? _.get(req, 'session.rootOrgId') : CONSTANTS.X_Channel_Id, + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-user-token': extractUserToken(req), + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-userid' : extractUserIdFromRequest(req), + + }, method: req.method, - url: CONSTANTS.SUNBIRD_PROXY_URL + req.url, + url: CONSTANTS.KNOWLEDGE_MW_API_BASE + actionConst + req.url, } as AxiosRequestConfig) .then((response) => { res.status(response.status).send(response.data) @@ -199,9 +236,17 @@ authApi.get('/content/v3/read/:id', async (req: Request, res: Response) => { authApi.patch('/content/v3/update/:id', async (req: Request, res: Response) => { axios({ data: req.body, - headers: req.headers, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: no-duplicate-string + 'X-Channel-Id' : (_.get(req, 'session.rootOrgId')) ? _.get(req, 'session.rootOrgId') : CONSTANTS.X_Channel_Id, + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-user-token': extractUserToken(req), + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-userid' : extractUserIdFromRequest(req), + }, method: req.method, - url: CONSTANTS.SUNBIRD_PROXY_URL + req.url, + url: CONSTANTS.KNOWLEDGE_MW_API_BASE + actionConst + req.url, } as AxiosRequestConfig) .then((response) => { res.status(response.status).send(response.data) @@ -211,6 +256,135 @@ authApi.patch('/content/v3/update/:id', async (req: Request, res: Response) => { }) }) +authApi.get('/readBatch/:batchId', async (req: Request, res: Response) => { + try { + const batchId = req.params.batchId + const response = await axios.get(API_END_POINTS.readBatch(batchId), { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-user-token': extractUserToken(req), + }, + }) + res.status(response.status).send(response.data) + } catch (err) { + logError(failedToProcess + err) + res.status((err && err.response && err.response.status) || 500).send( + (err && err.response && err.response.data) || { + error: ERROR.GENERAL_ERR_MSG, + } + ) + } +}) + +authApi.post('/batch/:key', async (req: Request, res: Response) => { + try { + const key = req.params.key as string + let targetUrl = '' + switch (key) { + case 'create': + targetUrl = API_END_POINTS.createBatch + break + case 'addUser': + targetUrl = API_END_POINTS.batchAddUser + break + case 'removeUser': + targetUrl = API_END_POINTS.batchRemoveUser + break + case 'issueBatchCert': + targetUrl = API_END_POINTS.issueCertToCourseBatch + break + case 'downloadCert': + targetUrl = API_END_POINTS.downloadCert + break + case 'getUserProgress': + targetUrl = API_END_POINTS.getUserProgress + break + default: + logError('Unsupported operation received for batch API - ' + key) + res.status(400).send('Unsupported operation name - ' + key) + break + } + const response = await axios.post(targetUrl, req.body, { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-user-token': extractUserToken(req), + }, + }) + res.status(response.status).send(response.data) + } catch (err) { + logError(failedToProcess + err) + res.status((err && err.response && err.response.status) || 500).send( + (err && err.response && err.response.data) || { + error: ERROR.GENERAL_ERR_MSG, + } + ) + } +}) + +authApi.patch('/batch/:key', async (req: Request, res: Response) => { + try { + const key = req.params.key as string + let targetUrl = '' + switch (key) { + case 'update': + targetUrl = API_END_POINTS.updateBatch + break + case 'addCert': + targetUrl = API_END_POINTS.addCertToCourseBatch + break + case 'removeCert': + targetUrl = API_END_POINTS.removeCertFromCourseBatch + break + default: + logError('Unsupported operation received for batch API - ' + key) + res.status(400).send('Unsupported operation name - ' + key) + break + } + const response = await axios.patch(targetUrl, req.body, { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-user-token': extractUserToken(req), + }, + }) + res.status(response.status).send(response.data) + } catch (err) { + logError(failedToProcess + err) + res.status((err && err.response && err.response.status) || 500).send( + (err && err.response && err.response.data) || { + error: ERROR.GENERAL_ERR_MSG, + } + ) + } +}) + +authApi.get('/readCert/:certId', async (req, res) => { + try { + const certId = req.params.certId + const response = await axios.get(API_END_POINTS.readCert(certId), { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-user-token': extractUserToken(req), + }, + }) + res.status(response.status).send(response.data) + } catch (err) { + logError(failedToProcess + err) + res.status((err && err.response && err.response.status) || 500).send( + (err && err.response && err.response.data) || { + error: ERROR.GENERAL_ERR_MSG, + } + ) + } +}) + authApi.all('*', (req: Request, res: Response) => { axios({ data: req.body, diff --git a/src/configs/cassandra.config.ts b/src/configs/cassandra.config.ts index 1d751e30..f2cb7966 100644 --- a/src/configs/cassandra.config.ts +++ b/src/configs/cassandra.config.ts @@ -2,10 +2,14 @@ import cassandraDriver from 'cassandra-driver' import { CONSTANTS } from '../utils/env' export const cassandraClientOptions: cassandraDriver.ClientOptions = { - contactPoints: [CONSTANTS.CASSANDRA_IP], + contactPoints: getIPList(), keyspace: CONSTANTS.CASSANDRA_KEYSPACE, localDataCenter: 'datacenter1', queryOptions: { prepare: true, }, } + +function getIPList() { + return CONSTANTS.CASSANDRA_IP.split(',') +} diff --git a/src/configs/keycloak.config.ts b/src/configs/keycloak.config.ts index 61244877..030c54b2 100644 --- a/src/configs/keycloak.config.ts +++ b/src/configs/keycloak.config.ts @@ -2,9 +2,24 @@ import { CONSTANTS } from '../utils/env' export function getKeycloakConfig(url?: string, realm?: string) { return { - bearerOnly: true, + 'ssl-required': 'external', + // tslint:disable-next-line: object-literal-sort-keys + 'public-client': true, realm: realm ? realm : CONSTANTS.KEYCLOAK_REALM, resource: 'portal', - serverUrl: url ? `${url}` : `${CONSTANTS.HTTPS_HOST}/auth`, + 'auth-server-url': url ? `${url}` : `${CONSTANTS.HTTPS_HOST}/auth`, + 'confidential-port': 0, + } +} + +export function getOAuthKeycloakConfig() { + return { + bearerOnly: true, + credentials: { + secret: CONSTANTS.KEYCLOAK_GOOGLE_CLIENT_SECRET, + }, + realm: CONSTANTS.PORTAL_REALM, + resource: CONSTANTS.KEYCLOAK_GOOGLE_CLIENT_ID, + serverUrl: CONSTANTS.PORTAL_AUTH_SERVER_URL, } } diff --git a/src/configs/session.config.ts b/src/configs/session.config.ts index 0ef3a7b2..971338f5 100644 --- a/src/configs/session.config.ts +++ b/src/configs/session.config.ts @@ -2,16 +2,25 @@ import cassandraDriver from 'cassandra-driver' import cassandraStore from 'cassandra-store' import expressSession from 'express-session' import { CONSTANTS } from '../utils/env' +const expressCassandra = require('express-cassandra') +const _ = require('lodash') let sessionConfig: expressSession.SessionOptions +const consistency = getConsistencyLevel(CONSTANTS.PORTAL_CASSANDRA_CONSISTENCY_LEVEL) const cassandraClientOptions: cassandraDriver.ClientOptions = { - contactPoints: [CONSTANTS.CASSANDRA_IP], + contactPoints: getIPList(), keyspace: 'portal', queryOptions: { + consistency, prepare: true, }, } + +function getIPList() { + return CONSTANTS.CASSANDRA_IP.split(',') +} + if ( CONSTANTS.IS_CASSANDRA_AUTH_ENABLED && CONSTANTS.CASSANDRA_USERNAME && @@ -45,3 +54,9 @@ export function getSessionConfig( } return sessionConfig } + +// tslint:disable-next-line: no-any +function getConsistencyLevel(consistencyParam: any) { + // tslint:disable-next-line: max-line-length + return (consistencyParam && _.get(expressCassandra, `consistencies.${consistencyParam}`) ? _.get(expressCassandra, `consistencies.${consistencyParam}`) : expressCassandra.consistencies.one) +} diff --git a/src/index.ts b/src/index.ts index 7bbb9f87..3f2b36a6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,4 @@ import cluster from 'cluster' -import * as os from 'os' import { Server } from './server' // Code to inject axios retry logic @@ -13,9 +12,10 @@ if (cluster.isMaster) { if (CONSTANTS.IS_DEVELOPMENT) { cluster.fork() } else { - os.cpus().forEach(() => { + const threadCount = CONSTANTS.CLUSTER_THREAD + for (let index = 0; index < threadCount; index++) { cluster.fork() - }) + } } cluster.on('exit', () => { diff --git a/src/models/user.model.ts b/src/models/user.model.ts index 96e4a75e..966bd3d3 100644 --- a/src/models/user.model.ts +++ b/src/models/user.model.ts @@ -151,4 +151,5 @@ export interface ISunbirdbUserResponse { firstName: string lastName: string userId: string + userOrgId: string } diff --git a/src/protectedApi_v8/catalog.ts b/src/protectedApi_v8/catalog.ts index ef6c4303..ed97ba22 100644 --- a/src/protectedApi_v8/catalog.ts +++ b/src/protectedApi_v8/catalog.ts @@ -7,22 +7,22 @@ import { IFilterUnitContent } from '../models/catalog.model' import { getFilters, getFilterUnitByType } from '../service/catalog' import { logError } from '../utils/logger' import { ERROR } from '../utils/message' -import { extractAuthorizationFromRequest, extractUserIdFromRequest } from '../utils/requestExtract' +import {extractUserIdFromRequest, extractUserToken} from '../utils/requestExtract' export const catalogApi = Router() const API_END_POINTS = { - getCatalogEndPoint: `${CONSTANTS.SB_EXT_API_BASE_2}/v1/catalog/`, + getCatalogEndPoint: `${CONSTANTS.KONG_API_BASE}/v1/catalog/`, } const failedToProcess = 'Failed to process the request. ' catalogApi.get('/', async (req, res) => { try { - const xAuth = extractAuthorizationFromRequest(req).split(' ') const response = await axios.get(API_END_POINTS.getCatalogEndPoint, { ...axiosRequestConfig, headers: { - xAuthUser: xAuth[1], + Authorization: CONSTANTS.SB_API_KEY, + 'x-authenticated-user-token': extractUserToken(req), }, }) res.status(response.status).send(response.data) diff --git a/src/protectedApi_v8/cohorts.ts b/src/protectedApi_v8/cohorts.ts index d58c9650..12d424d0 100644 --- a/src/protectedApi_v8/cohorts.ts +++ b/src/protectedApi_v8/cohorts.ts @@ -4,19 +4,20 @@ import { axiosRequestConfig } from '../configs/request.config' import { CONSTANTS } from '../utils/env' import { logError } from '../utils/logger' import { ERROR } from '../utils/message' -import { extractUserIdFromRequest } from '../utils/requestExtract' +import { extractAuthorizationFromRequest, extractUserIdFromRequest, extractUserToken } from '../utils/requestExtract' const API_END_POINTS = { - addTemplate: `https://igot-dev.in/api/course/batch/cert/v1/template/add`, - autoenrollment: (userId: string, courseId: string) => `${CONSTANTS.COHORTS_API_BASE}/v1/autoenrollment/${userId}/${courseId}`, - cohorts: `${CONSTANTS.COHORTS_API_BASE}/v2/resources`, - downloadCert: (certId: string) => `https://igot-dev.in/api/certreg/v2/certs/download/${certId}`, + addTemplate: `${CONSTANTS.HTTPS_HOST}/api/course/batch/cert/v1/template/add`, + autoenrollment: `${CONSTANTS.KONG_API_BASE}/v1/autoenrollment`, + batchParticipantsApi: `${CONSTANTS.KONG_API_BASE}/course/v1/batch/participants/list`, + cohorts: `${CONSTANTS.KONG_API_BASE}/v2/resources`, + downloadCert: (certId: string) => `${CONSTANTS.HTTPS_HOST}/api/certreg/v2/certs/download/${certId}`, groupCohorts: (groupId: number) => `${CONSTANTS.USER_PROFILE_API_BASE}/groups/${groupId}/users `, hierarchyApiEndPoint: (contentId: string) => `${CONSTANTS.KNOWLEDGE_MW_API_BASE}/action/content/v3/hierarchy/${contentId}?hierarchyType=detail`, - issueCert: 'https://igot-dev.in/api/course/batch/cert/v1/issue?reIssue=true', - + issueCert: `${CONSTANTS.KONG_API_BASE}/course/batch/cert/v1/issue?reIssue=true`, + kongSearchUser: `${CONSTANTS.KONG_API_BASE}/user/v1/search`, searchUserRegistry: `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/v1/user/search/profile`, } const VALID_COHORT_TYPES = new Set([ @@ -41,24 +42,25 @@ cohortsApi.get('/:cohortType/:contentId', async (req, res) => { } const org = req.header('org') const rootOrgValue = req.header('rootOrg') - const auth = req.header('Authorization') as string if (!org || !rootOrgValue) { res.status(400).send(ERROR.ERROR_NO_ORG_DATA) return } if (cohortType === 'authors') { const host = req.protocol + '://' + req.get('host') - const userList = await getAuthorsDetails(host, auth, contentId) + const userList = await getAuthorsDetails(host, extractAuthorizationFromRequest(req), contentId) res.status(200).send(userList) } else { - const url = `${API_END_POINTS.cohorts}/${contentId}/user/${extractUserIdFromRequest( - req - )}/cohorts/${cohortType}` + const url = `${API_END_POINTS.cohorts}/user/cohorts/${cohortType}` const response = await axios({ ...axiosRequestConfig, headers: { - Authorization: auth, + Authorization: CONSTANTS.SB_API_KEY, + resourceId: contentId, rootOrg: rootOrgValue, + userUUID: extractUserIdFromRequest(req), + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-user-token': extractUserToken(req), }, method: 'GET', url, @@ -144,12 +146,15 @@ cohortsApi.get('/user/autoenrollment/:courseId', async (req, res) => { const courseId = req.params.courseId const wid = req.headers.wid as string const rootOrgValue = req.headers.rootorg - const auth = req.header('Authorization') as string - const response = await axios.get(API_END_POINTS.autoenrollment(wid, courseId), { + const response = await axios.get(API_END_POINTS.autoenrollment, { ...axiosRequestConfig, headers: { - Authorization: auth, + Authorization: CONSTANTS.SB_API_KEY, + courseId, rootOrg: rootOrgValue, + userUUID: wid, + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-user-token': extractUserToken(req), }, }) res.status(response.status).send(response.data) @@ -166,14 +171,12 @@ cohortsApi.get('/user/autoenrollment/:courseId', async (req, res) => { cohortsApi.patch('/course/batch/cert/template/add', async (req, res) => { try { const template = req.body - const auth = req.header('Authorization') as string - const token = auth.split(' ')[1] const response = await axios.patch(API_END_POINTS.addTemplate, template, { ...axiosRequestConfig, headers: { - Authorization: CONSTANTS.CERT_AUTH_TOKEN, + Authorization: CONSTANTS.SB_API_KEY, /* tslint:disable-next-line */ - 'x-authenticated-user-token': token, + 'x-authenticated-user-token': extractUserToken(req), }, }) @@ -192,14 +195,12 @@ cohortsApi.patch('/course/batch/cert/template/add', async (req, res) => { cohortsApi.post('/course/batch/cert/issue', async (req, res) => { try { const template = req.body - const auth = req.header('Authorization') as string - const token = auth.split(' ')[1] const response = await axios.post(API_END_POINTS.issueCert, template, { ...axiosRequestConfig, headers: { - Authorization: CONSTANTS.CERT_AUTH_TOKEN, + Authorization: CONSTANTS.SB_API_KEY, /* tslint:disable-next-line */ - 'x-authenticated-user-token': token, + 'x-authenticated-user-token': extractUserToken(req), }, }) @@ -218,14 +219,12 @@ cohortsApi.post('/course/batch/cert/issue', async (req, res) => { cohortsApi.get('/course/batch/cert/download/:certId', async (req, res) => { try { const certId = req.params.certId - const auth = req.header('Authorization') as string - const token = auth.split(' ')[1] const response = await axios.get(API_END_POINTS.downloadCert(certId), { ...axiosRequestConfig, headers: { - Authorization: CONSTANTS.CERT_AUTH_TOKEN, + Authorization: CONSTANTS.SB_API_KEY, /* tslint:disable-next-line */ - 'x-authenticated-user-token': token, + 'x-authenticated-user-token': extractUserToken(req), }, }) @@ -241,17 +240,85 @@ cohortsApi.get('/course/batch/cert/download/:certId', async (req, res) => { } }) -function getUsers(userprofile: IUserProfile): ICohortsUser { +cohortsApi.get('/course/getUsersForBatch/:batchId', async (req, res) => { + try { + const batchId = req.params.batchId + const reqBody = { + request: { + batch: { + active: true, + batchId, + }, + }, + } + const userlist: ICohortsUser[] = [] + const response = await axios.post(API_END_POINTS.batchParticipantsApi, reqBody, { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + /* tslint:disable-next-line */ + 'x-authenticated-user-token': extractUserToken(req), + }, + }) + if ((typeof response.data.result.batch.participants !== 'undefined' && response.data.result.batch.participants.length > 0)) { + const searchresponse = await axios({ + ...axiosRequestConfig, + data: { request: { filters: { userId: response.data.result.batch.participants } } }, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), + }, + method: 'POST', + url: API_END_POINTS.kongSearchUser, + }) + if (searchresponse.data.result.response.count > 0) { + for (const profileObj of searchresponse.data.result.response.content) { + const user: ICohortsUser = getUsers(profileObj) + user.department = profileObj.channel + userlist.push(user) + } + } + } + res.status(response.status).send(userlist) + } catch (err) { + logError(err) + + res.status((err && err.response && err.response.status) || 500).send( + (err && err.response && err.response.data) || { + error: unknownError, + } + ) + } +}) +function getUsers(userprofile: IUserProfile): ICohortsUser { + let designationValue = '' + let primaryEmail = '' + let mobileNumber = 0 + if (userprofile.profileDetails !== undefined) { + if (userprofile.profileDetails.professionalDetails !== undefined && userprofile.profileDetails.professionalDetails.length > 0) { + if (userprofile.profileDetails.professionalDetails[0].designation !== undefined) { + designationValue = userprofile.profileDetails.professionalDetails[0].designation + } else { + designationValue = userprofile.profileDetails.professionalDetails[0].designationOther === undefined ? '' : + userprofile.profileDetails.professionalDetails[0].designationOther + } + } + if (userprofile.profileDetails.personalDetails !== undefined) { + primaryEmail = userprofile.profileDetails.personalDetails.primaryEmail + mobileNumber = userprofile.profileDetails.personalDetails.mobile + } + } return { city: '', - department: userprofile.professionalDetails[0].name, + department: userprofile.channel === undefined ? '' : userprofile.channel, desc: '', - designation: userprofile.professionalDetails[0].designation, - email: userprofile.personalDetails.primaryEmail, - first_name: userprofile.personalDetails.firstname, - last_name: userprofile.personalDetails.middlename, - phone_No: userprofile.personalDetails.mobile, + designation: designationValue, + email: primaryEmail, + first_name: userprofile.firstName, + last_name: userprofile.lastName, + phone_No: mobileNumber, userLocation: '', user_id: userprofile.id, } @@ -271,10 +338,19 @@ export interface ICohortsUser { } export interface IUserProfile { + channel: string + firstName: string + id: string + lastName: string + profileDetails: IUserProfileDetails +} + +export interface IUserProfileDetails { personalDetails: IPersonalDetails professionalDetails: IProfessionalDetailsEntity[] - id: string + employmentDetails: IEmploymentDetails } + export interface IPersonalDetails { firstname: string middlename: string @@ -293,6 +369,9 @@ export interface IPersonalDetails { personalEmail: string } +export interface IEmploymentDetails { + departmentName: string +} export interface IProfessionalDetailsEntity { description: string industry: string diff --git a/src/protectedApi_v8/competency.ts b/src/protectedApi_v8/competency.ts index 56fd4ba4..e44d797e 100644 --- a/src/protectedApi_v8/competency.ts +++ b/src/protectedApi_v8/competency.ts @@ -4,6 +4,7 @@ import { Router } from 'express' import { axiosRequestConfig } from '../configs/request.config' import { CONSTANTS } from '../utils/env' import { ERROR } from '../utils/message' +import { extractAuthorizationFromRequest } from '../utils/requestExtract' const API_END_POINTS = { addCompetency: `${CONSTANTS.FRAC_API_BASE}/api/frac/addDataNode`, @@ -17,7 +18,7 @@ const unknownError = 'Failed due to unknown reason' competencyApi.get('/getCompetency', async (req, res) => { try { const rootOrg = req.header('rootOrg') - const authToken = req.header('Authorization') + const authToken = extractAuthorizationFromRequest(req) if (!rootOrg) { res.status(400).send(ERROR.ERROR_NO_ORG_DATA) return @@ -40,7 +41,7 @@ competencyApi.get('/getCompetency', async (req, res) => { competencyApi.post('/addCompetency', async (req, res) => { try { - const authToken = req.header('Authorization') + const authToken = extractAuthorizationFromRequest(req) const response = await axios.post(API_END_POINTS.addCompetency, req.body, { ...axiosRequestConfig, headers: { @@ -59,7 +60,7 @@ competencyApi.post('/addCompetency', async (req, res) => { competencyApi.post('/searchCompetency', async (req, res) => { try { - const authToken = req.header('Authorization') + const authToken = extractAuthorizationFromRequest(req) const response = await axios.post(API_END_POINTS.searchCompetency, req.body, { ...axiosRequestConfig, headers: { diff --git a/src/protectedApi_v8/connections.ts b/src/protectedApi_v8/connections.ts index 4b2981b4..257c07fa 100644 --- a/src/protectedApi_v8/connections.ts +++ b/src/protectedApi_v8/connections.ts @@ -5,18 +5,19 @@ import { CONSTANTS } from '../utils/env' import { logError, logInfo } from '../utils/logger' import { ERROR } from '../utils/message' import { extractUserIdFromRequest } from '../utils/requestExtract' +import { extractUserToken } from '../utils/requestExtract' const unknown = 'Connections Apis:- Failed due to unknown reason' const apiEndpoints = { detail: `${CONSTANTS.USER_PROFILE_API_BASE}/user/multi-fetch/wid`, - getConnectionEstablishedData: `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/connections/profile/fetch/established`, - getConnectionRequestsData: `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/connections/profile/fetch/requested`, - getConnectionRequestsReceivedData: `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/connections/profile/fetch/requests/received`, - getConnectionSuggestsData: `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/connections/profile/find/suggests`, + getConnectionEstablishedData: `${CONSTANTS.KONG_API_BASE}/connections/profile/fetch/established`, + getConnectionRequestsData: `${CONSTANTS.KONG_API_BASE}/connections/profile/fetch/requested`, + getConnectionRequestsReceivedData: `${CONSTANTS.KONG_API_BASE}/connections/profile/fetch/requests/received`, + getConnectionSuggestsData: `${CONSTANTS.KONG_API_BASE}/connections/profile/find/suggests`, getUserRegistryById: (userId: string) => `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/v1/user/search/profile?userId=${userId}`, - postConnectionAddData: `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/connections/add`, - postConnectionRecommendationData: `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/connections/profile/find/recommended`, - postConnectionUpdateData: `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/connections/update`, + postConnectionAddData: `${CONSTANTS.KONG_API_BASE}/connections/add`, + postConnectionRecommendationData: `${CONSTANTS.KONG_API_BASE}/connections/profile/find/recommended`, + postConnectionUpdateData: `${CONSTANTS.KONG_API_BASE}/connections/update`, } export const connectionsApi = Router() @@ -37,8 +38,11 @@ connectionsApi.get('/connections/requested', async (req, res) => { const response = await axios.get(apiEndpoints.getConnectionRequestsData, { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, rootOrg, userId, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, }) res.send((response.data)) @@ -69,8 +73,11 @@ connectionsApi.get('/connections/requests/received', async (req, res) => { const response = await axios.get(apiEndpoints.getConnectionRequestsReceivedData, { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, rootOrg, userId, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, }) res.send((response.data)) @@ -101,8 +108,11 @@ connectionsApi.get('/connections/established', async (req, res) => { const response = await axios.get(apiEndpoints.getConnectionEstablishedData, { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, rootOrg, userId, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, }) res.send((response.data)) @@ -133,8 +143,11 @@ connectionsApi.get('/connections/established/:id', async (req, res) => { const response = await axios.get(apiEndpoints.getConnectionEstablishedData, { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, rootOrg, userId, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, }) res.send((response.data)) @@ -165,8 +178,11 @@ connectionsApi.get('/connections/suggests', async (req, res) => { const response = await axios.get(apiEndpoints.getConnectionSuggestsData, { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, rootOrg, userId, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, }) res.send((response.data)) @@ -216,7 +232,10 @@ connectionsApi.post('/add/connection', async (req, res) => { { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, } ) @@ -270,7 +289,10 @@ connectionsApi.post('/update/connection', async (req, res) => { { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, } ) @@ -307,8 +329,11 @@ connectionsApi.post('/connections/recommended', async (req, res) => { { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, rootOrg, userId, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, } ) @@ -371,8 +396,11 @@ connectionsApi.post('/connections/recommended/userDepartment', async (req, res) { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, rootOrg, userId, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, } ) diff --git a/src/protectedApi_v8/connections_v2.ts b/src/protectedApi_v8/connections_v2.ts new file mode 100644 index 00000000..8b913588 --- /dev/null +++ b/src/protectedApi_v8/connections_v2.ts @@ -0,0 +1,459 @@ +import axios from 'axios' +import { Router } from 'express' +import { axiosRequestConfig } from '../configs/request.config' +import { CONSTANTS } from '../utils/env' +import { logError, logInfo } from '../utils/logger' +import { ERROR } from '../utils/message' +import { extractUserId, extractUserIdFromRequest } from '../utils/requestExtract' +import { extractUserToken } from '../utils/requestExtract' + +const _ = require('lodash') + +const unknown = 'Connections Apis:- Failed due to unknown reason' +const apiEndpoints = { + detail: `${CONSTANTS.USER_PROFILE_API_BASE}/user/multi-fetch/wid`, + getConnectionEstablishedData: `${CONSTANTS.KONG_API_BASE}/connections/profile/fetch/established`, + getConnectionRequestsData: `${CONSTANTS.KONG_API_BASE}/connections/profile/fetch/requested`, + getConnectionRequestsReceivedData: `${CONSTANTS.KONG_API_BASE}/connections/profile/fetch/requests/received`, + getConnectionSuggestsData: `${CONSTANTS.KONG_API_BASE}/connections/profile/find/suggests`, + getUserOrgName: `${CONSTANTS.KONG_API_BASE}/user/v1/search`, + getUserRegistryById: (userId: string) => `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/v1/user/search/profile?userId=${userId}`, + postConnectionAddData: `${CONSTANTS.KONG_API_BASE}/connections/add`, + postConnectionRecommendationData: `${CONSTANTS.KONG_API_BASE}/connections/profile/find/recommended`, + postConnectionUpdateData: `${CONSTANTS.KONG_API_BASE}/connections/update`, +} + +export const connectionsV2Api = Router() + +connectionsV2Api.get('/v2/connections/requested', async (req, res) => { + try { + const rootOrg = req.headers.rootorg + const userId = extractUserIdFromRequest(req) + + if (!rootOrg) { + res.status(400).send(ERROR.ERROR_NO_ORG_DATA) + return + } + if (!userId) { + res.status(400).send(ERROR.GENERAL_ERR_MSG) + return + } + const response = await axios.get(apiEndpoints.getConnectionRequestsData, { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + userId, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), + }, + }) + res.send((response.data)) + + } catch (err) { + logError('CONNECTIONS REQUESTS ERROR> ', err) + res.status((err && err.response && err.response.status) || 500).send( + (err && err.response && err.response.data) || { + error: unknown, + } + ) + } +}) + +connectionsV2Api.get('/v2/connections/requests/received', async (req, res) => { + try { + const rootOrg = req.headers.rootorg + const userId = extractUserIdFromRequest(req) + + if (!rootOrg) { + res.status(400).send(ERROR.ERROR_NO_ORG_DATA) + return + } + if (!userId) { + res.status(400).send(ERROR.GENERAL_ERR_MSG) + return + } + const response = await axios.get(apiEndpoints.getConnectionRequestsReceivedData, { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + userId, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), + }, + }) + res.send((response.data)) + + } catch (err) { + logError('CONNECTIONS REQUESTS ERROR> ', err) + res.status((err && err.response && err.response.status) || 500).send( + (err && err.response && err.response.data) || { + error: unknown, + } + ) + } +}) + +connectionsV2Api.get('/v2/connections/established', async (req, res) => { + try { + const rootOrg = req.headers.rootorg + const userId = extractUserIdFromRequest(req) + + if (!rootOrg) { + res.status(400).send(ERROR.ERROR_NO_ORG_DATA) + return + } + if (!userId) { + res.status(400).send(ERROR.GENERAL_ERR_MSG) + return + } + const response = await axios.get(apiEndpoints.getConnectionEstablishedData, { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + userId, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), + }, + }) + res.send((response.data)) + + } catch (err) { + logError('CONNECTIONS ERROR', err) + res.status((err && err.response && err.response.status) || 500).send( + (err && err.response && err.response.data) || { + error: unknown, + } + ) + } +}) + +connectionsV2Api.get('/v2/connections/established/:id', async (req, res) => { + try { + const rootOrg = req.headers.rootorg + const userId = req.params.id + + if (!rootOrg) { + res.status(400).send(ERROR.ERROR_NO_ORG_DATA) + return + } + if (!userId) { + res.status(400).send(ERROR.GENERAL_ERR_MSG) + return + } + const response = await axios.get(apiEndpoints.getConnectionEstablishedData, { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + userId, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), + }, + }) + res.send((response.data)) + + } catch (err) { + logError('CONNECTIONS ERROR', err) + res.status((err && err.response && err.response.status) || 500).send( + (err && err.response && err.response.data) || { + error: unknown, + } + ) + } +}) + +connectionsV2Api.get('/v2/connections/suggests', async (req, res) => { + try { + const rootOrg = req.headers.rootorg + const userId = extractUserId(req) + + if (!rootOrg) { + res.status(400).send(ERROR.ERROR_NO_ORG_DATA) + return + } + if (!userId) { + res.status(400).send(ERROR.GENERAL_ERR_MSG) + return + } + const response = await axios.get(apiEndpoints.getConnectionSuggestsData, { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + userId, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), + }, + }) + res.send((response.data)) + + } catch (err) { + logError('SUGGESTS ERROR >', err) + res.status((err && err.response && err.response.status) || 500).send( + (err && err.response && err.response.data) || { + error: unknown, + } + ) + } +}) + +connectionsV2Api.post('/v2/add/connection', async (req, res) => { + try { + const rootOrg = req.header('rootorg') + const userIdFrom = extractUserIdFromRequest(req) + const userNameFrom = req.body.userNameFrom + const userDepartmentFrom = req.body.userDepartmentFrom + const userIdTo = req.body.userIdTo + const userNameTo = req.body.userNameTo + const userDepartmentTo = req.body.userDepartmentTo + + if (!rootOrg) { + res.status(400).send(ERROR.ERROR_NO_ORG_DATA) + return + } + if (!userIdFrom || !userIdTo || !userNameFrom || !userDepartmentFrom || !userNameTo || !userDepartmentTo) { + res.status(400).send(ERROR.GENERAL_ERR_MSG) + return + } + + const body = { + userDepartmentFrom, + userIdFrom, + userNameFrom, + + userDepartmentTo, + userIdTo, + userNameTo, + + } + const response = await axios.post( + apiEndpoints.postConnectionAddData, + body, + { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), + }, + } + ) + res.send(response.data) + + } catch (err) { + logError('ADD CONNECTION ERROR > ', err) + res.status((err && err.response && err.response.status) || 500).send( + (err && err.response && err.response.data) || { + error: unknown, + } + ) + } +}) + +connectionsV2Api.post('/v2/update/connection', async (req, res) => { + try { + const rootOrg = req.header('rootorg') + const userNameFrom = req.body.userNameFrom + const userDepartmentFrom = req.body.userDepartmentFrom + const userIdFrom = extractUserIdFromRequest(req) + + const userNameTo = req.body.userNameTo + const userDepartmentTo = req.body.userDepartmentTo + const userIdTo = req.body.userIdTo + + const status = req.body.status + + if (!rootOrg) { + res.status(400).send(ERROR.ERROR_NO_ORG_DATA) + return + } + if (!userIdFrom || !userIdTo || !userNameFrom || !userDepartmentFrom || !userNameTo || !userDepartmentTo || !status) { + res.status(400).send(ERROR.GENERAL_ERR_MSG) + return + } + const body = { + status, + + userDepartmentFrom, + userIdFrom, + userNameFrom, + + userDepartmentTo, + userIdTo, + userNameTo, + } + const response = await axios.post( + apiEndpoints.postConnectionUpdateData, + body, + { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), + }, + } + ) + res.send(response.data) + + } catch (err) { + logError('UPDATE CONNECTION ERROR > ', err) + res.status((err && err.response && err.response.status) || 500).send( + (err && err.response && err.response.data) || { + error: unknown, + } + ) + } +}) + +connectionsV2Api.post('/v2/connections/recommended', async (req, res) => { + try { + const body = req.body + const rootOrg = req.header('rootorg') + const userId = extractUserId(req) + + if (!rootOrg) { + res.status(400).send(ERROR.ERROR_NO_ORG_DATA) + return + } + if (!userId) { + res.status(400).send(ERROR.GENERAL_ERR_MSG) + return + } + + const response = await axios.post( + apiEndpoints.postConnectionRecommendationData, + body, + { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + userId, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), + }, + } + ) + res.send(response.data) + + } catch (err) { + logError('RECOMMENDED ERROR > ', err) + res.status((err && err.response && err.response.status) || 500).send( + (err && err.response && err.response.data) || { + error: unknown, + } + ) + } +}) + +connectionsV2Api.post('/v2/connections/recommended/userDepartment', async (req, res) => { + try { + let usrDept = '' + // tslint:disable-next-line: no-any + const userDepartment: any = [] + const rootOrg = req.header('rootorg') + const userId = extractUserId(req) + if (!rootOrg) { + res.status(400).send(ERROR.ERROR_NO_ORG_DATA) + return + } + if (!userId) { + res.status(400).send(ERROR.GENERAL_ERR_MSG) + return + } + + /** + * @author: Suvajit + * Step 1: Gets the User Department using search api + * Step 2: Loops through and gets all the dept + * Step 3: Send the data to recommandation api + */ + + const body = { + request : { + filters : { + userId, + }, + query: '', + }, + } + const url = `${apiEndpoints.getUserOrgName}` + const responseDetails = await axios.post( + url, + body, + { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + 'Content-Type': 'application/json', + 'X-Authenticated-User-Token': extractUserToken(req), + }, + } + ) + logInfo('responseDetails from /search/ : ', JSON.stringify(responseDetails.data)) + + // tslint:disable-next-line: no-any + const orgData: any = [] + const contentData = responseDetails.data.result.response.content + // tslint:disable-next-line: no-any + contentData.forEach((content: any) => { + const orgs = content.organisations + // tslint:disable-next-line: no-any + orgs.forEach((org: any) => { + orgData.push(org) + }) + }) + if (_.isEmpty(orgData)) { + res.status(400).send(ERROR.ERROR_NO_DEPT_DATA) + return + } + + // tslint:disable-next-line: no-any + orgData.forEach((element: any) => { + userDepartment.push(element.orgName) + }) + + usrDept = userDepartment || 'igot' + + const reqtoApi = { + offset: 0, + search: [ + { + field: 'employmentDetails.departmentName', + values: usrDept, + }, + ], + size: 5, + } + + const response = await axios.post( + apiEndpoints.postConnectionRecommendationData, + reqtoApi, + { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + userId, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), + }, + } + ) + res.send(response.data) + + } catch (err) { + logError('RECOMMENDED ERROR > ', err) + res.status((err && err.response && err.response.status) || 500).send( + (err && err.response && err.response.data) || { + error: unknown, + } + ) + } +}) diff --git a/src/protectedApi_v8/contentValidation.ts b/src/protectedApi_v8/contentValidation.ts index a39d0ec1..fc8916b2 100644 --- a/src/protectedApi_v8/contentValidation.ts +++ b/src/protectedApi_v8/contentValidation.ts @@ -5,16 +5,17 @@ import { axiosRequestConfig } from '../configs/request.config' import { CONSTANTS } from '../utils/env' import { logError } from '../utils/logger' import { ERROR } from '../utils/message' +import { extractUserToken } from '../utils/requestExtract' const API_END_POINTS = { checkPdfProfanity: `${CONSTANTS.CONTENT_VALIDATION_API_BASE}/contentValidation/v1/checkPdfProfanity`, checkProfanity: (contentId: string, userId: string) => `${CONSTANTS.CONTENT_VALIDATION_API_BASE}/contentValidation/v1/checkProfanity/${contentId}/${userId}`, checkTextProfanity: `${CONSTANTS.PROFANITY_SERVICE_API_BASE}/checkProfanity`, - getPdfProfanity: `${CONSTANTS.CONTENT_VALIDATION_API_BASE}/contentValidation/v1/getPdfProfanity`, + getPdfProfanity: `${CONSTANTS.KONG_API_BASE}/contentValidation/v1/getPdfProfanity`, getPdfProfanityForContent: (contentId: string) => - `${CONSTANTS.CONTENT_VALIDATION_API_BASE}/contentValidation/v1/getPdfProfanityForContent/${contentId}`, - startPdfProfanity: `${CONSTANTS.CONTENT_VALIDATION_API_BASE}/contentValidation/v1/startPdfProfanity`, + `${CONSTANTS.KONG_API_BASE}/contentValidation/v1/getPdfProfanityForContent/${contentId}`, + startPdfProfanity: `${CONSTANTS.KONG_API_BASE}/contentValidation/v1/startPdfProfanity`, } export const contentValidationApi = Router() @@ -82,7 +83,14 @@ contentValidationApi.post('/validatePdfContent', async (req, res) => { contentValidationApi.post('/startPdfProfanity', async (req, res) => { try { - const response = await axios.post(API_END_POINTS.startPdfProfanity, req.body, axiosRequestConfig) + const response = await axios.post(API_END_POINTS.startPdfProfanity, req.body, { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), + }, + }) res.status(response.status).send(response.data) } catch (err) { logError(failedToProcess + err) @@ -96,7 +104,14 @@ contentValidationApi.post('/startPdfProfanity', async (req, res) => { contentValidationApi.post('/getPdfProfanity', async (req, res) => { try { - const response = await axios.post(API_END_POINTS.getPdfProfanity, req.body, axiosRequestConfig) + const response = await axios.post(API_END_POINTS.getPdfProfanity, req.body, { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), + }, + }) res.status(response.status).send(response.data) } catch (err) { logError(failedToProcess + err) @@ -116,9 +131,12 @@ contentValidationApi.get('/getPdfProfanityForContent/:contentId', async (req, re const response = await axios.get(API_END_POINTS.getPdfProfanityForContent(contentId), { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, 'Content-Type': 'application/json', rootOrg: rootOrgValue, wid, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, }) res.status(response.status).send(response.data) diff --git a/src/protectedApi_v8/contentprivate.ts b/src/protectedApi_v8/contentprivate.ts new file mode 100644 index 00000000..fdfdb916 --- /dev/null +++ b/src/protectedApi_v8/contentprivate.ts @@ -0,0 +1,255 @@ +import axios from 'axios' +import { Router } from 'express' + +import { axiosRequestConfig } from '../configs/request.config' +import { CONSTANTS } from '../utils/env' +import { logError, logInfo } from '../utils/logger' +import { ERROR } from '../utils/message' +import { extractUserId, extractUserToken } from '../utils/requestExtract' + +export const contentPrivateApi = Router() + +const API_END_POINTS = { + getHierarchyDetails: (id: string) => `${CONSTANTS.KNOWLEDGE_MW_API_BASE}/action/content/v3/hierarchy/${id}?mode=edit`, + readUserEndPoint: (userId: string) => `${CONSTANTS.KONG_API_BASE}/user/v2/read/${userId}`, + updateContentEndPoint: (id: string) => `${CONSTANTS.KONG_API_BASE}/private/content/v3/update/${id}`, +} +// tslint:disable-next-line: no-commented-code +const editableFields = ['versionKey', 'isExternal', 'difficultyLevel', 'visibility'] +const editableFieldsReviewer = ['versionKey', 'isExternal', 'reviewer', 'reviewerIDs'] +const editableFieldsPublisher = ['versionKey', 'isExternal', 'publisherIDs: ', 'publisherDetails'] +const userIdFailedMessage = 'NO_USER_ID' +const FIELD_VALIDATION_ERROR = 'TRYING_TO_UPDATE_NON_EDITABLE_FIELDS' +const CHANNEL_VALIDATION_ERROR = 'SOURCE_MISMATCH_ERROR' + +contentPrivateApi.patch('/update/:id', async (req, res) => { + try { + const id = req.params.id + // tslint:disable-next-line: no-commented-code + const content = req.body.request.content + const fields = Object.keys(content) + const userId = extractUserId(req) + const userToken = extractUserToken(req) as string + let validationErrorFlag = false + if (!userId) { + res.status(400).send(userIdFailedMessage) + return + } + // tslint: disable - next - line: no - commented - code + logInfo('line no: 36 ===> ', id, JSON.stringify(fields), userId, userToken) + // tslint: disable - next - line: no - commented - code + if (fields instanceof Array) { + for (const entry of fields) { + // tslint: disable - next - line: no - commented - code + logInfo('line no: 43 ===> ', entry, JSON.stringify(editableFields)) + if (editableFields.indexOf(entry) === -1) { + validationErrorFlag = true + } + } + if (validationErrorFlag) { + res.status(400).send({ + msg: FIELD_VALIDATION_ERROR, + }) + } + } + const userChannel = await getUserChannel(userToken, userId) + const hierarchySource = await getHierarchyDetails(userToken, id) + // tslint:disable-next-line: no-commented-code + logInfo('line no: 58 ===> ', JSON.stringify(userChannel), JSON.stringify(hierarchySource)) + if (userChannel !== hierarchySource) { + res.status(400).send({ + msg: CHANNEL_VALIDATION_ERROR, + }) + } else { + const response = await axios.patch( + API_END_POINTS.updateContentEndPoint(id), + req.body, + { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': userToken, + }, + } + ) + // tslint:disable-next-line: no-commented-code + // logInfo('line no: 70 ===> ', JSON.stringify(response.status), response.data) + if (response.status && response.data) { + res.status(response.status).send(response.data) + } + } + } catch (err) { + logError(Error + err) + res.status((err && err.response && err.response.status) || 500).send( + (err && err.response && err.response.data) || { + error: ERROR.GENERAL_ERR_MSG, + } + ) + } +}) + +contentPrivateApi.patch('/migratereviewer/:id', async (req, res) => { + try { + const id = req.params.id + const content = req.body.request.content + const fields = Object.keys(content) + const userId = extractUserId(req) + const userToken = extractUserToken(req) as string + let validationErrorFlag = false + if (!userId) { + res.status(400).send(userIdFailedMessage) + return + } + if (fields instanceof Array) { + for (const entry of fields) { + if (editableFieldsReviewer.indexOf(entry) === -1 && fields.length !== editableFieldsReviewer.length) { + validationErrorFlag = true + } + } + if (validationErrorFlag) { + res.status(400).send({ + msg: FIELD_VALIDATION_ERROR, + }) + } + } + const userChannel = await getUserChannel(userToken, userId) + const hierarchySource = await getHierarchyDetails(userToken, id) + logInfo('line no: 50 ===> ', userChannel, hierarchySource) + if (userChannel !== hierarchySource) { + res.status(400).send({ + msg: CHANNEL_VALIDATION_ERROR, + }) + } else { + const response = await axios.patch( + API_END_POINTS.updateContentEndPoint(id), + req.body, + { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': userToken, + }, + } + ) + // tslint:disable-next-line: no-commented-code + // logInfo('line no: 70 ===> ', JSON.stringify(response.status), response.data) + if (response.status && response.data) { + res.status(response.status).send(response.data) + } + } + } catch (err) { + logError(Error + err) + res.status((err && err.response && err.response.status) || 500).send( + (err && err.response && err.response.data) || { + error: ERROR.GENERAL_ERR_MSG, + } + ) + } +}) + +contentPrivateApi.patch('/migratepublisher/:id', async (req, res) => { + try { + const id = req.params.id + const content = req.body.request.content + const fields = Object.keys(content) + const userId = extractUserId(req) + const userToken = extractUserToken(req) as string + let validationErrorFlag = false + + if (!userId) { + res.status(400).send(userIdFailedMessage) + return + } + if (fields instanceof Array) { + for (const entry of fields) { + if (editableFieldsPublisher.indexOf(entry) === -1 && fields.length !== editableFieldsPublisher.length) { + validationErrorFlag = true + } + } + if (validationErrorFlag) { + res.status(400).send({ + msg: FIELD_VALIDATION_ERROR, + }) + } + } + const userChannel = await getUserChannel(userToken, userId) + const hierarchySource = await getHierarchyDetails(userToken, id) + logInfo('line no: 50 ===> ', userChannel, hierarchySource) + if (userChannel !== hierarchySource) { + res.status(400).send({ + msg: CHANNEL_VALIDATION_ERROR, + }) + } else { + const response = await axios.patch( + API_END_POINTS.updateContentEndPoint(id), + req.body, + { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': userToken, + }, + } + ) + // tslint:disable-next-line: no-commented-code + // logInfo('line no: 70 ===> ', JSON.stringify(response.status), response.data) + if (response.status && response.data) { + res.status(response.status).send(response.data) + } + } + } catch (err) { + logError(Error + err) + res.status((err && err.response && err.response.status) || 500).send( + (err && err.response && err.response.data) || { + error: ERROR.GENERAL_ERR_MSG, + } + ) + } +}) + +export async function getHierarchyDetails(token: string, id: string) { + try { + const response = await axios.get(API_END_POINTS.getHierarchyDetails(id), { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': token, + }, + }) + logInfo('line 201 ====>', response.data) + const hierarchyResult = response.data.result.content + logInfo('line 202 ====>', JSON.stringify(hierarchyResult)) + if (typeof hierarchyResult !== 'undefined' && hierarchyResult != null) { + return hierarchyResult.channel + } + } catch (error) { + logError('ERROR WHILE FETCHING THE Hierarchy DETAILS --> ', error) + return 'contentSourceDetails' + } +} + +export async function getUserChannel(token: string, userId: string) { + try { + const response = await axios.get(API_END_POINTS.readUserEndPoint(userId), { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': token, + }, + }) + logInfo('line 222 ====>', response.data) + const userProfileResult = response.data.result.response + logInfo('line 222 ====>', JSON.stringify(userProfileResult)) + if (typeof userProfileResult !== 'undefined' && userProfileResult != null) { + return userProfileResult.rootOrgId + } + } catch (error) { + logError('ERROR WHILE FETCHING THE USER DETAILS --> ', error) + return 'userChannelDetails' + } +} diff --git a/src/protectedApi_v8/discussionHub/categories.ts b/src/protectedApi_v8/discussionHub/categories.ts index 31e12376..bdeb36d9 100644 --- a/src/protectedApi_v8/discussionHub/categories.ts +++ b/src/protectedApi_v8/discussionHub/categories.ts @@ -4,13 +4,13 @@ import { getRootOrg } from '../../authoring/utils/header' import { axiosRequestConfig } from '../../configs/request.config' import { CONSTANTS } from '../../utils/env' import { logError, logInfo } from '../../utils/logger' -import { extractUserIdFromRequest } from '../../utils/requestExtract' +import { extractUserIdFromRequest, extractUserToken } from '../../utils/requestExtract' const API_ENDPOINTS = { - getAllCategories: `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/categories`, + getAllCategories: `${CONSTANTS.KONG_API_BASE}/nodebb/api/categories`, // tslint:disable-next-line: no-any getCategoryDetails: (cid: any, slug?: any, tid?: any) => { - let url = `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/category/${cid}` + let url = `${CONSTANTS.KONG_API_BASE}/nodebb/api/category/${cid}` if (slug) { url = `${url}/${slug}` } @@ -31,7 +31,12 @@ categoriesApi.get('/', async (req, res) => { const url = API_ENDPOINTS.getAllCategories const response = await axios.get( url, - { ...axiosRequestConfig, headers: { rootOrg } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) res.send(response.data) } catch (err) { @@ -54,7 +59,12 @@ categoriesApi.get('/:cid/:slug?/:tid?', async (req, res) => { const url = API_ENDPOINTS.getCategoryDetails(cid, slug, tid) const response = await axios.get( `${url}?page=${pageNo}&sort=${sort}`, - { ...axiosRequestConfig, headers: { rootOrg } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) res.send(response.data) } catch (err) { diff --git a/src/protectedApi_v8/discussionHub/notifications.ts b/src/protectedApi_v8/discussionHub/notifications.ts index 9be53dd1..ebcbdb3c 100644 --- a/src/protectedApi_v8/discussionHub/notifications.ts +++ b/src/protectedApi_v8/discussionHub/notifications.ts @@ -2,13 +2,13 @@ import axios from 'axios' import { Router } from 'express' import { getRootOrg } from '../../authoring/utils/header' import { axiosRequestConfig } from '../../configs/request.config' -import { getUserUID, getWriteApiToken } from '../../utils/discussionHub-helper' +import { getUserUIDBySession} from '../../utils/discussionHub-helper' import { CONSTANTS } from '../../utils/env' import { logError, logInfo } from '../../utils/logger' -import { extractUserIdFromRequest } from '../../utils/requestExtract' +import { extractUserIdFromRequest , extractUserToken} from '../../utils/requestExtract' const API_ENDPOINTS = { - getNotifications: `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/notifications`, + getNotifications: `${CONSTANTS.KONG_API_BASE}/nodebb/auth/api/notifications`, } export const notificationsApi = Router() @@ -18,11 +18,15 @@ notificationsApi.get('/', async (req, res) => { const rootOrg = getRootOrg(req) const userId = extractUserIdFromRequest(req) logInfo(`UserId: ${userId}, rootOrg: ${rootOrg}`) - const userUid = await getUserUID(userId) + const userUid = await getUserUIDBySession(req) const url = API_ENDPOINTS.getNotifications + `?_uid=${userUid}` const response = await axios.get( url, - { ...axiosRequestConfig, headers: { authorization: getWriteApiToken() } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) res.send(response.data) } catch (err) { diff --git a/src/protectedApi_v8/discussionHub/posts.ts b/src/protectedApi_v8/discussionHub/posts.ts index dbcf6d0b..5f6abb50 100644 --- a/src/protectedApi_v8/discussionHub/posts.ts +++ b/src/protectedApi_v8/discussionHub/posts.ts @@ -4,10 +4,10 @@ import { getRootOrg } from '../../authoring/utils/header' import { axiosRequestConfig } from '../../configs/request.config' import { CONSTANTS } from '../../utils/env' import { logError, logInfo } from '../../utils/logger' -import { extractUserIdFromRequest } from '../../utils/requestExtract' +import { extractUserIdFromRequest, extractUserToken} from '../../utils/requestExtract' const API_ENDPOINTS = { - getPosts: (term: string) => `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/recent/posts/${term}`, + getPosts: (term: string) => `${CONSTANTS.DISCUSSION_HUB_API_BASE}/nodebb/api/recent/posts/${term}`, } export const postsApi = Router() @@ -21,7 +21,12 @@ postsApi.get('/:term', async (req, res) => { const url = API_ENDPOINTS.getPosts(term) const response = await axios.get( url, - { ...axiosRequestConfig, headers: { rootOrg } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) res.send(response.data) } catch (err) { diff --git a/src/protectedApi_v8/discussionHub/tags.ts b/src/protectedApi_v8/discussionHub/tags.ts index 7d547043..f119e9f4 100644 --- a/src/protectedApi_v8/discussionHub/tags.ts +++ b/src/protectedApi_v8/discussionHub/tags.ts @@ -4,11 +4,11 @@ import { getRootOrg } from '../../authoring/utils/header' import { axiosRequestConfig } from '../../configs/request.config' import { CONSTANTS } from '../../utils/env' import { logError, logInfo } from '../../utils/logger' -import { extractUserIdFromRequest } from '../../utils/requestExtract' +import { extractUserIdFromRequest, extractUserToken} from '../../utils/requestExtract' const API_ENDPOINTS = { - getTagTopics: (tagName: string) => `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/tags/${tagName}`, - getTags: `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/tags`, + getTagTopics: (tagName: string) => `${CONSTANTS.KONG_API_BASE}/nodebb/api/tags/${tagName}`, + getTags: `${CONSTANTS.KONG_API_BASE}/nodebb/api/tags`, } export const tagsApi = Router() @@ -21,7 +21,12 @@ tagsApi.get('/', async (req, res) => { const url = API_ENDPOINTS.getTags const response = await axios.get( url, - { ...axiosRequestConfig, headers: { rootOrg } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) res.send(response.data) } catch (err) { @@ -39,7 +44,12 @@ tagsApi.get('/:tagName', async (req, res) => { const url = API_ENDPOINTS.getTagTopics(tagName) const response = await axios.get( url, - { ...axiosRequestConfig, headers: { rootOrg } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) res.send(response.data) } catch (err) { diff --git a/src/protectedApi_v8/discussionHub/topics.ts b/src/protectedApi_v8/discussionHub/topics.ts index 1be67f3e..a85a404b 100644 --- a/src/protectedApi_v8/discussionHub/topics.ts +++ b/src/protectedApi_v8/discussionHub/topics.ts @@ -2,19 +2,19 @@ import axios from 'axios' import { Router } from 'express' import { getRootOrg } from '../../authoring/utils/header' import { axiosRequestConfig } from '../../configs/request.config' -import { getUserUID, getWriteApiToken } from '../../utils/discussionHub-helper' +import { getUserUIDBySession} from '../../utils/discussionHub-helper' import { CONSTANTS } from '../../utils/env' import { logError, logInfo } from '../../utils/logger' -import { extractUserIdFromRequest } from '../../utils/requestExtract' +import { extractUserIdFromRequest, extractUserToken } from '../../utils/requestExtract' const API_ENDPOINTS = { - getPopularTopics: `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/popular`, - getRecentTopics: `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/recent`, - getTopTopics: `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/top`, - getUnreadTopics: `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/unread`, - getUnreadTopicsTotal: `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/unread/total`, + getPopularTopics: `${CONSTANTS.KONG_API_BASE}/nodebb/api/popular`, + getRecentTopics: `${CONSTANTS.KONG_API_BASE}/nodebb/api/recent`, + getTopTopics: `${CONSTANTS.KONG_API_BASE}/nodebb/api/top`, + getUnreadTopics: `${CONSTANTS.KONG_API_BASE}/nodebb/auth/api/unread`, + getUnreadTopicsTotal: `${CONSTANTS.KONG_API_BASE}/nodebb/auth/api/unread/total`, // tslint:disable-next-line: object-literal-sort-keys - getTopicDetails: (tid: number) => `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/topic/${tid}`, + getTopicDetails: (tid: number) => `${CONSTANTS.KONG_API_BASE}/nodebb/auth/api/topic/${tid}`, } export const topicsApi = Router() @@ -31,7 +31,12 @@ topicsApi.get('/recent', async (req, res) => { logInfo(`UserId: ${userId}, rootOrg: ${rootOrg}, Url: ${url}`) const response = await axios.get( url, - { ...axiosRequestConfig, headers: { rootOrg } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) res.send(response.data) } catch (err) { @@ -49,7 +54,12 @@ topicsApi.get('/top', async (req, res) => { const url = API_ENDPOINTS.getTopTopics const response = await axios.get( url, - { ...axiosRequestConfig, headers: { rootOrg } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) res.send(response.data) } catch (err) { @@ -68,7 +78,12 @@ topicsApi.get('/popular', async (req, res) => { const url = API_ENDPOINTS.getPopularTopics const response = await axios.get( `${url}?page=${pageNo}`, - { ...axiosRequestConfig, headers: { rootOrg } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) res.send(response.data) } catch (err) { @@ -83,11 +98,17 @@ topicsApi.get('/unread', async (req, res) => { const rootOrg = getRootOrg(req) const userId = extractUserIdFromRequest(req) logInfo(`UserId: ${userId}, rootOrg: ${rootOrg}`) - const userUid = await getUserUID(userId) + const userUid = await getUserUIDBySession(req) const url = API_ENDPOINTS.getUnreadTopics + `?_uid=${userUid}` const response = await axios.get( url, - { ...axiosRequestConfig, headers: { authorization: getWriteApiToken() } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + }, + } ) res.send(response.data) } catch (err) { @@ -102,11 +123,16 @@ topicsApi.get('/unread/total', async (req, res) => { const rootOrg = getRootOrg(req) const userId = extractUserIdFromRequest(req) logInfo(`UserId: ${userId}, rootOrg: ${rootOrg}`) - const userUid = await getUserUID(userId) + const userUid = await getUserUIDBySession(req) const url = API_ENDPOINTS.getUnreadTopicsTotal + `?_uid=${userUid}` const response = await axios.get( url, - { ...axiosRequestConfig, headers: { authorization: getWriteApiToken() } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) res.send(response.data) } catch (err) { @@ -124,11 +150,16 @@ topicsApi.get('/:tid', async (req, res) => { const sort = req.query.sort || '' logInfo(`UserId: ${userId}, rootOrg: ${rootOrg}`) const tid = req.params.tid - const userUid = await getUserUID(userId) + const userUid = await getUserUIDBySession(req) const url = API_ENDPOINTS.getTopicDetails(tid) + `?page=${pageNo}&_uid=${userUid}&sort=${sort}` const response = await axios.get( url, - { ...axiosRequestConfig, headers: { authorization: getWriteApiToken() } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) res.send(response.data) } catch (err) { diff --git a/src/protectedApi_v8/discussionHub/users.ts b/src/protectedApi_v8/discussionHub/users.ts index 828fb6c2..b0cb758c 100644 --- a/src/protectedApi_v8/discussionHub/users.ts +++ b/src/protectedApi_v8/discussionHub/users.ts @@ -2,23 +2,23 @@ import axios from 'axios' import { Router } from 'express' import { getRootOrg } from '../../authoring/utils/header' import { axiosRequestConfig } from '../../configs/request.config' -import { getUserSlug, getUserUID, getWriteApiToken } from '../../utils/discussionHub-helper' +import { getUserSlug, getUserUIDBySession} from '../../utils/discussionHub-helper' import { CONSTANTS } from '../../utils/env' import { logError, logInfo } from '../../utils/logger' -import { extractUserIdFromRequest } from '../../utils/requestExtract' +import { extractUserIdFromRequest, extractUserToken} from '../../utils/requestExtract' const API_ENDPOINTS = { - getUserBookmarks: (slug: string) => `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/user/${slug}/bookmarks`, - getUserDownvotedPosts: (slug: string) => `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/user/${slug}/downvoted`, - getUserGroups: (slug: string) => `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/user/${slug}/groups`, - getUserInfo: (slug: string) => `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/user/${slug}/info`, - getUserPosts: (slug: string) => `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/user/${slug}/posts`, - getUserProfile: (slug: string) => `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/user/${slug}`, - getUserUpvotedPosts: (slug: string) => `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/user/${slug}/upvoted`, - getUsersWatchedTopics: (slug: string) => `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/user/${slug}/watched`, + getUserBookmarks: (slug: string) => `${CONSTANTS.KONG_API_BASE}/nodebb/auth/api/user/${slug}/bookmarks`, + getUserDownvotedPosts: (slug: string) => `${CONSTANTS.KONG_API_BASE}/nodebb/auth/api/user/${slug}/downvoted`, + getUserGroups: (slug: string) => `${CONSTANTS.KONG_API_BASE}/nodebb/auth/api/user/${slug}/groups`, + getUserInfo: (slug: string) => `${CONSTANTS.KONG_API_BASE}/nodebb/auth/api/user/${slug}/info`, + getUserPosts: (slug: string) => `${CONSTANTS.KONG_API_BASE}/nodebb/auth/api/user/${slug}/posts`, + getUserProfile: (slug: string) => `${CONSTANTS.KONG_API_BASE}/nodebb/auth/api/user/${slug}`, + getUserUpvotedPosts: (slug: string) => `${CONSTANTS.KONG_API_BASE}/nodebb/auth/api/user/${slug}/upvoted`, + getUsersWatchedTopics: (slug: string) => `${CONSTANTS.KONG_API_BASE}/nodebb/auth/api/user/${slug}/watched`, // tslint:disable-next-line: object-literal-sort-keys - getUserByEmail: (email: string) => `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/user/email/${email}`, - getUserByUsername: (username: string) => `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/user/username/${username}`, + getUserByEmail: (email: string) => `${CONSTANTS.KONG_API_BASE}/nodebb/api/user/email/${email}`, + getUserByUsername: (username: string) => `${CONSTANTS.KONG_API_BASE}/api/user/username/${username}`, } export const usersApi = Router() @@ -29,11 +29,16 @@ usersApi.get('/:slug/bookmarks', async (req, res) => { const userId = extractUserIdFromRequest(req) logInfo(`UserId: ${userId}, rootOrg: ${rootOrg}`) const slug = req.params.slug - const userUid = await getUserUID(userId) + const userUid = await getUserUIDBySession(req) const url = API_ENDPOINTS.getUserBookmarks(slug) + `?_uid=${userUid}` const response = await axios.get( url, - { ...axiosRequestConfig, headers: { authorization: getWriteApiToken() } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) res.send(response.data) } catch (err) { @@ -49,11 +54,16 @@ usersApi.get('/:slug/downvoted', async (req, res) => { const userId = extractUserIdFromRequest(req) logInfo(`UserId: ${userId}, rootOrg: ${rootOrg}`) const slug = req.params.slug - const userUid = await getUserUID(userId) + const userUid = await getUserUIDBySession(req) const url = API_ENDPOINTS.getUserDownvotedPosts(slug) + `?_uid=${userUid}` const response = await axios.get( url, - { ...axiosRequestConfig, headers: { authorization: getWriteApiToken() } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) res.send(response.data) } catch (err) { @@ -69,11 +79,16 @@ usersApi.get('/:slug/groups', async (req, res) => { const userId = extractUserIdFromRequest(req) logInfo(`UserId: ${userId}, rootOrg: ${rootOrg}`) const slug = req.params.slug - const userUid = await getUserUID(userId) + const userUid = await getUserUIDBySession(req) const url = API_ENDPOINTS.getUserGroups(slug) + `?_uid=${userUid}` const response = await axios.get( url, - { ...axiosRequestConfig, headers: { authorization: getWriteApiToken() } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) res.send(response.data) } catch (err) { @@ -89,11 +104,16 @@ usersApi.get('/:slug/info', async (req, res) => { const userId = extractUserIdFromRequest(req) logInfo(`UserId: ${userId}, rootOrg: ${rootOrg}`) const slug = req.params.slug - const userUid = await getUserUID(userId) + const userUid = await getUserUIDBySession(req) const url = API_ENDPOINTS.getUserInfo(slug) + `?_uid=${userUid}` const response = await axios.get( url, - { ...axiosRequestConfig, headers: { authorization: getWriteApiToken() } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) res.send(response.data) } catch (err) { @@ -108,12 +128,17 @@ usersApi.get('/me', async (req, res) => { const rootOrg = getRootOrg(req) const userId = extractUserIdFromRequest(req) logInfo(`UserId: ${userId}, rootOrg: ${rootOrg}`) - const userSlug = await getUserSlug(userId) - const userUid = await getUserUID(userId) + const userSlug = await getUserSlug(req, userId) + const userUid = await getUserUIDBySession(req) const url = API_ENDPOINTS.getUserProfile(userSlug) + `?_uid=${userUid}` const response = await axios.get( url, - { ...axiosRequestConfig, headers: { authorization: getWriteApiToken() } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) res.send(response.data) } catch (err) { @@ -129,11 +154,16 @@ usersApi.get('/:slug/posts', async (req, res) => { const userId = extractUserIdFromRequest(req) logInfo(`UserId: ${userId}, rootOrg: ${rootOrg}`) const slug = req.params.slug - const userUid = await getUserUID(userId) + const userUid = await getUserUIDBySession(req) const url = API_ENDPOINTS.getUserPosts(slug) + `?_uid=${userUid}` const response = await axios.get( url, - { ...axiosRequestConfig, headers: { authorization: getWriteApiToken() } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) res.send(response.data) } catch (err) { @@ -149,11 +179,16 @@ usersApi.get('/:slug/upvoted', async (req, res) => { const userId = extractUserIdFromRequest(req) logInfo(`UserId: ${userId}, rootOrg: ${rootOrg}`) const slug = req.params.slug - const userUid = await getUserUID(userId) + const userUid = await getUserUIDBySession(req) const url = API_ENDPOINTS.getUserUpvotedPosts(slug) + `?_uid=${userUid}` const response = await axios.get( url, - { ...axiosRequestConfig, headers: { authorization: getWriteApiToken() } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) res.send(response.data) } catch (err) { @@ -169,11 +204,16 @@ usersApi.get('/:slug/watched', async (req, res) => { const userId = extractUserIdFromRequest(req) logInfo(`UserId: ${userId}, rootOrg: ${rootOrg}`) const slug = req.params.slug - const userUid = await getUserUID(userId) + const userUid = await getUserUIDBySession(req) const url = API_ENDPOINTS.getUsersWatchedTopics(slug) + `?_uid=${userUid}` const response = await axios.get( url, - { ...axiosRequestConfig, headers: { authorization: getWriteApiToken() } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) res.send(response.data) } catch (err) { @@ -189,7 +229,7 @@ usersApi.get('/email/:email', async (req, res) => { const userId = extractUserIdFromRequest(req) logInfo(`UserId: ${userId}, rootOrg: ${rootOrg}`) const email = req.params.email - const response = await getUserByEmail(email) + const response = await getUserByEmail(req, email) res.send(response.data) } catch (err) { logError('ERROR ON GET topicsApi /email/:email >', err) @@ -204,13 +244,17 @@ usersApi.get('/:slug/about', async (req, res) => { const userId = extractUserIdFromRequest(req) logInfo(`UserId: ${userId}, rootOrg: ${rootOrg}`) const slug = req.params.slug - const userUid = await getUserUID(userId) + const userUid = await getUserUIDBySession(req) logInfo('called /:slug/about slug=> ', slug) const url = API_ENDPOINTS.getUserProfile(slug) + `?_uid=${userUid}` logInfo('called /:slug/about url=> ', url) const response = await axios.get( url, - { ...axiosRequestConfig, headers: { authorization: getWriteApiToken() } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) res.send(response.data) } catch (err) { @@ -221,7 +265,7 @@ usersApi.get('/:slug/about', async (req, res) => { }) // tslint:disable-next-line: no-any -export async function getUserByEmail(email: any): Promise { +export async function getUserByEmail(req: any , email: any): Promise { logInfo('Finding user in NodeBB DiscussionHub...') // tslint:disable-next-line: no-try-promise try { @@ -229,7 +273,11 @@ export async function getUserByEmail(email: any): Promise { return new Promise(async (resolve, reject) => { const response = await axios.get( url, - { ...axiosRequestConfig } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + }} ).catch((err) => { logError('ERROR ON method getUserByEmail api call to nodebb DiscussionHub >', err) reject(err) @@ -244,7 +292,7 @@ export async function getUserByEmail(email: any): Promise { } // tslint:disable-next-line: no-any -export async function getUserByUsername(username: any): Promise { +export async function getUserByUsername(req: any , username: any): Promise { logInfo('Finding user in NodeBB DiscussionHub...') // tslint:disable-next-line: no-try-promise try { @@ -252,7 +300,11 @@ export async function getUserByUsername(username: any): Promise { return new Promise(async (resolve, reject) => { const response = await axios.get( url, - { ...axiosRequestConfig } + { ...axiosRequestConfig , headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + }} ).catch((err) => { logError('ERROR ON method getUserByUsername api call to nodebb DiscussionHub >', err) reject(err) diff --git a/src/protectedApi_v8/discussionHub/writeApi.ts b/src/protectedApi_v8/discussionHub/writeApi.ts index 4eab0086..0757e141 100644 --- a/src/protectedApi_v8/discussionHub/writeApi.ts +++ b/src/protectedApi_v8/discussionHub/writeApi.ts @@ -2,28 +2,28 @@ import axios from 'axios' import { Router } from 'express' import { getRootOrg } from '../../authoring/utils/header' import { axiosRequestConfig } from '../../configs/request.config' -import { getUserUID, getWriteApiAdminUID, getWriteApiToken } from '../../utils/discussionHub-helper' +import { getUserUIDBySession, getWriteApiAdminUID} from '../../utils/discussionHub-helper' import { CONSTANTS } from '../../utils/env' import { logError, logInfo } from '../../utils/logger' -import { extractUserIdFromRequest } from '../../utils/requestExtract' +import { extractUserIdFromRequest, extractUserToken } from '../../utils/requestExtract' const API_ENDPOINTS = { - createTopic: `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/v2/topics`, - createUser: `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/v2/users`, + createTopic: `${CONSTANTS.KONG_API_BASE}/nodebb/auth/api/v2/topics`, + createUser: `${CONSTANTS.KONG_API_BASE}/nodebb/auth/api/v2/users`, // tslint:disable-next-line: object-literal-sort-keys createOrUpdateTags: (topicId: string | number) => - `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/v2/topics/${topicId}/tags`, - followTopic: (topicId: string | number) => `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/v2/topics/${topicId}/follow`, - replyToTopic: (topicId: string | number) => `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/v2/topics/${topicId}`, - votePost: (postId: string | number) => `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/v2/posts/${postId}/vote`, + `${CONSTANTS.KONG_API_BASE}/nodebb/auth/api/v2/topics/${topicId}/tags`, + followTopic: (topicId: string | number) => `${CONSTANTS.KONG_API_BASE}/nodebb/auth/api/v2/topics/${topicId}/follow`, + replyToTopic: (topicId: string | number) => `${CONSTANTS.KONG_API_BASE}/nodebb/auth/api/v2/topics/${topicId}`, + votePost: (postId: string | number) => `${CONSTANTS.KONG_API_BASE}/nodebb/auth/api/v2/posts/${postId}/vote`, // tslint:disable-next-line: object-literal-sort-keys - bookmarkPost: (postId: string | number) => `${CONSTANTS.DISCUSSION_HUB_API_BASE}/api/v2/posts/${postId}/bookmark`, + bookmarkPost: (postId: string | number) => `${CONSTANTS.KONG_API_BASE}/nodebb/auth/api/v2/posts/${postId}/bookmark`, } export const writeApi = Router() // tslint:disable-next-line: no-any -export async function createDiscussionHubUser(user: any): Promise { +export async function createDiscussionHubUser(req: any , user: any): Promise { logInfo('Starting to create new user into NodeBB DiscussionHub...') // tslint:disable-next-line: no-try-promise try { @@ -36,7 +36,11 @@ export async function createDiscussionHubUser(user: any): Promise { const response = await axios.post( url, request1, - { ...axiosRequestConfig, headers: { authorization: getWriteApiToken() } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ).catch((err) => { logError('ERROR ON method createDiscussionHubUser api call to nodebb DiscussionHub>', err) reject(err) @@ -56,14 +60,18 @@ writeApi.post('/topics', async (req, res) => { const userId = extractUserIdFromRequest(req) logInfo(`UserId: ${userId}, rootOrg: ${rootOrg}`) const url = API_ENDPOINTS.createTopic - const userUid = await getUserUID(userId) + const userUid = await getUserUIDBySession(req) const response = await axios.post( url, { ...req.body, _uid: userUid, }, - { ...axiosRequestConfig, headers: { authorization: getWriteApiToken() } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) if (response && response.data) { res.send(response.data) @@ -82,14 +90,18 @@ writeApi.post('/topics/:topicId', async (req, res) => { logInfo(`UserId: ${userId}, rootOrg: ${rootOrg}`) const topicId = req.params.topicId const url = API_ENDPOINTS.replyToTopic(topicId) - const userUid = await getUserUID(userId) + const userUid = await getUserUIDBySession(req) const response = await axios.post( url, { ...req.body, _uid: userUid, }, - { ...axiosRequestConfig, headers: { authorization: getWriteApiToken() } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) if (response && response.data) { res.send(response.data) @@ -106,7 +118,7 @@ writeApi.post('/users', async (req, res) => { const rootOrg = getRootOrg(req) const userId = extractUserIdFromRequest(req) logInfo(`UserId: ${userId}, rootOrg: ${rootOrg}`) - const response = await createDiscussionHubUser(req.body) + const response = await createDiscussionHubUser(req, req.body) res.send(response.data) } catch (err) { logError('ERROR ON writeAPI POST /users >', err) @@ -122,13 +134,17 @@ writeApi.post('/posts/:postId/bookmark', async (req, res) => { logInfo(`UserId: ${userId}, rootOrg: ${rootOrg}`) const postId = req.params.postId const url = API_ENDPOINTS.bookmarkPost(postId) - const userUid = await getUserUID(userId) + const userUid = await getUserUIDBySession(req) const response = await axios.post( url, { _uid: userUid, }, - { ...axiosRequestConfig, headers: { authorization: getWriteApiToken() } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) if (response && response.data) { res.send(response.data) @@ -146,11 +162,15 @@ writeApi.delete('/posts/:postId/bookmark', async (req, res) => { const userId = extractUserIdFromRequest(req) logInfo(`UserId: ${userId}, rootOrg: ${rootOrg}`) const postId = req.params.postId - const userUid = await getUserUID(userId) + const userUid = await getUserUIDBySession(req) const url = API_ENDPOINTS.bookmarkPost(postId) + `?_uid=${userUid}` const response = await axios.delete( url, - { ...axiosRequestConfig, headers: { authorization: getWriteApiToken() } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) if (response && response.data) { res.send(response.data) @@ -169,14 +189,18 @@ writeApi.post('/posts/:postId/vote', async (req, res) => { logInfo(`UserId: ${userId}, rootOrg: ${rootOrg}`) const postId = req.params.postId const url = API_ENDPOINTS.votePost(postId) - const userUid = await getUserUID(userId) + const userUid = await getUserUIDBySession(req) const response = await axios.post( url, { ...req.body, _uid: userUid, }, - { ...axiosRequestConfig, headers: { authorization: getWriteApiToken() } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) if (response && response.data) { res.send(response.data) @@ -194,11 +218,15 @@ writeApi.delete('/posts/:postId/vote', async (req, res) => { const userId = extractUserIdFromRequest(req) logInfo(`UserId: ${userId}, rootOrg: ${rootOrg}`) const postId = req.params.postId - const userUid = await getUserUID(userId) + const userUid = await getUserUIDBySession(req) const url = API_ENDPOINTS.votePost(postId) + `?_uid=${userUid}` const response = await axios.delete( url, - { ...axiosRequestConfig, headers: { authorization: getWriteApiToken() } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) if (response && response.data) { res.send(response.data) @@ -217,14 +245,18 @@ writeApi.put('/topics/:topicId/follow', async (req, res) => { logInfo(`UserId: ${userId}, rootOrg: ${rootOrg}`) const topicId = req.params.topicId const url = API_ENDPOINTS.followTopic(topicId) - const userUid = await getUserUID(userId) + const userUid = await getUserUIDBySession(req) const response = await axios.put( url, { // TODO : _uid: userUid, }, - { ...axiosRequestConfig, headers: { authorization: getWriteApiToken() } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) if (response && response.data) { res.send(response.data) @@ -248,7 +280,11 @@ writeApi.put('/topics/:topicId/tags', async (req, res) => { { ...req.body, }, - { ...axiosRequestConfig, headers: { authorization: getWriteApiToken() } } + { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req) + } } ) if (response && response.data) { res.send(response.data) diff --git a/src/protectedApi_v8/frac.ts b/src/protectedApi_v8/frac.ts index 710d614a..de106583 100644 --- a/src/protectedApi_v8/frac.ts +++ b/src/protectedApi_v8/frac.ts @@ -5,17 +5,21 @@ import { axiosRequestConfig } from '../configs/request.config' import { CONSTANTS } from '../utils/env' import { logError, logInfo } from '../utils/logger' import { ERROR } from '../utils/message' +import { extractAuthorizationFromRequest } from '../utils/requestExtract' const API_END_POINTS = { - addDataNode: `${CONSTANTS.FRAC_API_BASE}/fracapis/frac/addDataNode`, - addDataNodeBulk: `${CONSTANTS.FRAC_API_BASE}/fracapis/frac/addDataNodeBulk`, - getActivity: `${CONSTANTS.FRAC_API_BASE}/fracapis/frac/getAllNodes?type=ACTIVITY&status=VERIFIED`, - getCompetencyArea: `${CONSTANTS.FRAC_API_BASE}/fracapis/frac/getAllNodes?type=COMPETENCYAREA`, - getDictionary: `${CONSTANTS.FRAC_API_BASE}/fracapis/frac/getAllNodes?type=COMPETENCY&status=VERIFIED`, + addDataNode: `${CONSTANTS.FRAC_API_BASE}/frac/addDataNode`, + addDataNodeBulk: `${CONSTANTS.FRAC_API_BASE}/frac/addDataNodeBulk`, + bookmarkDataNode: `${CONSTANTS.FRAC_API_BASE}/frac/bookmarkDataNode`, + filterByMappings: `${CONSTANTS.FRAC_API_BASE}/frac/filterByMappings`, + getActivity: `${CONSTANTS.FRAC_API_BASE}/frac/getAllNodes?type=ACTIVITY&status=VERIFIED`, + getCompetencyArea: `${CONSTANTS.FRAC_API_BASE}/frac/getAllNodes?type=COMPETENCYAREA`, + getDictionary: `${CONSTANTS.FRAC_API_BASE}/frac/getAllNodes?type=COMPETENCY&status=VERIFIED`, + getKnowledgeResource: `${CONSTANTS.FRAC_API_BASE}/frac/getAllNodes?type=KNOWLEDGERESOURCE`, getNodeById: (id: string, type: string) => - `${CONSTANTS.FRAC_API_BASE}/fracapis/frac/getNodeById?id=${id}&type=${type}&isDetail=true`, - getRole: `${CONSTANTS.FRAC_API_BASE}/fracapis/frac/getAllNodes?type=ROLE&status=VERIFIED`, - searchNodes: `${CONSTANTS.FRAC_API_BASE}/fracapis/frac/searchNodes`, + `${CONSTANTS.FRAC_API_BASE}/frac/getNodeById?id=${id}&type=${type}&isDetail=true`, + getRole: `${CONSTANTS.FRAC_API_BASE}/frac/getAllNodes?type=ROLE&status=VERIFIED`, + searchNodes: `${CONSTANTS.FRAC_API_BASE}/frac/searchNodes`, } export const fracApi = Router() @@ -38,6 +42,13 @@ fracApi.get('/getAllNodes/:type', async (req, res) => { case 'activity': apiEndPoint = API_END_POINTS.getActivity break + case 'knowledgeResource': + apiEndPoint = API_END_POINTS.getKnowledgeResource + const queryParams = req.query + if (queryParams.bookmarks) { + apiEndPoint = apiEndPoint + '&bookmarks=' + queryParams.bookmarks + } + break default: res.status(400).send('TYPE_IS_NOT_PROVIDED_OR_TYPE_IS_NOT_CONFIGURED') break @@ -45,7 +56,7 @@ fracApi.get('/getAllNodes/:type', async (req, res) => { const response = await axios.get(apiEndPoint, { ...axiosRequestConfig, headers: { - Authorization: req.header('Authorization'), + Authorization: extractAuthorizationFromRequest(req), }, }) res.status(response.status).send(response.data) @@ -63,7 +74,7 @@ fracApi.post('/addDataNode', async (req, res) => { const response = await axios.post(API_END_POINTS.addDataNode, req.body, { ...axiosRequestConfig, headers: { - Authorization: req.header('Authorization'), + Authorization: extractAuthorizationFromRequest(req), }, }) res.status(response.status).send(response.data) @@ -81,7 +92,7 @@ fracApi.post('/addDataNodeBulk', async (req, res) => { const response = await axios.post(API_END_POINTS.addDataNodeBulk, req.body, { ...axiosRequestConfig, headers: { - Authorization: req.header('Authorization'), + Authorization: extractAuthorizationFromRequest(req), }, }) res.status(response.status).send(response.data) @@ -99,7 +110,25 @@ fracApi.post('/searchNodes', async (req, res) => { const response = await axios.post(API_END_POINTS.searchNodes, req.body, { ...axiosRequestConfig, headers: { - Authorization: req.header('Authorization'), + Authorization: extractAuthorizationFromRequest(req), + }, + }) + res.status(response.status).send(response.data) + } catch (err) { + res.status((err && err.response && err.response.status) || 500).send( + (err && err.response && err.response.data) || { + error: unknownError, + } + ) + } +}) + +fracApi.post('/filterByMappings', async (req, res) => { + try { + const response = await axios.post(API_END_POINTS.filterByMappings, req.body, { + ...axiosRequestConfig, + headers: { + Authorization: extractAuthorizationFromRequest(req), }, }) res.status(response.status).send(response.data) @@ -116,10 +145,15 @@ fracApi.get('/getNodeById/:id/:type', async (req, res) => { try { const id = req.params.id const type = req.params.type - const response = await axios.get(API_END_POINTS.getNodeById(id, type), { + let apiEndpoint = API_END_POINTS.getNodeById(id, type) + const queryParams = req.query + if (queryParams.bookmarks) { + apiEndpoint = apiEndpoint + '&bookmarks=' + queryParams.bookmarks + } + const response = await axios.get(apiEndpoint, { ...axiosRequestConfig, headers: { - Authorization: req.header('Authorization'), + Authorization: extractAuthorizationFromRequest(req), }, }) res.status(response.status).send(response.data) @@ -135,7 +169,7 @@ fracApi.get('/getNodeById/:id/:type', async (req, res) => { fracApi.get('/:type/:key', async (req, res) => { try { const rootOrg = req.header('rootOrg') - const authToken = req.header('Authorization') + const authToken = extractAuthorizationFromRequest(req) if (!rootOrg || !authToken) { res.status(400).send(ERROR.ERROR_NO_ORG_DATA) return @@ -145,26 +179,26 @@ fracApi.get('/:type/:key', async (req, res) => { // tslint:disable-next-line: no-useless-cast const type = req.params.type as string const searchBody = { - childCount : true, + childCount: true, childNodes: true, searches: [ - { - field : 'name', - keyword : key, - type, + { + field: 'name', + keyword: key, + type, }, - { - field : 'status', - keyword : 'VERIFIED', + { + field: 'status', + keyword: 'VERIFIED', type, - }, - ], - } + }, + ], + } logInfo('Req body========>', JSON.stringify(searchBody)) const response = await axios.post(API_END_POINTS.searchNodes, searchBody, { ...axiosRequestConfig, headers: { - Authorization: req.header('Authorization'), + Authorization: extractAuthorizationFromRequest(req), }, }) res.status(200).send(response.data) @@ -177,3 +211,21 @@ fracApi.get('/:type/:key', async (req, res) => { ) } }) + +fracApi.post('/bookmarkDataNode', async (req, res) => { + try { + const response = await axios.post(API_END_POINTS.bookmarkDataNode, req.body, { + ...axiosRequestConfig, + headers: { + Authorization: extractAuthorizationFromRequest(req), + }, + }) + res.status(response.status).send(response.data) + } catch (err) { + res.status((err && err.response && err.response.status) || 500).send( + (err && err.response && err.response.data) || { + error: unknownError, + } + ) + } +}) diff --git a/src/protectedApi_v8/network.ts b/src/protectedApi_v8/network.ts index ec4b906b..3aad2304 100644 --- a/src/protectedApi_v8/network.ts +++ b/src/protectedApi_v8/network.ts @@ -5,14 +5,15 @@ import { CONSTANTS } from '../utils/env' import { logError, logInfo } from '../utils/logger' import { ERROR } from '../utils/message' import { extractUserIdFromRequest } from '../utils/requestExtract' +import { extractUserToken } from '../utils/requestExtract' const unknown = 'Network Apis:- Failed due to unknown reason' const apiEndpoints = { detail: `${CONSTANTS.USER_PROFILE_API_BASE}/user/multi-fetch/wid`, - getConnectionEstablishedData: `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/connections/profile/fetch/established`, - getConnectionRequestsData: `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/connections/profile/fetch/requested`, - getConnectionRequestsReceivedData: `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/connections/profile/fetch/requests/received`, - getConnectionSuggestsData: `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/connections/profile/find/suggests`, + getConnectionEstablishedData: `${CONSTANTS.KONG_API_BASE}/connections/profile/fetch/established`, + getConnectionRequestsData: `${CONSTANTS.KONG_API_BASE}/connections/profile/fetch/requested`, + getConnectionRequestsReceivedData: `${CONSTANTS.KONG_API_BASE}/connections/profile/fetch/requests/received`, + getConnectionSuggestsData: `${CONSTANTS.KONG_API_BASE}/connections/profile/find/suggests`, postConnectionAddData: `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/connections/add`, postConnectionRecommendationData: `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/connections/profile/find/recommended`, postConnectionUpdateData: `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/connections/update`, @@ -37,8 +38,11 @@ networkConnectionApi.get('/connections/requested', async (req, res) => { const response = await axios.get(apiEndpoints.getConnectionRequestsData, { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, rootOrg, userId, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, }) res.send((response.data)) @@ -69,8 +73,11 @@ networkConnectionApi.get('/connections/requests/received', async (req, res) => { const response = await axios.get(apiEndpoints.getConnectionRequestsReceivedData, { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, rootOrg, userId, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, }) res.send((response.data)) @@ -101,8 +108,11 @@ networkConnectionApi.get('/connections/established', async (req, res) => { const response = await axios.get(apiEndpoints.getConnectionEstablishedData, { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, rootOrg, userId, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, }) res.send((response.data)) @@ -133,8 +143,11 @@ networkConnectionApi.get('/connections/established/:id', async (req, res) => { const response = await axios.get(apiEndpoints.getConnectionEstablishedData, { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, rootOrg, userId, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, }) res.send((response.data)) @@ -165,8 +178,11 @@ networkConnectionApi.get('/connections/suggests', async (req, res) => { const response = await axios.get(apiEndpoints.getConnectionSuggestsData, { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, rootOrg, userId, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, }) res.send((response.data)) @@ -206,7 +222,10 @@ networkConnectionApi.post('/add/connection', async (req, res) => { { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, } ) @@ -248,7 +267,10 @@ networkConnectionApi.post('/update/connection', async (req, res) => { { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, } ) diff --git a/src/protectedApi_v8/protectedApiV8.ts b/src/protectedApi_v8/protectedApiV8.ts index 1df3190d..1bbb53e0 100644 --- a/src/protectedApi_v8/protectedApiV8.ts +++ b/src/protectedApi_v8/protectedApiV8.ts @@ -7,8 +7,11 @@ import { certificationApi } from './certifications' import { cohortsApi } from './cohorts' import { competencyApi } from './competency' import { conceptGraphApi } from './concept' -import { connectionsApi } from './connections' +// tslint:disable-next-line: no-commented-code +// import { connectionsApi } from './connections' +import { connectionsV2Api } from './connections_v2' import { contentApi } from './content' +import { contentPrivateApi } from './contentprivate' import { contentValidationApi } from './contentValidation' import { counterApi } from './counter' import { deptApi } from './departments' @@ -23,6 +26,7 @@ import { networkConnectionApi } from './network' import { networkHubApi } from './network-hub' import { portalApi } from './portal-v3' import { recommendationApi } from './recommendation' +import { userAuthKeyCloakApi } from './resource' import { roleActivityApi } from './roleActivity' import { scoringApi } from './scoring' import { scromApi } from './scrom' @@ -65,12 +69,15 @@ protectedApiV8.use('/translate', translateApi) protectedApiV8.use('/attended-content', attendedContentApi) protectedApiV8.use('/event-external', externalEventsApi) protectedApiV8.use('/network', networkConnectionApi) -protectedApiV8.use('/connections', connectionsApi) +// protectedApiV8.use('/connections', connectionsApi) +protectedApiV8.use('/connections', connectionsV2Api) protectedApiV8.use('/competency', competencyApi) protectedApiV8.use('/dept', deptApi) protectedApiV8.use('/portal', portalApi) protectedApiV8.use('/scroing', scoringApi) protectedApiV8.use('/workflowhandler', workflowHandlerApi) protectedApiV8.use('/roleactivity', roleActivityApi) +protectedApiV8.use('/resource', userAuthKeyCloakApi) protectedApiV8.use('/workallocation', workAllocationApi) protectedApiV8.use('/frac', fracApi) +protectedApiV8.use('/contentprivate', contentPrivateApi) diff --git a/src/protectedApi_v8/resource.ts b/src/protectedApi_v8/resource.ts new file mode 100644 index 00000000..7e1858ec --- /dev/null +++ b/src/protectedApi_v8/resource.ts @@ -0,0 +1,27 @@ +import { Router } from 'express' +import { logInfo } from '../utils/logger' +const _ = require('lodash') +export const userAuthKeyCloakApi = Router() +userAuthKeyCloakApi.get('/', (req, res) => { + const host = req.get('host') + let queryParam = '' + let isLocal = 0 + if (!_.isEmpty(req.query)) { + queryParam = req.query.q + if (queryParam && queryParam.includes('localhost')) { + isLocal = 1 + } + if (req.query.redirect_uri) { + logInfo('Received redirectUrl value : ' + req.query.redirect_uri) + res.redirect(req.query.redirect_uri) + return + } + } + let redirectUrl = '' + if (isLocal) { + redirectUrl = queryParam + } else { + redirectUrl = `https://${host}${queryParam}` // 'https://' + host + '/page/home' + } + res.redirect(redirectUrl) +}) diff --git a/src/protectedApi_v8/roleActivity.ts b/src/protectedApi_v8/roleActivity.ts index 4dacb455..0196daf3 100644 --- a/src/protectedApi_v8/roleActivity.ts +++ b/src/protectedApi_v8/roleActivity.ts @@ -6,11 +6,12 @@ import { ERROR } from '../utils/message' import axios from 'axios' import { axiosRequestConfig } from '../configs/request.config' import { CONSTANTS } from '../utils/env' +import { extractAuthorizationFromRequest } from '../utils/requestExtract' export const roleActivityApi = Router() const API_END_POINTS = { - searchNodes: `${CONSTANTS.FRAC_API_BASE}/fracapis/frac/searchNodes`, + searchNodes: `${CONSTANTS.FRAC_API_BASE}/frac/searchNodes`, } roleActivityApi.get('/', async (req, res) => { @@ -33,7 +34,7 @@ roleActivityApi.get('/', async (req, res) => { roleActivityApi.get('/:roleKey', async (req, res) => { try { const rootOrg = req.header('rootOrg') - const authToken = req.header('Authorization') + const authToken = extractAuthorizationFromRequest(req) if (!rootOrg || !authToken) { res.status(400).send(ERROR.ERROR_NO_ORG_DATA) return @@ -60,7 +61,7 @@ roleActivityApi.get('/:roleKey', async (req, res) => { const response = await axios.post(API_END_POINTS.searchNodes, searchBody, { ...axiosRequestConfig, headers: { - Authorization: req.header('Authorization'), + Authorization: extractAuthorizationFromRequest(req), }, }) const returnRoleList: IRole[] = [] diff --git a/src/protectedApi_v8/scoring.ts b/src/protectedApi_v8/scoring.ts index 8b472751..f7827730 100644 --- a/src/protectedApi_v8/scoring.ts +++ b/src/protectedApi_v8/scoring.ts @@ -4,11 +4,12 @@ import { axiosRequestConfig } from '../configs/request.config' import { CONSTANTS } from '../utils/env' import { logError } from '../utils/logger' import { ERROR } from '../utils/message' +import { extractUserToken } from '../utils/requestExtract' const API_END_POINTS = { - calculateScoreEndPoint: `${CONSTANTS.SCORING_SERVICE_API_BASE}/action/scoring/add`, - fetchScore: `${CONSTANTS.SCORING_SERVICE_API_BASE}/action/scoring/fetch`, - fetchTemplate: (templateId: string) => `${CONSTANTS.SCORING_SERVICE_API_BASE}/action/scoring/getTemplate/${templateId}`, + calculateScoreEndPoint: `${CONSTANTS.KONG_API_BASE}/scoring/v1/add`, + fetchScore: `${CONSTANTS.KONG_API_BASE}/scoring/v1/fetch`, + fetchTemplate: (templateId: string) => `${CONSTANTS.KONG_API_BASE}/scoring/v1/getTemplate/${templateId}`, } export const scoringApi = Router() @@ -30,8 +31,11 @@ scoringApi.post('/calculate', async (req, res) => { { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, org: orgValue, rootOrg: rootOrgValue, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, } ) @@ -60,8 +64,11 @@ scoringApi.post('/fetch', async (req, res) => { { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, org: orgValue, rootOrg: rootOrgValue, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, } ) @@ -88,8 +95,11 @@ scoringApi.get('/getTemplate/:templateId', async (req, res) => { const response = await axios.get(API_END_POINTS.fetchTemplate(templateId), { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, org: orgValue, rootOrg: rootOrgValue, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, }) res.status(response.status).send(response.data) diff --git a/src/protectedApi_v8/user/auto-complete.ts b/src/protectedApi_v8/user/auto-complete.ts index 5f786a6e..41b79152 100644 --- a/src/protectedApi_v8/user/auto-complete.ts +++ b/src/protectedApi_v8/user/auto-complete.ts @@ -3,10 +3,11 @@ import { Router } from 'express' import { axiosRequestConfig } from '../../configs/request.config' import { CONSTANTS } from '../../utils/env' import { ERROR } from '../../utils/message' +import { extractUserToken } from '../../utils/requestExtract' const API_END_POINTS = { users: (queryParams: string) => - `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/v1/user/autocomplete?${queryParams}`, + `${CONSTANTS.KONG_API_BASE}/v1/user/autocomplete?${queryParams}`, usersByDepartment: (rootOrg: string, searchItem: string) => `${CONSTANTS.USER_PROFILE_API_BASE}/user/autocomplete/${rootOrg}/department/${searchItem}`, } @@ -47,7 +48,12 @@ autocompleteApi.get('/:query', async (req, res) => { const url = API_END_POINTS.users('searchString=' + queryParams) const response = await axios({ ...axiosRequestConfig, - headers: { rootOrg }, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + rootOrg, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), + }, method: 'GET', url, }) diff --git a/src/protectedApi_v8/user/details.ts b/src/protectedApi_v8/user/details.ts index 190fd33d..71f593df 100644 --- a/src/protectedApi_v8/user/details.ts +++ b/src/protectedApi_v8/user/details.ts @@ -149,7 +149,7 @@ export function wTokenApiMock(req: any, token: any): Promise { const user = body.user // Check if user is present in NodeBB DiscussionHub // tslint:disable-next-line: no-identical-functions - const userPresent = await getUserByEmail(user.email).catch(async (err) => { + const userPresent = await getUserByEmail(req, user.email).catch(async (err) => { if (err.response && (err.response.status === 404)) { // If user is not already present in nodeBB DiscussionHub // then create the user @@ -160,7 +160,7 @@ export function wTokenApiMock(req: any, token: any): Promise { username: user.wid, } // tslint:disable-next-line: no-any - await createDiscussionHubUser(reqToDiscussionHub).catch((createDiscussionHubUserErr: any) => { + await createDiscussionHubUser(req, reqToDiscussionHub).catch((createDiscussionHubUserErr: any) => { logError(`Creatin of User failed..!:`, createDiscussionHubUserErr) resolve(body) }) diff --git a/src/protectedApi_v8/user/evaluate.ts b/src/protectedApi_v8/user/evaluate.ts index 88d99e20..142ed573 100644 --- a/src/protectedApi_v8/user/evaluate.ts +++ b/src/protectedApi_v8/user/evaluate.ts @@ -3,11 +3,12 @@ import { Router } from 'express' import { axiosRequestConfig } from '../../configs/request.config' import { CONSTANTS } from '../../utils/env' import { ERROR } from '../../utils/message' -import { extractUserIdFromRequest } from '../../utils/requestExtract' +import { extractUserIdFromRequest, extractUserToken } from '../../utils/requestExtract' const GENERAL_ERR_MSG = 'Failed due to unknown reason' const API_END_POINTS = { - assessmentSubmitV2: `${CONSTANTS.SUBMISSION_API_BASE}/v2/user`, + assessmentSubmitV2: `${CONSTANTS.KONG_API_BASE}/v2/user`, + assessmentSubmitV3: `${CONSTANTS.KONG_API_BASE}/v3/user`, iapSubmitAssessment: `${CONSTANTS.SB_EXT_API_BASE_2}/v3/iap-assessment`, postAssessment: `${CONSTANTS.POST_ASSESSMENT_BASE}/lmsapi/v1/post_assessment`, } @@ -22,7 +23,7 @@ evaluateApi.post('/assessment/submit/v2', async (req, res) => { return } const userId = extractUserIdFromRequest(req) - const url = `${API_END_POINTS.assessmentSubmitV2}/${userId}/assessment/submit` + const url = `${API_END_POINTS.assessmentSubmitV2}/assessment/submit` const requestBody = { ...req.body, } @@ -30,7 +31,38 @@ evaluateApi.post('/assessment/submit/v2', async (req, res) => { ...axiosRequestConfig, data: requestBody, headers: { + Authorization: CONSTANTS.SB_API_KEY, rootOrg, + userId, + 'x-authenticated-user-token': extractUserToken(req), + }, + method: 'POST', + url, + }) + res.status(response.status).send(response.data) + } catch (err) { + res.status((err && err.response && err.response.status) || 500).send( + (err && err.response && err.response.data) || { + error: GENERAL_ERR_MSG, + } + ) + } +}) + +evaluateApi.post('/assessment/submit/v3', async (req, res) => { + try { + const userId = extractUserIdFromRequest(req) + const url = `${API_END_POINTS.assessmentSubmitV3}/assessment/submit` + const requestBody = { + ...req.body, + } + const response = await axios({ + ...axiosRequestConfig, + data: requestBody, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + userId, + 'x-authenticated-user-token': extractUserToken(req), }, method: 'POST', url, diff --git a/src/protectedApi_v8/user/mandatoryContent.ts b/src/protectedApi_v8/user/mandatoryContent.ts index 3c543ba3..d70eeb5f 100644 --- a/src/protectedApi_v8/user/mandatoryContent.ts +++ b/src/protectedApi_v8/user/mandatoryContent.ts @@ -4,13 +4,14 @@ import { axiosRequestConfig } from '../../configs/request.config' import { CONSTANTS } from '../../utils/env' import { logError } from '../../utils/logger' import { ERROR } from '../../utils/message' +import { extractUserToken } from '../../utils/requestExtract' import { extractAuthorizationFromRequest } from '../../utils/requestExtract' const API_END_POINTS = { - mandatoryContentStatus: `${CONSTANTS.SB_EXT_API_BASE_2}/v1/check/mandatoryContentStatus`, + mandatoryContentStatus: `${CONSTANTS.KONG_API_BASE}/v1/check/mandatoryContentStatus`, } export const mandatoryContent = Router() @@ -30,9 +31,11 @@ mandatoryContent.get('/checkStatus', async (req, res) => { const response = await axios.get(API_END_POINTS.mandatoryContentStatus, { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, org: orgValue, rootOrg: rootOrgValue, wid: widValue, + 'x-authenticated-user-token': extractUserToken(req), xAuthUser: xAuth[1], }, }) diff --git a/src/protectedApi_v8/user/profile-details.ts b/src/protectedApi_v8/user/profile-details.ts index c9ee7966..f1d59d52 100644 --- a/src/protectedApi_v8/user/profile-details.ts +++ b/src/protectedApi_v8/user/profile-details.ts @@ -8,16 +8,27 @@ import { logError, logInfo } from '../../utils/logger' import { ERROR } from '../../utils/message' import { extractUserIdFromRequest, extractUserToken } from '../../utils/requestExtract' +const uuidv1 = require('uuid/v1') +const dateFormat = require('dateformat') + const API_END_POINTS = { createOSUserRegistry: (userId: string) => `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/v1/user/create/profile?userId=${userId}`, createSb: `${CONSTANTS.KONG_API_BASE}/user/v3/create`, createUserRegistry: `${CONSTANTS.USER_PROFILE_API_BASE}/public/v8/profileDetails/createUserRegistry`, + // tslint:disable-next-line: object-literal-sort-keys + createNodeBBUser: `${CONSTANTS.KONG_API_BASE}/discussion/user/v1/create`, getMasterLanguages: `${CONSTANTS.USER_PROFILE_API_BASE}/public/v8/profileDetails/getMasterLanguages`, getMasterNationalities: `${CONSTANTS.USER_PROFILE_API_BASE}/public/v8/profileDetails/getMasterNationalities`, getOSUserRegistryById: (userId: string) => `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/v1/user/search/profile?userId=${userId}`, getProfilePageMeta: `${CONSTANTS.USER_PROFILE_API_BASE}/public/v8/profileDetails/getProfilePageMeta`, getUserRegistry: `${CONSTANTS.USER_PROFILE_API_BASE}/public/v8/profileDetails/getUserRegistry`, getUserRegistryById: `${CONSTANTS.USER_PROFILE_API_BASE}/public/v8/profileDetails/getUserRegistryById`, + kongCreateUser: `${CONSTANTS.KONG_API_BASE}/user/v3/create`, + kongSearchUser: `${CONSTANTS.KONG_API_BASE}/user/v1/search`, + kongSendWelcomeEmail: `${CONSTANTS.KONG_API_BASE}/private/user/v1/notification/email`, + kongUpdateUser: `${CONSTANTS.KONG_API_BASE}/user/private/v1/update`, + kongUserRead: (userId: string) => `${CONSTANTS.KONG_API_BASE}/user/v2/read/${userId}`, + kongUserResetPassword: `${CONSTANTS.KONG_API_BASE}/private/user/v1/password/reset`, // tslint:disable-next-line: object-literal-sort-keys migrateRegistry: `${CONSTANTS.USER_PROFILE_API_BASE}/public/v8/profileDetails/migrateRegistry`, resetPassword: `${CONSTANTS.LEARNER_SERVICE_API_BASE}/private/user/v1/password/reset`, @@ -202,7 +213,10 @@ const failedToCreateUser = 'Not able to create User in SunBird' const failedToReadUser = 'Failed to read newly created user details.' const failedToCreateUserInOpenSaber = 'Not able to create User Registry in Opensaber' const createUserFailed = 'ERROR CREATING USER >' +const failedToUpdateUser = 'Failed to update user profile data.' +const unknownError = 'Failed due to unknown reason' +// tslint:disable-next-line: max-lines-per-function profileDeatailsApi.post('/createUser', async (req, res) => { try { const sbChannel = req.body.personalDetails.channel @@ -214,15 +228,37 @@ profileDeatailsApi.post('/createUser', async (req, res) => { const sbemailVerified_ = true const sbfirstName_ = req.body.personalDetails.firstName const sblastName_ = req.body.personalDetails.lastName - + const isEmailRequired = (req.body.personalDetails.isEmailRequired) ? req.body.personalDetails.isEmailRequired : true const searchresponse = await axios({ ...axiosRequestConfig, data: { request: { query: '', filters: { email: sbemail_.toLowerCase() } } }, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), + }, method: 'POST', - url: API_END_POINTS.searchSb, + url: API_END_POINTS.kongSearchUser, }) if (searchresponse.data.result.response.count > 0) { - res.status(400).send(emailAdressExist) + res.status(400).send( + { + id: 'api.error.createUser', + ver: '1.0', + // tslint:disable-next-line: object-literal-sort-keys + ts: dateFormat(new Date(), 'yyyy-mm-dd HH:MM:ss:lo'), + params: + { + resmsgid: uuidv1(), + // tslint:disable-next-line: object-literal-sort-keys + msgid: null, + status: 'failed', + err: 'USR_EMAIL_EXISTS', + errmsg: emailAdressExist, + }, + responseCode: 'USR_EMAIL_EXISTS', + result: {}, + }) return } else { const sbUserProfile: Partial = { @@ -238,7 +274,7 @@ profileDeatailsApi.post('/createUser', async (req, res) => { 'x-authenticated-user-token': extractUserToken(req), }, method: 'POST', - url: API_END_POINTS.createSb, + url: API_END_POINTS.kongCreateUser, }) if (response.data.responseCode === 'CLIENT_ERROR') { res.status(400).send(failedToCreateUser) @@ -253,84 +289,127 @@ profileDeatailsApi.post('/createUser', async (req, res) => { 'x-authenticated-user-token': extractUserToken(req), }, method: 'GET', - url: API_END_POINTS.userRead(sbUserId), + url: API_END_POINTS.kongUserRead(sbUserId), }) if (sbUserReadResponse.data.params.status !== 'success') { res.status(500).send(failedToReadUser) return } - - const passwordResetRequest = { - key: 'email', - type: 'email', + // tslint:disable-next-line: no-commented-code + const nodebbPayload = { + username: sbUserReadResponse.data.result.response.userName, + // tslint:disable-next-line: object-literal-sort-keys + identifier: sbUserReadResponse.data.result.response.identifier, + fullname: sbUserReadResponse.data.result.response.firstName + ' ' + sbUserReadResponse.data.result.response.lastName, + } + await axios({ + ...axiosRequestConfig, + data: { request: nodebbPayload }, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), + }, + method: 'POST', + url: API_END_POINTS.createNodeBBUser, + }) + const sbUserOrgId = sbUserReadResponse.data.result.response.rootOrgId + const sbProfileUpdateReq = { + profileDetails: { + employmentDetails: { + departmentName: sbChannel, + }, + personalDetails: { + firstname: sbfirstName_, + primaryEmail: sbemail_, + surname: sblastName_, + }, + }, userId: sbUserId, } + if (req.body.personalDetails.designation) { + const arrDesignation = [] + const objDesignation = { + designation: (req.body.personalDetails.designation) ? req.body.personalDetails.designation : '', + } + arrDesignation.push(objDesignation) + const profDetailsPropertyName = 'professionalDetails' + sbProfileUpdateReq[profDetailsPropertyName] = arrDesignation + } - logInfo('Sending Password reset request -> ' + passwordResetRequest) - const passwordResetResponse = await axios({ + const sbUserProfileUpdateResp = await axios({ ...axiosRequestConfig, - data: { request: passwordResetRequest }, - method: 'POST', - url: API_END_POINTS.resetPassword, + data: { request: sbProfileUpdateReq }, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + }, + method: 'PATCH', + url: API_END_POINTS.kongUpdateUser, }) - logInfo('Received response from password reset -> ' + passwordResetResponse) - - if (passwordResetResponse.data.params.status === 'success') { - const welcomeMailRequest = { - allowedLoging: 'You can use your email to Login', - body: 'Hello', - emailTemplateType: 'iGotWelcome', - firstName: sbUserProfile.firstName, - link: passwordResetResponse.data.result.link, - mode: 'email', - orgName: sbChannel, - recipientEmails: [ sbemail_ ], - setPasswordLink: true, - subject: 'Welcome Email', - welcomeMessage: 'Hello', + if (sbUserProfileUpdateResp.data.responseCode === 'CLIENT_ERROR') { + res.status(400).send(failedToUpdateUser) + return + } + if (isEmailRequired) { + const passwordResetRequest = { + key: 'email', + type: 'email', + userId: sbUserId, } - const welcomeMailResponse = await axios({ + logInfo('Sending Password reset request -> ' + passwordResetRequest) + const passwordResetResponse = await axios({ ...axiosRequestConfig, - data: { request: welcomeMailRequest }, + data: { request: passwordResetRequest }, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + }, method: 'POST', - url: API_END_POINTS.sendWelcomeEmail, + url: API_END_POINTS.kongUserResetPassword, }) + logInfo('Received response from password reset -> ' + passwordResetResponse) - if (welcomeMailResponse.data.params.status !== 'success') { - res.status(500).send('Failed to send Welcome Email.') + if (passwordResetResponse.data.params.status === 'success') { + const welcomeMailRequest = { + allowedLoging: 'You can use your email to Login', + body: 'Hello', + emailTemplateType: 'iGotWelcome', + firstName: sbUserProfile.firstName, + link: passwordResetResponse.data.result.link, + mode: 'email', + orgName: sbChannel, + recipientEmails: [ sbemail_ ], + setPasswordLink: true, + subject: 'Welcome Email', + welcomeMessage: 'Hello', + } + + const welcomeMailResponse = await axios({ + ...axiosRequestConfig, + data: { request: welcomeMailRequest }, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + }, + method: 'POST', + url: API_END_POINTS.kongSendWelcomeEmail, + }) + + if (welcomeMailResponse.data.params.status !== 'success') { + res.status(500).send('Failed to send Welcome Email.') + return + } + } else { + res.status(500).send('Failed to reset the password for user.') return } - } else { - res.status(500).send('Failed to reset the password for user.') - return } - const personalDetailsRegistry: IPersonalDetails = { - firstname: sbfirstName_, - primaryEmail: sbemail_, - surname: sblastName_, - userName: sbUserReadResponse.data.result.response.userName, - } - const userRegistry = getUserRegistry(personalDetailsRegistry, sbChannel) - const userRegistryResponse = await axios({ - ...axiosRequestConfig, - data: userRegistry, - headers: { - wid: sbUserId, - }, - method: 'POST', - url: API_END_POINTS.createOSUserRegistry(sbUserId), - }) - if (userRegistryResponse.data === null) { - res.status(500).send(failedToCreateUserInOpenSaber) - } else { - const sbUserProfileResponse: Partial = { - email: sbemail_, firstName: sbfirstName_, lastName: sblastName_, - userId: sbUserId, - } - res.send(sbUserProfileResponse) + const sbUserProfileResponse: Partial = { + email: sbemail_, firstName: sbfirstName_, lastName: sblastName_, + userId: sbUserId, + userOrgId: sbUserOrgId, } + res.send(sbUserProfileResponse) } } } catch (err) { @@ -339,6 +418,25 @@ profileDeatailsApi.post('/createUser', async (req, res) => { } }) +profileDeatailsApi.patch('/updateUser', async (req, res) => { + try { + const response = await axios.patch(API_END_POINTS.kongUpdateUser, req.body, { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + }, + }) + res.status(response.status).send(response.data) + } catch (err) { + logError(failedToUpdateUser + err) + res.status((err && err.response && err.response.status) || 500).send( + (err && err.response && err.response.data) || { + error: unknownError, + } + ) + } +}) + profileDeatailsApi.post('/createUserV2WithRegistry', async (req, res) => { try { const sbChannel = req.body.personalDetails.channel @@ -512,11 +610,32 @@ profileDeatailsApi.post('/createUserWithoutInvitationEmail', async (req, res) => const searchresponse = await axios({ ...axiosRequestConfig, data: { request: { query: '', filters: { email: sbemail_.toLowerCase() } } }, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), + }, method: 'POST', - url: API_END_POINTS.searchSb, + url: API_END_POINTS.kongSearchUser, }) if (searchresponse.data.result.response.count > 0) { - res.status(400).send(emailAdressExist) + res.status(400).send({ + id: 'api.error.createUser', + ver: '1.0', + // tslint:disable-next-line: object-literal-sort-keys + ts: dateFormat(new Date(), 'yyyy-mm-dd HH:MM:ss:lo'), + params: + { + resmsgid: uuidv1(), + // tslint:disable-next-line: object-literal-sort-keys + msgid: null, + status: 'failed', + err: 'USR_EMAIL_EXISTS', + errmsg: emailAdressExist, + }, + responseCode: 'USR_EMAIL_EXISTS', + result: {}, + }) return } else { const sbUserProfile: Partial = { @@ -532,7 +651,7 @@ profileDeatailsApi.post('/createUserWithoutInvitationEmail', async (req, res) => 'x-authenticated-user-token': extractUserToken(req), }, method: 'POST', - url: API_END_POINTS.createSb, + url: API_END_POINTS.kongCreateUser, }) if (response.data.responseCode === 'CLIENT_ERROR') { res.status(400).send(failedToCreateUser) @@ -547,31 +666,39 @@ profileDeatailsApi.post('/createUserWithoutInvitationEmail', async (req, res) => 'x-authenticated-user-token': extractUserToken(req), }, method: 'GET', - url: API_END_POINTS.userRead(sbUserId), + url: API_END_POINTS.kongUserRead(sbUserId), }) if (sbUserReadResponse.data.params.status !== 'success') { res.status(500).send(failedToReadUser) return } - const personalDetailsRegistry: IPersonalDetails = { - firstname: sbfirstName_, - primaryEmail: sbemail_, - surname: sblastName_, - userName: sbUserReadResponse.data.result.response.userName, + const sbProfileUpdateReq = { + profileDetails: { + employmentDetails: { + departmentName: sbChannel, + }, + personalDetails: { + firstname: sbfirstName_, + primaryEmail: sbemail_, + surname: sblastName_, + }, + }, + userId: sbUserId, } - const userRegistry = getUserRegistry(personalDetailsRegistry, sbChannel) - const userRegistryResponse = await axios({ + + const sbUserProfileUpdateResp = await axios({ ...axiosRequestConfig, - data: userRegistry, + data: { request: sbProfileUpdateReq }, headers: { - wid: sbUserId, + Authorization: CONSTANTS.SB_API_KEY, }, - method: 'POST', - url: API_END_POINTS.createOSUserRegistry(sbUserId), + method: 'PATCH', + url: API_END_POINTS.kongUpdateUser, }) - if (userRegistryResponse.data === null) { - res.status(500).send(failedToCreateUserInOpenSaber) + if (sbUserProfileUpdateResp.data.responseCode === 'CLIENT_ERROR') { + res.status(400).send(failedToUpdateUser) + return } else { const sbUserProfileResponse: Partial = { email: sbemail_, firstName: sbfirstName_, lastName: sblastName_, diff --git a/src/protectedApi_v8/user/profile-registry.ts b/src/protectedApi_v8/user/profile-registry.ts index d6b193be..179e4c1a 100644 --- a/src/protectedApi_v8/user/profile-registry.ts +++ b/src/protectedApi_v8/user/profile-registry.ts @@ -3,11 +3,14 @@ import { Router } from 'express' import { axiosRequestConfig, axiosRequestConfigLong } from '../../configs/request.config' import { CONSTANTS } from '../../utils/env' import { logError, logInfo } from '../../utils/logger' -import { extractUserIdFromRequest } from '../../utils/requestExtract' +import { extractAuthorizationFromRequest, + extractUserIdFromRequest, + IAuthorizedRequest } from '../../utils/requestExtract' const fs = require('fs') const API_END_POINTS = { createUserRegistry: (userId: string) => `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/v1/user/create/profile?userId=${userId}`, + getAllPosition: `${CONSTANTS.FRAC_API_BASE}/frac/getAllNodes?type=POSITION&status=VERIFIED`, getUserRegistry: `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/v1/user/get/profile`, getUserRegistryById: (userId: string) => `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/v1/user/search/profile?userId=${userId}`, searchUserRegistry: `${CONSTANTS.NETWORK_HUB_SERVICE_BACKEND}/v1/user/search/profile`, @@ -97,6 +100,7 @@ profileRegistryApi.get('/getUserRegistry/:osid', async (req, res) => { } }) +// @Deprecated - Use Read API // tslint:disable-next-line: no-identical-functions profileRegistryApi.get('/getUserRegistryById', async (req, res) => { try { @@ -191,10 +195,15 @@ profileRegistryApi.get('/getProfilePageMeta', async (_req, res) => { .catch((err) => { logError(`error fetching degreesMeta`, err) }) - const designations = await designationMeta() + let designations = Object.create({}) + designations = await designationMeta() .catch((err) => { logError(`error fetching designationMeta`, err) }) + designations.designations = await designationMetaFrac(_req) + .catch((err) => { + logError('error fetching desingations from FRAC', err) + }) res.json({ degrees, designations, @@ -369,3 +378,38 @@ export async function getProfileStatus(userId: string) { return false } } + +export interface IPosition { + type: string + id: string + name: string + description: string + status: string + secondaryStatus: string + source: string + active: string +} + +export async function designationMetaFrac(req: IAuthorizedRequest) { + return new Promise(async (resolve, reject) => { + try { + const response = await axios.get(API_END_POINTS.getAllPosition, { + ...axiosRequestConfig, + headers: { + Authorization: extractAuthorizationFromRequest(req), + }, + }) + if (response.data.responseData) { + const result = response.data.responseData.map((item: IPosition) => { + return { name : item.name } + }) + resolve(result) + } else { + reject('Failed to receive response from FRAC API for designations') + } + } catch (err) { + logError('ERROR while calling FRAC API to get Designation') + throw err + } + }) +} diff --git a/src/protectedApi_v8/user/progress.ts b/src/protectedApi_v8/user/progress.ts index 086a2519..c482d152 100644 --- a/src/protectedApi_v8/user/progress.ts +++ b/src/protectedApi_v8/user/progress.ts @@ -4,7 +4,7 @@ import { axiosRequestConfig } from '../../configs/request.config' import { CONSTANTS } from '../../utils/env' import { logError, logErrorHeading, logInfo } from '../../utils/logger' import { ERROR } from '../../utils/message' -import { extractUserIdFromRequest } from '../../utils/requestExtract' +import { extractUserId, extractUserIdFromRequest } from '../../utils/requestExtract' const API_END_POINTS = { // tslint:disable-next-line: max-line-length @@ -55,7 +55,7 @@ progressApi.get('/', async (req, res) => { rootOrg, }, method: 'GET', - url: API_END_POINTS.hash(extractUserIdFromRequest(req)), + url: API_END_POINTS.hash(extractUserId(req)), }) // tslint:disable-next-line: no-console console.log('get progress api response : ', response) @@ -81,7 +81,7 @@ progressApi.post('/', async (req, res) => { return } const response = await axios.post( - API_END_POINTS.hash(extractUserIdFromRequest(req)), + API_END_POINTS.hash(extractUserId(req)), req.body, { ...axiosRequestConfig, diff --git a/src/protectedApi_v8/user/user.ts b/src/protectedApi_v8/user/user.ts index 5af72bd6..61bc1397 100644 --- a/src/protectedApi_v8/user/user.ts +++ b/src/protectedApi_v8/user/user.ts @@ -56,13 +56,13 @@ user.use('/account-settings', accountSettingsApi) user.use('/mini-profile', userMiniProfile) user.use('/activity', activity) user.use('/change-email', changeEmailApi) -user.use('/autocomplete', autocompleteApi) +user.use('/autocomplete', autocompleteApi) // Validate user.use('/badge', badgeApi) user.use('/class-diagram', classDiagramApi) user.use('/code', codeApi) -user.use('/content', userContentApi) +user.use('/content', userContentApi) // Validate user.use('/dashboard', dashboardApi) -user.use('/details', detailsApi) +user.use('/details', detailsApi) // Validate user.use('/email', emailApi) user.use('/emailToUserId', emailToUserIdApi) user.use('/evaluate', evaluateApi) @@ -70,22 +70,22 @@ user.use('/feedback', feedbackApi) user.use('/feedbackV2', feedbackV2Api) user.use('/follow', followApi) user.use('/goals', goalsApi) -user.use('/history', historyApi) +user.use('/history', historyApi) // Validate user.use('/iconBadge', iconBadgeApi) user.use('/myAnalytics', myAnalyticsApi) -user.use('/notifications', notificationsApi) +user.use('/notifications', notificationsApi) // Validate user.use('/ocm', ocmApi) user.use('/playlist', playlistApi) -user.use('/preference', protectedPreference) +user.use('/preference', protectedPreference) // Validate user.use('/profile', profileApi) -user.use('/profileDetails', profileDeatailsApi) +user.use('/profileDetails', profileDeatailsApi) // Validate user.use('/progress', progressApi) -user.use('/rating', ratingApi) +user.use('/rating', ratingApi) // Validate user.use('/rdbms', rdbmsApi) user.use('/roles', rolesApi) user.use('/share', shareApi) user.use('/skills', skillsApi) -user.use('/telemetry', telemetryApi) +user.use('/telemetry', telemetryApi) // Validate user.use('/tnc', protectedTnc) user.use('/token', userTokenApi) user.use('/topic', topicApi) @@ -95,5 +95,5 @@ user.use('/validate', validateApi) user.use('/realTimeProgress', realTimeProgressApi) user.use('/exercise', exerciseApi) user.use('/users', usersApi) -user.use('/mandatoryContent', mandatoryContent) -user.use('/profileRegistry', profileRegistryApi) +user.use('/mandatoryContent', mandatoryContent) // Validate +user.use('/profileRegistry', profileRegistryApi) // Validate diff --git a/src/protectedApi_v8/workallocation.ts b/src/protectedApi_v8/workallocation.ts index 818afb79..98847691 100644 --- a/src/protectedApi_v8/workallocation.ts +++ b/src/protectedApi_v8/workallocation.ts @@ -5,25 +5,26 @@ import { axiosRequestConfig } from '../configs/request.config' import { CONSTANTS } from '../utils/env' import { logError } from '../utils/logger' import { ERROR } from '../utils/message' -import { extractUserIdFromRequest } from '../utils/requestExtract' +import { extractAuthorizationFromRequest, extractUserId, extractUserToken } from '../utils/requestExtract' const workallocationV1Path = 'v1/workallocation' const workallocationV2Path = 'v2/workallocation' const API_END_POINTS = { - addAllocationEndPoint: (path: string) => `${CONSTANTS.SB_EXT_API_BASE_2}/${path}/add`, - addWorkOrderEndPoint: (path: string) => `${CONSTANTS.SB_EXT_API_BASE_2}/${path}/add/workorder`, - copyWorkOrderEndPoint: (path: string) => `${CONSTANTS.SB_EXT_API_BASE_2}/${path}/copy/workOrder`, - getPdf: (id: string) => `${CONSTANTS.SB_EXT_API_BASE_2}/getWOPdf/${id}`, - getUserBasicDetails: (userId: string) => `${CONSTANTS.SB_EXT_API_BASE_2}/${workallocationV2Path}/user/basicInfo/${userId}`, + addAllocationEndPoint: (path: string) => `${CONSTANTS.KONG_API_BASE}/${path}/add`, + addWorkOrderEndPoint: (path: string) => `${CONSTANTS.KONG_API_BASE}/${path}/add/workorder`, + copyWorkOrderEndPoint: (path: string) => `${CONSTANTS.KONG_API_BASE}/${path}/copy/workOrder`, + getPdf: (id: string) => `${CONSTANTS.KONG_API_BASE}/getWOPdf/${id}`, + getUserBasicDetails: (userId: string) => `${CONSTANTS.KONG_API_BASE}/${workallocationV2Path}/user/basicInfo/${userId}`, + getUserCompetenciesDetails: (userId: string) => `${CONSTANTS.KONG_API_BASE}/${workallocationV2Path}/user/competencies/${userId}`, getUsersEndPoint: `${CONSTANTS.SB_EXT_API_BASE_2}/v1/workallocation/getUsers`, - getWorkAllocationById: (path: string, id: string) => `${CONSTANTS.SB_EXT_API_BASE_2}/${path}/getWorkAllocationById/${id}`, - getWorkOrderById: (path: string, id: string) => `${CONSTANTS.SB_EXT_API_BASE_2}/${path}/getWorkOrderById/${id}`, - getWorkOrders: (path: string) => `${CONSTANTS.SB_EXT_API_BASE_2}/${path}/getWorkOrders`, + getWorkAllocationById: (path: string, id: string) => `${CONSTANTS.KONG_API_BASE}/${path}/getWorkAllocationById/${id}`, + getWorkOrderById: (path: string, id: string) => `${CONSTANTS.KONG_API_BASE}/${path}/getWorkOrderById/${id}`, + getWorkOrders: (path: string) => `${CONSTANTS.KONG_API_BASE}/${path}/getWorkOrders`, updateAllocationEndPoint: `${CONSTANTS.SB_EXT_API_BASE_2}/v1/workallocation/update`, - updateWorkAllocationEndPoint: (path: string) => `${CONSTANTS.SB_EXT_API_BASE_2}/${path}/update`, - updateWorkOrder: (path: string) => `${CONSTANTS.SB_EXT_API_BASE_2}/${path}/update/workorder`, + updateWorkAllocationEndPoint: (path: string) => `${CONSTANTS.KONG_API_BASE}/${path}/update`, + updateWorkOrder: (path: string) => `${CONSTANTS.KONG_API_BASE}/${path}/update/workorder`, userAutoCompleteEndPoint: (searchTerm: string) => - `${CONSTANTS.SB_EXT_API_BASE_2}/v1/workallocation/users/autocomplete?searchTerm=${searchTerm}`, + `${CONSTANTS.KONG_API_BASE}/v1/workallocation/users/autocomplete?searchTerm=${searchTerm}`, } export const workAllocationApi = Router() @@ -35,7 +36,7 @@ const workOrderIdFailedMessage = 'NO_WORKORDER_ID' workAllocationApi.post('/add', async (req, res) => { try { - const userId = extractUserIdFromRequest(req) + const userId = extractUserId(req) if (!userId) { res.status(400).send(userIdFailedMessage) return @@ -46,7 +47,7 @@ workAllocationApi.post('/add', async (req, res) => { { ...axiosRequestConfig, headers: { - Authorization: req.header('Authorization'), + Authorization: extractAuthorizationFromRequest(req), userId, }, } @@ -64,7 +65,7 @@ workAllocationApi.post('/add', async (req, res) => { workAllocationApi.post('/update', async (req, res) => { try { - const userId = extractUserIdFromRequest(req) + const userId = extractUserId(req) if (!userId) { res.status(400).send(userIdFailedMessage) return @@ -75,7 +76,7 @@ workAllocationApi.post('/update', async (req, res) => { { ...axiosRequestConfig, headers: { - Authorization: req.header('Authorization'), + Authorization: extractAuthorizationFromRequest(req), userId, }, } @@ -119,7 +120,9 @@ workAllocationApi.get('/user/autocomplete/:searchTerm', async (req, res) => { const response = await axios.get(API_END_POINTS.userAutoCompleteEndPoint(searchTerm), { ...axiosRequestConfig, headers: { - + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-user-token': extractUserToken(req), }, }) res.status(response.status).send(response.data) @@ -137,7 +140,7 @@ workAllocationApi.get('/user/autocomplete/:searchTerm', async (req, res) => { workAllocationApi.post('/v2/add', async (req, res) => { try { - const userId = extractUserIdFromRequest(req) + const userId = extractUserId(req) if (!userId) { res.status(400).send(userIdFailedMessage) return @@ -148,8 +151,11 @@ workAllocationApi.post('/v2/add', async (req, res) => { { ...axiosRequestConfig, headers: { - Authorization: req.header('Authorization'), + Authorization: CONSTANTS.SB_API_KEY, userId, + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-user-token': extractUserToken(req), + }, } ) @@ -166,7 +172,7 @@ workAllocationApi.post('/v2/add', async (req, res) => { workAllocationApi.post('/v2/update', async (req, res) => { try { - const userId = extractUserIdFromRequest(req) + const userId = extractUserId(req) if (!userId) { res.status(400).send(userIdFailedMessage) return @@ -177,8 +183,10 @@ workAllocationApi.post('/v2/update', async (req, res) => { { ...axiosRequestConfig, headers: { - Authorization: req.header('Authorization'), + Authorization: CONSTANTS.SB_API_KEY, userId, + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-user-token': extractUserToken(req), }, } ) @@ -194,7 +202,7 @@ workAllocationApi.post('/v2/update', async (req, res) => { }) workAllocationApi.post('/add/workorder', async (req, res) => { try { - const userId = extractUserIdFromRequest(req) + const userId = extractUserId(req) if (!userId) { res.status(400).send(userIdFailedMessage) return @@ -205,7 +213,10 @@ workAllocationApi.post('/add/workorder', async (req, res) => { { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, userId, + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-user-token': extractUserToken(req), }, } ) @@ -221,20 +232,21 @@ workAllocationApi.post('/add/workorder', async (req, res) => { }) workAllocationApi.post('/update/workorder', async (req, res) => { try { - const userId = extractUserIdFromRequest(req) + const userId = extractUserId(req) if (!userId) { res.status(400).send(userIdFailedMessage) return } - const auth = req.header('Authorization') as string const response = await axios.post( API_END_POINTS.updateWorkOrder(workallocationV2Path), req.body, { ...axiosRequestConfig, headers: { - Authorization: auth, + Authorization: CONSTANTS.SB_API_KEY, userId, + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-user-token': extractUserToken(req), }, } ) @@ -256,7 +268,11 @@ workAllocationApi.post('/getWorkOrders', async (req, res) => { req.body, { ...axiosRequestConfig, - headers: req.headers, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-user-token': extractUserToken(req), + }, } ) res.status(response.status).send(response.data) @@ -281,7 +297,11 @@ workAllocationApi.get('/getWorkOrderById/:workOrderId', async (req, res) => { API_END_POINTS.getWorkOrderById(workallocationV2Path, workOrderId), { ...axiosRequestConfig, - headers: req.headers, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-user-token': extractUserToken(req), + }, } ) res.status(response.status).send(response.data) @@ -306,7 +326,11 @@ workAllocationApi.get('/getWorkAllocationById/:workAllocationId', async (req, re API_END_POINTS.getWorkAllocationById(workallocationV2Path, workAllocationId), { ...axiosRequestConfig, - headers: req.headers, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-user-token': extractUserToken(req), + }, } ) res.status(response.status).send(response.data) @@ -322,7 +346,7 @@ workAllocationApi.get('/getWorkAllocationById/:workAllocationId', async (req, re workAllocationApi.post('/copy/workOrder', async (req, res) => { try { - const userId = extractUserIdFromRequest(req) + const userId = extractUserId(req) if (!userId) { res.status(400).send(userIdFailedMessage) return @@ -333,7 +357,10 @@ workAllocationApi.post('/copy/workOrder', async (req, res) => { { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, userId, + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-user-token': extractUserToken(req), }, } ) @@ -359,7 +386,11 @@ workAllocationApi.get('/getUserBasicInfo/:userId', async (req, res) => { API_END_POINTS.getUserBasicDetails(userId), { ...axiosRequestConfig, - headers: req.headers, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-user-token': extractUserToken(req), + }, } ) res.status(response.status).send(response.data) @@ -386,6 +417,9 @@ workAllocationApi.get('/getWOPdf/:workOrderId', async (req, res) => { ...axiosRequestConfig, headers: { Accept: 'application/pdf', + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-user-token': extractUserToken(req), }, responseType: 'arraybuffer', @@ -402,3 +436,32 @@ workAllocationApi.get('/getWOPdf/:workOrderId', async (req, res) => { ) } }) + +workAllocationApi.get('/getUserCompetencies/:userId', async (req, res) => { + try { + const userId = req.params.userId + if (!userId) { + res.status(400).send(userIdFailedMessage) + return + } + const response = await axios.get( + API_END_POINTS.getUserCompetenciesDetails(userId), + { + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: no-duplicate-string + 'x-authenticated-user-token': extractUserToken(req), + }, + } + ) + res.status(response.status).send(response.data) + } catch (err) { + logError(Error + err) + res.status((err && err.response && err.response.status) || 500).send( + (err && err.response && err.response.data) || { + error: ERROR.GENERAL_ERR_MSG, + } + ) + } +}) diff --git a/src/protectedApi_v8/workflow-handler.ts b/src/protectedApi_v8/workflow-handler.ts index 18d2d583..57772c78 100644 --- a/src/protectedApi_v8/workflow-handler.ts +++ b/src/protectedApi_v8/workflow-handler.ts @@ -5,20 +5,21 @@ import { axiosRequestConfig } from '../configs/request.config' import { CONSTANTS } from '../utils/env' import { logError } from '../utils/logger' import { ERROR } from '../utils/message' +import { extractUserToken } from '../utils/requestExtract' const API_END_POINTS = { - applicationTransition: `${CONSTANTS.WORKFLOW_HANDLER_SERVICE_API_BASE}/v1/workflow/transition`, - applicationsSearch: `${CONSTANTS.WORKFLOW_HANDLER_SERVICE_API_BASE}/v1/workflow/applications/search`, + applicationTransition: `${CONSTANTS.KONG_API_BASE}/workflow/transition`, + applicationsSearch: `${CONSTANTS.KONG_API_BASE}/workflow/applications/search`, historyBasedOnApplicationId: (applicationId: string) => `${CONSTANTS.WORKFLOW_HANDLER_SERVICE_API_BASE}/v1/workflow/${applicationId}/history`, historyBasedOnWfId: (workflowId: string, applicationId: string) => `${CONSTANTS.WORKFLOW_HANDLER_SERVICE_API_BASE}/v1/workflow/${workflowId}/${applicationId}/history`, nextActionSearch: (serviceName: string, state: string) => - `${CONSTANTS.WORKFLOW_HANDLER_SERVICE_API_BASE}/v1/workflow/nextAction/${serviceName}/${state}`, - userProfileUpdate: `${CONSTANTS.WORKFLOW_HANDLER_SERVICE_API_BASE}/v1/workflow/updateUserProfileWF`, - userWfFieldsSearch: `${CONSTANTS.WORKFLOW_HANDLER_SERVICE_API_BASE}/v1/workflow/getUserWFApplicationFields`, - userWfSearch: `${CONSTANTS.WORKFLOW_HANDLER_SERVICE_API_BASE}/v1/workflow/getUserWF`, - workflowProcess: (wfId: string) => `${CONSTANTS.WORKFLOW_HANDLER_SERVICE_API_BASE}/v1/workflow/workflowProcess/${wfId}`, + `${CONSTANTS.KONG_API_BASE}/workflow/nextAction/${serviceName}/${state}`, + userProfileUpdate: `${CONSTANTS.KONG_API_BASE}/workflow/updateUserProfileWF`, + userWfFieldsSearch: `${CONSTANTS.KONG_API_BASE}/workflow/getUserWFApplicationFields`, + userWfSearch: `${CONSTANTS.KONG_API_BASE}/workflow/getUserWF`, + workflowProcess: (wfId: string) => `${CONSTANTS.KONG_API_BASE}/workflow/workflowProcess/${wfId}`, } export const workflowHandlerApi = Router() @@ -39,8 +40,11 @@ workflowHandlerApi.post('/transition', async (req, res) => { { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, org: orgValue, rootOrg: rootOrgValue, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, } ) @@ -69,9 +73,11 @@ workflowHandlerApi.post('/applicationsSearch', async (req, res) => { { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, org: orgValue, rootOrg: rootOrgValue, - + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, } ) @@ -95,9 +101,11 @@ workflowHandlerApi.get('/nextActionSearch/:serviceName/:state', async (req, res) const response = await axios.get(API_END_POINTS.nextActionSearch(serviceName, state), { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, org: orgValue, rootOrg: rootOrgValue, - + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, }) res.status(response.status).send(response.data) @@ -120,8 +128,11 @@ workflowHandlerApi.get('/historyByApplicationIdAndWfId/:applicationId/:wfId', as const response = await axios.get(API_END_POINTS.historyBasedOnWfId(wfId, applicationId), { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, org: orgValue, rootOrg: rootOrgValue, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, }) res.status(response.status).send(response.data) @@ -142,7 +153,10 @@ workflowHandlerApi.get('/workflowProcess/:wfId', async (req, res) => { const response = await axios.get(API_END_POINTS.workflowProcess(wfId), { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, rootOrg: rootOrgValue, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, }) res.status(response.status).send(response.data) @@ -164,8 +178,11 @@ workflowHandlerApi.get('/historyByApplicationId/:applicationId', async (req, res const response = await axios.get(API_END_POINTS.historyBasedOnApplicationId(applicationId), { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, org: orgValue, rootOrg: rootOrgValue, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, }) res.status(response.status).send(response.data) @@ -193,8 +210,11 @@ workflowHandlerApi.post('/updateUserProfileWf', async (req, res) => { { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, org: orgValue, rootOrg: rootOrgValue, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, } ) @@ -224,9 +244,12 @@ workflowHandlerApi.post('/userWfSearch', async (req, res) => { { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, org: orgValue, rootOrg: rootOrgValue, wid, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, } ) @@ -256,9 +279,12 @@ workflowHandlerApi.post('/userWFApplicationFieldsSearch', async (req, res) => { { ...axiosRequestConfig, headers: { + Authorization: CONSTANTS.SB_API_KEY, org: orgValue, rootOrg: rootOrgValue, wid, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), }, } ) diff --git a/src/proxies_v8/proxies_v8.ts b/src/proxies_v8/proxies_v8.ts index 060fd761..c9e41990 100644 --- a/src/proxies_v8/proxies_v8.ts +++ b/src/proxies_v8/proxies_v8.ts @@ -2,12 +2,14 @@ import axios from 'axios' import express from 'express' import { UploadedFile } from 'express-fileupload' import FormData from 'form-data' +import lodash from 'lodash' import { axiosRequestConfig } from '../configs/request.config' import { CONSTANTS } from '../utils/env' -import { logInfo } from '../utils/logger' +import { logError, logInfo } from '../utils/logger' import { ilpProxyCreatorRoute, // proxyCreatorDiscussion, + proxyAssessmentRead, proxyContent, proxyContentLearnerVM, proxyCreatorKnowledge, @@ -17,15 +19,21 @@ import { proxyCreatorSunbird, proxyCreatorSunbirdSearch, proxyCreatorToAppentUserId, + proxyQuestionRead, scormProxyCreatorRoute } from '../utils/proxyCreator' import { extractUserIdFromRequest, extractUserToken } from '../utils/requestExtract' const API_END_POINTS = { contentNotificationEmail: `${CONSTANTS.NOTIFICATION_SERVIC_API_BASE}/v1/notification/send/sync`, + kongExtOrgSearch: `${CONSTANTS.KONG_API_BASE}/org/v1/cb/ext/search`, + kongSearchOrg: `${CONSTANTS.KONG_API_BASE}/org/v1/search`, + orgTypeListEndPoint: `${CONSTANTS.KONG_API_BASE}/data/v1/system/settings/get/orgTypeList`, } export const proxiesV8 = express.Router() +const _ = require('lodash') +const FILE_NOT_FOUND_ERR = 'File not found in the request' proxiesV8.get('/', (_req, res) => { res.json({ @@ -49,7 +57,9 @@ proxiesV8.post('/upload/*', (req, res) => { Authorization: CONSTANTS.SB_API_KEY, org: 'dopt', rootorg: 'igot', + // tslint:disable-next-line: all 'x-authenticated-user-token': extractUserToken(req), + // tslint:disable-next-line: all 'x-authenticated-userid': extractUserIdFromRequest(req), }, host: 'knowledge-mw-service', @@ -72,7 +82,7 @@ proxiesV8.post('/upload/*', (req, res) => { } ) } else { - res.send('File not found') + res.send(FILE_NOT_FOUND_ERR) } }) @@ -92,6 +102,7 @@ proxiesV8.post('/private/upload/*', (_req, _res) => { Authorization: CONSTANTS.SB_API_KEY, org: 'dopt', rootorg: 'igot', + // tslint:disable-next-line: all 'x-authenticated-user-token': extractUserToken(_req), 'x-authenticated-userid': extractUserIdFromRequest(_req), }, @@ -115,7 +126,7 @@ proxiesV8.post('/private/upload/*', (_req, _res) => { } ) } else { - _res.send('File not found') + _res.send(FILE_NOT_FOUND_ERR) } }) @@ -157,15 +168,24 @@ proxiesV8.use( proxyCreatorRoute(express.Router(), CONSTANTS.WEB_HOST_PROXY + '/web-hosted') ) +proxiesV8.use('/contentsearch/*', + // tslint:disable-next-line: max-line-length + proxyCreatorSunbirdSearch(express.Router(), `${CONSTANTS.KONG_API_BASE}/content/v1/search`) +) + proxiesV8.use('/sunbirdigot/*', // tslint:disable-next-line: max-line-length - proxyCreatorSunbirdSearch(express.Router(), `${CONSTANTS.SUNBIRD_PROXY_API_BASE}/composite/v1/search`) + proxyCreatorSunbirdSearch(express.Router(), `${CONSTANTS.KONG_API_BASE}/composite/v1/search`) ) proxiesV8.use('/v1/content/retire', proxyCreatorKnowledge(express.Router(), `${CONSTANTS.KNOWLEDGE_MW_API_BASE}`) ) +proxiesV8.use('/v1/content/copy/*', + proxyCreatorKnowledge(express.Router(), `${CONSTANTS.KNOWLEDGE_MW_API_BASE}`) +) + proxiesV8.use('/private/content/*', proxyContent(express.Router(), `${CONSTANTS.CONTENT_SERVICE_API_BASE}`) ) @@ -176,15 +196,57 @@ proxiesV8.use('/learnervm/private/content/*', proxiesV8.use('/content-progres/*', // tslint:disable-next-line: max-line-length - proxyCreatorSunbirdSearch(express.Router(), `${CONSTANTS.SUNBIRD_PROXY_API_BASE}/course/v1/content/state/update`) + proxyCreatorSunbirdSearch(express.Router(), `${CONSTANTS.KONG_API_BASE}/course/v1/content/state/update`) ) proxiesV8.use('/read/content-progres/*', // tslint:disable-next-line: max-line-length - proxyCreatorSunbirdSearch(express.Router(), `${CONSTANTS.SUNBIRD_PROXY_API_BASE}/course/v1/content/state/read`) + proxyCreatorSunbirdSearch(express.Router(), `${CONSTANTS.KONG_API_BASE}/course/v1/content/state/read`) ) -proxiesV8.use('/api/user/v2/read', - proxyCreatorToAppentUserId(express.Router(), `${CONSTANTS.SUNBIRD_PROXY_API_BASE}/user/v2/read/`) +proxiesV8.get(['/api/user/v2/read', '/api/user/v2/read/:id'], async (req, res) => { + const host = req.get('host') + const originalUrl = req.originalUrl + const lastIndex = originalUrl.lastIndexOf('/') + const subStr = originalUrl.substr(lastIndex).substr(1).split('-').length + let userId = extractUserIdFromRequest(req).split(':')[2] + if (subStr === 5 && (originalUrl.substr(lastIndex).substr(1))) { + userId = originalUrl.substr(lastIndex).substr(1) + } + + await axios({ + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), + }, + method: 'GET', + url: `${CONSTANTS.KONG_API_BASE}/user/v2/read/` + userId, + }).then((response) => { + if (response.data.responseCode === 'OK') { + res.status(200).send(response.data) + } else { + logError('User Read API.. Received non OK response.' + JSON.stringify(response.data)) + res.redirect(`https://${host}/public/logout?error=` + encodeURIComponent(JSON.stringify(response.data.params.errmsg))) + } + }).catch((err) => { + let errMsg = 'Internal Server Error' + if (err.response && err.response.data) { + logError('Received error for user read API. Error: ' + JSON.stringify(err.response.data)) + errMsg = err.response.data.params.errmsg + } + if (req.session) { + req.session.destroy((dErr) => { + logError('Failed to clear the session. ERROR: ' + JSON.stringify(dErr)) + }) + } + res.clearCookie('connect.sid', { path: '/' }) + res.redirect(`https://${host}/public/logout?error=` + encodeURIComponent(errMsg)) + }) +}) + +proxiesV8.use('/api/user/v5/read', + proxyCreatorToAppentUserId(express.Router(), `${CONSTANTS.KONG_API_BASE}/user/v5/read/`) ) proxiesV8.use([ @@ -194,7 +256,12 @@ proxiesV8.use([ ], proxyCreatorQML(express.Router(), `${CONSTANTS.KONG_API_BASE}`, '/action/') ) - +proxiesV8.use('/action/content/v3/updateReviewStatus', + proxyCreatorKnowledge(express.Router(), `${CONSTANTS.KONG_API_BASE}`) +) +proxiesV8.use('/action/content/v3/hierarchyUpdate', + proxyCreatorKnowledge(express.Router(), `${CONSTANTS.KONG_API_BASE}`) +) proxiesV8.use('/action/*', proxyCreatorKnowledge(express.Router(), `${CONSTANTS.KNOWLEDGE_MW_API_BASE}`) ) @@ -209,6 +276,120 @@ proxiesV8.use('/notification/*', proxyCreatorSunbird(express.Router(), `${CONSTANTS.KONG_API_BASE}`) ) +proxiesV8.post('/org/v1/search', async (req, res) => { + const roleData = lodash.get(req, 'session.userRoles') + const rootOrgId = lodash.get(req, 'session.rootOrgId') + let urlPath = API_END_POINTS.kongSearchOrg + if (roleData.includes('STATE_ADMIN')) { + req.body.request.filters.sbRootOrgId = rootOrgId + urlPath = API_END_POINTS.kongExtOrgSearch + } + const searchResponse = await axios({ + ...axiosRequestConfig, + data: req.body, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), + }, + method: 'POST', + url: urlPath, + }) + res.status(200).send(searchResponse.data) +}) + +proxiesV8.use('/org/*', + proxyCreatorSunbird(express.Router(), `${CONSTANTS.KONG_API_BASE}`) +) + +proxiesV8.use('/dashboard/*', + proxyCreatorSunbird(express.Router(), `${CONSTANTS.KONG_API_BASE}`) +) + +proxiesV8.post('/user/v1/bulkupload', (req, res) => { + if (req.files && req.files.data) { + const url = removePrefix('/proxies/v8', req.originalUrl) + const file: UploadedFile = req.files.data as UploadedFile + const formData = new FormData() + formData.append('file', Buffer.from(file.data), { + contentType: file.mimetype, + filename: file.name, + }) + let rootOrgId = _.get(req, 'session.rootOrgId') + if (!rootOrgId) { + rootOrgId = '' + } + let channel = _.get(req, 'session.channel') + if (!channel) { + channel = '' + } + formData.submit( + { + headers: { + // tslint:disable-next-line:max-line-length + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-orgid': rootOrgId, + 'x-authenticated-user-orgname': channel, + 'x-authenticated-user-token': extractUserToken(req), + 'x-authenticated-userid': extractUserIdFromRequest(req), + }, + host: 'kong', + path: url, + port: 8000, + }, + // tslint:disable-next-line: all + (err, response) => { + // tslint:disable-next-line: all + response.on('data', (data) => { + if (!err && (response.statusCode === 200 || response.statusCode === 201)) { + res.send(JSON.parse(data.toString('utf8'))) + } else { + res.send(data.toString('utf8')) + } + }) + if (err) { + res.send(err) + } + } + ) + } else { + res.send(FILE_NOT_FOUND_ERR) + } +}) + +proxiesV8.use('/user/*', + proxyCreatorSunbird(express.Router(), `${CONSTANTS.KONG_API_BASE}`) +) + +proxiesV8.use('/otp/*', + proxyCreatorSunbird(express.Router(), `${CONSTANTS.KONG_API_BASE}`) +) + +proxiesV8.use('/event/*', + proxyCreatorSunbird(express.Router(), `${CONSTANTS.KONG_API_BASE}`) +) + +proxiesV8.use('/searchBy/*', + proxyCreatorSunbird(express.Router(), `${CONSTANTS.KONG_API_BASE}`) +) + +proxiesV8.use('/staff/*', + proxyCreatorSunbird(express.Router(), `${CONSTANTS.KONG_API_BASE}`) +) + +proxiesV8.use('/budget/*', + proxyCreatorSunbird(express.Router(), `${CONSTANTS.KONG_API_BASE}`) +) + +proxiesV8.use('/orghistory/*', + proxyCreatorSunbird(express.Router(), `${CONSTANTS.KONG_API_BASE}`) +) + +proxiesV8.use('/storage/*', + proxyCreatorSunbird(express.Router(), `${CONSTANTS.KONG_API_BASE}`) +) + // proxiesV8.use('/api/framework/*', // // tslint:disable-next-line: max-line-length // proxyCreatorQML(express.Router(), `${CONSTANTS.KONG_API_BASE}`, '/api/') @@ -219,6 +400,50 @@ proxiesV8.use('/api/*', proxyCreatorSunbird(express.Router(), `${CONSTANTS.KONG_API_BASE}`) ) +proxiesV8.use('/dashboard/*', + // tslint:disable-next-line: max-line-length + proxyCreatorSunbird(express.Router(), `${CONSTANTS.KONG_API_BASE}`) +) + +proxiesV8.use('/wat/dashboard/*', + // tslint:disable-next-line: max-line-length + proxyCreatorSunbird(express.Router(), `${CONSTANTS.DASHBOARD_API_BASE}`) +) + +proxiesV8.get('/data/v1/system/settings/get/orgTypeList', async (req, res) => { + const roleData = lodash.get(req, 'session.userRoles') + logInfo('orgTypeList API call : Users Roles are...') + logInfo(roleData) + const response = await axios({ + ...axiosRequestConfig, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(req), + }, + method: 'GET', + url: API_END_POINTS.orgTypeListEndPoint, + }) + if (roleData.includes('STATE_ADMIN')) { + const hiddenList = ['CBC', 'CBP', 'STATE'] + const orgTypeListObj = JSON.parse(response.data.result.response.value) + const orgTypeList = orgTypeListObj.orgTypeList + // tslint:disable-next-line: no-any + orgTypeList.forEach((element: any) => { + if (hiddenList.includes(element.name)) { + element.isHidden = true + } + }) + orgTypeListObj.orgTypeList = orgTypeList + response.data.result.response.value = JSON.stringify(orgTypeListObj) + } + res.status(200).send(response.data) +}) + +proxiesV8.use('/data/*', + proxyCreatorSunbird(express.Router(), `${CONSTANTS.KONG_API_BASE}`) +) + proxiesV8.use('/assets/*', // tslint:disable-next-line: max-line-length proxyCreatorSunbird(express.Router(), `${CONSTANTS.KONG_API_BASE}`) @@ -230,7 +455,37 @@ proxiesV8.use('/assets/*', // ) proxiesV8.use('/discussion/*', // tslint:disable-next-line: max-line-length - proxyCreatorSunbird(express.Router(), `${CONSTANTS.DISCUSSION_HUB_MIDDLEWARE}`) + proxyCreatorSunbird(express.Router(), `${CONSTANTS.KONG_API_BASE}`) +) + +proxiesV8.use('/assessment/read/*', + // tslint:disable-next-line: max-line-length + proxyAssessmentRead(express.Router(), `${CONSTANTS.KONG_API_BASE}` + '/player/questionset/v1/hierarchy') +) + +proxiesV8.use('/question/read', + // tslint:disable-next-line: max-line-length + proxyQuestionRead(express.Router(), `${CONSTANTS.KONG_API_BASE}` + '/player/question/v1/list') +) + +proxiesV8.use('/cbp/question/list', + // tslint:disable-next-line: max-line-length + proxyQuestionRead(express.Router(), `${CONSTANTS.KONG_API_BASE}` + '/question/v1/list') +) + +proxiesV8.use('/questionset/*', + // tslint:disable-next-line: max-line-length + proxyCreatorSunbird(express.Router(), `${CONSTANTS.KONG_API_BASE}`) +) + +proxiesV8.use('/ratings/*', + // tslint:disable-next-line: max-line-length + proxyCreatorSunbird(express.Router(), `${CONSTANTS.KONG_API_BASE}`) +) + +proxiesV8.use('/moderatoradmin/*', + // tslint:disable-next-line: max-line-length + proxyCreatorSunbird(express.Router(), `${CONSTANTS.KONG_API_BASE}`) ) function removePrefix(prefix: string, s: string) { @@ -292,6 +547,8 @@ proxiesV8.post('/notifyContentState', async (req, res) => { id: `${CONSTANTS.NOTIFY_EMAIL_TEMPLATE_ID}`, params: { body: contentBody, + orgImageUrl: `${CONSTANTS.FRAC_API_BASE}` + '/img/logos/iGOT_logo.png', + orgName: 'iGOT Support Team', }, }, } @@ -308,8 +565,8 @@ proxiesV8.post('/notifyContentState', async (req, res) => { }) logInfo('Response -> ' + JSON.stringify(stateEmailResponse.data)) if (!stateEmailResponse.data.result.response) { - res.status(400).send('Failed to send content state notification...') + res.status(400).send(stateEmailResponse.data) } else { - res.status(200).send('Email sent successfully.') + res.status(200).send(stateEmailResponse.data) } }) diff --git a/src/publicApi_v8/googleOAuthHelper.ts b/src/publicApi_v8/googleOAuthHelper.ts new file mode 100644 index 00000000..c508936c --- /dev/null +++ b/src/publicApi_v8/googleOAuthHelper.ts @@ -0,0 +1,87 @@ +const { google } = require('googleapis') +import { CONSTANTS } from '../utils/env' +import { logError, logInfo } from '../utils/logger' +import { getKeyCloakClient } from './keycloakHelper' + +const redirectPath = '/apis/public/v8/google/callback' +const defaultScope = ['https://www.googleapis.com/auth/userinfo.email+https://www.googleapis.com/auth/userinfo.profile+openid'] + +// tslint:disable-next-line: no-any +export function createConnection(req: any) { + const redirect = `https://${req.get('host')}${redirectPath}` + return new google.auth.OAuth2(CONSTANTS.GOOGLE_CLIENT_ID, CONSTANTS.GOOGLE_CLIENT_SECRET, redirect) +} + +// tslint:disable-next-line: no-any +export function generateAuthUrl(req: any) { + const connection = createConnection(req) + return connection.generateAuthUrl({ + access_type: 'offline', + prompt: 'consent', + scope: defaultScope, + }) +} + +// tslint:disable-next-line: no-any +export async function getGoogleProfile(req: any) { + try { + const client = createConnection(req) + if (req.query.error === 'access_denied') { + throw new Error('GOOGLE_ACCESS_DENIED') + } + const { tokens } = await client.getToken(req.query.code) + client.setCredentials(tokens) + logInfo('userInformation being fetched from oauth2 api') + const oauth2 = await google.oauth2({ + auth: client, + version: 'v2', + }) + const googleProfileFetched = await oauth2.userinfo.get() || {} + logInfo('userInformation fetched -> ' + JSON.stringify(googleProfileFetched.data)) + return { + emailId: googleProfileFetched.data.email, + firstName: googleProfileFetched.data.given_name, + lastName: googleProfileFetched.data.family_name, + name: googleProfileFetched.data.name, + } + } catch (err) { + logError('Failed to get user profile: ' + JSON.stringify(err)) + } + return {} +} + +// tslint:disable-next-line: no-any +export async function getQueryParams(queryObj: any) { + return '?' + Object.keys(queryObj) + .map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(queryObj[key])}`) + .join('&') +} + +// tslint:disable-next-line: no-any +export async function createSession(emailId: string, req: any, res: any) { + // tslint:disable-next-line: no-any + let grant: { access_token: { token: any }; refresh_token: { token: any } } + const scope = 'offline_access' + const keycloakClient = getKeyCloakClient() + logInfo('login in progress') + // tslint:disable-next-line: no-any + try { + grant = await keycloakClient.grantManager.obtainDirectly(emailId, undefined, undefined, scope) + } catch (err) { + logError('googleOauthHelper: createSession failed') + throw new Error('unable to create session') + } + keycloakClient.storeGrant(grant, req, res) + req.kauth.grant = grant + return new Promise((resolve, reject) => { + // tslint:disable-next-line: no-any + keycloakClient.authenticated(req, (error: any) => { + if (error) { + logError('googleauthhelper:createSession error creating session') + reject('GOOGLE_CREATE_SESSION_FAILED') + } else { + resolve({access_token: grant.access_token.token, refresh_token: grant.refresh_token.token}) + } + }) + }) +} diff --git a/src/publicApi_v8/googleauth.ts b/src/publicApi_v8/googleauth.ts new file mode 100644 index 00000000..5c67477a --- /dev/null +++ b/src/publicApi_v8/googleauth.ts @@ -0,0 +1,82 @@ +import express from 'express' +import { CONSTANTS } from '../utils/env' +import { logError, logInfo } from '../utils/logger' +import { getGoogleProfile } from './googleOAuthHelper' +import { createUserWithMailId, fetchUserByEmailId, updateKeycloakSession } from './ssoUserHelper' + +export const googleAuth = express.Router() + +const googleScope = 'https://www.googleapis.com/auth/userinfo.email%20https://www.googleapis.com/auth/userinfo.profile' +const otherParams = '&prompt=consent&response_type=code&scope=' +const googleUrl = 'https://accounts.google.com/o/oauth2/v2/auth?' +const HTTPS_PROTO = 'https://' +const clientIdWithValue = 'client_id=' + CONSTANTS.GOOGLE_CLIENT_ID +const redirectUri = '&redirect_uri=' + +googleAuth.get(['/auth', '/authV2', '/testauth'], async (req, res) => { + let redirectUrlHost = HTTPS_PROTO + req.hostname + if (req.url.substring(req.url.lastIndexOf('/')) === '/auth') { + redirectUrlHost = redirectUrlHost + CONSTANTS.GOOGLE_AUTH_CALLBACK_URL + } else if (req.url.substring(req.url.lastIndexOf('/')) === '/authV2') { + redirectUrlHost = redirectUrlHost + '/public/google/sso' + } else if (req.url.substring(req.url.lastIndexOf('/')) === '/testauth') { + redirectUrlHost = redirectUrlHost + '/apis/public/v8/google/callback' + } + let oAuthParams = clientIdWithValue + redirectUri + redirectUrlHost + oAuthParams = oAuthParams + otherParams + googleScope + res.redirect(googleUrl + oAuthParams) +}) + +googleAuth.get('/callback', async (req, res) => { + const host = req.get('host') + let resRedirectUrl = `https://${host}/page/home` + try { + logInfo('Successfully received callback from google. Received query params -> ' + JSON.stringify(req.query)) + const googleProfile = await getGoogleProfile(req) + logInfo('Successfully got authenticated with google...') + logInfo('Email: ' + googleProfile.emailId) + let result: { errMessage: string, rootOrgId: string, userExist: boolean, } + result = await fetchUserByEmailId(googleProfile.emailId) + logInfo('isUserExist ? ' + result.userExist + 'rootOrgId: ? ' + result.rootOrgId + ', errorMessage ? ' + result.errMessage) + let isFirstTimeUser = false + if (result.errMessage === '') { + let createResult: { errMessage: string, userCreated: boolean, userId: string } + if (!result.userExist) { + createResult = await createUserWithMailId(googleProfile.emailId, + googleProfile.firstName, googleProfile.lastName) + if (createResult.errMessage !== '') { + result.errMessage = createResult.errMessage + } + isFirstTimeUser = true + } else { + logInfo('result.rootOrgId = ' + result.rootOrgId + ', XChannelId = ' + CONSTANTS.X_Channel_Id) + if (result.rootOrgId !== '' && result.rootOrgId === CONSTANTS.X_Channel_Id) { + isFirstTimeUser = true + } + } + + if (result.errMessage === '') { + let keycloakResult: { + access_token: string, errMessage: string, keycloakSessionCreated: boolean, refresh_token: string + } + keycloakResult = await updateKeycloakSession(googleProfile.emailId, req, res) + logInfo('Keycloak Session Details:: ' + JSON.stringify(keycloakResult)) + if (keycloakResult.errMessage !== '') { + result.errMessage = keycloakResult.errMessage + } else { + isFirstTimeUser = true + } + } + } + if (result.errMessage !== '') { + logInfo('Received error in processing... Error ' + result.errMessage) + resRedirectUrl = `https://${host}/public/logout?error=` + encodeURIComponent(JSON.stringify(result.errMessage)) + } else if (isFirstTimeUser) { + resRedirectUrl = `https://${host}/public/welcome` + } + } catch (err) { + logError('Failed to process callback event. Error: ' + JSON.stringify(err)) + resRedirectUrl = `https://${host}/public/logout?error=` + encodeURIComponent(JSON.stringify(err)) + } + res.redirect(resRedirectUrl) +}) diff --git a/src/publicApi_v8/keycloakHelper.ts b/src/publicApi_v8/keycloakHelper.ts new file mode 100644 index 00000000..731cefc9 --- /dev/null +++ b/src/publicApi_v8/keycloakHelper.ts @@ -0,0 +1,77 @@ +const keycloak = require('keycloak-connect') +const async = require('async') +import request from 'request' +import { getOAuthKeycloakConfig } from '../configs/keycloak.config' +import { getSessionConfig } from '../configs/session.config' +import { CONSTANTS } from '../utils/env' +import { logError, logInfo } from '../utils/logger' +import { PERMISSION_HELPER } from '../utils/permissionHelper' + +export function getKeyCloakClient() { + const sessionConfig = getSessionConfig() + const keycloakObj = new keycloak({ store: sessionConfig.store }, getOAuthKeycloakConfig()) + keycloakObj.authenticated = authenticated + keycloakObj.deauthenticated = deauthenticated + return keycloakObj +} + +// tslint:disable-next-line: no-any +const deauthenticated = async (reqObj: any) => { + logInfo('keycloakHelper::deauthenticated...') + const keyCloakPropertyName = 'keycloak-token' + if (reqObj.session.hasOwnProperty(keyCloakPropertyName)) { + const keycloakToken = reqObj.session[keyCloakPropertyName] + if (keycloakToken) { + const tokenObject = JSON.parse(keycloakToken) + const refreshToken = tokenObject.refresh_token + if (refreshToken) { + const host = reqObj.get('host') + const urlValue = `https://${host}` + '/auth/realms/' + CONSTANTS.KEYCLOAK_REALM + '/protocol/openid-connect/logout' + try { + request.post({ + form: { + client_id: CONSTANTS.KEYCLOAK_GOOGLE_CLIENT_ID, + client_secret: CONSTANTS.KEYCLOAK_GOOGLE_CLIENT_SECRET, + refresh_token: refreshToken, + }, + url: urlValue, + }) + } catch (err) { + // tslint:disable-next-line: no-console + console.log('Failed to call keycloak logout API ', err, '------', new Date().toString()) + } + } else { + logError('Not able to retrieve refresh_token value from Session. Logout process failed.') + } + } else { + logError('Not able to retrieve keycloak-token value from Session. Logout process failed.') + } + } else { + logError('Session does not have property with name: ' + keyCloakPropertyName) + } + delete reqObj.session.userRoles + delete reqObj.session.userId + reqObj.session.destroy() + logInfo(`${process.pid}: User Deauthenticated`) +} + +// tslint:disable-next-line: no-any +const authenticated = async (reqObj: any, next: any) => { + logInfo('keycloakHelper::authenticated...') + const postLoginRequest = [] + // tslint:disable-next-line: no-any + postLoginRequest.push((callback: any) => { + PERMISSION_HELPER.getCurrentUserRoles(reqObj, callback) + }) + + // tslint:disable-next-line: no-any + async.series(postLoginRequest, (err: any) => { + if (err) { + logError('error loggin in user', '------', new Date().toString()) + next(err, null) + } else { + logInfo(`${process.pid}: User authenticated`, '------', new Date().toString()) + next(null, 'loggedin') + } + }) +} diff --git a/src/publicApi_v8/parichayAuth.ts b/src/publicApi_v8/parichayAuth.ts new file mode 100644 index 00000000..7432e887 --- /dev/null +++ b/src/publicApi_v8/parichayAuth.ts @@ -0,0 +1,103 @@ +import axios from 'axios' +import express from 'express' +import { axiosRequestConfig } from '../configs/request.config' +import { CONSTANTS } from '../utils/env' +import { getCurrnetExpiryTime } from '../utils/jwtHelper' +import { logError, logInfo } from '../utils/logger' +import { createUserWithMailId, fetchUserByEmailId, updateKeycloakSession } from './ssoUserHelper' + +export const parichayAuth = express.Router() + +parichayAuth.get('/auth', async (req, res) => { + logInfo('Received host : ' + req.hostname) + const redirectUrl = 'https://' + req.hostname + CONSTANTS.PARICHAY_AUTH_CALLBACK_URL + let oAuthParams = 'client_id=' + CONSTANTS.PARICHAY_CLIENT_ID + oAuthParams = oAuthParams + '&redirect_uri=' + redirectUrl + oAuthParams = oAuthParams + '&response_type=code&scope=user_details' + oAuthParams = oAuthParams + '&code_challenge=' + CONSTANTS.PARICHAY_CODE_CHALLENGE + oAuthParams = oAuthParams + '&code_challenge_method=S256' + const parichayUrl = CONSTANTS.PARICHAY_AUTH_URL + '?' + oAuthParams + res.redirect(parichayUrl) +}) + +parichayAuth.get('/callback', async (req, res) => { + const host = req.get('host') + if (!req.query.code) { + res.redirect(`https://${host}/public/logout?error=` + encodeURIComponent('Failed to login in Parichay. Code param is missing.')) + return + } + let resRedirectUrl = `https://${host}/page/home` + try { + const redirectUrl = 'https://' + req.hostname + CONSTANTS.PARICHAY_AUTH_CALLBACK_URL + const tokenResponse = await axios({ + ...axiosRequestConfig, + data: { + client_id: CONSTANTS.PARICHAY_CLIENT_ID, + client_secret: CONSTANTS.PARICHAY_CLIENT_SECRET, + code: decodeURIComponent(req.query.code), + // tslint:disable-next-line: max-line-length + code_verifier: CONSTANTS.PARICHAY_CODE_VERIFIER, + grant_type: 'authorization_code', + redirect_uri: redirectUrl, + }, + method: 'POST', + url: CONSTANTS.PARICHAY_TOKEN_URL, + }) + if (req.session) { + req.session.parichayToken = tokenResponse.data + req.session.cookie.expires = new Date(getCurrnetExpiryTime(tokenResponse.data.access_token)) + } else { + logError('Failed to set parichay token in req session. Session not available...') + } + const userDetailResponse = await axios({ + ...axiosRequestConfig, + headers: { + Authorization: tokenResponse.data.access_token, + }, + method: 'GET', + url: CONSTANTS.PARICHAY_USER_DETAILS_URL, + }) + + let result: { errMessage: string, rootOrgId: string, userExist: boolean, } + let isFirstTimeUser = false + result = await fetchUserByEmailId(userDetailResponse.data.loginId) + if (result.errMessage === '') { + let createResult: { errMessage: string, userCreated: boolean, userId: string } + if (!result.userExist) { + logInfo('Sunbird User does not exist for email: ' + userDetailResponse.data.loginId) + createResult = await createUserWithMailId(userDetailResponse.data.loginId, + userDetailResponse.data.FirstName, userDetailResponse.data.LastName) + if (createResult.errMessage !== '') { + result.errMessage = createResult.errMessage + } + isFirstTimeUser = true + } else { + logInfo('result.rootOrgId = ' + result.rootOrgId + ', XChannelId = ' + CONSTANTS.X_Channel_Id) + if (result.rootOrgId !== '' && result.rootOrgId === CONSTANTS.X_Channel_Id) { + isFirstTimeUser = true + } + } + if (result.errMessage === '') { + let keycloakResult: { + access_token: string, errMessage: string, keycloakSessionCreated: boolean, refresh_token: string + } + keycloakResult = await updateKeycloakSession(userDetailResponse.data.loginId, req, res) + if (keycloakResult.errMessage !== '') { + result.errMessage = keycloakResult.errMessage + } else { + isFirstTimeUser = true + } + } + } + if (result.errMessage !== '') { + logInfo('Received error from user search. ') + resRedirectUrl = `https://${host}/public/logout?error=` + encodeURIComponent(JSON.stringify(result.errMessage)) + } else if (isFirstTimeUser) { + resRedirectUrl = `https://${host}/public/welcome` + } + } catch (err) { + logError('Failed to process callback API.. error: ' + JSON.stringify(err)) + resRedirectUrl = `https://${host}/public/logout?error=` + encodeURIComponent('Internal Server Error. Please contact administrator.') + } + res.redirect(resRedirectUrl) +}) diff --git a/src/publicApi_v8/publicApiV8.ts b/src/publicApi_v8/publicApiV8.ts index dbbc8e61..bb5844e3 100644 --- a/src/publicApi_v8/publicApiV8.ts +++ b/src/publicApi_v8/publicApiV8.ts @@ -1,8 +1,7 @@ import express from 'express' import { CONSTANTS } from '../utils/env' import { proxyCreatorRoute } from '../utils/proxyCreator' -import { signup } from './signup' -import { publicTnc } from './tnc' +import { parichayAuth } from './parichayAuth' import { workallocationPublic } from './workallocationPublic' export const publicApiV8 = express.Router() @@ -16,6 +15,8 @@ publicApiV8.get('/', (_req, res) => { publicApiV8.use('/assets', proxyCreatorRoute(express.Router(), CONSTANTS.WEB_HOST_PROXY + '/web-hosted/web-client-public-assets')) -publicApiV8.use('/tnc', publicTnc) -publicApiV8.use('/signup', signup) publicApiV8.use('/workallocation', workallocationPublic) + +publicApiV8.use('/org/v1/list', proxyCreatorRoute(express.Router(), CONSTANTS.KONG_API_BASE + '/org/v1/list')) + +publicApiV8.use('/parichay', parichayAuth) diff --git a/src/publicApi_v8/ssoUserHelper.ts b/src/publicApi_v8/ssoUserHelper.ts new file mode 100644 index 00000000..68694b2a --- /dev/null +++ b/src/publicApi_v8/ssoUserHelper.ts @@ -0,0 +1,117 @@ +import axios from 'axios' +import { axiosRequestConfig } from '../configs/request.config' +import { CONSTANTS } from '../utils/env' +import { logError, logInfo } from '../utils/logger' +import { getKeyCloakClient } from './keycloakHelper' + +const API_END_POINTS = { + cbExtSignUpUser: `${CONSTANTS.KONG_API_BASE}/user/v1/ext/signup`, +} + +export async function fetchUserByEmailId(emailId: string) { + const sbUserSearchRes = await axios({ + ...axiosRequestConfig, + data: { request: { + fields : ['userId', 'status', 'channel', 'rootOrgId', 'organisations'], + filters: { email: emailId.toLowerCase() }, + } }, + method: 'POST', + url: CONSTANTS.LEARNER_SERVICE_API_BASE + '/private/user/v1/search', + }) + const result = { + errMessage : '', rootOrgId: '', userExist : false, + } + + if (sbUserSearchRes.data.responseCode.toUpperCase() === 'OK') { + if (sbUserSearchRes.data.result.response.count === 0) { + logInfo('user accound doesnot exist. returning false') + } else if (sbUserSearchRes.data.result.response.count === 1) { + const contentObj = sbUserSearchRes.data.result.response.content[0] + const status = contentObj.status + logInfo('user account exist. Data: ' + JSON.stringify(sbUserSearchRes.data) + ', Status: ' + status) + if (status === 1) { + logInfo('user account enabled. returning true') + result.userExist = true + result.rootOrgId = contentObj.rootOrgId + } else { + logInfo('user account is diabled. throwing error') + result.errMessage = 'Account Disabled. Please contact Admin.' + } + } else { + result.errMessage = 'More than one user account exists. Please contact Admin.' + } + } else { + logError('googleOauthHelper: fetchUserByEmailId failed' + JSON.stringify(sbUserSearchRes.data)) + result.errMessage = 'Failed to verify email exist. Internal Server Error.' + } + return Promise.resolve(result) +} + +export async function createUserWithMailId(emailId: string, firstNameStr: string, lastNameStr: string) { + const result = { + errMessage : '', userCreated : false, userId: '', + } + const signUpErr = 'SIGN_UP_ERR-' + let statusString = '' + const signUpResponse = await axios({ + ...axiosRequestConfig, + data: { + request: + { + email: emailId, + emailVerified: true, + firstName: firstNameStr, + lastName : lastNameStr, + } }, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + }, + method: 'POST', + url: API_END_POINTS.cbExtSignUpUser, + }) + statusString = signUpResponse.data.params.status + if (statusString.toUpperCase() !== 'SUCCESS') { + result.errMessage = signUpErr + 'FAILED_TO_CREATE_USER' + return Promise.resolve(result) + } + result.userCreated = true + result.userId = signUpResponse.data.result.userId + return Promise.resolve(result) +} + +// tslint:disable-next-line: no-any +export async function updateKeycloakSession(emailId: string, req: any, res: any) { + const scope = 'offline_access' + const keycloakClient = getKeyCloakClient() + // tslint:disable-next-line: no-any + let grant: { access_token: { token: any }; refresh_token: { token: any } } + const result = { + access_token: '', errMessage : '', keycloakSessionCreated: false, refresh_token: '', + } + try { + grant = await keycloakClient.grantManager.obtainDirectly(emailId, undefined, undefined, scope) + keycloakClient.storeGrant(grant, req, res) + req.kauth.grant = grant + const userId = req.kauth.grant.access_token.content.sub.split(':') + req.session.userId = userId[userId.length - 1] + logInfo('userId ::', userId, '------', new Date().toString()) + req.session.keycloakClientId = CONSTANTS.KEYCLOAK_GOOGLE_CLIENT_ID + req.session.keycloakClientSecret = CONSTANTS.KEYCLOAK_GOOGLE_CLIENT_SECRET + result.access_token = grant.access_token.token + result.refresh_token = grant.refresh_token.token + result.keycloakSessionCreated = true + // tslint:disable-next-line: no-any + keycloakClient.authenticated(req, (error: any) => { + logInfo('ssoUserHelper::keycloakClient::authenticated..') + if (error) { + logError('googleauthhelper:createSession error creating session') + result.errMessage = 'GOOGLE_CREATE_SESSION_FAILED' + } + }) + return Promise.resolve(result) + } catch (err) { + logError('googleOauthHelper: createSession failed. Error: ' + JSON.stringify(err)) + result.errMessage = 'FAILED_TO_CREATE_KEYCLOAK_SESSION' + } + return Promise.resolve(result) +} diff --git a/src/server.ts b/src/server.ts index e1461538..76c634e5 100644 --- a/src/server.ts +++ b/src/server.ts @@ -21,6 +21,8 @@ import { logInfo, logSuccess } from './utils/logger' const cookieParser = require('cookie-parser') const healthcheck = require('express-healthcheck') +import { apiWhiteListLogger, isAllowed } from './utils/apiWhiteList' + function haltOnTimedOut(req: Express.Request, _: Express.Response, next: NextFunction) { if (!req.timedout) { next() @@ -37,8 +39,21 @@ export class Server { protected app = express() private keycloak?: CustomKeycloak private constructor() { + if (CONSTANTS.CORS_ENVIRONMENT === 'dev') { + this.app.use(cors({origin: 'https://local.igot-dev.in:3000', credentials: true})) + } else { + this.app.use(cors()) + } + const sessionConfig = getSessionConfig() + this.app.use(expressSession(sessionConfig)) + this.app.use(express.urlencoded({ extended: false, limit: '50mb' })) + this.app.use(express.json({ limit: '50mb' })) this.setCookie() - this.setKeyCloak() + this.app.all('*', apiWhiteListLogger()) + if (CONSTANTS.PORTAL_API_WHITELIST_CHECK === 'true') { + this.app.all('*', isAllowed()) + } + this.setKeyCloak(sessionConfig) this.authoringProxies() this.configureMiddleware() this.servePublicApi() @@ -69,10 +84,8 @@ export class Server { private configureMiddleware() { this.app.use(connectTimeout('240s')) this.app.use(compression()) - this.app.use(express.urlencoded({ extended: false, limit: '50mb' })) - this.app.use(express.json({ limit: '50mb' })) this.app.use(fileUpload()) - this.app.use(cors()) + // this.app.use(cors()) this.app.use('/healthcheck', healthcheck({ healthy() { return { everything: 'is ok' } @@ -95,7 +108,7 @@ export class Server { ) // TODO: See what needs to be logged this.app.use((req, _, next) => { - logInfo(`Worker ${process.pid} : ${req.url}`) + logInfo(`Server:ConfigureMiddleWare:: Worker ${process.pid} : ${req.url}`) next() }) this.app.use(morgan('dev')) @@ -116,10 +129,9 @@ export class Server { ) this.app.use(haltOnTimedOut) } - private setKeyCloak() { - const sessionConfig = getSessionConfig() + // tslint:disable-next-line: no-any + private setKeyCloak(sessionConfig: any) { this.keycloak = new CustomKeycloak(sessionConfig) - this.app.use(expressSession(sessionConfig)) this.app.use(this.keycloak.middleware) } @@ -152,9 +164,15 @@ export class Server { } private resetCookies() { this.app.use('/reset', (_req, res) => { - logInfo('==========================\nCLEARING RES COOKIES') - res.clearCookie('connect.sid') - res.status(200).send() + logInfo('CLEARING RES COOKIES') + res.clearCookie('connect.sid', { path: '/' }) + const host = _req.get('host') + let redirectUrl = '/public/logout' + logInfo('Reset Cookies... received host value ' + host) + if (host === `${CONSTANTS.KARMAYOGI_PORTAL_HOST}`) { + redirectUrl = '/public/home' + } + res.redirect(redirectUrl) }) } } diff --git a/src/static-data/degrees.json b/src/static-data/degrees.json index a2db558e..516f7d14 100644 --- a/src/static-data/degrees.json +++ b/src/static-data/degrees.json @@ -119,7 +119,6 @@ "Bachelor of Science in Athletic Training", "Bachelor of Science in Biology", "Bachelor of Science in Biomedical Engineering", - "Bachelor of Science in Bible", "Bachelor of Science in Business Administration", "Bachelor of Science in Business Administration - Computer Application", "Bachelor of Science in Business Administration - Economics", @@ -200,7 +199,15 @@ "Bachelor of Music in Theory", "Bachelor of Music in Music Education", "Bachelor of Science in Veterinary Technology", - "Bachelor of Science in military and strategic studies" + "Bachelor of Science in military and strategic studies", + "Bachelor of Education - Special Education", + "Bachelor in Prosthetics & Orthotics", + "Bachelor in Audiology and Speech Language Pathology", + "Bachelor in Rehabilitation Science", + "Shastri/Shastri(Hons.)", + "Shiksha Shastri", + "Fazil", + "Afzal-Ul-Ulma" ], "postGraduations": [ "Master of Accountancy", @@ -383,4 +390,4 @@ "Doctor of Veterinary Medicine", "Doctor of Radio oncology" ] -} \ No newline at end of file +} diff --git a/src/static-data/designation.json b/src/static-data/designation.json index 4863e422..d0a24adf 100644 --- a/src/static-data/designation.json +++ b/src/static-data/designation.json @@ -1,27 +1,35 @@ { "designations": [ - "Secretary", + "AD(OL)", "Additional Secretary", - "Joint Secretary", + "Assistant Director (English Shorthand and Typ", + "Assistant Director Office Management", + "Assistant Section Officer (ASO)", + "DD(Cost)", + "DD(OL)", + "Deputy Secretary (iGOT-ISTM)", + "Deputy Director (Peripatetic Training)", "Director", + "Director (Coordination)", + "Director( Admin and GA)", + "Director (External assistance and internation", + "Director Vigilance", "DS", - "PSO", - "Sr. PPS", - "Under Secretary", - "DD(Cost)", - "PPS", "JD(OL)", - "DD(OL)", - "AD(OL)", - "SO", - "PS", - "Assistant Section Officer (ASO)", + "Joint Secretary", + "Junior Secretariat Assistant (JSA)", + "Junior Translation Officer (JTO)", "Personal Assistant (PA)", + "PS", + "PSO", + "PPS", + "Secretary", + "Senior Secretariat Assistant (SSA)", "Senior Translation Officer (STO)", - "Junior Translation Officer (JTO)", + "SO", + "Sr. PPS", "Stenographer Grade 'C'", - "Senior Secretariat Assistant (SSA)", - "Junior Secretariat Assistant (JSA)" + "Under Secretary" ], "gradePay": [ "1", @@ -54,4 +62,4 @@ "28", "29" ] -} \ No newline at end of file +} diff --git a/src/static-data/govtOrg.json b/src/static-data/govtOrg.json index 394f717a..ab89f08f 100644 --- a/src/static-data/govtOrg.json +++ b/src/static-data/govtOrg.json @@ -233,6 +233,9 @@ "Central Engineering Service", "Central Electrical. & Mechanical Engineering Service", "Central Architect Service.", - "Central Water Engineering Service" + "Central Water Engineering Service", + "Central Secretariat Service (CSS)", + "Central Secretariat Stenographer's Service (CSSS)", + "Armed Forces Head Quarters Civil Service (AFHQCS)" ] } \ No newline at end of file diff --git a/src/static-data/nationality.json b/src/static-data/nationality.json index a13ef62b..d4c73c49 100644 --- a/src/static-data/nationality.json +++ b/src/static-data/nationality.json @@ -1,7 +1,7 @@ { "nationalities": [ { - "name": "India", + "name": "Indian", "countryCode": "+91" }, { @@ -785,4 +785,4 @@ "countryCode": "+263" } ] -} \ No newline at end of file +} diff --git a/src/utils/apiWhiteList.ts b/src/utils/apiWhiteList.ts new file mode 100644 index 00000000..6e3c0582 --- /dev/null +++ b/src/utils/apiWhiteList.ts @@ -0,0 +1,385 @@ +const _ = require('lodash') +const uuidv1 = require('uuid/v1') +const { pathToRegexp } = require('path-to-regexp') +const dateFormat = require('dateformat') + +import { NextFunction, Request, Response } from 'express' +import { CONSTANTS } from './env' +import { logError, logInfo } from './logger' +import { ROLE } from './roles' +import { API_LIST } from './whitelistApis' + +/** + * @param { String } REQ_URL - Request URL + * @returns { Boolean } - Return boolean value based on exclude path criteria + */ +// tslint:disable-next-line: no-any +const checkIsStaticRoute = (REQ_URL: any) => { + const excludePath = [ + '.md', + '.js', + '.js.map', + '.ico', + '.ttf', + '.woff2', + '.woff', + '.eot', + '.svg', + '.gif', + '.png', + '.html', + '/dist/', + '/streaming/', + '/resourcebundles/', + '/assets/', + '/content-plugins/', + '/editors/', + '/public/', + ] + // tslint:disable-next-line: no-any + return _.some(excludePath, (path: any) => _.includes(REQ_URL, path)) +} + +const shouldAllow = (req: Request) => { + // Ignore static routes + return req.path === '/' || checkIsStaticRoute(req.path) +} + +/** + * @description + * Set of methods which checks for certain condition on URL + * @since release-3.1.0 + */ +const urlChecks = { + // tslint:disable-next-line: no-any + PARAM_EQUALITY_CHECK: async (resolve: any, reject: any, req: Request, checksParams: any, REQ_URL: any) => { + if (_.get(checksParams, 'checks')) { + // tslint:disable-next-line: no-any + const ownerChecks: any[] = [] + // tslint:disable-next-line: no-any + checksParams.checks.forEach((ownerCheckObj: any) => { + ownerChecks.push(new Promise((res, rej) => { + const _checkFor = _.get(ownerCheckObj, 'entity') + if (_checkFor && typeof urlChecks[_checkFor] === 'function') { + urlChecks[_checkFor](res, rej, req, ownerCheckObj, REQ_URL) + } + })) + }) + try { + await Promise.all(ownerChecks) + .then((_pSuccess) => { + resolve() + }) + .catch((pError) => { + return reject(pError) + }) + } catch (error) { + return reject() + } + } else { + return reject('Owner check validation failed.') + } + }, + // tslint:disable-next-line: no-any + ROLE_CHECK: (resolve: any, reject: any, req: Request, rolesForURL: any, REQ_URL: any) => { + const roleData = _.get(req, 'session.userRoles') + const data = (roleData) ? roleData : [] + logInfo('Portal_API_WHITELIST : Middleware for URL [ ' + REQ_URL + ' ]') + if (_.includes(rolesForURL, 'ALL') && data.length > 0) { + resolve() + } else if (_.intersection(rolesForURL, data).length > 0) { + resolve() + } else { + return reject('User doesn\'t have appropriate roles') + } + }, + // tslint:disable-next-line: no-any + SCOPE_CHECK : (resolve: any, reject: any, req: Request, rolesForURL: any, REQ_URL: any) => { + logInfo('Portal_API_WHITELIST_SCOPE_CHECK : Middleware for URL [ ' + REQ_URL + ' ]') + const orgData = (_.get(req, 'session.orgs')) ? _.get(req, 'session.orgs') : [] + const orgId = (_.get(req, 'query.orgId')) ? _.get(req, 'query.orgId') : '' + if (_.isEmpty(orgId) || _.isEmpty(orgData)) { + return reject('User doesn\'t have appropriate organisation for scope check 1') + } + // tslint:disable-next-line: no-any + let scopeRoles: any = [] + // tslint:disable-next-line: no-any + orgData.forEach((element: any) => { + if (orgId === element.organisationId) { + scopeRoles = element.roles + } + }) + + if (_.isEmpty(scopeRoles)) { + return reject('User doesn\'t have appropriate organisation for scope check') + } + + if (_.includes(rolesForURL, 'ALL') && scopeRoles.length > 0) { + resolve() + } else if (_.intersection(rolesForURL, scopeRoles).length > 0) { + resolve() + } else { + return reject('User doesn\'t have appropriate roles') + } + }, + // Callback to `PARAM_EQUALITY_CHECK` promise object + // tslint:disable-next-line: no-any + __adminCheck__userId: (resolve: any, reject: any, req: any, ownerCheckObj: any, _REQ_URL: any) => { + try { + const _sessionUserId = _.get(req, 'session.userId') + const _reqUserId = _.get(ownerCheckObj, 'params') ? _.get(req, ownerCheckObj.params) : _.get(req, 'body.userId') + const _sessionRole = _.get(req, 'session.userRoles') + if (_.includes(_sessionRole, ROLE.MDO_ADMIN)) { + resolve() + } else { + if (_sessionUserId === _reqUserId) { + resolve() + } else { + return reject('Mismatch in user id verification. Session UserId [ ' + _sessionUserId + + ' ] is not an admin or does not match with request body UserId [ ' + _reqUserId + ' ]') + } + } + } catch (error) { + return reject('User id validation failed.') + } + }, + // Callback to `PARAM_EQUALITY_CHECK` promise object + // tslint:disable-next-line: no-any + __param__equality: (resolve: any, reject: any, req: any, ownerCheckObj: any, _REQ_URL: any) => { + try { + const comparedWith = _.get(ownerCheckObj, 'session') ? _.get(req, ownerCheckObj.session) : null + const comparedFrom = _.get(ownerCheckObj, 'requestbody') ? _.get(req, ownerCheckObj.requestbody) : null + + if ((_.isArray(comparedWith) && _.isArray(comparedFrom)) && (_.intersection(comparedWith, comparedFrom).length > 0)) { + resolve() + } else if (_.isArray(comparedWith) && (_.includes(comparedWith, comparedFrom))) { + resolve() + } else if (_.isArray(comparedFrom) && (_.includes(comparedFrom, comparedWith))) { + resolve() + } else if (comparedWith === comparedFrom) { + resolve() + } else { + return reject('Mismatch in param validation') + } + } catch (error) { + return reject('User id validation failed.') + } + }, +} + +/** + * @param {Object} req - Request Object + * @param {Object} res - Response Object + * @param {Function} next - Function for next middleware + * @param {Array} checksToExecute - Array of methods (checks; defined in urlChecks object) + * @description + * 1. Array of methods executed by promise + * 2. On success; API is allowed + * 3. On error; 403 Forbidden response is sent + * @since release-3.1.0 + */ +// tslint:disable-next-line: no-any +const executeChecks = async (req: Request, res: Response , next: NextFunction, checksToExecute: any = []) => { + try { + // tslint:disable-next-line: no-any + await (Promise as any).allSettled(checksToExecute) + // tslint:disable-next-line: no-any + .then((pSuccess: any) => { + if (pSuccess) { + const _isRejected = _.find(pSuccess, {status: 'rejected'}) + if (_isRejected) { + throw new Error(_isRejected.reason) + } else { + next() + } + } else { + throw new Error('API whitelisting validation failed') + } + }) + // tslint:disable-next-line: no-any + .catch((pError: any) => { + logError(pError) + respond403(req, res) + }) + } catch (error) { + // tslint:disable-next-line: no-console + console.log('ERROR --', error) + respond403(req, res) + } +} + +/** + * @param {Object} req - Request Object + * @param {Object} res - Response Object + * @description - Generic function to return 403 Forbidden response + * @since release-3.1.0 + */ +const respond403 = (req: Request, res: Response) => { + const REQ_URL = req.path + const err = ({ msg: 'API WHITELIST :: Forbidden access for API [ ' + REQ_URL + ' ]', url: REQ_URL }) + logError(err.msg) + res.status(403) + res.send( + { + id: 'api.error', + ver: '1.0', + // tslint:disable-next-line: object-literal-sort-keys + ts: dateFormat(new Date(), 'yyyy-mm-dd HH:MM:ss:lo'), + params: + { + resmsgid: uuidv1(), + // tslint:disable-next-line: object-literal-sort-keys + msgid: null, + status: 'failed', + err: 'FORBIDDEN_ERROR', + errmsg: 'Forbidden: API WHITELIST Access is denied', + }, + responseCode: 'FORBIDDEN', + result: {}, + }) + res.end() +} + +const respond419 = (req: Request, res: Response) => { + const REQ_URL = req.path + if (_.includes(REQ_URL, '/reset')) { + res.sendFile('../../index.html') + } else { + const err = ({ msg: 'API WHITELIST :: Unauthorized access for API [ ' + REQ_URL + ' ]', url: REQ_URL }) + logError(err.msg) + res.status(419) + res.setHeader('location', redirectToLogin(req)) + res.send( + { + id: 'api.error', + ver: '1.0', + // tslint:disable-next-line: object-literal-sort-keys + ts: dateFormat(new Date(), 'yyyy-mm-dd HH:MM:ss:lo'), + params: + { + resmsgid: uuidv1(), + // tslint:disable-next-line: object-literal-sort-keys + msgid: null, + status: 'failed', + err: 'UNAUTHORIZED_ERROR', + errmsg: 'UNAUTHORIZED: Access is denied', + }, + responseCode: 'UNAUTHORIZED', + redirectUrl: redirectToLogin(req), + result: {}, + }) + } + + res.end() +} + +/** + * @description - Function to check whether + * 1. Incoming API is whitelisted (or) not + * 2. If API does not exists then request is terminated and 403 Forbidden response is sent + * 3. If incoming API is present in API_LIST (whitelistApis); then check URL pattern matching + * 4. Refer `API_LIST` and execute the checks defined + * @since release-3.1.0 + */ +export const isAllowed = () => { + // tslint:disable-next-line: only-arrow-functions + return function(req: Request, res: Response, next: NextFunction) { + let REQ_URL = req.path + if (CONSTANTS.PORTAL_API_WHITELIST_CHECK === 'true') { + if (shouldAllow(req) || _.includes(REQ_URL, '/resource')) { + next() + } else { + + // Pattern match for URL + // tslint:disable-next-line: no-any + _.forEach(API_LIST.URL_PATTERN, (url: any) => { + const regExp = pathToRegexp(url) + if (regExp.test(REQ_URL)) { + REQ_URL = url + return false + } + return true + }) + // Is API whitelisted ? + if (_.get(API_LIST.URL, REQ_URL)) { + const URL_RULE_OBJ = _.get(API_LIST.URL, REQ_URL) + // tslint:disable-next-line: no-any + const checksToExecute: any[] = [] + + // Iterate for checks defined for API and push to array + if (_.isEmpty(URL_RULE_OBJ.checksNeeded)) { + next() + } else { + const urlChecksNeeded = URL_RULE_OBJ.checksNeeded + // tslint:disable-next-line: no-any + urlChecksNeeded.forEach((CHECK: any) => { + // tslint:disable-next-line: no-shadowed-variable + checksToExecute.push(new Promise((res, rej) => { + if (_.get(URL_RULE_OBJ, CHECK) && typeof urlChecks[CHECK] === 'function') { + urlChecks[CHECK](res, rej, req, URL_RULE_OBJ[CHECK], REQ_URL) + } + })) + }) + executeChecks(req, res, next, checksToExecute) + } + } else { + // If API is not whitelisted + logInfo('Portal_API_WHITELIST: URL not whitelisted') + respond403(req, res) + } + } + } else { + next() + } + } +} +const redirectToLogin = (req: Request) => { + const redirectUrl = 'protected/v8/resource/' + return `https://${req.get('host')}/${redirectUrl}` // 'http://localhost:3003/protected/v8/user/resource/' + // tslint:disable-next-line: no-commented-code + // return 'http://localhost:3003/protected/v8/user/resource/' +} + +const validateAPI = (req: Request, res: Response, next: NextFunction) => { + let REQ_URL_ORIGINAL = req.path + // tslint:disable-next-line: no-any + _.forEach(API_LIST.URL_PATTERN, (url: any) => { + const regExp = pathToRegexp(url) + if (regExp.test(REQ_URL_ORIGINAL)) { + REQ_URL_ORIGINAL = url + return false + } + return true + }) + if (_.get(API_LIST.URL, REQ_URL_ORIGINAL)) { + next() + } else { + // If API is not whitelisted + logInfo('Portal_API_WHITELIST_LOGGER: URL not whitelisted') + respond403(req, res) + } +} +/** + * This function is used for checking whether + */ +export function apiWhiteListLogger() { + return (req: Request, res: Response, next: NextFunction) => { + if (req.path === '/' || checkIsStaticRoute(req.path)) { + next() + return + } + const REQ_URL = req.path + if (!_.includes(REQ_URL, '/resource') && (req.session)) { + if (!('userRoles' in req.session) || (('userRoles' in req.session) && (req.session.userRoles.length === 0))) { + logError('Portal_API_WHITELIST_LOGGER: User needs to authenticated themselves', '------', new Date().toString()) + respond419(req, res) + } else { + // Pattern match for URL + logInfo('In WhilteList Call========' + REQ_URL, '------', new Date().toString()) + validateAPI(req, res, next) + } + } else { + next() + } + } +} diff --git a/src/utils/custom-keycloak.ts b/src/utils/custom-keycloak.ts index 540bb01a..2f07feec 100644 --- a/src/utils/custom-keycloak.ts +++ b/src/utils/custom-keycloak.ts @@ -1,9 +1,12 @@ import * as express from 'express' import expressSession from 'express-session' import keycloakConnect from 'keycloak-connect' +import request from 'request' import { getKeycloakConfig } from '../configs/keycloak.config' import { CONSTANTS } from './env' -import { logInfo } from './logger' +import { logError, logInfo } from './logger' +import { PERMISSION_HELPER } from './permissionHelper' +const async = require('async') const composable = require('composable-middleware') @@ -28,7 +31,7 @@ export class CustomKeycloak { const middleware = composable( keycloak.middleware({ admin: '/callback', - logout: '/logout', + logout: '/reset', }) ) middleware(req, res, next) @@ -45,21 +48,118 @@ export class CustomKeycloak { } }) } + return (this.multiTenantKeycloak.get(req.hostname) || this.multiTenantKeycloak.get(domain) || this.multiTenantKeycloak.get('common')) as keycloakConnect } - authenticated = () => { - logInfo(`${process.pid}: User authenticated`) + // tslint:disable-next-line: no-any + authenticated = (reqObj: any, next: any) => { + logInfo('Step 3: authenticated function', '------', new Date().toString()) + try { + const userId = reqObj.kauth.grant.access_token.content.sub.split(':') + reqObj.session.userId = userId[userId.length - 1] + logInfo('userId ::', userId, '------', new Date().toString()) + } catch (err) { + logError('userId conversation error' + reqObj.kauth.grant.access_token.content.sub, '------', new Date().toString()) + } + const postLoginRequest = [] + // tslint:disable-next-line: no-any + postLoginRequest.push((callback: any) => { + PERMISSION_HELPER.getCurrentUserRoles(reqObj, callback) + }) + + // tslint:disable-next-line: no-any + async.series(postLoginRequest, (err: any) => { + if (err) { + logError('error loggin in user', '------', new Date().toString()) + next(err, null) + } else { + logInfo(`${process.pid}: User authenticated`, '------', new Date().toString()) + next(null, 'loggedin') + } + }) } - deauthenticated = () => { + + // tslint:disable-next-line: no-any + deauthenticated = (reqObj: any) => { + const keyCloakPropertyName = 'keycloak-token' + if (reqObj.session.hasOwnProperty(keyCloakPropertyName)) { + const keycloakToken = reqObj.session[keyCloakPropertyName] + if (keycloakToken) { + const tokenObject = JSON.parse(keycloakToken) + const refreshToken = tokenObject.refresh_token + if (refreshToken) { + const host = reqObj.get('host') + const urlValue = `https://${host}` + '/auth/realms/' + CONSTANTS.KEYCLOAK_REALM + '/protocol/openid-connect/logout' + const formData: Record = { + client_id: 'portal', + refresh_token: refreshToken, + } + + if (reqObj.session.hasOwnProperty('keycloakClientId') && (reqObj.session.keycloakClientId !== '')) { + formData.client_id = reqObj.session.keycloakClientId + formData.client_secret = reqObj.session.keycloakClientSecret + } + logInfo('formData used in logout: ' + JSON.stringify(formData)) + try { + request.post({ + form: formData, + url: urlValue, + }) + } catch (err) { + // tslint:disable-next-line: no-console + console.log('Failed to call keycloak logout API ', err, '------', new Date().toString()) + } + + if (reqObj.session.parichayToken) { + logInfo('Parichay login found... trying to logout from Parichay...') + try { + request.get({ + headers: { + Authorization: reqObj.session.parichayToken.access_token, + }, + url: CONSTANTS.PARICHAY_REVOKE_URL, + }, (err, res, body) => { + if (err) { + logError('Received error when calling Parichay logout... ') + logError(JSON.stringify(err)) + } + if (res) { + logInfo('Received response from Parichay logout... ') + logInfo(JSON.stringify(res.body)) + } + if (body) { + logInfo('Received body from Parichay logout...') + logInfo(JSON.stringify(body)) + } + }) + } catch (err) { + // tslint:disable-next-line: no-console + console.log('Failed to call parichay revoke API ', err, '------', new Date().toString()) + } + } + } else { + logError('Not able to retrieve refresh_token value from Session. Logout process failed.') + } + } else { + logError('Not able to retrieve keycloak-token value from Session. Logout process failed.') + } + } else { + logError('Session does not have property with name: ' + keyCloakPropertyName) + } + delete reqObj.session.userRoles + delete reqObj.session.userId + delete reqObj.session.keycloakClientId + delete reqObj.session.keycloakClientSecret + reqObj.session.destroy() logInfo(`${process.pid}: User Deauthenticated`) } protect = (req: express.Request, res: express.Response, next: express.NextFunction) => { const keycloak = this.getKeyCloakObject(req) - keycloak.protect()(req, res, next) + return keycloak.protect()(req, res, next) } private generateKeyCloak( diff --git a/src/utils/discussionHub-helper.ts b/src/utils/discussionHub-helper.ts index b88f3a95..fef4ed5c 100644 --- a/src/utils/discussionHub-helper.ts +++ b/src/utils/discussionHub-helper.ts @@ -21,23 +21,15 @@ export function getWriteApiAdminUID(): number { } // tslint:disable-next-line: no-any -export async function getUserUID(wid: any) { +export async function getUserUIDBySession(req: any) { // tslint:disable-next-line: no-any - const userPresent = await getUserByUsername(wid).catch(async (_err: any) => { - // If user is not already present in nodeBB NodeBB DiscussionHub - logError(usrNotFound) - return Promise.reject(new Error(usrNotFound)) - }) - if (userPresent && userPresent.uid) { - logInfo('user found - uid: ', userPresent.uid) - return Promise.resolve(userPresent.uid) - } + return req.session.uid } // tslint:disable-next-line: no-any -export async function getUserSlug(wid: any) { +export async function getUserSlug(req: any, wid: any) { // tslint:disable-next-line: no-any - const userPresent = await getUserByUsername(wid).catch(async (_err: any) => { + const userPresent = await getUserByUsername(req, wid).catch(async (_err: any) => { // If user is not already present in nodeBB NodeBB DiscussionHub logError(usrNotFound) return Promise.reject(new Error('User not found')) diff --git a/src/utils/env.ts b/src/utils/env.ts index a990330d..996bdd5e 100644 --- a/src/utils/env.ts +++ b/src/utils/env.ts @@ -1,5 +1,5 @@ const env = process.env -const HTTPS_HOST = env.HTTPS_HOST || 'http://localhost' +const HTTPS_HOST = env.HTTPS_HOST || 'https://igot-dev.in' export const CONSTANTS = { ACCESS_CONTROL_API_BASE: env.ACCESS_CONTROL_API_BASE || env.SBEXT_API_BASE, ANALYTICS_TIMEOUT: env.ANALYTICS_TIMEOUT || 10000, @@ -15,11 +15,14 @@ export const CONSTANTS = { CASSANDRA_KEYSPACE: env.CASSANDRA_KEYSPACE || 'bodhi', CASSANDRA_PASSWORD: env.CASSANDRA_PASSWORD || '', CASSANDRA_USERNAME: env.CASSANDRA_USERNAME || '', + CLUSTER_THREAD: env.CLUSTER_THREAD || 1, CONTENT_API_BASE: env.CONTENT_API_BASE || 'http://localhost:5903', CONTENT_HIERARCHY: env.CONTENT_HIERARCHY || 'http://localhost:5903/hierarchy', CONTENT_META_FETCH_API_BASE: env.CONTENT_META_FETCH_API_BASE || 'http://localhost:5906', CONTENT_STORE_DEVELOPMENT_BASE: '', + CORS_ENVIRONMENT: env.CORS_ENVIRONMENT || 'prod', COUNTER: 'http://localhost:5903', + DASHBOARD_API_BASE: env.DASHBOARD_API_BASE || 'https://igot-dashboard.tarento.com/api', DEFAULT_ORG: env.DEFAULT_ORG || 'dopt', DEFAULT_ROOT_ORG: env.DEFAULT_ROOT_ORG || 'igot', ES_BASE: env.ES_BASE || 'http://localhost:9200', @@ -46,12 +49,14 @@ export const CONSTANTS = { // tslint:disable-next-line: object-literal-sort-keys KC_NEW_USER_DEFAULT_PWD: env.KC_NEW_USER_DEFAULT_PWD || 'User@123', KEYCLOAK_REALM: env.KEYCLOAK_REALM || 'sunbird', - KEYCLOAK_SESSION_TTL: 24 * 60 * 60 * 1000, + // tslint:disable-next-line: ban + KEYCLOAK_SESSION_TTL: parseInt(env.KEYCLOAK_SESSION_TTL || '0', 10) || 24 * 60 * 60 * 1000, KHUB_CLIENT_SECRET: env.KHUB_CLIENT_SECRET || 'axc123', KHUB_GRAPH_DATA: env.KHUB_GRAPH_DATA || 'http://localhost:3016', KHUB_SEARCH_BASE: env.KHUB_SEARCH_BASE || 'http://localhost:3014', KNOWLEDGE_MW_API_BASE: env.KNOWLEDGE_MW_API_BASE || 'http://knowledge-mw-service:5000', - KONG_API_BASE: env.KONG_API_BASE || 'http://kong:8000', + KONG_API_BASE: env.KONG_API_BASE || 'https://igot-dev.in/api', + PORTAL_CASSANDRA_CONSISTENCY_LEVEL: env.PORTAL_CASSANDRA_CONSISTENCY_LEVEL || 'one', POST_ASSESSMENT_BASE: env.POST_ASSESSMENT_BASE || 'http://localhost.com', POST_ASSESSMENT_CLIENT_ID: env.POST_ASSESSMENT_CLIENT_ID || '', POST_ASSESSMENT_CLIENT_SECRET: env.POST_ASSESSMENT_CLIENT_SECRET || @@ -62,7 +67,7 @@ export const CONSTANTS = { LIKE_API_BASE: env.LIKE_API_BASE || env.SB_EXT_API_BASE_2, MULTI_TENANT_KEYCLOAK: env.MULTI_TENANT_KEYCLOAK || - 'igot;https://igot-sunbird.idc.tarento.com/auth;sunbird', + 'igot,https://igot-dev.in/auth,sunbird', NAVIGATOR_JSON_HOST: env.NAVIGATOR_JSON_HOST || 'http://localhost:3007/web-hosted/navigator/json', NODE_API_BASE: env.NODE_API_BASE || 'http://localhost:5001', @@ -78,12 +83,15 @@ export const CONSTANTS = { DISCUSSION_HUB_WRITE_API_UID: env.DISCUSSION_HUB_WRITE_API_UID || 1, OPEN_SABER_USER_REGISTRY_BASE: env.OPEN_SABER_USER_REGISTRY_BASE || 'http://localhost:8005', PID_API_BASE: env.PID_API_BASE || 'http://localhost:9200', + PORTAL_API_WHITELIST_CHECK: env.PORTAL_API_WHITELIST_CHECK || 'true', + PORTAL_REALM: env.PORTAL_REALM || 'sunbird', PLAYLISTV1_API_BASE: env.PLAYLISTV1_API_BASE || env.SBEXT_API_BASE_2, PLAYLIST_API_BASE: env.PLAYLIST_API_BASE || env.SBEXT_API_BASE, // tslint:disable-next-line:ban PORTAL_PORT: parseInt(env.PORTAL_PORT + '', 10) || 3003, PREFERENCE_API_BASE: env.PREFERENCE_API_BASE || env.SB_EXT_API_BASE_4, PROGRESS_API_BASE: env.PROGRESS_API_BASE || env.SB_EXT_API_BASE_2, + PM_DASHBOARD_API_BASE: env.PM_DASHBOARD_API_BASE || 'https://pm.igot-dev.in', RATING_API_BASE: env.RATING_API_BASE || env.SB_EXT_API_BASE_2 || 'http://localhost:7001', RECOMMENDATION_API_BASE: env.RECOMMENDATION_API_BASE || env.SBEXT_API_BASE, RESET_PASSWORD: '', @@ -123,14 +131,14 @@ export const CONSTANTS = { COHORTS_API_BASE: env.COHORTS_API_BASE || env.SB_EXT_API_BASE_2, CONTENT_SOURCE_API_BASE: env.CONTENT_SOURCE_API_BASE || env.SB_EXT_API_BASE_2, CONTINUE_LEARNING_API_BASE: env.CONTINUE_LEARNING_API_BASE || env.SB_EXT_API_BASE_2, - FRAC_API_BASE: env.FRAC_API_BASE || 'https://igot-frac-dev.tarento.com', + FRAC_API_BASE: env.FRAC_API_BASE || 'https://frac.igot-dev.in', NETWORK_SERVICE_BACKEND: env.NETWOR_SERVICE_API_BASE || 'http:localhost:7001', CONTENT_VALIDATION_API_BASE: env.CONTENT_VALIDATION_API_BASE || 'http://localhost:6590', PROFANITY_SERVICE_API_BASE: env.PROFANITY_SERVICE_API_BASE || 'http://localhost:4001', DISCUSSION_CATEGORY_LIST: env.DISCUSSION_CATEGORY_LIST || 'cid[]=5&cid[]=6&cid[]=8&cid[]=9&cid[]=10&cid[]=11&cid[]=12&cid[]=13', WORKFLOW_HANDLER_SERVICE_API_BASE: env.WORKFLOW_HANDLER_SERVICE_API_BASE || 'http://localhost:5099', SUNBIRD_PROXY_URL: env.SUNBIRD_PROXY_URL || 'https://igot-sunbird.idc.tarento.com/apis/proxies/v8/action', - SUNBIRD_PROXY_API_BASE: env.SUNBIRD_PROXY_API_BASE || 'https://igot-sunbird.idc.tarento.com/api', + SUNBIRD_PROXY_API_BASE: env.SUNBIRD_PROXY_API_BASE || 'https://igot-dev.in/api', SCORING_SERVICE_API_BASE: env.SCORING_SERVICE_API_BASE || 'http://localhost:7014', // tslint:disable-next-line:max-line-length SB_API_KEY: env.SB_API_KEY || 'bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJRekw4VVA1dUtqUFdaZVpMd1ZtTFJvNHdqWTg2a2FrcSJ9.TPjV0xLacSbp3FbJ7XeqHoKFN35Rl4YHx3DZNN9pm0o', @@ -144,11 +152,29 @@ export const CONSTANTS = { NOTIFY_PUBLIST_FAILED: 'The content #contentLink which sent for publish requires few more changes. Please contact the publishers.', NOTIFY_PUBLISH_COMPLETED_BODY: 'The content #contentLink is successfully published.' + ' The content will be available for the users in few hours.', - NOTIFY_EMAIL_TEMPLATE_ID: 'emailtemplate', + NOTIFY_EMAIL_TEMPLATE_ID: 'contentEmailTemplate', CONTENT_SERVICE_API_BASE: env.CONTENT_SERVICE_API_BASE || 'http://content-service:9000', VM_LEARNING_SERVICE_URL: env.VM_LEARNING_SERVICE_URL, // tslint:disable-next-line: max-line-length CERT_AUTH_TOKEN: 'bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJRekw4VVA1dUtqUFdaZVpMd1ZtTFJvNHdqWTg2a2FrcSJ9.TPjV0xLacSbp3FbJ7XeqHoKFN35Rl4YHx3DZNN9pm0o', + // tslint:disable-next-line: max-line-length + KEYCLOAK_PUBLIC_KEY: 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoBa+pmsxpPhGED2/zexM/PL+rLv2YnLCbX2agY2fllucCvnPNmWRTyg8L+qgkJBpHuhcHqXEFTfBm2WCe4yke+0LnGi6SGsCJTrc2Sh+Lgo/L9r1lr7uOoD8BHE6ywnbHG2ok7qyomCTD9LpG1WXFk4T3WUH9+gN2vm77s3YJz2yfo2UlMd1Dp9nWZhfwB1vwJLuRHnqEKkSH8M2K8SFRdpgOyLdM9fprr7Ebgr7SWdoAy2q3mUONSmDsftKDeEWjr6MXGTATfbMfKE3GFqddMjFHkmvh42aM+RlU3N2xo2msF8M2sYF6YlIDkED+9h+y0QROJjQlBr774GAd06I0wIDAQAB', + KARMAYOGI_PORTAL_HOST: env.KARMAYOGI_PORTAL_HOST || 'igot-dev.in', + GOOGLE_CLIENT_ID: env.GOOGLE_CLIENT_ID || 'googleClientId', + GOOGLE_CLIENT_SECRET: env.GOOGLE_CLIENT_SECRET || 'googleClientSecret', + PARICHAY_CLIENT_ID: env.PARICHAY_CLIENT_ID || 'parichayClientId', + PARICHAY_CLIENT_SECRET: env.PARICHAY_CLIENT_SECRET || 'parichayClientSecret', + KEYCLOAK_GOOGLE_CLIENT_ID: env.KEYCLOAK_GOOGLE_CLIENT_ID || 'keycloakGoogleClientId', + KEYCLOAK_GOOGLE_CLIENT_SECRET: env.KEYCLOAK_GOOGLE_CLIENT_SECRET || 'keycloakGoogleClientSecret', + PORTAL_AUTH_SERVER_URL: env.PORTAL_AUTH_SERVER_URL || 'https://igot-dev.in/auth', + PARICHAY_CODE_CHALLENGE: env.PARICHAY_CODE_CHALLENGE || 'parichayCodeChallenge', + PARICHAY_CODE_VERIFIER: env.PARICHAY_CODE_VERIFIER || 'parichayCodeVerfifier', + PARICHAY_AUTH_URL: env.PARICHAY_AUTH_URL || 'parichayAuthUrl', + PARICHAY_AUTH_CALLBACK_URL: env.PARICHAY_AUTH_CALLBACK_URL || '/apis/public/v8/parichay/callback', + PARICHAY_TOKEN_URL: env.PARICHAY_TOKEN_URL || 'parichayTokenUrl', + PARICHAY_USER_DETAILS_URL: env.PARICHAY_USER_DETAILS_URL || 'parichayUserDetailsUrl', + GOOGLE_AUTH_CALLBACK_URL: env.GOOGLE_AUTH_CALLBACK_URL || '/apis/public/v8/google/callback', + PARICHAY_REVOKE_URL: env.PARICHAY_REVOKE_URL || 'parichayRevokeUrl', } diff --git a/src/utils/fileLogger.ts b/src/utils/fileLogger.ts new file mode 100644 index 00000000..f556a345 --- /dev/null +++ b/src/utils/fileLogger.ts @@ -0,0 +1,21 @@ +'use strict' + +const fs = require('fs') +const fileFormat = () => { + let date = new Date().toISOString().substr(0, 10) + date = date.replace(/:/g, '_') + date = date.replace(/-/g, '_') + date = date.replace(/T/g, '_') + const name = date + '.log' + return process.cwd() + '/logs/' + name +} + +const logFile = fs.createWriteStream(fileFormat(), {flags : 'w'}) +export let pino = require('pino')({}, +{ + [Symbol.for('needsMetadata')]: true, + // tslint:disable-next-line: no-any + write(msg: any) { + logFile.write(msg) + }, +}) diff --git a/src/utils/jwtHelper.ts b/src/utils/jwtHelper.ts new file mode 100644 index 00000000..5182bf1b --- /dev/null +++ b/src/utils/jwtHelper.ts @@ -0,0 +1,33 @@ +import { CONSTANTS } from './env' + +const jwt = require('jsonwebtoken') + +// tslint:disable-next-line: no-any +export function getExpiryTime(accessToken: any) { + const jwtPayload = jwt.decode(accessToken) + if (jwtPayload && jwtPayload.exp) { + const diff = ((Math.floor(Date.now() / 1000)) - jwtPayload.exp) + if (diff > 0) { + return diff + } else { + return 0 + } + } + return 0 +} + +// tslint:disable-next-line: no-any +export function getCurrnetExpiryTime(accessToken: any) { + const jwtPayload = jwt.decode(accessToken) + if (jwtPayload && jwtPayload.exp) { + return jwtPayload.exp * 1000 + } else { + // return configured value for KEYCLOAK + return CONSTANTS.KEYCLOAK_SESSION_TTL + } +} + +// tslint:disable-next-line: no-any +export function decodeCode(accessToken: any) { + return jwt.decode(accessToken) +} diff --git a/src/utils/keycloak-user-creation.ts b/src/utils/keycloak-user-creation.ts index 783187a4..27963bc0 100644 --- a/src/utils/keycloak-user-creation.ts +++ b/src/utils/keycloak-user-creation.ts @@ -9,7 +9,7 @@ const CASSANDRA_KEYSPACE = CONSTANTS.CASSANDRA_KEYSPACE const defaultNewUserPassword = CONSTANTS.KC_NEW_USER_DEFAULT_PWD const cassandraClientOptions: cassandraDriver.ClientOptions = { - contactPoints: [CONSTANTS.CASSANDRA_IP], + contactPoints: getIPList(), keyspace: CASSANDRA_KEYSPACE, localDataCenter: 'datacenter1', queryOptions: { @@ -17,6 +17,10 @@ const cassandraClientOptions: cassandraDriver.ClientOptions = { }, } +function getIPList() { + return CONSTANTS.CASSANDRA_IP.split(',') +} + const keycloakConfig = { baseUrl: `${CONSTANTS.HTTPS_HOST}/auth`, realmName: CONSTANTS.KEYCLOAK_REALM, diff --git a/src/utils/message.ts b/src/utils/message.ts index 48d77780..3bb0f01d 100644 --- a/src/utils/message.ts +++ b/src/utils/message.ts @@ -1,4 +1,5 @@ export const ERROR = { + ERROR_NO_DEPT_DATA: 'Department details not available', ERROR_NO_ORG_DATA: 'ERROR_NO_ORG_DATA', GENERAL_ERR_MSG: 'Failed due to unknown reason', fetchErrorElasticSearch: 'ERROR_ELASTIC_SEARCH_CONNECTION', diff --git a/src/utils/permissionHelper.ts b/src/utils/permissionHelper.ts new file mode 100644 index 00000000..657b17b3 --- /dev/null +++ b/src/utils/permissionHelper.ts @@ -0,0 +1,131 @@ +const _ = require('lodash') +import axios from 'axios' +import request from 'request' +import { axiosRequestConfig } from '../configs/request.config' +import { CONSTANTS } from './env' +import { logError, logInfo } from './logger' +import { extractUserToken } from './requestExtract' + +export const PERMISSION_HELPER = { + // tslint:disable-next-line: no-any + setRolesData(reqObj: any, callback: any, body: any) { + logInfo('permission helper:: setRolesData function ', '------', new Date().toString()) + // tslint:disable-next-line: no-any + const userData: any = JSON.parse(body) + logInfo(JSON.stringify(userData)) + if (reqObj.session) { + reqObj.session.userId = userData.result.response.id ? userData.result.response.id : userData.result.response.userId + reqObj.session.userName = userData.result.response.userName + reqObj.session.firstName = userData.result.response.firstName + reqObj.session.lastName = userData.result.response.lastName + reqObj.session.userRoles = userData.result.response.roles + reqObj.session.orgs = userData.result.response.organisations + reqObj.session.rootOrgId = userData.result.response.rootOrgId + reqObj.session.channel = userData.result.response.channel + if (userData.result.response.hasOwnProperty('profileDetails') && + userData.result.response.profileDetails.hasOwnProperty('userRoles')) { + reqObj.session.userPositions = userData.result.response.profileDetails.userRoles + } else { + reqObj.session.userPositions = [] + } + if (!_.includes(reqObj.session.userRoles, 'PUBLIC')) { + reqObj.session.userRoles.push('PUBLIC') + } + this.createNodeBBUser(reqObj, callback) + // tslint:disable-next-line: no-any + // reqObj.session.save((error: any) => { + // if (error) { + // logError('reqObj.session.save error -- ', error) + // callback(error, null) + // } else { + // logInfo('Before calling createNodeBBUser', '------', new Date().toString()) + // this.createNodeBBUser(reqObj, callback) + // // callback(null, userData) + // } + // }) + } else { + callback('reqObj.session no session', null) + } + logInfo('permission helper:: setRolesData function end', '------', new Date().toString()) + }, + // tslint:disable-next-line: no-any + setNodeBBUID(reqObj: any, callback: any, body: any) { + logInfo('setNodeBBUID :: ', new Date().toString()) + // tslint:disable-next-line: no-any + const nodeBBData: any = body + if (reqObj.session) { + reqObj.session.uid = nodeBBData.data.result.userId.uid + logInfo('After appending uid to session', reqObj.session.uid) + } + // tslint:disable-next-line: no-any + reqObj.session.save((error: any) => { + if (error) { + logError('reqObj.session.save error -- ', error, '------', new Date().toString()) + callback(error, null) + } else { + // tslint:disable-next-line: no-console + console.log(`setNodeBBUID::Success of save -- reqObj.session ${new Date()}--- `) + callback(null, nodeBBData) + } + }) + }, + // tslint:disable-next-line: no-any + getCurrentUserRoles(reqObj: any, callback: any) { + logInfo('Step 3: getCurrentUserRoles', '------', new Date().toString()) + const userId = reqObj.session.userId + const readUrl = `${CONSTANTS.KONG_API_BASE}/user/v2/read/` + userId + const options = { + headers: { + Authorization: CONSTANTS.SB_API_KEY, + 'X-Channel-Id': CONSTANTS.X_Channel_Id, + 'x-authenticated-user-token': reqObj.kauth.grant.access_token.token, + 'x-authenticated-userid': userId, + }, + url: readUrl, + } + // tslint:disable-next-line: no-any + request.get(options, (err: any, _httpResponse: any, body: any) => { + if (body) { + // tslint:disable-next-line: no-console + logInfo('Success user/v2/read::', '------', new Date().toString()) + this.setRolesData(reqObj, callback, body) + } + if (err) { + logError('Making axios call to nodeBB ERROR -- ', err, '------', new Date().toString()) + callback(err, null) + } + }) + }, + // tslint:disable-next-line: no-any + async createNodeBBUser(reqObj: any, callback: any) { + const readUrl = `${CONSTANTS.KONG_API_BASE}/discussion/user/v1/create` + + // tslint:disable-next-line: no-commented-code + const nodebbPayload = { + username: reqObj.session.userName, + // tslint:disable-next-line: object-literal-sort-keys + identifier: reqObj.session.userId, + fullname: reqObj.session.firstName + ' ' + reqObj.session.lastName, + } + try { + const nodeBBResp = await axios({ + ...axiosRequestConfig, + data: { request: nodebbPayload }, + headers: { + Authorization: CONSTANTS.SB_API_KEY, + // tslint:disable-next-line: all + 'x-authenticated-user-token': extractUserToken(reqObj), + }, + method: 'POST', + url: readUrl, + }) + if (nodeBBResp) { + this.setNodeBBUID(reqObj, callback, nodeBBResp) + } + } catch (err) { + // tslint:disable-next-line: no-console + console.log('Making axios call to nodeBB ERROR -- ', err, '------', new Date().toString()) + callback(err, null) + } + }, +} diff --git a/src/utils/proxyCreator.ts b/src/utils/proxyCreator.ts index 172aa947..40b28820 100644 --- a/src/utils/proxyCreator.ts +++ b/src/utils/proxyCreator.ts @@ -1,29 +1,50 @@ import { Router } from 'express' import { createProxyServer } from 'http-proxy' -import { extractUserIdFromRequest, extractUserToken } from '../utils/requestExtract' +import { extractUserEmailFromRequest, extractUserIdFromRequest, extractUserToken } from '../utils/requestExtract' import { CONSTANTS } from './env' import { logInfo } from './logger' +const _ = require('lodash') + const proxyCreator = (timeout = 10000) => createProxyServer({ timeout, }) const proxy = createProxyServer({}) const PROXY_SLUG = '/proxies/v8' +const PROXY_SLUG_WAT = '/proxies/v8/wat' // tslint:disable-next-line: no-any proxy.on('proxyReq', (proxyReq: any, req: any, _res: any, _options: any) => { - proxyReq.setHeader('X-Channel-Id', CONSTANTS.X_Channel_Id) + // tslint:disable-next-line: no-duplicate-string + proxyReq.setHeader('X-Channel-Id', (_.get(req, 'session.rootOrgId')) ? _.get(req, 'session.rootOrgId') : CONSTANTS.X_Channel_Id) // tslint:disable-next-line: max-line-length proxyReq.setHeader('Authorization', CONSTANTS.SB_API_KEY) proxyReq.setHeader('x-authenticated-user-token', extractUserToken(req)) proxyReq.setHeader('x-authenticated-userid', extractUserIdFromRequest(req)) + let rootOrgId = '' + if (req.session.hasOwnProperty('rootOrgId')) { + rootOrgId = req.session.rootOrgId + } + proxyReq.setHeader('x-authenticated-user-orgid', rootOrgId) + let channel = '' + if (req.session.hasOwnProperty('channel')) { + channel = req.session.channel + } + proxyReq.setHeader('x-authenticated-user-orgname', channel) + proxyReq.setHeader('x-authenticated-user-nodebb-uid', req.session.uid) // condition has been added to set the session in nodebb req header - if (req.originalUrl.includes('/discussion') && !req.originalUrl.includes('/discussion/user/v1/create')) { - proxyReq.setHeader('Authorization', 'Bearer ' + req.session.nodebb_authorization_token) - } + /* tslint:disable-next-line */ + if (req.originalUrl.includes('/discussion') && !req.originalUrl.includes('/discussion/user/v1/create') && req.session) { + + if (req.body) { + req.body._uid = req.session.uid + } + // tslint:disable-next-line: no-console + console.log('REQ_URL_ORIGINAL discussion', proxyReq.path) - if (req.body) { + } + if (!req.originalUrl.includes('/storage/upload') && req.body) { const bodyData = JSON.stringify(req.body) proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData)) proxyReq.write(bodyData) @@ -32,12 +53,46 @@ proxy.on('proxyReq', (proxyReq: any, req: any, _res: any, _options: any) => { // tslint:disable-next-line: no-any proxy.on('proxyRes', (proxyRes: any, req: any, _res: any, ) => { - if (req.originalUrl.includes('/discussion/user/v1/create')) { - const nodebb_auth_token = proxyRes.headers.nodebb_auth_token - if (req.session) { - req.session.nodebb_authorization_token = nodebb_auth_token + // res.removeHeader('access-control-allow-origin') + delete proxyRes.headers['access-control-allow-origin'] + // write user session with roles + // if (req.originalUrl.includes('/user/v2/read')) { + // // tslint:disable-next-line: no-any + // proxyRes.on('data', (data: any) => { + // if ((proxyRes.statusCode === 200 || proxyRes.statusCode === 201)) { + // data = JSON.parse(data.toString('utf-8')) + // const roles = data.result.response.roles + // req.session.userId = data.result.response.id ? data.result.response.id : data.result.response.userId + // req.session.userName = data.result.response.userName + // req.session.userRoles = roles + // // console.log(req); + // // tslint:disable-next-line: only-arrow-functions + // req.session.save(function(error: string) { + // if (error) { + // // tslint:disable-next-line: no-console + // console.log(error) + // } + // }) + // } + // }) + // } + // tslint:disable-next-line: no-any + proxyRes.on('data', (data: any) => { + if (req.originalUrl.includes('/discussion/user/v1/create')) { + + if ((proxyRes.statusCode === 200 || proxyRes.statusCode === 201)) { + data = JSON.parse(data.toString('utf-8')) + // tslint:disable-next-line: no-console + console.log('_res==>', data) + req.session.uid = data.result.userId.uid + } + const nodebbToken = '722686c6-2a2e-4b22-addf-c427261fbdc6' + if (req.session) { + req.session.nodebb_authorization_token = nodebbToken + } } - } + }) + }) export function proxyCreatorRoute(route: Router, targetUrl: string, timeout = 10000): Router { @@ -91,13 +146,41 @@ export function proxyCreatorLearner(route: Router, targetUrl: string, _timeout = }) return route } - +// tslint:disable-next-line export function proxyCreatorSunbird(route: Router, targetUrl: string, _timeout = 10000): Router { route.all('/*', (req, res) => { - // tslint:disable-next-line: no-console console.log('REQ_URL_ORIGINAL proxyCreatorSunbird', req.originalUrl) - const url = removePrefix(`${PROXY_SLUG}`, req.originalUrl) + let url = '' + if (req.originalUrl.includes('/proxies/v8/wat')) { + url = removePrefix(`${PROXY_SLUG_WAT}`, req.originalUrl) + } else { + url = removePrefix(`${PROXY_SLUG}`, req.originalUrl) + } + + if (req.originalUrl.includes('/discussion') && !req.originalUrl.includes('/discussion/user/v1/create') && req.session) { + if (req.originalUrl.includes('?')) { + url = `${url}&_uid=${req.session.uid}` + } else { + url = `${url}?_uid=${req.session.uid}` + } + if (req.originalUrl.includes('/discussion/v2/topics')) { + req.body.email = extractUserEmailFromRequest(req) + } + // tslint:disable-next-line: no-console + console.log('REQ_URL_ORIGINAL proxyCreatorSunbird ======= discussion', url) + } + + if (req.originalUrl.includes('/dashboard') && !req.originalUrl.includes('/dashboard/analytics/getChartV2/Karmayogi') && req.session) { + if (req.originalUrl.includes('?')) { + url = `${url}&_uid=${_.get(req, 'session.rootOrgId')}` + } else { + url = `${url}?_uid=${_.get(req, 'session.rootOrgId')}` + } + // tslint:disable-next-line: no-console + console.log('REQ_URL_ORIGINAL proxyCreatorSunbird ======= dashboard analytics', url) + } + proxy.web(req, res, { changeOrigin: true, ignorePath: true, @@ -157,15 +240,19 @@ export function proxyCreatorSunbirdSearch(route: Router, targetUrl: string, _tim export function proxyCreatorToAppentUserId(route: Router, targetUrl: string, _timeout = 10000): Router { route.all('/*', (req, res) => { - const userId = extractUserIdFromRequest(req).split(':') - + const originalUrl = req.originalUrl + const lastIndex = originalUrl.lastIndexOf('/') + const subStr = originalUrl.substr(lastIndex).substr(1).split('-').length + let userId = extractUserIdFromRequest(req).split(':')[2] + if (subStr === 5 && (originalUrl.substr(lastIndex).substr(1))) { + userId = originalUrl.substr(lastIndex).substr(1) + } // tslint:disable-next-line: no-console console.log('REQ_URL_ORIGINAL proxyCreatorToAppentUserId', req.originalUrl) - proxy.web(req, res, { changeOrigin: true, ignorePath: true, - target: targetUrl + userId[userId.length - 1], + target: targetUrl + userId, // [userId.length - 1], }) }) return route @@ -213,3 +300,31 @@ export function proxyContentLearnerVM(route: Router, targetUrl: string, _timeout }) return route } + +export function proxyAssessmentRead(route: Router, targetUrl: string, _timeout = 10000): Router { + route.all('/*', (req, res) => { + let url = removePrefix(`${PROXY_SLUG}/assessment/read`, req.originalUrl) + url = targetUrl + url + '?hierarchy=detail' + // tslint:disable-next-line: no-console + console.log('REQ_URL_UPDATED proxyAssessmentRead', url) + proxy.web(req, res, { + changeOrigin: true, + ignorePath: true, + target: url, + }) + }) + return route +} + +export function proxyQuestionRead(route: Router, targetUrl: string, _timeout = 10000): Router { + route.all('/*', (req, res) => { + // tslint:disable-next-line: no-console + console.log('REQ_URL_UPDATED proxyAssessmentRead', targetUrl) + proxy.web(req, res, { + changeOrigin: true, + ignorePath: true, + target: targetUrl, + }) + }) + return route +} diff --git a/src/utils/requestExtract.ts b/src/utils/requestExtract.ts index 65872b15..c161f177 100644 --- a/src/utils/requestExtract.ts +++ b/src/utils/requestExtract.ts @@ -25,6 +25,16 @@ export const extractUserIdFromRequest = (req: IAuthorizedRequest): string => { } return (req.kauth && req.kauth.grant.access_token.content.sub) as string } + +export const extractUserId = (req: IAuthorizedRequest): string => { + const wid = req.header('wid') + if (wid) { + return wid + } + const userId = (req.kauth && req.kauth.grant.access_token.content.sub) as string + return userId.split(':')[2] +} + export const extractUserNameFromRequest = (req: IAuthorizedRequest) => (req.kauth && req.kauth.grant.access_token.content.name) as string @@ -45,9 +55,9 @@ export const extractUserToken = (req: IAuthorizedRequest) => { } export const extractAuthorizationFromRequest = (req: IAuthorizedRequest): string => { - const authorization = req.header('Authorization') - - return authorization as string + const token = req.kauth && req.kauth.grant.access_token.token + // Bearer is added as other areas are using split function to get the token + return 'Bearer ' + token } export const extractUserTokenFromRequest = (req: IAuthorizedRequest): string => { const xAuthorization = req.header('X-Authenticated-User-Token') diff --git a/src/utils/roles.ts b/src/utils/roles.ts new file mode 100644 index 00000000..f6a56a05 --- /dev/null +++ b/src/utils/roles.ts @@ -0,0 +1,21 @@ +// Valid Roles +export const ROLE = { + CBC_ADMIN: 'CBC_ADMIN', + CBC_MEMBER: 'CBC_MEMBER', + CBP_ADMIN: 'CBP_ADMIN', + CONTENT_CREATOR: 'CONTENT_CREATOR', + CONTENT_PUBLISHER: 'CONTENT_PUBLISHER', + CONTENT_REVIEWER: 'CONTENT_REVIEWER', + EDITOR: 'EDITOR', + FRAC_ACCESS_COMPENTENCY: 'FRAC_COMPETENCY_MEMBER', + FRAC_ADMIN: 'FRAC_ADMIN', + FRAC_COMPETENCY_REVIEWER: 'FRAC_COMPETENCY_REVIEWER', + FRAC_REVIEWER_ONE: 'FRAC_REVIEWER_L1', + FRAC_REVIEWER_TWO: 'FRAC_REVIEWER_L2', + IFU_MEMBER: 'IFU_MEMBER', + MDO_ADMIN: 'MDO_ADMIN', + PUBLIC: 'PUBLIC', + SPV_ADMIN: 'SPV_ADMIN', + STATE_ADMIN: 'STATE_ADMIN', + WAT_MEMBER: 'WAT_MEMBER', +} diff --git a/src/utils/whitelistApis.ts b/src/utils/whitelistApis.ts new file mode 100644 index 00000000..6c571d6b --- /dev/null +++ b/src/utils/whitelistApis.ts @@ -0,0 +1,2132 @@ +'use strict' +import { ROLE } from './roles' + +const CHECK = { + PARAM_EQUALITY_CHECK: 'PARAM_EQUALITY_CHECK', + ROLE: 'ROLE_CHECK', + SCOPE: 'SCOPE_CHECK', +} + +// All api list validations +export const API_LIST = { + URL: + { + // '/authApi/content/v3/create': { + // checksNeeded: [CHECK.ROLE], + // // tslint:disable-next-line: object-literal-sort-keys + // ROLE_CHECK: [ + // ROLE.PUBLIC, + // ], + // }, + // '/authApi/content/v3/read/:do_id': { + // checksNeeded: [CHECK.ROLE], + // // tslint:disable-next-line: object-literal-sort-keys + // ROLE_CHECK: [ + // ROLE.PUBLIC, + // ], + // }, + // '/authApi/content/v3/update/:do_id': { + // checksNeeded: [CHECK.ROLE], + // // tslint:disable-next-line: object-literal-sort-keys + // ROLE_CHECK: [ + // ROLE.PUBLIC, + // ], + // }, + '/protected/v8/user/details': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/user/profileDetails/test': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ROLE.CONTENT_CREATOR, + ], + }, + // tslint:disable-next-line: object-literal-sort-keys + '/protected/v8/resource/': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/api/user/v2/read': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, 'ALL', + ], + }, + '/proxies/v8/api/user/v2/read/:id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, 'ALL', + ], + }, + '/proxies/v8/user/v1/updateLogin': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, 'ALL', + ], + }, + '/proxies/v8/event/v4/read/:do_id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/event/v4/publish/:do_id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ], + }, + '/proxies/v8/event/v4/create': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ], + }, + '/proxies/v8/user/v1/read/:id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/sunbirdigot/read': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/sunbirdigot/search': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/contentsearch/search': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/read/content-progres/:do_id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/discussion/recent': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/content-progres/:do_id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/discussion/user/v1/create': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/discussion/topic/:id/:slug': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/learner/course/v1/user/enrollment/list/:id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/learner/certreg/v1/certs/validate': { + checksNeeded: [], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [], + }, + '/proxies/v8/action/content/v3/hierarchy/:do_id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/action/content/v3/read/:do_id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/action/content/v3/reject/:do_id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_REVIEWER, + ROLE.CONTENT_PUBLISHER, + ], + }, + '/proxies/v8/discussion/forum/v2/read': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/discussion/forum/v3/create': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/discussion/category/list': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/discussion/category/:id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/discussion/forum/tags': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/discussion/user/:id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/action/content/v3/hierarchyUpdate': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_PUBLISHER, + ROLE.CONTENT_REVIEWER, + ], + }, + '/proxies/v8/action/content/v3/hierarchy/update': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ROLE.EDITOR, + ROLE.CONTENT_PUBLISHER, + ROLE.CONTENT_REVIEWER, + ], + }, + '/proxies/v8/action/content/v3/create': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ROLE.MDO_ADMIN, + ], + }, + '/proxies/v8/dashboard/analytics/getDashboardConfig/Karmayogi/:comp': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/dashboard/analytics/getDashboardsForProfile/Karmayogi': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/dashboard/analytics/getChartV2/Karmayogi': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/wat/dashboard/getDashboardConfig/Karmayogi/overview': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/upload/action/content/v3/upload/:do_id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ROLE.EDITOR, + ROLE.MDO_ADMIN, + ], + }, + '/proxies/v8/v1/content/retire': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ROLE.EDITOR, + ], + }, + '/proxies/v8/action/content/v3/copy/:do_id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ], + }, + '/proxies/v8/action/content/v3/updateReviewStatus/:do_id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_REVIEWER, + ROLE.CONTENT_PUBLISHER, + ], + }, + '/proxies/v8/action/content/v3/review/:do_id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ROLE.CONTENT_REVIEWER, + ROLE.CONTENT_PUBLISHER, + ], + }, + '/proxies/v8/action/content/v3/publish/:do_id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_PUBLISHER, + ], + }, + '/proxies/v8/action/content/v3/update/:do_id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ROLE.EDITOR, + ROLE.CONTENT_REVIEWER, + ROLE.CONTENT_PUBLISHER, + ], + }, + '/proxies/v8/data/v1/system/settings/get/orgTypeList': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CBC_ADMIN, + ROLE.MDO_ADMIN, + ROLE.SPV_ADMIN, + ROLE.STATE_ADMIN, + ], + }, + '/proxies/v8/org/v1/search': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/user/private/v1/assign/role': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ROLE.SPV_ADMIN, + ROLE.CBP_ADMIN, + ROLE.STATE_ADMIN, + ROLE.CONTENT_CREATOR, + ], + }, + '/proxies/v8/user/v1/search': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/org/v1/read': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CBC_ADMIN, + ROLE.MDO_ADMIN, + ROLE.SPV_ADMIN, + ROLE.STATE_ADMIN, + ], + }, + '/proxies/v8/org/v1/profile/read': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CBC_ADMIN, + ROLE.MDO_ADMIN, + ROLE.SPV_ADMIN, + ROLE.STATE_ADMIN, + ], + }, + '/proxies/v8/org/v1/profile/patch': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CBC_ADMIN, + ROLE.MDO_ADMIN, + ROLE.SPV_ADMIN, + ROLE.STATE_ADMIN, + ], + }, + '/proxies/v8/org/v1/update': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CBC_ADMIN, + ROLE.MDO_ADMIN, + ROLE.SPV_ADMIN, + ROLE.STATE_ADMIN, + ], + }, + '/proxies/v8/user/v1/block': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ROLE.SPV_ADMIN, + ROLE.CBP_ADMIN, + ROLE.STATE_ADMIN, + ROLE.CONTENT_CREATOR, + ], + }, + '/proxies/v8/user/v1/unblock': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ROLE.SPV_ADMIN, + ROLE.CBP_ADMIN, + ROLE.STATE_ADMIN, + ROLE.CONTENT_CREATOR, + ], + }, + '/proxies/v8/data/v1/system/settings/get/orgTypeConfig': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CBC_ADMIN, + ROLE.MDO_ADMIN, + ROLE.SPV_ADMIN, + ROLE.STATE_ADMIN, + ], + }, + '/proxies/v8/discussion/tags': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/org/v1/create': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CBC_ADMIN, + ROLE.MDO_ADMIN, + ROLE.SPV_ADMIN, + ROLE.STATE_ADMIN, + ], + }, + '/proxies/v8/learnervm/private/content/v3/publish/:do_id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_PUBLISHER, + ], + }, + '/proxies/v8/learnervm/private/content/v3/review/:do_id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_REVIEWER, + ], + }, + '/proxies/v8/discussion/v2/topics': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/discussion/v2/topics/:id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/discussion/tags/:tag': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/discussion/user/:userKey/bookmarks': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/discussion/user/:userKey/bookmark': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/discussion/user/:userKey/upvoted': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/discussion/user/:userKey/downvoted': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/discussion/categories': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/user/v1/autocomplete/:key': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/user/v1/migrate': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CBC_ADMIN, + ROLE.MDO_ADMIN, + ROLE.SPV_ADMIN, + ROLE.STATE_ADMIN, + ], + }, + '/proxies/v8/user/private/v1/migrate': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CBC_ADMIN, + ROLE.MDO_ADMIN, + ROLE.SPV_ADMIN, + ROLE.STATE_ADMIN, + ], + }, + '/proxies/v8/user/private/v1/assign/role/userrole': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/discussion/v2/posts/:id/vote': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/discussion/v2/posts/:id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/discussion/v2/posts/:id/bookmark': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/discussion/popular': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/discussion/moderation/consumer': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/discussion/moderation/producer': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/learnervm/private/content/v3/retire/': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ROLE.EDITOR, + ], + }, + '/proxies/v8/private/content/v3/update/:do_id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ROLE.EDITOR, + ], + }, + '/proxies/v8/notifyContentState': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/connections/connections/recommended/userDepartment': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/discussionHub/categories/:cid/:slug?/:tid?': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/discussionHub/topics/recent': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/cohorts/:cohortType/:contentId': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ROLE.EDITOR, + ROLE.PUBLIC, + ], + }, + '/protected/v8/user/content/like': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/user/telemetry': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/scrom/get/:id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/user/progress/:contentId': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/user/rating/:contentId': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/user/progress': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/user/history/continue': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/portal/departmentType/': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CBC_ADMIN, + ROLE.SPV_ADMIN, + ROLE.MDO_ADMIN, + ], + }, + '/protected/v8/portal/spv/department': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.SPV_ADMIN, + ], + }, + '/protected/v8/portal/spv/deptAction/': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.SPV_ADMIN, + ], + }, + '/protected/v8/user/roles/getUsersV2': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/portal/spv/mydepartment': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.SPV_ADMIN, + ], + }, + '/protected/v8/portal/mdo/mydepartment': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ], + }, + '/protected/v8/user/profileDetails/createUser': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ROLE.SPV_ADMIN, + ROLE.CBP_ADMIN, + ROLE.CONTENT_CREATOR, + ROLE.STATE_ADMIN, + ], + }, + '/protected/v8/user/profileRegistry/getUserRegistryByUser/:id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/user/profileRegistry/createUserRegistryV2': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/user/profileRegistry/createUserRegistry': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/portal/deptAction': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CBC_ADMIN, + ROLE.MDO_ADMIN, + ROLE.SPV_ADMIN, + ], + }, + '/protected/v8/workflowhandler/historyByApplicationId/:applicationId': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ROLE.WAT_MEMBER, + ROLE.CBC_ADMIN, + ROLE.SPV_ADMIN, + ROLE.STATE_ADMIN, + ], + }, + '/protected/v8/user/autocomplete/:query': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/portal/spv/deptAction/userrole': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.SPV_ADMIN, + ], + }, + '/protected/v8/user/preference': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/workflowhandler/applicationsSearch': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ROLE.WAT_MEMBER, + ROLE.CBC_ADMIN, + ROLE.SPV_ADMIN, + ROLE.STATE_ADMIN, + ], + }, + '/protected/v8/workallocation/getWorkOrders': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ROLE.WAT_MEMBER, + ROLE.CBC_ADMIN, + ROLE.SPV_ADMIN, + ], + }, + '/protected/v8/workallocation/add/workorder': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ROLE.WAT_MEMBER, + ROLE.CBC_ADMIN, + ROLE.SPV_ADMIN, + ], + }, + '/protected/v8/workallocation/getWorkOrderById/:workOrderId': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ROLE.WAT_MEMBER, + ROLE.CBC_ADMIN, + ROLE.SPV_ADMIN, + ], + SCOPE_CHECK: [ + ROLE.MDO_ADMIN, + ], + }, + '/protected/v8/workallocation/user/autocomplete/:searchTerm': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/workallocation/getUserCompetencies/:userId': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/frac/searchNodes': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/frac/filterByMappings': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/frac/:type/:key': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/workallocation/v2/add': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ROLE.WAT_MEMBER, + ROLE.CBC_ADMIN, + ROLE.SPV_ADMIN, + ], + }, + '/protected/v8/workallocation/getWorkAllocationById/:workAllocationId': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ROLE.WAT_MEMBER, + ROLE.CBC_ADMIN, + ROLE.SPV_ADMIN, + ], + }, + '/protected/v8/workallocation/update/workorder': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ROLE.WAT_MEMBER, + ROLE.CBC_ADMIN, + ROLE.SPV_ADMIN, + ], + }, + '/protected/v8/workallocation/getWOPdf/:workOrderId': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ROLE.WAT_MEMBER, + ROLE.CBC_ADMIN, + ROLE.SPV_ADMIN, + ], + }, + '/protected/v8/portal/cbp/mydepartment': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CBC_ADMIN, + ], + }, + '/protected/v8/user/mandatoryContent/checkStatus': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/user/rating/content/average-ratingInfo/:do_id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/social/post/timeline': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/user/history/:id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/frac/getAllNodes/:type': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/frac/getNodeById/:id/:type': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/portal/listDeptNames': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/scroing/getTemplate/:templateId': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/portal/cbc/department': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CBC_ADMIN, + ], + }, + '/protected/v8/portal/cbc/department/:deptId/': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CBC_ADMIN, + ], + }, + '/protected/v8/portal/spv/department/:deptId/': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.SPV_ADMIN, + ], + }, + '/protected/v8/scroing/calculate': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ROLE.EDITOR, + ROLE.CONTENT_PUBLISHER, + ROLE.CONTENT_REVIEWER, + ], + }, + // '/protected/v8/connections/connections/recommended': { + // checksNeeded: [CHECK.ROLE], + // // tslint:disable-next-line: object-literal-sort-keys + // ROLE_CHECK: [ + // ROLE.PUBLIC, + // ], + // }, + // '/protected/v8/connections/connections/requests/received': { + // checksNeeded: [CHECK.ROLE], + // // tslint:disable-next-line: object-literal-sort-keys + // ROLE_CHECK: [ + // ROLE.PUBLIC, + // ], + // }, + // '/protected/v8/connections/connections/established': { + // checksNeeded: [CHECK.ROLE], + // // tslint:disable-next-line: object-literal-sort-keys + // ROLE_CHECK: [ + // ROLE.PUBLIC, + // ], + // }, + // '/protected/v8/connections/connections/established/:id': { + // checksNeeded: [CHECK.ROLE], + // // tslint:disable-next-line: object-literal-sort-keys + // ROLE_CHECK: [ + // ROLE.PUBLIC, + // ], + // }, + // '/protected/v8/connections/connections/requested': { + // checksNeeded: [CHECK.ROLE], + // // tslint:disable-next-line: object-literal-sort-keys + // ROLE_CHECK: [ + // ROLE.PUBLIC, + // ], + // }, + // '/protected/v8/connections/add/connection': { + // checksNeeded: [CHECK.ROLE], + // // tslint:disable-next-line: object-literal-sort-keys + // ROLE_CHECK: [ + // ROLE.PUBLIC, + // ], + // }, + // '/protected/v8/connections/connections/suggests': { + // checksNeeded: [CHECK.ROLE], + // // tslint:disable-next-line: object-literal-sort-keys + // ROLE_CHECK: [ + // ROLE.PUBLIC, + // ], + // }, + '/protected/v8/cohorts/course/getUsersForBatch/:courseId': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/cohorts/user/autoenrollment/:courseId': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/profanity/startPdfProfanity': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ROLE.EDITOR, + ROLE.CONTENT_PUBLISHER, + ROLE.CONTENT_REVIEWER, + ], + }, + '/protected/v8/profanity/getPdfProfanityForContent/:contentId': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ROLE.CONTENT_REVIEWER, + ROLE.CONTENT_PUBLISHER, + ROLE.EDITOR, + ], + }, + '/protected/v8/catalog': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ROLE.EDITOR, + ROLE.PUBLIC, + ], + }, + '/protected/v8/scroing/fetch': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ROLE.CONTENT_REVIEWER, + ROLE.EDITOR, + ROLE.CONTENT_PUBLISHER, + ], + }, + '/protected/v8/portal/mdo/deptAction/userrole': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ], + }, + '/protected/v8/workallocation/v2/update': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ROLE.WAT_MEMBER, + ROLE.CBC_ADMIN, + ROLE.SPV_ADMIN, + ], + }, + '/protected/v8/user/profileDetails/updateUser': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/frac/addDataNodeBulk': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/roleactivity/:txt': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/connections/update/connection': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/workflowhandler/userWFApplicationFieldsSearch': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/user/details/detailV1': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/user/profileRegistry/getMasterNationalities': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/user/profileRegistry/getMasterLanguages': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/user/profileRegistry/getProfilePageMeta': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/user/notifications/settings': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/user/profileRegistry/searchUserRegistry': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/workflowhandler/transition': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/workflowhandler/nextActionSearch/:serviceName/:state': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ROLE.WAT_MEMBER, + ROLE.CBC_ADMIN, + ROLE.SPV_ADMIN, + ], + }, + '/protected/v8/workflowhandler/historyByApplicationIdAndWfId/:applicationId/:wfId': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ROLE.WAT_MEMBER, + ROLE.CBC_ADMIN, + ROLE.SPV_ADMIN, + ], + }, + '/protected/v8/workflowhandler/workflowProcess/:wfId': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ROLE.WAT_MEMBER, + ROLE.CBC_ADMIN, + ROLE.SPV_ADMIN, + ], + }, + '/protected/v8/workflowhandler/updateUserProfileWf': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ROLE.WAT_MEMBER, + ROLE.CBC_ADMIN, + ROLE.SPV_ADMIN, + ], + }, + '/protected/v8/workflowhandler/userWfSearch': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ROLE.WAT_MEMBER, + ROLE.CBC_ADMIN, + ROLE.SPV_ADMIN, + ], + }, + '/protected/v8/user/profileRegistry/getUserRegistryById': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/user/profileRegistry/getUserRegistryById/:id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/workallocation/copy/workOrder': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ROLE.WAT_MEMBER, + ROLE.CBC_ADMIN, + ROLE.SPV_ADMIN, + ], + }, + '/reset': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, 'ALL', + ], + }, + '/protected/v8/user/evaluate/assessment/submit/v2': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/user/evaluate/assessment/submit/v3': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/connections/v2/connections/recommended/userDepartment': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/connections/v2/connections/recommended': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/connections/v2/connections/requests/received': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/connections/v2/connections/established': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/contentprivate/update/:do_id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ], + }, + '/protected/v8/contentprivate/migratepublisher/:do_id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ], + }, + '/protected/v8/contentprivate/migratereviewer/:do_id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ], + }, + '/protected/v8/connections/v2/connections/established/:id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/connections/v2/connections/requested': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/connections/v2/add/connection': { + checksNeeded: [CHECK.ROLE, CHECK.PARAM_EQUALITY_CHECK], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + PARAM_EQUALITY_CHECK: { + checks: [ + { entity: '__param__equality', session: 'session.userId', requestbody: 'body.userIdFrom' }, + ], + }, + }, + '/protected/v8/connections/v2/connections/suggests': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/connections/v2/update/connection': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/user/profileDetails/createUserWithoutInvitationEmail': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ], + }, + '/authApi/batch/:key': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/authApi/readBatch/:batchId': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ROLE.MDO_ADMIN, + ], + }, + '/authApi/readCert/:certId': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, '/proxies/v8/searchBy/:key': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, '/proxies/v8/staff/position': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ], + }, '/proxies/v8/staff/position/:orgId': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ], + }, '/proxies/v8/budget/scheme': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ], + }, '/proxies/v8/budget/scheme/:orgId': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ], + }, '/proxies/v8/budget/scheme/:orgId/:budgetYear': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ], + }, '/proxies/v8/orghistory/:orgId/:key': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CBC_ADMIN, + ROLE.MDO_ADMIN, + ROLE.SPV_ADMIN, + ], + }, + '/proxies/v8/discussion/user/uid/:uid': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/discussion/user/:username/posts': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/action/framework/v3/read/:id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/action/framework/v3/category/master/create': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/action/framework/v3/category/master/search': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/action/framework/v3/category/master/read/:id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/action/framework/v3/category/create': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/action/framework/v3/category/read/:id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/action/framework/v3/category/retire/:id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/action/framework/v3/term/create': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/action/content/v3/upload/:do_id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/learner/course/v1/batch/list': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/cohorts/course/batch/cert/download/:certId': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/cohorts/course/batch/cert/issue': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/protected/v8/cohorts/course/batch/cert/template/add': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/discussion/v2/categories': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/storage/upload': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ], + }, + '/proxies/v8/storage/delete': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ], + }, + '/proxies/v8/user/v1/extPatch': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/learner/course/v2/user/enrollment/admin/list': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ROLE.MDO_ADMIN, + ROLE.CBP_ADMIN, + ], + }, + '/protected/v8/frac/bookmarkDataNode': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/assessment/read/:id': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/question/read': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/cbp/question/list': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ROLE.CONTENT_PUBLISHER, + ROLE.CONTENT_REVIEWER, + ], + }, + '/proxies/v8/questionset/v1/create': { + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ], + checksNeeded: [CHECK.ROLE], + }, + '/proxies/v8/questionset/v1/read/:id': { + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ROLE.CONTENT_PUBLISHER, + ROLE.CONTENT_REVIEWER, + ], + checksNeeded: [CHECK.ROLE], + }, + '/proxies/v8/questionset/v1/update/:id': { + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ROLE.CONTENT_PUBLISHER, + ROLE.CONTENT_REVIEWER, + ], + checksNeeded: [CHECK.ROLE], + }, + '/proxies/v8/questionset/v1/review/:id': { + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ], + checksNeeded: [CHECK.ROLE], + }, + '/proxies/v8/questionset/v1/publish/:id': { + ROLE_CHECK: [ + ROLE.CONTENT_PUBLISHER, + ], + checksNeeded: [CHECK.ROLE], + }, + '/proxies/v8/questionset/v1/hierarchy/update': { + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ], + checksNeeded: [CHECK.ROLE], + }, + '/proxies/v8/questionset/v1/retire/:id': { + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ROLE.CONTENT_PUBLISHER, + ROLE.CONTENT_REVIEWER, + ], + checksNeeded: [CHECK.ROLE], + }, + '/proxies/v8/questionset/v1/reject/:id': { + ROLE_CHECK: [ + ROLE.CONTENT_PUBLISHER, + ROLE.CONTENT_REVIEWER, + ], + checksNeeded: [CHECK.ROLE], + }, + '/proxies/v8/questionset/v1/hierarchy/:id': { + ROLE_CHECK: [ + ROLE.CONTENT_CREATOR, + ROLE.CONTENT_PUBLISHER, + ROLE.CONTENT_REVIEWER, + ], + checksNeeded: [CHECK.ROLE], + }, + '/proxies/v8/ratings/v1/read/:activityId/:activityType/:userId': { + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + checksNeeded: [CHECK.ROLE], + }, + '/proxies/v8/ratings/v1/upsert': { + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + checksNeeded: [CHECK.ROLE], + }, + '/proxies/v8/ratings/v1/summary/:activityId/:activityType': { + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + checksNeeded: [CHECK.ROLE], + }, + '/proxies/v8/ratings/v1/ratingLookUp': { + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + checksNeeded: [CHECK.ROLE], + }, + '/proxies/v8/user/v1/positions': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/org/ext/v1/create': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.SPV_ADMIN, + ROLE.STATE_ADMIN, + ], + }, + '/proxies/v8/user/basicInfo': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/user/basicProfileUpdate': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/forms/tagFormToCourse': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/forms/untagFormToCourse': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/forms/getAllApplications': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/forms/searchForms': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/moderatoradmin/feedback/persist/text/moderated': { + ROLE_CHECK: [ + ROLE.SPV_ADMIN, + ], + checksNeeded: [CHECK.ROLE], + }, + '/proxies/v8/moderatoradmin/feedback/text/fetch': { + ROLE_CHECK: [ + ROLE.SPV_ADMIN, + ], + checksNeeded: [CHECK.ROLE], + }, + '/proxies/v8/moderatoradmin/profanity/type/text': { + ROLE_CHECK: [ + ROLE.SPV_ADMIN, + ], + checksNeeded: [CHECK.ROLE], + }, + '/proxies/v8/moderatoradmin/feedback/flag/values': { + ROLE_CHECK: [ + ROLE.SPV_ADMIN, + ], + checksNeeded: [CHECK.ROLE], + }, + '/proxies/v8/user/v1/bulkupload': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ], + }, + '/proxies/v8/user/v1/bulkupload/:orgId': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.MDO_ADMIN, + ], + }, + '/proxies/v8/otp/v1/generate': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + '/proxies/v8/otp/v1/verify': { + checksNeeded: [CHECK.ROLE], + // tslint:disable-next-line: object-literal-sort-keys + ROLE_CHECK: [ + ROLE.PUBLIC, + ], + }, + }, + URL_PATTERN: + [ + // '/authApi/content/v3/create', + // '/authApi/content/v3/read/:do_id', + // '/authApi/content/v3/update/:do_id', + '/authApi/readBatch/:batchId', + '/authApi/batch/:key', + '/authApi/readCert/:certId', + '/proxies/v8/api/user/v2/read', + '/proxies/v8/api/user/v2/read/:id', + '/proxies/v8/user/v1/updateLogin', + '/proxies/v8/event/v4/read/:do_id', + '/proxies/v8/event/v4/publish/:do_id', + '/proxies/v8/event/v4/create', + '/proxies/v8/user/v1/read/:id', + '/proxies/v8/contentsearch/search', + '/proxies/v8/sunbirdigot/read', + '/proxies/v8/sunbirdigot/search', + '/proxies/v8/discussion/user/v1/create', + '/proxies/v8/data/v1/system/settings/get/orgTypeList', + '/proxies/v8/org/v1/search', + '/proxies/v8/org/v1/update', + '/proxies/v8/notifyContentState', + '/proxies/v8/discussion/topic/:id/:slug', + '/proxies/v8/discussion/v2/posts/:id/vote', + '/proxies/v8/discussion/v2/posts/:id', + '/proxies/v8/discussion/v2/posts/:id/bookmark', + '/proxies/v8/discussion/moderation/producer', + '/proxies/v8/discussion/moderation/consumer', + '/proxies/v8/learner/course/v1/user/enrollment/list/:id', + '/proxies/v8/learner/certreg/v1/certs/validate', + '/proxies/v8/read/content-progres/:do_id', + '/proxies/v8/content-progres/:do_id', + '/proxies/v8/action/content/v3/hierarchy/:do_id', + '/proxies/v8/action/content/v3/hierarchyUpdate', + '/proxies/v8/action/content/v3/hierarchy/update', + '/proxies/v8/action/content/v3/read/:do_id', + '/proxies/v8/discussion/forum/v2/read', + '/proxies/v8/discussion/category/list', + '/proxies/v8/discussion/category/:id', + '/proxies/v8/discussion/forum/tags', + '/proxies/v8/action/content/v3/update/:do_id', + '/proxies/v8/discussion/user/:id', + '/proxies/v8/action/content/v3/create', + '/proxies/v8/upload/action/content/v3/upload/:do_id', + '/proxies/v8/v1/content/retire', + '/proxies/v8/action/content/v3/copy/:do_id', + '/proxies/v8/action/content/v3/updateReviewStatus/:do_id', + '/proxies/v8/action/content/v3/review/:do_id', + '/proxies/v8/discussion/recent', + '/proxies/v8/discussion/popular', + '/proxies/v8/action/content/v3/publish/:do_id', + '/proxies/v8/action/content/v3/reject/:do_id', + '/proxies/v8/user/private/v1/assign/role', + '/proxies/v8/user/v1/search', + '/proxies/v8/org/v1/read', + '/proxies/v8/org/v1/profile/read', + '/proxies/v8/org/v1/profile/patch', + '/proxies/v8/org/v1/create', + '/proxies/v8/discussion/tags', + '/proxies/v8/user/v1/block', + '/proxies/v8/user/v1/unblock', + '/proxies/v8/data/v1/system/settings/get/orgTypeConfig', + '/proxies/v8/learnervm/private/content/v3/publish/:do_id', + '/proxies/v8/learnervm/private/content/v3/review/:do_id', + '/proxies/v8/discussion/v2/topics', + '/proxies/v8/discussion/v2/topics/:id', + '/proxies/v8/discussion/v2/categories', + '/proxies/v8/discussion/tags/:tag', + '/proxies/v8/discussion/user/:userKey/bookmarks', + '/proxies/v8/discussion/user/:userKey/bookmark', + '/proxies/v8/discussion/user/:userKey/upvoted', + '/proxies/v8/discussion/user/:userKey/downvoted', + '/proxies/v8/discussion/categories', + '/proxies/v8/user/v1/autocomplete/:key', + '/proxies/v8/user/v1/migrate', + '/proxies/v8/user/private/v1/migrate', + '/proxies/v8/user/private/v1/assign/role/userrole', + '/proxies/v8/learnervm/private/content/v3/retire/', + '/proxies/v8/private/content/v3/update/:do_id', + '/proxies/v8/dashboard/analytics/getDashboardConfig/Karmayogi/:comp', + '/proxies/v8/dashboard/analytics/getDashboardsForProfile/Karmayogi', + '/proxies/v8/dashboard/analytics/getChartV2/Karmayogi', + '/proxies/v8/wat/dashboard/getDashboardConfig/Karmayogi/overview', + '/protected/v8/user/profileDetails/test', + '/protected/v8/resource/', + '/protected/v8/user/details', + '/protected/v8/connections/connections/recommended/userDepartment', + '/protected/v8/discussionHub/categories/:cid/:slug?/:tid?', + '/protected/v8/discussionHub/topics/recent', + '/protected/v8/cohorts/:cohortType/:contentId', + '/protected/v8/user/content/like', + '/protected/v8/user/telemetry', + '/protected/v8/scrom/get/:id', + '/protected/v8/user/progress/:contentId', + '/protected/v8/user/rating/:contentId', + '/protected/v8/user/progress', + '/protected/v8/user/history/continue', + '/protected/v8/portal/departmentType/', + '/protected/v8/portal/spv/department', + '/protected/v8/portal/spv/deptAction/', + '/protected/v8/user/roles/getUsersV2', + '/protected/v8/portal/spv/mydepartment', + '/protected/v8/portal/mdo/mydepartment', + '/protected/v8/user/profileDetails/createUser', + '/protected/v8/user/profileRegistry/getUserRegistryByUser/:id', + '/protected/v8/user/profileRegistry/createUserRegistryV2', + '/protected/v8/user/profileRegistry/createUserRegistry', + '/protected/v8/portal/deptAction', + '/protected/v8/workflowhandler/historyByApplicationId/:applicationId', + '/protected/v8/user/autocomplete/:query', + '/protected/v8/portal/spv/deptAction/userrole', + '/protected/v8/user/preference', + '/protected/v8/workflowhandler/applicationsSearch', + '/protected/v8/workallocation/getWorkOrders', + '/protected/v8/workallocation/add/workorder', + '/protected/v8/workallocation/getWorkOrderById/:workOrderId', + '/protected/v8/workallocation/user/autocomplete/:searchTerm', + '/protected/v8/workallocation/getUserCompetencies/:userId', + '/protected/v8/frac/searchNodes', + '/protected/v8/frac/filterByMappings', + '/protected/v8/frac/:type/:key', + '/protected/v8/workallocation/v2/add', + '/protected/v8/workallocation/getWorkAllocationById/:workAllocationId', + '/protected/v8/workallocation/update/workorder', + '/protected/v8/workallocation/v2/update', + '/protected/v8/workallocation/getWOPdf/:workOrderId', + '/protected/v8/portal/cbp/mydepartment', + '/protected/v8/user/mandatoryContent/checkStatus', + '/protected/v8/contentprivate/update/:do_id', + '/protected/v8/contentprivate/migratepublisher/:do_id', + '/protected/v8/contentprivate/migratereviewer/:do_id', + '/protected/v8/user/rating/content/average-ratingInfo/:do_id', + '/protected/v8/social/post/timeline', + '/protected/v8/user/history/:id', + '/protected/v8/frac/getAllNodes/:type', + '/protected/v8/frac/getNodeById/:id/:type', + '/protected/v8/portal/listDeptNames', + '/protected/v8/scroing/getTemplate/:templateId', + '/protected/v8/portal/cbc/department', + '/protected/v8/portal/cbc/department/:deptId/', + '/protected/v8/portal/spv/department/:deptId/', + '/protected/v8/scroing/calculate', + // '/protected/v8/connections/connections/recommended', + // '/protected/v8/connections/connections/requests/received', + // '/protected/v8/connections/connections/established', + // '/protected/v8/connections/connections/established/:id', + // '/protected/v8/connections/connections/requested', + // '/protected/v8/connections/add/connection', + // '/protected/v8/connections/connections/suggests', + '/protected/v8/cohorts/course/getUsersForBatch/:courseId', + '/protected/v8/cohorts/user/autoenrollment/:courseId', + '/protected/v8/profanity/startPdfProfanity', + '/protected/v8/profanity/getPdfProfanityForContent/:contentId', + '/protected/v8/catalog', + '/protected/v8/scroing/fetch', + '/protected/v8/portal/mdo/deptAction/userrole', + '/protected/v8/user/profileDetails/updateUser', + '/protected/v8/frac/addDataNodeBulk', + '/protected/v8/roleactivity/:txt', + '/protected/v8/connections/update/connection', + '/protected/v8/workflowhandler/userWFApplicationFieldsSearch', + '/protected/v8/user/details/detailV1', + '/protected/v8/user/profileRegistry/getMasterNationalities', + '/protected/v8/user/profileRegistry/getMasterLanguages', + '/protected/v8/user/profileRegistry/getProfilePageMeta', + '/protected/v8/user/notifications/settings', + '/protected/v8/user/profileRegistry/searchUserRegistry', + '/protected/v8/workflowhandler/transition', + '/protected/v8/workflowhandler/nextActionSearch/:serviceName/:state', + '/protected/v8/workflowhandler/historyByApplicationIdAndWfId/:applicationId/:wfId', + '/protected/v8/workflowhandler/workflowProcess/:wfId', + '/protected/v8/workflowhandler/updateUserProfileWf', + '/protected/v8/workflowhandler/userWfSearch', + '/protected/v8/user/profileRegistry/getUserRegistryById', + '/protected/v8/user/profileRegistry/getUserRegistryById/:id', + '/protected/v8/workallocation/copy/workOrder', + '/reset', + '/protected/v8/user/evaluate/assessment/submit/v2', + '/protected/v8/user/evaluate/assessment/submit/v3', + '/protected/v8/connections/v2/connections/recommended/userDepartment', + '/protected/v8/connections/v2/connections/recommended', + '/protected/v8/connections/v2/connections/requests/received', + '/protected/v8/connections/v2/connections/established', + '/protected/v8/connections/v2/connections/established/:id', + '/protected/v8/connections/v2/connections/requested', + '/protected/v8/connections/v2/add/connection', + '/protected/v8/connections/v2/connections/suggests', + '/protected/v8/connections/v2/update/connection', + '/protected/v8/user/profileDetails/createUserWithoutInvitationEmail', + '/proxies/v8/searchBy/:key', + '/proxies/v8/staff/position', + '/proxies/v8/staff/position/:orgId', + '/proxies/v8/budget/scheme', + '/proxies/v8/budget/scheme/:orgId', + '/proxies/v8/budget/scheme/:orgId/:budgetYear', + '/proxies/v8/orghistory/:orgId/:key', + '/proxies/v8/discussion/user/uid/:uid', + '/proxies/v8/discussion/user/:username/posts', + '/proxies/v8/action/framework/v3/read/:id', + '/proxies/v8/action/framework/v3/category/master/create', + '/proxies/v8/action/framework/v3/category/master/search', + '/proxies/v8/action/framework/v3/category/master/read/:id', + '/proxies/v8/action/framework/v3/category/create', + '/proxies/v8/action/framework/v3/category/read/:id', + '/proxies/v8/action/framework/v3/category/retire/:id', + '/proxies/v8/action/framework/v3/term/create', + '/proxies/v8/action/content/v3/upload/:do_id', + '/proxies/v8/learner/course/v1/batch/list', + '/protected/v8/cohorts/course/batch/cert/download/:certId', + '/protected/v8/cohorts/course/batch/cert/issue', + '/protected/v8/cohorts/course/batch/cert/template/add', + '/proxies/v8/storage/upload', + '/proxies/v8/storage/delete', + '/proxies/v8/user/v1/extPatch', + '/proxies/v8/learner/course/v2/user/enrollment/admin/list', + '/protected/v8/frac/bookmarkDataNode', + '/proxies/v8/assessment/read/:id', + '/proxies/v8/question/read', + '/proxies/v8/cbp/question/list', + '/proxies/v8/questionset/v1/create', + '/proxies/v8/questionset/v1/read/:id', + '/proxies/v8/questionset/v1/update/:id', + '/proxies/v8/questionset/v1/review/:id', + '/proxies/v8/questionset/v1/publish/:id', + '/proxies/v8/questionset/v1/hierarchy/update', + '/proxies/v8/questionset/v1/retire/:id', + '/proxies/v8/questionset/v1/reject/:id', + '/proxies/v8/questionset/v1/hierarchy/:id', + '/proxies/v8/ratings/v1/read/:activityId/:activityType/:userId', + '/proxies/v8/ratings/v1/upsert', + '/proxies/v8/ratings/v1/summary/:activityId/:activityType', + '/proxies/v8/ratings/v1/ratingLookUp', + '/proxies/v8/user/v1/positions', + '/proxies/v8/org/ext/v1/create', + '/proxies/v8/user/basicInfo', + '/proxies/v8/user/basicProfileUpdate', + '/proxies/v8/forms/getAllApplications', + '/proxies/v8/forms/tagFormToCourse', + '/proxies/v8/forms/untagFormToCourse', + '/proxies/v8/forms/searchForms', + '/proxies/v8/moderatoradmin/feedback/persist/text/moderated', + '/proxies/v8/moderatoradmin/feedback/text/fetch', + '/proxies/v8/moderatoradmin/profanity/type/text', + '/proxies/v8/moderatoradmin/feedback/flag/values', + '/proxies/v8/user/v1/bulkupload', + '/proxies/v8/user/v1/bulkupload/:orgId', + '/proxies/v8/otp/v1/generate', + '/proxies/v8/otp/v1/otp', + ], +}