@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.
Files changed (252) hide show
  1. package/.gitlab-ci.yml +135 -0
  2. package/Makefile +16 -9
  3. package/README.md +18 -2
  4. package/alias-script.sh +30 -0
  5. package/dist/index.js +106 -128
  6. package/dist/index.js.map +1 -1
  7. package/dist/templates/db-schema/.gitignore-rename +1 -0
  8. package/dist/templates/db-schema/.gitlab-ci.yml +139 -0
  9. package/dist/templates/db-schema/001_Schema.sql +1 -0
  10. package/dist/templates/db-schema/DEV_MODE.txt +1 -0
  11. package/dist/templates/db-schema/Dockerfile +3 -0
  12. package/dist/templates/db-schema/Email-Templates/Individual/README.md +1 -0
  13. package/dist/templates/db-schema/GET_VERSION.sql +47 -0
  14. package/dist/templates/db-schema/Makefile +885 -0
  15. package/dist/templates/db-schema/README.md +117 -0
  16. package/dist/templates/db-schema/SET_VERSION.sql +5 -0
  17. package/dist/templates/db-schema/docker-compose.yaml +47 -0
  18. package/dist/templates/db-schema/package.json +3 -0
  19. package/dist/templates/db-schema/push.sh +0 -0
  20. package/dist/templates/db-schema/samples/899_DB_Grant_User.sql +9 -0
  21. package/dist/templates/db-schema/samples/990_SAMPLE_Init_Data.sql +27 -0
  22. package/dist/templates/k8s-deployment/.gitignore-rename +1 -0
  23. package/dist/templates/k8s-deployment/.gitlab-ci.yml +128 -0
  24. package/dist/templates/k8s-deployment/.helmignore +23 -0
  25. package/dist/templates/k8s-deployment/Chart.yaml +23 -0
  26. package/dist/templates/k8s-deployment/Makefile +196 -0
  27. package/dist/templates/k8s-deployment/README.md +32 -0
  28. package/dist/templates/k8s-deployment/resources/charts/mysql/Chart.yaml +23 -0
  29. package/dist/templates/k8s-deployment/resources/charts/mysql/charts/mysql-install/Chart.yaml +23 -0
  30. package/dist/templates/k8s-deployment/resources/charts/mysql/charts/mysql-install/script/Makefile +12 -0
  31. package/dist/templates/k8s-deployment/resources/charts/mysql/charts/mysql-install/templates/_helpers.tpl +62 -0
  32. package/dist/templates/k8s-deployment/resources/charts/mysql/charts/mysql-install/templates/configmap.yaml +1 -0
  33. package/dist/templates/k8s-deployment/resources/charts/mysql/charts/mysql-install/templates/job.yaml +1 -0
  34. package/dist/templates/k8s-deployment/resources/charts/mysql/charts/mysql-install/templates/secret.yaml +1 -0
  35. package/dist/templates/k8s-deployment/resources/charts/mysql/charts/mysql-install/values.yaml +51 -0
  36. package/dist/templates/k8s-deployment/resources/charts/mysql/templates/_helpers.tpl +62 -0
  37. package/dist/templates/k8s-deployment/resources/charts/mysql/templates/configmap.yaml +1 -0
  38. package/dist/templates/k8s-deployment/resources/charts/mysql/templates/deployment.yaml +1 -0
  39. package/dist/templates/k8s-deployment/resources/charts/mysql/templates/ingress.yaml +1 -0
  40. package/dist/templates/k8s-deployment/resources/charts/mysql/templates/job.yaml +1 -0
  41. package/dist/templates/k8s-deployment/resources/charts/mysql/templates/pv.yaml +1 -0
  42. package/dist/templates/k8s-deployment/resources/charts/mysql/templates/pvc.yaml +1 -0
  43. package/dist/templates/k8s-deployment/resources/charts/mysql/templates/sc.yaml +1 -0
  44. package/dist/templates/k8s-deployment/resources/charts/mysql/templates/secret.yaml +1 -0
  45. package/dist/templates/k8s-deployment/resources/charts/mysql/templates/service.yaml +1 -0
  46. package/dist/templates/k8s-deployment/resources/charts/mysql/templates/statefulset.yaml +1 -0
  47. package/dist/templates/k8s-deployment/resources/charts/mysql/values.yaml +15 -0
  48. package/dist/templates/k8s-deployment/resources/charts/redis/Chart.yaml +23 -0
  49. package/dist/templates/k8s-deployment/resources/charts/redis/charts/redis-install/Chart.yaml +23 -0
  50. package/dist/templates/k8s-deployment/resources/charts/redis/charts/redis-install/script/Makefile +8 -0
  51. package/dist/templates/k8s-deployment/resources/charts/redis/charts/redis-install/templates/_helpers.tpl +62 -0
  52. package/dist/templates/k8s-deployment/resources/charts/redis/charts/redis-install/templates/configmap.yaml +1 -0
  53. package/dist/templates/k8s-deployment/resources/charts/redis/charts/redis-install/templates/job.yaml +1 -0
  54. package/dist/templates/k8s-deployment/resources/charts/redis/charts/redis-install/templates/secret.yaml +1 -0
  55. package/dist/templates/k8s-deployment/resources/charts/redis/charts/redis-install/values.yaml +42 -0
  56. package/dist/templates/k8s-deployment/resources/charts/redis/templates/_helpers.tpl +62 -0
  57. package/dist/templates/k8s-deployment/resources/charts/redis/templates/configmap.yaml +1 -0
  58. package/dist/templates/k8s-deployment/resources/charts/redis/templates/deployment.yaml +1 -0
  59. package/dist/templates/k8s-deployment/resources/charts/redis/templates/ingress.yaml +1 -0
  60. package/dist/templates/k8s-deployment/resources/charts/redis/templates/job.yaml +1 -0
  61. package/dist/templates/k8s-deployment/resources/charts/redis/templates/pv.yaml +1 -0
  62. package/dist/templates/k8s-deployment/resources/charts/redis/templates/pvc.yaml +1 -0
  63. package/dist/templates/k8s-deployment/resources/charts/redis/templates/sc.yaml +1 -0
  64. package/dist/templates/k8s-deployment/resources/charts/redis/templates/secret.yaml +1 -0
  65. package/dist/templates/k8s-deployment/resources/charts/redis/templates/service.yaml +1 -0
  66. package/dist/templates/k8s-deployment/resources/charts/redis/templates/statefulset.yaml +1 -0
  67. package/dist/templates/k8s-deployment/resources/charts/redis/values.yaml +12 -0
  68. package/dist/templates/k8s-deployment/services/charts/hooks/Chart.yaml +23 -0
  69. package/dist/templates/k8s-deployment/services/charts/hooks/charts/pre-delete-rsc/Chart.yaml +23 -0
  70. package/dist/templates/k8s-deployment/services/charts/hooks/charts/pre-delete-rsc/script/Makefile +49 -0
  71. package/dist/templates/k8s-deployment/services/charts/hooks/charts/pre-delete-rsc/script/_env.yaml +2 -0
  72. package/dist/templates/k8s-deployment/services/charts/hooks/charts/pre-delete-rsc/templates/_helpers.tpl +62 -0
  73. package/dist/templates/k8s-deployment/services/charts/hooks/charts/pre-delete-rsc/templates/configmap.yaml +1 -0
  74. package/dist/templates/k8s-deployment/services/charts/hooks/charts/pre-delete-rsc/templates/job.yaml +1 -0
  75. package/dist/templates/k8s-deployment/services/charts/hooks/charts/pre-delete-rsc/templates/secret.yaml +1 -0
  76. package/dist/templates/k8s-deployment/services/charts/hooks/charts/pre-delete-rsc/values.yaml +36 -0
  77. package/dist/templates/k8s-deployment/services/charts/sample-nginx/Chart.yaml +23 -0
  78. package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/_helpers.tpl +62 -0
  79. package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/cluster-role-binding.yaml +1 -0
  80. package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/configmap.yaml +1 -0
  81. package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/cronjob.yaml +1 -0
  82. package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/deployment.yaml +1 -0
  83. package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/ingress.yaml +1 -0
  84. package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/pv.yaml +1 -0
  85. package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/pvc.yaml +1 -0
  86. package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/sc.yaml +1 -0
  87. package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/secret.yaml +1 -0
  88. package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/service-account.yaml +1 -0
  89. package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/service.yaml +1 -0
  90. package/dist/templates/k8s-deployment/services/charts/sample-nginx/templates/statefulset.yaml +1 -0
  91. package/dist/templates/k8s-deployment/services/charts/sample-nginx/values.yaml +47 -0
  92. package/dist/templates/k8s-deployment/services/charts/tests/Chart.yaml +23 -0
  93. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/Chart.yaml +23 -0
  94. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/Makefile +9 -0
  95. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress/fixtures/index.json +1 -0
  96. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress/integration/login/login-spec.js +47 -0
  97. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress/integration/login/loginEmailWrong-spec.js +14 -0
  98. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress/integration/login/loginPasswordWrong-spec.js +14 -0
  99. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress/integration/profile/updatePassword-spec.js +15 -0
  100. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress/integration/profile/updateProfile-spec.js +25 -0
  101. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress/integration/test-script.spec.js +9 -0
  102. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress/plugins/index.js +22 -0
  103. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress/support/commands.js +258 -0
  104. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress/support/index.js +35 -0
  105. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress/support/misc.js +8 -0
  106. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/cypress.json +4 -0
  107. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/templates/_helpers.tpl +62 -0
  108. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/templates/configmap.yaml +1 -0
  109. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/templates/pod.yaml +1 -0
  110. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/templates/secret.yaml +1 -0
  111. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/values.yaml +70 -0
  112. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/.helmignore +2 -0
  113. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/Chart.yaml +23 -0
  114. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/script/Makefile +14 -0
  115. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/templates/_helpers.tpl +62 -0
  116. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/templates/configmap.yaml +1 -0
  117. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/templates/pod.yaml +1 -0
  118. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/templates/secret.yaml +1 -0
  119. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/_t-0100-readiness-liveness.ts +84 -0
  120. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/hub.ts +372 -0
  121. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-contact.ts +158 -0
  122. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-contract.ts +328 -0
  123. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-kyc.ts +304 -0
  124. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-onboard-app.ts +823 -0
  125. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-onboard-web.ts +493 -0
  126. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-profile.ts +277 -0
  127. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-whitelist.ts +133 -0
  128. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/resources/live.jpg +0 -0
  129. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/resources/mykad_front.jpg +0 -0
  130. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/resources/profile.jpg +0 -0
  131. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/t-0200-start.ts +172 -0
  132. package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/values.yaml +59 -0
  133. package/dist/templates/k8s-deployment/templates/_cluster-role-binding.tpl +20 -0
  134. package/dist/templates/k8s-deployment/templates/_configmap.tpl +37 -0
  135. package/dist/templates/k8s-deployment/templates/_cronjob.tpl +225 -0
  136. package/dist/templates/k8s-deployment/templates/_deployment.tpl +246 -0
  137. package/dist/templates/k8s-deployment/templates/_helpers.tpl +31 -0
  138. package/dist/templates/k8s-deployment/templates/_ingress.tpl +77 -0
  139. package/dist/templates/k8s-deployment/templates/_job.tpl +233 -0
  140. package/dist/templates/k8s-deployment/templates/_pod.tpl +214 -0
  141. package/dist/templates/k8s-deployment/templates/_pv.tpl +42 -0
  142. package/dist/templates/k8s-deployment/templates/_pvc.tpl +27 -0
  143. package/dist/templates/k8s-deployment/templates/_root.tpl +314 -0
  144. package/dist/templates/k8s-deployment/templates/_sc.tpl +19 -0
  145. package/dist/templates/k8s-deployment/templates/_secret.tpl +15 -0
  146. package/dist/templates/k8s-deployment/templates/_service-account.tpl +8 -0
  147. package/dist/templates/k8s-deployment/templates/_service.tpl +40 -0
  148. package/dist/templates/k8s-deployment/templates/_statefulset.tpl +244 -0
  149. package/dist/templates/k8s-deployment/templates/root-cm.yaml +10 -0
  150. package/dist/templates/k8s-deployment/templates/root-pull-secret.yaml +11 -0
  151. package/dist/templates/k8s-deployment/templates/root-secret.yaml +24 -0
  152. package/dist/templates/k8s-deployment/values.yaml +38 -0
  153. package/dist/templates/k8s-helm-chart/Chart.yaml +23 -0
  154. package/dist/templates/k8s-helm-chart/templates/_helpers.tpl +62 -0
  155. package/dist/templates/k8s-helm-chart/templates/cluster-role-binding.yaml +1 -0
  156. package/dist/templates/k8s-helm-chart/templates/configmap.yaml +1 -0
  157. package/dist/templates/k8s-helm-chart/templates/cronjob.yaml +1 -0
  158. package/dist/templates/k8s-helm-chart/templates/deployment.yaml +1 -0
  159. package/dist/templates/k8s-helm-chart/templates/ingress.yaml +1 -0
  160. package/dist/templates/k8s-helm-chart/templates/pv.yaml +1 -0
  161. package/dist/templates/k8s-helm-chart/templates/pvc.yaml +1 -0
  162. package/dist/templates/k8s-helm-chart/templates/sc.yaml +1 -0
  163. package/dist/templates/k8s-helm-chart/templates/secret.yaml +1 -0
  164. package/dist/templates/k8s-helm-chart/templates/service-account.yaml +1 -0
  165. package/dist/templates/k8s-helm-chart/templates/service.yaml +1 -0
  166. package/dist/templates/k8s-helm-chart/templates/statefulset.yaml +1 -0
  167. package/dist/templates/k8s-helm-chart/values.yaml +41 -0
  168. package/dist/templates/mxw-base-api-express/.dockerignore +2 -0
  169. package/dist/templates/mxw-base-api-express/.env +10 -0
  170. package/dist/templates/mxw-base-api-express/.gitignore-rename +3 -0
  171. package/dist/templates/mxw-base-api-express/.gitlab-ci.yml +174 -0
  172. package/dist/templates/mxw-base-api-express/.nvmrc +1 -0
  173. package/dist/templates/mxw-base-api-express/Dockerfile +14 -0
  174. package/dist/templates/mxw-base-api-express/Makefile +84 -0
  175. package/dist/templates/mxw-base-api-express/README.md +71 -0
  176. package/dist/templates/mxw-base-api-express/package.json +55 -0
  177. package/dist/templates/mxw-base-api-express/src/app-service.test.ts +94 -0
  178. package/dist/templates/mxw-base-api-express/src/app-service.ts +498 -0
  179. package/dist/templates/mxw-base-api-express/src/auth/auth-user.test.ts +215 -0
  180. package/dist/templates/mxw-base-api-express/src/auth/auth-user.ts +86 -0
  181. package/dist/templates/mxw-base-api-express/src/auth/auth.ts +81 -0
  182. package/dist/templates/mxw-base-api-express/src/core-service.ts +72 -0
  183. package/dist/templates/mxw-base-api-express/src/crud.ts +84 -0
  184. package/dist/templates/mxw-base-api-express/src/http-handler.ts +71 -0
  185. package/dist/templates/mxw-base-api-express/src/server.ts +54 -0
  186. package/dist/templates/mxw-base-api-express/src/test.ts +38 -0
  187. package/dist/templates/mxw-base-api-express/src/utils/api-utilities.ts +52 -0
  188. package/dist/templates/mxw-base-api-express/src/utils/file-utilities.ts +55 -0
  189. package/dist/templates/mxw-base-api-express/tsconfig.json +32 -0
  190. package/dist/templates/nestjs-api/.dockerignore +2 -0
  191. package/dist/templates/nestjs-api/.env +12 -0
  192. package/dist/templates/nestjs-api/.eslintrc.js +25 -0
  193. package/dist/templates/nestjs-api/.gitignore-rename +35 -0
  194. package/dist/templates/nestjs-api/.gitlab-ci.yml +174 -0
  195. package/dist/templates/nestjs-api/.nvmrc +1 -0
  196. package/dist/templates/nestjs-api/.prettierrc +4 -0
  197. package/dist/templates/nestjs-api/Dockerfile +19 -0
  198. package/dist/templates/nestjs-api/Makefile +84 -0
  199. package/dist/templates/nestjs-api/README.md +67 -0
  200. package/dist/templates/nestjs-api/nest-cli.json +8 -0
  201. package/dist/templates/nestjs-api/package.json +75 -0
  202. package/dist/templates/nestjs-api/src/app.controller.spec.ts +22 -0
  203. package/dist/templates/nestjs-api/src/app.controller.ts +27 -0
  204. package/dist/templates/nestjs-api/src/app.module.ts +10 -0
  205. package/dist/templates/nestjs-api/src/app.service.ts +12 -0
  206. package/dist/templates/nestjs-api/src/main.ts +31 -0
  207. package/dist/templates/nestjs-api/test/app.e2e-spec.ts +24 -0
  208. package/dist/templates/nestjs-api/test/jest-e2e.json +9 -0
  209. package/dist/templates/nestjs-api/tsconfig.build.json +4 -0
  210. package/dist/templates/nestjs-api/tsconfig.json +22 -0
  211. package/dist/templates/nestjs-library/.eslintrc.js +24 -0
  212. package/dist/templates/nestjs-library/.gitignore-rename +39 -0
  213. package/dist/templates/nestjs-library/.gitlab-ci.yml +135 -0
  214. package/dist/templates/nestjs-library/.npmignore-rename +30 -0
  215. package/dist/templates/nestjs-library/.prettierrc +6 -0
  216. package/dist/templates/nestjs-library/LICENSE +21 -0
  217. package/dist/templates/nestjs-library/Makefile +60 -0
  218. package/dist/templates/nestjs-library/README.md +3 -0
  219. package/dist/templates/nestjs-library/index.d.ts +1 -0
  220. package/dist/templates/nestjs-library/index.js +6 -0
  221. package/dist/templates/nestjs-library/index.ts +1 -0
  222. package/dist/templates/nestjs-library/lib/index.ts +2 -0
  223. package/dist/templates/nestjs-library/package.json +41 -0
  224. package/dist/templates/nestjs-library/tsconfig.build.json +4 -0
  225. package/dist/templates/nestjs-library/tsconfig.json +18 -0
  226. package/dist/templates/ts-library/.dockerignore +2 -0
  227. package/dist/templates/ts-library/.eslintrc.js +24 -0
  228. package/dist/templates/ts-library/.gitignore-rename +37 -0
  229. package/dist/templates/ts-library/.gitlab-ci.yml +135 -0
  230. package/dist/templates/ts-library/.npmignore-rename +30 -0
  231. package/dist/templates/ts-library/.prettierrc +6 -0
  232. package/dist/templates/ts-library/LICENSE +21 -0
  233. package/dist/templates/ts-library/Makefile +58 -0
  234. package/dist/templates/ts-library/README.md +1 -0
  235. package/dist/templates/ts-library/index.d.ts +1 -0
  236. package/dist/templates/ts-library/index.js +6 -0
  237. package/dist/templates/ts-library/index.ts +1 -0
  238. package/dist/templates/ts-library/lib/index.ts +1 -0
  239. package/dist/templates/ts-library/lib/samples/index.ts +5 -0
  240. package/dist/templates/ts-library/lib/samples/samples-function.ts +3 -0
  241. package/dist/templates/ts-library/package.json +34 -0
  242. package/dist/templates/ts-library/test/jest-e2e.json +9 -0
  243. package/dist/templates/ts-library/test/sample.e2e-spec.ts +10 -0
  244. package/dist/templates/ts-library/tsconfig.build.json +4 -0
  245. package/dist/templates/ts-library/tsconfig.json +18 -0
  246. package/dist/utils/env.js +146 -0
  247. package/dist/utils/env.js.map +1 -0
  248. package/dist/utils/template.js +362 -1
  249. package/dist/utils/template.js.map +1 -1
  250. package/package.json +9 -5
  251. package/src/index.ts +0 -182
  252. 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
+ }