ソースを参照

update sso keycloak, get all & show hospital area, get area by sales, feature sales

pearlgw 2 ヶ月 前
コミット
66d98a85b6

+ 2 - 0
index.js

@@ -17,8 +17,10 @@ const logRoutes = require('./src/routes/superadmin/LogRoute.js')
17 17
 const areaRoutes = require('./src/routes/sales/AreaRoute.js')
18 18
 const vendorSalesRoutes = require('./src/routes/sales/VendorRoute.js')
19 19
 const { port } = require('./config/config.js')
20
+const keycloak = require('./src/middleware/Keycloak.js');
20 21
 
21 22
 app.use(cors())
23
+app.use(keycloak.middleware());
22 24
 app.use(express.json())
23 25
 app.use('/storage/', express.static(path.join(__dirname, 'storage/')));
24 26
 

+ 658 - 0
package-lock.json

@@ -21,6 +21,7 @@
21 21
         "dotenv": "^16.5.0",
22 22
         "express": "^5.1.0",
23 23
         "jsonwebtoken": "^9.0.2",
24
+        "keycloak-connect": "^26.1.1",
24 25
         "multer": "^2.0.1",
25 26
         "pg": "^8.16.2",
26 27
         "qs": "^6.14.0"
@@ -127,6 +128,40 @@
127 128
         "@prisma/debug": "6.10.1"
128 129
       }
129 130
     },
131
+    "node_modules/@testim/chrome-version": {
132
+      "version": "1.1.4",
133
+      "resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.4.tgz",
134
+      "integrity": "sha512-kIhULpw9TrGYnHp/8VfdcneIcxKnLixmADtukQRtJUmsVlMg0niMkwV0xZmi8hqa57xqilIHjWFA0GKvEjVU5g==",
135
+      "license": "MIT",
136
+      "optional": true
137
+    },
138
+    "node_modules/@tootallnate/quickjs-emscripten": {
139
+      "version": "0.23.0",
140
+      "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
141
+      "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==",
142
+      "license": "MIT",
143
+      "optional": true
144
+    },
145
+    "node_modules/@types/node": {
146
+      "version": "24.0.10",
147
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.10.tgz",
148
+      "integrity": "sha512-ENHwaH+JIRTDIEEbDK6QSQntAYGtbvdDXnMXnZaZ6k13Du1dPMmprkEHIL7ok2Wl2aZevetwTAb5S+7yIF+enA==",
149
+      "license": "MIT",
150
+      "optional": true,
151
+      "dependencies": {
152
+        "undici-types": "~7.8.0"
153
+      }
154
+    },
155
+    "node_modules/@types/yauzl": {
156
+      "version": "2.10.3",
157
+      "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
158
+      "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==",
159
+      "license": "MIT",
160
+      "optional": true,
161
+      "dependencies": {
162
+        "@types/node": "*"
163
+      }
164
+    },
130 165
     "node_modules/accepts": {
131 166
       "version": "2.0.0",
132 167
       "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
@@ -140,12 +175,47 @@
140 175
         "node": ">= 0.6"
141 176
       }
142 177
     },
178
+    "node_modules/agent-base": {
179
+      "version": "7.1.3",
180
+      "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz",
181
+      "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==",
182
+      "license": "MIT",
183
+      "optional": true,
184
+      "engines": {
185
+        "node": ">= 14"
186
+      }
187
+    },
143 188
     "node_modules/append-field": {
144 189
       "version": "1.0.0",
145 190
       "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
146 191
       "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==",
147 192
       "license": "MIT"
148 193
     },
194
+    "node_modules/asn1.js": {
195
+      "version": "5.4.1",
196
+      "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
197
+      "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
198
+      "license": "MIT",
199
+      "dependencies": {
200
+        "bn.js": "^4.0.0",
201
+        "inherits": "^2.0.1",
202
+        "minimalistic-assert": "^1.0.0",
203
+        "safer-buffer": "^2.1.0"
204
+      }
205
+    },
206
+    "node_modules/ast-types": {
207
+      "version": "0.13.4",
208
+      "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz",
209
+      "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==",
210
+      "license": "MIT",
211
+      "optional": true,
212
+      "dependencies": {
213
+        "tslib": "^2.0.1"
214
+      },
215
+      "engines": {
216
+        "node": ">=4"
217
+      }
218
+    },
149 219
     "node_modules/asynckit": {
150 220
       "version": "0.4.0",
151 221
       "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -163,6 +233,16 @@
163 233
         "proxy-from-env": "^1.1.0"
164 234
       }
165 235
     },
236
+    "node_modules/basic-ftp": {
237
+      "version": "5.0.5",
238
+      "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz",
239
+      "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==",
240
+      "license": "MIT",
241
+      "optional": true,
242
+      "engines": {
243
+        "node": ">=10.0.0"
244
+      }
245
+    },
166 246
     "node_modules/bcrypt": {
167 247
       "version": "6.0.0",
168 248
       "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz",
@@ -177,6 +257,12 @@
177 257
         "node": ">= 18"
178 258
       }
179 259
     },
260
+    "node_modules/bn.js": {
261
+      "version": "4.12.2",
262
+      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz",
263
+      "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==",
264
+      "license": "MIT"
265
+    },
180 266
     "node_modules/body-parser": {
181 267
       "version": "2.2.0",
182 268
       "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz",
@@ -197,6 +283,22 @@
197 283
         "node": ">=18"
198 284
       }
199 285
     },
286
+    "node_modules/brorand": {
287
+      "version": "1.1.0",
288
+      "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
289
+      "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==",
290
+      "license": "MIT"
291
+    },
292
+    "node_modules/buffer-crc32": {
293
+      "version": "0.2.13",
294
+      "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
295
+      "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
296
+      "license": "MIT",
297
+      "optional": true,
298
+      "engines": {
299
+        "node": "*"
300
+      }
301
+    },
200 302
     "node_modules/buffer-equal-constant-time": {
201 303
       "version": "1.0.1",
202 304
       "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
@@ -258,6 +360,29 @@
258 360
         "url": "https://github.com/sponsors/ljharb"
259 361
       }
260 362
     },
363
+    "node_modules/chromedriver": {
364
+      "version": "138.0.1",
365
+      "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-138.0.1.tgz",
366
+      "integrity": "sha512-QS/Z1qB2OpKsPUlJjkfKmpf9lGw6ObB0dX5+dP3M0gdtbu80TUnS+EjXbtu6YkbMfr2/Qt8IfOONrawNW1GwhA==",
367
+      "hasInstallScript": true,
368
+      "license": "Apache-2.0",
369
+      "optional": true,
370
+      "dependencies": {
371
+        "@testim/chrome-version": "^1.1.4",
372
+        "axios": "^1.7.4",
373
+        "compare-versions": "^6.1.0",
374
+        "extract-zip": "^2.0.1",
375
+        "proxy-agent": "^6.4.0",
376
+        "proxy-from-env": "^1.1.0",
377
+        "tcp-port-used": "^1.0.2"
378
+      },
379
+      "bin": {
380
+        "chromedriver": "bin/chromedriver"
381
+      },
382
+      "engines": {
383
+        "node": ">=20"
384
+      }
385
+    },
261 386
     "node_modules/combined-stream": {
262 387
       "version": "1.0.8",
263 388
       "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -270,6 +395,13 @@
270 395
         "node": ">= 0.8"
271 396
       }
272 397
     },
398
+    "node_modules/compare-versions": {
399
+      "version": "6.1.1",
400
+      "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz",
401
+      "integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==",
402
+      "license": "MIT",
403
+      "optional": true
404
+    },
273 405
     "node_modules/concat-stream": {
274 406
       "version": "2.0.0",
275 407
       "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
@@ -337,6 +469,16 @@
337 469
         "node": ">= 0.10"
338 470
       }
339 471
     },
472
+    "node_modules/data-uri-to-buffer": {
473
+      "version": "6.0.2",
474
+      "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz",
475
+      "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==",
476
+      "license": "MIT",
477
+      "optional": true,
478
+      "engines": {
479
+        "node": ">= 14"
480
+      }
481
+    },
340 482
     "node_modules/date-fns": {
341 483
       "version": "4.1.0",
342 484
       "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
@@ -385,6 +527,28 @@
385 527
         }
386 528
       }
387 529
     },
530
+    "node_modules/deep-is": {
531
+      "version": "0.1.4",
532
+      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
533
+      "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
534
+      "license": "MIT",
535
+      "optional": true
536
+    },
537
+    "node_modules/degenerator": {
538
+      "version": "5.0.1",
539
+      "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz",
540
+      "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==",
541
+      "license": "MIT",
542
+      "optional": true,
543
+      "dependencies": {
544
+        "ast-types": "^0.13.4",
545
+        "escodegen": "^2.1.0",
546
+        "esprima": "^4.0.1"
547
+      },
548
+      "engines": {
549
+        "node": ">= 14"
550
+      }
551
+    },
388 552
     "node_modules/delayed-stream": {
389 553
       "version": "1.0.0",
390 554
       "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -444,6 +608,21 @@
444 608
       "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
445 609
       "license": "MIT"
446 610
     },
611
+    "node_modules/elliptic": {
612
+      "version": "6.6.1",
613
+      "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz",
614
+      "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==",
615
+      "license": "MIT",
616
+      "dependencies": {
617
+        "bn.js": "^4.11.9",
618
+        "brorand": "^1.1.0",
619
+        "hash.js": "^1.0.0",
620
+        "hmac-drbg": "^1.0.1",
621
+        "inherits": "^2.0.4",
622
+        "minimalistic-assert": "^1.0.1",
623
+        "minimalistic-crypto-utils": "^1.0.1"
624
+      }
625
+    },
447 626
     "node_modules/encodeurl": {
448 627
       "version": "2.0.0",
449 628
       "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
@@ -453,6 +632,16 @@
453 632
         "node": ">= 0.8"
454 633
       }
455 634
     },
635
+    "node_modules/end-of-stream": {
636
+      "version": "1.4.5",
637
+      "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
638
+      "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
639
+      "license": "MIT",
640
+      "optional": true,
641
+      "dependencies": {
642
+        "once": "^1.4.0"
643
+      }
644
+    },
456 645
     "node_modules/es-define-property": {
457 646
       "version": "1.0.1",
458 647
       "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
@@ -504,6 +693,62 @@
504 693
       "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
505 694
       "license": "MIT"
506 695
     },
696
+    "node_modules/escodegen": {
697
+      "version": "2.1.0",
698
+      "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
699
+      "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
700
+      "license": "BSD-2-Clause",
701
+      "optional": true,
702
+      "dependencies": {
703
+        "esprima": "^4.0.1",
704
+        "estraverse": "^5.2.0",
705
+        "esutils": "^2.0.2"
706
+      },
707
+      "bin": {
708
+        "escodegen": "bin/escodegen.js",
709
+        "esgenerate": "bin/esgenerate.js"
710
+      },
711
+      "engines": {
712
+        "node": ">=6.0"
713
+      },
714
+      "optionalDependencies": {
715
+        "source-map": "~0.6.1"
716
+      }
717
+    },
718
+    "node_modules/esprima": {
719
+      "version": "4.0.1",
720
+      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
721
+      "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
722
+      "license": "BSD-2-Clause",
723
+      "optional": true,
724
+      "bin": {
725
+        "esparse": "bin/esparse.js",
726
+        "esvalidate": "bin/esvalidate.js"
727
+      },
728
+      "engines": {
729
+        "node": ">=4"
730
+      }
731
+    },
732
+    "node_modules/estraverse": {
733
+      "version": "5.3.0",
734
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
735
+      "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
736
+      "license": "BSD-2-Clause",
737
+      "optional": true,
738
+      "engines": {
739
+        "node": ">=4.0"
740
+      }
741
+    },
742
+    "node_modules/esutils": {
743
+      "version": "2.0.3",
744
+      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
745
+      "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
746
+      "license": "BSD-2-Clause",
747
+      "optional": true,
748
+      "engines": {
749
+        "node": ">=0.10.0"
750
+      }
751
+    },
507 752
     "node_modules/etag": {
508 753
       "version": "1.8.1",
509 754
       "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
@@ -555,6 +800,37 @@
555 800
         "url": "https://opencollective.com/express"
556 801
       }
557 802
     },
803
+    "node_modules/extract-zip": {
804
+      "version": "2.0.1",
805
+      "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
806
+      "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
807
+      "license": "BSD-2-Clause",
808
+      "optional": true,
809
+      "dependencies": {
810
+        "debug": "^4.1.1",
811
+        "get-stream": "^5.1.0",
812
+        "yauzl": "^2.10.0"
813
+      },
814
+      "bin": {
815
+        "extract-zip": "cli.js"
816
+      },
817
+      "engines": {
818
+        "node": ">= 10.17.0"
819
+      },
820
+      "optionalDependencies": {
821
+        "@types/yauzl": "^2.9.1"
822
+      }
823
+    },
824
+    "node_modules/fd-slicer": {
825
+      "version": "1.1.0",
826
+      "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
827
+      "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
828
+      "license": "MIT",
829
+      "optional": true,
830
+      "dependencies": {
831
+        "pend": "~1.2.0"
832
+      }
833
+    },
558 834
     "node_modules/finalhandler": {
559 835
       "version": "2.1.0",
560 836
       "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz",
@@ -693,6 +969,37 @@
693 969
         "node": ">= 0.4"
694 970
       }
695 971
     },
972
+    "node_modules/get-stream": {
973
+      "version": "5.2.0",
974
+      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
975
+      "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
976
+      "license": "MIT",
977
+      "optional": true,
978
+      "dependencies": {
979
+        "pump": "^3.0.0"
980
+      },
981
+      "engines": {
982
+        "node": ">=8"
983
+      },
984
+      "funding": {
985
+        "url": "https://github.com/sponsors/sindresorhus"
986
+      }
987
+    },
988
+    "node_modules/get-uri": {
989
+      "version": "6.0.4",
990
+      "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz",
991
+      "integrity": "sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==",
992
+      "license": "MIT",
993
+      "optional": true,
994
+      "dependencies": {
995
+        "basic-ftp": "^5.0.2",
996
+        "data-uri-to-buffer": "^6.0.2",
997
+        "debug": "^4.3.4"
998
+      },
999
+      "engines": {
1000
+        "node": ">= 14"
1001
+      }
1002
+    },
696 1003
     "node_modules/gopd": {
697 1004
       "version": "1.2.0",
698 1005
       "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
@@ -732,6 +1039,16 @@
732 1039
         "url": "https://github.com/sponsors/ljharb"
733 1040
       }
734 1041
     },
1042
+    "node_modules/hash.js": {
1043
+      "version": "1.1.7",
1044
+      "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
1045
+      "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
1046
+      "license": "MIT",
1047
+      "dependencies": {
1048
+        "inherits": "^2.0.3",
1049
+        "minimalistic-assert": "^1.0.1"
1050
+      }
1051
+    },
735 1052
     "node_modules/hasown": {
736 1053
       "version": "2.0.2",
737 1054
       "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
@@ -744,6 +1061,17 @@
744 1061
         "node": ">= 0.4"
745 1062
       }
746 1063
     },
1064
+    "node_modules/hmac-drbg": {
1065
+      "version": "1.0.1",
1066
+      "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
1067
+      "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==",
1068
+      "license": "MIT",
1069
+      "dependencies": {
1070
+        "hash.js": "^1.0.3",
1071
+        "minimalistic-assert": "^1.0.0",
1072
+        "minimalistic-crypto-utils": "^1.0.1"
1073
+      }
1074
+    },
747 1075
     "node_modules/http-errors": {
748 1076
       "version": "2.0.0",
749 1077
       "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
@@ -769,6 +1097,34 @@
769 1097
         "node": ">= 0.8"
770 1098
       }
771 1099
     },
1100
+    "node_modules/http-proxy-agent": {
1101
+      "version": "7.0.2",
1102
+      "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
1103
+      "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
1104
+      "license": "MIT",
1105
+      "optional": true,
1106
+      "dependencies": {
1107
+        "agent-base": "^7.1.0",
1108
+        "debug": "^4.3.4"
1109
+      },
1110
+      "engines": {
1111
+        "node": ">= 14"
1112
+      }
1113
+    },
1114
+    "node_modules/https-proxy-agent": {
1115
+      "version": "7.0.6",
1116
+      "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
1117
+      "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
1118
+      "license": "MIT",
1119
+      "optional": true,
1120
+      "dependencies": {
1121
+        "agent-base": "^7.1.2",
1122
+        "debug": "4"
1123
+      },
1124
+      "engines": {
1125
+        "node": ">= 14"
1126
+      }
1127
+    },
772 1128
     "node_modules/iconv-lite": {
773 1129
       "version": "0.6.3",
774 1130
       "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
@@ -787,6 +1143,30 @@
787 1143
       "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
788 1144
       "license": "ISC"
789 1145
     },
1146
+    "node_modules/ip-address": {
1147
+      "version": "9.0.5",
1148
+      "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
1149
+      "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
1150
+      "license": "MIT",
1151
+      "optional": true,
1152
+      "dependencies": {
1153
+        "jsbn": "1.1.0",
1154
+        "sprintf-js": "^1.1.3"
1155
+      },
1156
+      "engines": {
1157
+        "node": ">= 12"
1158
+      }
1159
+    },
1160
+    "node_modules/ip-regex": {
1161
+      "version": "4.3.0",
1162
+      "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz",
1163
+      "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==",
1164
+      "license": "MIT",
1165
+      "optional": true,
1166
+      "engines": {
1167
+        "node": ">=8"
1168
+      }
1169
+    },
790 1170
     "node_modules/ipaddr.js": {
791 1171
       "version": "1.9.1",
792 1172
       "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@@ -802,6 +1182,28 @@
802 1182
       "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
803 1183
       "license": "MIT"
804 1184
     },
1185
+    "node_modules/is-url": {
1186
+      "version": "1.2.4",
1187
+      "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz",
1188
+      "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==",
1189
+      "license": "MIT",
1190
+      "optional": true
1191
+    },
1192
+    "node_modules/is2": {
1193
+      "version": "2.0.9",
1194
+      "resolved": "https://registry.npmjs.org/is2/-/is2-2.0.9.tgz",
1195
+      "integrity": "sha512-rZkHeBn9Zzq52sd9IUIV3a5mfwBY+o2HePMh0wkGBM4z4qjvy2GwVxQ6nNXSfw6MmVP6gf1QIlWjiOavhM3x5g==",
1196
+      "license": "MIT",
1197
+      "optional": true,
1198
+      "dependencies": {
1199
+        "deep-is": "^0.1.3",
1200
+        "ip-regex": "^4.1.0",
1201
+        "is-url": "^1.2.4"
1202
+      },
1203
+      "engines": {
1204
+        "node": ">=v0.10.0"
1205
+      }
1206
+    },
805 1207
     "node_modules/jiti": {
806 1208
       "version": "2.4.2",
807 1209
       "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz",
@@ -812,6 +1214,13 @@
812 1214
         "jiti": "lib/jiti-cli.mjs"
813 1215
       }
814 1216
     },
1217
+    "node_modules/jsbn": {
1218
+      "version": "1.1.0",
1219
+      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
1220
+      "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==",
1221
+      "license": "MIT",
1222
+      "optional": true
1223
+    },
815 1224
     "node_modules/jsonwebtoken": {
816 1225
       "version": "9.0.2",
817 1226
       "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
@@ -845,6 +1254,17 @@
845 1254
         "safe-buffer": "^5.0.1"
846 1255
       }
847 1256
     },
1257
+    "node_modules/jwk-to-pem": {
1258
+      "version": "2.0.7",
1259
+      "resolved": "https://registry.npmjs.org/jwk-to-pem/-/jwk-to-pem-2.0.7.tgz",
1260
+      "integrity": "sha512-cSVphrmWr6reVchuKQZdfSs4U9c5Y4hwZggPoz6cbVnTpAVgGRpEuQng86IyqLeGZlhTh+c4MAreB6KbdQDKHQ==",
1261
+      "license": "Apache-2.0",
1262
+      "dependencies": {
1263
+        "asn1.js": "^5.3.0",
1264
+        "elliptic": "^6.6.1",
1265
+        "safe-buffer": "^5.0.1"
1266
+      }
1267
+    },
848 1268
     "node_modules/jws": {
849 1269
       "version": "3.2.2",
850 1270
       "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
@@ -855,6 +1275,21 @@
855 1275
         "safe-buffer": "^5.0.1"
856 1276
       }
857 1277
     },
1278
+    "node_modules/keycloak-connect": {
1279
+      "version": "26.1.1",
1280
+      "resolved": "https://registry.npmjs.org/keycloak-connect/-/keycloak-connect-26.1.1.tgz",
1281
+      "integrity": "sha512-2wvNJXldB9Em+mp6liJ+AnftcJovFEvNhUgv3hblNDmVihBoBqn4zFlwLIN41lo0H8CicB2T86xZ5U2MiQ9FFA==",
1282
+      "license": "Apache-2.0",
1283
+      "dependencies": {
1284
+        "jwk-to-pem": "^2.0.0"
1285
+      },
1286
+      "engines": {
1287
+        "node": ">=14"
1288
+      },
1289
+      "optionalDependencies": {
1290
+        "chromedriver": "latest"
1291
+      }
1292
+    },
858 1293
     "node_modules/lodash.includes": {
859 1294
       "version": "4.3.0",
860 1295
       "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
@@ -897,6 +1332,16 @@
897 1332
       "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
898 1333
       "license": "MIT"
899 1334
     },
1335
+    "node_modules/lru-cache": {
1336
+      "version": "7.18.3",
1337
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
1338
+      "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
1339
+      "license": "ISC",
1340
+      "optional": true,
1341
+      "engines": {
1342
+        "node": ">=12"
1343
+      }
1344
+    },
900 1345
     "node_modules/math-intrinsics": {
901 1346
       "version": "1.1.0",
902 1347
       "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -948,6 +1393,18 @@
948 1393
         "node": ">= 0.6"
949 1394
       }
950 1395
     },
1396
+    "node_modules/minimalistic-assert": {
1397
+      "version": "1.0.1",
1398
+      "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
1399
+      "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
1400
+      "license": "ISC"
1401
+    },
1402
+    "node_modules/minimalistic-crypto-utils": {
1403
+      "version": "1.0.1",
1404
+      "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
1405
+      "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==",
1406
+      "license": "MIT"
1407
+    },
951 1408
     "node_modules/minimist": {
952 1409
       "version": "1.2.8",
953 1410
       "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
@@ -1045,6 +1502,16 @@
1045 1502
         "node": ">= 0.6"
1046 1503
       }
1047 1504
     },
1505
+    "node_modules/netmask": {
1506
+      "version": "2.0.2",
1507
+      "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz",
1508
+      "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==",
1509
+      "license": "MIT",
1510
+      "optional": true,
1511
+      "engines": {
1512
+        "node": ">= 0.4.0"
1513
+      }
1514
+    },
1048 1515
     "node_modules/node-addon-api": {
1049 1516
       "version": "8.4.0",
1050 1517
       "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.4.0.tgz",
@@ -1107,6 +1574,40 @@
1107 1574
         "wrappy": "1"
1108 1575
       }
1109 1576
     },
1577
+    "node_modules/pac-proxy-agent": {
1578
+      "version": "7.2.0",
1579
+      "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz",
1580
+      "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==",
1581
+      "license": "MIT",
1582
+      "optional": true,
1583
+      "dependencies": {
1584
+        "@tootallnate/quickjs-emscripten": "^0.23.0",
1585
+        "agent-base": "^7.1.2",
1586
+        "debug": "^4.3.4",
1587
+        "get-uri": "^6.0.1",
1588
+        "http-proxy-agent": "^7.0.0",
1589
+        "https-proxy-agent": "^7.0.6",
1590
+        "pac-resolver": "^7.0.1",
1591
+        "socks-proxy-agent": "^8.0.5"
1592
+      },
1593
+      "engines": {
1594
+        "node": ">= 14"
1595
+      }
1596
+    },
1597
+    "node_modules/pac-resolver": {
1598
+      "version": "7.0.1",
1599
+      "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz",
1600
+      "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==",
1601
+      "license": "MIT",
1602
+      "optional": true,
1603
+      "dependencies": {
1604
+        "degenerator": "^5.0.0",
1605
+        "netmask": "^2.0.2"
1606
+      },
1607
+      "engines": {
1608
+        "node": ">= 14"
1609
+      }
1610
+    },
1110 1611
     "node_modules/parseurl": {
1111 1612
       "version": "1.3.3",
1112 1613
       "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@@ -1125,6 +1626,13 @@
1125 1626
         "node": ">=16"
1126 1627
       }
1127 1628
     },
1629
+    "node_modules/pend": {
1630
+      "version": "1.2.0",
1631
+      "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
1632
+      "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
1633
+      "license": "MIT",
1634
+      "optional": true
1635
+    },
1128 1636
     "node_modules/pg": {
1129 1637
       "version": "8.16.2",
1130 1638
       "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.2.tgz",
@@ -1292,12 +1800,43 @@
1292 1800
         "node": ">= 0.10"
1293 1801
       }
1294 1802
     },
1803
+    "node_modules/proxy-agent": {
1804
+      "version": "6.5.0",
1805
+      "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz",
1806
+      "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==",
1807
+      "license": "MIT",
1808
+      "optional": true,
1809
+      "dependencies": {
1810
+        "agent-base": "^7.1.2",
1811
+        "debug": "^4.3.4",
1812
+        "http-proxy-agent": "^7.0.1",
1813
+        "https-proxy-agent": "^7.0.6",
1814
+        "lru-cache": "^7.14.1",
1815
+        "pac-proxy-agent": "^7.1.0",
1816
+        "proxy-from-env": "^1.1.0",
1817
+        "socks-proxy-agent": "^8.0.5"
1818
+      },
1819
+      "engines": {
1820
+        "node": ">= 14"
1821
+      }
1822
+    },
1295 1823
     "node_modules/proxy-from-env": {
1296 1824
       "version": "1.1.0",
1297 1825
       "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
1298 1826
       "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
1299 1827
       "license": "MIT"
1300 1828
     },
1829
+    "node_modules/pump": {
1830
+      "version": "3.0.3",
1831
+      "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
1832
+      "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==",
1833
+      "license": "MIT",
1834
+      "optional": true,
1835
+      "dependencies": {
1836
+        "end-of-stream": "^1.1.0",
1837
+        "once": "^1.3.1"
1838
+      }
1839
+    },
1301 1840
     "node_modules/qs": {
1302 1841
       "version": "6.14.0",
1303 1842
       "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
@@ -1520,6 +2059,57 @@
1520 2059
         "url": "https://github.com/sponsors/ljharb"
1521 2060
       }
1522 2061
     },
2062
+    "node_modules/smart-buffer": {
2063
+      "version": "4.2.0",
2064
+      "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
2065
+      "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
2066
+      "license": "MIT",
2067
+      "optional": true,
2068
+      "engines": {
2069
+        "node": ">= 6.0.0",
2070
+        "npm": ">= 3.0.0"
2071
+      }
2072
+    },
2073
+    "node_modules/socks": {
2074
+      "version": "2.8.5",
2075
+      "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.5.tgz",
2076
+      "integrity": "sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww==",
2077
+      "license": "MIT",
2078
+      "optional": true,
2079
+      "dependencies": {
2080
+        "ip-address": "^9.0.5",
2081
+        "smart-buffer": "^4.2.0"
2082
+      },
2083
+      "engines": {
2084
+        "node": ">= 10.0.0",
2085
+        "npm": ">= 3.0.0"
2086
+      }
2087
+    },
2088
+    "node_modules/socks-proxy-agent": {
2089
+      "version": "8.0.5",
2090
+      "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz",
2091
+      "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==",
2092
+      "license": "MIT",
2093
+      "optional": true,
2094
+      "dependencies": {
2095
+        "agent-base": "^7.1.2",
2096
+        "debug": "^4.3.4",
2097
+        "socks": "^2.8.3"
2098
+      },
2099
+      "engines": {
2100
+        "node": ">= 14"
2101
+      }
2102
+    },
2103
+    "node_modules/source-map": {
2104
+      "version": "0.6.1",
2105
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
2106
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
2107
+      "license": "BSD-3-Clause",
2108
+      "optional": true,
2109
+      "engines": {
2110
+        "node": ">=0.10.0"
2111
+      }
2112
+    },
1523 2113
     "node_modules/split2": {
1524 2114
       "version": "4.2.0",
1525 2115
       "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
@@ -1529,6 +2119,13 @@
1529 2119
         "node": ">= 10.x"
1530 2120
       }
1531 2121
     },
2122
+    "node_modules/sprintf-js": {
2123
+      "version": "1.1.3",
2124
+      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
2125
+      "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
2126
+      "license": "BSD-3-Clause",
2127
+      "optional": true
2128
+    },
1532 2129
     "node_modules/statuses": {
1533 2130
       "version": "2.0.2",
1534 2131
       "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
@@ -1555,6 +2152,42 @@
1555 2152
         "safe-buffer": "~5.2.0"
1556 2153
       }
1557 2154
     },
2155
+    "node_modules/tcp-port-used": {
2156
+      "version": "1.0.2",
2157
+      "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.2.tgz",
2158
+      "integrity": "sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==",
2159
+      "license": "MIT",
2160
+      "optional": true,
2161
+      "dependencies": {
2162
+        "debug": "4.3.1",
2163
+        "is2": "^2.0.6"
2164
+      }
2165
+    },
2166
+    "node_modules/tcp-port-used/node_modules/debug": {
2167
+      "version": "4.3.1",
2168
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
2169
+      "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
2170
+      "license": "MIT",
2171
+      "optional": true,
2172
+      "dependencies": {
2173
+        "ms": "2.1.2"
2174
+      },
2175
+      "engines": {
2176
+        "node": ">=6.0"
2177
+      },
2178
+      "peerDependenciesMeta": {
2179
+        "supports-color": {
2180
+          "optional": true
2181
+        }
2182
+      }
2183
+    },
2184
+    "node_modules/tcp-port-used/node_modules/ms": {
2185
+      "version": "2.1.2",
2186
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
2187
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
2188
+      "license": "MIT",
2189
+      "optional": true
2190
+    },
1558 2191
     "node_modules/toidentifier": {
1559 2192
       "version": "1.0.1",
1560 2193
       "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
@@ -1564,6 +2197,13 @@
1564 2197
         "node": ">=0.6"
1565 2198
       }
1566 2199
     },
2200
+    "node_modules/tslib": {
2201
+      "version": "2.8.1",
2202
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
2203
+      "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
2204
+      "license": "0BSD",
2205
+      "optional": true
2206
+    },
1567 2207
     "node_modules/type-is": {
1568 2208
       "version": "2.0.1",
1569 2209
       "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
@@ -1584,6 +2224,13 @@
1584 2224
       "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
1585 2225
       "license": "MIT"
1586 2226
     },
2227
+    "node_modules/undici-types": {
2228
+      "version": "7.8.0",
2229
+      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz",
2230
+      "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==",
2231
+      "license": "MIT",
2232
+      "optional": true
2233
+    },
1587 2234
     "node_modules/unpipe": {
1588 2235
       "version": "1.0.0",
1589 2236
       "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
@@ -1622,6 +2269,17 @@
1622 2269
       "engines": {
1623 2270
         "node": ">=0.4"
1624 2271
       }
2272
+    },
2273
+    "node_modules/yauzl": {
2274
+      "version": "2.10.0",
2275
+      "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
2276
+      "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
2277
+      "license": "MIT",
2278
+      "optional": true,
2279
+      "dependencies": {
2280
+        "buffer-crc32": "~0.2.3",
2281
+        "fd-slicer": "~1.1.0"
2282
+      }
1625 2283
     }
1626 2284
   }
1627 2285
 }

+ 1 - 0
package.json

@@ -25,6 +25,7 @@
25 25
     "dotenv": "^16.5.0",
26 26
     "express": "^5.1.0",
27 27
     "jsonwebtoken": "^9.0.2",
28
+    "keycloak-connect": "^26.1.1",
28 29
     "multer": "^2.0.1",
29 30
     "pg": "^8.16.2",
30 31
     "qs": "^6.14.0"

+ 2 - 0
prisma/migrations/20250705091358_update_field_user_area/migration.sql

@@ -0,0 +1,2 @@
1
+-- DropForeignKey
2
+ALTER TABLE "user_areas" DROP CONSTRAINT "user_areas_user_id_fkey";

+ 0 - 2
prisma/schema.prisma

@@ -55,7 +55,6 @@ model User {
55 55
   updatedAt  DateTime   @updatedAt
56 56
   deletedAt  DateTime?
57 57
   hospitals  Hospital[]
58
-  user_areas UserArea[]
59 58
   vendors    Vendor[]
60 59
 
61 60
   @@map("users")
@@ -136,7 +135,6 @@ model UserArea {
136 135
   id          String    @id @default(uuid())
137 136
   user_id     String
138 137
   province_id String
139
-  user        User      @relation(fields: [user_id], references: [id])
140 138
   province    Province  @relation(fields: [province_id], references: [id])
141 139
   createdAt   DateTime  @default(now())
142 140
   updatedAt   DateTime  @updatedAt

+ 1 - 1
src/controllers/sales/AreaController.js

@@ -9,7 +9,7 @@ exports.getAllAreaByUser = async (req, res) => {
9 9
 
10 10
         const { areas, total } = await getAllAreaByUserService({ page, limit, search, sortBy, orderBy }, req);
11 11
 
12
-        return UserAreaCollection(req, res, areas, total, page, limit, 'Area data successfully retrieved');
12
+        return UserAreaCollection({ req, res, data: areas, total, page, limit, message: 'Area data successfully retrieved' });
13 13
     } catch (err) {
14 14
         return errorResponse(res, err);
15 15
     }

+ 3 - 3
src/controllers/sales/HospitalController.js

@@ -11,7 +11,7 @@ exports.getAllHospitalByArea = async (req, res) => {
11 11
 
12 12
         const { hospitals, total } = await getAllHospitalByAreaService({ page, limit, search, sortBy, orderBy, province, city, type, ownership, progress_status }, req);
13 13
 
14
-        return HospitalCollection(req, res, hospitals, total, page, limit, 'Hospital data successfully retrieved');
14
+        return HospitalCollection({ req, res, data: hospitals, total, page, limit, message: 'Hospital data successfully retrieved' });
15 15
     } catch (err) {
16 16
         return errorResponse(res, err);
17 17
     }
@@ -41,8 +41,8 @@ exports.updateHospital = async (req, res) => {
41 41
 exports.showHospital = async (req, res) => {
42 42
     try {
43 43
         const id = req.params.id;
44
-        const data = await showHospitalService(id);
45
-        return HospitalResource(res, data, 'Success show hospital');
44
+        const { hospital, userName } = await showHospitalService(id);
45
+        return HospitalResource(res, hospital, userName, 'Success show hospital');
46 46
     } catch (err) {
47 47
         return errorResponse(res, err);
48 48
     }

+ 21 - 0
src/middleware/CheckRoles.js

@@ -0,0 +1,21 @@
1
+module.exports = (allowedRoles = []) => {
2
+    return async (req, res, next) => {
3
+        try {
4
+            const tokenData = req.tokenData;
5
+            const roles = tokenData.realm_access?.roles || [];
6
+
7
+            const hasAccess = allowedRoles.some(role => roles.includes(role));
8
+
9
+            if (hasAccess) {
10
+                return next();
11
+            }
12
+
13
+            const error = new Error('Access Denied');
14
+            // const error = new Error(`Access Denied: You need one of the following roles: ${allowedRoles.join(", ")}`);
15
+            error.statusCode = 403;
16
+            throw error;
17
+        } catch (error) {
18
+            next(error);
19
+        }
20
+    };
21
+};

+ 22 - 0
src/middleware/ExtractToken.js

@@ -0,0 +1,22 @@
1
+const jwt = require("jsonwebtoken");
2
+
3
+module.exports = async (req, res, next) => {
4
+    try {
5
+        // Decode access token
6
+        const bearerToken = req.headers.authorization;
7
+        // bearerToken would return "Bearer <access_token>"
8
+
9
+        const token = bearerToken.split(" ");
10
+        // token would return ["Bearer", "<access_token>"]
11
+
12
+        const tokenData = jwt.decode(token[1]);
13
+        // tokenData would return user's data
14
+
15
+        // Store decoded token data in request
16
+        req.tokenData = tokenData;
17
+
18
+        next();
19
+    } catch (error) {
20
+        next(error);
21
+    }
22
+}

+ 12 - 0
src/middleware/Keycloak.js

@@ -0,0 +1,12 @@
1
+const Keycloak = require("keycloak-connect");
2
+require('dotenv').config();
3
+
4
+const config = {
5
+  "realm": process.env.KEYCLOAK_REALM,
6
+  "auth-server-url": `${process.env.KEYCLOAK_URL}`,
7
+  "ssl-required": "external",
8
+  "resource": process.env.KEYCLOAK_CLIENT,
9
+  "bearer-only": true
10
+}
11
+
12
+module.exports = new Keycloak({}, config);

+ 1 - 6
src/repository/sales/AreaRepository.js

@@ -9,12 +9,7 @@ const AreaRepository = {
9 9
             orderBy,
10 10
             select: {
11 11
                 id: true,
12
-                user: {
13
-                    select: {
14
-                        id: true,
15
-                        username: true
16
-                    }
17
-                },
12
+                user_id: true,
18 13
                 province: {
19 14
                     select: {
20 15
                         id: true,

+ 4 - 2
src/repository/sales/HospitalRepository.js

@@ -21,7 +21,8 @@ const HospitalRepository = {
21 21
                 image: true,
22 22
                 progress_status: true,
23 23
                 note: true,
24
-                user: { select: { id: true, username: true } },
24
+                // user: { select: { id: true, username: true } },
25
+                created_by: true,
25 26
                 createdAt: true,
26 27
                 updatedAt: true,
27 28
             }
@@ -56,7 +57,8 @@ const HospitalRepository = {
56 57
                 image: true,
57 58
                 progress_status: true,
58 59
                 note: true,
59
-                user: { select: { id: true, username: true } },
60
+                // user: { select: { id: true, username: true } },
61
+                created_by: true,
60 62
                 createdAt: true,
61 63
                 updatedAt: true,
62 64
             }

+ 18 - 9
src/resources/sales/area/UserAreaCollection.js

@@ -1,13 +1,22 @@
1
+const { getUserNameById } = require("../../../utils/CheckUserKeycloak");
1 2
 const { ListResponse } = require("../../../utils/ListResponse");
2 3
 
3
-exports.UserAreaCollection = (req, res, data = [], total = null, page = 1, limit = 10, message = 'Success') => {
4
-    if (typeof total !== 'number') {
5
-        return res.status(200).json({
6
-            success: true,
7
-            message,
8
-            data: Array.isArray(data)
9
-        });
10
-    }
4
+const transformArea = async (data = []) => {
5
+    return Promise.all(data.map(async ({ user_id, ...rest }) => {
6
+        const name = await getUserNameById(user_id);
11 7
 
12
-    return ListResponse({ req, res, data, total, page, limit, message });
8
+        return {
9
+            ...rest,
10
+            user: {
11
+                id: user_id,
12
+                name: name
13
+            },
14
+        };
15
+    }));
16
+};
17
+
18
+exports.UserAreaCollection = async ({ req, res, data = [], total = 0, page = 1, limit = 10, message = 'Success' }) => {
19
+    const formatted = await transformArea(data);
20
+
21
+    return ListResponse({ req, res, data: formatted, total, page, limit, message });
13 22
 };

+ 20 - 15
src/resources/sales/hospital/HospitalCollection.js

@@ -1,22 +1,27 @@
1 1
 const { ListResponse } = require("../../../utils/ListResponse");
2 2
 const { formatISOWithoutTimezone } = require("../../../utils/FormatDate.js");
3
+const { getUserNameById } = require("../../../utils/CheckUserKeycloak.js");
3 4
 
4
-const formatItem = (item) => ({
5
-    ...item,
6
-    createdAt: formatISOWithoutTimezone(item.createdAt),
7
-    updatedAt: formatISOWithoutTimezone(item.updatedAt)
8
-});
5
+// Fungsi transform per item
6
+const transformHospitalList = async (data = []) => {
7
+    return Promise.all(data.map(async ({ created_by, ...rest }) => {
8
+        const name = await getUserNameById(created_by);
9 9
 
10
-exports.HospitalCollection = (req, res, data = [], total = null, page = 1, limit = 10, message = 'Success') => {
11
-    const formattedData = data.map(formatItem);
10
+        return {
11
+            ...rest,
12
+            user: {
13
+                id: created_by,
14
+                name: name
15
+            },
16
+            createdAt: formatISOWithoutTimezone(rest.createdAt),
17
+            updatedAt: formatISOWithoutTimezone(rest.updatedAt)
18
+        };
19
+    }));
20
+};
12 21
 
13
-    if (typeof total !== 'number') {
14
-        return res.status(200).json({
15
-            success: true,
16
-            message,
17
-            data: Array.isArray(formattedData)
18
-        });
19
-    }
22
+// Collection yang async
23
+exports.HospitalCollection = async ({ req, res, data = [], total = 0, page = 1, limit = 10, message = 'Success' }) => {
24
+    const formatted = await transformHospitalList(data);
20 25
 
21
-    return ListResponse({ req, res, data: formattedData, total, page, limit, message });
26
+    return ListResponse({ req, res, data: formatted, total, page, limit, message });
22 27
 };

+ 16 - 8
src/resources/sales/hospital/HospitalResource.js

@@ -1,17 +1,25 @@
1 1
 const { formatISOWithoutTimezone } = require("../../../utils/FormatDate");
2 2
 
3
-const formatItem = (item) => ({
4
-    ...item,
5
-    createdAt: formatISOWithoutTimezone(item.createdAt),
6
-    updatedAt: formatISOWithoutTimezone(item.updatedAt)
7
-});
3
+const formatItem = ({ item, userName }) => {
4
+    const { created_by, ...rest } = item;
8 5
 
9
-exports.HospitalResource = (res, data, message = 'Success') => {
10
-    const formattedData = formatItem(data);
6
+    return {
7
+        ...rest,
8
+        user: {
9
+            id: created_by,
10
+            name: userName
11
+        },
12
+        createdAt: formatISOWithoutTimezone(item.createdAt),
13
+        updatedAt: formatISOWithoutTimezone(item.updatedAt)
14
+    };
15
+};
16
+
17
+exports.HospitalResource = (res, item, userName, message = 'Success') => {
18
+    const formattedData = formatItem({ item, userName });
11 19
 
12 20
     return res.status(200).json({
13 21
         success: true,
14 22
         message,
15 23
         data: formattedData
16 24
     });
17
-};
25
+};

+ 16 - 7
src/routes/admin/CityRoute.js

@@ -1,13 +1,22 @@
1 1
 const express = require('express')
2 2
 const router = express.Router()
3 3
 const cityController = require('../../controllers/admin/CityController.js')
4
-const verifyJWT = require('../../middleware/VerifyJWT.js');
5
-const checkRole = require('../../middleware/CheckRole.js');
4
+// const verifyJWT = require('../../middleware/VerifyJWT.js');
5
+// const checkRole = require('../../middleware/CheckRole.js');
6
+const keycloak = require('../../middleware/Keycloak.js');
7
+const extractToken = require('../../middleware/ExtractToken.js');
8
+const checkRoles = require('../../middleware/CheckRoles.js');
6 9
 
7
-router.get('/', verifyJWT, checkRole(['admin', 'sales']), cityController.getAllCity);
8
-router.post('/', verifyJWT, checkRole(['admin']), cityController.storeCity);
9
-router.get('/:id', verifyJWT, checkRole(['admin', 'sales']), cityController.showCity);
10
-router.patch('/:id', verifyJWT, checkRole(['admin']), cityController.updateCity);
11
-router.delete('/:id', verifyJWT, checkRole(['admin']), cityController.deleteCity);
10
+// router.get('/', verifyJWT, checkRole(['admin', 'sales']), cityController.getAllCity);
11
+// router.post('/', verifyJWT, checkRole(['admin']), cityController.storeCity);
12
+// router.get('/:id', verifyJWT, checkRole(['admin', 'sales']), cityController.showCity);
13
+// router.patch('/:id', verifyJWT, checkRole(['admin']), cityController.updateCity);
14
+// router.delete('/:id', verifyJWT, checkRole(['admin']), cityController.deleteCity);
15
+
16
+router.get('/', [keycloak.protect(), extractToken, checkRoles(["admin", "sales"])], cityController.getAllCity);
17
+router.post('/', [keycloak.protect(), extractToken, checkRoles(['admin'])], cityController.storeCity);
18
+router.get('/:id', [keycloak.protect(), extractToken, checkRoles(["admin", "sales"])], cityController.showCity);
19
+router.patch('/:id', [keycloak.protect(), extractToken, checkRoles(['admin'])], cityController.updateCity);
20
+router.delete('/:id', [keycloak.protect(), extractToken, checkRoles(['admin'])], cityController.deleteCity);
12 21
 
13 22
 module.exports = router;

+ 41 - 17
src/routes/admin/HospitalRoute.js

@@ -3,28 +3,52 @@ const router = express.Router()
3 3
 const hospitalController = require('../../controllers/admin/HospitalController.js')
4 4
 const vendorHistoryController = require('../../controllers/admin/VendorHistoryController.js')
5 5
 const executivesHistoryController = require('../../controllers/admin/ExecutivesHistoryController.js')
6
-const verifyJWT = require('../../middleware/VerifyJWT.js');
7
-const checkRole = require('../../middleware/CheckRole.js');
6
+// const verifyJWT = require('../../middleware/VerifyJWT.js');
7
+// const checkRole = require('../../middleware/CheckRole.js');
8 8
 const upload = require('../../middleware/UploadImage.js');
9 9
 
10
-router.get('/', verifyJWT, checkRole(['admin']), hospitalController.getAllHospital);
11
-router.post('/', verifyJWT, upload.single('image'), checkRole(['admin']), hospitalController.storeHospital);
12
-router.get('/:id', verifyJWT, checkRole(['admin']), hospitalController.showHospital);
13
-router.patch('/:id', verifyJWT, upload.single('image'), checkRole(['admin']), hospitalController.updateHospital);
14
-router.delete('/:id', verifyJWT, checkRole(['admin']), hospitalController.deleteHospital);
10
+const keycloak = require('../../middleware/Keycloak.js');
11
+const extractToken = require('../../middleware/ExtractToken.js');
12
+const checkRoles = require('../../middleware/CheckRoles.js');
13
+
14
+// router.get('/', verifyJWT, checkRole(['admin']), hospitalController.getAllHospital);
15
+// router.post('/', verifyJWT, upload.single('image'), checkRole(['admin']), hospitalController.storeHospital);
16
+// router.get('/:id', verifyJWT, checkRole(['admin']), hospitalController.showHospital);
17
+// router.patch('/:id', verifyJWT, upload.single('image'), checkRole(['admin']), hospitalController.updateHospital);
18
+// router.delete('/:id', verifyJWT, checkRole(['admin']), hospitalController.deleteHospital);
19
+
20
+// // Vendor History
21
+// router.get('/:id/vendor-history', verifyJWT, checkRole(['admin']), vendorHistoryController.getAllVendorHistory);
22
+// router.post('/:id/vendor-history', verifyJWT, checkRole(['admin']), vendorHistoryController.storeVendorHistory);
23
+// router.get('/:id/vendor-history/:id_vendor_history', verifyJWT, checkRole(['admin']), vendorHistoryController.showVendorHistory);
24
+// router.patch('/:id/vendor-history/:id_vendor_history', verifyJWT, checkRole(['admin']), vendorHistoryController.updateVendorHistory);
25
+// router.delete('/:id/vendor-history/:id_vendor_history', verifyJWT, checkRole(['admin']), vendorHistoryController.deleteVendorHistory);
26
+
27
+// // Executives History
28
+// router.get('/:id/executives-history', verifyJWT, checkRole(['admin']), executivesHistoryController.getAllExecutivesHistory);
29
+// router.post('/:id/executives-history', verifyJWT, checkRole(['admin']), executivesHistoryController.storeExecutivesHistory);
30
+// router.get('/:id/executives-history/:id_executives_history', verifyJWT, checkRole(['admin']), executivesHistoryController.showExecutivesHistory);
31
+// router.patch('/:id/executives-history/:id_executives_history', verifyJWT, checkRole(['admin']), executivesHistoryController.updateExecutivesHistory);
32
+// router.delete('/:id/executives-history/:id_executives_history', verifyJWT, checkRole(['admin']), executivesHistoryController.deleteExecutivesHistory);
33
+
34
+router.get('/', [keycloak.protect(), extractToken, checkRoles(["admin"])], hospitalController.getAllHospital);
35
+router.post('/', [keycloak.protect(), extractToken, checkRoles(["admin", "admin"])], upload.single('image'), hospitalController.storeHospital);
36
+router.get('/:id', [keycloak.protect(), extractToken, checkRoles(["admin"])], hospitalController.showHospital);
37
+router.patch('/:id', [keycloak.protect(), extractToken, checkRoles(["admin", "admin"])], upload.single('image'), hospitalController.updateHospital);
38
+router.delete('/:id', [keycloak.protect(), extractToken, checkRoles(["admin"])], hospitalController.deleteHospital);
15 39
 
16 40
 // Vendor History
17
-router.get('/:id/vendor-history', verifyJWT, checkRole(['admin']), vendorHistoryController.getAllVendorHistory);
18
-router.post('/:id/vendor-history', verifyJWT, checkRole(['admin']), vendorHistoryController.storeVendorHistory);
19
-router.get('/:id/vendor-history/:id_vendor_history', verifyJWT, checkRole(['admin']), vendorHistoryController.showVendorHistory);
20
-router.patch('/:id/vendor-history/:id_vendor_history', verifyJWT, checkRole(['admin']), vendorHistoryController.updateVendorHistory);
21
-router.delete('/:id/vendor-history/:id_vendor_history', verifyJWT, checkRole(['admin']), vendorHistoryController.deleteVendorHistory);
41
+router.get('/:id/vendor-history', [keycloak.protect(), extractToken, checkRoles(["admin"])], vendorHistoryController.getAllVendorHistory);
42
+router.post('/:id/vendor-history', [keycloak.protect(), extractToken, checkRoles(["admin"])], vendorHistoryController.storeVendorHistory);
43
+router.get('/:id/vendor-history/:id_vendor_history', [keycloak.protect(), extractToken, checkRoles(["admin"])], vendorHistoryController.showVendorHistory);
44
+router.patch('/:id/vendor-history/:id_vendor_history', [keycloak.protect(), extractToken, checkRoles(["admin"])], vendorHistoryController.updateVendorHistory);
45
+router.delete('/:id/vendor-history/:id_vendor_history', [keycloak.protect(), extractToken, checkRoles(["admin"])], vendorHistoryController.deleteVendorHistory);
22 46
 
23 47
 // Executives History
24
-router.get('/:id/executives-history', verifyJWT, checkRole(['admin']), executivesHistoryController.getAllExecutivesHistory);
25
-router.post('/:id/executives-history', verifyJWT, checkRole(['admin']), executivesHistoryController.storeExecutivesHistory);
26
-router.get('/:id/executives-history/:id_executives_history', verifyJWT, checkRole(['admin']), executivesHistoryController.showExecutivesHistory);
27
-router.patch('/:id/executives-history/:id_executives_history', verifyJWT, checkRole(['admin']), executivesHistoryController.updateExecutivesHistory);
28
-router.delete('/:id/executives-history/:id_executives_history', verifyJWT, checkRole(['admin']), executivesHistoryController.deleteExecutivesHistory);
48
+router.get('/:id/executives-history', [keycloak.protect(), extractToken, checkRoles(["admin"])], executivesHistoryController.getAllExecutivesHistory);
49
+router.post('/:id/executives-history', [keycloak.protect(), extractToken, checkRoles(["admin"])], executivesHistoryController.storeExecutivesHistory);
50
+router.get('/:id/executives-history/:id_executives_history', [keycloak.protect(), extractToken, checkRoles(["admin"])], executivesHistoryController.showExecutivesHistory);
51
+router.patch('/:id/executives-history/:id_executives_history', [keycloak.protect(), extractToken, checkRoles(["admin"])], executivesHistoryController.updateExecutivesHistory);
52
+router.delete('/:id/executives-history/:id_executives_history', [keycloak.protect(), extractToken, checkRoles(["admin"])], executivesHistoryController.deleteExecutivesHistory);
29 53
 
30 54
 module.exports = router;

+ 12 - 7
src/routes/admin/ProvinceRoute.js

@@ -1,19 +1,24 @@
1 1
 const express = require('express')
2 2
 const router = express.Router()
3 3
 const provinceController = require('../../controllers/admin/ProvinceController.js')
4
-const verifyJWT = require('../../middleware/VerifyJWT.js');
5
-const checkRole = require('../../middleware/CheckRole.js');
4
+// const verifyJWT = require('../../middleware/VerifyJWT.js');
5
+// const checkRole = require('../../middleware/CheckRole.js');
6
+
7
+const keycloak = require('../../middleware/Keycloak.js');
8
+const extractToken = require('../../middleware/ExtractToken.js');
9
+const checkRoles = require('../../middleware/CheckRoles.js');
6 10
 
7 11
 // router.get('/', verifyJWT, checkRole(['admin', 'sales']), provinceController.getAllProvince);
12
+// router.get('/', verifyJWT, checkRole(['admin']), provinceController.getAllProvince);
8 13
 // router.post('/', verifyJWT, checkRole(['admin']), provinceController.storeProvince);
9 14
 // router.get('/:id', verifyJWT, checkRole(['admin']), provinceController.showProvince);
10 15
 // router.patch('/:id', verifyJWT, checkRole(['admin']), provinceController.updateProvince);
11 16
 // router.delete('/:id', verifyJWT, checkRole(['admin']), provinceController.deleteProvince);
12 17
 
13
-router.get('/', verifyJWT, checkRole(['admin']), provinceController.getAllProvince);
14
-router.post('/', verifyJWT, checkRole(['admin']), provinceController.storeProvince);
15
-router.get('/:id', verifyJWT, checkRole(['admin']), provinceController.showProvince);
16
-router.patch('/:id', verifyJWT, checkRole(['admin']), provinceController.updateProvince);
17
-router.delete('/:id', verifyJWT, checkRole(['admin']), provinceController.deleteProvince);
18
+router.get('/', [keycloak.protect(), extractToken, checkRoles(['admin'])], provinceController.getAllProvince);
19
+router.post('/', [keycloak.protect(), extractToken, checkRoles(['admin'])], provinceController.storeProvince);
20
+router.get('/:id', [keycloak.protect(), extractToken, checkRoles(['admin'])], provinceController.showProvince);
21
+router.patch('/:id', [keycloak.protect(), extractToken, checkRoles(['admin'])], provinceController.updateProvince);
22
+router.delete('/:id', [keycloak.protect(), extractToken, checkRoles(['admin'])], provinceController.deleteProvince);
18 23
 
19 24
 module.exports = router;

+ 17 - 7
src/routes/admin/SalesRoute.js

@@ -1,14 +1,24 @@
1 1
 const express = require('express');
2 2
 const salesControllers = require('../../controllers/admin/SalesController.js');
3
-const verifyJWT = require('../../middleware/VerifyJWT.js');
4
-const checkRole = require('../../middleware/CheckRole.js');
3
+// const verifyJWT = require('../../middleware/VerifyJWT.js');
4
+// const checkRole = require('../../middleware/CheckRole.js');
5
+
6
+const keycloak = require('../../middleware/Keycloak.js');
7
+const extractToken = require('../../middleware/ExtractToken.js');
8
+const checkRoles = require('../../middleware/CheckRoles.js');
5 9
 
6 10
 const router = express.Router();
7 11
 
8
-router.post('/', verifyJWT, checkRole(['admin']), salesControllers.storeSales);
9
-router.get('/', verifyJWT, checkRole(['admin']), salesControllers.getAllSales);
10
-router.get('/:id', verifyJWT, checkRole(['admin']), salesControllers.showSales);
11
-router.patch('/:id', verifyJWT, checkRole(['admin']), salesControllers.updateSales);
12
-router.delete('/:id', verifyJWT, checkRole(['admin']), salesControllers.deleteSales);
12
+// router.post('/', verifyJWT, checkRole(['admin']), salesControllers.storeSales);
13
+// router.get('/', verifyJWT, checkRole(['admin']), salesControllers.getAllSales);
14
+// router.get('/:id', verifyJWT, checkRole(['admin']), salesControllers.showSales);
15
+// router.patch('/:id', verifyJWT, checkRole(['admin']), salesControllers.updateSales);
16
+// router.delete('/:id', verifyJWT, checkRole(['admin']), salesControllers.deleteSales);
17
+
18
+router.post('/', [keycloak.protect(), extractToken, checkRoles(['admin'])], salesControllers.storeSales);
19
+router.get('/', [keycloak.protect(), extractToken, checkRoles(['admin'])], salesControllers.getAllSales);
20
+router.get('/:id', [keycloak.protect(), extractToken, checkRoles(['admin'])], salesControllers.showSales);
21
+router.patch('/:id', [keycloak.protect(), extractToken, checkRoles(['admin'])], salesControllers.updateSales);
22
+router.delete('/:id', [keycloak.protect(), extractToken, checkRoles(['admin'])], salesControllers.deleteSales);
13 23
 
14 24
 module.exports = router;

+ 18 - 8
src/routes/admin/VendorRoute.js

@@ -1,13 +1,23 @@
1 1
 const express = require('express')
2 2
 const router = express.Router()
3 3
 const vendorController = require('../../controllers/admin/VendorController.js')
4
-const verifyJWT = require('../../middleware/VerifyJWT.js');
5
-const checkRole = require('../../middleware/CheckRole.js');
6
-
7
-router.get('/', verifyJWT, checkRole(['admin', 'sales']), vendorController.getAllVendor);
8
-router.post('/', verifyJWT, checkRole(['admin', 'sales']), vendorController.storeVendor);
9
-router.get('/:id', verifyJWT, checkRole(['admin', 'sales']), vendorController.showVendor);
10
-router.patch('/:id', verifyJWT, checkRole(['admin', 'sales']), vendorController.updateVendor);
11
-router.delete('/:id', verifyJWT, checkRole(['admin']), vendorController.deleteVendor);
4
+// const verifyJWT = require('../../middleware/VerifyJWT.js');
5
+// const checkRole = require('../../middleware/CheckRole.js');
6
+
7
+const keycloak = require('../../middleware/Keycloak.js');
8
+const extractToken = require('../../middleware/ExtractToken.js');
9
+const checkRoles = require('../../middleware/CheckRoles.js');
10
+
11
+// router.get('/', verifyJWT, checkRole(['admin', 'sales']), vendorController.getAllVendor);
12
+// router.post('/', verifyJWT, checkRole(['admin', 'sales']), vendorController.storeVendor);
13
+// router.get('/:id', verifyJWT, checkRole(['admin', 'sales']), vendorController.showVendor);
14
+// router.patch('/:id', verifyJWT, checkRole(['admin', 'sales']), vendorController.updateVendor);
15
+// router.delete('/:id', verifyJWT, checkRole(['admin']), vendorController.deleteVendor);
16
+
17
+router.get('/', [keycloak.protect(), extractToken, checkRoles(['admin', 'sales'])], vendorController.getAllVendor);
18
+router.post('/', [keycloak.protect(), extractToken, checkRoles(['admin', 'sales'])], vendorController.storeVendor);
19
+router.get('/:id', [keycloak.protect(), extractToken, checkRoles(['admin', 'sales'])], vendorController.showVendor);
20
+router.patch('/:id', [keycloak.protect(), extractToken, checkRoles(['admin', 'sales'])], vendorController.updateVendor);
21
+router.delete('/:id', [keycloak.protect(), extractToken, checkRoles(['admin'])], vendorController.deleteVendor);
12 22
 
13 23
 module.exports = router;

+ 11 - 4
src/routes/sales/AreaRoute.js

@@ -1,9 +1,16 @@
1 1
 const express = require('express')
2 2
 const router = express.Router()
3 3
 const areaController = require('../../controllers/sales/AreaController.js')
4
-const verifyJWT = require('../../middleware/VerifyJWT.js');
5
-const checkRole = require('../../middleware/CheckRole.js');
6
-const upload = require('../../middleware/UploadImage.js');
4
+// const verifyJWT = require('../../middleware/VerifyJWT.js');
5
+// const checkRole = require('../../middleware/CheckRole.js');
6
+// const upload = require('../../middleware/UploadImage.js');
7
+
8
+const keycloak = require('../../middleware/Keycloak.js');
9
+const extractToken = require('../../middleware/ExtractToken.js');
10
+const checkRoles = require('../../middleware/CheckRoles.js');
11
+
12
+// router.get('/', verifyJWT, checkRole(['sales']), areaController.getAllAreaByUser);
13
+
14
+router.get('/', [keycloak.protect(), extractToken, checkRoles(['sales'])], areaController.getAllAreaByUser);
7 15
 
8
-router.get('/', verifyJWT, checkRole(['sales']), areaController.getAllAreaByUser);
9 16
 module.exports = router;

+ 39 - 16
src/routes/sales/HospitalRoute.js

@@ -3,27 +3,50 @@ const router = express.Router()
3 3
 const hospitalController = require('../../controllers/sales/HospitalController.js')
4 4
 const vendorHistoryController = require('../../controllers/sales/VendorHistoryController.js')
5 5
 const executivesHistoryController = require('../../controllers/sales/ExecutivesHistoryController.js')
6
-const verifyJWT = require('../../middleware/VerifyJWT.js');
7
-const checkRole = require('../../middleware/CheckRole.js');
6
+// const verifyJWT = require('../../middleware/VerifyJWT.js');
7
+// const checkRole = require('../../middleware/CheckRole.js');
8 8
 const upload = require('../../middleware/UploadImage.js');
9 9
 
10
-router.get('/', verifyJWT, checkRole(['sales']), hospitalController.getAllHospitalByArea);
11
-router.post('/', verifyJWT, upload.single('image'), checkRole(['sales']), hospitalController.storeHospital);
12
-router.patch('/:id', verifyJWT, upload.single('image'), checkRole(['sales']), hospitalController.updateHospital);
13
-router.get('/:id', verifyJWT, checkRole(['sales']), hospitalController.showHospital);
10
+const keycloak = require('../../middleware/Keycloak.js');
11
+const extractToken = require('../../middleware/ExtractToken.js');
12
+const checkRoles = require('../../middleware/CheckRoles.js');
13
+
14
+// router.get('/', verifyJWT, checkRole(['sales']), hospitalController.getAllHospitalByArea);
15
+// router.post('/', verifyJWT, upload.single('image'), checkRole(['sales']), hospitalController.storeHospital);
16
+// router.patch('/:id', verifyJWT, upload.single('image'), checkRole(['sales']), hospitalController.updateHospital);
17
+// router.get('/:id', verifyJWT, checkRole(['sales']), hospitalController.showHospital);
18
+
19
+// // Vendor History
20
+// router.get('/:id/vendor-history', verifyJWT, checkRole(['sales']), vendorHistoryController.getAllVendorHistory);
21
+// router.post('/:id/vendor-history', verifyJWT, checkRole(['sales']), vendorHistoryController.storeVendorHistory);
22
+// router.get('/:id/vendor-history/:id_vendor_history', verifyJWT, checkRole(['sales']), vendorHistoryController.showVendorHistory);
23
+// router.patch('/:id/vendor-history/:id_vendor_history', verifyJWT, checkRole(['sales']), vendorHistoryController.updateVendorHistory);
24
+// router.delete('/:id/vendor-history/:id_vendor_history', verifyJWT, checkRole(['sales']), vendorHistoryController.deleteVendorHistory);
25
+
26
+// // Executives History
27
+// router.get('/:id/executives-history', verifyJWT, checkRole(['sales']), executivesHistoryController.getAllExecutivesHistory);
28
+// router.post('/:id/executives-history', verifyJWT, checkRole(['sales']), executivesHistoryController.storeExecutivesHistory);
29
+// router.get('/:id/executives-history/:id_executives_history', verifyJWT, checkRole(['sales']), executivesHistoryController.showExecutivesHistory);
30
+// router.patch('/:id/executives-history/:id_executives_history', verifyJWT, checkRole(['sales']), executivesHistoryController.updateExecutivesHistory);
31
+// router.delete('/:id/executives-history/:id_executives_history', verifyJWT, checkRole(['sales']), executivesHistoryController.deleteExecutivesHistory);
32
+
33
+router.get('/', [keycloak.protect(), extractToken, checkRoles(['sales'])], hospitalController.getAllHospitalByArea);
34
+router.post('/', [keycloak.protect(), extractToken, checkRoles(['sales'])], upload.single('image'), hospitalController.storeHospital);
35
+router.patch('/:id', [keycloak.protect(), extractToken, checkRoles(['sales'])], upload.single('image'), hospitalController.updateHospital);
36
+router.get('/:id', [keycloak.protect(), extractToken, checkRoles(['sales'])], hospitalController.showHospital);
14 37
 
15 38
 // Vendor History
16
-router.get('/:id/vendor-history', verifyJWT, checkRole(['sales']), vendorHistoryController.getAllVendorHistory);
17
-router.post('/:id/vendor-history', verifyJWT, checkRole(['sales']), vendorHistoryController.storeVendorHistory);
18
-router.get('/:id/vendor-history/:id_vendor_history', verifyJWT, checkRole(['sales']), vendorHistoryController.showVendorHistory);
19
-router.patch('/:id/vendor-history/:id_vendor_history', verifyJWT, checkRole(['sales']), vendorHistoryController.updateVendorHistory);
20
-router.delete('/:id/vendor-history/:id_vendor_history', verifyJWT, checkRole(['sales']), vendorHistoryController.deleteVendorHistory);
39
+router.get('/:id/vendor-history', [keycloak.protect(), extractToken, checkRoles(['sales'])], vendorHistoryController.getAllVendorHistory);
40
+router.post('/:id/vendor-history', [keycloak.protect(), extractToken, checkRoles(['sales'])], vendorHistoryController.storeVendorHistory);
41
+router.get('/:id/vendor-history/:id_vendor_history', [keycloak.protect(), extractToken, checkRoles(['sales'])], vendorHistoryController.showVendorHistory);
42
+router.patch('/:id/vendor-history/:id_vendor_history', [keycloak.protect(), extractToken, checkRoles(['sales'])], vendorHistoryController.updateVendorHistory);
43
+router.delete('/:id/vendor-history/:id_vendor_history', [keycloak.protect(), extractToken, checkRoles(['sales'])], vendorHistoryController.deleteVendorHistory);
21 44
 
22 45
 // Executives History
23
-router.get('/:id/executives-history', verifyJWT, checkRole(['sales']), executivesHistoryController.getAllExecutivesHistory);
24
-router.post('/:id/executives-history', verifyJWT, checkRole(['sales']), executivesHistoryController.storeExecutivesHistory);
25
-router.get('/:id/executives-history/:id_executives_history', verifyJWT, checkRole(['sales']), executivesHistoryController.showExecutivesHistory);
26
-router.patch('/:id/executives-history/:id_executives_history', verifyJWT, checkRole(['sales']), executivesHistoryController.updateExecutivesHistory);
27
-router.delete('/:id/executives-history/:id_executives_history', verifyJWT, checkRole(['sales']), executivesHistoryController.deleteExecutivesHistory);
46
+router.get('/:id/executives-history', [keycloak.protect(), extractToken, checkRoles(['sales'])], executivesHistoryController.getAllExecutivesHistory);
47
+router.post('/:id/executives-history', [keycloak.protect(), extractToken, checkRoles(['sales'])], executivesHistoryController.storeExecutivesHistory);
48
+router.get('/:id/executives-history/:id_executives_history', [keycloak.protect(), extractToken, checkRoles(['sales'])], executivesHistoryController.showExecutivesHistory);
49
+router.patch('/:id/executives-history/:id_executives_history', [keycloak.protect(), extractToken, checkRoles(['sales'])], executivesHistoryController.updateExecutivesHistory);
50
+router.delete('/:id/executives-history/:id_executives_history', [keycloak.protect(), extractToken, checkRoles(['sales'])], executivesHistoryController.deleteExecutivesHistory);
28 51
 
29 52
 module.exports = router;

+ 7 - 3
src/routes/sales/VendorRoute.js

@@ -1,9 +1,13 @@
1 1
 const express = require('express')
2 2
 const router = express.Router()
3 3
 const vendorController = require('../../controllers/sales/VendorController.js')
4
-const verifyJWT = require('../../middleware/VerifyJWT.js');
5
-const checkRole = require('../../middleware/CheckRole.js');
4
+// const verifyJWT = require('../../middleware/VerifyJWT.js');
5
+// const checkRole = require('../../middleware/CheckRole.js');
6 6
 
7
-router.get('/', verifyJWT, checkRole(['sales']), vendorController.getAllVendor);
7
+const keycloak = require('../../middleware/Keycloak.js');
8
+const extractToken = require('../../middleware/ExtractToken.js');
9
+const checkRoles = require('../../middleware/CheckRoles.js');
10
+
11
+router.get('/', [keycloak.protect(), extractToken, checkRoles(['sales'])], vendorController.getAllVendor);
8 12
 
9 13
 module.exports = router;

+ 1 - 1
src/services/sales/AreaService.js

@@ -5,7 +5,7 @@ exports.getAllAreaByUserService = async ({ page, limit, search, sortBy, orderBy
5 5
     const skip = (page - 1) * limit;
6 6
 
7 7
     const where = {
8
-        user_id: req.user.id,
8
+        user_id: req.tokenData.sub,
9 9
         deletedAt: null,
10 10
         ...SearchFilter(search, ['province.name']),
11 11
     };

+ 5 - 2
src/services/sales/HospitalService.js

@@ -7,12 +7,13 @@ const CityRepository = require('../../repository/admin/CityRepository.js');
7 7
 const HttpException = require('../../utils/HttpException.js');
8 8
 const HospitalRepository = require('../../repository/admin/HospitalRepository.js');
9 9
 const { formatISOWithoutTimezone } = require('../../utils/FormatDate.js');
10
+const { getUserNameById } = require('../../utils/CheckUserKeycloak.js');
10 11
 
11 12
 exports.getAllHospitalByAreaService = async ({ page, limit, search, sortBy, orderBy, province, city, type, ownership, progress_status }, req) => {
12 13
     const skip = (page - 1) * limit;
13 14
 
14 15
     const userAreas = await prisma.userArea.findMany({
15
-        where: { user_id: req.user.id },
16
+        where: { user_id: req.tokenData.sub },
16 17
         select: { province_id: true },
17 18
     });
18 19
 
@@ -216,5 +217,7 @@ exports.showHospitalService = async (id) => {
216 217
         throw new HttpException("Data hospital not found", 404);
217 218
     }
218 219
 
219
-    return hospital;
220
+    const userName = await getUserNameById(hospital.created_by);
221
+
222
+    return { hospital, userName };
220 223
 };

+ 47 - 0
src/utils/CheckUserKeycloak.js

@@ -0,0 +1,47 @@
1
+const axios = require('axios');
2
+require('dotenv').config();
3
+
4
+const getKeycloakAdminToken = async () => {
5
+    const response = await axios.post(`${process.env.KEYCLOAK_URL}/realms/master/protocol/openid-connect/token`, new URLSearchParams({
6
+        client_id: 'admin-cli',
7
+        username: process.env.KEYCLOAK_ADMIN_USERNAME,
8
+        password: process.env.KEYCLOAK_ADMIN_PASSWORD,
9
+        grant_type: 'password'
10
+    }), {
11
+        headers: {
12
+            'Content-Type': 'application/x-www-form-urlencoded'
13
+        }
14
+    });
15
+
16
+    return response.data.access_token;
17
+};
18
+
19
+const getUserInfoById = async (userId) => {
20
+    try {
21
+        const token = await getKeycloakAdminToken();
22
+
23
+        const response = await axios.get(`${process.env.KEYCLOAK_URL}/admin/realms/${process.env.KEYCLOAK_REALM}/users/${userId}`, {
24
+            headers: {
25
+                Authorization: `Bearer ${token}`
26
+            }
27
+        });
28
+
29
+        return response.data;
30
+    } catch (error) {
31
+        console.error("Failed to get user info from Keycloak:", error.message);
32
+        return null;
33
+    }
34
+};
35
+
36
+const getUserNameById = async (userId) => {
37
+    const userInfo = await getUserInfoById(userId);
38
+    if (!userInfo) return null;
39
+
40
+    const firstName = userInfo.firstName || '';
41
+    const lastName = userInfo.lastName || '';
42
+    const fullName = `${firstName} ${lastName}`.trim();
43
+
44
+    return fullName || null;
45
+};
46
+
47
+module.exports = { getUserNameById };