@innvoid/getmarket-sdk 0.2.7 → 0.2.9
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-HNOUEVHW.js +410 -0
- package/dist/chunk-HNOUEVHW.js.map +1 -0
- package/dist/express.d.cts +1 -1
- package/dist/express.d.ts +1 -1
- package/dist/index.cjs +282 -342
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -24
- package/dist/index.d.ts +11 -24
- package/dist/index.js +196 -15
- package/dist/index.js.map +1 -1
- package/dist/middlewares/index.cjs +88 -204
- package/dist/middlewares/index.cjs.map +1 -1
- package/dist/middlewares/index.d.cts +34 -40
- package/dist/middlewares/index.d.ts +34 -40
- package/dist/middlewares/index.js +1 -1
- package/dist/{types-CRECQuHp.d.cts → types-Cc_McZgD.d.cts} +12 -10
- package/dist/{types-CRECQuHp.d.ts → types-Cc_McZgD.d.ts} +12 -10
- package/package.json +2 -2
- package/dist/chunk-WM2QICZQ.js +0 -666
- package/dist/chunk-WM2QICZQ.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -45,14 +45,9 @@ __export(src_exports, {
|
|
|
45
45
|
allowSysAdminOrPermissionsAll: () => allowSysAdminOrPermissionsAll,
|
|
46
46
|
allowSysAdminOrRoles: () => allowSysAdminOrRoles,
|
|
47
47
|
allowSysAdminOrRolesOrAnyPermission: () => allowSysAdminOrRolesOrAnyPermission,
|
|
48
|
-
authCustomerAllowFirebase: () => authCustomerAllowFirebase,
|
|
49
|
-
authCustomerRequired: () => authCustomerRequired,
|
|
50
|
-
authEmployeeAllowFirebase: () => authEmployeeAllowFirebase,
|
|
51
|
-
authEmployeeRequired: () => authEmployeeRequired,
|
|
52
48
|
buildInternalHeaders: () => buildInternalHeaders,
|
|
53
49
|
closeCache: () => closeCache,
|
|
54
50
|
createAuthMiddleware: () => createAuthMiddleware,
|
|
55
|
-
createAuthMiddlewareLegacySimple: () => createAuthMiddleware2,
|
|
56
51
|
createBulkRefsClient: () => createBulkRefsClient,
|
|
57
52
|
createFisClient: () => createFisClient,
|
|
58
53
|
createHttpClient: () => createHttpClient,
|
|
@@ -63,6 +58,9 @@ __export(src_exports, {
|
|
|
63
58
|
createPayClient: () => createPayClient,
|
|
64
59
|
createPlatformClient: () => createPlatformClient,
|
|
65
60
|
createResClient: () => createResClient,
|
|
61
|
+
extractCustomerUid: () => extractCustomerUid,
|
|
62
|
+
extractEmployeeUid: () => extractEmployeeUid,
|
|
63
|
+
getBearerToken: () => getBearerToken,
|
|
66
64
|
getOrSet: () => getOrSet,
|
|
67
65
|
getRequestContextFromHeaders: () => getRequestContextFromHeaders,
|
|
68
66
|
getTwoLevelCache: () => getTwoLevelCache,
|
|
@@ -71,6 +69,7 @@ __export(src_exports, {
|
|
|
71
69
|
mapAxiosToUpstreamError: () => mapAxiosToUpstreamError,
|
|
72
70
|
newUid: () => newUid,
|
|
73
71
|
newUidV4: () => newUidV4,
|
|
72
|
+
normalizeUid: () => normalizeUid,
|
|
74
73
|
parseHeaders: () => parseHeaders,
|
|
75
74
|
readRs256PublicKey: () => readRs256PublicKey,
|
|
76
75
|
readServiceEnv: () => readServiceEnv,
|
|
@@ -651,6 +650,9 @@ function internalAuth(req, res, next) {
|
|
|
651
650
|
function getAuth(req) {
|
|
652
651
|
return req.auth ?? {};
|
|
653
652
|
}
|
|
653
|
+
function hasAuthContext(req) {
|
|
654
|
+
return !!req.auth;
|
|
655
|
+
}
|
|
654
656
|
function normalizeCode(v) {
|
|
655
657
|
if (!v) return null;
|
|
656
658
|
if (typeof v === "string") return v;
|
|
@@ -675,7 +677,7 @@ function permsSet(list) {
|
|
|
675
677
|
}
|
|
676
678
|
function requireAuthContext() {
|
|
677
679
|
return (req, res, next) => {
|
|
678
|
-
if (!req
|
|
680
|
+
if (!hasAuthContext(req)) {
|
|
679
681
|
return sendError(req, res, 401, "UNAUTHORIZED", "Missing auth context");
|
|
680
682
|
}
|
|
681
683
|
return next();
|
|
@@ -689,6 +691,9 @@ function requirePermissions(perms, options) {
|
|
|
689
691
|
const sysAdminBypass = options?.sysAdminBypass !== false;
|
|
690
692
|
const sysAdminRole = options?.sysAdminRole || "SYS_ADMIN";
|
|
691
693
|
return (req, res, next) => {
|
|
694
|
+
if (!hasAuthContext(req)) {
|
|
695
|
+
return sendError(req, res, 401, "UNAUTHORIZED", "Missing auth context");
|
|
696
|
+
}
|
|
692
697
|
const auth = getAuth(req);
|
|
693
698
|
if (sysAdminBypass && isSysAdmin(auth, sysAdminRole)) return next();
|
|
694
699
|
const allow = permsSet(auth.permissions);
|
|
@@ -714,6 +719,9 @@ function requireAnyPermission(perms, options) {
|
|
|
714
719
|
const sysAdminBypass = options?.sysAdminBypass !== false;
|
|
715
720
|
const sysAdminRole = options?.sysAdminRole || "SYS_ADMIN";
|
|
716
721
|
return (req, res, next) => {
|
|
722
|
+
if (!hasAuthContext(req)) {
|
|
723
|
+
return sendError(req, res, 401, "UNAUTHORIZED", "Missing auth context");
|
|
724
|
+
}
|
|
717
725
|
const auth = getAuth(req);
|
|
718
726
|
if (sysAdminBypass && isSysAdmin(auth, sysAdminRole)) return next();
|
|
719
727
|
const allow = permsSet(auth.permissions);
|
|
@@ -739,6 +747,9 @@ function requireRoles(roles, options) {
|
|
|
739
747
|
const sysAdminBypass = options?.sysAdminBypass !== false;
|
|
740
748
|
const sysAdminRole = options?.sysAdminRole || "SYS_ADMIN";
|
|
741
749
|
return (req, res, next) => {
|
|
750
|
+
if (!hasAuthContext(req)) {
|
|
751
|
+
return sendError(req, res, 401, "UNAUTHORIZED", "Missing auth context");
|
|
752
|
+
}
|
|
742
753
|
const auth = getAuth(req);
|
|
743
754
|
if (sysAdminBypass && isSysAdmin(auth, sysAdminRole)) return next();
|
|
744
755
|
const have = rolesSet(auth);
|
|
@@ -755,6 +766,9 @@ function requireRolesOrAnyPermission(roles, perms, options) {
|
|
|
755
766
|
const sysAdminBypass = options?.sysAdminBypass !== false;
|
|
756
767
|
const sysAdminRole = options?.sysAdminRole || "SYS_ADMIN";
|
|
757
768
|
return (req, res, next) => {
|
|
769
|
+
if (!hasAuthContext(req)) {
|
|
770
|
+
return sendError(req, res, 401, "UNAUTHORIZED", "Missing auth context");
|
|
771
|
+
}
|
|
758
772
|
const auth = getAuth(req);
|
|
759
773
|
if (sysAdminBypass && isSysAdmin(auth, sysAdminRole)) return next();
|
|
760
774
|
const haveRoles = rolesSet(auth);
|
|
@@ -780,6 +794,157 @@ function requireRolesOrAnyPermission(roles, perms, options) {
|
|
|
780
794
|
};
|
|
781
795
|
}
|
|
782
796
|
|
|
797
|
+
// src/middlewares/guards.ts
|
|
798
|
+
function normalizeRole(r) {
|
|
799
|
+
if (!r) return null;
|
|
800
|
+
if (typeof r === "string") return r;
|
|
801
|
+
return r.code || r.name || null;
|
|
802
|
+
}
|
|
803
|
+
function normalizePerm(p) {
|
|
804
|
+
if (!p) return null;
|
|
805
|
+
if (typeof p === "string") return p;
|
|
806
|
+
return p.code || p.name || null;
|
|
807
|
+
}
|
|
808
|
+
function getAuth2(req) {
|
|
809
|
+
return req.auth ?? {};
|
|
810
|
+
}
|
|
811
|
+
function roleSet(auth) {
|
|
812
|
+
return new Set(
|
|
813
|
+
(auth.roles ?? []).map(normalizeRole).filter(Boolean)
|
|
814
|
+
);
|
|
815
|
+
}
|
|
816
|
+
function permissionSets(auth) {
|
|
817
|
+
const allow = new Set(
|
|
818
|
+
(auth.permissions ?? []).map(normalizePerm).filter(Boolean)
|
|
819
|
+
);
|
|
820
|
+
const deny = new Set(
|
|
821
|
+
(auth.denied_permissions ?? []).map(normalizePerm).filter(Boolean)
|
|
822
|
+
);
|
|
823
|
+
return { allow, deny };
|
|
824
|
+
}
|
|
825
|
+
function normalizeHandlers(auth) {
|
|
826
|
+
if (!auth) return [];
|
|
827
|
+
return Array.isArray(auth) ? auth : [auth];
|
|
828
|
+
}
|
|
829
|
+
function buildBaseChain(options) {
|
|
830
|
+
const chain = [];
|
|
831
|
+
if (options?.includeParseHeaders !== false) {
|
|
832
|
+
chain.push(parseHeaders);
|
|
833
|
+
}
|
|
834
|
+
chain.push(...normalizeHandlers(options?.auth));
|
|
835
|
+
return chain;
|
|
836
|
+
}
|
|
837
|
+
function hasSysAdmin(auth, options) {
|
|
838
|
+
const sysAdminBypass = options?.sysAdminBypass !== false;
|
|
839
|
+
if (!sysAdminBypass) return false;
|
|
840
|
+
const sysAdminRole = options?.sysAdminRole || "SYS_ADMIN";
|
|
841
|
+
return roleSet(auth).has(sysAdminRole);
|
|
842
|
+
}
|
|
843
|
+
function allowSysAdminOrAnyPermission(perms, options) {
|
|
844
|
+
const required = (Array.isArray(perms) ? perms : [perms]).filter(Boolean);
|
|
845
|
+
return [
|
|
846
|
+
...buildBaseChain(options),
|
|
847
|
+
(req, res, next) => {
|
|
848
|
+
const auth = getAuth2(req);
|
|
849
|
+
if (hasSysAdmin(auth, options)) return next();
|
|
850
|
+
const { allow, deny } = permissionSets(auth);
|
|
851
|
+
for (const p of required) {
|
|
852
|
+
if (deny.has(p)) {
|
|
853
|
+
return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, {
|
|
854
|
+
denied: p
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
const ok = required.some((p) => allow.has(p));
|
|
859
|
+
if (!ok) {
|
|
860
|
+
return sendError(req, res, 403, "FORBIDDEN", "Missing permissions (ANY)", {
|
|
861
|
+
required,
|
|
862
|
+
mode: "ANY"
|
|
863
|
+
});
|
|
864
|
+
}
|
|
865
|
+
return next();
|
|
866
|
+
}
|
|
867
|
+
];
|
|
868
|
+
}
|
|
869
|
+
function allowSysAdminOrPermissionsAll(perms, options) {
|
|
870
|
+
const required = (Array.isArray(perms) ? perms : [perms]).filter(Boolean);
|
|
871
|
+
return [
|
|
872
|
+
...buildBaseChain(options),
|
|
873
|
+
(req, res, next) => {
|
|
874
|
+
const auth = getAuth2(req);
|
|
875
|
+
if (hasSysAdmin(auth, options)) return next();
|
|
876
|
+
const { allow, deny } = permissionSets(auth);
|
|
877
|
+
for (const p of required) {
|
|
878
|
+
if (deny.has(p)) {
|
|
879
|
+
return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, {
|
|
880
|
+
denied: p
|
|
881
|
+
});
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
const missing = required.filter((p) => !allow.has(p));
|
|
885
|
+
if (missing.length) {
|
|
886
|
+
return sendError(req, res, 403, "FORBIDDEN", "Missing permissions (ALL)", {
|
|
887
|
+
required,
|
|
888
|
+
missing,
|
|
889
|
+
mode: "ALL"
|
|
890
|
+
});
|
|
891
|
+
}
|
|
892
|
+
return next();
|
|
893
|
+
}
|
|
894
|
+
];
|
|
895
|
+
}
|
|
896
|
+
function allowSysAdminOrRoles(roles, options) {
|
|
897
|
+
const required = (Array.isArray(roles) ? roles : [roles]).filter(Boolean);
|
|
898
|
+
return [
|
|
899
|
+
...buildBaseChain(options),
|
|
900
|
+
(req, res, next) => {
|
|
901
|
+
const auth = getAuth2(req);
|
|
902
|
+
if (hasSysAdmin(auth, options)) return next();
|
|
903
|
+
const have = roleSet(auth);
|
|
904
|
+
const ok = required.some((r) => have.has(r));
|
|
905
|
+
if (!ok) {
|
|
906
|
+
return sendError(req, res, 403, "FORBIDDEN", "Role not allowed", {
|
|
907
|
+
required,
|
|
908
|
+
mode: "ANY"
|
|
909
|
+
});
|
|
910
|
+
}
|
|
911
|
+
return next();
|
|
912
|
+
}
|
|
913
|
+
];
|
|
914
|
+
}
|
|
915
|
+
function allowSysAdminOrRolesOrAnyPermission(roles, permissions, options) {
|
|
916
|
+
const requiredRoles = (Array.isArray(roles) ? roles : [roles]).filter(Boolean);
|
|
917
|
+
const requiredPerms = (Array.isArray(permissions) ? permissions : [permissions]).filter(Boolean);
|
|
918
|
+
return [
|
|
919
|
+
...buildBaseChain(options),
|
|
920
|
+
(req, res, next) => {
|
|
921
|
+
const auth = getAuth2(req);
|
|
922
|
+
if (hasSysAdmin(auth, options)) return next();
|
|
923
|
+
const { allow, deny } = permissionSets(auth);
|
|
924
|
+
const haveRoles = roleSet(auth);
|
|
925
|
+
for (const p of requiredPerms) {
|
|
926
|
+
if (deny.has(p)) {
|
|
927
|
+
return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, {
|
|
928
|
+
denied: p
|
|
929
|
+
});
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
const okRole = requiredRoles.some((r) => haveRoles.has(r));
|
|
933
|
+
if (okRole) return next();
|
|
934
|
+
const okPerm = requiredPerms.some((p) => allow.has(p));
|
|
935
|
+
if (okPerm) return next();
|
|
936
|
+
return sendError(req, res, 403, "FORBIDDEN", "Permission denied", {
|
|
937
|
+
roles: requiredRoles,
|
|
938
|
+
permissions: requiredPerms,
|
|
939
|
+
mode: "ROLES_OR_ANY_PERMISSION"
|
|
940
|
+
});
|
|
941
|
+
}
|
|
942
|
+
];
|
|
943
|
+
}
|
|
944
|
+
function allowAuthAdminOrPerm(permission, options) {
|
|
945
|
+
return allowSysAdminOrRolesOrAnyPermission(["AUTH_ADMIN"], [permission], options);
|
|
946
|
+
}
|
|
947
|
+
|
|
783
948
|
// src/auth/jwt.ts
|
|
784
949
|
var import_fs2 = __toESM(require("fs"), 1);
|
|
785
950
|
var import_jsonwebtoken = __toESM(require("jsonwebtoken"), 1);
|
|
@@ -792,12 +957,26 @@ function readFileIfExists(path) {
|
|
|
792
957
|
return null;
|
|
793
958
|
}
|
|
794
959
|
}
|
|
960
|
+
function getBearerToken(req) {
|
|
961
|
+
const auth = String(req?.headers?.authorization || "");
|
|
962
|
+
if (!auth.startsWith("Bearer ")) return null;
|
|
963
|
+
const token = auth.slice(7).trim();
|
|
964
|
+
return token.length ? token : null;
|
|
965
|
+
}
|
|
966
|
+
function normalizeUid(v) {
|
|
967
|
+
const s = String(v ?? "").trim();
|
|
968
|
+
return s.length ? s : null;
|
|
969
|
+
}
|
|
795
970
|
function readRs256PublicKey() {
|
|
796
971
|
const fromFile = readFileIfExists(process.env.JWT_PUBLIC_KEY_PATH);
|
|
797
972
|
if (fromFile) return fromFile;
|
|
798
|
-
const fromEnv = String(
|
|
973
|
+
const fromEnv = String(
|
|
974
|
+
process.env.AUTH_JWT_PUBLIC_KEY || process.env.AUTH_RSA_PUBLIC_KEY || ""
|
|
975
|
+
).replace(/\\n/g, "\n").trim();
|
|
799
976
|
if (fromEnv) return fromEnv;
|
|
800
|
-
throw new Error(
|
|
977
|
+
throw new Error(
|
|
978
|
+
"Missing RS256 public key (JWT_PUBLIC_KEY_PATH / AUTH_JWT_PUBLIC_KEY / AUTH_RSA_PUBLIC_KEY)"
|
|
979
|
+
);
|
|
801
980
|
}
|
|
802
981
|
function verifyBackendJwtRS256(raw) {
|
|
803
982
|
const publicKey = readRs256PublicKey();
|
|
@@ -809,28 +988,46 @@ function verifyBackendJwtRS256(raw) {
|
|
|
809
988
|
issuer
|
|
810
989
|
});
|
|
811
990
|
}
|
|
991
|
+
function extractEmployeeUid(decoded) {
|
|
992
|
+
const direct = normalizeUid(decoded?.employee_uid) ?? normalizeUid(decoded?.employee?.uid);
|
|
993
|
+
if (direct) return direct;
|
|
994
|
+
const sub = normalizeUid(decoded?.sub);
|
|
995
|
+
if (!sub) return null;
|
|
996
|
+
const match = /^emp:(.+)$/i.exec(sub);
|
|
997
|
+
return match?.[1] ? normalizeUid(match[1]) : null;
|
|
998
|
+
}
|
|
999
|
+
function extractCustomerUid(decoded) {
|
|
1000
|
+
const direct = normalizeUid(decoded?.customer_uid) ?? normalizeUid(decoded?.customer?.uid);
|
|
1001
|
+
if (direct) return direct;
|
|
1002
|
+
const sub = normalizeUid(decoded?.sub);
|
|
1003
|
+
if (!sub) return null;
|
|
1004
|
+
const match = /^cus:(.+)$/i.exec(sub);
|
|
1005
|
+
return match?.[1] ? normalizeUid(match[1]) : null;
|
|
1006
|
+
}
|
|
812
1007
|
|
|
813
1008
|
// src/auth/middleware.ts
|
|
814
|
-
function
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
}
|
|
820
|
-
function normalizeUid(v) {
|
|
821
|
-
const s = String(v ?? "").trim();
|
|
822
|
-
return s.length ? s : null;
|
|
1009
|
+
function sendAuthError(res, code, message, status = 401) {
|
|
1010
|
+
return res.status(status).json({
|
|
1011
|
+
ok: false,
|
|
1012
|
+
code,
|
|
1013
|
+
message
|
|
1014
|
+
});
|
|
823
1015
|
}
|
|
824
1016
|
function createAuthMiddleware(opts) {
|
|
825
|
-
const {
|
|
1017
|
+
const {
|
|
1018
|
+
subject,
|
|
1019
|
+
allowFirebaseIdToken = false,
|
|
1020
|
+
requireSubject = true,
|
|
1021
|
+
hydrate
|
|
1022
|
+
} = opts;
|
|
826
1023
|
return async (req, res, next) => {
|
|
827
1024
|
const token = getBearerToken(req);
|
|
828
1025
|
if (!token) {
|
|
829
|
-
return
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
1026
|
+
return sendAuthError(
|
|
1027
|
+
res,
|
|
1028
|
+
"AUTH_MISSING_TOKEN",
|
|
1029
|
+
"Missing Authorization Bearer token"
|
|
1030
|
+
);
|
|
834
1031
|
}
|
|
835
1032
|
const headerCtx = req.context || {};
|
|
836
1033
|
const company_uid = normalizeUid(headerCtx.company_uid);
|
|
@@ -851,45 +1048,70 @@ function createAuthMiddleware(opts) {
|
|
|
851
1048
|
expires_at: decoded?.exp
|
|
852
1049
|
}
|
|
853
1050
|
};
|
|
854
|
-
|
|
1051
|
+
if (subject === "employee") {
|
|
1052
|
+
baseCtx.employee_uid = extractEmployeeUid(decoded) ?? void 0;
|
|
1053
|
+
} else {
|
|
1054
|
+
baseCtx.customer_uid = extractCustomerUid(decoded) ?? void 0;
|
|
1055
|
+
}
|
|
1056
|
+
const hydrated = await hydrate({
|
|
1057
|
+
decoded,
|
|
1058
|
+
req,
|
|
1059
|
+
subject,
|
|
1060
|
+
company_uid,
|
|
1061
|
+
branch_uid
|
|
1062
|
+
});
|
|
855
1063
|
Object.assign(baseCtx, hydrated);
|
|
1064
|
+
if (subject === "employee" && !baseCtx.employee_uid) {
|
|
1065
|
+
return sendAuthError(
|
|
1066
|
+
res,
|
|
1067
|
+
"AUTH_EMPLOYEE_UID_MISSING",
|
|
1068
|
+
"employee_uid missing in token/context (expected employee_uid or sub=emp:<uid>)"
|
|
1069
|
+
);
|
|
1070
|
+
}
|
|
1071
|
+
if (subject === "customer" && !baseCtx.customer_uid) {
|
|
1072
|
+
return sendAuthError(
|
|
1073
|
+
res,
|
|
1074
|
+
"AUTH_CUSTOMER_UID_MISSING",
|
|
1075
|
+
"customer_uid missing in token/context (expected customer_uid or sub=cus:<uid>)"
|
|
1076
|
+
);
|
|
1077
|
+
}
|
|
856
1078
|
if (requireSubject) {
|
|
857
1079
|
if (subject === "employee" && !baseCtx.employee) {
|
|
858
|
-
return
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
1080
|
+
return sendAuthError(
|
|
1081
|
+
res,
|
|
1082
|
+
"AUTH_EMPLOYEE_NOT_FOUND",
|
|
1083
|
+
"Employee not resolved by hydrator"
|
|
1084
|
+
);
|
|
863
1085
|
}
|
|
864
1086
|
if (subject === "customer" && !baseCtx.customer) {
|
|
865
|
-
return
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
1087
|
+
return sendAuthError(
|
|
1088
|
+
res,
|
|
1089
|
+
"AUTH_CUSTOMER_NOT_FOUND",
|
|
1090
|
+
"Customer not resolved by hydrator"
|
|
1091
|
+
);
|
|
870
1092
|
}
|
|
871
1093
|
}
|
|
872
1094
|
req.auth = baseCtx;
|
|
873
1095
|
return next();
|
|
874
|
-
} catch {
|
|
1096
|
+
} catch (backendErr) {
|
|
875
1097
|
if (!allowFirebaseIdToken) {
|
|
876
|
-
return
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
1098
|
+
return sendAuthError(
|
|
1099
|
+
res,
|
|
1100
|
+
"AUTH_INVALID_TOKEN",
|
|
1101
|
+
"Invalid or expired token"
|
|
1102
|
+
);
|
|
881
1103
|
}
|
|
882
1104
|
try {
|
|
883
|
-
const { default:
|
|
884
|
-
const firebaseDecoded = await
|
|
1105
|
+
const { default: admin } = await import("firebase-admin");
|
|
1106
|
+
const firebaseDecoded = await admin.auth().verifyIdToken(token);
|
|
885
1107
|
if (firebaseDecoded.email && firebaseDecoded.email_verified === false) {
|
|
886
|
-
return
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
1108
|
+
return sendAuthError(
|
|
1109
|
+
res,
|
|
1110
|
+
"AUTH_EMAIL_NOT_VERIFIED",
|
|
1111
|
+
"Email not verified"
|
|
1112
|
+
);
|
|
891
1113
|
}
|
|
892
|
-
|
|
1114
|
+
const firebaseCtx = {
|
|
893
1115
|
tokenType: "backend",
|
|
894
1116
|
subject,
|
|
895
1117
|
firebase: firebaseDecoded,
|
|
@@ -900,302 +1122,21 @@ function createAuthMiddleware(opts) {
|
|
|
900
1122
|
permissions: [],
|
|
901
1123
|
denied_permissions: []
|
|
902
1124
|
};
|
|
1125
|
+
req.auth = firebaseCtx;
|
|
903
1126
|
return next();
|
|
904
1127
|
} catch {
|
|
905
|
-
return
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
};
|
|
913
|
-
}
|
|
914
|
-
|
|
915
|
-
// src/auth/authentication.ts
|
|
916
|
-
var import_firebase_admin = __toESM(require("firebase-admin"), 1);
|
|
917
|
-
var import_jsonwebtoken2 = __toESM(require("jsonwebtoken"), 1);
|
|
918
|
-
var import_fs3 = __toESM(require("fs"), 1);
|
|
919
|
-
function getBearerToken2(req) {
|
|
920
|
-
const auth = String(req.headers?.authorization || "");
|
|
921
|
-
if (!auth.startsWith("Bearer ")) return null;
|
|
922
|
-
const token = auth.slice(7).trim();
|
|
923
|
-
return token.length ? token : null;
|
|
924
|
-
}
|
|
925
|
-
function readPublicKey() {
|
|
926
|
-
const publicKeyPath = process.env.JWT_PUBLIC_KEY_PATH;
|
|
927
|
-
const publicKeyEnv = process.env.AUTH_JWT_PUBLIC_KEY || process.env.AUTH_RSA_PUBLIC_KEY || "";
|
|
928
|
-
if (publicKeyPath) {
|
|
929
|
-
const v = import_fs3.default.readFileSync(publicKeyPath, "utf8").trim();
|
|
930
|
-
if (v) return v;
|
|
931
|
-
}
|
|
932
|
-
const envKey = publicKeyEnv.replace(/\\n/g, "\n").trim();
|
|
933
|
-
if (envKey) return envKey;
|
|
934
|
-
throw new Error("Missing RS256 public key (JWT_PUBLIC_KEY_PATH / AUTH_JWT_PUBLIC_KEY / AUTH_RSA_PUBLIC_KEY)");
|
|
935
|
-
}
|
|
936
|
-
function verifyBackendJwtRS2562(raw) {
|
|
937
|
-
const publicKey = readPublicKey();
|
|
938
|
-
const audience = process.env.JWT_AUDIENCE || process.env.AUTH_JWT_AUDIENCE || "getmarket.api";
|
|
939
|
-
const issuer = process.env.JWT_ISSUER || process.env.AUTH_JWT_ISSUER || "getmarket-auth";
|
|
940
|
-
return import_jsonwebtoken2.default.verify(raw, publicKey, {
|
|
941
|
-
algorithms: ["RS256"],
|
|
942
|
-
audience,
|
|
943
|
-
issuer
|
|
944
|
-
});
|
|
945
|
-
}
|
|
946
|
-
function normalizeUid2(v) {
|
|
947
|
-
const s = String(v ?? "").trim();
|
|
948
|
-
return s.length ? s : null;
|
|
949
|
-
}
|
|
950
|
-
function deriveCompanyBranch(decoded, companyUid, branchUid) {
|
|
951
|
-
const companiesFromToken = Array.isArray(decoded?.companies) ? decoded.companies : [];
|
|
952
|
-
const company = decoded?.company ?? (companyUid ? companiesFromToken.find((c) => c?.uid === companyUid) : null) ?? null;
|
|
953
|
-
const branch = decoded?.branch ?? (branchUid && company?.branches ? (company.branches || []).find((b) => b?.uid === branchUid) : null) ?? null;
|
|
954
|
-
return { companiesFromToken, company, branch };
|
|
955
|
-
}
|
|
956
|
-
function extractEmployeeUid(decoded) {
|
|
957
|
-
const direct = normalizeUid2(decoded?.employee_uid);
|
|
958
|
-
if (direct) return direct;
|
|
959
|
-
const sub = normalizeUid2(decoded?.sub);
|
|
960
|
-
if (!sub) return null;
|
|
961
|
-
const m = /^emp:(.+)$/i.exec(sub);
|
|
962
|
-
return m?.[1] ? normalizeUid2(m[1]) : null;
|
|
963
|
-
}
|
|
964
|
-
function extractCustomerUid(decoded) {
|
|
965
|
-
const direct = normalizeUid2(decoded?.customer_uid);
|
|
966
|
-
if (direct) return direct;
|
|
967
|
-
const sub = normalizeUid2(decoded?.sub);
|
|
968
|
-
if (!sub) return null;
|
|
969
|
-
const m = /^cus:(.+)$/i.exec(sub);
|
|
970
|
-
return m?.[1] ? normalizeUid2(m[1]) : null;
|
|
971
|
-
}
|
|
972
|
-
function createAuthMiddleware2(opts) {
|
|
973
|
-
const { subject, allowFirebaseIdToken = false } = opts;
|
|
974
|
-
return async (req, res, next) => {
|
|
975
|
-
const token = getBearerToken2(req);
|
|
976
|
-
if (!token) {
|
|
977
|
-
return res.status(401).json({
|
|
978
|
-
ok: false,
|
|
979
|
-
code: "AUTH_MISSING_TOKEN",
|
|
980
|
-
message: "Missing Authorization Bearer token"
|
|
981
|
-
});
|
|
982
|
-
}
|
|
983
|
-
try {
|
|
984
|
-
const decoded = verifyBackendJwtRS2562(token);
|
|
985
|
-
const headerCtx = req.context || {};
|
|
986
|
-
const companyUid = normalizeUid2(headerCtx.company_uid);
|
|
987
|
-
const branchUid = normalizeUid2(headerCtx.branch_uid);
|
|
988
|
-
const { companiesFromToken, company, branch } = deriveCompanyBranch(decoded, companyUid, branchUid);
|
|
989
|
-
const ctx = {
|
|
990
|
-
tokenType: "backend",
|
|
991
|
-
subject,
|
|
992
|
-
company_uid: companyUid ?? void 0,
|
|
993
|
-
branch_uid: branchUid ?? void 0,
|
|
994
|
-
companies: companiesFromToken,
|
|
995
|
-
company,
|
|
996
|
-
branch,
|
|
997
|
-
roles: Array.isArray(decoded?.roles) ? decoded.roles : [],
|
|
998
|
-
permissions: Array.isArray(decoded?.permissions) ? decoded.permissions : [],
|
|
999
|
-
denied_permissions: Array.isArray(decoded?.denied_permissions) ? decoded.denied_permissions : [],
|
|
1000
|
-
session: {
|
|
1001
|
-
jti: decoded?.jti,
|
|
1002
|
-
device_id: decoded?.device_id,
|
|
1003
|
-
expires_at: decoded?.exp
|
|
1004
|
-
}
|
|
1005
|
-
};
|
|
1006
|
-
if (subject === "employee") {
|
|
1007
|
-
const employee_uid = extractEmployeeUid(decoded);
|
|
1008
|
-
if (!employee_uid) {
|
|
1009
|
-
return res.status(401).json({
|
|
1010
|
-
ok: false,
|
|
1011
|
-
code: "AUTH_EMPLOYEE_UID_MISSING",
|
|
1012
|
-
message: "employee_uid missing in token (expected employee_uid or sub=emp:<uid>)"
|
|
1013
|
-
});
|
|
1014
|
-
}
|
|
1015
|
-
ctx.employee_uid = employee_uid;
|
|
1016
|
-
const embedded = decoded?.employee ?? decoded?.user ?? null;
|
|
1017
|
-
ctx.employee = embedded && typeof embedded === "object" ? embedded : { uid: employee_uid, email: decoded?.email ?? null };
|
|
1018
|
-
} else {
|
|
1019
|
-
const customer_uid = extractCustomerUid(decoded);
|
|
1020
|
-
if (!customer_uid) {
|
|
1021
|
-
return res.status(401).json({
|
|
1022
|
-
ok: false,
|
|
1023
|
-
code: "AUTH_CUSTOMER_UID_MISSING",
|
|
1024
|
-
message: "customer_uid missing in token (expected customer_uid or sub=cus:<uid>)"
|
|
1025
|
-
});
|
|
1026
|
-
}
|
|
1027
|
-
ctx.customer_uid = customer_uid;
|
|
1028
|
-
const embedded = decoded?.customer ?? null;
|
|
1029
|
-
ctx.customer = embedded && typeof embedded === "object" ? embedded : { uid: customer_uid };
|
|
1030
|
-
}
|
|
1031
|
-
req.auth = ctx;
|
|
1032
|
-
return next();
|
|
1033
|
-
} catch {
|
|
1034
|
-
if (!allowFirebaseIdToken) {
|
|
1035
|
-
return res.status(401).json({
|
|
1036
|
-
ok: false,
|
|
1037
|
-
code: "AUTH_INVALID_TOKEN",
|
|
1038
|
-
message: "Invalid or expired token"
|
|
1039
|
-
});
|
|
1040
|
-
}
|
|
1041
|
-
try {
|
|
1042
|
-
const firebaseDecoded = await import_firebase_admin.default.auth().verifyIdToken(token);
|
|
1043
|
-
if (firebaseDecoded.email && firebaseDecoded.email_verified === false) {
|
|
1044
|
-
return res.status(401).json({
|
|
1045
|
-
ok: false,
|
|
1046
|
-
code: "AUTH_EMAIL_NOT_VERIFIED",
|
|
1047
|
-
message: "Email not verified"
|
|
1048
|
-
});
|
|
1049
|
-
}
|
|
1050
|
-
const headerCtx = req.context || {};
|
|
1051
|
-
const companyUid = normalizeUid2(headerCtx.company_uid);
|
|
1052
|
-
const branchUid = normalizeUid2(headerCtx.branch_uid);
|
|
1053
|
-
req.auth = {
|
|
1054
|
-
tokenType: "backend",
|
|
1055
|
-
subject,
|
|
1056
|
-
firebase: firebaseDecoded,
|
|
1057
|
-
company_uid: companyUid ?? void 0,
|
|
1058
|
-
branch_uid: branchUid ?? void 0,
|
|
1059
|
-
companies: [],
|
|
1060
|
-
roles: [],
|
|
1061
|
-
permissions: [],
|
|
1062
|
-
denied_permissions: []
|
|
1063
|
-
};
|
|
1064
|
-
return next();
|
|
1065
|
-
} catch {
|
|
1066
|
-
return res.status(401).json({
|
|
1067
|
-
ok: false,
|
|
1068
|
-
code: "AUTH_INVALID_TOKEN",
|
|
1069
|
-
message: "Invalid or expired token"
|
|
1070
|
-
});
|
|
1128
|
+
return sendAuthError(
|
|
1129
|
+
res,
|
|
1130
|
+
"AUTH_INVALID_TOKEN",
|
|
1131
|
+
"Invalid or expired token"
|
|
1132
|
+
);
|
|
1071
1133
|
}
|
|
1072
1134
|
}
|
|
1073
1135
|
};
|
|
1074
1136
|
}
|
|
1075
|
-
var authEmployeeRequired = createAuthMiddleware2({ subject: "employee", allowFirebaseIdToken: false });
|
|
1076
|
-
var authCustomerRequired = createAuthMiddleware2({ subject: "customer", allowFirebaseIdToken: false });
|
|
1077
|
-
var authEmployeeAllowFirebase = createAuthMiddleware2({ subject: "employee", allowFirebaseIdToken: true });
|
|
1078
|
-
var authCustomerAllowFirebase = createAuthMiddleware2({ subject: "customer", allowFirebaseIdToken: true });
|
|
1079
|
-
|
|
1080
|
-
// src/middlewares/guards.ts
|
|
1081
|
-
function normalizeRole(r) {
|
|
1082
|
-
if (!r) return null;
|
|
1083
|
-
if (typeof r === "string") return r;
|
|
1084
|
-
return r.code || r.name || null;
|
|
1085
|
-
}
|
|
1086
|
-
function normalizePerm(p) {
|
|
1087
|
-
if (!p) return null;
|
|
1088
|
-
if (typeof p === "string") return p;
|
|
1089
|
-
return p.code || p.name || null;
|
|
1090
|
-
}
|
|
1091
|
-
function isSysAdmin2(roles) {
|
|
1092
|
-
if (!Array.isArray(roles)) return false;
|
|
1093
|
-
return roles.some((r) => normalizeRole(r) === "SYS_ADMIN");
|
|
1094
|
-
}
|
|
1095
|
-
function getAuth2(req) {
|
|
1096
|
-
return req.auth ?? {};
|
|
1097
|
-
}
|
|
1098
|
-
function permissionSets(auth) {
|
|
1099
|
-
const allow = new Set((auth.permissions ?? []).map(normalizePerm).filter(Boolean));
|
|
1100
|
-
const deny = new Set((auth.denied_permissions ?? []).map(normalizePerm).filter(Boolean));
|
|
1101
|
-
return { allow, deny };
|
|
1102
|
-
}
|
|
1103
|
-
function roleSet(auth) {
|
|
1104
|
-
return new Set((auth.roles ?? []).map(normalizeRole).filter(Boolean));
|
|
1105
|
-
}
|
|
1106
|
-
function allowSysAdminOrAnyPermission(...perms) {
|
|
1107
|
-
const required = (perms ?? []).filter(Boolean);
|
|
1108
|
-
return [
|
|
1109
|
-
parseHeaders,
|
|
1110
|
-
authEmployeeRequired,
|
|
1111
|
-
(req, res, next) => {
|
|
1112
|
-
const auth = getAuth2(req);
|
|
1113
|
-
if (isSysAdmin2(auth.roles)) return next();
|
|
1114
|
-
const { allow, deny } = permissionSets(auth);
|
|
1115
|
-
for (const p of required) {
|
|
1116
|
-
if (deny.has(p)) {
|
|
1117
|
-
return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, { denied: p });
|
|
1118
|
-
}
|
|
1119
|
-
}
|
|
1120
|
-
const ok = required.some((p) => allow.has(p));
|
|
1121
|
-
if (!ok) {
|
|
1122
|
-
return sendError(req, res, 403, "FORBIDDEN", "Missing permissions (ANY)", { required });
|
|
1123
|
-
}
|
|
1124
|
-
return next();
|
|
1125
|
-
}
|
|
1126
|
-
];
|
|
1127
|
-
}
|
|
1128
|
-
function allowSysAdminOrPermissionsAll(...perms) {
|
|
1129
|
-
const required = (perms ?? []).filter(Boolean);
|
|
1130
|
-
return [
|
|
1131
|
-
parseHeaders,
|
|
1132
|
-
authEmployeeRequired,
|
|
1133
|
-
(req, res, next) => {
|
|
1134
|
-
const auth = getAuth2(req);
|
|
1135
|
-
if (isSysAdmin2(auth.roles)) return next();
|
|
1136
|
-
const { allow, deny } = permissionSets(auth);
|
|
1137
|
-
for (const p of required) {
|
|
1138
|
-
if (deny.has(p)) {
|
|
1139
|
-
return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, { denied: p });
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
|
-
const missing = required.filter((p) => !allow.has(p));
|
|
1143
|
-
if (missing.length) {
|
|
1144
|
-
return sendError(req, res, 403, "FORBIDDEN", "Missing permissions (ALL)", { required, missing });
|
|
1145
|
-
}
|
|
1146
|
-
return next();
|
|
1147
|
-
}
|
|
1148
|
-
];
|
|
1149
|
-
}
|
|
1150
|
-
function allowSysAdminOrRoles(...roles) {
|
|
1151
|
-
const required = (roles ?? []).filter(Boolean);
|
|
1152
|
-
return [
|
|
1153
|
-
parseHeaders,
|
|
1154
|
-
authEmployeeRequired,
|
|
1155
|
-
(req, res, next) => {
|
|
1156
|
-
const auth = getAuth2(req);
|
|
1157
|
-
if (isSysAdmin2(auth.roles)) return next();
|
|
1158
|
-
const have = roleSet(auth);
|
|
1159
|
-
const ok = required.some((r) => have.has(r));
|
|
1160
|
-
if (!ok) {
|
|
1161
|
-
return sendError(req, res, 403, "FORBIDDEN", "Role not allowed", { required });
|
|
1162
|
-
}
|
|
1163
|
-
return next();
|
|
1164
|
-
}
|
|
1165
|
-
];
|
|
1166
|
-
}
|
|
1167
|
-
function allowSysAdminOrRolesOrAnyPermission(roles, permissions) {
|
|
1168
|
-
const requiredRoles = (Array.isArray(roles) ? roles : [roles]).filter(Boolean);
|
|
1169
|
-
const requiredPerms = (Array.isArray(permissions) ? permissions : [permissions]).filter(Boolean);
|
|
1170
|
-
return [
|
|
1171
|
-
parseHeaders,
|
|
1172
|
-
authEmployeeRequired,
|
|
1173
|
-
(req, res, next) => {
|
|
1174
|
-
const auth = getAuth2(req);
|
|
1175
|
-
if (isSysAdmin2(auth.roles)) return next();
|
|
1176
|
-
const { allow, deny } = permissionSets(auth);
|
|
1177
|
-
for (const p of requiredPerms) {
|
|
1178
|
-
if (deny.has(p)) {
|
|
1179
|
-
return sendError(req, res, 403, "FORBIDDEN", `Denied: ${p}`, { permission: p });
|
|
1180
|
-
}
|
|
1181
|
-
}
|
|
1182
|
-
const haveRoles = roleSet(auth);
|
|
1183
|
-
if (requiredRoles.some((r) => haveRoles.has(r))) return next();
|
|
1184
|
-
if (requiredPerms.some((p) => allow.has(p))) return next();
|
|
1185
|
-
return sendError(req, res, 403, "FORBIDDEN", "Permission denied", {
|
|
1186
|
-
roles: requiredRoles,
|
|
1187
|
-
permissions: requiredPerms,
|
|
1188
|
-
mode: "ROLES_OR_ANY_PERMISSION"
|
|
1189
|
-
});
|
|
1190
|
-
}
|
|
1191
|
-
];
|
|
1192
|
-
}
|
|
1193
|
-
function allowAuthAdminOrPerm(permission) {
|
|
1194
|
-
return allowSysAdminOrRolesOrAnyPermission(["AUTH_ADMIN"], [permission]);
|
|
1195
|
-
}
|
|
1196
1137
|
|
|
1197
1138
|
// src/internalHttpClient.ts
|
|
1198
|
-
var
|
|
1139
|
+
var import_fs3 = __toESM(require("fs"), 1);
|
|
1199
1140
|
var InternalHttpError = class extends Error {
|
|
1200
1141
|
status;
|
|
1201
1142
|
code;
|
|
@@ -1210,7 +1151,7 @@ var InternalHttpError = class extends Error {
|
|
|
1210
1151
|
function readSecretFile2(path) {
|
|
1211
1152
|
if (!path) return null;
|
|
1212
1153
|
try {
|
|
1213
|
-
const v =
|
|
1154
|
+
const v = import_fs3.default.readFileSync(path, "utf8").trim();
|
|
1214
1155
|
return v.length ? v : null;
|
|
1215
1156
|
} catch {
|
|
1216
1157
|
return null;
|
|
@@ -1894,14 +1835,9 @@ function isUid(value) {
|
|
|
1894
1835
|
allowSysAdminOrPermissionsAll,
|
|
1895
1836
|
allowSysAdminOrRoles,
|
|
1896
1837
|
allowSysAdminOrRolesOrAnyPermission,
|
|
1897
|
-
authCustomerAllowFirebase,
|
|
1898
|
-
authCustomerRequired,
|
|
1899
|
-
authEmployeeAllowFirebase,
|
|
1900
|
-
authEmployeeRequired,
|
|
1901
1838
|
buildInternalHeaders,
|
|
1902
1839
|
closeCache,
|
|
1903
1840
|
createAuthMiddleware,
|
|
1904
|
-
createAuthMiddlewareLegacySimple,
|
|
1905
1841
|
createBulkRefsClient,
|
|
1906
1842
|
createFisClient,
|
|
1907
1843
|
createHttpClient,
|
|
@@ -1912,6 +1848,9 @@ function isUid(value) {
|
|
|
1912
1848
|
createPayClient,
|
|
1913
1849
|
createPlatformClient,
|
|
1914
1850
|
createResClient,
|
|
1851
|
+
extractCustomerUid,
|
|
1852
|
+
extractEmployeeUid,
|
|
1853
|
+
getBearerToken,
|
|
1915
1854
|
getOrSet,
|
|
1916
1855
|
getRequestContextFromHeaders,
|
|
1917
1856
|
getTwoLevelCache,
|
|
@@ -1920,6 +1859,7 @@ function isUid(value) {
|
|
|
1920
1859
|
mapAxiosToUpstreamError,
|
|
1921
1860
|
newUid,
|
|
1922
1861
|
newUidV4,
|
|
1862
|
+
normalizeUid,
|
|
1923
1863
|
parseHeaders,
|
|
1924
1864
|
readRs256PublicKey,
|
|
1925
1865
|
readServiceEnv,
|