@innvoid/getmarket-sdk 0.1.10 → 0.1.12
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-6E3X3D6Q.js → chunk-SLB6QUUN.js} +50 -64
- package/dist/chunk-SLB6QUUN.js.map +1 -0
- package/dist/index.cjs +49 -63
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/middlewares/index.cjs +49 -63
- package/dist/middlewares/index.cjs.map +1 -1
- package/dist/middlewares/index.d.cts +1 -5
- package/dist/middlewares/index.d.ts +1 -5
- package/dist/middlewares/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-6E3X3D6Q.js.map +0 -1
|
@@ -361,9 +361,7 @@ function readPublicKey() {
|
|
|
361
361
|
}
|
|
362
362
|
const envKey = publicKeyEnv.replace(/\\n/g, "\n").trim();
|
|
363
363
|
if (envKey) return envKey;
|
|
364
|
-
throw new Error(
|
|
365
|
-
"Missing RS256 public key (JWT_PUBLIC_KEY_PATH / AUTH_JWT_PUBLIC_KEY / AUTH_RSA_PUBLIC_KEY)"
|
|
366
|
-
);
|
|
364
|
+
throw new Error("Missing RS256 public key (JWT_PUBLIC_KEY_PATH / AUTH_JWT_PUBLIC_KEY / AUTH_RSA_PUBLIC_KEY)");
|
|
367
365
|
}
|
|
368
366
|
function verifyBackendJwtRS2562(raw) {
|
|
369
367
|
const publicKey = readPublicKey();
|
|
@@ -385,6 +383,22 @@ function deriveCompanyBranch(decoded, companyUid, branchUid) {
|
|
|
385
383
|
const branch = decoded?.branch ?? (branchUid && company?.branches ? (company.branches || []).find((b) => b?.uid === branchUid) : null) ?? null;
|
|
386
384
|
return { companiesFromToken, company, branch };
|
|
387
385
|
}
|
|
386
|
+
function extractEmployeeUid(decoded) {
|
|
387
|
+
const direct = normalizeUid2(decoded?.employee_uid);
|
|
388
|
+
if (direct) return direct;
|
|
389
|
+
const sub = normalizeUid2(decoded?.sub);
|
|
390
|
+
if (!sub) return null;
|
|
391
|
+
const m = /^emp:(.+)$/i.exec(sub);
|
|
392
|
+
return m?.[1] ? normalizeUid2(m[1]) : null;
|
|
393
|
+
}
|
|
394
|
+
function extractCustomerUid(decoded) {
|
|
395
|
+
const direct = normalizeUid2(decoded?.customer_uid);
|
|
396
|
+
if (direct) return direct;
|
|
397
|
+
const sub = normalizeUid2(decoded?.sub);
|
|
398
|
+
if (!sub) return null;
|
|
399
|
+
const m = /^cus:(.+)$/i.exec(sub);
|
|
400
|
+
return m?.[1] ? normalizeUid2(m[1]) : null;
|
|
401
|
+
}
|
|
388
402
|
function createAuthMiddleware2(opts) {
|
|
389
403
|
const { subject, allowFirebaseIdToken = false } = opts;
|
|
390
404
|
return async (req, res, next) => {
|
|
@@ -420,25 +434,29 @@ function createAuthMiddleware2(opts) {
|
|
|
420
434
|
}
|
|
421
435
|
};
|
|
422
436
|
if (subject === "employee") {
|
|
423
|
-
const
|
|
424
|
-
if (!
|
|
437
|
+
const employee_uid = extractEmployeeUid(decoded);
|
|
438
|
+
if (!employee_uid) {
|
|
425
439
|
return res.status(401).json({
|
|
426
440
|
ok: false,
|
|
427
|
-
code: "
|
|
428
|
-
message: "
|
|
441
|
+
code: "AUTH_EMPLOYEE_UID_MISSING",
|
|
442
|
+
message: "employee_uid missing in token (expected employee_uid or sub=emp:<uid>)"
|
|
429
443
|
});
|
|
430
444
|
}
|
|
431
|
-
ctx.
|
|
445
|
+
ctx.employee_uid = employee_uid;
|
|
446
|
+
const embedded = decoded?.employee ?? decoded?.user ?? null;
|
|
447
|
+
ctx.employee = embedded && typeof embedded === "object" ? embedded : { uid: employee_uid, email: decoded?.email ?? null };
|
|
432
448
|
} else {
|
|
433
|
-
const
|
|
434
|
-
if (!
|
|
449
|
+
const customer_uid = extractCustomerUid(decoded);
|
|
450
|
+
if (!customer_uid) {
|
|
435
451
|
return res.status(401).json({
|
|
436
452
|
ok: false,
|
|
437
|
-
code: "
|
|
438
|
-
message: "
|
|
453
|
+
code: "AUTH_CUSTOMER_UID_MISSING",
|
|
454
|
+
message: "customer_uid missing in token (expected customer_uid or sub=cus:<uid>)"
|
|
439
455
|
});
|
|
440
456
|
}
|
|
441
|
-
ctx.
|
|
457
|
+
ctx.customer_uid = customer_uid;
|
|
458
|
+
const embedded = decoded?.customer ?? null;
|
|
459
|
+
ctx.customer = embedded && typeof embedded === "object" ? embedded : { uid: customer_uid };
|
|
442
460
|
}
|
|
443
461
|
req.auth = ctx;
|
|
444
462
|
return next();
|
|
@@ -508,14 +526,13 @@ function getAuth2(req) {
|
|
|
508
526
|
return req.auth ?? {};
|
|
509
527
|
}
|
|
510
528
|
function permissionSets(auth) {
|
|
511
|
-
const allow = new Set(
|
|
512
|
-
|
|
513
|
-
);
|
|
514
|
-
const deny = new Set(
|
|
515
|
-
(auth.denied_permissions ?? []).map(normalizePerm).filter(Boolean)
|
|
516
|
-
);
|
|
529
|
+
const allow = new Set((auth.permissions ?? []).map(normalizePerm).filter(Boolean));
|
|
530
|
+
const deny = new Set((auth.denied_permissions ?? []).map(normalizePerm).filter(Boolean));
|
|
517
531
|
return { allow, deny };
|
|
518
532
|
}
|
|
533
|
+
function roleSet(auth) {
|
|
534
|
+
return new Set((auth.roles ?? []).map(normalizeRole).filter(Boolean));
|
|
535
|
+
}
|
|
519
536
|
function allowSysAdminOrAnyPermission(...perms) {
|
|
520
537
|
const required = (perms ?? []).filter(Boolean);
|
|
521
538
|
return [
|
|
@@ -527,16 +544,12 @@ function allowSysAdminOrAnyPermission(...perms) {
|
|
|
527
544
|
const { allow, deny } = permissionSets(auth);
|
|
528
545
|
for (const p of required) {
|
|
529
546
|
if (deny.has(p)) {
|
|
530
|
-
return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, {
|
|
531
|
-
denied: p
|
|
532
|
-
});
|
|
547
|
+
return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, { denied: p });
|
|
533
548
|
}
|
|
534
549
|
}
|
|
535
550
|
const ok = required.some((p) => allow.has(p));
|
|
536
551
|
if (!ok) {
|
|
537
|
-
return sendError(req, res, 403, "FORBIDDEN", "Missing permissions (ANY)", {
|
|
538
|
-
required
|
|
539
|
-
});
|
|
552
|
+
return sendError(req, res, 403, "FORBIDDEN", "Missing permissions (ANY)", { required });
|
|
540
553
|
}
|
|
541
554
|
return next();
|
|
542
555
|
}
|
|
@@ -553,17 +566,12 @@ function allowSysAdminOrPermissionsAll(...perms) {
|
|
|
553
566
|
const { allow, deny } = permissionSets(auth);
|
|
554
567
|
for (const p of required) {
|
|
555
568
|
if (deny.has(p)) {
|
|
556
|
-
return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, {
|
|
557
|
-
denied: p
|
|
558
|
-
});
|
|
569
|
+
return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, { denied: p });
|
|
559
570
|
}
|
|
560
571
|
}
|
|
561
572
|
const missing = required.filter((p) => !allow.has(p));
|
|
562
573
|
if (missing.length) {
|
|
563
|
-
return sendError(req, res, 403, "FORBIDDEN", "Missing permissions (ALL)", {
|
|
564
|
-
required,
|
|
565
|
-
missing
|
|
566
|
-
});
|
|
574
|
+
return sendError(req, res, 403, "FORBIDDEN", "Missing permissions (ALL)", { required, missing });
|
|
567
575
|
}
|
|
568
576
|
return next();
|
|
569
577
|
}
|
|
@@ -577,55 +585,33 @@ function allowSysAdminOrRoles(...roles) {
|
|
|
577
585
|
(req, res, next) => {
|
|
578
586
|
const auth = getAuth2(req);
|
|
579
587
|
if (isSysAdmin2(auth.roles)) return next();
|
|
580
|
-
const have =
|
|
581
|
-
(auth.roles ?? []).map(normalizeRole).filter(Boolean)
|
|
582
|
-
);
|
|
588
|
+
const have = roleSet(auth);
|
|
583
589
|
const ok = required.some((r) => have.has(r));
|
|
584
590
|
if (!ok) {
|
|
585
|
-
return sendError(req, res, 403, "FORBIDDEN", "Role not allowed", {
|
|
586
|
-
required
|
|
587
|
-
});
|
|
591
|
+
return sendError(req, res, 403, "FORBIDDEN", "Role not allowed", { required });
|
|
588
592
|
}
|
|
589
593
|
return next();
|
|
590
594
|
}
|
|
591
595
|
];
|
|
592
596
|
}
|
|
593
|
-
|
|
594
|
-
// src/middlewares/accessControl.ts
|
|
595
|
-
function normalizeList(v) {
|
|
596
|
-
return Array.isArray(v) ? v : [v];
|
|
597
|
-
}
|
|
598
|
-
function roleCode(r) {
|
|
599
|
-
if (!r) return null;
|
|
600
|
-
return typeof r === "string" ? r : r.code || r.name || null;
|
|
601
|
-
}
|
|
602
|
-
function permCode(p) {
|
|
603
|
-
if (!p) return null;
|
|
604
|
-
return typeof p === "string" ? p : p.code || p.name || null;
|
|
605
|
-
}
|
|
606
|
-
function isSysAdmin3(roles) {
|
|
607
|
-
if (!Array.isArray(roles)) return false;
|
|
608
|
-
return roles.map(roleCode).filter(Boolean).includes("SYS_ADMIN");
|
|
609
|
-
}
|
|
610
597
|
function allowSysAdminOrRolesOrAnyPermission(roles, permissions) {
|
|
611
|
-
const requiredRoles =
|
|
612
|
-
const requiredPerms =
|
|
598
|
+
const requiredRoles = (Array.isArray(roles) ? roles : [roles]).filter(Boolean);
|
|
599
|
+
const requiredPerms = (Array.isArray(permissions) ? permissions : [permissions]).filter(Boolean);
|
|
613
600
|
return [
|
|
614
601
|
parseHeaders,
|
|
615
602
|
authEmployeeRequired,
|
|
616
603
|
(req, res, next) => {
|
|
617
|
-
const auth = req
|
|
618
|
-
if (
|
|
619
|
-
const deny =
|
|
604
|
+
const auth = getAuth2(req);
|
|
605
|
+
if (isSysAdmin2(auth.roles)) return next();
|
|
606
|
+
const { allow, deny } = permissionSets(auth);
|
|
620
607
|
for (const p of requiredPerms) {
|
|
621
608
|
if (deny.has(p)) {
|
|
622
609
|
return sendError(req, res, 403, "FORBIDDEN", `Denied: ${p}`, { permission: p });
|
|
623
610
|
}
|
|
624
611
|
}
|
|
625
|
-
const haveRoles =
|
|
612
|
+
const haveRoles = roleSet(auth);
|
|
626
613
|
if (requiredRoles.some((r) => haveRoles.has(r))) return next();
|
|
627
|
-
|
|
628
|
-
if (requiredPerms.some((p) => havePerms.has(p))) return next();
|
|
614
|
+
if (requiredPerms.some((p) => allow.has(p))) return next();
|
|
629
615
|
return sendError(req, res, 403, "FORBIDDEN", "Permission denied", {
|
|
630
616
|
roles: requiredRoles,
|
|
631
617
|
permissions: requiredPerms,
|
|
@@ -662,4 +648,4 @@ export {
|
|
|
662
648
|
allowSysAdminOrRolesOrAnyPermission,
|
|
663
649
|
allowAuthAdminOrPerm
|
|
664
650
|
};
|
|
665
|
-
//# sourceMappingURL=chunk-
|
|
651
|
+
//# sourceMappingURL=chunk-SLB6QUUN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/middlewares/parseHeaders.ts","../src/middlewares/internalAuth.ts","../src/middlewares/respond.ts","../src/middlewares/authorization.ts","../src/auth/jwt.ts","../src/auth/middleware.ts","../src/auth/authentication.ts","../src/middlewares/guards.ts"],"sourcesContent":["// sdk/src/middlewares/parseHeaders.ts\nimport type {Request, Response, NextFunction} from \"express\";\nimport {getRequestContextFromHeaders} from \"../headers\";\n\n/**\n * ✅ NO-LEGACY / ESTÁNDAR:\n * - Lee SOLO x-company y x-branch (UIDs planos)\n * - Setea req.context = { company_uid, branch_uid }\n * - NO toca req.auth (auth lo setea authentication/requireAuth)\n */\nexport default function parseHeaders(req: Request, _res: Response, next: NextFunction) {\n (req as any).context = getRequestContextFromHeaders(req.headers as any);\n next();\n}\n","import type {Request, Response, NextFunction} from \"express\";\nimport fs from \"fs\";\nimport crypto from \"crypto\";\nimport {sendError} from \"./respond\";\nimport {HEADER_INTERNAL_API_KEY} from \"../headers\";\n\nfunction readSecretFile(path?: string): string | null {\n if (!path) return null;\n try {\n const v = fs.readFileSync(path, \"utf8\").trim();\n return v.length ? v : null;\n } catch {\n return null;\n }\n}\n\nfunction splitKeys(v?: string | null): string[] {\n if (!v) return [];\n return v.split(\",\").map((s) => s.trim()).filter(Boolean);\n}\n\nfunction getExpectedKeys(): string[] {\n const fileKey = readSecretFile(process.env.INTERNAL_API_KEY_FILE);\n const envKey = (process.env.INTERNAL_API_KEY || \"\").trim();\n const raw = fileKey || envKey;\n return splitKeys(raw);\n}\n\nfunction extractToken(req: Request): string | null {\n const apiKey = (req.header(HEADER_INTERNAL_API_KEY) || \"\").trim();\n return apiKey || null;\n}\n\nfunction safeEquals(a: string, b: string): boolean {\n const aa = Buffer.from(a);\n const bb = Buffer.from(b);\n if (aa.length !== bb.length) return false;\n return crypto.timingSafeEqual(aa, bb);\n}\n\nexport default function internalAuth(req: Request, res: Response, next: NextFunction) {\n const token = extractToken(req);\n\n if (!token) {\n return sendError(req, res, 401, \"UNAUTHORIZED\", `Missing internal api key (${HEADER_INTERNAL_API_KEY})`);\n }\n\n const expectedKeys = getExpectedKeys();\n if (expectedKeys.length === 0) {\n return sendError(\n req,\n res,\n 500,\n \"MISCONFIGURED_INTERNAL_AUTH\",\n \"Internal api key not configured (INTERNAL_API_KEY or INTERNAL_API_KEY_FILE)\"\n );\n }\n\n const ok = expectedKeys.some((k) => safeEquals(token, k));\n if (!ok) {\n return sendError(req, res, 403, \"FORBIDDEN\", \"Invalid internal api key\");\n }\n\n return next();\n}\n","import type {Request, Response} from \"express\";\n\nexport function sendOk<T>(_req: Request, res: Response, data: T, statusCode = 200) {\n return res.status(statusCode).json({ok: true, data, requestId: res.locals?.requestId ?? null});\n}\n\nexport function sendError(\n _req: Request,\n res: Response,\n statusCode: number,\n code: string,\n message: string,\n details?: any\n) {\n return res.status(statusCode).json({\n ok: false,\n error: {code, message, ...(details !== undefined ? {details} : {})},\n requestId: res.locals?.requestId ?? null,\n });\n}\n","// packages/sdk/src/middlewares/authorization.ts\nimport type {Request, Response, NextFunction} from \"express\";\nimport {sendError} from \"./respond\";\n\ntype AuthRole = string | { code?: string; name?: string };\ntype AuthPermission = string | { code?: string; name?: string };\n\ntype AuthShape = {\n roles?: AuthRole[];\n permissions?: AuthPermission[];\n denied_permissions?: AuthPermission[];\n};\n\nfunction getAuth(req: Request): AuthShape {\n return ((req as any).auth ?? {}) as AuthShape;\n}\n\nfunction normalizeCode(v: any): string | null {\n if (!v) return null;\n if (typeof v === \"string\") return v;\n if (typeof v === \"object\") return v.code || v.name || null;\n return null;\n}\n\nfunction rolesSet(auth: AuthShape): Set<string> {\n const out = new Set<string>();\n for (const r of auth.roles || []) {\n const c = normalizeCode(r);\n if (c) out.add(c);\n }\n return out;\n}\n\nfunction permsSet(list?: AuthPermission[]): Set<string> {\n const out = new Set<string>();\n for (const p of list || []) {\n const c = normalizeCode(p);\n if (c) out.add(c);\n }\n return out;\n}\n\n/**\n * 401 si no existe req.auth (contexto auth).\n * Útil para proteger rutas donde SIEMPRE debe existir auth.\n */\nexport function requireAuthContext() {\n return (req: Request, res: Response, next: NextFunction) => {\n if (!(req as any).auth) {\n return sendError(req, res, 401, \"UNAUTHORIZED\", \"Missing auth context\");\n }\n return next();\n };\n}\n\n/**\n * Helper: SYS_ADMIN bypass (por defecto activo)\n */\nfunction isSysAdmin(auth: AuthShape, sysAdminRole: string) {\n const have = rolesSet(auth);\n return have.has(sysAdminRole);\n}\n\n/**\n * Requiere TODOS los permisos indicados.\n * Regla: denied_permissions siempre gana sobre permissions.\n *\n * options:\n * - sysAdminBypass: default true\n * - sysAdminRole: default \"SYS_ADMIN\"\n */\nexport function requirePermissions(\n perms: string[],\n options?: { sysAdminBypass?: boolean; sysAdminRole?: string }\n) {\n const sysAdminBypass = options?.sysAdminBypass !== false;\n const sysAdminRole = options?.sysAdminRole || \"SYS_ADMIN\";\n\n return (req: Request, res: Response, next: NextFunction) => {\n const auth = getAuth(req);\n\n if (sysAdminBypass && isSysAdmin(auth, sysAdminRole)) return next();\n\n const allow = permsSet(auth.permissions);\n const deny = permsSet(auth.denied_permissions);\n\n // deny gana siempre\n for (const p of perms) {\n if (deny.has(p)) {\n return sendError(req, res, 403, \"FORBIDDEN\", `Denied permission: ${p}`, {\n denied: p,\n });\n }\n }\n\n const missing = perms.filter((p) => !allow.has(p));\n if (missing.length) {\n return sendError(req, res, 403, \"FORBIDDEN\", \"Missing permissions\", {\n missing,\n mode: \"ALL\",\n });\n }\n\n return next();\n };\n}\n\n/**\n * Requiere AL MENOS 1 permiso de la lista (ANY/OR).\n * Regla: denied_permissions siempre gana.\n */\nexport function requireAnyPermission(\n perms: string[],\n options?: { sysAdminBypass?: boolean; sysAdminRole?: string }\n) {\n const sysAdminBypass = options?.sysAdminBypass !== false;\n const sysAdminRole = options?.sysAdminRole || \"SYS_ADMIN\";\n\n return (req: Request, res: Response, next: NextFunction) => {\n const auth = getAuth(req);\n\n if (sysAdminBypass && isSysAdmin(auth, sysAdminRole)) return next();\n\n const allow = permsSet(auth.permissions);\n const deny = permsSet(auth.denied_permissions);\n\n // deny gana siempre (si alguno requerido está denegado explícitamente)\n for (const p of perms) {\n if (deny.has(p)) {\n return sendError(req, res, 403, \"FORBIDDEN\", `Denied permission: ${p}`, {\n denied: p,\n });\n }\n }\n\n const ok = perms.some((p) => allow.has(p));\n if (!ok) {\n return sendError(req, res, 403, \"FORBIDDEN\", \"Permission denied\", {\n required: perms,\n mode: \"ANY\",\n });\n }\n\n return next();\n };\n}\n\n/**\n * Requiere al menos 1 rol (ANY/OR).\n * options:\n * - sysAdminBypass: default true\n * - sysAdminRole: default \"SYS_ADMIN\"\n */\nexport function requireRoles(\n roles: string[],\n options?: { sysAdminBypass?: boolean; sysAdminRole?: string }\n) {\n const sysAdminBypass = options?.sysAdminBypass !== false;\n const sysAdminRole = options?.sysAdminRole || \"SYS_ADMIN\";\n\n return (req: Request, res: Response, next: NextFunction) => {\n const auth = getAuth(req);\n\n // SYS_ADMIN bypass aplica también aquí\n if (sysAdminBypass && isSysAdmin(auth, sysAdminRole)) return next();\n\n const have = rolesSet(auth);\n if (!roles.some((r) => have.has(r))) {\n return sendError(req, res, 403, \"FORBIDDEN\", \"Role not allowed\", {\n required: roles,\n mode: \"ANY\",\n });\n }\n\n return next();\n };\n}\n\n/**\n * Requiere (roles ANY) OR (permissions ANY).\n * deny_permissions siempre gana sobre permissions.\n */\nexport function requireRolesOrAnyPermission(\n roles: string[],\n perms: string[],\n options?: { sysAdminBypass?: boolean; sysAdminRole?: string }\n) {\n const sysAdminBypass = options?.sysAdminBypass !== false;\n const sysAdminRole = options?.sysAdminRole || \"SYS_ADMIN\";\n\n return (req: Request, res: Response, next: NextFunction) => {\n const auth = getAuth(req);\n\n if (sysAdminBypass && isSysAdmin(auth, sysAdminRole)) return next();\n\n const haveRoles = rolesSet(auth);\n const allow = permsSet(auth.permissions);\n const deny = permsSet(auth.denied_permissions);\n\n // deny gana siempre (si cualquiera de los permisos evaluados está denegado explícitamente)\n for (const p of perms) {\n if (deny.has(p)) {\n return sendError(req, res, 403, \"FORBIDDEN\", `Denied permission: ${p}`, {\n denied: p,\n });\n }\n }\n\n const okRole = roles.some((r) => haveRoles.has(r));\n const okPerm = perms.some((p) => allow.has(p));\n\n if (!okRole && !okPerm) {\n return sendError(req, res, 403, \"FORBIDDEN\", \"Access denied\", {\n roles,\n permissions: perms,\n mode: \"ROLES_OR_PERMS_ANY\",\n });\n }\n\n return next();\n };\n}\n","import fs from \"fs\";\nimport jwt, {JwtPayload} from \"jsonwebtoken\";\n\nfunction readFileIfExists(path?: string): string | null {\n if (!path) return null;\n try {\n const v = fs.readFileSync(path, \"utf8\").trim();\n return v.length ? v : null;\n } catch {\n return null;\n }\n}\n\n/**\n * ✅ Keys viven en getmarket-stack:\n * - JWT_PUBLIC_KEY_PATH=/run/secrets/jwtRS256.key.pub (recomendado)\n * - fallback env AUTH_JWT_PUBLIC_KEY / AUTH_RSA_PUBLIC_KEY\n */\nexport function readRs256PublicKey(): string {\n const fromFile = readFileIfExists(process.env.JWT_PUBLIC_KEY_PATH);\n if (fromFile) return fromFile;\n\n const fromEnv = String(process.env.AUTH_JWT_PUBLIC_KEY || process.env.AUTH_RSA_PUBLIC_KEY || \"\")\n .replace(/\\\\n/g, \"\\n\")\n .trim();\n\n if (fromEnv) return fromEnv;\n\n throw new Error(\"Missing RS256 public key (JWT_PUBLIC_KEY_PATH / AUTH_JWT_PUBLIC_KEY / AUTH_RSA_PUBLIC_KEY)\");\n}\n\nexport function verifyBackendJwtRS256(raw: string): JwtPayload {\n const publicKey = readRs256PublicKey();\n\n const audience = process.env.JWT_AUDIENCE || process.env.AUTH_JWT_AUDIENCE || \"getmarket.api\";\n const issuer = process.env.JWT_ISSUER || process.env.AUTH_JWT_ISSUER || \"getmarket-auth\";\n\n // ✅ SOLO RS256\n return jwt.verify(raw, publicKey, {\n algorithms: [\"RS256\"],\n audience,\n issuer,\n }) as JwtPayload;\n}\n","import type {NextFunction, Response} from \"express\";\nimport {verifyBackendJwtRS256} from \"./jwt\";\nimport type {AuthContext, AuthMiddlewareOptions} from \"./types\";\n\nfunction getBearerToken(req: any): string | null {\n const auth = String(req.headers?.authorization || \"\");\n if (!auth.startsWith(\"Bearer \")) return null;\n const token = auth.slice(7).trim();\n return token.length ? token : null;\n}\n\nfunction normalizeUid(v: any): string | null {\n const s = String(v ?? \"\").trim();\n return s.length ? s : null;\n}\n\n/**\n * ✅ Middleware estándar:\n * - Solo Authorization: Bearer\n * - Solo RS256\n * - Cero legacy\n * - Hidrata vía hook (OBLIGATORIO)\n */\nexport function createAuthMiddleware(opts: AuthMiddlewareOptions) {\n const {subject, allowFirebaseIdToken = false, requireSubject = true, hydrate} = opts;\n\n return async (req: any, res: Response, next: NextFunction) => {\n const token = getBearerToken(req);\n if (!token) {\n return res.status(401).json({\n ok: false,\n code: \"AUTH_MISSING_TOKEN\",\n message: \"Missing Authorization Bearer token\",\n });\n }\n\n // Contexto desde parseHeaders (SDK) -> req.context\n const headerCtx = (req as any).context || {};\n const company_uid = normalizeUid(headerCtx.company_uid);\n const branch_uid = normalizeUid(headerCtx.branch_uid);\n\n // 1) RS256 backend JWT\n try {\n const decoded: any = verifyBackendJwtRS256(token);\n\n const baseCtx: AuthContext = {\n tokenType: \"backend\",\n subject,\n company_uid: company_uid ?? undefined,\n branch_uid: branch_uid ?? undefined,\n roles: Array.isArray(decoded?.roles) ? decoded.roles : [],\n permissions: Array.isArray(decoded?.permissions) ? decoded.permissions : [],\n denied_permissions: Array.isArray(decoded?.denied_permissions) ? decoded.denied_permissions : [],\n session: {\n jti: decoded?.jti,\n device_id: decoded?.device_id,\n expires_at: decoded?.exp,\n },\n };\n\n // ✅ hydrate obligatorio\n const hydrated = await hydrate({decoded, req, subject, company_uid, branch_uid});\n Object.assign(baseCtx, hydrated);\n\n if (requireSubject) {\n if (subject === \"employee\" && !baseCtx.employee) {\n return res.status(401).json({\n ok: false,\n code: \"AUTH_EMPLOYEE_NOT_FOUND\",\n message: \"Employee not resolved by hydrator\",\n });\n }\n if (subject === \"customer\" && !baseCtx.customer) {\n return res.status(401).json({\n ok: false,\n code: \"AUTH_CUSTOMER_NOT_FOUND\",\n message: \"Customer not resolved by hydrator\",\n });\n }\n }\n\n (req as any).auth = baseCtx;\n return next();\n } catch {\n // 2) Firebase opcional\n if (!allowFirebaseIdToken) {\n return res.status(401).json({\n ok: false,\n code: \"AUTH_INVALID_TOKEN\",\n message: \"Invalid or expired token\",\n });\n }\n\n try {\n const {default: admin} = await import(\"firebase-admin\");\n const firebaseDecoded = await admin.auth().verifyIdToken(token);\n\n if (firebaseDecoded.email && firebaseDecoded.email_verified === false) {\n return res.status(401).json({\n ok: false,\n code: \"AUTH_EMAIL_NOT_VERIFIED\",\n message: \"Email not verified\",\n });\n }\n\n (req as any).auth = {\n tokenType: \"backend\",\n subject,\n firebase: firebaseDecoded,\n company_uid: company_uid ?? undefined,\n branch_uid: branch_uid ?? undefined,\n companies: [],\n roles: [],\n permissions: [],\n denied_permissions: [],\n } satisfies AuthContext;\n\n return next();\n } catch {\n return res.status(401).json({\n ok: false,\n code: \"AUTH_INVALID_TOKEN\",\n message: \"Invalid or expired token\",\n });\n }\n }\n };\n}\n","// packages/sdk/src/auth/authentication.ts\nimport type {NextFunction, Response} from \"express\";\nimport admin from \"firebase-admin\";\nimport jwt, {JwtPayload} from \"jsonwebtoken\";\nimport fs from \"fs\";\n\ntype Subject = \"employee\" | \"customer\";\ntype TokenType = \"backend\";\n\nexport interface AuthContext {\n tokenType: TokenType;\n subject: Subject;\n\n // ✅ UID-first canonical\n employee_uid?: string;\n customer_uid?: string;\n\n // Opcional (puede venir embebido o ser ref mínimo)\n employee?: any;\n customer?: any;\n\n company_uid?: string;\n branch_uid?: string;\n\n company?: any;\n branch?: any;\n companies?: any[];\n\n roles?: any[];\n permissions?: any[];\n denied_permissions?: any[];\n\n session?: { jti?: string; device_id?: string; expires_at?: number };\n firebase?: admin.auth.DecodedIdToken;\n}\n\n/**\n * ✅ ÚNICO estándar:\n * - Authorization: Bearer <token>\n */\nfunction getBearerToken(req: any): string | null {\n const auth = String(req.headers?.authorization || \"\");\n if (!auth.startsWith(\"Bearer \")) return null;\n const token = auth.slice(7).trim();\n return token.length ? token : null;\n}\n\nfunction readPublicKey(): string {\n const publicKeyPath = process.env.JWT_PUBLIC_KEY_PATH;\n const publicKeyEnv = process.env.AUTH_JWT_PUBLIC_KEY || process.env.AUTH_RSA_PUBLIC_KEY || \"\";\n\n if (publicKeyPath) {\n const v = fs.readFileSync(publicKeyPath, \"utf8\").trim();\n if (v) return v;\n }\n\n const envKey = publicKeyEnv.replace(/\\\\n/g, \"\\n\").trim();\n if (envKey) return envKey;\n\n throw new Error(\"Missing RS256 public key (JWT_PUBLIC_KEY_PATH / AUTH_JWT_PUBLIC_KEY / AUTH_RSA_PUBLIC_KEY)\");\n}\n\nfunction verifyBackendJwtRS256(raw: string): JwtPayload {\n const publicKey = readPublicKey();\n const audience = process.env.JWT_AUDIENCE || process.env.AUTH_JWT_AUDIENCE || \"getmarket.api\";\n const issuer = process.env.JWT_ISSUER || process.env.AUTH_JWT_ISSUER || \"getmarket-auth\";\n\n return jwt.verify(raw, publicKey, {\n algorithms: [\"RS256\"],\n audience,\n issuer,\n }) as JwtPayload;\n}\n\nfunction normalizeUid(v: any): string | null {\n const s = String(v ?? \"\").trim();\n return s.length ? s : null;\n}\n\nfunction deriveCompanyBranch(decoded: any, companyUid: string | null, branchUid: string | null) {\n const companiesFromToken = Array.isArray(decoded?.companies) ? decoded.companies : [];\n\n const company =\n decoded?.company ??\n (companyUid ? companiesFromToken.find((c: any) => c?.uid === companyUid) : null) ??\n null;\n\n const branch =\n decoded?.branch ??\n (branchUid && company?.branches ? (company.branches || []).find((b: any) => b?.uid === branchUid) : null) ??\n null;\n\n return {companiesFromToken, company, branch};\n}\n\n/**\n * ✅ UID-first extractors\n * - decoded.employee_uid / decoded.customer_uid\n * - decoded.sub = \"emp:<uid>\" / \"cus:<uid>\"\n */\nfunction extractEmployeeUid(decoded: any): string | null {\n const direct = normalizeUid(decoded?.employee_uid);\n if (direct) return direct;\n\n const sub = normalizeUid(decoded?.sub);\n if (!sub) return null;\n\n const m = /^emp:(.+)$/i.exec(sub);\n return m?.[1] ? normalizeUid(m[1]) : null;\n}\n\nfunction extractCustomerUid(decoded: any): string | null {\n const direct = normalizeUid(decoded?.customer_uid);\n if (direct) return direct;\n\n const sub = normalizeUid(decoded?.sub);\n if (!sub) return null;\n\n const m = /^cus:(.+)$/i.exec(sub);\n return m?.[1] ? normalizeUid(m[1]) : null;\n}\n\nexport function createAuthMiddleware(opts: { subject: Subject; allowFirebaseIdToken?: boolean }) {\n const {subject, allowFirebaseIdToken = false} = opts;\n\n return async (req: any, res: Response, next: NextFunction) => {\n const token = getBearerToken(req);\n if (!token) {\n return res.status(401).json({\n ok: false,\n code: \"AUTH_MISSING_TOKEN\",\n message: \"Missing Authorization Bearer token\",\n });\n }\n\n // 1) Backend JWT RS256\n try {\n const decoded: any = verifyBackendJwtRS256(token);\n\n const headerCtx = (req as any).context || {};\n const companyUid = normalizeUid(headerCtx.company_uid);\n const branchUid = normalizeUid(headerCtx.branch_uid);\n\n const {companiesFromToken, company, branch} = deriveCompanyBranch(decoded, companyUid, branchUid);\n\n const ctx: AuthContext = {\n tokenType: \"backend\",\n subject,\n\n company_uid: companyUid ?? undefined,\n branch_uid: branchUid ?? undefined,\n\n companies: companiesFromToken,\n company,\n branch,\n\n roles: Array.isArray(decoded?.roles) ? decoded.roles : [],\n permissions: Array.isArray(decoded?.permissions) ? decoded.permissions : [],\n denied_permissions: Array.isArray(decoded?.denied_permissions) ? decoded.denied_permissions : [],\n\n session: {\n jti: decoded?.jti,\n device_id: decoded?.device_id,\n expires_at: decoded?.exp,\n },\n };\n\n if (subject === \"employee\") {\n const employee_uid = extractEmployeeUid(decoded);\n if (!employee_uid) {\n return res.status(401).json({\n ok: false,\n code: \"AUTH_EMPLOYEE_UID_MISSING\",\n message: \"employee_uid missing in token (expected employee_uid or sub=emp:<uid>)\",\n });\n }\n ctx.employee_uid = employee_uid;\n\n // ✅ employee embebido es opcional; si no viene, dejamos ref mínimo\n const embedded = decoded?.employee ?? decoded?.user ?? null;\n ctx.employee = embedded && typeof embedded === \"object\"\n ? embedded\n : {uid: employee_uid, email: decoded?.email ?? null};\n } else {\n const customer_uid = extractCustomerUid(decoded);\n if (!customer_uid) {\n return res.status(401).json({\n ok: false,\n code: \"AUTH_CUSTOMER_UID_MISSING\",\n message: \"customer_uid missing in token (expected customer_uid or sub=cus:<uid>)\",\n });\n }\n ctx.customer_uid = customer_uid;\n\n const embedded = decoded?.customer ?? null;\n ctx.customer = embedded && typeof embedded === \"object\"\n ? embedded\n : {uid: customer_uid};\n }\n\n req.auth = ctx;\n return next();\n } catch {\n // 2) Firebase opcional\n if (!allowFirebaseIdToken) {\n return res.status(401).json({\n ok: false,\n code: \"AUTH_INVALID_TOKEN\",\n message: \"Invalid or expired token\",\n });\n }\n\n try {\n const firebaseDecoded = await admin.auth().verifyIdToken(token);\n\n if (firebaseDecoded.email && firebaseDecoded.email_verified === false) {\n return res.status(401).json({\n ok: false,\n code: \"AUTH_EMAIL_NOT_VERIFIED\",\n message: \"Email not verified\",\n });\n }\n\n const headerCtx = (req as any).context || {};\n const companyUid = normalizeUid(headerCtx.company_uid);\n const branchUid = normalizeUid(headerCtx.branch_uid);\n\n req.auth = {\n tokenType: \"backend\",\n subject,\n firebase: firebaseDecoded,\n company_uid: companyUid ?? undefined,\n branch_uid: branchUid ?? undefined,\n companies: [],\n roles: [],\n permissions: [],\n denied_permissions: [],\n };\n\n return next();\n } catch {\n return res.status(401).json({\n ok: false,\n code: \"AUTH_INVALID_TOKEN\",\n message: \"Invalid or expired token\",\n });\n }\n }\n };\n}\n\nexport const authEmployeeRequired = createAuthMiddleware({subject: \"employee\", allowFirebaseIdToken: false});\nexport const authCustomerRequired = createAuthMiddleware({subject: \"customer\", allowFirebaseIdToken: false});\nexport const authEmployeeAllowFirebase = createAuthMiddleware({subject: \"employee\", allowFirebaseIdToken: true});\nexport const authCustomerAllowFirebase = createAuthMiddleware({subject: \"customer\", allowFirebaseIdToken: true});\n","// packages/sdk/src/middlewares/guards.ts\nimport type {Request, Response, NextFunction, RequestHandler} from \"express\";\nimport parseHeaders from \"./parseHeaders\";\nimport {authEmployeeRequired} from \"../auth\";\nimport {sendError} from \"./respond\";\n\ntype RoleShape = string | { code?: string; name?: string };\ntype PermShape = string | { code?: string; name?: string };\n\nfunction normalizeRole(r: RoleShape): string | null {\n if (!r) return null;\n if (typeof r === \"string\") return r;\n return r.code || r.name || null;\n}\n\nfunction normalizePerm(p: PermShape): string | null {\n if (!p) return null;\n if (typeof p === \"string\") return p;\n return p.code || p.name || null;\n}\n\nfunction isSysAdmin(roles: RoleShape[] | undefined): boolean {\n if (!Array.isArray(roles)) return false;\n return roles.some((r) => normalizeRole(r) === \"SYS_ADMIN\");\n}\n\nfunction getAuth(req: Request) {\n return ((req as any).auth ?? {}) as {\n roles?: RoleShape[];\n permissions?: PermShape[];\n denied_permissions?: PermShape[];\n };\n}\n\nfunction permissionSets(auth: ReturnType<typeof getAuth>) {\n const allow = new Set<string>((auth.permissions ?? []).map(normalizePerm).filter(Boolean) as string[]);\n const deny = new Set<string>((auth.denied_permissions ?? []).map(normalizePerm).filter(Boolean) as string[]);\n return {allow, deny};\n}\n\nfunction roleSet(auth: ReturnType<typeof getAuth>) {\n return new Set<string>((auth.roles ?? []).map(normalizeRole).filter(Boolean) as string[]);\n}\n\n/**\n * ✅ SysAdmin bypass OR (ANY) permissions\n * - Si tiene alguno de los permisos => OK\n * - denied_permissions gana siempre\n */\nexport function allowSysAdminOrAnyPermission(...perms: string[]): RequestHandler[] {\n const required = (perms ?? []).filter(Boolean);\n\n return [\n parseHeaders,\n authEmployeeRequired,\n (req: Request, res: Response, next: NextFunction) => {\n const auth = getAuth(req);\n if (isSysAdmin(auth.roles)) return next();\n\n const {allow, deny} = permissionSets(auth);\n\n for (const p of required) {\n if (deny.has(p)) {\n return sendError(req, res, 403, \"FORBIDDEN\", `Denied permission: ${p}`, {denied: p});\n }\n }\n\n const ok = required.some((p) => allow.has(p));\n if (!ok) {\n return sendError(req, res, 403, \"FORBIDDEN\", \"Missing permissions (ANY)\", {required});\n }\n\n return next();\n },\n ];\n}\n\n/**\n * ✅ SysAdmin bypass OR (ALL) permissions (AND)\n */\nexport function allowSysAdminOrPermissionsAll(...perms: string[]): RequestHandler[] {\n const required = (perms ?? []).filter(Boolean);\n\n return [\n parseHeaders,\n authEmployeeRequired,\n (req: Request, res: Response, next: NextFunction) => {\n const auth = getAuth(req);\n if (isSysAdmin(auth.roles)) return next();\n\n const {allow, deny} = permissionSets(auth);\n\n for (const p of required) {\n if (deny.has(p)) {\n return sendError(req, res, 403, \"FORBIDDEN\", `Denied permission: ${p}`, {denied: p});\n }\n }\n\n const missing = required.filter((p) => !allow.has(p));\n if (missing.length) {\n return sendError(req, res, 403, \"FORBIDDEN\", \"Missing permissions (ALL)\", {required, missing});\n }\n\n return next();\n },\n ];\n}\n\n/**\n * ✅ SysAdmin bypass OR roles (ANY)\n */\nexport function allowSysAdminOrRoles(...roles: string[]): RequestHandler[] {\n const required = (roles ?? []).filter(Boolean);\n\n return [\n parseHeaders,\n authEmployeeRequired,\n (req: Request, res: Response, next: NextFunction) => {\n const auth = getAuth(req);\n if (isSysAdmin(auth.roles)) return next();\n\n const have = roleSet(auth);\n\n const ok = required.some((r) => have.has(r));\n if (!ok) {\n return sendError(req, res, 403, \"FORBIDDEN\", \"Role not allowed\", {required});\n }\n\n return next();\n },\n ];\n}\n\n/**\n * ✅ SYS_ADMIN bypass OR (ANY) roles OR (ANY) permissions\n * - denied_permissions siempre gana\n */\nexport function allowSysAdminOrRolesOrAnyPermission(\n roles: string | string[],\n permissions: string | string[]\n): RequestHandler[] {\n const requiredRoles = (Array.isArray(roles) ? roles : [roles]).filter(Boolean);\n const requiredPerms = (Array.isArray(permissions) ? permissions : [permissions]).filter(Boolean);\n\n return [\n parseHeaders,\n authEmployeeRequired,\n (req: Request, res: Response, next: NextFunction) => {\n const auth = getAuth(req);\n if (isSysAdmin(auth.roles)) return next();\n\n const {allow, deny} = permissionSets(auth);\n for (const p of requiredPerms) {\n if (deny.has(p)) {\n return sendError(req, res, 403, \"FORBIDDEN\", `Denied: ${p}`, {permission: p});\n }\n }\n\n const haveRoles = roleSet(auth);\n if (requiredRoles.some((r) => haveRoles.has(r))) return next();\n\n if (requiredPerms.some((p) => allow.has(p))) return next();\n\n return sendError(req, res, 403, \"FORBIDDEN\", \"Permission denied\", {\n roles: requiredRoles,\n permissions: requiredPerms,\n mode: \"ROLES_OR_ANY_PERMISSION\",\n });\n },\n ];\n}\n\n/**\n * ✅ Helper específico Auth:\n * Rol AUTH_ADMIN o permiso fino (y SYS_ADMIN bypass)\n */\nexport function allowAuthAdminOrPerm(permission: string): RequestHandler[] {\n return allowSysAdminOrRolesOrAnyPermission([\"AUTH_ADMIN\"], [permission]);\n}\n"],"mappings":"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","names":["fs","admin","jwt","fs","getBearerToken","verifyBackendJwtRS256","normalizeUid","createAuthMiddleware","isSysAdmin","getAuth"]}
|
package/dist/index.cjs
CHANGED
|
@@ -921,9 +921,7 @@ function readPublicKey() {
|
|
|
921
921
|
}
|
|
922
922
|
const envKey = publicKeyEnv.replace(/\\n/g, "\n").trim();
|
|
923
923
|
if (envKey) return envKey;
|
|
924
|
-
throw new Error(
|
|
925
|
-
"Missing RS256 public key (JWT_PUBLIC_KEY_PATH / AUTH_JWT_PUBLIC_KEY / AUTH_RSA_PUBLIC_KEY)"
|
|
926
|
-
);
|
|
924
|
+
throw new Error("Missing RS256 public key (JWT_PUBLIC_KEY_PATH / AUTH_JWT_PUBLIC_KEY / AUTH_RSA_PUBLIC_KEY)");
|
|
927
925
|
}
|
|
928
926
|
function verifyBackendJwtRS2562(raw) {
|
|
929
927
|
const publicKey = readPublicKey();
|
|
@@ -945,6 +943,22 @@ function deriveCompanyBranch(decoded, companyUid, branchUid) {
|
|
|
945
943
|
const branch = decoded?.branch ?? (branchUid && company?.branches ? (company.branches || []).find((b) => b?.uid === branchUid) : null) ?? null;
|
|
946
944
|
return { companiesFromToken, company, branch };
|
|
947
945
|
}
|
|
946
|
+
function extractEmployeeUid(decoded) {
|
|
947
|
+
const direct = normalizeUid2(decoded?.employee_uid);
|
|
948
|
+
if (direct) return direct;
|
|
949
|
+
const sub = normalizeUid2(decoded?.sub);
|
|
950
|
+
if (!sub) return null;
|
|
951
|
+
const m = /^emp:(.+)$/i.exec(sub);
|
|
952
|
+
return m?.[1] ? normalizeUid2(m[1]) : null;
|
|
953
|
+
}
|
|
954
|
+
function extractCustomerUid(decoded) {
|
|
955
|
+
const direct = normalizeUid2(decoded?.customer_uid);
|
|
956
|
+
if (direct) return direct;
|
|
957
|
+
const sub = normalizeUid2(decoded?.sub);
|
|
958
|
+
if (!sub) return null;
|
|
959
|
+
const m = /^cus:(.+)$/i.exec(sub);
|
|
960
|
+
return m?.[1] ? normalizeUid2(m[1]) : null;
|
|
961
|
+
}
|
|
948
962
|
function createAuthMiddleware2(opts) {
|
|
949
963
|
const { subject, allowFirebaseIdToken = false } = opts;
|
|
950
964
|
return async (req, res, next) => {
|
|
@@ -980,25 +994,29 @@ function createAuthMiddleware2(opts) {
|
|
|
980
994
|
}
|
|
981
995
|
};
|
|
982
996
|
if (subject === "employee") {
|
|
983
|
-
const
|
|
984
|
-
if (!
|
|
997
|
+
const employee_uid = extractEmployeeUid(decoded);
|
|
998
|
+
if (!employee_uid) {
|
|
985
999
|
return res.status(401).json({
|
|
986
1000
|
ok: false,
|
|
987
|
-
code: "
|
|
988
|
-
message: "
|
|
1001
|
+
code: "AUTH_EMPLOYEE_UID_MISSING",
|
|
1002
|
+
message: "employee_uid missing in token (expected employee_uid or sub=emp:<uid>)"
|
|
989
1003
|
});
|
|
990
1004
|
}
|
|
991
|
-
ctx.
|
|
1005
|
+
ctx.employee_uid = employee_uid;
|
|
1006
|
+
const embedded = decoded?.employee ?? decoded?.user ?? null;
|
|
1007
|
+
ctx.employee = embedded && typeof embedded === "object" ? embedded : { uid: employee_uid, email: decoded?.email ?? null };
|
|
992
1008
|
} else {
|
|
993
|
-
const
|
|
994
|
-
if (!
|
|
1009
|
+
const customer_uid = extractCustomerUid(decoded);
|
|
1010
|
+
if (!customer_uid) {
|
|
995
1011
|
return res.status(401).json({
|
|
996
1012
|
ok: false,
|
|
997
|
-
code: "
|
|
998
|
-
message: "
|
|
1013
|
+
code: "AUTH_CUSTOMER_UID_MISSING",
|
|
1014
|
+
message: "customer_uid missing in token (expected customer_uid or sub=cus:<uid>)"
|
|
999
1015
|
});
|
|
1000
1016
|
}
|
|
1001
|
-
ctx.
|
|
1017
|
+
ctx.customer_uid = customer_uid;
|
|
1018
|
+
const embedded = decoded?.customer ?? null;
|
|
1019
|
+
ctx.customer = embedded && typeof embedded === "object" ? embedded : { uid: customer_uid };
|
|
1002
1020
|
}
|
|
1003
1021
|
req.auth = ctx;
|
|
1004
1022
|
return next();
|
|
@@ -1068,14 +1086,13 @@ function getAuth2(req) {
|
|
|
1068
1086
|
return req.auth ?? {};
|
|
1069
1087
|
}
|
|
1070
1088
|
function permissionSets(auth) {
|
|
1071
|
-
const allow = new Set(
|
|
1072
|
-
|
|
1073
|
-
);
|
|
1074
|
-
const deny = new Set(
|
|
1075
|
-
(auth.denied_permissions ?? []).map(normalizePerm).filter(Boolean)
|
|
1076
|
-
);
|
|
1089
|
+
const allow = new Set((auth.permissions ?? []).map(normalizePerm).filter(Boolean));
|
|
1090
|
+
const deny = new Set((auth.denied_permissions ?? []).map(normalizePerm).filter(Boolean));
|
|
1077
1091
|
return { allow, deny };
|
|
1078
1092
|
}
|
|
1093
|
+
function roleSet(auth) {
|
|
1094
|
+
return new Set((auth.roles ?? []).map(normalizeRole).filter(Boolean));
|
|
1095
|
+
}
|
|
1079
1096
|
function allowSysAdminOrAnyPermission(...perms) {
|
|
1080
1097
|
const required = (perms ?? []).filter(Boolean);
|
|
1081
1098
|
return [
|
|
@@ -1087,16 +1104,12 @@ function allowSysAdminOrAnyPermission(...perms) {
|
|
|
1087
1104
|
const { allow, deny } = permissionSets(auth);
|
|
1088
1105
|
for (const p of required) {
|
|
1089
1106
|
if (deny.has(p)) {
|
|
1090
|
-
return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, {
|
|
1091
|
-
denied: p
|
|
1092
|
-
});
|
|
1107
|
+
return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, { denied: p });
|
|
1093
1108
|
}
|
|
1094
1109
|
}
|
|
1095
1110
|
const ok = required.some((p) => allow.has(p));
|
|
1096
1111
|
if (!ok) {
|
|
1097
|
-
return sendError(req, res, 403, "FORBIDDEN", "Missing permissions (ANY)", {
|
|
1098
|
-
required
|
|
1099
|
-
});
|
|
1112
|
+
return sendError(req, res, 403, "FORBIDDEN", "Missing permissions (ANY)", { required });
|
|
1100
1113
|
}
|
|
1101
1114
|
return next();
|
|
1102
1115
|
}
|
|
@@ -1113,17 +1126,12 @@ function allowSysAdminOrPermissionsAll(...perms) {
|
|
|
1113
1126
|
const { allow, deny } = permissionSets(auth);
|
|
1114
1127
|
for (const p of required) {
|
|
1115
1128
|
if (deny.has(p)) {
|
|
1116
|
-
return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, {
|
|
1117
|
-
denied: p
|
|
1118
|
-
});
|
|
1129
|
+
return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, { denied: p });
|
|
1119
1130
|
}
|
|
1120
1131
|
}
|
|
1121
1132
|
const missing = required.filter((p) => !allow.has(p));
|
|
1122
1133
|
if (missing.length) {
|
|
1123
|
-
return sendError(req, res, 403, "FORBIDDEN", "Missing permissions (ALL)", {
|
|
1124
|
-
required,
|
|
1125
|
-
missing
|
|
1126
|
-
});
|
|
1134
|
+
return sendError(req, res, 403, "FORBIDDEN", "Missing permissions (ALL)", { required, missing });
|
|
1127
1135
|
}
|
|
1128
1136
|
return next();
|
|
1129
1137
|
}
|
|
@@ -1137,55 +1145,33 @@ function allowSysAdminOrRoles(...roles) {
|
|
|
1137
1145
|
(req, res, next) => {
|
|
1138
1146
|
const auth = getAuth2(req);
|
|
1139
1147
|
if (isSysAdmin2(auth.roles)) return next();
|
|
1140
|
-
const have =
|
|
1141
|
-
(auth.roles ?? []).map(normalizeRole).filter(Boolean)
|
|
1142
|
-
);
|
|
1148
|
+
const have = roleSet(auth);
|
|
1143
1149
|
const ok = required.some((r) => have.has(r));
|
|
1144
1150
|
if (!ok) {
|
|
1145
|
-
return sendError(req, res, 403, "FORBIDDEN", "Role not allowed", {
|
|
1146
|
-
required
|
|
1147
|
-
});
|
|
1151
|
+
return sendError(req, res, 403, "FORBIDDEN", "Role not allowed", { required });
|
|
1148
1152
|
}
|
|
1149
1153
|
return next();
|
|
1150
1154
|
}
|
|
1151
1155
|
];
|
|
1152
1156
|
}
|
|
1153
|
-
|
|
1154
|
-
// src/middlewares/accessControl.ts
|
|
1155
|
-
function normalizeList(v) {
|
|
1156
|
-
return Array.isArray(v) ? v : [v];
|
|
1157
|
-
}
|
|
1158
|
-
function roleCode(r) {
|
|
1159
|
-
if (!r) return null;
|
|
1160
|
-
return typeof r === "string" ? r : r.code || r.name || null;
|
|
1161
|
-
}
|
|
1162
|
-
function permCode(p) {
|
|
1163
|
-
if (!p) return null;
|
|
1164
|
-
return typeof p === "string" ? p : p.code || p.name || null;
|
|
1165
|
-
}
|
|
1166
|
-
function isSysAdmin3(roles) {
|
|
1167
|
-
if (!Array.isArray(roles)) return false;
|
|
1168
|
-
return roles.map(roleCode).filter(Boolean).includes("SYS_ADMIN");
|
|
1169
|
-
}
|
|
1170
1157
|
function allowSysAdminOrRolesOrAnyPermission(roles, permissions) {
|
|
1171
|
-
const requiredRoles =
|
|
1172
|
-
const requiredPerms =
|
|
1158
|
+
const requiredRoles = (Array.isArray(roles) ? roles : [roles]).filter(Boolean);
|
|
1159
|
+
const requiredPerms = (Array.isArray(permissions) ? permissions : [permissions]).filter(Boolean);
|
|
1173
1160
|
return [
|
|
1174
1161
|
parseHeaders,
|
|
1175
1162
|
authEmployeeRequired,
|
|
1176
1163
|
(req, res, next) => {
|
|
1177
|
-
const auth = req
|
|
1178
|
-
if (
|
|
1179
|
-
const deny =
|
|
1164
|
+
const auth = getAuth2(req);
|
|
1165
|
+
if (isSysAdmin2(auth.roles)) return next();
|
|
1166
|
+
const { allow, deny } = permissionSets(auth);
|
|
1180
1167
|
for (const p of requiredPerms) {
|
|
1181
1168
|
if (deny.has(p)) {
|
|
1182
1169
|
return sendError(req, res, 403, "FORBIDDEN", `Denied: ${p}`, { permission: p });
|
|
1183
1170
|
}
|
|
1184
1171
|
}
|
|
1185
|
-
const haveRoles =
|
|
1172
|
+
const haveRoles = roleSet(auth);
|
|
1186
1173
|
if (requiredRoles.some((r) => haveRoles.has(r))) return next();
|
|
1187
|
-
|
|
1188
|
-
if (requiredPerms.some((p) => havePerms.has(p))) return next();
|
|
1174
|
+
if (requiredPerms.some((p) => allow.has(p))) return next();
|
|
1189
1175
|
return sendError(req, res, 403, "FORBIDDEN", "Permission denied", {
|
|
1190
1176
|
roles: requiredRoles,
|
|
1191
1177
|
permissions: requiredPerms,
|