@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/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.auth) {
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(process.env.AUTH_JWT_PUBLIC_KEY || process.env.AUTH_RSA_PUBLIC_KEY || "").replace(/\\n/g, "\n").trim();
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("Missing RS256 public key (JWT_PUBLIC_KEY_PATH / AUTH_JWT_PUBLIC_KEY / AUTH_RSA_PUBLIC_KEY)");
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 getBearerToken(req) {
815
- const auth = String(req.headers?.authorization || "");
816
- if (!auth.startsWith("Bearer ")) return null;
817
- const token = auth.slice(7).trim();
818
- return token.length ? token : null;
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 { subject, allowFirebaseIdToken = false, requireSubject = true, hydrate } = opts;
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 res.status(401).json({
830
- ok: false,
831
- code: "AUTH_MISSING_TOKEN",
832
- message: "Missing Authorization Bearer token"
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
- const hydrated = await hydrate({ decoded, req, subject, company_uid, branch_uid });
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 res.status(401).json({
859
- ok: false,
860
- code: "AUTH_EMPLOYEE_NOT_FOUND",
861
- message: "Employee not resolved by hydrator"
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 res.status(401).json({
866
- ok: false,
867
- code: "AUTH_CUSTOMER_NOT_FOUND",
868
- message: "Customer not resolved by hydrator"
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 res.status(401).json({
877
- ok: false,
878
- code: "AUTH_INVALID_TOKEN",
879
- message: "Invalid or expired token"
880
- });
1098
+ return sendAuthError(
1099
+ res,
1100
+ "AUTH_INVALID_TOKEN",
1101
+ "Invalid or expired token"
1102
+ );
881
1103
  }
882
1104
  try {
883
- const { default: admin2 } = await import("firebase-admin");
884
- const firebaseDecoded = await admin2.auth().verifyIdToken(token);
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 res.status(401).json({
887
- ok: false,
888
- code: "AUTH_EMAIL_NOT_VERIFIED",
889
- message: "Email not verified"
890
- });
1108
+ return sendAuthError(
1109
+ res,
1110
+ "AUTH_EMAIL_NOT_VERIFIED",
1111
+ "Email not verified"
1112
+ );
891
1113
  }
892
- req.auth = {
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 res.status(401).json({
906
- ok: false,
907
- code: "AUTH_INVALID_TOKEN",
908
- message: "Invalid or expired token"
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 import_fs4 = __toESM(require("fs"), 1);
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 = import_fs4.default.readFileSync(path, "utf8").trim();
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,