@innvoid/getmarket-sdk 0.1.4 → 0.1.6
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/cache/index.js +0 -1
- package/dist/chunk-JXOLNJ7J.js +224 -0
- package/dist/chunk-JXOLNJ7J.js.map +1 -0
- package/dist/chunk-KJ64O2EG.js +19 -0
- package/dist/chunk-KJ64O2EG.js.map +1 -0
- package/dist/{chunk-GG7EI74E.js → chunk-OSYBK5AN.js} +5 -3
- package/dist/chunk-OSYBK5AN.js.map +1 -0
- package/dist/chunk-P2U3MT2E.js +39 -0
- package/dist/chunk-P2U3MT2E.js.map +1 -0
- package/dist/core/index.cjs +4 -2
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +1 -2
- package/dist/core/index.d.ts +1 -2
- package/dist/core/index.js +2 -4
- package/dist/express.cjs +19 -0
- package/dist/express.cjs.map +1 -0
- package/dist/express.d.cts +12 -0
- package/dist/express.d.ts +12 -0
- package/dist/express.js +1 -0
- package/dist/headers/index.cjs +12 -6
- package/dist/headers/index.cjs.map +1 -1
- package/dist/headers/index.d.cts +3 -18
- package/dist/headers/index.d.ts +3 -18
- package/dist/headers/index.js +1 -2
- package/dist/index.cjs +138 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -6
- package/dist/index.d.ts +34 -6
- package/dist/index.js +147 -14
- package/dist/index.js.map +1 -1
- package/dist/middlewares/index.cjs +133 -35
- package/dist/middlewares/index.cjs.map +1 -1
- package/dist/middlewares/index.d.cts +43 -14
- package/dist/middlewares/index.d.ts +43 -14
- package/dist/middlewares/index.js +9 -4
- package/dist/parse-C4vk-fmH.d.cts +16 -0
- package/dist/parse-C4vk-fmH.d.ts +16 -0
- package/dist/types-CRECQuHp.d.cts +54 -0
- package/dist/types-CRECQuHp.d.ts +54 -0
- package/package.json +6 -1
- package/dist/auth/index.cjs +0 -181
- package/dist/auth/index.cjs.map +0 -1
- package/dist/auth/index.d.cts +0 -3
- package/dist/auth/index.d.ts +0 -3
- package/dist/auth/index.js +0 -12
- package/dist/chunk-65HACONF.js +0 -33
- package/dist/chunk-65HACONF.js.map +0 -1
- package/dist/chunk-GG7EI74E.js.map +0 -1
- package/dist/chunk-PZ5AY32C.js +0 -10
- package/dist/chunk-PZ5AY32C.js.map +0 -1
- package/dist/chunk-W23UYULS.js +0 -156
- package/dist/chunk-W23UYULS.js.map +0 -1
- package/dist/chunk-Y2JJLHAY.js +0 -149
- package/dist/chunk-Y2JJLHAY.js.map +0 -1
- package/dist/index-WbfzvmOt.d.cts +0 -87
- package/dist/index-WbfzvmOt.d.ts +0 -87
- /package/dist/{auth/index.js.map → express.js.map} +0 -0
|
@@ -33,28 +33,16 @@ __export(middlewares_exports, {
|
|
|
33
33
|
internalAuth: () => internalAuth,
|
|
34
34
|
parseHeaders: () => parseHeaders,
|
|
35
35
|
requestId: () => requestId,
|
|
36
|
+
requireAnyPermission: () => requireAnyPermission,
|
|
36
37
|
requireAuthContext: () => requireAuthContext,
|
|
37
38
|
requirePermissions: () => requirePermissions,
|
|
38
39
|
requireRoles: () => requireRoles,
|
|
40
|
+
requireRolesOrAnyPermission: () => requireRolesOrAnyPermission,
|
|
39
41
|
sendError: () => sendError,
|
|
40
42
|
sendOk: () => sendOk
|
|
41
43
|
});
|
|
42
44
|
module.exports = __toCommonJS(middlewares_exports);
|
|
43
45
|
|
|
44
|
-
// src/middlewares/requestId.ts
|
|
45
|
-
var import_crypto = require("crypto");
|
|
46
|
-
var REQUEST_ID_HEADER = "x-request-id";
|
|
47
|
-
var REQUEST_ID_HEADER_ALT = "x-requestid";
|
|
48
|
-
var RESPONSE_REQUEST_ID_HEADER = "X-Request-Id";
|
|
49
|
-
function requestId(req, res, next) {
|
|
50
|
-
const headerId = req.headers[REQUEST_ID_HEADER] || req.headers[REQUEST_ID_HEADER_ALT];
|
|
51
|
-
const id = headerId?.trim() || (0, import_crypto.randomUUID)();
|
|
52
|
-
req.requestId = id;
|
|
53
|
-
res.locals.requestId = id;
|
|
54
|
-
res.setHeader(RESPONSE_REQUEST_ID_HEADER, id);
|
|
55
|
-
next();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
46
|
// src/headers/constants.ts
|
|
59
47
|
var HEADER_REQUEST_ID = "x-request-id";
|
|
60
48
|
var HEADER_COMPANY_UID = "x-company";
|
|
@@ -63,28 +51,43 @@ var HEADER_EMPLOYEE_UID = "x-employee-uid";
|
|
|
63
51
|
var HEADER_INTERNAL_API_KEY = "x-internal-api-key";
|
|
64
52
|
|
|
65
53
|
// src/headers/parse.ts
|
|
66
|
-
function
|
|
54
|
+
function normalizeHeaderValue(v) {
|
|
67
55
|
if (typeof v !== "string") return null;
|
|
68
56
|
const s = v.trim();
|
|
69
|
-
|
|
57
|
+
if (!s) return null;
|
|
58
|
+
if (s.startsWith("{") || s.startsWith("[") || s.includes('"')) return null;
|
|
59
|
+
if (s.length < 6) return null;
|
|
60
|
+
return s;
|
|
61
|
+
}
|
|
62
|
+
function h(headers, key) {
|
|
63
|
+
return headers[key] ?? headers[key.toLowerCase()] ?? headers[key.toUpperCase()];
|
|
70
64
|
}
|
|
71
65
|
function getRequestContextFromHeaders(headers) {
|
|
72
66
|
return {
|
|
73
|
-
requestId:
|
|
74
|
-
company_uid:
|
|
75
|
-
branch_uid:
|
|
76
|
-
employee_uid:
|
|
67
|
+
requestId: normalizeHeaderValue(h(headers, HEADER_REQUEST_ID)) ?? null,
|
|
68
|
+
company_uid: normalizeHeaderValue(h(headers, HEADER_COMPANY_UID)) ?? null,
|
|
69
|
+
branch_uid: normalizeHeaderValue(h(headers, HEADER_BRANCH_UID)) ?? null,
|
|
70
|
+
employee_uid: normalizeHeaderValue(h(headers, HEADER_EMPLOYEE_UID)) ?? null
|
|
77
71
|
};
|
|
78
72
|
}
|
|
79
73
|
|
|
80
74
|
// src/middlewares/parseHeaders.ts
|
|
81
75
|
function parseHeaders(req, _res, next) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
76
|
+
req.context = getRequestContextFromHeaders(req.headers);
|
|
77
|
+
next();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// src/middlewares/requestId.ts
|
|
81
|
+
var import_crypto = require("crypto");
|
|
82
|
+
var REQUEST_ID_HEADER = "x-request-id";
|
|
83
|
+
var REQUEST_ID_HEADER_ALT = "x-requestid";
|
|
84
|
+
var RESPONSE_REQUEST_ID_HEADER = "X-Request-Id";
|
|
85
|
+
function requestId(req, res, next) {
|
|
86
|
+
const headerId = req.headers[REQUEST_ID_HEADER] || req.headers[REQUEST_ID_HEADER_ALT];
|
|
87
|
+
const id = headerId?.trim() || (0, import_crypto.randomUUID)();
|
|
88
|
+
req.requestId = id;
|
|
89
|
+
res.locals.requestId = id;
|
|
90
|
+
res.setHeader(RESPONSE_REQUEST_ID_HEADER, id);
|
|
88
91
|
next();
|
|
89
92
|
}
|
|
90
93
|
|
|
@@ -156,10 +159,32 @@ function internalAuth(req, res, next) {
|
|
|
156
159
|
return next();
|
|
157
160
|
}
|
|
158
161
|
|
|
159
|
-
// src/middlewares/
|
|
162
|
+
// src/middlewares/authorization.ts
|
|
160
163
|
function getAuth(req) {
|
|
161
164
|
return req.auth ?? {};
|
|
162
165
|
}
|
|
166
|
+
function normalizeCode(v) {
|
|
167
|
+
if (!v) return null;
|
|
168
|
+
if (typeof v === "string") return v;
|
|
169
|
+
if (typeof v === "object") return v.code || v.name || null;
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
function rolesSet(auth) {
|
|
173
|
+
const out = /* @__PURE__ */ new Set();
|
|
174
|
+
for (const r of auth.roles || []) {
|
|
175
|
+
const c = normalizeCode(r);
|
|
176
|
+
if (c) out.add(c);
|
|
177
|
+
}
|
|
178
|
+
return out;
|
|
179
|
+
}
|
|
180
|
+
function permsSet(list) {
|
|
181
|
+
const out = /* @__PURE__ */ new Set();
|
|
182
|
+
for (const p of list || []) {
|
|
183
|
+
const c = normalizeCode(p);
|
|
184
|
+
if (c) out.add(c);
|
|
185
|
+
}
|
|
186
|
+
return out;
|
|
187
|
+
}
|
|
163
188
|
function requireAuthContext() {
|
|
164
189
|
return (req, res, next) => {
|
|
165
190
|
if (!req.auth) {
|
|
@@ -168,29 +193,100 @@ function requireAuthContext() {
|
|
|
168
193
|
return next();
|
|
169
194
|
};
|
|
170
195
|
}
|
|
171
|
-
function
|
|
196
|
+
function isSysAdmin(auth, sysAdminRole) {
|
|
197
|
+
const have = rolesSet(auth);
|
|
198
|
+
return have.has(sysAdminRole);
|
|
199
|
+
}
|
|
200
|
+
function requirePermissions(perms, options) {
|
|
201
|
+
const sysAdminBypass = options?.sysAdminBypass !== false;
|
|
202
|
+
const sysAdminRole = options?.sysAdminRole || "SYS_ADMIN";
|
|
172
203
|
return (req, res, next) => {
|
|
173
204
|
const auth = getAuth(req);
|
|
174
|
-
|
|
175
|
-
const
|
|
205
|
+
if (sysAdminBypass && isSysAdmin(auth, sysAdminRole)) return next();
|
|
206
|
+
const allow = permsSet(auth.permissions);
|
|
207
|
+
const deny = permsSet(auth.denied_permissions);
|
|
176
208
|
for (const p of perms) {
|
|
177
209
|
if (deny.has(p)) {
|
|
178
|
-
return sendError(req, res, 403, "FORBIDDEN", `Denied: ${p}
|
|
210
|
+
return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, {
|
|
211
|
+
denied: p
|
|
212
|
+
});
|
|
179
213
|
}
|
|
180
214
|
}
|
|
181
215
|
const missing = perms.filter((p) => !allow.has(p));
|
|
182
216
|
if (missing.length) {
|
|
183
|
-
return sendError(req, res, 403, "FORBIDDEN", "Missing permissions", {
|
|
217
|
+
return sendError(req, res, 403, "FORBIDDEN", "Missing permissions", {
|
|
218
|
+
missing,
|
|
219
|
+
mode: "ALL"
|
|
220
|
+
});
|
|
184
221
|
}
|
|
185
222
|
return next();
|
|
186
223
|
};
|
|
187
224
|
}
|
|
188
|
-
function
|
|
225
|
+
function requireAnyPermission(perms, options) {
|
|
226
|
+
const sysAdminBypass = options?.sysAdminBypass !== false;
|
|
227
|
+
const sysAdminRole = options?.sysAdminRole || "SYS_ADMIN";
|
|
189
228
|
return (req, res, next) => {
|
|
190
229
|
const auth = getAuth(req);
|
|
191
|
-
|
|
230
|
+
if (sysAdminBypass && isSysAdmin(auth, sysAdminRole)) return next();
|
|
231
|
+
const allow = permsSet(auth.permissions);
|
|
232
|
+
const deny = permsSet(auth.denied_permissions);
|
|
233
|
+
for (const p of perms) {
|
|
234
|
+
if (deny.has(p)) {
|
|
235
|
+
return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, {
|
|
236
|
+
denied: p
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
const ok = perms.some((p) => allow.has(p));
|
|
241
|
+
if (!ok) {
|
|
242
|
+
return sendError(req, res, 403, "FORBIDDEN", "Permission denied", {
|
|
243
|
+
required: perms,
|
|
244
|
+
mode: "ANY"
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
return next();
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
function requireRoles(roles, options) {
|
|
251
|
+
const sysAdminBypass = options?.sysAdminBypass !== false;
|
|
252
|
+
const sysAdminRole = options?.sysAdminRole || "SYS_ADMIN";
|
|
253
|
+
return (req, res, next) => {
|
|
254
|
+
const auth = getAuth(req);
|
|
255
|
+
if (sysAdminBypass && isSysAdmin(auth, sysAdminRole)) return next();
|
|
256
|
+
const have = rolesSet(auth);
|
|
192
257
|
if (!roles.some((r) => have.has(r))) {
|
|
193
|
-
return sendError(req, res, 403, "FORBIDDEN", "Role not allowed", {
|
|
258
|
+
return sendError(req, res, 403, "FORBIDDEN", "Role not allowed", {
|
|
259
|
+
required: roles,
|
|
260
|
+
mode: "ANY"
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
return next();
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
function requireRolesOrAnyPermission(roles, perms, options) {
|
|
267
|
+
const sysAdminBypass = options?.sysAdminBypass !== false;
|
|
268
|
+
const sysAdminRole = options?.sysAdminRole || "SYS_ADMIN";
|
|
269
|
+
return (req, res, next) => {
|
|
270
|
+
const auth = getAuth(req);
|
|
271
|
+
if (sysAdminBypass && isSysAdmin(auth, sysAdminRole)) return next();
|
|
272
|
+
const haveRoles = rolesSet(auth);
|
|
273
|
+
const allow = permsSet(auth.permissions);
|
|
274
|
+
const deny = permsSet(auth.denied_permissions);
|
|
275
|
+
for (const p of perms) {
|
|
276
|
+
if (deny.has(p)) {
|
|
277
|
+
return sendError(req, res, 403, "FORBIDDEN", `Denied permission: ${p}`, {
|
|
278
|
+
denied: p
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
const okRole = roles.some((r) => haveRoles.has(r));
|
|
283
|
+
const okPerm = perms.some((p) => allow.has(p));
|
|
284
|
+
if (!okRole && !okPerm) {
|
|
285
|
+
return sendError(req, res, 403, "FORBIDDEN", "Access denied", {
|
|
286
|
+
roles,
|
|
287
|
+
permissions: perms,
|
|
288
|
+
mode: "ROLES_OR_PERMS_ANY"
|
|
289
|
+
});
|
|
194
290
|
}
|
|
195
291
|
return next();
|
|
196
292
|
};
|
|
@@ -200,9 +296,11 @@ function requireRoles(...roles) {
|
|
|
200
296
|
internalAuth,
|
|
201
297
|
parseHeaders,
|
|
202
298
|
requestId,
|
|
299
|
+
requireAnyPermission,
|
|
203
300
|
requireAuthContext,
|
|
204
301
|
requirePermissions,
|
|
205
302
|
requireRoles,
|
|
303
|
+
requireRolesOrAnyPermission,
|
|
206
304
|
sendError,
|
|
207
305
|
sendOk
|
|
208
306
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/middlewares/index.ts","../../src/middlewares/requestId.ts","../../src/headers/constants.ts","../../src/headers/parse.ts","../../src/middlewares/parseHeaders.ts","../../src/middlewares/internalAuth.ts","../../src/middlewares/respond.ts","../../src/middlewares/autorization.ts"],"sourcesContent":["export {default as requestId} from \"./requestId\";\nexport {default as parseHeaders} from \"./parseHeaders\";\nexport {default as internalAuth} from \"./internalAuth\";\nexport * from \"./autorization\";\nexport * from \"./respond\";\n","// middlewares/requestId.ts\nimport type {Request, Response, NextFunction} from \"express\";\nimport {randomUUID, randomBytes} from \"crypto\";\n\nexport const REQUEST_ID_HEADER = \"x-request-id\";\nexport const REQUEST_ID_HEADER_ALT = \"x-requestid\";\nexport const RESPONSE_REQUEST_ID_HEADER = \"X-Request-Id\";\n\n// Si quieres IDs más cortos (opcional). Por defecto usamos UUID.\nfunction nanoidLike(len = 21) {\n return randomBytes(16).toString(\"base64url\").slice(0, len);\n}\n\nexport default function requestId(req: Request, res: Response, next: NextFunction) {\n const headerId = (req.headers[REQUEST_ID_HEADER] || req.headers[REQUEST_ID_HEADER_ALT]) as\n | string\n | undefined;\n\n // ✅ estándar único: usa UUID (o cambia a nanoidLike() si prefieres corto)\n const id = headerId?.trim() || randomUUID();\n\n // ✅ estándar único (no legacy)\n (req as any).requestId = id;\n res.locals.requestId = id;\n\n // ✅ respuesta\n res.setHeader(RESPONSE_REQUEST_ID_HEADER, id);\n\n next();\n}\n","export const HEADER_REQUEST_ID = \"x-request-id\";\n\nexport const HEADER_COMPANY_UID = \"x-company\";\nexport const HEADER_BRANCH_UID = \"x-branch\";\nexport const HEADER_EMPLOYEE_UID = \"x-employee-uid\";\n\nexport const HEADER_INTERNAL_API_KEY = \"x-internal-api-key\";\nexport const HEADER_AUTHORIZATION = \"authorization\";\n","import {\n HEADER_BRANCH_UID,\n HEADER_COMPANY_UID,\n HEADER_EMPLOYEE_UID,\n HEADER_REQUEST_ID,\n} from \"./constants\";\n\nexport type RequestContext = {\n requestId?: string | null;\n\n company_uid?: string | null;\n branch_uid?: string | null;\n employee_uid?: string | null;\n};\n\nfunction asString(v: unknown): string | null {\n if (typeof v !== \"string\") return null;\n const s = v.trim();\n return s ? s : null;\n}\n\n/**\n * ✅ NO-LEGACY:\n * - x-company: <UID>\n * - x-branch: <UID>\n * - x-employee-uid: <UID> (opcional)\n * - x-request-id: string (opcional)\n *\n * 🚫 No JSON, no _id, no objetos.\n */\nexport function getRequestContextFromHeaders(headers: Record<string, any>): RequestContext {\n return {\n requestId: asString(headers[HEADER_REQUEST_ID]) ?? null,\n company_uid: asString(headers[HEADER_COMPANY_UID]) ?? null,\n branch_uid: asString(headers[HEADER_BRANCH_UID]) ?? null,\n employee_uid: asString(headers[HEADER_EMPLOYEE_UID]) ?? null,\n };\n}\n","import type {Request, Response, NextFunction} from \"express\";\nimport {getRequestContextFromHeaders} from \"../headers\";\n\n/**\n * ✅ NO-LEGACY:\n * - solo setea UIDs\n * - no crea objetos company/branch\n * - no copia provider\n */\nexport default function parseHeaders(req: Request, _res: Response, next: NextFunction) {\n const context = getRequestContextFromHeaders(req.headers as any);\n\n (req as any).context = context;\n\n const auth: any = (req as any).auth ?? ((req as any).auth = {});\n if (context.company_uid) auth.company_uid = context.company_uid;\n if (context.branch_uid) auth.branch_uid = context.branch_uid;\n if (context.employee_uid) auth.employee_uid = context.employee_uid;\n\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 AuthShape = {\n roles?: string[];\n permissions?: string[];\n denied_permissions?: string[];\n};\n\nfunction getAuth(req: Request): AuthShape {\n return ((req as any).auth ?? {}) as AuthShape;\n}\n\n/**\n * 401 si no existe req.auth (contexto auth).\n * Útil para proteger rutas internas 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 * Requiere TODOS los permisos indicados.\n * Regla: denied_permissions siempre gana sobre permissions.\n */\nexport function requirePermissions(...perms: string[]) {\n return (req: Request, res: Response, next: NextFunction) => {\n const auth = getAuth(req);\n\n const allow = new Set<string>(auth.permissions ?? []);\n const deny = new Set<string>(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: ${p}`);\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\", {missing});\n }\n\n return next();\n };\n}\n\n/**\n * Requiere al menos 1 de los roles indicados.\n */\nexport function requireRoles(...roles: string[]) {\n return (req: Request, res: Response, next: NextFunction) => {\n const auth = getAuth(req);\n const have = new Set<string>(auth.roles ?? []);\n\n if (!roles.some((r) => have.has(r))) {\n return sendError(req, res, 403, \"FORBIDDEN\", \"Role not allowed\", {required: roles});\n }\n\n return next();\n };\n}\n"],"mappings":"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","names":["import_crypto","fs","crypto"]}
|
|
1
|
+
{"version":3,"sources":["../../src/middlewares/index.ts","../../src/headers/constants.ts","../../src/headers/parse.ts","../../src/middlewares/parseHeaders.ts","../../src/middlewares/requestId.ts","../../src/middlewares/internalAuth.ts","../../src/middlewares/respond.ts","../../src/middlewares/authorization.ts"],"sourcesContent":["// packages/sdk/src/middlewares/index.ts\nexport {default as parseHeaders} from \"./parseHeaders\";\nexport {default as requestId} from \"./requestId\";\nexport {default as internalAuth} from \"./internalAuth\";\nexport {sendOk, sendError} from \"./respond\";\n\n// authorization helpers\nexport * from \"./authorization\";\n","export const HEADER_REQUEST_ID = \"x-request-id\";\n\nexport const HEADER_COMPANY_UID = \"x-company\";\nexport const HEADER_BRANCH_UID = \"x-branch\";\nexport const HEADER_EMPLOYEE_UID = \"x-employee-uid\";\n\nexport const HEADER_INTERNAL_API_KEY = \"x-internal-api-key\";\nexport const HEADER_AUTHORIZATION = \"authorization\";\n","import {\n HEADER_BRANCH_UID,\n HEADER_COMPANY_UID,\n HEADER_EMPLOYEE_UID,\n HEADER_REQUEST_ID,\n} from \"./constants\";\n\nexport type RequestContext = {\n requestId?: string | null;\n company_uid?: string | null;\n branch_uid?: string | null;\n employee_uid?: string | null;\n};\n\nfunction normalizeHeaderValue(v: unknown): string | null {\n if (typeof v !== \"string\") return null;\n const s = v.trim();\n if (!s) return null;\n\n // ✅ NO-LEGACY: bloquea JSON en headers\n if (s.startsWith(\"{\") || s.startsWith(\"[\") || s.includes('\"')) return null;\n\n // Evitar valores demasiado cortos (basura)\n if (s.length < 6) return null;\n\n return s;\n}\n\n/**\n * Lee header aunque venga en mayúsculas/minúsculas (Express suele bajar a lower-case).\n */\nfunction h(headers: Record<string, any>, key: string): unknown {\n return headers[key] ?? headers[key.toLowerCase()] ?? headers[key.toUpperCase()];\n}\n\n/**\n * ✅ NO-LEGACY:\n * - x-company: <UID>\n * - x-branch: <UID>\n * - x-employee-uid: <UID> (opcional; NO reemplaza JWT)\n * - x-request-id: string (opcional)\n */\nexport function getRequestContextFromHeaders(headers: Record<string, any>): RequestContext {\n return {\n requestId: normalizeHeaderValue(h(headers, HEADER_REQUEST_ID)) ?? null,\n company_uid: normalizeHeaderValue(h(headers, HEADER_COMPANY_UID)) ?? null,\n branch_uid: normalizeHeaderValue(h(headers, HEADER_BRANCH_UID)) ?? null,\n employee_uid: normalizeHeaderValue(h(headers, HEADER_EMPLOYEE_UID)) ?? null,\n };\n}\n","// 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","// middlewares/requestId.ts\nimport type {Request, Response, NextFunction} from \"express\";\nimport {randomUUID, randomBytes} from \"crypto\";\n\nexport const REQUEST_ID_HEADER = \"x-request-id\";\nexport const REQUEST_ID_HEADER_ALT = \"x-requestid\";\nexport const RESPONSE_REQUEST_ID_HEADER = \"X-Request-Id\";\n\n// Si quieres IDs más cortos (opcional). Por defecto usamos UUID.\nfunction nanoidLike(len = 21) {\n return randomBytes(16).toString(\"base64url\").slice(0, len);\n}\n\nexport default function requestId(req: Request, res: Response, next: NextFunction) {\n const headerId = (req.headers[REQUEST_ID_HEADER] || req.headers[REQUEST_ID_HEADER_ALT]) as\n | string\n | undefined;\n\n // ✅ estándar único: usa UUID (o cambia a nanoidLike() si prefieres corto)\n const id = headerId?.trim() || randomUUID();\n\n // ✅ estándar único (no legacy)\n (req as any).requestId = id;\n res.locals.requestId = id;\n\n // ✅ respuesta\n res.setHeader(RESPONSE_REQUEST_ID_HEADER, id);\n\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"],"mappings":"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","names":["import_crypto","fs","crypto"]}
|
|
@@ -1,33 +1,62 @@
|
|
|
1
1
|
import { Request, Response, NextFunction } from 'express';
|
|
2
2
|
|
|
3
|
-
declare function requestId(req: Request, res: Response, next: NextFunction): void;
|
|
4
|
-
|
|
5
3
|
/**
|
|
6
|
-
* ✅ NO-LEGACY:
|
|
7
|
-
* -
|
|
8
|
-
* -
|
|
9
|
-
* -
|
|
4
|
+
* ✅ NO-LEGACY / ESTÁNDAR:
|
|
5
|
+
* - Lee SOLO x-company y x-branch (UIDs planos)
|
|
6
|
+
* - Setea req.context = { company_uid, branch_uid }
|
|
7
|
+
* - NO toca req.auth (auth lo setea authentication/requireAuth)
|
|
10
8
|
*/
|
|
11
9
|
declare function parseHeaders(req: Request, _res: Response, next: NextFunction): void;
|
|
12
10
|
|
|
11
|
+
declare function requestId(req: Request, res: Response, next: NextFunction): void;
|
|
12
|
+
|
|
13
13
|
declare function internalAuth(req: Request, res: Response, next: NextFunction): void | Response<any, Record<string, any>>;
|
|
14
14
|
|
|
15
|
+
declare function sendOk<T>(_req: Request, res: Response, data: T, statusCode?: number): Response<any, Record<string, any>>;
|
|
16
|
+
declare function sendError(_req: Request, res: Response, statusCode: number, code: string, message: string, details?: any): Response<any, Record<string, any>>;
|
|
17
|
+
|
|
15
18
|
/**
|
|
16
19
|
* 401 si no existe req.auth (contexto auth).
|
|
17
|
-
* Útil para proteger rutas
|
|
20
|
+
* Útil para proteger rutas donde SIEMPRE debe existir auth.
|
|
18
21
|
*/
|
|
19
22
|
declare function requireAuthContext(): (req: Request, res: Response, next: NextFunction) => void | Response<any, Record<string, any>>;
|
|
20
23
|
/**
|
|
21
24
|
* Requiere TODOS los permisos indicados.
|
|
22
25
|
* Regla: denied_permissions siempre gana sobre permissions.
|
|
26
|
+
*
|
|
27
|
+
* options:
|
|
28
|
+
* - sysAdminBypass: default true
|
|
29
|
+
* - sysAdminRole: default "SYS_ADMIN"
|
|
23
30
|
*/
|
|
24
|
-
declare function requirePermissions(
|
|
31
|
+
declare function requirePermissions(perms: string[], options?: {
|
|
32
|
+
sysAdminBypass?: boolean;
|
|
33
|
+
sysAdminRole?: string;
|
|
34
|
+
}): (req: Request, res: Response, next: NextFunction) => void | Response<any, Record<string, any>>;
|
|
25
35
|
/**
|
|
26
|
-
* Requiere
|
|
36
|
+
* Requiere AL MENOS 1 permiso de la lista (ANY/OR).
|
|
37
|
+
* Regla: denied_permissions siempre gana.
|
|
27
38
|
*/
|
|
28
|
-
declare function
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
39
|
+
declare function requireAnyPermission(perms: string[], options?: {
|
|
40
|
+
sysAdminBypass?: boolean;
|
|
41
|
+
sysAdminRole?: string;
|
|
42
|
+
}): (req: Request, res: Response, next: NextFunction) => void | Response<any, Record<string, any>>;
|
|
43
|
+
/**
|
|
44
|
+
* Requiere al menos 1 rol (ANY/OR).
|
|
45
|
+
* options:
|
|
46
|
+
* - sysAdminBypass: default true
|
|
47
|
+
* - sysAdminRole: default "SYS_ADMIN"
|
|
48
|
+
*/
|
|
49
|
+
declare function requireRoles(roles: string[], options?: {
|
|
50
|
+
sysAdminBypass?: boolean;
|
|
51
|
+
sysAdminRole?: string;
|
|
52
|
+
}): (req: Request, res: Response, next: NextFunction) => void | Response<any, Record<string, any>>;
|
|
53
|
+
/**
|
|
54
|
+
* Requiere (roles ANY) OR (permissions ANY).
|
|
55
|
+
* deny_permissions siempre gana sobre permissions.
|
|
56
|
+
*/
|
|
57
|
+
declare function requireRolesOrAnyPermission(roles: string[], perms: string[], options?: {
|
|
58
|
+
sysAdminBypass?: boolean;
|
|
59
|
+
sysAdminRole?: string;
|
|
60
|
+
}): (req: Request, res: Response, next: NextFunction) => void | Response<any, Record<string, any>>;
|
|
32
61
|
|
|
33
|
-
export { internalAuth, parseHeaders, requestId, requireAuthContext, requirePermissions, requireRoles, sendError, sendOk };
|
|
62
|
+
export { internalAuth, parseHeaders, requestId, requireAnyPermission, requireAuthContext, requirePermissions, requireRoles, requireRolesOrAnyPermission, sendError, sendOk };
|
|
@@ -1,33 +1,62 @@
|
|
|
1
1
|
import { Request, Response, NextFunction } from 'express';
|
|
2
2
|
|
|
3
|
-
declare function requestId(req: Request, res: Response, next: NextFunction): void;
|
|
4
|
-
|
|
5
3
|
/**
|
|
6
|
-
* ✅ NO-LEGACY:
|
|
7
|
-
* -
|
|
8
|
-
* -
|
|
9
|
-
* -
|
|
4
|
+
* ✅ NO-LEGACY / ESTÁNDAR:
|
|
5
|
+
* - Lee SOLO x-company y x-branch (UIDs planos)
|
|
6
|
+
* - Setea req.context = { company_uid, branch_uid }
|
|
7
|
+
* - NO toca req.auth (auth lo setea authentication/requireAuth)
|
|
10
8
|
*/
|
|
11
9
|
declare function parseHeaders(req: Request, _res: Response, next: NextFunction): void;
|
|
12
10
|
|
|
11
|
+
declare function requestId(req: Request, res: Response, next: NextFunction): void;
|
|
12
|
+
|
|
13
13
|
declare function internalAuth(req: Request, res: Response, next: NextFunction): void | Response<any, Record<string, any>>;
|
|
14
14
|
|
|
15
|
+
declare function sendOk<T>(_req: Request, res: Response, data: T, statusCode?: number): Response<any, Record<string, any>>;
|
|
16
|
+
declare function sendError(_req: Request, res: Response, statusCode: number, code: string, message: string, details?: any): Response<any, Record<string, any>>;
|
|
17
|
+
|
|
15
18
|
/**
|
|
16
19
|
* 401 si no existe req.auth (contexto auth).
|
|
17
|
-
* Útil para proteger rutas
|
|
20
|
+
* Útil para proteger rutas donde SIEMPRE debe existir auth.
|
|
18
21
|
*/
|
|
19
22
|
declare function requireAuthContext(): (req: Request, res: Response, next: NextFunction) => void | Response<any, Record<string, any>>;
|
|
20
23
|
/**
|
|
21
24
|
* Requiere TODOS los permisos indicados.
|
|
22
25
|
* Regla: denied_permissions siempre gana sobre permissions.
|
|
26
|
+
*
|
|
27
|
+
* options:
|
|
28
|
+
* - sysAdminBypass: default true
|
|
29
|
+
* - sysAdminRole: default "SYS_ADMIN"
|
|
23
30
|
*/
|
|
24
|
-
declare function requirePermissions(
|
|
31
|
+
declare function requirePermissions(perms: string[], options?: {
|
|
32
|
+
sysAdminBypass?: boolean;
|
|
33
|
+
sysAdminRole?: string;
|
|
34
|
+
}): (req: Request, res: Response, next: NextFunction) => void | Response<any, Record<string, any>>;
|
|
25
35
|
/**
|
|
26
|
-
* Requiere
|
|
36
|
+
* Requiere AL MENOS 1 permiso de la lista (ANY/OR).
|
|
37
|
+
* Regla: denied_permissions siempre gana.
|
|
27
38
|
*/
|
|
28
|
-
declare function
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
39
|
+
declare function requireAnyPermission(perms: string[], options?: {
|
|
40
|
+
sysAdminBypass?: boolean;
|
|
41
|
+
sysAdminRole?: string;
|
|
42
|
+
}): (req: Request, res: Response, next: NextFunction) => void | Response<any, Record<string, any>>;
|
|
43
|
+
/**
|
|
44
|
+
* Requiere al menos 1 rol (ANY/OR).
|
|
45
|
+
* options:
|
|
46
|
+
* - sysAdminBypass: default true
|
|
47
|
+
* - sysAdminRole: default "SYS_ADMIN"
|
|
48
|
+
*/
|
|
49
|
+
declare function requireRoles(roles: string[], options?: {
|
|
50
|
+
sysAdminBypass?: boolean;
|
|
51
|
+
sysAdminRole?: string;
|
|
52
|
+
}): (req: Request, res: Response, next: NextFunction) => void | Response<any, Record<string, any>>;
|
|
53
|
+
/**
|
|
54
|
+
* Requiere (roles ANY) OR (permissions ANY).
|
|
55
|
+
* deny_permissions siempre gana sobre permissions.
|
|
56
|
+
*/
|
|
57
|
+
declare function requireRolesOrAnyPermission(roles: string[], perms: string[], options?: {
|
|
58
|
+
sysAdminBypass?: boolean;
|
|
59
|
+
sysAdminRole?: string;
|
|
60
|
+
}): (req: Request, res: Response, next: NextFunction) => void | Response<any, Record<string, any>>;
|
|
32
61
|
|
|
33
|
-
export { internalAuth, parseHeaders, requestId, requireAuthContext, requirePermissions, requireRoles, sendError, sendOk };
|
|
62
|
+
export { internalAuth, parseHeaders, requestId, requireAnyPermission, requireAuthContext, requirePermissions, requireRoles, requireRolesOrAnyPermission, sendError, sendOk };
|
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
import {
|
|
2
2
|
internalAuth,
|
|
3
3
|
parseHeaders,
|
|
4
|
-
|
|
4
|
+
requireAnyPermission,
|
|
5
5
|
requireAuthContext,
|
|
6
6
|
requirePermissions,
|
|
7
7
|
requireRoles,
|
|
8
|
+
requireRolesOrAnyPermission,
|
|
8
9
|
sendError,
|
|
9
10
|
sendOk
|
|
10
|
-
} from "../chunk-
|
|
11
|
-
import
|
|
12
|
-
|
|
11
|
+
} from "../chunk-JXOLNJ7J.js";
|
|
12
|
+
import {
|
|
13
|
+
requestId
|
|
14
|
+
} from "../chunk-KJ64O2EG.js";
|
|
15
|
+
import "../chunk-P2U3MT2E.js";
|
|
13
16
|
export {
|
|
14
17
|
internalAuth,
|
|
15
18
|
parseHeaders,
|
|
16
19
|
requestId,
|
|
20
|
+
requireAnyPermission,
|
|
17
21
|
requireAuthContext,
|
|
18
22
|
requirePermissions,
|
|
19
23
|
requireRoles,
|
|
24
|
+
requireRolesOrAnyPermission,
|
|
20
25
|
sendError,
|
|
21
26
|
sendOk
|
|
22
27
|
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
type RequestContext = {
|
|
2
|
+
requestId?: string | null;
|
|
3
|
+
company_uid?: string | null;
|
|
4
|
+
branch_uid?: string | null;
|
|
5
|
+
employee_uid?: string | null;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* ✅ NO-LEGACY:
|
|
9
|
+
* - x-company: <UID>
|
|
10
|
+
* - x-branch: <UID>
|
|
11
|
+
* - x-employee-uid: <UID> (opcional; NO reemplaza JWT)
|
|
12
|
+
* - x-request-id: string (opcional)
|
|
13
|
+
*/
|
|
14
|
+
declare function getRequestContextFromHeaders(headers: Record<string, any>): RequestContext;
|
|
15
|
+
|
|
16
|
+
export { type RequestContext as R, getRequestContextFromHeaders as g };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
type RequestContext = {
|
|
2
|
+
requestId?: string | null;
|
|
3
|
+
company_uid?: string | null;
|
|
4
|
+
branch_uid?: string | null;
|
|
5
|
+
employee_uid?: string | null;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* ✅ NO-LEGACY:
|
|
9
|
+
* - x-company: <UID>
|
|
10
|
+
* - x-branch: <UID>
|
|
11
|
+
* - x-employee-uid: <UID> (opcional; NO reemplaza JWT)
|
|
12
|
+
* - x-request-id: string (opcional)
|
|
13
|
+
*/
|
|
14
|
+
declare function getRequestContextFromHeaders(headers: Record<string, any>): RequestContext;
|
|
15
|
+
|
|
16
|
+
export { type RequestContext as R, getRequestContextFromHeaders as g };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Request } from 'express';
|
|
2
|
+
|
|
3
|
+
type AuthSubject = "employee" | "customer";
|
|
4
|
+
type TokenType = "backend";
|
|
5
|
+
type AuthSession = {
|
|
6
|
+
jti?: string;
|
|
7
|
+
device_id?: string;
|
|
8
|
+
expires_at?: number;
|
|
9
|
+
};
|
|
10
|
+
type AuthContext = {
|
|
11
|
+
tokenType: TokenType;
|
|
12
|
+
subject: AuthSubject;
|
|
13
|
+
employee?: any;
|
|
14
|
+
customer?: any;
|
|
15
|
+
company_uid?: string;
|
|
16
|
+
branch_uid?: string;
|
|
17
|
+
companies?: any[];
|
|
18
|
+
company?: any;
|
|
19
|
+
branch?: any;
|
|
20
|
+
roles?: string[];
|
|
21
|
+
permissions?: string[];
|
|
22
|
+
denied_permissions?: string[];
|
|
23
|
+
session?: AuthSession;
|
|
24
|
+
firebase?: any;
|
|
25
|
+
};
|
|
26
|
+
type HydrateInput = {
|
|
27
|
+
decoded: any;
|
|
28
|
+
req: Request;
|
|
29
|
+
subject: AuthSubject;
|
|
30
|
+
company_uid: string | null;
|
|
31
|
+
branch_uid: string | null;
|
|
32
|
+
};
|
|
33
|
+
type HydrateResult = Partial<Pick<AuthContext, "employee" | "customer" | "companies" | "company" | "branch" | "roles" | "permissions" | "denied_permissions">>;
|
|
34
|
+
type Hydrator = (input: HydrateInput) => Promise<HydrateResult> | HydrateResult;
|
|
35
|
+
type AuthMiddlewareOptions = {
|
|
36
|
+
subject: AuthSubject;
|
|
37
|
+
/**
|
|
38
|
+
* ✅ Si true, exige que el sujeto (employee/customer) exista tras hydrate.
|
|
39
|
+
* Default: true
|
|
40
|
+
*/
|
|
41
|
+
requireSubject?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Si true, permite fallback a Firebase idToken.
|
|
44
|
+
* Default: false
|
|
45
|
+
*/
|
|
46
|
+
allowFirebaseIdToken?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* ✅ OBLIGATORIO para evitar acoplamientos:
|
|
49
|
+
* el micro decide cómo hidratar (DB local / AuthClient / etc).
|
|
50
|
+
*/
|
|
51
|
+
hydrate: Hydrator;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export type { AuthContext as A, HydrateInput as H, TokenType as T, AuthMiddlewareOptions as a, AuthSession as b, AuthSubject as c, HydrateResult as d, Hydrator as e };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Request } from 'express';
|
|
2
|
+
|
|
3
|
+
type AuthSubject = "employee" | "customer";
|
|
4
|
+
type TokenType = "backend";
|
|
5
|
+
type AuthSession = {
|
|
6
|
+
jti?: string;
|
|
7
|
+
device_id?: string;
|
|
8
|
+
expires_at?: number;
|
|
9
|
+
};
|
|
10
|
+
type AuthContext = {
|
|
11
|
+
tokenType: TokenType;
|
|
12
|
+
subject: AuthSubject;
|
|
13
|
+
employee?: any;
|
|
14
|
+
customer?: any;
|
|
15
|
+
company_uid?: string;
|
|
16
|
+
branch_uid?: string;
|
|
17
|
+
companies?: any[];
|
|
18
|
+
company?: any;
|
|
19
|
+
branch?: any;
|
|
20
|
+
roles?: string[];
|
|
21
|
+
permissions?: string[];
|
|
22
|
+
denied_permissions?: string[];
|
|
23
|
+
session?: AuthSession;
|
|
24
|
+
firebase?: any;
|
|
25
|
+
};
|
|
26
|
+
type HydrateInput = {
|
|
27
|
+
decoded: any;
|
|
28
|
+
req: Request;
|
|
29
|
+
subject: AuthSubject;
|
|
30
|
+
company_uid: string | null;
|
|
31
|
+
branch_uid: string | null;
|
|
32
|
+
};
|
|
33
|
+
type HydrateResult = Partial<Pick<AuthContext, "employee" | "customer" | "companies" | "company" | "branch" | "roles" | "permissions" | "denied_permissions">>;
|
|
34
|
+
type Hydrator = (input: HydrateInput) => Promise<HydrateResult> | HydrateResult;
|
|
35
|
+
type AuthMiddlewareOptions = {
|
|
36
|
+
subject: AuthSubject;
|
|
37
|
+
/**
|
|
38
|
+
* ✅ Si true, exige que el sujeto (employee/customer) exista tras hydrate.
|
|
39
|
+
* Default: true
|
|
40
|
+
*/
|
|
41
|
+
requireSubject?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Si true, permite fallback a Firebase idToken.
|
|
44
|
+
* Default: false
|
|
45
|
+
*/
|
|
46
|
+
allowFirebaseIdToken?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* ✅ OBLIGATORIO para evitar acoplamientos:
|
|
49
|
+
* el micro decide cómo hidratar (DB local / AuthClient / etc).
|
|
50
|
+
*/
|
|
51
|
+
hydrate: Hydrator;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export type { AuthContext as A, HydrateInput as H, TokenType as T, AuthMiddlewareOptions as a, AuthSession as b, AuthSubject as c, HydrateResult as d, Hydrator as e };
|