@innvoid/getmarket-sdk 0.2.8 → 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.
@@ -168,6 +168,9 @@ function internalAuth(req, res, next) {
168
168
  function getAuth(req) {
169
169
  return req.auth ?? {};
170
170
  }
171
+ function hasAuthContext(req) {
172
+ return !!req.auth;
173
+ }
171
174
  function normalizeCode(v) {
172
175
  if (!v) return null;
173
176
  if (typeof v === "string") return v;
@@ -192,7 +195,7 @@ function permsSet(list) {
192
195
  }
193
196
  function requireAuthContext() {
194
197
  return (req, res, next) => {
195
- if (!req.auth) {
198
+ if (!hasAuthContext(req)) {
196
199
  return sendError(req, res, 401, "UNAUTHORIZED", "Missing auth context");
197
200
  }
198
201
  return next();
@@ -206,6 +209,9 @@ function requirePermissions(perms, options) {
206
209
  const sysAdminBypass = options?.sysAdminBypass !== false;
207
210
  const sysAdminRole = options?.sysAdminRole || "SYS_ADMIN";
208
211
  return (req, res, next) => {
212
+ if (!hasAuthContext(req)) {
213
+ return sendError(req, res, 401, "UNAUTHORIZED", "Missing auth context");
214
+ }
209
215
  const auth = getAuth(req);
210
216
  if (sysAdminBypass && isSysAdmin(auth, sysAdminRole)) return next();
211
217
  const allow = permsSet(auth.permissions);
@@ -231,6 +237,9 @@ function requireAnyPermission(perms, options) {
231
237
  const sysAdminBypass = options?.sysAdminBypass !== false;
232
238
  const sysAdminRole = options?.sysAdminRole || "SYS_ADMIN";
233
239
  return (req, res, next) => {
240
+ if (!hasAuthContext(req)) {
241
+ return sendError(req, res, 401, "UNAUTHORIZED", "Missing auth context");
242
+ }
234
243
  const auth = getAuth(req);
235
244
  if (sysAdminBypass && isSysAdmin(auth, sysAdminRole)) return next();
236
245
  const allow = permsSet(auth.permissions);
@@ -256,6 +265,9 @@ function requireRoles(roles, options) {
256
265
  const sysAdminBypass = options?.sysAdminBypass !== false;
257
266
  const sysAdminRole = options?.sysAdminRole || "SYS_ADMIN";
258
267
  return (req, res, next) => {
268
+ if (!hasAuthContext(req)) {
269
+ return sendError(req, res, 401, "UNAUTHORIZED", "Missing auth context");
270
+ }
259
271
  const auth = getAuth(req);
260
272
  if (sysAdminBypass && isSysAdmin(auth, sysAdminRole)) return next();
261
273
  const have = rolesSet(auth);
@@ -272,6 +284,9 @@ function requireRolesOrAnyPermission(roles, perms, options) {
272
284
  const sysAdminBypass = options?.sysAdminBypass !== false;
273
285
  const sysAdminRole = options?.sysAdminRole || "SYS_ADMIN";
274
286
  return (req, res, next) => {
287
+ if (!hasAuthContext(req)) {
288
+ return sendError(req, res, 401, "UNAUTHORIZED", "Missing auth context");
289
+ }
275
290
  const auth = getAuth(req);
276
291
  if (sysAdminBypass && isSysAdmin(auth, sysAdminRole)) return next();
277
292
  const haveRoles = rolesSet(auth);
@@ -297,296 +312,6 @@ function requireRolesOrAnyPermission(roles, perms, options) {
297
312
  };
298
313
  }
299
314
 
300
- // src/auth/jwt.ts
301
- var import_fs2 = __toESM(require("fs"), 1);
302
- var import_jsonwebtoken = __toESM(require("jsonwebtoken"), 1);
303
- function readFileIfExists(path) {
304
- if (!path) return null;
305
- try {
306
- const v = import_fs2.default.readFileSync(path, "utf8").trim();
307
- return v.length ? v : null;
308
- } catch {
309
- return null;
310
- }
311
- }
312
- function getBearerToken(req) {
313
- const auth = String(req?.headers?.authorization || "");
314
- if (!auth.startsWith("Bearer ")) return null;
315
- const token = auth.slice(7).trim();
316
- return token.length ? token : null;
317
- }
318
- function normalizeUid(v) {
319
- const s = String(v ?? "").trim();
320
- return s.length ? s : null;
321
- }
322
- function readRs256PublicKey() {
323
- const fromFile = readFileIfExists(process.env.JWT_PUBLIC_KEY_PATH);
324
- if (fromFile) return fromFile;
325
- const fromEnv = String(
326
- process.env.AUTH_JWT_PUBLIC_KEY || process.env.AUTH_RSA_PUBLIC_KEY || ""
327
- ).replace(/\\n/g, "\n").trim();
328
- if (fromEnv) return fromEnv;
329
- throw new Error(
330
- "Missing RS256 public key (JWT_PUBLIC_KEY_PATH / AUTH_JWT_PUBLIC_KEY / AUTH_RSA_PUBLIC_KEY)"
331
- );
332
- }
333
- function verifyBackendJwtRS256(raw) {
334
- const publicKey = readRs256PublicKey();
335
- const audience = process.env.JWT_AUDIENCE || process.env.AUTH_JWT_AUDIENCE || "getmarket.api";
336
- const issuer = process.env.JWT_ISSUER || process.env.AUTH_JWT_ISSUER || "getmarket-auth";
337
- return import_jsonwebtoken.default.verify(raw, publicKey, {
338
- algorithms: ["RS256"],
339
- audience,
340
- issuer
341
- });
342
- }
343
- function extractEmployeeUid(decoded) {
344
- const direct = normalizeUid(decoded?.employee_uid) ?? normalizeUid(decoded?.employee?.uid);
345
- if (direct) return direct;
346
- const sub = normalizeUid(decoded?.sub);
347
- if (!sub) return null;
348
- const match = /^emp:(.+)$/i.exec(sub);
349
- return match?.[1] ? normalizeUid(match[1]) : null;
350
- }
351
- function extractCustomerUid(decoded) {
352
- const direct = normalizeUid(decoded?.customer_uid) ?? normalizeUid(decoded?.customer?.uid);
353
- if (direct) return direct;
354
- const sub = normalizeUid(decoded?.sub);
355
- if (!sub) return null;
356
- const match = /^cus:(.+)$/i.exec(sub);
357
- return match?.[1] ? normalizeUid(match[1]) : null;
358
- }
359
-
360
- // src/auth/middleware.ts
361
- function createAuthMiddleware(opts) {
362
- const {
363
- subject,
364
- allowFirebaseIdToken = false,
365
- requireSubject = true,
366
- hydrate
367
- } = opts;
368
- return async (req, res, next) => {
369
- const token = getBearerToken(req);
370
- if (!token) {
371
- return res.status(401).json({
372
- ok: false,
373
- code: "AUTH_MISSING_TOKEN",
374
- message: "Missing Authorization Bearer token"
375
- });
376
- }
377
- const headerCtx = req.context || {};
378
- const company_uid = normalizeUid(headerCtx.company_uid);
379
- const branch_uid = normalizeUid(headerCtx.branch_uid);
380
- try {
381
- const decoded = verifyBackendJwtRS256(token);
382
- const baseCtx = {
383
- tokenType: "backend",
384
- subject,
385
- company_uid: company_uid ?? void 0,
386
- branch_uid: branch_uid ?? void 0,
387
- roles: Array.isArray(decoded?.roles) ? decoded.roles : [],
388
- permissions: Array.isArray(decoded?.permissions) ? decoded.permissions : [],
389
- denied_permissions: Array.isArray(decoded?.denied_permissions) ? decoded.denied_permissions : [],
390
- session: {
391
- jti: decoded?.jti,
392
- device_id: decoded?.device_id,
393
- expires_at: decoded?.exp
394
- }
395
- };
396
- if (subject === "employee") {
397
- baseCtx.employee_uid = extractEmployeeUid(decoded) ?? void 0;
398
- } else {
399
- baseCtx.customer_uid = extractCustomerUid(decoded) ?? void 0;
400
- }
401
- const hydrated = await hydrate({
402
- decoded,
403
- req,
404
- subject,
405
- company_uid,
406
- branch_uid
407
- });
408
- Object.assign(baseCtx, hydrated);
409
- if (subject === "employee" && !baseCtx.employee_uid) {
410
- return res.status(401).json({
411
- ok: false,
412
- code: "AUTH_EMPLOYEE_UID_MISSING",
413
- message: "employee_uid missing in token/context (expected employee_uid or sub=emp:<uid>)"
414
- });
415
- }
416
- if (subject === "customer" && !baseCtx.customer_uid) {
417
- return res.status(401).json({
418
- ok: false,
419
- code: "AUTH_CUSTOMER_UID_MISSING",
420
- message: "customer_uid missing in token/context (expected customer_uid or sub=cus:<uid>)"
421
- });
422
- }
423
- if (requireSubject) {
424
- if (subject === "employee" && !baseCtx.employee) {
425
- return res.status(401).json({
426
- ok: false,
427
- code: "AUTH_EMPLOYEE_NOT_FOUND",
428
- message: "Employee not resolved by hydrator"
429
- });
430
- }
431
- if (subject === "customer" && !baseCtx.customer) {
432
- return res.status(401).json({
433
- ok: false,
434
- code: "AUTH_CUSTOMER_NOT_FOUND",
435
- message: "Customer not resolved by hydrator"
436
- });
437
- }
438
- }
439
- req.auth = baseCtx;
440
- return next();
441
- } catch {
442
- if (!allowFirebaseIdToken) {
443
- return res.status(401).json({
444
- ok: false,
445
- code: "AUTH_INVALID_TOKEN",
446
- message: "Invalid or expired token"
447
- });
448
- }
449
- try {
450
- const { default: admin } = await import("firebase-admin");
451
- const firebaseDecoded = await admin.auth().verifyIdToken(token);
452
- if (firebaseDecoded.email && firebaseDecoded.email_verified === false) {
453
- return res.status(401).json({
454
- ok: false,
455
- code: "AUTH_EMAIL_NOT_VERIFIED",
456
- message: "Email not verified"
457
- });
458
- }
459
- req.auth = {
460
- tokenType: "backend",
461
- subject,
462
- firebase: firebaseDecoded,
463
- company_uid: company_uid ?? void 0,
464
- branch_uid: branch_uid ?? void 0,
465
- companies: [],
466
- roles: [],
467
- permissions: [],
468
- denied_permissions: []
469
- };
470
- return next();
471
- } catch {
472
- return res.status(401).json({
473
- ok: false,
474
- code: "AUTH_INVALID_TOKEN",
475
- message: "Invalid or expired token"
476
- });
477
- }
478
- }
479
- };
480
- }
481
-
482
- // src/auth/authentication.ts
483
- function deriveCompanyBranch(decoded, companyUid, branchUid) {
484
- const companiesFromToken = Array.isArray(decoded?.companies) ? decoded.companies : [];
485
- const company = decoded?.company ?? (companyUid ? companiesFromToken.find((c) => c?.uid === companyUid) : null) ?? null;
486
- const branch = decoded?.branch ?? (branchUid && company?.branches ? (company.branches || []).find((b) => b?.uid === branchUid) : null) ?? null;
487
- return {
488
- companiesFromToken,
489
- company,
490
- branch
491
- };
492
- }
493
- var authEmployeeRequired = createAuthMiddleware({
494
- subject: "employee",
495
- allowFirebaseIdToken: false,
496
- requireSubject: false,
497
- hydrate: async ({ decoded, company_uid, branch_uid }) => {
498
- const employee_uid = extractEmployeeUid(decoded) ?? normalizeUid(decoded?.employee?.uid);
499
- const { companiesFromToken, company, branch } = deriveCompanyBranch(
500
- decoded,
501
- company_uid,
502
- branch_uid
503
- );
504
- const employee = decoded?.employee && typeof decoded.employee === "object" ? decoded.employee : employee_uid ? { uid: employee_uid, email: decoded?.email ?? null } : void 0;
505
- return {
506
- employee_uid: employee_uid ?? void 0,
507
- employee,
508
- companies: companiesFromToken,
509
- company,
510
- branch,
511
- roles: Array.isArray(decoded?.roles) ? decoded.roles : [],
512
- permissions: Array.isArray(decoded?.permissions) ? decoded.permissions : [],
513
- denied_permissions: Array.isArray(decoded?.denied_permissions) ? decoded.denied_permissions : []
514
- };
515
- }
516
- });
517
- var authCustomerRequired = createAuthMiddleware({
518
- subject: "customer",
519
- allowFirebaseIdToken: false,
520
- requireSubject: false,
521
- hydrate: async ({ decoded, company_uid, branch_uid }) => {
522
- const customer_uid = extractCustomerUid(decoded) ?? normalizeUid(decoded?.customer?.uid);
523
- const { companiesFromToken, company, branch } = deriveCompanyBranch(
524
- decoded,
525
- company_uid,
526
- branch_uid
527
- );
528
- const customer = decoded?.customer && typeof decoded.customer === "object" ? decoded.customer : customer_uid ? { uid: customer_uid } : void 0;
529
- return {
530
- customer_uid: customer_uid ?? void 0,
531
- customer,
532
- companies: companiesFromToken,
533
- company,
534
- branch,
535
- roles: Array.isArray(decoded?.roles) ? decoded.roles : [],
536
- permissions: Array.isArray(decoded?.permissions) ? decoded.permissions : [],
537
- denied_permissions: Array.isArray(decoded?.denied_permissions) ? decoded.denied_permissions : []
538
- };
539
- }
540
- });
541
- var authEmployeeAllowFirebase = createAuthMiddleware({
542
- subject: "employee",
543
- allowFirebaseIdToken: true,
544
- requireSubject: false,
545
- hydrate: async ({ decoded, company_uid, branch_uid }) => {
546
- const employee_uid = extractEmployeeUid(decoded) ?? normalizeUid(decoded?.employee?.uid);
547
- const { companiesFromToken, company, branch } = deriveCompanyBranch(
548
- decoded,
549
- company_uid,
550
- branch_uid
551
- );
552
- const employee = decoded?.employee && typeof decoded.employee === "object" ? decoded.employee : employee_uid ? { uid: employee_uid, email: decoded?.email ?? null } : void 0;
553
- return {
554
- employee_uid: employee_uid ?? void 0,
555
- employee,
556
- companies: companiesFromToken,
557
- company,
558
- branch,
559
- roles: Array.isArray(decoded?.roles) ? decoded.roles : [],
560
- permissions: Array.isArray(decoded?.permissions) ? decoded.permissions : [],
561
- denied_permissions: Array.isArray(decoded?.denied_permissions) ? decoded.denied_permissions : []
562
- };
563
- }
564
- });
565
- var authCustomerAllowFirebase = createAuthMiddleware({
566
- subject: "customer",
567
- allowFirebaseIdToken: true,
568
- requireSubject: false,
569
- hydrate: async ({ decoded, company_uid, branch_uid }) => {
570
- const customer_uid = extractCustomerUid(decoded) ?? normalizeUid(decoded?.customer?.uid);
571
- const { companiesFromToken, company, branch } = deriveCompanyBranch(
572
- decoded,
573
- company_uid,
574
- branch_uid
575
- );
576
- const customer = decoded?.customer && typeof decoded.customer === "object" ? decoded.customer : customer_uid ? { uid: customer_uid } : void 0;
577
- return {
578
- customer_uid: customer_uid ?? void 0,
579
- customer,
580
- companies: companiesFromToken,
581
- company,
582
- branch,
583
- roles: Array.isArray(decoded?.roles) ? decoded.roles : [],
584
- permissions: Array.isArray(decoded?.permissions) ? decoded.permissions : [],
585
- denied_permissions: Array.isArray(decoded?.denied_permissions) ? decoded.denied_permissions : []
586
- };
587
- }
588
- });
589
-
590
315
  // src/middlewares/guards.ts
591
316
  function normalizeRole(r) {
592
317
  if (!r) return null;
@@ -598,100 +323,134 @@ function normalizePerm(p) {
598
323
  if (typeof p === "string") return p;
599
324
  return p.code || p.name || null;
600
325
  }
601
- function isSysAdmin2(roles) {
602
- if (!Array.isArray(roles)) return false;
603
- return roles.some((r) => normalizeRole(r) === "SYS_ADMIN");
604
- }
605
326
  function getAuth2(req) {
606
327
  return req.auth ?? {};
607
328
  }
329
+ function roleSet(auth) {
330
+ return new Set(
331
+ (auth.roles ?? []).map(normalizeRole).filter(Boolean)
332
+ );
333
+ }
608
334
  function permissionSets(auth) {
609
- const allow = new Set((auth.permissions ?? []).map(normalizePerm).filter(Boolean));
610
- const deny = new Set((auth.denied_permissions ?? []).map(normalizePerm).filter(Boolean));
335
+ const allow = new Set(
336
+ (auth.permissions ?? []).map(normalizePerm).filter(Boolean)
337
+ );
338
+ const deny = new Set(
339
+ (auth.denied_permissions ?? []).map(normalizePerm).filter(Boolean)
340
+ );
611
341
  return { allow, deny };
612
342
  }
613
- function roleSet(auth) {
614
- return new Set((auth.roles ?? []).map(normalizeRole).filter(Boolean));
343
+ function normalizeHandlers(auth) {
344
+ if (!auth) return [];
345
+ return Array.isArray(auth) ? auth : [auth];
346
+ }
347
+ function buildBaseChain(options) {
348
+ const chain = [];
349
+ if (options?.includeParseHeaders !== false) {
350
+ chain.push(parseHeaders);
351
+ }
352
+ chain.push(...normalizeHandlers(options?.auth));
353
+ return chain;
354
+ }
355
+ function hasSysAdmin(auth, options) {
356
+ const sysAdminBypass = options?.sysAdminBypass !== false;
357
+ if (!sysAdminBypass) return false;
358
+ const sysAdminRole = options?.sysAdminRole || "SYS_ADMIN";
359
+ return roleSet(auth).has(sysAdminRole);
615
360
  }
616
- function allowSysAdminOrAnyPermission(...perms) {
617
- const required = (perms ?? []).filter(Boolean);
361
+ function allowSysAdminOrAnyPermission(perms, options) {
362
+ const required = (Array.isArray(perms) ? perms : [perms]).filter(Boolean);
618
363
  return [
619
- parseHeaders,
620
- authEmployeeRequired,
364
+ ...buildBaseChain(options),
621
365
  (req, res, next) => {
622
366
  const auth = getAuth2(req);
623
- if (isSysAdmin2(auth.roles)) return next();
367
+ if (hasSysAdmin(auth, options)) return next();
624
368
  const { allow, deny } = permissionSets(auth);
625
369
  for (const p of required) {
626
370
  if (deny.has(p)) {
627
- return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, { denied: p });
371
+ return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, {
372
+ denied: p
373
+ });
628
374
  }
629
375
  }
630
376
  const ok = required.some((p) => allow.has(p));
631
377
  if (!ok) {
632
- return sendError(req, res, 403, "FORBIDDEN", "Missing permissions (ANY)", { required });
378
+ return sendError(req, res, 403, "FORBIDDEN", "Missing permissions (ANY)", {
379
+ required,
380
+ mode: "ANY"
381
+ });
633
382
  }
634
383
  return next();
635
384
  }
636
385
  ];
637
386
  }
638
- function allowSysAdminOrPermissionsAll(...perms) {
639
- const required = (perms ?? []).filter(Boolean);
387
+ function allowSysAdminOrPermissionsAll(perms, options) {
388
+ const required = (Array.isArray(perms) ? perms : [perms]).filter(Boolean);
640
389
  return [
641
- parseHeaders,
642
- authEmployeeRequired,
390
+ ...buildBaseChain(options),
643
391
  (req, res, next) => {
644
392
  const auth = getAuth2(req);
645
- if (isSysAdmin2(auth.roles)) return next();
393
+ if (hasSysAdmin(auth, options)) return next();
646
394
  const { allow, deny } = permissionSets(auth);
647
395
  for (const p of required) {
648
396
  if (deny.has(p)) {
649
- return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, { denied: p });
397
+ return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, {
398
+ denied: p
399
+ });
650
400
  }
651
401
  }
652
402
  const missing = required.filter((p) => !allow.has(p));
653
403
  if (missing.length) {
654
- return sendError(req, res, 403, "FORBIDDEN", "Missing permissions (ALL)", { required, missing });
404
+ return sendError(req, res, 403, "FORBIDDEN", "Missing permissions (ALL)", {
405
+ required,
406
+ missing,
407
+ mode: "ALL"
408
+ });
655
409
  }
656
410
  return next();
657
411
  }
658
412
  ];
659
413
  }
660
- function allowSysAdminOrRoles(...roles) {
661
- const required = (roles ?? []).filter(Boolean);
414
+ function allowSysAdminOrRoles(roles, options) {
415
+ const required = (Array.isArray(roles) ? roles : [roles]).filter(Boolean);
662
416
  return [
663
- parseHeaders,
664
- authEmployeeRequired,
417
+ ...buildBaseChain(options),
665
418
  (req, res, next) => {
666
419
  const auth = getAuth2(req);
667
- if (isSysAdmin2(auth.roles)) return next();
420
+ if (hasSysAdmin(auth, options)) return next();
668
421
  const have = roleSet(auth);
669
422
  const ok = required.some((r) => have.has(r));
670
423
  if (!ok) {
671
- return sendError(req, res, 403, "FORBIDDEN", "Role not allowed", { required });
424
+ return sendError(req, res, 403, "FORBIDDEN", "Role not allowed", {
425
+ required,
426
+ mode: "ANY"
427
+ });
672
428
  }
673
429
  return next();
674
430
  }
675
431
  ];
676
432
  }
677
- function allowSysAdminOrRolesOrAnyPermission(roles, permissions) {
433
+ function allowSysAdminOrRolesOrAnyPermission(roles, permissions, options) {
678
434
  const requiredRoles = (Array.isArray(roles) ? roles : [roles]).filter(Boolean);
679
435
  const requiredPerms = (Array.isArray(permissions) ? permissions : [permissions]).filter(Boolean);
680
436
  return [
681
- parseHeaders,
682
- authEmployeeRequired,
437
+ ...buildBaseChain(options),
683
438
  (req, res, next) => {
684
439
  const auth = getAuth2(req);
685
- if (isSysAdmin2(auth.roles)) return next();
440
+ if (hasSysAdmin(auth, options)) return next();
686
441
  const { allow, deny } = permissionSets(auth);
442
+ const haveRoles = roleSet(auth);
687
443
  for (const p of requiredPerms) {
688
444
  if (deny.has(p)) {
689
- return sendError(req, res, 403, "FORBIDDEN", `Denied: ${p}`, { permission: p });
445
+ return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, {
446
+ denied: p
447
+ });
690
448
  }
691
449
  }
692
- const haveRoles = roleSet(auth);
693
- if (requiredRoles.some((r) => haveRoles.has(r))) return next();
694
- if (requiredPerms.some((p) => allow.has(p))) return next();
450
+ const okRole = requiredRoles.some((r) => haveRoles.has(r));
451
+ if (okRole) return next();
452
+ const okPerm = requiredPerms.some((p) => allow.has(p));
453
+ if (okPerm) return next();
695
454
  return sendError(req, res, 403, "FORBIDDEN", "Permission denied", {
696
455
  roles: requiredRoles,
697
456
  permissions: requiredPerms,
@@ -700,8 +459,8 @@ function allowSysAdminOrRolesOrAnyPermission(roles, permissions) {
700
459
  }
701
460
  ];
702
461
  }
703
- function allowAuthAdminOrPerm(permission) {
704
- return allowSysAdminOrRolesOrAnyPermission(["AUTH_ADMIN"], [permission]);
462
+ function allowAuthAdminOrPerm(permission, options) {
463
+ return allowSysAdminOrRolesOrAnyPermission(["AUTH_ADMIN"], [permission], options);
705
464
  }
706
465
  // Annotate the CommonJS export names for ESM import in node:
707
466
  0 && (module.exports = {