@nathapp/na-cli 1.0.0-rc.4 → 1.0.0-rc.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitlab-ci.yml +135 -0
- package/Makefile +16 -9
- package/README.md +18 -2
- package/alias-script.sh +30 -0
- package/dist/index.js +106 -128
- package/dist/index.js.map +1 -1
- package/dist/templates/db-schema/.gitignore-rename +1 -0
- package/dist/templates/db-schema/.gitlab-ci.yml +139 -0
- package/dist/templates/db-schema/001_Schema.sql +1 -0
- package/dist/templates/db-schema/DEV_MODE.txt +1 -0
- package/dist/templates/db-schema/Dockerfile +3 -0
- package/dist/templates/db-schema/Email-Templates/Individual/README.md +1 -0
- package/dist/templates/db-schema/GET_VERSION.sql +47 -0
- package/dist/templates/db-schema/Makefile +885 -0
- package/dist/templates/db-schema/README.md +117 -0
- package/dist/templates/db-schema/SET_VERSION.sql +5 -0
- package/dist/templates/db-schema/docker-compose.yaml +47 -0
- package/dist/templates/db-schema/package.json +3 -0
- package/dist/templates/db-schema/push.sh +0 -0
- package/dist/templates/db-schema/samples/899_DB_Grant_User.sql +9 -0
- package/dist/templates/db-schema/samples/990_SAMPLE_Init_Data.sql +27 -0
- package/dist/templates/k8s-deployment/.gitignore-rename +1 -0
- package/dist/templates/k8s-deployment/.gitlab-ci.yml +128 -0
- package/dist/templates/k8s-deployment/.helmignore +23 -0
- package/dist/templates/k8s-deployment/Chart.yaml +23 -0
- package/dist/templates/k8s-deployment/Makefile +196 -0
- package/dist/templates/k8s-deployment/README.md +32 -0
- package/dist/templates/k8s-deployment/resources/charts/mysql/Chart.yaml +23 -0
- package/dist/templates/k8s-deployment/resources/charts/mysql/charts/mysql-install/Chart.yaml +23 -0
- package/dist/templates/k8s-deployment/resources/charts/mysql/charts/mysql-install/script/Makefile +12 -0
- package/dist/templates/k8s-deployment/resources/charts/mysql/charts/mysql-install/templates/_helpers.tpl +62 -0
- package/dist/templates/k8s-deployment/resources/charts/mysql/charts/mysql-install/templates/configmap.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/mysql/charts/mysql-install/templates/job.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/mysql/charts/mysql-install/templates/secret.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/mysql/charts/mysql-install/values.yaml +51 -0
- package/dist/templates/k8s-deployment/resources/charts/mysql/templates/_helpers.tpl +62 -0
- package/dist/templates/k8s-deployment/resources/charts/mysql/templates/configmap.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/mysql/templates/deployment.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/mysql/templates/ingress.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/mysql/templates/job.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/mysql/templates/pv.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/mysql/templates/pvc.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/mysql/templates/sc.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/mysql/templates/secret.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/mysql/templates/service.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/mysql/templates/statefulset.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/mysql/values.yaml +15 -0
- package/dist/templates/k8s-deployment/resources/charts/redis/Chart.yaml +23 -0
- package/dist/templates/k8s-deployment/resources/charts/redis/charts/redis-install/Chart.yaml +23 -0
- package/dist/templates/k8s-deployment/resources/charts/redis/charts/redis-install/script/Makefile +8 -0
- package/dist/templates/k8s-deployment/resources/charts/redis/charts/redis-install/templates/_helpers.tpl +62 -0
- package/dist/templates/k8s-deployment/resources/charts/redis/charts/redis-install/templates/configmap.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/redis/charts/redis-install/templates/job.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/redis/charts/redis-install/templates/secret.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/redis/charts/redis-install/values.yaml +42 -0
- package/dist/templates/k8s-deployment/resources/charts/redis/templates/_helpers.tpl +62 -0
- package/dist/templates/k8s-deployment/resources/charts/redis/templates/configmap.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/redis/templates/deployment.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/redis/templates/ingress.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/redis/templates/job.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/redis/templates/pv.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/redis/templates/pvc.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/redis/templates/sc.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/redis/templates/secret.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/redis/templates/service.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/redis/templates/statefulset.yaml +1 -0
- package/dist/templates/k8s-deployment/resources/charts/redis/values.yaml +12 -0
- package/dist/templates/k8s-deployment/services/charts/hooks/Chart.yaml +23 -0
- package/dist/templates/k8s-deployment/services/charts/hooks/charts/pre-delete-rsc/Chart.yaml +23 -0
- package/dist/templates/k8s-deployment/services/charts/hooks/charts/pre-delete-rsc/script/Makefile +49 -0
- package/dist/templates/k8s-deployment/services/charts/hooks/charts/pre-delete-rsc/script/_env.yaml +2 -0
- package/dist/templates/k8s-deployment/services/charts/hooks/charts/pre-delete-rsc/templates/_helpers.tpl +62 -0
- package/dist/templates/k8s-deployment/services/charts/hooks/charts/pre-delete-rsc/templates/configmap.yaml +1 -0
- package/dist/templates/k8s-deployment/services/charts/hooks/charts/pre-delete-rsc/templates/job.yaml +1 -0
- package/dist/templates/k8s-deployment/services/charts/hooks/charts/pre-delete-rsc/templates/secret.yaml +1 -0
- package/dist/templates/k8s-deployment/services/charts/hooks/charts/pre-delete-rsc/values.yaml +36 -0
- package/dist/templates/k8s-deployment/services/charts/sample-nginx/Chart.yaml +23 -0
- package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/_helpers.tpl +62 -0
- package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/cluster-role-binding.yaml +1 -0
- package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/configmap.yaml +1 -0
- package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/cronjob.yaml +1 -0
- package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/deployment.yaml +1 -0
- package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/ingress.yaml +1 -0
- package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/pv.yaml +1 -0
- package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/pvc.yaml +1 -0
- package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/sc.yaml +1 -0
- package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/secret.yaml +1 -0
- package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/service-account.yaml +1 -0
- package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/service.yaml +1 -0
- package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/statefulset.yaml +1 -0
- package/dist/templates/k8s-deployment/services/charts/sample-nginx/values.yaml +47 -0
- package/dist/templates/k8s-deployment/services/charts/tests/Chart.yaml +23 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/Chart.yaml +23 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/Makefile +9 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress/fixtures/index.json +1 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress/integration/login/login-spec.js +47 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress/integration/login/loginEmailWrong-spec.js +14 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress/integration/login/loginPasswordWrong-spec.js +14 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress/integration/profile/updatePassword-spec.js +15 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress/integration/profile/updateProfile-spec.js +25 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress/integration/test-script.spec.js +9 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress/plugins/index.js +22 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress/support/commands.js +258 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress/support/index.js +35 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress/support/misc.js +8 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress.json +4 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/templates/_helpers.tpl +62 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/templates/configmap.yaml +1 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/templates/pod.yaml +1 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/templates/secret.yaml +1 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/values.yaml +70 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/.helmignore +2 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/Chart.yaml +23 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/script/Makefile +14 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/templates/_helpers.tpl +62 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/templates/configmap.yaml +1 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/templates/pod.yaml +1 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/templates/secret.yaml +1 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/_t-0100-readiness-liveness.ts +84 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/hub.ts +372 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-contact.ts +158 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-contract.ts +328 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-kyc.ts +304 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-onboard-app.ts +823 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-onboard-web.ts +493 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-profile.ts +277 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-whitelist.ts +133 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/resources/live.jpg +0 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/resources/mykad_front.jpg +0 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/resources/profile.jpg +0 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/t-0200-start.ts +172 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/values.yaml +59 -0
- package/dist/templates/k8s-deployment/templates/_cluster-role-binding.tpl +20 -0
- package/dist/templates/k8s-deployment/templates/_configmap.tpl +37 -0
- package/dist/templates/k8s-deployment/templates/_cronjob.tpl +225 -0
- package/dist/templates/k8s-deployment/templates/_deployment.tpl +246 -0
- package/dist/templates/k8s-deployment/templates/_helpers.tpl +31 -0
- package/dist/templates/k8s-deployment/templates/_ingress.tpl +77 -0
- package/dist/templates/k8s-deployment/templates/_job.tpl +233 -0
- package/dist/templates/k8s-deployment/templates/_pod.tpl +214 -0
- package/dist/templates/k8s-deployment/templates/_pv.tpl +42 -0
- package/dist/templates/k8s-deployment/templates/_pvc.tpl +27 -0
- package/dist/templates/k8s-deployment/templates/_root.tpl +314 -0
- package/dist/templates/k8s-deployment/templates/_sc.tpl +19 -0
- package/dist/templates/k8s-deployment/templates/_secret.tpl +15 -0
- package/dist/templates/k8s-deployment/templates/_service-account.tpl +8 -0
- package/dist/templates/k8s-deployment/templates/_service.tpl +40 -0
- package/dist/templates/k8s-deployment/templates/_statefulset.tpl +244 -0
- package/dist/templates/k8s-deployment/templates/root-cm.yaml +10 -0
- package/dist/templates/k8s-deployment/templates/root-pull-secret.yaml +11 -0
- package/dist/templates/k8s-deployment/templates/root-secret.yaml +24 -0
- package/dist/templates/k8s-deployment/values.yaml +38 -0
- package/dist/templates/k8s-helm-chart/Chart.yaml +23 -0
- package/dist/templates/k8s-helm-chart/templates/_helpers.tpl +62 -0
- package/dist/templates/k8s-helm-chart/templates/cluster-role-binding.yaml +1 -0
- package/dist/templates/k8s-helm-chart/templates/configmap.yaml +1 -0
- package/dist/templates/k8s-helm-chart/templates/cronjob.yaml +1 -0
- package/dist/templates/k8s-helm-chart/templates/deployment.yaml +1 -0
- package/dist/templates/k8s-helm-chart/templates/ingress.yaml +1 -0
- package/dist/templates/k8s-helm-chart/templates/pv.yaml +1 -0
- package/dist/templates/k8s-helm-chart/templates/pvc.yaml +1 -0
- package/dist/templates/k8s-helm-chart/templates/sc.yaml +1 -0
- package/dist/templates/k8s-helm-chart/templates/secret.yaml +1 -0
- package/dist/templates/k8s-helm-chart/templates/service-account.yaml +1 -0
- package/dist/templates/k8s-helm-chart/templates/service.yaml +1 -0
- package/dist/templates/k8s-helm-chart/templates/statefulset.yaml +1 -0
- package/dist/templates/k8s-helm-chart/values.yaml +41 -0
- package/dist/templates/mxw-base-api-express/.dockerignore +2 -0
- package/dist/templates/mxw-base-api-express/.env +10 -0
- package/dist/templates/mxw-base-api-express/.gitignore-rename +3 -0
- package/dist/templates/mxw-base-api-express/.gitlab-ci.yml +174 -0
- package/dist/templates/mxw-base-api-express/.nvmrc +1 -0
- package/dist/templates/mxw-base-api-express/Dockerfile +14 -0
- package/dist/templates/mxw-base-api-express/Makefile +84 -0
- package/dist/templates/mxw-base-api-express/README.md +71 -0
- package/dist/templates/mxw-base-api-express/package.json +55 -0
- package/dist/templates/mxw-base-api-express/src/app-service.test.ts +94 -0
- package/dist/templates/mxw-base-api-express/src/app-service.ts +498 -0
- package/dist/templates/mxw-base-api-express/src/auth/auth-user.test.ts +215 -0
- package/dist/templates/mxw-base-api-express/src/auth/auth-user.ts +86 -0
- package/dist/templates/mxw-base-api-express/src/auth/auth.ts +81 -0
- package/dist/templates/mxw-base-api-express/src/core-service.ts +72 -0
- package/dist/templates/mxw-base-api-express/src/crud.ts +84 -0
- package/dist/templates/mxw-base-api-express/src/http-handler.ts +71 -0
- package/dist/templates/mxw-base-api-express/src/server.ts +54 -0
- package/dist/templates/mxw-base-api-express/src/test.ts +38 -0
- package/dist/templates/mxw-base-api-express/src/utils/api-utilities.ts +52 -0
- package/dist/templates/mxw-base-api-express/src/utils/file-utilities.ts +55 -0
- package/dist/templates/mxw-base-api-express/tsconfig.json +32 -0
- package/dist/templates/nestjs-api/.dockerignore +2 -0
- package/dist/templates/nestjs-api/.env +12 -0
- package/dist/templates/nestjs-api/.eslintrc.js +25 -0
- package/dist/templates/nestjs-api/.gitignore-rename +35 -0
- package/dist/templates/nestjs-api/.gitlab-ci.yml +174 -0
- package/dist/templates/nestjs-api/.nvmrc +1 -0
- package/dist/templates/nestjs-api/.prettierrc +4 -0
- package/dist/templates/nestjs-api/Dockerfile +19 -0
- package/dist/templates/nestjs-api/Makefile +84 -0
- package/dist/templates/nestjs-api/README.md +67 -0
- package/dist/templates/nestjs-api/nest-cli.json +8 -0
- package/dist/templates/nestjs-api/package.json +75 -0
- package/dist/templates/nestjs-api/src/app.controller.spec.ts +22 -0
- package/dist/templates/nestjs-api/src/app.controller.ts +27 -0
- package/dist/templates/nestjs-api/src/app.module.ts +10 -0
- package/dist/templates/nestjs-api/src/app.service.ts +12 -0
- package/dist/templates/nestjs-api/src/main.ts +31 -0
- package/dist/templates/nestjs-api/test/app.e2e-spec.ts +24 -0
- package/dist/templates/nestjs-api/test/jest-e2e.json +9 -0
- package/dist/templates/nestjs-api/tsconfig.build.json +4 -0
- package/dist/templates/nestjs-api/tsconfig.json +22 -0
- package/dist/templates/nestjs-library/.eslintrc.js +24 -0
- package/dist/templates/nestjs-library/.gitignore-rename +39 -0
- package/dist/templates/nestjs-library/.gitlab-ci.yml +135 -0
- package/dist/templates/nestjs-library/.npmignore-rename +30 -0
- package/dist/templates/nestjs-library/.prettierrc +6 -0
- package/dist/templates/nestjs-library/LICENSE +21 -0
- package/dist/templates/nestjs-library/Makefile +60 -0
- package/dist/templates/nestjs-library/README.md +3 -0
- package/dist/templates/nestjs-library/index.d.ts +1 -0
- package/dist/templates/nestjs-library/index.js +6 -0
- package/dist/templates/nestjs-library/index.ts +1 -0
- package/dist/templates/nestjs-library/lib/index.ts +2 -0
- package/dist/templates/nestjs-library/package.json +41 -0
- package/dist/templates/nestjs-library/tsconfig.build.json +4 -0
- package/dist/templates/nestjs-library/tsconfig.json +18 -0
- package/dist/templates/ts-library/.dockerignore +2 -0
- package/dist/templates/ts-library/.eslintrc.js +24 -0
- package/dist/templates/ts-library/.gitignore-rename +37 -0
- package/dist/templates/ts-library/.gitlab-ci.yml +135 -0
- package/dist/templates/ts-library/.npmignore-rename +30 -0
- package/dist/templates/ts-library/.prettierrc +6 -0
- package/dist/templates/ts-library/LICENSE +21 -0
- package/dist/templates/ts-library/Makefile +58 -0
- package/dist/templates/ts-library/README.md +1 -0
- package/dist/templates/ts-library/index.d.ts +1 -0
- package/dist/templates/ts-library/index.js +6 -0
- package/dist/templates/ts-library/index.ts +1 -0
- package/dist/templates/ts-library/lib/index.ts +1 -0
- package/dist/templates/ts-library/lib/samples/index.ts +5 -0
- package/dist/templates/ts-library/lib/samples/samples-function.ts +3 -0
- package/dist/templates/ts-library/package.json +34 -0
- package/dist/templates/ts-library/test/jest-e2e.json +9 -0
- package/dist/templates/ts-library/test/sample.e2e-spec.ts +10 -0
- package/dist/templates/ts-library/tsconfig.build.json +4 -0
- package/dist/templates/ts-library/tsconfig.json +18 -0
- package/dist/utils/env.js +146 -0
- package/dist/utils/env.js.map +1 -0
- package/dist/utils/template.js +362 -1
- package/dist/utils/template.js.map +1 -1
- package/package.json +9 -5
- package/src/index.ts +0 -182
- package/src/utils/template.ts +0 -9
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import { describe, it, before, after, beforeEach, afterEach } from 'mocha';
|
|
4
|
+
import { expect } from 'chai';
|
|
5
|
+
import Sinon from "sinon";
|
|
6
|
+
import jwt from "jsonwebtoken";
|
|
7
|
+
import AuthUser from './auth-user';
|
|
8
|
+
import { CREDENTIAL_TYPE } from './auth';
|
|
9
|
+
import { errors } from 'mxw-libs-errors';
|
|
10
|
+
|
|
11
|
+
let sandbox: Sinon.SinonSandbox;
|
|
12
|
+
let clock: Sinon.SinonFakeTimers;
|
|
13
|
+
|
|
14
|
+
const JWT_SECRET = "secret";
|
|
15
|
+
|
|
16
|
+
describe('Suite: AuthUser', () => {
|
|
17
|
+
before(function () {
|
|
18
|
+
clock = Sinon.useFakeTimers({
|
|
19
|
+
now: new Date().getTime(),
|
|
20
|
+
shouldAdvanceTime: true
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
beforeEach(function () {
|
|
25
|
+
sandbox = Sinon.createSandbox();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
afterEach(function () {
|
|
29
|
+
if (sandbox) {
|
|
30
|
+
sandbox.restore();
|
|
31
|
+
sandbox = undefined;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
after(function () {
|
|
36
|
+
if (clock) {
|
|
37
|
+
clock.restore();
|
|
38
|
+
clock = undefined;
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe("Create credential", async () => {
|
|
43
|
+
it("Create token with minimum fields", async () => {
|
|
44
|
+
AuthUser.init(JWT_SECRET, "1m");
|
|
45
|
+
|
|
46
|
+
const token = AuthUser.Instance.createToken({
|
|
47
|
+
userId: 1,
|
|
48
|
+
type: CREDENTIAL_TYPE.USER,
|
|
49
|
+
username: "bean"
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
expect(token).is.a("string").lengthOf.greaterThan(0);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("Create token with all fields", async () => {
|
|
56
|
+
AuthUser.init(JWT_SECRET, "1m");
|
|
57
|
+
|
|
58
|
+
const token = AuthUser.Instance.createToken({
|
|
59
|
+
id: 1,
|
|
60
|
+
userId: 1,
|
|
61
|
+
type: CREDENTIAL_TYPE.USER,
|
|
62
|
+
orgId: 100,
|
|
63
|
+
email: "bean@happy.com",
|
|
64
|
+
username: "bean"
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
expect(token).is.a("string").lengthOf.greaterThan(0);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("Create token with missing field", async () => {
|
|
71
|
+
AuthUser.init(JWT_SECRET, "1m");
|
|
72
|
+
|
|
73
|
+
const fields = {
|
|
74
|
+
id: 1,
|
|
75
|
+
userId: 1,
|
|
76
|
+
type: CREDENTIAL_TYPE.USER,
|
|
77
|
+
orgId: 100,
|
|
78
|
+
email: "bean@happy.com",
|
|
79
|
+
username: "bean"
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
delete fields.userId;
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
AuthUser.Instance.createToken(fields);
|
|
86
|
+
expect.fail("It should be failed");
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
expect(error).has.property("code").eq(errors.PARAMETER_MISSING);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe("Verify credential", async () => {
|
|
95
|
+
it("Verify token", async () => {
|
|
96
|
+
AuthUser.init(JWT_SECRET, "1m");
|
|
97
|
+
|
|
98
|
+
const token = AuthUser.Instance.createToken({
|
|
99
|
+
userId: 1,
|
|
100
|
+
type: CREDENTIAL_TYPE.USER,
|
|
101
|
+
username: "bean"
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const credential = AuthUser.Instance.verifyToken(token, CREDENTIAL_TYPE.USER);
|
|
105
|
+
|
|
106
|
+
expect(credential).has.property("userId").is.a("number").eq(1);
|
|
107
|
+
expect(credential).has.property("type").is.a("number").eq(CREDENTIAL_TYPE.USER);
|
|
108
|
+
expect(credential).has.property("username").is.a("string").eq("bean");
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("Accept all token type", async () => {
|
|
112
|
+
AuthUser.init(JWT_SECRET, "1m");
|
|
113
|
+
|
|
114
|
+
const token = AuthUser.Instance.createToken({
|
|
115
|
+
userId: 1,
|
|
116
|
+
type: CREDENTIAL_TYPE.USER,
|
|
117
|
+
username: "bean"
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
const credential = AuthUser.Instance.verifyToken(token, null);
|
|
121
|
+
|
|
122
|
+
expect(credential).has.property("userId").is.a("number").eq(1);
|
|
123
|
+
expect(credential).has.property("type").is.a("number").eq(CREDENTIAL_TYPE.USER);
|
|
124
|
+
expect(credential).has.property("username").is.a("string").eq("bean");
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("Verify broken token", async () => {
|
|
128
|
+
const token = jwt.sign({
|
|
129
|
+
hello: "world"
|
|
130
|
+
}, JWT_SECRET, { expiresIn: "1m" });
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
AuthUser.Instance.verifyToken(token, CREDENTIAL_TYPE.USER);
|
|
134
|
+
expect.fail("It should be failed");
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
expect(error).has.property("code").eq(errors.PARAMETER_MISSING);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it("Verify invalid token", async () => {
|
|
142
|
+
try {
|
|
143
|
+
AuthUser.Instance.verifyToken("Trust me.. I am good", CREDENTIAL_TYPE.USER);
|
|
144
|
+
expect.fail("It should be failed");
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
expect(error).has.property("code").eq(errors.INVALID_SIGNATURE);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it("Verify mismatched token type", async () => {
|
|
152
|
+
AuthUser.init(JWT_SECRET, "1m");
|
|
153
|
+
|
|
154
|
+
const token = AuthUser.Instance.createToken({
|
|
155
|
+
userId: 1,
|
|
156
|
+
type: CREDENTIAL_TYPE.USER,
|
|
157
|
+
username: "bean"
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
try {
|
|
161
|
+
AuthUser.Instance.verifyToken(token, CREDENTIAL_TYPE.GUEST);
|
|
162
|
+
expect.fail("It should be failed");
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
expect(error).has.property("code").eq(errors.INVALID_FORMAT);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it("Verify invalid token type", async () => {
|
|
170
|
+
AuthUser.init(JWT_SECRET, "1m");
|
|
171
|
+
|
|
172
|
+
const stub = sandbox.stub(AuthUser.Instance as any, "checkCredential").callsFake((cred: Credential, type?: CREDENTIAL_TYPE) => {
|
|
173
|
+
return cred;
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
const token = AuthUser.Instance.createToken({
|
|
177
|
+
userId: 1,
|
|
178
|
+
type: 100,
|
|
179
|
+
username: "bean"
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
stub.restore();
|
|
183
|
+
|
|
184
|
+
try {
|
|
185
|
+
AuthUser.Instance.verifyToken(token, null);
|
|
186
|
+
expect.fail("It should be failed");
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
expect(error).has.property("code").eq(errors.INVALID_FORMAT);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it("Verify expired token", async () => {
|
|
194
|
+
AuthUser.init(JWT_SECRET, "1m");
|
|
195
|
+
|
|
196
|
+
const token = AuthUser.Instance.createToken({
|
|
197
|
+
userId: 1,
|
|
198
|
+
type: CREDENTIAL_TYPE.USER,
|
|
199
|
+
username: "bean"
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
await clock.tickAsync(60000);
|
|
203
|
+
|
|
204
|
+
try {
|
|
205
|
+
const credential = AuthUser.Instance.verifyToken(token, CREDENTIAL_TYPE.USER);
|
|
206
|
+
expect.fail("It should be failed");
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
expect(error).has.property("code").eq(errors.EXPIRED);
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
});
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { allowNull, allowNullOrEmpty, checkFormat, checkNumber, checkString, isUndefinedOrNull, isUndefinedOrNullOrEmpty, notAllowNullOrEmpty } from "mxw-libs-utils";
|
|
4
|
+
import { errors, throwError } from "mxw-libs-errors";
|
|
5
|
+
|
|
6
|
+
import { BearerToken, CREDENTIAL_TYPE } from "./auth";
|
|
7
|
+
|
|
8
|
+
export * from "./auth";
|
|
9
|
+
|
|
10
|
+
export class Credential {
|
|
11
|
+
id?: number;
|
|
12
|
+
userId: number;
|
|
13
|
+
type: CREDENTIAL_TYPE;
|
|
14
|
+
orgId?: number;
|
|
15
|
+
email?: string;
|
|
16
|
+
username: string;
|
|
17
|
+
iat?: number;
|
|
18
|
+
exp?: number;
|
|
19
|
+
|
|
20
|
+
static check(cred: Credential, type: CREDENTIAL_TYPE) {
|
|
21
|
+
if (isUndefinedOrNullOrEmpty(cred)) {
|
|
22
|
+
throwError(errors.NOT_INITIALIZED, "Missing credential");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return checkFormat({
|
|
26
|
+
id: allowNull(checkNumber),
|
|
27
|
+
userId: notAllowNullOrEmpty(checkNumber),
|
|
28
|
+
type: function (value) {
|
|
29
|
+
const credType = checkNumber(value);
|
|
30
|
+
|
|
31
|
+
if (type === credType) {
|
|
32
|
+
return credType;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
if (isUndefinedOrNull(type)) {
|
|
36
|
+
for (const t in CREDENTIAL_TYPE) {
|
|
37
|
+
if (Number(t) === credType) {
|
|
38
|
+
return credType;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
throwError(errors.INVALID_PARAMETER, "Invalid credential type", { credType });
|
|
45
|
+
},
|
|
46
|
+
orgId: allowNull(checkNumber),
|
|
47
|
+
email: allowNullOrEmpty(checkString),
|
|
48
|
+
username: notAllowNullOrEmpty(checkString),
|
|
49
|
+
iat: allowNull(checkNumber, undefined),
|
|
50
|
+
exp: allowNull(checkNumber, undefined)
|
|
51
|
+
}, cred) as Credential;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export class GuestCredential extends Credential {
|
|
56
|
+
static check(cred: GuestCredential) {
|
|
57
|
+
return super.check(cred, CREDENTIAL_TYPE.GUEST) as GuestCredential;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export class UserCredential extends Credential {
|
|
62
|
+
static check(cred: UserCredential) {
|
|
63
|
+
return super.check(cred, CREDENTIAL_TYPE.USER) as UserCredential;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export default class BasicAuth extends BearerToken<GuestCredential | UserCredential> {
|
|
68
|
+
private static self: BasicAuth;
|
|
69
|
+
|
|
70
|
+
constructor(secret: string, expiresIn: string, options?: any) {
|
|
71
|
+
super(secret, expiresIn, options);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
public static get Instance() {
|
|
75
|
+
return this.self || throwError(errors.NOT_INITIALIZED, "BasicAuth initialization is required");
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public static init(secret: string, expiresIn: string, options?: any) {
|
|
79
|
+
this.self = new BasicAuth(secret, expiresIn, options);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
protected checkCredential(cred: GuestCredential | UserCredential, type?: CREDENTIAL_TYPE) {
|
|
83
|
+
return Credential.check(cred, type);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { allowNullOrEmpty, checkFormat, checkString, isUndefinedOrNullOrEmpty, notAllowNullOrEmpty } from "mxw-libs-utils";
|
|
4
|
+
import jwt, { SignOptions, VerifyOptions } from "jsonwebtoken";
|
|
5
|
+
import { describeError, errors, throwError } from "mxw-libs-errors";
|
|
6
|
+
|
|
7
|
+
export enum CREDENTIAL_TYPE {
|
|
8
|
+
GUEST = 0,
|
|
9
|
+
USER = 1,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface AuthCredential<C> {
|
|
13
|
+
cred: C;
|
|
14
|
+
checkCredential(type?: CREDENTIAL_TYPE): C;
|
|
15
|
+
auth(cred: C): AuthCredential<C>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export abstract class BearerToken<C> {
|
|
19
|
+
private jwtSecret: string;
|
|
20
|
+
private signOptions: SignOptions;
|
|
21
|
+
private verifyOptions: VerifyOptions;
|
|
22
|
+
|
|
23
|
+
constructor(jwtSecret: string, jwtExpiresIn?: string, options?: any) {
|
|
24
|
+
const params: {
|
|
25
|
+
jwtSecret: string,
|
|
26
|
+
jwtExpiresIn?: string,
|
|
27
|
+
} = checkFormat({
|
|
28
|
+
jwtSecret: notAllowNullOrEmpty(checkString),
|
|
29
|
+
jwtExpiresIn: allowNullOrEmpty(checkString)
|
|
30
|
+
}, { jwtSecret, jwtExpiresIn });
|
|
31
|
+
|
|
32
|
+
this.signOptions = {};
|
|
33
|
+
|
|
34
|
+
if (params.jwtExpiresIn) {
|
|
35
|
+
this.signOptions.expiresIn = params.jwtExpiresIn;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
this.verifyOptions = {};
|
|
39
|
+
|
|
40
|
+
if (!isUndefinedOrNullOrEmpty(options?.JWT_SIGN_ALGO)) {
|
|
41
|
+
this.signOptions.algorithm = options?.JWT_SIGN_ALGO;
|
|
42
|
+
this.verifyOptions.algorithms = [options?.JWT_SIGN_ALGO];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
this.jwtSecret = params.jwtSecret;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
protected abstract checkCredential(cred: C, type?: CREDENTIAL_TYPE): C;
|
|
49
|
+
|
|
50
|
+
public createToken(cred: C, overrides?: any) {
|
|
51
|
+
const payload = this.checkCredential(cred);
|
|
52
|
+
|
|
53
|
+
if (!this.signOptions.expiresIn) {
|
|
54
|
+
throwError(errors.NOT_INITIALIZED, "Session expiry is not initialized");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return jwt.sign({
|
|
58
|
+
...overrides, ...payload
|
|
59
|
+
}, this.jwtSecret, this.signOptions);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public verifyToken(token: string, type: CREDENTIAL_TYPE) {
|
|
63
|
+
try {
|
|
64
|
+
const cred: any = jwt.verify(token, this.jwtSecret, this.verifyOptions) || throwError(errors.UNEXPECTED_MESSAGE, "Missing session", { token });
|
|
65
|
+
return this.checkCredential(cred, type);
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
const { code, message } = describeError(error);
|
|
69
|
+
|
|
70
|
+
if (errors.INVALID_FORMAT == code) {
|
|
71
|
+
throwError(errors.INVALID_FORMAT, message, { token, error });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
switch (error.name) {
|
|
75
|
+
case "TokenExpiredError": throwError(errors.EXPIRED, "Session expired", { token });
|
|
76
|
+
case "JsonWebTokenError": throwError(errors.INVALID_SIGNATURE, "Invalid token", { token });
|
|
77
|
+
}
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// for local development only
|
|
3
|
+
if (process.env.NODE_ENV == "local") require('dotenv').config()
|
|
4
|
+
import { CLogger, clog, levels } from "mxw-libs-clogger";
|
|
5
|
+
import { errors, throwError } from "mxw-libs-errors";
|
|
6
|
+
import { isUndefinedOrNull } from "mxw-libs-utils";
|
|
7
|
+
import AppService from "./app-service";
|
|
8
|
+
|
|
9
|
+
const { name, version } = require("../package.json");
|
|
10
|
+
|
|
11
|
+
export default class CoreService {
|
|
12
|
+
private static self: CoreService;
|
|
13
|
+
|
|
14
|
+
public static get Instance(): CoreService {
|
|
15
|
+
return this.self || throwError(errors.NOT_INITIALIZED, "CoreService initialization is required");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public static init(logLevel?: string) {
|
|
19
|
+
CLogger.Instance.init(levels.NORMAL);
|
|
20
|
+
|
|
21
|
+
if (isUndefinedOrNull(logLevel)) {
|
|
22
|
+
for (const [index, argv] of process.argv.entries()) {
|
|
23
|
+
if ("logLevel" == argv)
|
|
24
|
+
logLevel = process.argv[index + 1];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!isUndefinedOrNull(levels[logLevel])) {
|
|
29
|
+
CLogger.Instance.level = levels[logLevel];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const self = this.self = new this();
|
|
33
|
+
|
|
34
|
+
return self;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public static async term() {
|
|
38
|
+
try {
|
|
39
|
+
clog(levels.WARNING, "Service is terminating...");
|
|
40
|
+
|
|
41
|
+
if (this.self) {
|
|
42
|
+
// Terminate service
|
|
43
|
+
await AppService.term();
|
|
44
|
+
|
|
45
|
+
this.self = undefined;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
clog(levels.WARNING, "Service is terminated");
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
clog(levels.CRITICAL, "Service failed to terminate:", error);
|
|
52
|
+
throw error;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public async run() {
|
|
57
|
+
try {
|
|
58
|
+
clog(levels.WARNING, "Service", name, "(" + version + ") is starting...");
|
|
59
|
+
|
|
60
|
+
// Initialize service
|
|
61
|
+
const instance = await AppService.init();
|
|
62
|
+
const url = await instance.run();
|
|
63
|
+
|
|
64
|
+
clog(levels.WARNING, "Service is serving", url);
|
|
65
|
+
return this;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
clog(levels.CRITICAL, "Service failed to start:", error);
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { allowNull, checkFormat, checkNumber, renameKey } from "mxw-libs-utils";
|
|
4
|
+
import { AuthCredential, CREDENTIAL_TYPE } from "./auth/auth";
|
|
5
|
+
|
|
6
|
+
export * from "./auth/auth";
|
|
7
|
+
|
|
8
|
+
export class BaseList {
|
|
9
|
+
public static renameKey(obj: any, keys?: { [key: string]: string }) {
|
|
10
|
+
if (!keys) return { ...obj };
|
|
11
|
+
|
|
12
|
+
return renameKey({ ...obj }, (key) => {
|
|
13
|
+
if (keys[key]) {
|
|
14
|
+
return keys[key];
|
|
15
|
+
}
|
|
16
|
+
return key;
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public static diff(rec: any, out: any) {
|
|
21
|
+
let diff = [];
|
|
22
|
+
|
|
23
|
+
for (const key in rec) {
|
|
24
|
+
if (undefined === out[key]) {
|
|
25
|
+
diff.push(key);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return diff;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
class Pagination {
|
|
33
|
+
private _page: number;
|
|
34
|
+
private _pageSize: number;
|
|
35
|
+
|
|
36
|
+
constructor(page?: number, pageSize?: number) {
|
|
37
|
+
this.pagination(page, pageSize);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public pagination(page?: number, pageSize?: number) {
|
|
41
|
+
const params: {
|
|
42
|
+
page: number,
|
|
43
|
+
pageSize: number
|
|
44
|
+
} = checkFormat({
|
|
45
|
+
page: allowNull(checkNumber, this._page),
|
|
46
|
+
pageSize: allowNull(checkNumber, this._pageSize)
|
|
47
|
+
}, { page, pageSize });
|
|
48
|
+
|
|
49
|
+
this._page = params.page;
|
|
50
|
+
this._pageSize = params.pageSize;
|
|
51
|
+
|
|
52
|
+
return this;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public get page() {
|
|
56
|
+
return this._page;
|
|
57
|
+
}
|
|
58
|
+
public get pageSize() {
|
|
59
|
+
return this._pageSize;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export default abstract class CRUD<C, CI, UI, DI> extends Pagination implements AuthCredential<C>{
|
|
64
|
+
private _cred: C;
|
|
65
|
+
|
|
66
|
+
public abstract picklist(overrides?: any);
|
|
67
|
+
public abstract list(overrides?: any);
|
|
68
|
+
public abstract getDetail(id: number, overrides?: any);
|
|
69
|
+
public abstract create(params: CI);
|
|
70
|
+
public abstract update(params: UI);
|
|
71
|
+
public abstract delete(id: number | DI);
|
|
72
|
+
|
|
73
|
+
public abstract checkCredential(type?: CREDENTIAL_TYPE): C;
|
|
74
|
+
|
|
75
|
+
public auth(cred: C, type = CREDENTIAL_TYPE.USER) {
|
|
76
|
+
this._cred = cred;
|
|
77
|
+
this.checkCredential(type);
|
|
78
|
+
return this;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
public get cred() {
|
|
82
|
+
return this._cred;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { Request, Response, NextFunction } from "express";
|
|
4
|
+
import { clog, levels } from "mxw-libs-clogger";
|
|
5
|
+
import { errors, throwError } from "mxw-libs-errors";
|
|
6
|
+
|
|
7
|
+
export const finalHandler = (req: Request, res: Response, next: NextFunction) => {
|
|
8
|
+
if (!res.headersSent) {
|
|
9
|
+
res.statusCode = 404;
|
|
10
|
+
throwError(errors.NOT_FOUND, "Resource not found");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
resLog(null, req, res);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const errorHandler = (error: any, req: Request, res: Response, next: NextFunction) => {
|
|
17
|
+
const { code, message } = errors.describeError(error);
|
|
18
|
+
|
|
19
|
+
let statusCode: number;
|
|
20
|
+
|
|
21
|
+
// Respect the status code that caller specified
|
|
22
|
+
if (200 !== res.statusCode) {
|
|
23
|
+
statusCode = res.statusCode;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
// Define the default status code that based on error code
|
|
27
|
+
switch (code) {
|
|
28
|
+
case errors.UNAUTHORISED:
|
|
29
|
+
case errors.EXPIRED:
|
|
30
|
+
statusCode = 401;
|
|
31
|
+
break;
|
|
32
|
+
case "TooManyRequests":
|
|
33
|
+
statusCode = 429;
|
|
34
|
+
break;
|
|
35
|
+
default:
|
|
36
|
+
statusCode = 500;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
res.status(statusCode).send({
|
|
41
|
+
ret: code,
|
|
42
|
+
message
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
resLog(error, req, res);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const resLog = (error: any, req: Request, res: Response) => {
|
|
49
|
+
const ip = req.headers?.['x-forwarded-for'] || req.headers?.['x-real-ip'] || "0.0.0.0";
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
const contentLength = res.getHeaders()["content-length"];
|
|
53
|
+
|
|
54
|
+
if (!error) {
|
|
55
|
+
if (!req["logExcluded"]) {
|
|
56
|
+
clog(levels.ERROR, `RES: ${req.method} ${req.url} HTTP/${req.httpVersion} @${ip}`,
|
|
57
|
+
`OK ${contentLength || "-"}, elapsed: ${res["elapsed"] + "ms" || "--"}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
const { code, message, reason } = errors.describeError(error);
|
|
62
|
+
|
|
63
|
+
clog(levels.ERROR, `RES: ${req.method} ${req.url} HTTP/${req.httpVersion} @${ip}`,
|
|
64
|
+
`${res.statusCode}: ${code || "?"}, ${contentLength || "-"}, elapsed: ${res["elapsed"] + "ms" || "--"}, ${reason || message || "Unknown error"}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
clog(levels.ERROR, `RES: ${req.method} ${req.url} HTTP/${req.httpVersion} @${ip}`,
|
|
69
|
+
`${res.statusCode}: ${"?"} -, elapsed: ${res["elapsed"] + "ms" || "--"}, ${error}`);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { CLogger, clog, levels } from "mxw-libs-clogger";
|
|
4
|
+
import CoreService from "./core-service"
|
|
5
|
+
|
|
6
|
+
CoreService.init().run().catch(async () => {
|
|
7
|
+
await CoreService.term().catch(() => { });
|
|
8
|
+
process.exit(-1);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
async function exitHandler(cleanup = false) {
|
|
12
|
+
if (cleanup) {
|
|
13
|
+
await CoreService.term().catch(() => { });
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
//do something when app is closing
|
|
18
|
+
process.on("exit", exitHandler.bind(null, false));
|
|
19
|
+
|
|
20
|
+
//catches ctrl+c event
|
|
21
|
+
process.on("SIGINT", exitHandler.bind(null, true));
|
|
22
|
+
|
|
23
|
+
//catches SIGHUP (1) event to increase log depth (circled)
|
|
24
|
+
process.on("SIGHUP", () => {
|
|
25
|
+
CLogger.Instance.depth = null;
|
|
26
|
+
clog(levels.CRITICAL, "Logger depth:", CLogger.Instance.depth);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
//catches SIGUSR1 (10) event to increase log width (circled)
|
|
30
|
+
process.on("SIGUSR1", () => {
|
|
31
|
+
CLogger.Instance.width = null;
|
|
32
|
+
clog(levels.CRITICAL, "Logger width:", CLogger.Instance.width);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
//catches SIGUSR2 (12) event to increase log severity (circled)
|
|
36
|
+
process.on("SIGUSR2", () => {
|
|
37
|
+
CLogger.Instance.level = null;
|
|
38
|
+
clog(levels.CRITICAL, "Logger level:", CLogger.Instance.level);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
//catches uncaught exceptions
|
|
42
|
+
process.on("uncaughtException", (error) => {
|
|
43
|
+
exitHandler.bind(null, true);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
//catches unhandled rejection
|
|
47
|
+
process.on("unhandledRejection", (reason) => {
|
|
48
|
+
if (process.stderr.writable) {
|
|
49
|
+
process.stderr.write(`unhandledRejection: ${reason}`);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// listen for TERM signal .e.g. kill
|
|
54
|
+
process.on("SIGTERM", exitHandler.bind(null, true));
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { expect } from 'chai';
|
|
4
|
+
|
|
5
|
+
export interface TARGET {
|
|
6
|
+
key: string;
|
|
7
|
+
type: string;
|
|
8
|
+
value: any;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function assertValue(value: any, target: TARGET) {
|
|
12
|
+
if (null === target.value || undefined === target.value) {
|
|
13
|
+
if (!target.key) {
|
|
14
|
+
expect(value).is.not.exist;
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
expect(value).has.property(target.key).is.not.exist;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
if ("object" === target.type) {
|
|
22
|
+
if (!target.key) {
|
|
23
|
+
expect(value).to.deep.equal(target.value);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
expect(value).has.property(target.key).to.deep.equal(target.value);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
if (!target.key) {
|
|
31
|
+
expect(value).is.a(target.type).is.eq(target.value);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
expect(value).has.property(target.key).is.a(target.type).is.eq(target.value);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|