@innvoid/getmarket-sdk 0.1.5 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-JXOLNJ7J.js +224 -0
- package/dist/chunk-JXOLNJ7J.js.map +1 -0
- package/dist/chunk-KJ64O2EG.js +19 -0
- package/dist/{chunk-OJUNVATQ.js.map → chunk-KJ64O2EG.js.map} +1 -1
- package/dist/{chunk-RA5PN2F4.js → chunk-OSYBK5AN.js} +2 -2
- package/dist/chunk-P2U3MT2E.js +39 -0
- package/dist/chunk-P2U3MT2E.js.map +1 -0
- package/dist/core/index.js +2 -2
- package/dist/express.cjs.map +1 -1
- package/dist/express.d.cts +3 -0
- package/dist/express.d.ts +3 -0
- package/dist/headers/index.cjs +12 -6
- package/dist/headers/index.cjs.map +1 -1
- package/dist/headers/index.d.cts +1 -3
- package/dist/headers/index.d.ts +1 -3
- package/dist/headers/index.js +1 -1
- package/dist/index.cjs +401 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -4
- package/dist/index.d.ts +34 -4
- package/dist/index.js +305 -14
- package/dist/index.js.map +1 -1
- package/dist/middlewares/index.cjs +235 -136
- package/dist/middlewares/index.cjs.map +1 -1
- package/dist/middlewares/index.d.cts +51 -26
- package/dist/middlewares/index.d.ts +51 -26
- package/dist/middlewares/index.js +21 -17
- package/package.json +2 -2
- package/dist/chunk-65HACONF.js +0 -33
- package/dist/chunk-65HACONF.js.map +0 -1
- package/dist/chunk-A2E3FXYI.js +0 -157
- package/dist/chunk-A2E3FXYI.js.map +0 -1
- package/dist/chunk-OJUNVATQ.js +0 -11
- /package/dist/{chunk-RA5PN2F4.js.map → chunk-OSYBK5AN.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -37,19 +37,29 @@ __export(src_exports, {
|
|
|
37
37
|
HEADER_INTERNAL_API_KEY: () => HEADER_INTERNAL_API_KEY,
|
|
38
38
|
HEADER_REQUEST_ID: () => HEADER_REQUEST_ID,
|
|
39
39
|
InternalHttp: () => InternalHttp,
|
|
40
|
-
REQUEST_ID_HEADER: () => REQUEST_ID_HEADER,
|
|
41
|
-
REQUEST_ID_HEADER_ALT: () => REQUEST_ID_HEADER_ALT,
|
|
42
|
-
RESPONSE_REQUEST_ID_HEADER: () => RESPONSE_REQUEST_ID_HEADER,
|
|
43
40
|
TwoLevelCache: () => TwoLevelCache,
|
|
44
41
|
UpstreamError: () => UpstreamError,
|
|
42
|
+
authCustomerAllowFirebase: () => authCustomerAllowFirebase,
|
|
43
|
+
authCustomerRequired: () => authCustomerRequired,
|
|
44
|
+
authEmployeeAllowFirebase: () => authEmployeeAllowFirebase,
|
|
45
|
+
authEmployeeRequired: () => authEmployeeRequired,
|
|
45
46
|
closeCache: () => closeCache,
|
|
46
47
|
createAuthMiddleware: () => createAuthMiddleware,
|
|
48
|
+
createAuthMiddlewareLegacySimple: () => createAuthMiddleware2,
|
|
47
49
|
createHttpClient: () => createHttpClient,
|
|
48
50
|
getOrSet: () => getOrSet,
|
|
49
51
|
getRequestContextFromHeaders: () => getRequestContextFromHeaders,
|
|
50
52
|
getTwoLevelCache: () => getTwoLevelCache,
|
|
53
|
+
internalAuth: () => internalAuth,
|
|
51
54
|
mapAxiosToUpstreamError: () => mapAxiosToUpstreamError,
|
|
55
|
+
parseHeaders: () => parseHeaders,
|
|
52
56
|
readRs256PublicKey: () => readRs256PublicKey,
|
|
57
|
+
requestId: () => requestId,
|
|
58
|
+
requireAnyPermission: () => requireAnyPermission,
|
|
59
|
+
requireAuthContext: () => requireAuthContext,
|
|
60
|
+
requirePermissions: () => requirePermissions,
|
|
61
|
+
requireRoles: () => requireRoles,
|
|
62
|
+
requireRolesOrAnyPermission: () => requireRolesOrAnyPermission,
|
|
53
63
|
sendError: () => sendError,
|
|
54
64
|
sendOk: () => sendOk,
|
|
55
65
|
verifyBackendJwtRS256: () => verifyBackendJwtRS256,
|
|
@@ -381,21 +391,30 @@ function mapAxiosToUpstreamError(err, svc) {
|
|
|
381
391
|
var import_axios = __toESM(require("axios"), 1);
|
|
382
392
|
|
|
383
393
|
// src/middlewares/requestId.ts
|
|
394
|
+
var import_crypto = require("crypto");
|
|
384
395
|
var REQUEST_ID_HEADER = "x-request-id";
|
|
385
396
|
var REQUEST_ID_HEADER_ALT = "x-requestid";
|
|
386
397
|
var RESPONSE_REQUEST_ID_HEADER = "X-Request-Id";
|
|
398
|
+
function requestId(req, res, next) {
|
|
399
|
+
const headerId = req.headers[REQUEST_ID_HEADER] || req.headers[REQUEST_ID_HEADER_ALT];
|
|
400
|
+
const id = headerId?.trim() || (0, import_crypto.randomUUID)();
|
|
401
|
+
req.requestId = id;
|
|
402
|
+
res.locals.requestId = id;
|
|
403
|
+
res.setHeader(RESPONSE_REQUEST_ID_HEADER, id);
|
|
404
|
+
next();
|
|
405
|
+
}
|
|
387
406
|
|
|
388
407
|
// src/core/http.ts
|
|
389
|
-
function withRequestId(headers,
|
|
390
|
-
const
|
|
391
|
-
const rid = (
|
|
392
|
-
if (rid)
|
|
393
|
-
return
|
|
408
|
+
function withRequestId(headers, requestId2) {
|
|
409
|
+
const h2 = headers && typeof headers === "object" ? { ...headers } : {};
|
|
410
|
+
const rid = (requestId2 || "").trim();
|
|
411
|
+
if (rid) h2[REQUEST_ID_HEADER] = rid;
|
|
412
|
+
return h2;
|
|
394
413
|
}
|
|
395
|
-
function withRequestIdConfig(config = {},
|
|
414
|
+
function withRequestIdConfig(config = {}, requestId2) {
|
|
396
415
|
return {
|
|
397
416
|
...config,
|
|
398
|
-
headers: withRequestId(config.headers,
|
|
417
|
+
headers: withRequestId(config.headers, requestId2)
|
|
399
418
|
};
|
|
400
419
|
}
|
|
401
420
|
function createHttpClient(opts) {
|
|
@@ -519,20 +538,36 @@ var HEADER_INTERNAL_API_KEY = "x-internal-api-key";
|
|
|
519
538
|
var HEADER_AUTHORIZATION = "authorization";
|
|
520
539
|
|
|
521
540
|
// src/headers/parse.ts
|
|
522
|
-
function
|
|
541
|
+
function normalizeHeaderValue(v) {
|
|
523
542
|
if (typeof v !== "string") return null;
|
|
524
543
|
const s = v.trim();
|
|
525
|
-
|
|
544
|
+
if (!s) return null;
|
|
545
|
+
if (s.startsWith("{") || s.startsWith("[") || s.includes('"')) return null;
|
|
546
|
+
if (s.length < 6) return null;
|
|
547
|
+
return s;
|
|
548
|
+
}
|
|
549
|
+
function h(headers, key) {
|
|
550
|
+
return headers[key] ?? headers[key.toLowerCase()] ?? headers[key.toUpperCase()];
|
|
526
551
|
}
|
|
527
552
|
function getRequestContextFromHeaders(headers) {
|
|
528
553
|
return {
|
|
529
|
-
requestId:
|
|
530
|
-
company_uid:
|
|
531
|
-
branch_uid:
|
|
532
|
-
employee_uid:
|
|
554
|
+
requestId: normalizeHeaderValue(h(headers, HEADER_REQUEST_ID)) ?? null,
|
|
555
|
+
company_uid: normalizeHeaderValue(h(headers, HEADER_COMPANY_UID)) ?? null,
|
|
556
|
+
branch_uid: normalizeHeaderValue(h(headers, HEADER_BRANCH_UID)) ?? null,
|
|
557
|
+
employee_uid: normalizeHeaderValue(h(headers, HEADER_EMPLOYEE_UID)) ?? null
|
|
533
558
|
};
|
|
534
559
|
}
|
|
535
560
|
|
|
561
|
+
// src/middlewares/parseHeaders.ts
|
|
562
|
+
function parseHeaders(req, _res, next) {
|
|
563
|
+
req.context = getRequestContextFromHeaders(req.headers);
|
|
564
|
+
next();
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// src/middlewares/internalAuth.ts
|
|
568
|
+
var import_fs = __toESM(require("fs"), 1);
|
|
569
|
+
var import_crypto2 = __toESM(require("crypto"), 1);
|
|
570
|
+
|
|
536
571
|
// src/middlewares/respond.ts
|
|
537
572
|
function sendOk(_req, res, data, statusCode = 200) {
|
|
538
573
|
return res.status(statusCode).json({ ok: true, data, requestId: res.locals?.requestId ?? null });
|
|
@@ -545,13 +580,198 @@ function sendError(_req, res, statusCode, code, message, details) {
|
|
|
545
580
|
});
|
|
546
581
|
}
|
|
547
582
|
|
|
583
|
+
// src/middlewares/internalAuth.ts
|
|
584
|
+
function readSecretFile(path) {
|
|
585
|
+
if (!path) return null;
|
|
586
|
+
try {
|
|
587
|
+
const v = import_fs.default.readFileSync(path, "utf8").trim();
|
|
588
|
+
return v.length ? v : null;
|
|
589
|
+
} catch {
|
|
590
|
+
return null;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
function splitKeys(v) {
|
|
594
|
+
if (!v) return [];
|
|
595
|
+
return v.split(",").map((s) => s.trim()).filter(Boolean);
|
|
596
|
+
}
|
|
597
|
+
function getExpectedKeys() {
|
|
598
|
+
const fileKey = readSecretFile(process.env.INTERNAL_API_KEY_FILE);
|
|
599
|
+
const envKey = (process.env.INTERNAL_API_KEY || "").trim();
|
|
600
|
+
const raw = fileKey || envKey;
|
|
601
|
+
return splitKeys(raw);
|
|
602
|
+
}
|
|
603
|
+
function extractToken(req) {
|
|
604
|
+
const apiKey = (req.header(HEADER_INTERNAL_API_KEY) || "").trim();
|
|
605
|
+
return apiKey || null;
|
|
606
|
+
}
|
|
607
|
+
function safeEquals(a, b) {
|
|
608
|
+
const aa = Buffer.from(a);
|
|
609
|
+
const bb = Buffer.from(b);
|
|
610
|
+
if (aa.length !== bb.length) return false;
|
|
611
|
+
return import_crypto2.default.timingSafeEqual(aa, bb);
|
|
612
|
+
}
|
|
613
|
+
function internalAuth(req, res, next) {
|
|
614
|
+
const token = extractToken(req);
|
|
615
|
+
if (!token) {
|
|
616
|
+
return sendError(req, res, 401, "UNAUTHORIZED", `Missing internal api key (${HEADER_INTERNAL_API_KEY})`);
|
|
617
|
+
}
|
|
618
|
+
const expectedKeys = getExpectedKeys();
|
|
619
|
+
if (expectedKeys.length === 0) {
|
|
620
|
+
return sendError(
|
|
621
|
+
req,
|
|
622
|
+
res,
|
|
623
|
+
500,
|
|
624
|
+
"MISCONFIGURED_INTERNAL_AUTH",
|
|
625
|
+
"Internal api key not configured (INTERNAL_API_KEY or INTERNAL_API_KEY_FILE)"
|
|
626
|
+
);
|
|
627
|
+
}
|
|
628
|
+
const ok = expectedKeys.some((k) => safeEquals(token, k));
|
|
629
|
+
if (!ok) {
|
|
630
|
+
return sendError(req, res, 403, "FORBIDDEN", "Invalid internal api key");
|
|
631
|
+
}
|
|
632
|
+
return next();
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// src/middlewares/authorization.ts
|
|
636
|
+
function getAuth(req) {
|
|
637
|
+
return req.auth ?? {};
|
|
638
|
+
}
|
|
639
|
+
function normalizeCode(v) {
|
|
640
|
+
if (!v) return null;
|
|
641
|
+
if (typeof v === "string") return v;
|
|
642
|
+
if (typeof v === "object") return v.code || v.name || null;
|
|
643
|
+
return null;
|
|
644
|
+
}
|
|
645
|
+
function rolesSet(auth) {
|
|
646
|
+
const out = /* @__PURE__ */ new Set();
|
|
647
|
+
for (const r of auth.roles || []) {
|
|
648
|
+
const c = normalizeCode(r);
|
|
649
|
+
if (c) out.add(c);
|
|
650
|
+
}
|
|
651
|
+
return out;
|
|
652
|
+
}
|
|
653
|
+
function permsSet(list) {
|
|
654
|
+
const out = /* @__PURE__ */ new Set();
|
|
655
|
+
for (const p of list || []) {
|
|
656
|
+
const c = normalizeCode(p);
|
|
657
|
+
if (c) out.add(c);
|
|
658
|
+
}
|
|
659
|
+
return out;
|
|
660
|
+
}
|
|
661
|
+
function requireAuthContext() {
|
|
662
|
+
return (req, res, next) => {
|
|
663
|
+
if (!req.auth) {
|
|
664
|
+
return sendError(req, res, 401, "UNAUTHORIZED", "Missing auth context");
|
|
665
|
+
}
|
|
666
|
+
return next();
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
function isSysAdmin(auth, sysAdminRole) {
|
|
670
|
+
const have = rolesSet(auth);
|
|
671
|
+
return have.has(sysAdminRole);
|
|
672
|
+
}
|
|
673
|
+
function requirePermissions(perms, options) {
|
|
674
|
+
const sysAdminBypass = options?.sysAdminBypass !== false;
|
|
675
|
+
const sysAdminRole = options?.sysAdminRole || "SYS_ADMIN";
|
|
676
|
+
return (req, res, next) => {
|
|
677
|
+
const auth = getAuth(req);
|
|
678
|
+
if (sysAdminBypass && isSysAdmin(auth, sysAdminRole)) return next();
|
|
679
|
+
const allow = permsSet(auth.permissions);
|
|
680
|
+
const deny = permsSet(auth.denied_permissions);
|
|
681
|
+
for (const p of perms) {
|
|
682
|
+
if (deny.has(p)) {
|
|
683
|
+
return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, {
|
|
684
|
+
denied: p
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
const missing = perms.filter((p) => !allow.has(p));
|
|
689
|
+
if (missing.length) {
|
|
690
|
+
return sendError(req, res, 403, "FORBIDDEN", "Missing permissions", {
|
|
691
|
+
missing,
|
|
692
|
+
mode: "ALL"
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
return next();
|
|
696
|
+
};
|
|
697
|
+
}
|
|
698
|
+
function requireAnyPermission(perms, options) {
|
|
699
|
+
const sysAdminBypass = options?.sysAdminBypass !== false;
|
|
700
|
+
const sysAdminRole = options?.sysAdminRole || "SYS_ADMIN";
|
|
701
|
+
return (req, res, next) => {
|
|
702
|
+
const auth = getAuth(req);
|
|
703
|
+
if (sysAdminBypass && isSysAdmin(auth, sysAdminRole)) return next();
|
|
704
|
+
const allow = permsSet(auth.permissions);
|
|
705
|
+
const deny = permsSet(auth.denied_permissions);
|
|
706
|
+
for (const p of perms) {
|
|
707
|
+
if (deny.has(p)) {
|
|
708
|
+
return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, {
|
|
709
|
+
denied: p
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
const ok = perms.some((p) => allow.has(p));
|
|
714
|
+
if (!ok) {
|
|
715
|
+
return sendError(req, res, 403, "FORBIDDEN", "Permission denied", {
|
|
716
|
+
required: perms,
|
|
717
|
+
mode: "ANY"
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
return next();
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
function requireRoles(roles, options) {
|
|
724
|
+
const sysAdminBypass = options?.sysAdminBypass !== false;
|
|
725
|
+
const sysAdminRole = options?.sysAdminRole || "SYS_ADMIN";
|
|
726
|
+
return (req, res, next) => {
|
|
727
|
+
const auth = getAuth(req);
|
|
728
|
+
if (sysAdminBypass && isSysAdmin(auth, sysAdminRole)) return next();
|
|
729
|
+
const have = rolesSet(auth);
|
|
730
|
+
if (!roles.some((r) => have.has(r))) {
|
|
731
|
+
return sendError(req, res, 403, "FORBIDDEN", "Role not allowed", {
|
|
732
|
+
required: roles,
|
|
733
|
+
mode: "ANY"
|
|
734
|
+
});
|
|
735
|
+
}
|
|
736
|
+
return next();
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
function requireRolesOrAnyPermission(roles, perms, options) {
|
|
740
|
+
const sysAdminBypass = options?.sysAdminBypass !== false;
|
|
741
|
+
const sysAdminRole = options?.sysAdminRole || "SYS_ADMIN";
|
|
742
|
+
return (req, res, next) => {
|
|
743
|
+
const auth = getAuth(req);
|
|
744
|
+
if (sysAdminBypass && isSysAdmin(auth, sysAdminRole)) return next();
|
|
745
|
+
const haveRoles = rolesSet(auth);
|
|
746
|
+
const allow = permsSet(auth.permissions);
|
|
747
|
+
const deny = permsSet(auth.denied_permissions);
|
|
748
|
+
for (const p of perms) {
|
|
749
|
+
if (deny.has(p)) {
|
|
750
|
+
return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, {
|
|
751
|
+
denied: p
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
const okRole = roles.some((r) => haveRoles.has(r));
|
|
756
|
+
const okPerm = perms.some((p) => allow.has(p));
|
|
757
|
+
if (!okRole && !okPerm) {
|
|
758
|
+
return sendError(req, res, 403, "FORBIDDEN", "Access denied", {
|
|
759
|
+
roles,
|
|
760
|
+
permissions: perms,
|
|
761
|
+
mode: "ROLES_OR_PERMS_ANY"
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
return next();
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
|
|
548
768
|
// src/auth/jwt.ts
|
|
549
|
-
var
|
|
769
|
+
var import_fs2 = __toESM(require("fs"), 1);
|
|
550
770
|
var import_jsonwebtoken = __toESM(require("jsonwebtoken"), 1);
|
|
551
771
|
function readFileIfExists(path) {
|
|
552
772
|
if (!path) return null;
|
|
553
773
|
try {
|
|
554
|
-
const v =
|
|
774
|
+
const v = import_fs2.default.readFileSync(path, "utf8").trim();
|
|
555
775
|
return v.length ? v : null;
|
|
556
776
|
} catch {
|
|
557
777
|
return null;
|
|
@@ -587,12 +807,7 @@ function normalizeUid(v) {
|
|
|
587
807
|
return s.length ? s : null;
|
|
588
808
|
}
|
|
589
809
|
function createAuthMiddleware(opts) {
|
|
590
|
-
const {
|
|
591
|
-
subject,
|
|
592
|
-
allowFirebaseIdToken = false,
|
|
593
|
-
requireSubject = true,
|
|
594
|
-
hydrate
|
|
595
|
-
} = opts;
|
|
810
|
+
const { subject, allowFirebaseIdToken = false, requireSubject = true, hydrate } = opts;
|
|
596
811
|
return async (req, res, next) => {
|
|
597
812
|
const token = getBearerToken(req);
|
|
598
813
|
if (!token) {
|
|
@@ -650,8 +865,8 @@ function createAuthMiddleware(opts) {
|
|
|
650
865
|
});
|
|
651
866
|
}
|
|
652
867
|
try {
|
|
653
|
-
const { default:
|
|
654
|
-
const firebaseDecoded = await
|
|
868
|
+
const { default: admin2 } = await import("firebase-admin");
|
|
869
|
+
const firebaseDecoded = await admin2.auth().verifyIdToken(token);
|
|
655
870
|
if (firebaseDecoded.email && firebaseDecoded.email_verified === false) {
|
|
656
871
|
return res.status(401).json({
|
|
657
872
|
ok: false,
|
|
@@ -681,6 +896,153 @@ function createAuthMiddleware(opts) {
|
|
|
681
896
|
}
|
|
682
897
|
};
|
|
683
898
|
}
|
|
899
|
+
|
|
900
|
+
// src/auth/authentication.ts
|
|
901
|
+
var import_firebase_admin = __toESM(require("firebase-admin"), 1);
|
|
902
|
+
var import_jsonwebtoken2 = __toESM(require("jsonwebtoken"), 1);
|
|
903
|
+
var import_fs3 = __toESM(require("fs"), 1);
|
|
904
|
+
function getBearerToken2(req) {
|
|
905
|
+
const auth = String(req.headers?.authorization || "");
|
|
906
|
+
if (!auth.startsWith("Bearer ")) return null;
|
|
907
|
+
const token = auth.slice(7).trim();
|
|
908
|
+
return token.length ? token : null;
|
|
909
|
+
}
|
|
910
|
+
function readPublicKey() {
|
|
911
|
+
const publicKeyPath = process.env.JWT_PUBLIC_KEY_PATH;
|
|
912
|
+
const publicKeyEnv = process.env.AUTH_JWT_PUBLIC_KEY || process.env.AUTH_RSA_PUBLIC_KEY || "";
|
|
913
|
+
if (publicKeyPath) {
|
|
914
|
+
const v = import_fs3.default.readFileSync(publicKeyPath, "utf8").trim();
|
|
915
|
+
if (v) return v;
|
|
916
|
+
}
|
|
917
|
+
const envKey = publicKeyEnv.replace(/\\n/g, "\n").trim();
|
|
918
|
+
if (envKey) return envKey;
|
|
919
|
+
throw new Error(
|
|
920
|
+
"Missing RS256 public key (JWT_PUBLIC_KEY_PATH / AUTH_JWT_PUBLIC_KEY / AUTH_RSA_PUBLIC_KEY)"
|
|
921
|
+
);
|
|
922
|
+
}
|
|
923
|
+
function verifyBackendJwtRS2562(raw) {
|
|
924
|
+
const publicKey = readPublicKey();
|
|
925
|
+
const audience = process.env.JWT_AUDIENCE || process.env.AUTH_JWT_AUDIENCE || "getmarket.api";
|
|
926
|
+
const issuer = process.env.JWT_ISSUER || process.env.AUTH_JWT_ISSUER || "getmarket-auth";
|
|
927
|
+
return import_jsonwebtoken2.default.verify(raw, publicKey, {
|
|
928
|
+
algorithms: ["RS256"],
|
|
929
|
+
audience,
|
|
930
|
+
issuer
|
|
931
|
+
});
|
|
932
|
+
}
|
|
933
|
+
function normalizeUid2(v) {
|
|
934
|
+
const s = String(v ?? "").trim();
|
|
935
|
+
return s.length ? s : null;
|
|
936
|
+
}
|
|
937
|
+
function deriveCompanyBranch(decoded, companyUid, branchUid) {
|
|
938
|
+
const companiesFromToken = Array.isArray(decoded?.companies) ? decoded.companies : [];
|
|
939
|
+
const company = decoded?.company ?? (companyUid ? companiesFromToken.find((c) => c?.uid === companyUid) : null) ?? null;
|
|
940
|
+
const branch = decoded?.branch ?? (branchUid && company?.branches ? (company.branches || []).find((b) => b?.uid === branchUid) : null) ?? null;
|
|
941
|
+
return { companiesFromToken, company, branch };
|
|
942
|
+
}
|
|
943
|
+
function createAuthMiddleware2(opts) {
|
|
944
|
+
const { subject, allowFirebaseIdToken = false } = opts;
|
|
945
|
+
return async (req, res, next) => {
|
|
946
|
+
const token = getBearerToken2(req);
|
|
947
|
+
if (!token) {
|
|
948
|
+
return res.status(401).json({
|
|
949
|
+
ok: false,
|
|
950
|
+
code: "AUTH_MISSING_TOKEN",
|
|
951
|
+
message: "Missing Authorization Bearer token"
|
|
952
|
+
});
|
|
953
|
+
}
|
|
954
|
+
try {
|
|
955
|
+
const decoded = verifyBackendJwtRS2562(token);
|
|
956
|
+
const headerCtx = req.context || {};
|
|
957
|
+
const companyUid = normalizeUid2(headerCtx.company_uid);
|
|
958
|
+
const branchUid = normalizeUid2(headerCtx.branch_uid);
|
|
959
|
+
const { companiesFromToken, company, branch } = deriveCompanyBranch(decoded, companyUid, branchUid);
|
|
960
|
+
const ctx = {
|
|
961
|
+
tokenType: "backend",
|
|
962
|
+
subject,
|
|
963
|
+
company_uid: companyUid ?? void 0,
|
|
964
|
+
branch_uid: branchUid ?? void 0,
|
|
965
|
+
companies: companiesFromToken,
|
|
966
|
+
company,
|
|
967
|
+
branch,
|
|
968
|
+
roles: Array.isArray(decoded?.roles) ? decoded.roles : [],
|
|
969
|
+
permissions: Array.isArray(decoded?.permissions) ? decoded.permissions : [],
|
|
970
|
+
denied_permissions: Array.isArray(decoded?.denied_permissions) ? decoded.denied_permissions : [],
|
|
971
|
+
session: {
|
|
972
|
+
jti: decoded?.jti,
|
|
973
|
+
device_id: decoded?.device_id,
|
|
974
|
+
expires_at: decoded?.exp
|
|
975
|
+
}
|
|
976
|
+
};
|
|
977
|
+
if (subject === "employee") {
|
|
978
|
+
const employee = decoded?.employee ?? decoded?.user ?? null;
|
|
979
|
+
if (!employee) {
|
|
980
|
+
return res.status(401).json({
|
|
981
|
+
ok: false,
|
|
982
|
+
code: "AUTH_EMPLOYEE_NOT_FOUND",
|
|
983
|
+
message: "Employee not found in token"
|
|
984
|
+
});
|
|
985
|
+
}
|
|
986
|
+
ctx.employee = employee;
|
|
987
|
+
} else {
|
|
988
|
+
const customer = decoded?.customer ?? null;
|
|
989
|
+
if (!customer) {
|
|
990
|
+
return res.status(401).json({
|
|
991
|
+
ok: false,
|
|
992
|
+
code: "AUTH_CUSTOMER_NOT_FOUND",
|
|
993
|
+
message: "Customer not found in token"
|
|
994
|
+
});
|
|
995
|
+
}
|
|
996
|
+
ctx.customer = customer;
|
|
997
|
+
}
|
|
998
|
+
req.auth = ctx;
|
|
999
|
+
return next();
|
|
1000
|
+
} catch {
|
|
1001
|
+
if (!allowFirebaseIdToken) {
|
|
1002
|
+
return res.status(401).json({
|
|
1003
|
+
ok: false,
|
|
1004
|
+
code: "AUTH_INVALID_TOKEN",
|
|
1005
|
+
message: "Invalid or expired token"
|
|
1006
|
+
});
|
|
1007
|
+
}
|
|
1008
|
+
try {
|
|
1009
|
+
const firebaseDecoded = await import_firebase_admin.default.auth().verifyIdToken(token);
|
|
1010
|
+
if (firebaseDecoded.email && firebaseDecoded.email_verified === false) {
|
|
1011
|
+
return res.status(401).json({
|
|
1012
|
+
ok: false,
|
|
1013
|
+
code: "AUTH_EMAIL_NOT_VERIFIED",
|
|
1014
|
+
message: "Email not verified"
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
1017
|
+
const headerCtx = req.context || {};
|
|
1018
|
+
const companyUid = normalizeUid2(headerCtx.company_uid);
|
|
1019
|
+
const branchUid = normalizeUid2(headerCtx.branch_uid);
|
|
1020
|
+
req.auth = {
|
|
1021
|
+
tokenType: "backend",
|
|
1022
|
+
subject,
|
|
1023
|
+
firebase: firebaseDecoded,
|
|
1024
|
+
company_uid: companyUid ?? void 0,
|
|
1025
|
+
branch_uid: branchUid ?? void 0,
|
|
1026
|
+
companies: [],
|
|
1027
|
+
roles: [],
|
|
1028
|
+
permissions: [],
|
|
1029
|
+
denied_permissions: []
|
|
1030
|
+
};
|
|
1031
|
+
return next();
|
|
1032
|
+
} catch {
|
|
1033
|
+
return res.status(401).json({
|
|
1034
|
+
ok: false,
|
|
1035
|
+
code: "AUTH_INVALID_TOKEN",
|
|
1036
|
+
message: "Invalid or expired token"
|
|
1037
|
+
});
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
};
|
|
1041
|
+
}
|
|
1042
|
+
var authEmployeeRequired = createAuthMiddleware2({ subject: "employee", allowFirebaseIdToken: false });
|
|
1043
|
+
var authCustomerRequired = createAuthMiddleware2({ subject: "customer", allowFirebaseIdToken: false });
|
|
1044
|
+
var authEmployeeAllowFirebase = createAuthMiddleware2({ subject: "employee", allowFirebaseIdToken: true });
|
|
1045
|
+
var authCustomerAllowFirebase = createAuthMiddleware2({ subject: "customer", allowFirebaseIdToken: true });
|
|
684
1046
|
// Annotate the CommonJS export names for ESM import in node:
|
|
685
1047
|
0 && (module.exports = {
|
|
686
1048
|
HEADER_AUTHORIZATION,
|
|
@@ -690,19 +1052,29 @@ function createAuthMiddleware(opts) {
|
|
|
690
1052
|
HEADER_INTERNAL_API_KEY,
|
|
691
1053
|
HEADER_REQUEST_ID,
|
|
692
1054
|
InternalHttp,
|
|
693
|
-
REQUEST_ID_HEADER,
|
|
694
|
-
REQUEST_ID_HEADER_ALT,
|
|
695
|
-
RESPONSE_REQUEST_ID_HEADER,
|
|
696
1055
|
TwoLevelCache,
|
|
697
1056
|
UpstreamError,
|
|
1057
|
+
authCustomerAllowFirebase,
|
|
1058
|
+
authCustomerRequired,
|
|
1059
|
+
authEmployeeAllowFirebase,
|
|
1060
|
+
authEmployeeRequired,
|
|
698
1061
|
closeCache,
|
|
699
1062
|
createAuthMiddleware,
|
|
1063
|
+
createAuthMiddlewareLegacySimple,
|
|
700
1064
|
createHttpClient,
|
|
701
1065
|
getOrSet,
|
|
702
1066
|
getRequestContextFromHeaders,
|
|
703
1067
|
getTwoLevelCache,
|
|
1068
|
+
internalAuth,
|
|
704
1069
|
mapAxiosToUpstreamError,
|
|
1070
|
+
parseHeaders,
|
|
705
1071
|
readRs256PublicKey,
|
|
1072
|
+
requestId,
|
|
1073
|
+
requireAnyPermission,
|
|
1074
|
+
requireAuthContext,
|
|
1075
|
+
requirePermissions,
|
|
1076
|
+
requireRoles,
|
|
1077
|
+
requireRolesOrAnyPermission,
|
|
706
1078
|
sendError,
|
|
707
1079
|
sendOk,
|
|
708
1080
|
verifyBackendJwtRS256,
|