@culturefy/shared 1.0.63 → 1.0.64
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/build/cjs/enums/secretKeys.enum.js +0 -1
- package/build/cjs/enums/secretKeys.enum.js.map +1 -1
- package/build/cjs/interfaces/user.js.map +1 -1
- package/build/cjs/middlewares/verify-middleware.js +72 -18
- package/build/cjs/middlewares/verify-middleware.js.map +1 -1
- package/build/cjs/repositories/multi-tenant.repository.js +24 -11
- package/build/cjs/repositories/multi-tenant.repository.js.map +1 -1
- package/build/cjs/repositories/tenant-base.repository.js +7 -1
- package/build/cjs/repositories/tenant-base.repository.js.map +1 -1
- package/build/cjs/utils/initializers.js +11 -5
- package/build/cjs/utils/initializers.js.map +1 -1
- package/build/esm/enums/secretKeys.enum.js +0 -1
- package/build/esm/enums/secretKeys.enum.js.map +1 -1
- package/build/esm/interfaces/user.js.map +1 -1
- package/build/esm/middlewares/verify-middleware.js +74 -20
- package/build/esm/middlewares/verify-middleware.js.map +1 -1
- package/build/esm/repositories/multi-tenant.repository.js +24 -11
- package/build/esm/repositories/multi-tenant.repository.js.map +1 -1
- package/build/esm/repositories/tenant-base.repository.js +7 -1
- package/build/esm/repositories/tenant-base.repository.js.map +1 -1
- package/build/esm/utils/initializers.js +11 -5
- package/build/esm/utils/initializers.js.map +1 -1
- package/build/src/enums/secretKeys.enum.d.ts +0 -1
- package/build/src/enums/secretKeys.enum.js +0 -1
- package/build/src/enums/secretKeys.enum.js.map +1 -1
- package/build/src/middlewares/verify-middleware.js +79 -36
- package/build/src/middlewares/verify-middleware.js.map +1 -1
- package/build/src/repositories/multi-tenant.repository.d.ts +1 -0
- package/build/src/repositories/multi-tenant.repository.js +24 -11
- package/build/src/repositories/multi-tenant.repository.js.map +1 -1
- package/build/src/repositories/tenant-base.repository.d.ts +1 -0
- package/build/src/repositories/tenant-base.repository.js +18 -0
- package/build/src/repositories/tenant-base.repository.js.map +1 -1
- package/build/src/utils/initializers.d.ts +1 -0
- package/build/src/utils/initializers.js +11 -5
- package/build/src/utils/initializers.js.map +1 -1
- package/package.json +1 -1
|
@@ -17,7 +17,6 @@ let AzureSecretKeysEnum = exports.AzureSecretKeysEnum = /*#__PURE__*/function (A
|
|
|
17
17
|
// in-use,
|
|
18
18
|
AzureSecretKeysEnum["DB_CONNECTING_STRING_AUTH"] = "DB-CONNECTION-STRING-AUTH";
|
|
19
19
|
AzureSecretKeysEnum["DB_CONNECTING_STRING_USER"] = "DB-CONNECTION-STRING-USER";
|
|
20
|
-
AzureSecretKeysEnum["DB_CONNECTING_STRING_TENANT_BRIDGE"] = "DB-Connecting-String-Tenant-Bridge";
|
|
21
20
|
AzureSecretKeysEnum["DB_CONNECTING_STRING_PAYMENT"] = "DB-CONNECTION-STRING-PAYMENT";
|
|
22
21
|
AzureSecretKeysEnum["DB_CONNECTING_STRING_CORE"] = "DB-CONNECTION-STRING-CORE";
|
|
23
22
|
AzureSecretKeysEnum["DB_CONNECTING_STRING_BILLING"] = "DB-CONNECTION-STRING-BILLING";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secretKeys.enum.js","names":["AzureSecretKeysEnum","exports"],"sources":["../../../src/enums/secretKeys.enum.ts"],"sourcesContent":["// Enum for secret keys\nexport enum AzureSecretKeysEnum {\n KEYCLOAK_ADMIN_CLIENT_SECRET = \"KEYCLOAK-ADMIN-CLIENT-SECRET\",\n KEYCLOAK_ADMIN_CLIENT_ID = \"KEYCLOAK-ADMIN-CLIENT-ID\",\n KEYCLOAK_BASE_URL = \"KEYCLOAK-BASE-URL\",\n STRIPE_PAYMENT_WEBHOOK_SECRET_KEY = \"Stripe-payment-webhook-secret-key\", // in-use\n STRIPE_PRODUCT_WEBHOOK_SECRET = \"Stripe-product-webhook-secret-key\", // in-use\n STRIPE_PRICE_WEBHOOK_SECRET = \"Stripe-price-webhook-secret-key\", // in-use\n EMAIL_SERVICE_URL = \"Email-Service-Url\", // in-use,\n DB_CONNECTING_STRING_AUTH = \"DB-CONNECTION-STRING-AUTH\",\n DB_CONNECTING_STRING_USER = \"DB-CONNECTION-STRING-USER\",\n
|
|
1
|
+
{"version":3,"file":"secretKeys.enum.js","names":["AzureSecretKeysEnum","exports"],"sources":["../../../src/enums/secretKeys.enum.ts"],"sourcesContent":["// Enum for secret keys\nexport enum AzureSecretKeysEnum {\n KEYCLOAK_ADMIN_CLIENT_SECRET = \"KEYCLOAK-ADMIN-CLIENT-SECRET\",\n KEYCLOAK_ADMIN_CLIENT_ID = \"KEYCLOAK-ADMIN-CLIENT-ID\",\n KEYCLOAK_BASE_URL = \"KEYCLOAK-BASE-URL\",\n STRIPE_PAYMENT_WEBHOOK_SECRET_KEY = \"Stripe-payment-webhook-secret-key\", // in-use\n STRIPE_PRODUCT_WEBHOOK_SECRET = \"Stripe-product-webhook-secret-key\", // in-use\n STRIPE_PRICE_WEBHOOK_SECRET = \"Stripe-price-webhook-secret-key\", // in-use\n EMAIL_SERVICE_URL = \"Email-Service-Url\", // in-use,\n DB_CONNECTING_STRING_AUTH = \"DB-CONNECTION-STRING-AUTH\",\n DB_CONNECTING_STRING_USER = \"DB-CONNECTION-STRING-USER\",\n DB_CONNECTING_STRING_PAYMENT = \"DB-CONNECTION-STRING-PAYMENT\",\n DB_CONNECTING_STRING_CORE = \"DB-CONNECTION-STRING-CORE\",\n DB_CONNECTING_STRING_BILLING = \"DB-CONNECTION-STRING-BILLING\",\n DB_CONNECTING_STRING_STAGING = \"DB-CONNECTION-STRING-STAGING\",\n DB_CONNECTING_STRING_BNT_DEV = \"DB-CONNECTION-STRING-BNT-DEV\",\n DB_CONNECTION_STRING_TENANT_BRIDGE = \"DB-CONNECTION-STRING-TENANT-BRIDGE\",\n SERVICE_BUS_CONNECTION_STRING = \"servicebus-connection-string\",\n STRIPE_CUSTOMER_SYNC_WEBHOOK_SECRET = \"stripe-customer-sync-webhook-secret-key\",\n STRIPE_INVOICE_SYNC_WEBHOOK_SECRET = \"stripe-invoice-sync-webhook-secret-key\",\n STRIPE_PRODUCT_SYNC_WEBHOOK_SECRET = \"stripe-product-sync-webhook-secret-key\",\n STRIPE_PRICE_SYNC_WEBHOOK_SECRET = \"stripe-price-sync-webhook-secret-key\",\n STRIPE_SECRET_KEY = \"Stripe-secret-key\",\n STRIPE_WEBHOOK_CUSTOMER_CREATED_SECRET_KEY = \"Stripe-Webhook-Customer-Created-Secret-Key\",\n STRIPE_SUBSCRIPTION_SYNC_WEBHOOK_SECRET = \"stripe-subscription-sync-webhook-secret-key\",\n FIREBASE_SERVICE_ACCOUNTS_VARIABLE = \"firebase_service_accounts_variable\",\n HMS_ACCESS_KEY=\"MEETING-HMS-ACCESS-KEY-APP-SECRET\",\n MEETING_ROOM_APP_SECRET=\"MEETING-ROOM-APP-SECRET\",\n BASE_DB_CLUSTER_CONNECTING_STRING_CHAT = \"BASE-DB-CLUSTER-CONNECTING-STRING-CHAT\",\n AUTH_SERVICE_AUTHENTICATION_URL = \"AUTH-SERVICE-AUTHENTICATION-URL\",\n GCP_PROJECT_ID=\"gcp-project-id\",\n PUBSUB_SERVICE_ACCOUNT_KEYS=\"pubsub-service-account-keys\",\n VAPI_TOKEN = \"vapi-token\",\n GITHUB_TOKEN = \"GITHUB-TOKEN\",\n GITHUB_WORKFLOW_URL = \"GITHUB-WORKFLOW-URL\",\n DB_CONNECTION_STRING_ENCRYPTION_KEY = \"DB-CONNECTION-STRING-ENCRYPTION-KEY\",\n}\n\n// AUTH-SERVICE-AUTHENTICATION-URL\n// https://culturefy-auth-staging.azurewebsites.net/api/verify\n\n// REFRESH-SESSION-URL"],"mappings":";;;;AAAA;AAAA,IACYA,mBAAmB,GAAAC,OAAA,CAAAD,mBAAA,0BAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAI4C;EAJ/DA,mBAAmB;EAKwC;EAL3DA,mBAAmB;EAMoC;EANvDA,mBAAmB;EAOY;EAP/BA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAA,OAAnBA,mBAAmB;AAAA,OAqC/B;AACA;AAEA","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user.js","names":[],"sources":["../../../src/interfaces/user.ts"],"sourcesContent":["export interface ICreateUser {\n userId: string;\n email: string;\n businessId: string;\n}"],"mappings":"","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"user.js","names":[],"sources":["../../../src/interfaces/user.ts"],"sourcesContent":["export interface ICreateUser {\n userId: string;\n email: string;\n businessId: string;\n}\n"],"mappings":"","ignoreList":[]}
|
|
@@ -55,8 +55,24 @@ const parseCookieHeader = header => {
|
|
|
55
55
|
}
|
|
56
56
|
return out;
|
|
57
57
|
};
|
|
58
|
+
function isLocalRequest(origin, requestUrl) {
|
|
59
|
+
const hostCandidate = origin != null ? origin : requestUrl;
|
|
60
|
+
if (!hostCandidate) return false;
|
|
61
|
+
try {
|
|
62
|
+
const host = new URL(hostCandidate).hostname;
|
|
63
|
+
return host === "localhost" || host.startsWith("127.0.0.1");
|
|
64
|
+
} catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function getSessionMappingCookieName(appId, origin, requestUrl) {
|
|
69
|
+
if (isLocalRequest(origin, requestUrl)) {
|
|
70
|
+
return `session-v1.${appId}.mapping`;
|
|
71
|
+
}
|
|
72
|
+
return `__Secure-session-v1.${appId}.mapping`;
|
|
73
|
+
}
|
|
58
74
|
const verifyMw = async (req, ctx, next) => {
|
|
59
|
-
var _APP_MAP$appId, _p, _ref, _ref$state, _ref2, _tokenMapping$userId$, _tokenMapping$userId, _ref3, _p$sub, _ref4, _p$cfy_bid, _ref5, _p$email, _p$name, _ref6, _p$resource_access$
|
|
75
|
+
var _APP_MAP$appId, _req$headers$get, _p, _ref, _ref$state, _ref2, _tokenMapping$userId$, _tokenMapping$userId, _ref3, _p$sub, _ref4, _p$cfy_bid, _ref5, _p$email, _p$name, _ref6, _p$resource_access$to, _p$resource_access, _p$realm_access;
|
|
60
76
|
const appId = req.headers.get("app-id");
|
|
61
77
|
if (!appId || !(_constants.APP_MAP != null && (_APP_MAP$appId = _constants.APP_MAP[appId]) != null && _APP_MAP$appId.clientId)) {
|
|
62
78
|
return {
|
|
@@ -73,11 +89,12 @@ const verifyMw = async (req, ctx, next) => {
|
|
|
73
89
|
})
|
|
74
90
|
};
|
|
75
91
|
}
|
|
76
|
-
const
|
|
92
|
+
const clientId = _constants.APP_MAP[appId].clientId;
|
|
77
93
|
|
|
78
94
|
// cookies
|
|
79
95
|
const cookies = parseCookieHeader(req.headers.get("cookie"));
|
|
80
|
-
|
|
96
|
+
const requestOrigin = (_req$headers$get = req.headers.get("origin")) != null ? _req$headers$get : undefined;
|
|
97
|
+
let mapping = cookies[getSessionMappingCookieName(appId, requestOrigin, req.url)] || cookies[`__Secure-session-v1.${appId}.mapping`] || cookies[`session-v1.${appId}.mapping`] || req.headers.get("x-session-mapping") || req.headers.get("x-token-mapping");
|
|
81
98
|
if (!mapping) {
|
|
82
99
|
return {
|
|
83
100
|
status: 401,
|
|
@@ -166,7 +183,22 @@ const verifyMw = async (req, ctx, next) => {
|
|
|
166
183
|
};
|
|
167
184
|
}
|
|
168
185
|
const realm = tokenMapping.realmId;
|
|
169
|
-
const
|
|
186
|
+
const tokenClientId = tokenMapping.clientId;
|
|
187
|
+
if (!tokenClientId || tokenClientId !== clientId) {
|
|
188
|
+
return {
|
|
189
|
+
status: 403,
|
|
190
|
+
headers: {
|
|
191
|
+
"Content-Type": "application/json",
|
|
192
|
+
"Cache-Control": "no-store, no-cache, must-revalidate",
|
|
193
|
+
"Pragma": "no-cache",
|
|
194
|
+
"Vary": "Origin"
|
|
195
|
+
},
|
|
196
|
+
body: JSON.stringify({
|
|
197
|
+
status: "forbidden",
|
|
198
|
+
reason: "client_mismatch"
|
|
199
|
+
})
|
|
200
|
+
};
|
|
201
|
+
}
|
|
170
202
|
|
|
171
203
|
// decode/verify (lightweight; replace with your verifyJsonWebToken if you have it)
|
|
172
204
|
let p;
|
|
@@ -206,11 +238,11 @@ const verifyMw = async (req, ctx, next) => {
|
|
|
206
238
|
// Refresh only when expired
|
|
207
239
|
if (typeof p.exp === "number" && p.exp <= now) {
|
|
208
240
|
// Delegate to refresh helper; it will handle setting cookies/state or returning an error
|
|
209
|
-
return await getNewRefreshToken(req, ctx, appId, realm,
|
|
241
|
+
return await getNewRefreshToken(req, ctx, appId, realm, tokenClientId, rt, mapping, p, next);
|
|
210
242
|
}
|
|
211
243
|
|
|
212
244
|
// audience checks
|
|
213
|
-
const audOk = Array.isArray(p.aud) && p.aud.includes(
|
|
245
|
+
const audOk = Array.isArray(p.aud) && p.aud.includes(tokenClientId) || typeof p.aud === "string" && (p.aud === tokenClientId || p.aud === "account") || p.azp === tokenClientId;
|
|
214
246
|
if (!audOk) {
|
|
215
247
|
return {
|
|
216
248
|
status: 403,
|
|
@@ -238,7 +270,7 @@ const verifyMw = async (req, ctx, next) => {
|
|
|
238
270
|
tenantId,
|
|
239
271
|
email: (_ref5 = (_p$email = p.email) != null ? _p$email : p.preferred_username) != null ? _ref5 : null,
|
|
240
272
|
name: (_p$name = p.name) != null ? _p$name : undefined,
|
|
241
|
-
roles: (_ref6 = (_p$resource_access$
|
|
273
|
+
roles: (_ref6 = (_p$resource_access$to = (_p$resource_access = p.resource_access) == null || (_p$resource_access = _p$resource_access[tokenClientId]) == null ? void 0 : _p$resource_access.roles) != null ? _p$resource_access$to : (_p$realm_access = p.realm_access) == null ? void 0 : _p$realm_access.roles) != null ? _ref6 : [],
|
|
242
274
|
exp: p.exp
|
|
243
275
|
};
|
|
244
276
|
return next();
|
|
@@ -261,15 +293,31 @@ async function getNewRefreshToken(req, ctx, appId, realmId, clientId, rt, mappin
|
|
|
261
293
|
})
|
|
262
294
|
};
|
|
263
295
|
}
|
|
264
|
-
ctx.info("
|
|
296
|
+
ctx.info("Refreshing session token", {
|
|
265
297
|
realmId,
|
|
266
|
-
clientId
|
|
267
|
-
rt
|
|
298
|
+
clientId
|
|
268
299
|
});
|
|
269
300
|
|
|
270
301
|
// Call auth service to refresh
|
|
271
302
|
try {
|
|
272
|
-
var _req$headers$
|
|
303
|
+
var _req$headers$get2, _ref7, _ref7$state, _ref8, _updatedMapping$userI, _updatedMapping$userI2, _ref9, _p2$sub, _ref0, _p2$cfy_bid, _ref1, _p2$email, _p2$name, _ref10, _p2$resource_access$c, _p2$resource_access, _p2$realm_access;
|
|
304
|
+
if (!apiURL) {
|
|
305
|
+
ctx.error == null || ctx.error("Refresh session URL is not configured");
|
|
306
|
+
return {
|
|
307
|
+
status: 401,
|
|
308
|
+
headers: {
|
|
309
|
+
"Content-Type": "application/json",
|
|
310
|
+
"Cache-Control": "no-store, no-cache, must-revalidate",
|
|
311
|
+
"Pragma": "no-cache",
|
|
312
|
+
"Vary": "Origin"
|
|
313
|
+
},
|
|
314
|
+
body: JSON.stringify({
|
|
315
|
+
status: "unauthenticated",
|
|
316
|
+
reason: "refresh_not_configured"
|
|
317
|
+
})
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
const requestOrigin = (_req$headers$get2 = req.headers.get("origin")) != null ? _req$headers$get2 : undefined;
|
|
273
321
|
const resp = await fetch(apiURL, {
|
|
274
322
|
method: "POST",
|
|
275
323
|
headers: {
|
|
@@ -282,8 +330,7 @@ async function getNewRefreshToken(req, ctx, appId, realmId, clientId, rt, mappin
|
|
|
282
330
|
})
|
|
283
331
|
});
|
|
284
332
|
if (!resp.ok) {
|
|
285
|
-
|
|
286
|
-
ctx.warn == null || ctx.warn(`refresh call failed: ${resp.status} ${text}`);
|
|
333
|
+
ctx.warn == null || ctx.warn(`refresh call failed with status ${resp.status}`);
|
|
287
334
|
return {
|
|
288
335
|
status: 401,
|
|
289
336
|
headers: {
|
|
@@ -349,12 +396,15 @@ async function getNewRefreshToken(req, ctx, appId, realmId, clientId, rt, mappin
|
|
|
349
396
|
|
|
350
397
|
const mappingCookieValue = Buffer.from(mapping).toString("base64");
|
|
351
398
|
const appConfig = _constants.APP_MAP[appId];
|
|
352
|
-
|
|
353
|
-
|
|
399
|
+
|
|
400
|
+
// 5
|
|
401
|
+
const mappedDomain = pickCookieDomain(appConfig, requestOrigin, req.url);
|
|
402
|
+
const localRequest = isLocalRequest(requestOrigin, req.url);
|
|
403
|
+
(0, _cookies.setCookieKV)(ctx, getSessionMappingCookieName(appId, requestOrigin, req.url), mappingCookieValue, {
|
|
354
404
|
// mapping must be readable by FE in your flow; keep httpOnly default if you prefer server-only
|
|
355
405
|
httpOnly: false,
|
|
356
|
-
secure:
|
|
357
|
-
sameSite: "None",
|
|
406
|
+
secure: !localRequest,
|
|
407
|
+
sameSite: localRequest ? "Lax" : "None",
|
|
358
408
|
maxAge: mappingMaxAge,
|
|
359
409
|
domain: mappedDomain
|
|
360
410
|
});
|
|
@@ -413,7 +463,11 @@ async function getNewRefreshToken(req, ctx, appId, realmId, clientId, rt, mappin
|
|
|
413
463
|
// Continue pipeline after refresh
|
|
414
464
|
return next();
|
|
415
465
|
} catch (e) {
|
|
416
|
-
ctx.error == null || ctx.error("refresh exception",
|
|
466
|
+
ctx.error == null || ctx.error("refresh exception", {
|
|
467
|
+
message: e == null ? void 0 : e.message,
|
|
468
|
+
name: e == null ? void 0 : e.name,
|
|
469
|
+
code: e == null ? void 0 : e.code
|
|
470
|
+
});
|
|
417
471
|
return {
|
|
418
472
|
status: 401,
|
|
419
473
|
headers: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify-middleware.js","names":["_constants","require","_jwtDecode","_enums","_cookies","_utils","_tokenMapping","apiURL","process","env","REFRESH_SESSION_URL","verifyMappingCache","createCache","pickCookieDomain","appConfig","origin","requestUrl","undefined","hostCandidate","host","URL","hostname","startsWith","_appConfig$cookie$dom","cookie","domain","local","endsWith","dev","staging","prod","parseCookieHeader","header","out","part","split","k","rest","trim","decodeURIComponent","join","verifyMw","req","ctx","next","_APP_MAP$appId","_p","_ref","_ref$state","_ref2","_tokenMapping$userId$","_tokenMapping$userId","_ref3","_p$sub","_ref4","_p$cfy_bid","_ref5","_p$email","_p$name","_ref6","_p$resource_access$cl","_p$resource_access","_p$realm_access","appId","headers","get","APP_MAP","clientId","status","body","JSON","stringify","reason","expectedClientId","cookies","mapping","base64Decode","dbUrl","getAzureVaultSecretByKey","AZURE_KEY_VAULT_NAME","AzureSecretKeysEnum","DB_CONNECTING_STRING_USER","tokenMappingService","TokenMappingService","tokenMappingRaw","getOrSet","fetched","getTokenMappingById","tokenMapping","parse","at","accessToken","rt","refreshToken","realm","realmId","p","jwtDecode","sid","now","Math","floor","Date","exp","getNewRefreshToken","audOk","Array","isArray","aud","includes","azp","state","tenantId","toString","auth","userId","sub","keycloakUserId","businessId","cfy_bid","email","preferred_username","name","roles","resource_access","realm_access","exports","info","_req$headers$get","_ref7","_ref7$state","_ref8","_updatedMapping$userI","_updatedMapping$userI2","_ref9","_p2$sub","_ref0","_p2$cfy_bid","_ref1","_p2$email","_p2$name","_ref10","_p2$resource_access$c","_p2$resource_access","_p2$realm_access","resp","fetch","method","refresh_token","ok","text","warn","payload","json","data","newAT","access_token","newRT","updatedMapping","updateTokenMapping","expiresAt","expires_in","delete","mappingMaxAge","refresh_expires_in","mappingCookieValue","Buffer","from","mappedDomain","url","setCookieKV","httpOnly","secure","sameSite","maxAge","p2","audOk2","tenantId2","e","error","value","console","log","message"],"sources":["../../../src/middlewares/verify-middleware.ts"],"sourcesContent":["import { IAppId } from \"../types/app\";\nimport { APP_MAP } from \"../constants\";\nimport { jwtDecode } from \"jwt-decode\";\nimport { HttpRequest } from \"@azure/functions\";\nimport { AzureSecretKeysEnum } from \"../enums\";\nimport { setCookieKV } from \"../utils/cookies\";\nimport { IMiddleware } from \"../types/middleware\";\nimport { HttpResponseInit } from \"@azure/functions\";\nimport { createCache, getAzureVaultSecretByKey } from \"../utils\";\nimport { InvocationContext } from \"@azure/functions\";\nimport { TokenMappingService } from \"../service/tokenMapping.service\";\n\nconst apiURL = process.env.REFRESH_SESSION_URL || '';\nconst verifyMappingCache = createCache(\"verify-mw\", 60);\n\nfunction pickCookieDomain(appConfig: (typeof APP_MAP)[IAppId] | undefined, origin?: string, requestUrl?: string): string | undefined {\n if (!appConfig) return undefined;\n const hostCandidate = origin ?? requestUrl;\n if (!hostCandidate) return undefined;\n try {\n const host = new URL(hostCandidate).hostname;\n if (host === \"localhost\" || host.startsWith(\"127.0.0.1\")) {\n return appConfig.cookie.domain.local ?? undefined;\n }\n // culturefy.app domains\n if (host.endsWith(\".dev.culturefy.app\") || host === \"dev.culturefy.app\") {\n return appConfig.cookie.domain.dev;\n }\n if (host.endsWith(\".staging.culturefy.app\") || host === \"staging.culturefy.app\") {\n return appConfig.cookie.domain.staging;\n }\n if (host.endsWith(\".culturefy.app\")) {\n return appConfig.cookie.domain.prod;\n }\n // consultex.app domains\n if (host.endsWith(\".dev.consultex.app\") || host === \"dev.consultex.app\") {\n return appConfig.cookie.domain.dev;\n }\n if (host.endsWith(\".staging.consultex.app\") || host === \"staging.consultex.app\") {\n return appConfig.cookie.domain.staging;\n }\n if (host.endsWith(\".consultex.app\")) {\n return appConfig.cookie.domain.prod;\n }\n } catch {\n return undefined;\n }\n return undefined;\n}\n\nconst parseCookieHeader = (header: string | null | undefined) => {\n const out: Record<string, string> = {};\n if (!header) return out;\n for (const part of header.split(\";\")) {\n const [k, ...rest] = part.trim().split(\"=\");\n if (!k) continue;\n out[k] = decodeURIComponent(rest.join(\"=\") || \"\");\n }\n return out;\n};\n\nexport const verifyMw: IMiddleware = async (\n req: HttpRequest,\n ctx: InvocationContext,\n next: () => Promise<HttpResponseInit>\n): Promise<HttpResponseInit> => {\n const appId = req.headers.get(\"app-id\") as IAppId | undefined;\n\n if (!appId || !APP_MAP?.[appId]?.clientId) {\n return {\n status: 400,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"bad_request\", reason: \"invalid_app\" })\n };\n }\n\n const expectedClientId = APP_MAP[appId].clientId;\n\n // cookies\n const cookies = parseCookieHeader(req.headers.get(\"cookie\"));\n\n let mapping: string | null = cookies[`__Secure-session-v1.${appId}.mapping`];\n\n if (!mapping) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"no_token_mapping\" })\n };\n }\n\n mapping = base64Decode(mapping);\n\n if (!mapping) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"invalid_token_mapping\" })\n };\n }\n\n // Get database connection string\n const dbUrl = await getAzureVaultSecretByKey(\n ctx,\n process.env.AZURE_KEY_VAULT_NAME || \"\",\n AzureSecretKeysEnum.DB_CONNECTING_STRING_USER\n );\n\n if (!dbUrl) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"database_connection_string_not_found\" })\n };\n }\n\n const tokenMappingService = new TokenMappingService(ctx, dbUrl);\n\n const tokenMappingRaw = await verifyMappingCache.getOrSet(\n ctx,\n [mapping],\n async () => {\n const fetched = await tokenMappingService.getTokenMappingById(mapping);\n return fetched ? JSON.stringify(fetched) : \"\";\n },\n );\n const tokenMapping = tokenMappingRaw ? JSON.parse(tokenMappingRaw) : null;\n\n if (!tokenMapping) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"token_mapping_not_found\" })\n };\n }\n\n let at = tokenMapping.accessToken;\n let rt = tokenMapping.refreshToken;\n\n if (!at && !rt) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"no_tokens\" })\n };\n }\n\n const realm = tokenMapping.realmId;\n const clientId = tokenMapping.clientId;\n\n // decode/verify (lightweight; replace with your verifyJsonWebToken if you have it)\n let p: any;\n try {\n p = jwtDecode(at);\n } catch {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"invalid_token\" })\n };\n }\n\n if (!p?.sid) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"user_not_found\" })\n };\n }\n\n const now = Math.floor(Date.now() / 1000);\n // Refresh only when expired\n if (typeof p.exp === \"number\" && p.exp <= now) {\n // Delegate to refresh helper; it will handle setting cookies/state or returning an error\n return await getNewRefreshToken(req, ctx, appId, realm, clientId, rt, mapping, p, next);\n }\n\n // audience checks\n const audOk =\n (Array.isArray(p.aud) && p.aud.includes(clientId)) ||\n (typeof p.aud === \"string\" && (p.aud === clientId || p.aud === \"account\")) ||\n p.azp === clientId;\n\n if (!audOk) {\n return {\n status: 403,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"forbidden\", reason: \"audience_mismatch\" })\n };\n }\n\n\n // pass data downstream\n (ctx as any).state ??= {};\n const tenantId = realm.toString();\n\n (ctx as any).state.auth = {\n appId,\n userId: tokenMapping.userId?.toString?.() ?? p.sub ?? null,\n keycloakUserId: p.sub ?? tokenMapping.keycloakUserId ?? null,\n businessId: p.cfy_bid ?? tenantId ?? null,\n tenantId,\n email: p.email ?? p.preferred_username ?? null,\n name: p.name ?? undefined,\n roles: p.resource_access?.[clientId]?.roles ?? p.realm_access?.roles ?? [],\n exp: p.exp,\n };\n\n return next();\n};\n\n\n\nasync function getNewRefreshToken(\n req: HttpRequest,\n ctx: InvocationContext,\n appId: IAppId,\n realmId: string,\n clientId: string,\n rt: string | undefined,\n mapping: string,\n p: any,\n next: () => Promise<HttpResponseInit>\n): Promise<HttpResponseInit> {\n // Attempt server-side refresh using RT\n if (!rt) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"expired_no_rt\" })\n };\n }\n\n ctx.info(\"refreshing token payload ----------------------\", {\n realmId,\n clientId,\n rt\n });\n\n // Call auth service to refresh\n try {\n const resp = await fetch(apiURL, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n realmId,\n clientId: clientId,\n refresh_token: rt\n })\n });\n\n if (!resp.ok) {\n const text = await resp.text();\n ctx.warn?.(`refresh call failed: ${resp.status} ${text}`);\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"refresh_failed\" })\n };\n }\n\n const payload = await resp.json();\n const data = payload?.data || {};\n\n const newAT = data.access_token as string | undefined;\n const newRT = data.refresh_token as string | undefined;\n\n if (!newAT || !newRT) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"invalid_refresh_response\" })\n };\n }\n\n const dbUrl = await getAzureVaultSecretByKey(\n ctx,\n process.env.AZURE_KEY_VAULT_NAME || \"\",\n AzureSecretKeysEnum.DB_CONNECTING_STRING_USER\n );\n\n if (!dbUrl) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"database_connection_string_not_found\" })\n };\n }\n\n const tokenMappingService = new TokenMappingService(ctx, dbUrl);\n\n const updatedMapping = await tokenMappingService.updateTokenMapping(mapping, {\n accessToken: newAT as string,\n refreshToken: newRT as string,\n // expires_in is a duration (seconds); store absolute expiry for later checks\n expiresAt: typeof data.expires_in === \"number\" ? new Date(Date.now() + data.expires_in * 1000) : undefined\n });\n\n // Invalidate cache to ensure next request gets fresh tokens\n await verifyMappingCache.delete(ctx, mapping);\n\n // Set refreshed mapping cookie for client session (AT/RT stay server-side in token mapping)\n const mappingMaxAge =\n typeof data.refresh_expires_in === \"number\"\n ? data.refresh_expires_in\n : typeof data.expires_in === \"number\"\n ? data.expires_in\n : 60 * 60 * 24; // fallback 24h\n\n const mappingCookieValue = Buffer.from(mapping).toString(\"base64\");\n const appConfig = APP_MAP[appId];\n const mappedDomain = pickCookieDomain(appConfig, req.headers.get(\"origin\") ?? undefined, req.url);\n \n setCookieKV(ctx, `__Secure-session-v1.${appId}.mapping`, mappingCookieValue, {\n // mapping must be readable by FE in your flow; keep httpOnly default if you prefer server-only\n httpOnly: false,\n secure: true,\n sameSite: \"None\",\n maxAge: mappingMaxAge,\n domain: mappedDomain\n });\n\n // Decode new AT and proceed\n let p2: any;\n try { p2 = jwtDecode(newAT); } catch {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"invalid_new_token\" })\n };\n }\n\n const audOk2 =\n (Array.isArray(p2.aud) && p2.aud.includes(clientId)) ||\n (typeof p2.aud === \"string\" && (p2.aud === clientId || p2.aud === \"account\")) ||\n p2.azp === clientId;\n if (!audOk2) {\n return {\n status: 403,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"forbidden\", reason: \"audience_mismatch\" })\n };\n }\n\n // Update downstream auth state with refreshed token\n (ctx as any).state ??= {};\n const tenantId2 = realmId.toString();\n (ctx as any).state.auth = {\n appId,\n userId: updatedMapping?.userId?.toString?.() ?? p2.sub ?? null,\n keycloakUserId: p2.sub ?? updatedMapping?.keycloakUserId ?? null,\n businessId: p2.cfy_bid ?? tenantId2 ?? null,\n tenantId: tenantId2,\n email: p2.email ?? p2.preferred_username ?? null,\n name: p2.name ?? undefined,\n roles: p2.resource_access?.[clientId]?.roles ?? p2.realm_access?.roles ?? [],\n exp: p2.exp,\n };\n\n // Continue pipeline after refresh\n return next();\n } catch (e) {\n ctx.error?.(\"refresh exception\", e as any);\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"refresh_exception\" })\n };\n }\n}\n\nfunction base64Decode(value: string): string | null {\n try {\n return Buffer.from(value, 'base64').toString();\n } catch (error: any) {\n console.log(\"Error decoding base64: \" + error.message);\n return null;\n }\n}"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"verify-middleware.js","names":["_constants","require","_jwtDecode","_enums","_cookies","_utils","_tokenMapping","apiURL","process","env","REFRESH_SESSION_URL","verifyMappingCache","createCache","pickCookieDomain","appConfig","origin","requestUrl","undefined","hostCandidate","host","URL","hostname","startsWith","_appConfig$cookie$dom","cookie","domain","local","endsWith","dev","staging","prod","parseCookieHeader","header","out","part","split","k","rest","trim","decodeURIComponent","join","isLocalRequest","getSessionMappingCookieName","appId","verifyMw","req","ctx","next","_APP_MAP$appId","_req$headers$get","_p","_ref","_ref$state","_ref2","_tokenMapping$userId$","_tokenMapping$userId","_ref3","_p$sub","_ref4","_p$cfy_bid","_ref5","_p$email","_p$name","_ref6","_p$resource_access$to","_p$resource_access","_p$realm_access","headers","get","APP_MAP","clientId","status","body","JSON","stringify","reason","cookies","requestOrigin","mapping","url","base64Decode","dbUrl","getAzureVaultSecretByKey","AZURE_KEY_VAULT_NAME","AzureSecretKeysEnum","DB_CONNECTING_STRING_USER","tokenMappingService","TokenMappingService","tokenMappingRaw","getOrSet","fetched","getTokenMappingById","tokenMapping","parse","at","accessToken","rt","refreshToken","realm","realmId","tokenClientId","p","jwtDecode","sid","now","Math","floor","Date","exp","getNewRefreshToken","audOk","Array","isArray","aud","includes","azp","state","tenantId","toString","auth","userId","sub","keycloakUserId","businessId","cfy_bid","email","preferred_username","name","roles","resource_access","realm_access","exports","info","_req$headers$get2","_ref7","_ref7$state","_ref8","_updatedMapping$userI","_updatedMapping$userI2","_ref9","_p2$sub","_ref0","_p2$cfy_bid","_ref1","_p2$email","_p2$name","_ref10","_p2$resource_access$c","_p2$resource_access","_p2$realm_access","error","resp","fetch","method","refresh_token","ok","warn","payload","json","data","newAT","access_token","newRT","updatedMapping","updateTokenMapping","expiresAt","expires_in","delete","mappingMaxAge","refresh_expires_in","mappingCookieValue","Buffer","from","mappedDomain","localRequest","setCookieKV","httpOnly","secure","sameSite","maxAge","p2","audOk2","tenantId2","e","message","code","value","console","log"],"sources":["../../../src/middlewares/verify-middleware.ts"],"sourcesContent":["import { IAppId } from \"../types/app\";\nimport { APP_MAP } from \"../constants\";\nimport { jwtDecode } from \"jwt-decode\";\nimport { HttpRequest } from \"@azure/functions\";\nimport { AzureSecretKeysEnum } from \"../enums\";\nimport { setCookieKV } from \"../utils/cookies\";\nimport { IMiddleware } from \"../types/middleware\";\nimport { HttpResponseInit } from \"@azure/functions\";\nimport { createCache, getAzureVaultSecretByKey } from \"../utils\";\nimport { InvocationContext } from \"@azure/functions\";\nimport { TokenMappingService } from \"../service/tokenMapping.service\";\n\nconst apiURL = process.env.REFRESH_SESSION_URL || '';\nconst verifyMappingCache = createCache(\"verify-mw\", 60);\n\nfunction pickCookieDomain(appConfig: (typeof APP_MAP)[IAppId] | undefined, origin?: string, requestUrl?: string): string | undefined {\n if (!appConfig) return undefined;\n const hostCandidate = origin ?? requestUrl;\n if (!hostCandidate) return undefined;\n try {\n const host = new URL(hostCandidate).hostname;\n if (host === \"localhost\" || host.startsWith(\"127.0.0.1\")) {\n return appConfig.cookie.domain.local ?? undefined;\n }\n // culturefy.app domains\n if (host.endsWith(\".dev.culturefy.app\") || host === \"dev.culturefy.app\") {\n return appConfig.cookie.domain.dev;\n }\n if (host.endsWith(\".staging.culturefy.app\") || host === \"staging.culturefy.app\") {\n return appConfig.cookie.domain.staging;\n }\n if (host.endsWith(\".culturefy.app\")) {\n return appConfig.cookie.domain.prod;\n }\n // consultex.app domains\n if (host.endsWith(\".dev.consultex.app\") || host === \"dev.consultex.app\") {\n return appConfig.cookie.domain.dev;\n }\n if (host.endsWith(\".staging.consultex.app\") || host === \"staging.consultex.app\") {\n return appConfig.cookie.domain.staging;\n }\n if (host.endsWith(\".consultex.app\")) {\n return appConfig.cookie.domain.prod;\n }\n } catch {\n return undefined;\n }\n return undefined;\n}\n\nconst parseCookieHeader = (header: string | null | undefined) => {\n const out: Record<string, string> = {};\n if (!header) return out;\n for (const part of header.split(\";\")) {\n const [k, ...rest] = part.trim().split(\"=\");\n if (!k) continue;\n out[k] = decodeURIComponent(rest.join(\"=\") || \"\");\n }\n return out;\n};\n\nfunction isLocalRequest(origin?: string, requestUrl?: string): boolean {\n const hostCandidate = origin ?? requestUrl;\n if (!hostCandidate) return false;\n try {\n const host = new URL(hostCandidate).hostname;\n return host === \"localhost\" || host.startsWith(\"127.0.0.1\");\n } catch {\n return false;\n }\n}\n\nfunction getSessionMappingCookieName(appId: IAppId, origin?: string, requestUrl?: string): string {\n if (isLocalRequest(origin, requestUrl)) {\n return `session-v1.${appId}.mapping`;\n }\n return `__Secure-session-v1.${appId}.mapping`;\n}\n\nexport const verifyMw: IMiddleware = async (\n req: HttpRequest,\n ctx: InvocationContext,\n next: () => Promise<HttpResponseInit>\n): Promise<HttpResponseInit> => {\n const appId = req.headers.get(\"app-id\") as IAppId | undefined;\n\n if (!appId || !APP_MAP?.[appId]?.clientId) {\n return {\n status: 400,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"bad_request\", reason: \"invalid_app\" })\n };\n }\n\n const clientId = APP_MAP[appId].clientId;\n\n // cookies\n const cookies = parseCookieHeader(req.headers.get(\"cookie\"));\n const requestOrigin = req.headers.get(\"origin\") ?? undefined;\n\n let mapping: string | null =\n cookies[getSessionMappingCookieName(appId, requestOrigin, req.url)] ||\n cookies[`__Secure-session-v1.${appId}.mapping`] ||\n cookies[`session-v1.${appId}.mapping`] ||\n req.headers.get(\"x-session-mapping\") ||\n req.headers.get(\"x-token-mapping\");\n\n if (!mapping) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"no_token_mapping\" })\n };\n }\n\n mapping = base64Decode(mapping);\n\n if (!mapping) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"invalid_token_mapping\" })\n };\n }\n\n // Get database connection string\n const dbUrl = await getAzureVaultSecretByKey(\n ctx,\n process.env.AZURE_KEY_VAULT_NAME || \"\",\n AzureSecretKeysEnum.DB_CONNECTING_STRING_USER\n );\n\n if (!dbUrl) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"database_connection_string_not_found\" })\n };\n }\n\n const tokenMappingService = new TokenMappingService(ctx, dbUrl);\n\n const tokenMappingRaw = await verifyMappingCache.getOrSet(\n ctx,\n [mapping],\n async () => {\n const fetched = await tokenMappingService.getTokenMappingById(mapping);\n return fetched ? JSON.stringify(fetched) : \"\";\n },\n );\n const tokenMapping = tokenMappingRaw ? JSON.parse(tokenMappingRaw) : null;\n\n if (!tokenMapping) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"token_mapping_not_found\" })\n };\n }\n\n let at = tokenMapping.accessToken;\n let rt = tokenMapping.refreshToken;\n\n if (!at && !rt) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"no_tokens\" })\n };\n }\n\n const realm = tokenMapping.realmId;\n const tokenClientId = tokenMapping.clientId;\n\n if (!tokenClientId || tokenClientId !== clientId) {\n return {\n status: 403,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"forbidden\", reason: \"client_mismatch\" })\n };\n }\n\n // decode/verify (lightweight; replace with your verifyJsonWebToken if you have it)\n let p: any;\n try {\n p = jwtDecode(at);\n } catch {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"invalid_token\" })\n };\n }\n\n if (!p?.sid) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"user_not_found\" })\n };\n }\n\n const now = Math.floor(Date.now() / 1000);\n // Refresh only when expired\n if (typeof p.exp === \"number\" && p.exp <= now) {\n // Delegate to refresh helper; it will handle setting cookies/state or returning an error\n return await getNewRefreshToken(req, ctx, appId, realm, tokenClientId, rt, mapping, p, next);\n }\n\n // audience checks\n const audOk =\n (Array.isArray(p.aud) && p.aud.includes(tokenClientId)) ||\n (typeof p.aud === \"string\" && (p.aud === tokenClientId || p.aud === \"account\")) ||\n p.azp === tokenClientId;\n\n if (!audOk) {\n return {\n status: 403,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"forbidden\", reason: \"audience_mismatch\" })\n };\n }\n\n\n // pass data downstream\n (ctx as any).state ??= {};\n const tenantId = realm.toString();\n\n (ctx as any).state.auth = {\n appId,\n userId: tokenMapping.userId?.toString?.() ?? p.sub ?? null,\n keycloakUserId: p.sub ?? tokenMapping.keycloakUserId ?? null,\n businessId: p.cfy_bid ?? tenantId ?? null,\n tenantId,\n email: p.email ?? p.preferred_username ?? null,\n name: p.name ?? undefined,\n roles: p.resource_access?.[tokenClientId]?.roles ?? p.realm_access?.roles ?? [],\n exp: p.exp,\n };\n\n return next();\n};\n\n\n\nasync function getNewRefreshToken(\n req: HttpRequest,\n ctx: InvocationContext,\n appId: IAppId,\n realmId: string,\n clientId: string,\n rt: string | undefined,\n mapping: string,\n p: any,\n next: () => Promise<HttpResponseInit>\n): Promise<HttpResponseInit> {\n // Attempt server-side refresh using RT\n if (!rt) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"expired_no_rt\" })\n };\n }\n\n ctx.info(\"Refreshing session token\", {\n realmId,\n clientId,\n });\n\n // Call auth service to refresh\n try {\n if (!apiURL) {\n ctx.error?.(\"Refresh session URL is not configured\");\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"refresh_not_configured\" })\n };\n }\n const requestOrigin = req.headers.get(\"origin\") ?? undefined;\n const resp = await fetch(apiURL, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n realmId,\n clientId: clientId,\n refresh_token: rt\n })\n });\n\n if (!resp.ok) {\n ctx.warn?.(`refresh call failed with status ${resp.status}`);\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"refresh_failed\" })\n };\n }\n\n const payload = await resp.json();\n const data = payload?.data || {};\n\n const newAT = data.access_token as string | undefined;\n const newRT = data.refresh_token as string | undefined;\n\n if (!newAT || !newRT) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"invalid_refresh_response\" })\n };\n }\n\n const dbUrl = await getAzureVaultSecretByKey(\n ctx,\n process.env.AZURE_KEY_VAULT_NAME || \"\",\n AzureSecretKeysEnum.DB_CONNECTING_STRING_USER\n );\n\n if (!dbUrl) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"database_connection_string_not_found\" })\n };\n }\n\n const tokenMappingService = new TokenMappingService(ctx, dbUrl);\n\n const updatedMapping = await tokenMappingService.updateTokenMapping(mapping, {\n accessToken: newAT,\n refreshToken: newRT as string,\n // expires_in is a duration (seconds); store absolute expiry for later checks\n expiresAt: typeof data.expires_in === \"number\" ? new Date(Date.now() + data.expires_in * 1000) : undefined\n });\n\n // Invalidate cache to ensure next request gets fresh tokens\n await verifyMappingCache.delete(ctx, mapping);\n\n // Set refreshed mapping cookie for client session (AT/RT stay server-side in token mapping)\n const mappingMaxAge =\n typeof data.refresh_expires_in === \"number\"\n ? data.refresh_expires_in\n : typeof data.expires_in === \"number\"\n ? data.expires_in\n : 60 * 60 * 24; // fallback 24h\n\n const mappingCookieValue = Buffer.from(mapping).toString(\"base64\");\n const appConfig = APP_MAP[appId];\n\n // 5\n const mappedDomain = pickCookieDomain(appConfig, requestOrigin, req.url);\n const localRequest = isLocalRequest(requestOrigin, req.url);\n\n setCookieKV(ctx, getSessionMappingCookieName(appId, requestOrigin, req.url), mappingCookieValue, {\n // mapping must be readable by FE in your flow; keep httpOnly default if you prefer server-only\n httpOnly: false,\n secure: !localRequest,\n sameSite: localRequest ? \"Lax\" : \"None\",\n maxAge: mappingMaxAge,\n domain: mappedDomain\n });\n\n // Decode new AT and proceed\n let p2: any;\n try { p2 = jwtDecode(newAT); } catch {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"invalid_new_token\" })\n };\n }\n\n const audOk2 =\n (Array.isArray(p2.aud) && p2.aud.includes(clientId)) ||\n (typeof p2.aud === \"string\" && (p2.aud === clientId || p2.aud === \"account\")) ||\n p2.azp === clientId;\n if (!audOk2) {\n return {\n status: 403,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"forbidden\", reason: \"audience_mismatch\" })\n };\n }\n\n // Update downstream auth state with refreshed token\n (ctx as any).state ??= {};\n const tenantId2 = realmId.toString();\n (ctx as any).state.auth = {\n appId,\n userId: updatedMapping?.userId?.toString?.() ?? p2.sub ?? null,\n keycloakUserId: p2.sub ?? updatedMapping?.keycloakUserId ?? null,\n businessId: p2.cfy_bid ?? tenantId2 ?? null,\n tenantId: tenantId2,\n email: p2.email ?? p2.preferred_username ?? null,\n name: p2.name ?? undefined,\n roles: p2.resource_access?.[clientId]?.roles ?? p2.realm_access?.roles ?? [],\n exp: p2.exp,\n };\n\n // Continue pipeline after refresh\n return next();\n } catch (e: any) {\n ctx.error?.(\"refresh exception\", {\n message: e?.message,\n name: e?.name,\n code: e?.code,\n });\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"refresh_exception\" })\n };\n }\n}\n\nfunction base64Decode(value: string): string | null {\n try {\n return Buffer.from(value, 'base64').toString();\n } catch (error: any) {\n console.log(\"Error decoding base64: \" + error.message);\n return null;\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -57,11 +57,22 @@ let MultiTenantRepository = exports.MultiTenantRepository = (_dec = (0, _cache.C
|
|
|
57
57
|
this.serviceDBType = serviceDBType != null ? serviceDBType : "main";
|
|
58
58
|
this.tenantBridgeConfig = {
|
|
59
59
|
tenantBridgeEnvKey: "TENANT_BRIDGE_DB_URI",
|
|
60
|
-
tenantBridgeSecretKey: _enums.AzureSecretKeysEnum.
|
|
60
|
+
tenantBridgeSecretKey: _enums.AzureSecretKeysEnum.DB_CONNECTION_STRING_TENANT_BRIDGE,
|
|
61
61
|
...config
|
|
62
62
|
};
|
|
63
63
|
this.connectionPromise = this.ensureClientConnection();
|
|
64
64
|
}
|
|
65
|
+
getConnectionLogLabel(connectionString) {
|
|
66
|
+
const match = connectionString.match(/\/([^/?]+)(\?|$)/);
|
|
67
|
+
const dbName = (match == null ? void 0 : match[1]) || "unknown";
|
|
68
|
+
if (dbName.toLowerCase().includes("tenantbridge")) {
|
|
69
|
+
return "TenantBridge-DB";
|
|
70
|
+
}
|
|
71
|
+
if (dbName.toLowerCase().includes("user")) {
|
|
72
|
+
return "Auth-DB";
|
|
73
|
+
}
|
|
74
|
+
return `${dbName}-DB`;
|
|
75
|
+
}
|
|
65
76
|
getEncryptionIv() {
|
|
66
77
|
const iv = process.env.DB_CONNECTION_STRING_ENCRYPTION_IV;
|
|
67
78
|
if (!iv) {
|
|
@@ -89,7 +100,8 @@ let MultiTenantRepository = exports.MultiTenantRepository = (_dec = (0, _cache.C
|
|
|
89
100
|
if (existing && existing.connection.readyState === 1) {
|
|
90
101
|
return existing;
|
|
91
102
|
}
|
|
92
|
-
this.
|
|
103
|
+
const dbLabel = this.getConnectionLogLabel(connectionString);
|
|
104
|
+
this.context.info(`Initializing database connection (${dbLabel})...`);
|
|
93
105
|
const instance = new _mongoose.default.Mongoose();
|
|
94
106
|
try {
|
|
95
107
|
await instance.connect(connectionString, {
|
|
@@ -97,11 +109,11 @@ let MultiTenantRepository = exports.MultiTenantRepository = (_dec = (0, _cache.C
|
|
|
97
109
|
connectTimeoutMS: 10000,
|
|
98
110
|
socketTimeoutMS: 45000
|
|
99
111
|
});
|
|
100
|
-
this.context.info(`✅ MongoDB connected successfully ${
|
|
112
|
+
this.context.info(`✅ MongoDB connected successfully (${dbLabel})`);
|
|
101
113
|
MultiTenantRepository.connections.set(connectionString, instance);
|
|
102
114
|
return instance;
|
|
103
115
|
} catch (err) {
|
|
104
|
-
this.context.error(`❌ MongoDB connection error for ${
|
|
116
|
+
this.context.error(`❌ MongoDB connection error for (${dbLabel})`, {
|
|
105
117
|
message: err.message,
|
|
106
118
|
name: err.name,
|
|
107
119
|
code: err.code,
|
|
@@ -123,7 +135,7 @@ let MultiTenantRepository = exports.MultiTenantRepository = (_dec = (0, _cache.C
|
|
|
123
135
|
return localUri;
|
|
124
136
|
}
|
|
125
137
|
const vault = process.env.AZURE_KEY_VAULT_NAME || "";
|
|
126
|
-
const secretKey = this.tenantBridgeConfig.tenantBridgeSecretKey || _enums.AzureSecretKeysEnum.
|
|
138
|
+
const secretKey = this.tenantBridgeConfig.tenantBridgeSecretKey || _enums.AzureSecretKeysEnum.DB_CONNECTION_STRING_TENANT_BRIDGE;
|
|
127
139
|
const dbUrl = await (0, _secrets.getAzureVaultSecretByKey)(this.context, vault, secretKey);
|
|
128
140
|
if (!dbUrl) {
|
|
129
141
|
throw new Error("TenantBridge database connection string not found");
|
|
@@ -180,6 +192,9 @@ let MultiTenantRepository = exports.MultiTenantRepository = (_dec = (0, _cache.C
|
|
|
180
192
|
throw new Error(`DB connection string encryption key must be 16 bytes for aes-128-cbc (got ${utf8Key.length})`);
|
|
181
193
|
}
|
|
182
194
|
async getClientDbConnectionString(businessId, appId, serviceDBType) {
|
|
195
|
+
if (!appId) {
|
|
196
|
+
throw new Error("appId is required to resolve tenant client database");
|
|
197
|
+
}
|
|
183
198
|
const resolvedServiceDbType = serviceDBType != null ? serviceDBType : "main";
|
|
184
199
|
const tenantBridgeUrl = await this.getTenantBridgeSrvDbConnectionString();
|
|
185
200
|
const connection = await this.getOrCreateCachedConnection(tenantBridgeUrl);
|
|
@@ -187,16 +202,14 @@ let MultiTenantRepository = exports.MultiTenantRepository = (_dec = (0, _cache.C
|
|
|
187
202
|
const filter = {
|
|
188
203
|
businessId: this.toObjectId(businessId, "businessId")
|
|
189
204
|
};
|
|
190
|
-
|
|
191
|
-
filter.appId = appId;
|
|
192
|
-
}
|
|
205
|
+
filter.appId = appId;
|
|
193
206
|
filter.serviceDBType = resolvedServiceDbType;
|
|
194
207
|
const configMapping = await ConfigMapping.findOne(filter).lean().exec();
|
|
195
208
|
if (!(configMapping != null && configMapping.connectionString)) {
|
|
196
209
|
throw new Error("Config mapping not found for this business");
|
|
197
210
|
}
|
|
198
211
|
const decryptedConnectionString = await this.decryptConnectionString(configMapping.connectionString);
|
|
199
|
-
this.context.info(
|
|
212
|
+
this.context.info("Resolved tenant database mapping from TenantBridge");
|
|
200
213
|
return decryptedConnectionString;
|
|
201
214
|
}
|
|
202
215
|
getConnection() {
|
|
@@ -223,9 +236,9 @@ let MultiTenantRepository = exports.MultiTenantRepository = (_dec = (0, _cache.C
|
|
|
223
236
|
if (!existing) return;
|
|
224
237
|
try {
|
|
225
238
|
await existing.disconnect();
|
|
226
|
-
this.context.info(`✅ Disconnected from database
|
|
239
|
+
this.context.info(`✅ Disconnected from database (${this.getConnectionLogLabel(connectionString)})`);
|
|
227
240
|
} catch (error) {
|
|
228
|
-
this.context.error(`❌ Error disconnecting from database
|
|
241
|
+
this.context.error(`❌ Error disconnecting from database (${this.getConnectionLogLabel(connectionString)})`, error);
|
|
229
242
|
} finally {
|
|
230
243
|
MultiTenantRepository.connections.delete(connectionString);
|
|
231
244
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multi-tenant.repository.js","names":["_mongoose","_interopRequireWildcard","require","crypto","_identity","_keyvaultSecrets","_enums","_cache","_secrets","_configMapping","_dec","_dec2","_dec3","_class","_MultiTenantRepository","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","_applyDecoratedDescriptor","l","a","keys","forEach","enumerable","configurable","initializer","writable","slice","reverse","reduce","value","tenantDbCache","createCache","tenantBridgeCache","encryptionKeyCache","WithTenantDb","_target","_propertyKey","descriptor","originalMethod","args","ensureClientConnection","apply","MultiTenantRepository","exports","Cacheable","cache","key","getContext","instance","context","businessId","appId","serviceDbType","constructor","config","serviceDBType","tenantBridgeConfig","dbConnectionEncryptionKey","clientConnectionString","connectionPromise","tenantBridgeEnvKey","tenantBridgeSecretKey","AzureSecretKeysEnum","DB_CONNECTING_STRING_TENANT_BRIDGE","getEncryptionIv","iv","process","env","DB_CONNECTION_STRING_ENCRYPTION_IV","Buffer","alloc","normalizeFixedSize","label","utf8Value","from","length","base64Value","hexValue","Error","getOrCreateCachedConnection","connectionString","existing","connections","connection","readyState","info","mongoose","Mongoose","connect","serverSelectionTimeoutMS","connectTimeoutMS","socketTimeoutMS","err","error","message","name","code","stack","toObjectId","id","fieldName","Types","ObjectId","isValid","getTenantBridgeSrvDbConnectionString","envKey","localUri","undefined","vault","AZURE_KEY_VAULT_NAME","secretKey","dbUrl","getAzureVaultSecretByKey","getDbConnectionEncryptionKey","_secret$value","DB_CONNECTION_STRING_ENCRYPTION_KEY","vaultUrl","credential","DefaultAzureCredential","client","SecretClient","secret","getSecret","decryptConnectionString","encryptedValue","keyBuffer","normalizeEncryptionKey","ivBuffer","decipher","createDecipheriv","decrypted","update","final","utf8Key","base64Key","hexKey","getClientDbConnectionString","resolvedServiceDbType","tenantBridgeUrl","ConfigMapping","getModel","CONFIG_MAPPING_DOCUMENT_NAME","ConfigMappingModel","schema","CONFIG_MAPPING_COLLECTION_NAME","filter","configMapping","findOne","lean","exec","decryptedConnectionString","getConnection","clientDbUrl","disconnectByConnectionString","disconnect","delete","disconnectClient","getTenantModel","modelName","collectionName","model","models","Map","prototype","TenantModelRepository","modelDef","dbModel"],"sources":["../../../src/repositories/multi-tenant.repository.ts"],"sourcesContent":["import mongoose, { Model, Schema, Types } from \"mongoose\";\nimport * as crypto from \"crypto\";\nimport { InvocationContext } from \"@azure/functions\";\nimport { DefaultAzureCredential } from \"@azure/identity\";\nimport { SecretClient } from \"@azure/keyvault-secrets\";\nimport { AzureSecretKeysEnum } from \"../enums\";\nimport { Cacheable, createCache } from \"../utils/cache\";\nimport { getAzureVaultSecretByKey } from \"../utils/secrets\";\nimport {\n CONFIG_MAPPING_COLLECTION_NAME,\n CONFIG_MAPPING_DOCUMENT_NAME,\n ConfigMappingModel,\n IConfigMapping,\n} from \"../models/config-mapping.model\";\n\ntype ConnectionMap = Map<string, mongoose.Mongoose>;\n\ntype TenantBridgeConfig = {\n tenantBridgeEnvKey?: string;\n tenantBridgeSecretKey?: AzureSecretKeysEnum;\n};\n\nconst tenantDbCache = createCache(\"tenant-db\", 600);\nconst tenantBridgeCache = createCache(\"tenant-bridge-db-connection-string\", 1800);\nconst encryptionKeyCache = createCache(\"db-enc-key\", 1800);\n\n/**\n * Decorator that ensures tenant DB is connected before the method runs.\n */\nexport function WithTenantDb(\n _target: any,\n _propertyKey: string | symbol,\n descriptor: TypedPropertyDescriptor<(...args: any[]) => Promise<any>>,\n): void {\n if (!descriptor.value) return;\n const originalMethod = descriptor.value;\n descriptor.value = async function (\n this: MultiTenantRepository,\n ...args: any[]\n ) {\n await this.ensureClientConnection();\n return originalMethod.apply(this, args);\n };\n}\n\nexport class MultiTenantRepository {\n private static connections: ConnectionMap = new Map();\n private readonly context: InvocationContext;\n private readonly tenantBridgeConfig: TenantBridgeConfig;\n private readonly businessId: string;\n private readonly appId?: string;\n private readonly serviceDBType?: string;\n private dbConnectionEncryptionKey?: string;\n private clientConnectionString?: string;\n private connectionPromise?: Promise<mongoose.Mongoose>;\n\n constructor(\n context: InvocationContext,\n businessId: string,\n appId?: string,\n config?: TenantBridgeConfig,\n serviceDBType?: string,\n ) {\n this.context = context;\n this.businessId = businessId;\n this.appId = appId;\n this.serviceDBType = serviceDBType ?? \"main\";\n this.tenantBridgeConfig = {\n tenantBridgeEnvKey: \"TENANT_BRIDGE_DB_URI\",\n tenantBridgeSecretKey: AzureSecretKeysEnum.DB_CONNECTING_STRING_TENANT_BRIDGE,\n ...config,\n };\n\n this.connectionPromise = this.ensureClientConnection();\n }\n\n private getEncryptionIv(): Buffer {\n const iv = process.env.DB_CONNECTION_STRING_ENCRYPTION_IV;\n if (!iv) {\n return Buffer.alloc(16, 0);\n }\n return this.normalizeFixedSize(iv, \"IV\");\n }\n\n private normalizeFixedSize(value: string, label: string): Buffer {\n const utf8Value = Buffer.from(value, \"utf8\");\n if (utf8Value.length === 16) {\n return utf8Value;\n }\n\n const base64Value = Buffer.from(value, \"base64\");\n if (base64Value.length === 16) {\n return base64Value;\n }\n\n const hexValue = Buffer.from(value, \"hex\");\n if (hexValue.length === 16) {\n return hexValue;\n }\n\n throw new Error(\n `${label} must be 16 bytes for aes-128-cbc (got ${utf8Value.length})`,\n );\n }\n\n private async getOrCreateCachedConnection(\n connectionString: string,\n ): Promise<mongoose.Mongoose> {\n const existing = MultiTenantRepository.connections.get(connectionString);\n if (existing && existing.connection.readyState === 1) {\n return existing;\n }\n\n this.context.info(`Initializing database connection... ${connectionString}`);\n const instance = new mongoose.Mongoose();\n\n try {\n await instance.connect(connectionString, {\n serverSelectionTimeoutMS: 10000,\n connectTimeoutMS: 10000,\n socketTimeoutMS: 45000,\n });\n this.context.info(`✅ MongoDB connected successfully ${connectionString}`);\n MultiTenantRepository.connections.set(connectionString, instance);\n return instance;\n } catch (err: any) {\n this.context.error(\n `❌ MongoDB connection error for ${connectionString}`,\n {\n message: err.message,\n name: err.name,\n code: err.code,\n stack: err.stack,\n },\n );\n throw new Error(`Failed to connect to MongoDB: ${err.message}`);\n }\n }\n\n private toObjectId(id: string, fieldName: string): Types.ObjectId {\n if (!Types.ObjectId.isValid(id)) {\n throw new Error(`Invalid ${fieldName}`);\n }\n return new Types.ObjectId(id);\n }\n\n @Cacheable({\n cache: tenantBridgeCache,\n key: () => [\"tenant-bridge\"],\n getContext: (instance: unknown) =>\n (instance as MultiTenantRepository).context,\n })\n async getTenantBridgeSrvDbConnectionString(): Promise<string> {\n const envKey = this.tenantBridgeConfig.tenantBridgeEnvKey;\n const localUri =\n (envKey ? process.env[envKey] : undefined);\n\n if (localUri) {\n return localUri;\n }\n\n const vault = process.env.AZURE_KEY_VAULT_NAME || \"\";\n const secretKey =\n this.tenantBridgeConfig.tenantBridgeSecretKey ||\n AzureSecretKeysEnum.DB_CONNECTING_STRING_TENANT_BRIDGE;\n\n const dbUrl = await getAzureVaultSecretByKey(\n this.context,\n vault,\n secretKey,\n );\n if (!dbUrl) {\n throw new Error(\"TenantBridge database connection string not found\");\n }\n return dbUrl;\n }\n\n @Cacheable({\n cache: encryptionKeyCache,\n key: () => [\"key\"],\n getContext: (instance: unknown) =>\n (instance as MultiTenantRepository).context,\n })\n private async getDbConnectionEncryptionKey(): Promise<string> {\n if (this.dbConnectionEncryptionKey) {\n return this.dbConnectionEncryptionKey;\n }\n\n const envKey = process.env.DB_CONNECTION_STRING_ENCRYPTION_KEY;\n if (envKey) {\n this.dbConnectionEncryptionKey = envKey;\n return envKey;\n }\n\n const vault = process.env.AZURE_KEY_VAULT_NAME || \"\";\n if (!vault) {\n throw new Error(\"AZURE_KEY_VAULT_NAME is required to fetch encryption key\");\n }\n const vaultUrl = `https://${vault}.vault.azure.net`;\n const credential = new DefaultAzureCredential();\n const client = new SecretClient(vaultUrl, credential);\n const secret = await client.getSecret(\"DB-CONNECTION-STRING-ENCRYPTION-KEY\");\n const key = secret.value ?? \"\";\n if (!key) {\n throw new Error(\"DB connection string encryption key not found\");\n }\n this.dbConnectionEncryptionKey = key;\n return key;\n }\n\n private async decryptConnectionString(encryptedValue: string): Promise<string> {\n const key = await this.getDbConnectionEncryptionKey();\n const keyBuffer = this.normalizeEncryptionKey(key);\n\n const ivBuffer = this.getEncryptionIv();\n const decipher = crypto.createDecipheriv(\"aes-128-cbc\", keyBuffer, ivBuffer);\n let decrypted = decipher.update(encryptedValue, \"base64\", \"utf8\");\n decrypted += decipher.final(\"utf8\");\n return decrypted;\n }\n\n private normalizeEncryptionKey(key: string): Buffer {\n const utf8Key = Buffer.from(key, \"utf8\");\n if (utf8Key.length === 16) {\n return utf8Key;\n }\n\n const base64Key = Buffer.from(key, \"base64\");\n if (base64Key.length === 16) {\n return base64Key;\n }\n\n const hexKey = Buffer.from(key, \"hex\");\n if (hexKey.length === 16) {\n return hexKey;\n }\n\n throw new Error(\n `DB connection string encryption key must be 16 bytes for aes-128-cbc (got ${utf8Key.length})`,\n );\n }\n\n @Cacheable({\n cache: tenantDbCache,\n key: (businessId: string, appId?: string, serviceDbType?: string) => [\n businessId,\n appId,\n serviceDbType,\n ],\n getContext: (instance: unknown) =>\n (instance as MultiTenantRepository).context,\n })\n async getClientDbConnectionString(\n businessId: string,\n appId?: string,\n serviceDBType?: string,\n ): Promise<string> {\n const resolvedServiceDbType = serviceDBType ?? \"main\";\n const tenantBridgeUrl = await this.getTenantBridgeSrvDbConnectionString();\n const connection = await this.getOrCreateCachedConnection(tenantBridgeUrl);\n\n const ConfigMapping = this.getModel(\n connection,\n CONFIG_MAPPING_DOCUMENT_NAME,\n ConfigMappingModel.schema,\n CONFIG_MAPPING_COLLECTION_NAME,\n ) as Model<IConfigMapping>;\n\n const filter: Record<string, unknown> = {\n businessId: this.toObjectId(businessId, \"businessId\"),\n };\n if (appId) {\n filter.appId = appId;\n }\n filter.serviceDBType = resolvedServiceDbType;\n\n const configMapping =\n (await ConfigMapping.findOne(filter).lean().exec()) as\n | IConfigMapping\n | null;\n if (!configMapping?.connectionString) {\n throw new Error(\"Config mapping not found for this business\");\n }\n const decryptedConnectionString = await this.decryptConnectionString(\n configMapping.connectionString,\n );\n this.context.info(\n `Resolved tenant DB connection string from bridge: ${decryptedConnectionString}`,\n );\n return decryptedConnectionString;\n }\n\n protected getConnection(): mongoose.Mongoose | undefined {\n if (!this.clientConnectionString) return undefined;\n return MultiTenantRepository.connections.get(this.clientConnectionString);\n }\n\n protected async ensureClientConnection(): Promise<mongoose.Mongoose> {\n if (this.connectionPromise) {\n return this.connectionPromise;\n }\n\n if (this.clientConnectionString) {\n const existing = this.getConnection();\n if (existing && existing.connection.readyState === 1) {\n return existing;\n }\n }\n\n const clientDbUrl = await this.getClientDbConnectionString(\n this.businessId,\n this.appId,\n this.serviceDBType,\n );\n this.clientConnectionString = clientDbUrl;\n this.connectionPromise = this.getOrCreateCachedConnection(clientDbUrl);\n return this.connectionPromise;\n }\n\n async disconnectByConnectionString(connectionString: string): Promise<void> {\n const existing = MultiTenantRepository.connections.get(connectionString);\n if (!existing) return;\n try {\n await existing.disconnect();\n this.context.info(`✅ Disconnected from database: ${connectionString}`);\n } catch (error) {\n this.context.error(`❌ Error disconnecting from database: ${connectionString}`, error);\n } finally {\n MultiTenantRepository.connections.delete(connectionString);\n }\n }\n\n async disconnectClient(): Promise<void> {\n const clientDbUrl = await this.getClientDbConnectionString(\n this.businessId,\n this.appId,\n );\n await this.disconnectByConnectionString(clientDbUrl);\n this.clientConnectionString = undefined;\n this.connectionPromise = undefined;\n }\n\n protected getTenantModel(\n modelName: string,\n schema: Schema<any>,\n collectionName?: string,\n ): Model<any> {\n const connection = this.getConnection();\n if (!connection) {\n throw new Error(\"database connection not established\");\n }\n return this.getModel(connection, modelName, schema, collectionName);\n }\n\n protected model<T>(model: Model<T>, collectionName?: string): Model<T> {\n return this.getTenantModel(\n model.modelName,\n model.schema,\n collectionName,\n ) as Model<T>;\n }\n\n protected getModel(\n connection: mongoose.Mongoose,\n modelName: string,\n schema: Schema<any>,\n collectionName?: string,\n ): Model<any> {\n if (connection.models[modelName]) {\n return connection.models[modelName] as Model<any>;\n }\n return connection.model(modelName, schema, collectionName);\n }\n}\n\nexport abstract class TenantModelRepository<T> extends MultiTenantRepository {\n protected abstract readonly modelDef: Model<T>;\n\n protected get dbModel(): Model<T> {\n return this.model(this.modelDef);\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"multi-tenant.repository.js","names":["_mongoose","_interopRequireWildcard","require","crypto","_identity","_keyvaultSecrets","_enums","_cache","_secrets","_configMapping","_dec","_dec2","_dec3","_class","_MultiTenantRepository","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","_applyDecoratedDescriptor","l","a","keys","forEach","enumerable","configurable","initializer","writable","slice","reverse","reduce","value","tenantDbCache","createCache","tenantBridgeCache","encryptionKeyCache","WithTenantDb","_target","_propertyKey","descriptor","originalMethod","args","ensureClientConnection","apply","MultiTenantRepository","exports","Cacheable","cache","key","getContext","instance","context","businessId","appId","serviceDbType","constructor","config","serviceDBType","tenantBridgeConfig","dbConnectionEncryptionKey","clientConnectionString","connectionPromise","tenantBridgeEnvKey","tenantBridgeSecretKey","AzureSecretKeysEnum","DB_CONNECTION_STRING_TENANT_BRIDGE","getConnectionLogLabel","connectionString","match","dbName","toLowerCase","includes","getEncryptionIv","iv","process","env","DB_CONNECTION_STRING_ENCRYPTION_IV","Buffer","alloc","normalizeFixedSize","label","utf8Value","from","length","base64Value","hexValue","Error","getOrCreateCachedConnection","existing","connections","connection","readyState","dbLabel","info","mongoose","Mongoose","connect","serverSelectionTimeoutMS","connectTimeoutMS","socketTimeoutMS","err","error","message","name","code","stack","toObjectId","id","fieldName","Types","ObjectId","isValid","getTenantBridgeSrvDbConnectionString","envKey","localUri","undefined","vault","AZURE_KEY_VAULT_NAME","secretKey","dbUrl","getAzureVaultSecretByKey","getDbConnectionEncryptionKey","_secret$value","DB_CONNECTION_STRING_ENCRYPTION_KEY","vaultUrl","credential","DefaultAzureCredential","client","SecretClient","secret","getSecret","decryptConnectionString","encryptedValue","keyBuffer","normalizeEncryptionKey","ivBuffer","decipher","createDecipheriv","decrypted","update","final","utf8Key","base64Key","hexKey","getClientDbConnectionString","resolvedServiceDbType","tenantBridgeUrl","ConfigMapping","getModel","CONFIG_MAPPING_DOCUMENT_NAME","ConfigMappingModel","schema","CONFIG_MAPPING_COLLECTION_NAME","filter","configMapping","findOne","lean","exec","decryptedConnectionString","getConnection","clientDbUrl","disconnectByConnectionString","disconnect","delete","disconnectClient","getTenantModel","modelName","collectionName","model","models","Map","prototype","TenantModelRepository","modelDef","dbModel"],"sources":["../../../src/repositories/multi-tenant.repository.ts"],"sourcesContent":["import mongoose, { Model, Schema, Types } from \"mongoose\";\nimport * as crypto from \"crypto\";\nimport { InvocationContext } from \"@azure/functions\";\nimport { DefaultAzureCredential } from \"@azure/identity\";\nimport { SecretClient } from \"@azure/keyvault-secrets\";\nimport { AzureSecretKeysEnum } from \"../enums\";\nimport { Cacheable, createCache } from \"../utils/cache\";\nimport { getAzureVaultSecretByKey } from \"../utils/secrets\";\nimport {\n CONFIG_MAPPING_COLLECTION_NAME,\n CONFIG_MAPPING_DOCUMENT_NAME,\n ConfigMappingModel,\n IConfigMapping,\n} from \"../models/config-mapping.model\";\n\ntype ConnectionMap = Map<string, mongoose.Mongoose>;\n\ntype TenantBridgeConfig = {\n tenantBridgeEnvKey?: string;\n tenantBridgeSecretKey?: AzureSecretKeysEnum;\n};\n\nconst tenantDbCache = createCache(\"tenant-db\", 600);\nconst tenantBridgeCache = createCache(\"tenant-bridge-db-connection-string\", 1800);\nconst encryptionKeyCache = createCache(\"db-enc-key\", 1800);\n\n/**\n * Decorator that ensures tenant DB is connected before the method runs.\n */\nexport function WithTenantDb(\n _target: any,\n _propertyKey: string | symbol,\n descriptor: TypedPropertyDescriptor<(...args: any[]) => Promise<any>>,\n): void {\n if (!descriptor.value) return;\n const originalMethod = descriptor.value;\n descriptor.value = async function (\n this: MultiTenantRepository,\n ...args: any[]\n ) {\n await this.ensureClientConnection();\n return originalMethod.apply(this, args);\n };\n}\n\nexport class MultiTenantRepository {\n private static connections: ConnectionMap = new Map();\n private readonly context: InvocationContext;\n private readonly tenantBridgeConfig: TenantBridgeConfig;\n private readonly businessId: string;\n private readonly appId?: string;\n private readonly serviceDBType?: string;\n private dbConnectionEncryptionKey?: string;\n private clientConnectionString?: string;\n private connectionPromise?: Promise<mongoose.Mongoose>;\n\n constructor(\n context: InvocationContext,\n businessId: string,\n appId?: string,\n config?: TenantBridgeConfig,\n serviceDBType?: string,\n ) {\n this.context = context;\n this.businessId = businessId;\n this.appId = appId;\n this.serviceDBType = serviceDBType ?? \"main\";\n this.tenantBridgeConfig = {\n tenantBridgeEnvKey: \"TENANT_BRIDGE_DB_URI\",\n tenantBridgeSecretKey: AzureSecretKeysEnum.DB_CONNECTION_STRING_TENANT_BRIDGE,\n ...config,\n };\n\n this.connectionPromise = this.ensureClientConnection();\n }\n\n private getConnectionLogLabel(connectionString: string): string {\n const match = connectionString.match(/\\/([^/?]+)(\\?|$)/);\n const dbName = match?.[1] || \"unknown\";\n if (dbName.toLowerCase().includes(\"tenantbridge\")) {\n return \"TenantBridge-DB\";\n }\n if (dbName.toLowerCase().includes(\"user\")) {\n return \"Auth-DB\";\n }\n return `${dbName}-DB`;\n }\n\n private getEncryptionIv(): Buffer {\n const iv = process.env.DB_CONNECTION_STRING_ENCRYPTION_IV;\n if (!iv) {\n return Buffer.alloc(16, 0);\n }\n return this.normalizeFixedSize(iv, \"IV\");\n }\n\n private normalizeFixedSize(value: string, label: string): Buffer {\n const utf8Value = Buffer.from(value, \"utf8\");\n if (utf8Value.length === 16) {\n return utf8Value;\n }\n\n const base64Value = Buffer.from(value, \"base64\");\n if (base64Value.length === 16) {\n return base64Value;\n }\n\n const hexValue = Buffer.from(value, \"hex\");\n if (hexValue.length === 16) {\n return hexValue;\n }\n\n throw new Error(\n `${label} must be 16 bytes for aes-128-cbc (got ${utf8Value.length})`,\n );\n }\n\n private async getOrCreateCachedConnection(\n connectionString: string,\n ): Promise<mongoose.Mongoose> {\n const existing = MultiTenantRepository.connections.get(connectionString);\n if (existing && existing.connection.readyState === 1) {\n return existing;\n }\n\n const dbLabel = this.getConnectionLogLabel(connectionString);\n this.context.info(`Initializing database connection (${dbLabel})...`);\n const instance = new mongoose.Mongoose();\n\n try {\n await instance.connect(connectionString, {\n serverSelectionTimeoutMS: 10000,\n connectTimeoutMS: 10000,\n socketTimeoutMS: 45000,\n });\n this.context.info(`✅ MongoDB connected successfully (${dbLabel})`);\n MultiTenantRepository.connections.set(connectionString, instance);\n return instance;\n } catch (err: any) {\n this.context.error(\n `❌ MongoDB connection error for (${dbLabel})`,\n {\n message: err.message,\n name: err.name,\n code: err.code,\n stack: err.stack,\n },\n );\n throw new Error(`Failed to connect to MongoDB: ${err.message}`);\n }\n }\n\n private toObjectId(id: string, fieldName: string): Types.ObjectId {\n if (!Types.ObjectId.isValid(id)) {\n throw new Error(`Invalid ${fieldName}`);\n }\n return new Types.ObjectId(id);\n }\n\n @Cacheable({\n cache: tenantBridgeCache,\n key: () => [\"tenant-bridge\"],\n getContext: (instance: unknown) =>\n (instance as MultiTenantRepository).context,\n })\n async getTenantBridgeSrvDbConnectionString(): Promise<string> {\n const envKey = this.tenantBridgeConfig.tenantBridgeEnvKey;\n const localUri =\n (envKey ? process.env[envKey] : undefined);\n\n if (localUri) {\n return localUri;\n }\n\n const vault = process.env.AZURE_KEY_VAULT_NAME || \"\";\n const secretKey =\n this.tenantBridgeConfig.tenantBridgeSecretKey ||\n AzureSecretKeysEnum.DB_CONNECTION_STRING_TENANT_BRIDGE;\n\n const dbUrl = await getAzureVaultSecretByKey(\n this.context,\n vault,\n secretKey,\n );\n if (!dbUrl) {\n throw new Error(\"TenantBridge database connection string not found\");\n }\n return dbUrl;\n }\n\n @Cacheable({\n cache: encryptionKeyCache,\n key: () => [\"key\"],\n getContext: (instance: unknown) =>\n (instance as MultiTenantRepository).context,\n })\n private async getDbConnectionEncryptionKey(): Promise<string> {\n if (this.dbConnectionEncryptionKey) {\n return this.dbConnectionEncryptionKey;\n }\n\n const envKey = process.env.DB_CONNECTION_STRING_ENCRYPTION_KEY;\n if (envKey) {\n this.dbConnectionEncryptionKey = envKey;\n return envKey;\n }\n\n const vault = process.env.AZURE_KEY_VAULT_NAME || \"\";\n if (!vault) {\n throw new Error(\"AZURE_KEY_VAULT_NAME is required to fetch encryption key\");\n }\n const vaultUrl = `https://${vault}.vault.azure.net`;\n const credential = new DefaultAzureCredential();\n const client = new SecretClient(vaultUrl, credential);\n const secret = await client.getSecret(\"DB-CONNECTION-STRING-ENCRYPTION-KEY\");\n const key = secret.value ?? \"\";\n if (!key) {\n throw new Error(\"DB connection string encryption key not found\");\n }\n this.dbConnectionEncryptionKey = key;\n return key;\n }\n\n private async decryptConnectionString(encryptedValue: string): Promise<string> {\n const key = await this.getDbConnectionEncryptionKey();\n const keyBuffer = this.normalizeEncryptionKey(key);\n\n const ivBuffer = this.getEncryptionIv();\n const decipher = crypto.createDecipheriv(\"aes-128-cbc\", keyBuffer, ivBuffer);\n let decrypted = decipher.update(encryptedValue, \"base64\", \"utf8\");\n decrypted += decipher.final(\"utf8\");\n return decrypted;\n }\n\n private normalizeEncryptionKey(key: string): Buffer {\n const utf8Key = Buffer.from(key, \"utf8\");\n if (utf8Key.length === 16) {\n return utf8Key;\n }\n\n const base64Key = Buffer.from(key, \"base64\");\n if (base64Key.length === 16) {\n return base64Key;\n }\n\n const hexKey = Buffer.from(key, \"hex\");\n if (hexKey.length === 16) {\n return hexKey;\n }\n\n throw new Error(\n `DB connection string encryption key must be 16 bytes for aes-128-cbc (got ${utf8Key.length})`,\n );\n }\n\n @Cacheable({\n cache: tenantDbCache,\n key: (businessId: string, appId?: string, serviceDbType?: string) => [\n businessId,\n appId,\n serviceDbType,\n ],\n getContext: (instance: unknown) =>\n (instance as MultiTenantRepository).context,\n })\n async getClientDbConnectionString(\n businessId: string,\n appId?: string,\n serviceDBType?: string,\n ): Promise<string> {\n if (!appId) {\n throw new Error(\"appId is required to resolve tenant client database\");\n }\n const resolvedServiceDbType = serviceDBType ?? \"main\";\n const tenantBridgeUrl = await this.getTenantBridgeSrvDbConnectionString();\n const connection = await this.getOrCreateCachedConnection(tenantBridgeUrl);\n\n const ConfigMapping = this.getModel(\n connection,\n CONFIG_MAPPING_DOCUMENT_NAME,\n ConfigMappingModel.schema,\n CONFIG_MAPPING_COLLECTION_NAME,\n ) as Model<IConfigMapping>;\n\n const filter: Record<string, unknown> = {\n businessId: this.toObjectId(businessId, \"businessId\"),\n };\n filter.appId = appId;\n filter.serviceDBType = resolvedServiceDbType;\n\n const configMapping =\n (await ConfigMapping.findOne(filter).lean().exec()) as\n | IConfigMapping\n | null;\n if (!configMapping?.connectionString) {\n throw new Error(\"Config mapping not found for this business\");\n }\n const decryptedConnectionString = await this.decryptConnectionString(\n configMapping.connectionString,\n );\n this.context.info(\"Resolved tenant database mapping from TenantBridge\");\n return decryptedConnectionString;\n }\n\n protected getConnection(): mongoose.Mongoose | undefined {\n if (!this.clientConnectionString) return undefined;\n return MultiTenantRepository.connections.get(this.clientConnectionString);\n }\n\n protected async ensureClientConnection(): Promise<mongoose.Mongoose> {\n if (this.connectionPromise) {\n return this.connectionPromise;\n }\n\n if (this.clientConnectionString) {\n const existing = this.getConnection();\n if (existing && existing.connection.readyState === 1) {\n return existing;\n }\n }\n\n const clientDbUrl = await this.getClientDbConnectionString(\n this.businessId,\n this.appId,\n this.serviceDBType,\n );\n this.clientConnectionString = clientDbUrl;\n this.connectionPromise = this.getOrCreateCachedConnection(clientDbUrl);\n return this.connectionPromise;\n }\n\n async disconnectByConnectionString(connectionString: string): Promise<void> {\n const existing = MultiTenantRepository.connections.get(connectionString);\n if (!existing) return;\n try {\n await existing.disconnect();\n this.context.info(`✅ Disconnected from database (${this.getConnectionLogLabel(connectionString)})`);\n } catch (error) {\n this.context.error(`❌ Error disconnecting from database (${this.getConnectionLogLabel(connectionString)})`, error);\n } finally {\n MultiTenantRepository.connections.delete(connectionString);\n }\n }\n\n async disconnectClient(): Promise<void> {\n const clientDbUrl = await this.getClientDbConnectionString(\n this.businessId,\n this.appId,\n );\n await this.disconnectByConnectionString(clientDbUrl);\n this.clientConnectionString = undefined;\n this.connectionPromise = undefined;\n }\n\n protected getTenantModel(\n modelName: string,\n schema: Schema<any>,\n collectionName?: string,\n ): Model<any> {\n const connection = this.getConnection();\n if (!connection) {\n throw new Error(\"database connection not established\");\n }\n return this.getModel(connection, modelName, schema, collectionName);\n }\n\n protected model<T>(model: Model<T>, collectionName?: string): Model<T> {\n return this.getTenantModel(\n model.modelName,\n model.schema,\n collectionName,\n ) as Model<T>;\n }\n\n protected getModel(\n connection: mongoose.Mongoose,\n modelName: string,\n schema: Schema<any>,\n collectionName?: string,\n ): Model<any> {\n if (connection.models[modelName]) {\n return connection.models[modelName] as Model<any>;\n }\n return connection.model(modelName, schema, collectionName);\n }\n}\n\nexport abstract class TenantModelRepository<T> extends MultiTenantRepository {\n protected abstract readonly modelDef: Model<T>;\n\n protected get dbModel(): Model<T> {\n return this.model(this.modelDef);\n }\n}\n"],"mappings":";;;;;AAAA,IAAAA,SAAA,GAAAC,uBAAA,CAAAC,OAAA;AACA,IAAAC,MAAA,GAAAF,uBAAA,CAAAC,OAAA;AAEA,IAAAE,SAAA,GAAAF,OAAA;AACA,IAAAG,gBAAA,GAAAH,OAAA;AACA,IAAAI,MAAA,GAAAJ,OAAA;AACA,IAAAK,MAAA,GAAAL,OAAA;AACA,IAAAM,QAAA,GAAAN,OAAA;AACA,IAAAO,cAAA,GAAAP,OAAA;AAKwC,IAAAQ,IAAA,EAAAC,KAAA,EAAAC,KAAA,EAAAC,MAAA,EAAAC,sBAAA;AAAA,SAAAb,wBAAAc,CAAA,EAAAC,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAhB,uBAAA,YAAAA,CAAAc,CAAA,EAAAC,CAAA,SAAAA,CAAA,IAAAD,CAAA,IAAAA,CAAA,CAAAK,UAAA,SAAAL,CAAA,MAAAM,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAC,OAAA,EAAAV,CAAA,iBAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,SAAAQ,CAAA,MAAAF,CAAA,GAAAL,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAG,CAAA,CAAAK,GAAA,CAAAX,CAAA,UAAAM,CAAA,CAAAM,GAAA,CAAAZ,CAAA,GAAAM,CAAA,CAAAO,GAAA,CAAAb,CAAA,EAAAQ,CAAA,gBAAAP,CAAA,IAAAD,CAAA,gBAAAC,CAAA,OAAAa,cAAA,CAAAC,IAAA,CAAAf,CAAA,EAAAC,CAAA,OAAAM,CAAA,IAAAD,CAAA,GAAAU,MAAA,CAAAC,cAAA,KAAAD,MAAA,CAAAE,wBAAA,CAAAlB,CAAA,EAAAC,CAAA,OAAAM,CAAA,CAAAK,GAAA,IAAAL,CAAA,CAAAM,GAAA,IAAAP,CAAA,CAAAE,CAAA,EAAAP,CAAA,EAAAM,CAAA,IAAAC,CAAA,CAAAP,CAAA,IAAAD,CAAA,CAAAC,CAAA,WAAAO,CAAA,KAAAR,CAAA,EAAAC,CAAA;AAAA,SAAAkB,0BAAAZ,CAAA,EAAAP,CAAA,EAAAG,CAAA,EAAAC,CAAA,EAAAgB,CAAA,QAAAC,CAAA,cAAAL,MAAA,CAAAM,IAAA,CAAAlB,CAAA,EAAAmB,OAAA,WAAAhB,CAAA,IAAAc,CAAA,CAAAd,CAAA,IAAAH,CAAA,CAAAG,CAAA,OAAAc,CAAA,CAAAG,UAAA,KAAAH,CAAA,CAAAG,UAAA,EAAAH,CAAA,CAAAI,YAAA,KAAAJ,CAAA,CAAAI,YAAA,cAAAJ,CAAA,IAAAA,CAAA,CAAAK,WAAA,MAAAL,CAAA,CAAAM,QAAA,QAAAN,CAAA,GAAAlB,CAAA,CAAAyB,KAAA,GAAAC,OAAA,GAAAC,MAAA,WAAA3B,CAAA,EAAAC,CAAA,WAAAA,CAAA,CAAAG,CAAA,EAAAP,CAAA,EAAAG,CAAA,KAAAA,CAAA,KAAAkB,CAAA,GAAAD,CAAA,eAAAC,CAAA,CAAAK,WAAA,KAAAL,CAAA,CAAAU,KAAA,GAAAV,CAAA,CAAAK,WAAA,GAAAL,CAAA,CAAAK,WAAA,CAAAX,IAAA,CAAAK,CAAA,YAAAC,CAAA,CAAAK,WAAA,uBAAAL,CAAA,CAAAK,WAAA,IAAAV,MAAA,CAAAC,cAAA,CAAAV,CAAA,EAAAP,CAAA,EAAAqB,CAAA,WAAAA,CAAA;AASxC,MAAMW,aAAa,GAAG,IAAAC,kBAAW,EAAC,WAAW,EAAE,GAAG,CAAC;AACnD,MAAMC,iBAAiB,GAAG,IAAAD,kBAAW,EAAC,oCAAoC,EAAE,IAAI,CAAC;AACjF,MAAME,kBAAkB,GAAG,IAAAF,kBAAW,EAAC,YAAY,EAAE,IAAI,CAAC;;AAE1D;AACA;AACA;AACO,SAASG,YAAYA,CAC1BC,OAAY,EACZC,YAA6B,EAC7BC,UAAqE,EAC/D;EACN,IAAI,CAACA,UAAU,CAACR,KAAK,EAAE;EACvB,MAAMS,cAAc,GAAGD,UAAU,CAACR,KAAK;EACvCQ,UAAU,CAACR,KAAK,GAAG,gBAEjB,GAAGU,IAAW,EACd;IACA,MAAM,IAAI,CAACC,sBAAsB,CAAC,CAAC;IACnC,OAAOF,cAAc,CAACG,KAAK,CAAC,IAAI,EAAEF,IAAI,CAAC;EACzC,CAAC;AACH;AAAC,IAEYG,qBAAqB,GAAAC,OAAA,CAAAD,qBAAA,IAAAjD,IAAA,GAkH/B,IAAAmD,gBAAS,EAAC;EACTC,KAAK,EAAEb,iBAAiB;EACxBc,GAAG,EAAEA,CAAA,KAAM,CAAC,eAAe,CAAC;EAC5BC,UAAU,EAAGC,QAAiB,IAC3BA,QAAQ,CAA2BC;AACxC,CAAC,CAAC,EAAAvD,KAAA,GA0BD,IAAAkD,gBAAS,EAAC;EACTC,KAAK,EAAEZ,kBAAkB;EACzBa,GAAG,EAAEA,CAAA,KAAM,CAAC,KAAK,CAAC;EAClBC,UAAU,EAAGC,QAAiB,IAC3BA,QAAQ,CAA2BC;AACxC,CAAC,CAAC,EAAAtD,KAAA,GA4DD,IAAAiD,gBAAS,EAAC;EACTC,KAAK,EAAEf,aAAa;EACpBgB,GAAG,EAAEA,CAACI,UAAkB,EAAEC,KAAc,EAAEC,aAAsB,KAAK,CACnEF,UAAU,EACVC,KAAK,EACLC,aAAa,CACd;EACDL,UAAU,EAAGC,QAAiB,IAC3BA,QAAQ,CAA2BC;AACxC,CAAC,CAAC,EAAArD,MAAA,IAAAC,sBAAA,GA3NG,MAAM6C,qBAAqB,CAAC;EAWjCW,WAAWA,CACTJ,OAA0B,EAC1BC,UAAkB,EAClBC,KAAc,EACdG,MAA2B,EAC3BC,aAAsB,EACtB;IAAA,KAfeN,OAAO;IAAA,KACPO,kBAAkB;IAAA,KAClBN,UAAU;IAAA,KACVC,KAAK;IAAA,KACLI,aAAa;IAAA,KACtBE,yBAAyB;IAAA,KACzBC,sBAAsB;IAAA,KACtBC,iBAAiB;IASvB,IAAI,CAACV,OAAO,GAAGA,OAAO;IACtB,IAAI,CAACC,UAAU,GAAGA,UAAU;IAC5B,IAAI,CAACC,KAAK,GAAGA,KAAK;IAClB,IAAI,CAACI,aAAa,GAAGA,aAAa,WAAbA,aAAa,GAAI,MAAM;IAC5C,IAAI,CAACC,kBAAkB,GAAG;MACxBI,kBAAkB,EAAE,sBAAsB;MAC1CC,qBAAqB,EAAEC,0BAAmB,CAACC,kCAAkC;MAC7E,GAAGT;IACL,CAAC;IAED,IAAI,CAACK,iBAAiB,GAAG,IAAI,CAACnB,sBAAsB,CAAC,CAAC;EACxD;EAEQwB,qBAAqBA,CAACC,gBAAwB,EAAU;IAC9D,MAAMC,KAAK,GAAGD,gBAAgB,CAACC,KAAK,CAAC,kBAAkB,CAAC;IACxD,MAAMC,MAAM,GAAG,CAAAD,KAAK,oBAALA,KAAK,CAAG,CAAC,CAAC,KAAI,SAAS;IACtC,IAAIC,MAAM,CAACC,WAAW,CAAC,CAAC,CAACC,QAAQ,CAAC,cAAc,CAAC,EAAE;MACjD,OAAO,iBAAiB;IAC1B;IACA,IAAIF,MAAM,CAACC,WAAW,CAAC,CAAC,CAACC,QAAQ,CAAC,MAAM,CAAC,EAAE;MACzC,OAAO,SAAS;IAClB;IACA,OAAO,GAAGF,MAAM,KAAK;EACvB;EAEQG,eAAeA,CAAA,EAAW;IAChC,MAAMC,EAAE,GAAGC,OAAO,CAACC,GAAG,CAACC,kCAAkC;IACzD,IAAI,CAACH,EAAE,EAAE;MACP,OAAOI,MAAM,CAACC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5B;IACA,OAAO,IAAI,CAACC,kBAAkB,CAACN,EAAE,EAAE,IAAI,CAAC;EAC1C;EAEQM,kBAAkBA,CAAChD,KAAa,EAAEiD,KAAa,EAAU;IAC/D,MAAMC,SAAS,GAAGJ,MAAM,CAACK,IAAI,CAACnD,KAAK,EAAE,MAAM,CAAC;IAC5C,IAAIkD,SAAS,CAACE,MAAM,KAAK,EAAE,EAAE;MAC3B,OAAOF,SAAS;IAClB;IAEA,MAAMG,WAAW,GAAGP,MAAM,CAACK,IAAI,CAACnD,KAAK,EAAE,QAAQ,CAAC;IAChD,IAAIqD,WAAW,CAACD,MAAM,KAAK,EAAE,EAAE;MAC7B,OAAOC,WAAW;IACpB;IAEA,MAAMC,QAAQ,GAAGR,MAAM,CAACK,IAAI,CAACnD,KAAK,EAAE,KAAK,CAAC;IAC1C,IAAIsD,QAAQ,CAACF,MAAM,KAAK,EAAE,EAAE;MAC1B,OAAOE,QAAQ;IACjB;IAEA,MAAM,IAAIC,KAAK,CACb,GAAGN,KAAK,0CAA0CC,SAAS,CAACE,MAAM,GACpE,CAAC;EACH;EAEA,MAAcI,2BAA2BA,CACvCpB,gBAAwB,EACI;IAC5B,MAAMqB,QAAQ,GAAG5C,qBAAqB,CAAC6C,WAAW,CAAC7E,GAAG,CAACuD,gBAAgB,CAAC;IACxE,IAAIqB,QAAQ,IAAIA,QAAQ,CAACE,UAAU,CAACC,UAAU,KAAK,CAAC,EAAE;MACpD,OAAOH,QAAQ;IACjB;IAEA,MAAMI,OAAO,GAAG,IAAI,CAAC1B,qBAAqB,CAACC,gBAAgB,CAAC;IAC5D,IAAI,CAAChB,OAAO,CAAC0C,IAAI,CAAC,qCAAqCD,OAAO,MAAM,CAAC;IACrE,MAAM1C,QAAQ,GAAG,IAAI4C,iBAAQ,CAACC,QAAQ,CAAC,CAAC;IAExC,IAAI;MACF,MAAM7C,QAAQ,CAAC8C,OAAO,CAAC7B,gBAAgB,EAAE;QACvC8B,wBAAwB,EAAE,KAAK;QAC/BC,gBAAgB,EAAE,KAAK;QACvBC,eAAe,EAAE;MACnB,CAAC,CAAC;MACF,IAAI,CAAChD,OAAO,CAAC0C,IAAI,CAAC,qCAAqCD,OAAO,GAAG,CAAC;MAClEhD,qBAAqB,CAAC6C,WAAW,CAAC5E,GAAG,CAACsD,gBAAgB,EAAEjB,QAAQ,CAAC;MACjE,OAAOA,QAAQ;IACjB,CAAC,CAAC,OAAOkD,GAAQ,EAAE;MACjB,IAAI,CAACjD,OAAO,CAACkD,KAAK,CAChB,mCAAmCT,OAAO,GAAG,EAC7C;QACEU,OAAO,EAAEF,GAAG,CAACE,OAAO;QACpBC,IAAI,EAAEH,GAAG,CAACG,IAAI;QACdC,IAAI,EAAEJ,GAAG,CAACI,IAAI;QACdC,KAAK,EAAEL,GAAG,CAACK;MACb,CACF,CAAC;MACD,MAAM,IAAInB,KAAK,CAAC,iCAAiCc,GAAG,CAACE,OAAO,EAAE,CAAC;IACjE;EACF;EAEQI,UAAUA,CAACC,EAAU,EAAEC,SAAiB,EAAkB;IAChE,IAAI,CAACC,eAAK,CAACC,QAAQ,CAACC,OAAO,CAACJ,EAAE,CAAC,EAAE;MAC/B,MAAM,IAAIrB,KAAK,CAAC,WAAWsB,SAAS,EAAE,CAAC;IACzC;IACA,OAAO,IAAIC,eAAK,CAACC,QAAQ,CAACH,EAAE,CAAC;EAC/B;EAEA,MAMMK,oCAAoCA,CAAA,EAAoB;IAC5D,MAAMC,MAAM,GAAG,IAAI,CAACvD,kBAAkB,CAACI,kBAAkB;IACzD,MAAMoD,QAAQ,GACXD,MAAM,GAAGvC,OAAO,CAACC,GAAG,CAACsC,MAAM,CAAC,GAAGE,SAAU;IAE5C,IAAID,QAAQ,EAAE;MACZ,OAAOA,QAAQ;IACjB;IAEA,MAAME,KAAK,GAAG1C,OAAO,CAACC,GAAG,CAAC0C,oBAAoB,IAAI,EAAE;IACpD,MAAMC,SAAS,GACb,IAAI,CAAC5D,kBAAkB,CAACK,qBAAqB,IAC7CC,0BAAmB,CAACC,kCAAkC;IAExD,MAAMsD,KAAK,GAAG,MAAM,IAAAC,iCAAwB,EAC1C,IAAI,CAACrE,OAAO,EACZiE,KAAK,EACLE,SACF,CAAC;IACD,IAAI,CAACC,KAAK,EAAE;MACV,MAAM,IAAIjC,KAAK,CAAC,mDAAmD,CAAC;IACtE;IACA,OAAOiC,KAAK;EACd;EAEA,MAMcE,4BAA4BA,CAAA,EAAoB;IAAA,IAAAC,aAAA;IAC5D,IAAI,IAAI,CAAC/D,yBAAyB,EAAE;MAClC,OAAO,IAAI,CAACA,yBAAyB;IACvC;IAEA,MAAMsD,MAAM,GAAGvC,OAAO,CAACC,GAAG,CAACgD,mCAAmC;IAC9D,IAAIV,MAAM,EAAE;MACV,IAAI,CAACtD,yBAAyB,GAAGsD,MAAM;MACvC,OAAOA,MAAM;IACf;IAEA,MAAMG,KAAK,GAAG1C,OAAO,CAACC,GAAG,CAAC0C,oBAAoB,IAAI,EAAE;IACpD,IAAI,CAACD,KAAK,EAAE;MACV,MAAM,IAAI9B,KAAK,CAAC,0DAA0D,CAAC;IAC7E;IACA,MAAMsC,QAAQ,GAAG,WAAWR,KAAK,kBAAkB;IACnD,MAAMS,UAAU,GAAG,IAAIC,gCAAsB,CAAC,CAAC;IAC/C,MAAMC,MAAM,GAAG,IAAIC,6BAAY,CAACJ,QAAQ,EAAEC,UAAU,CAAC;IACrD,MAAMI,MAAM,GAAG,MAAMF,MAAM,CAACG,SAAS,CAAC,qCAAqC,CAAC;IAC5E,MAAMlF,GAAG,IAAA0E,aAAA,GAAGO,MAAM,CAAClG,KAAK,YAAA2F,aAAA,GAAI,EAAE;IAC9B,IAAI,CAAC1E,GAAG,EAAE;MACR,MAAM,IAAIsC,KAAK,CAAC,+CAA+C,CAAC;IAClE;IACA,IAAI,CAAC3B,yBAAyB,GAAGX,GAAG;IACpC,OAAOA,GAAG;EACZ;EAEA,MAAcmF,uBAAuBA,CAACC,cAAsB,EAAmB;IAC7E,MAAMpF,GAAG,GAAG,MAAM,IAAI,CAACyE,4BAA4B,CAAC,CAAC;IACrD,MAAMY,SAAS,GAAG,IAAI,CAACC,sBAAsB,CAACtF,GAAG,CAAC;IAElD,MAAMuF,QAAQ,GAAG,IAAI,CAAC/D,eAAe,CAAC,CAAC;IACvC,MAAMgE,QAAQ,GAAGpJ,MAAM,CAACqJ,gBAAgB,CAAC,aAAa,EAAEJ,SAAS,EAAEE,QAAQ,CAAC;IAC5E,IAAIG,SAAS,GAAGF,QAAQ,CAACG,MAAM,CAACP,cAAc,EAAE,QAAQ,EAAE,MAAM,CAAC;IACjEM,SAAS,IAAIF,QAAQ,CAACI,KAAK,CAAC,MAAM,CAAC;IACnC,OAAOF,SAAS;EAClB;EAEQJ,sBAAsBA,CAACtF,GAAW,EAAU;IAClD,MAAM6F,OAAO,GAAGhE,MAAM,CAACK,IAAI,CAAClC,GAAG,EAAE,MAAM,CAAC;IACxC,IAAI6F,OAAO,CAAC1D,MAAM,KAAK,EAAE,EAAE;MACzB,OAAO0D,OAAO;IAChB;IAEA,MAAMC,SAAS,GAAGjE,MAAM,CAACK,IAAI,CAAClC,GAAG,EAAE,QAAQ,CAAC;IAC5C,IAAI8F,SAAS,CAAC3D,MAAM,KAAK,EAAE,EAAE;MAC3B,OAAO2D,SAAS;IAClB;IAEA,MAAMC,MAAM,GAAGlE,MAAM,CAACK,IAAI,CAAClC,GAAG,EAAE,KAAK,CAAC;IACtC,IAAI+F,MAAM,CAAC5D,MAAM,KAAK,EAAE,EAAE;MACxB,OAAO4D,MAAM;IACf;IAEA,MAAM,IAAIzD,KAAK,CACb,6EAA6EuD,OAAO,CAAC1D,MAAM,GAC7F,CAAC;EACH;EAEA,MAUM6D,2BAA2BA,CAC/B5F,UAAkB,EAClBC,KAAc,EACdI,aAAsB,EACL;IACjB,IAAI,CAACJ,KAAK,EAAE;MACV,MAAM,IAAIiC,KAAK,CAAC,qDAAqD,CAAC;IACxE;IACA,MAAM2D,qBAAqB,GAAGxF,aAAa,WAAbA,aAAa,GAAI,MAAM;IACrD,MAAMyF,eAAe,GAAG,MAAM,IAAI,CAAClC,oCAAoC,CAAC,CAAC;IACzE,MAAMtB,UAAU,GAAG,MAAM,IAAI,CAACH,2BAA2B,CAAC2D,eAAe,CAAC;IAE1E,MAAMC,aAAa,GAAG,IAAI,CAACC,QAAQ,CACjC1D,UAAU,EACV2D,2CAA4B,EAC5BC,iCAAkB,CAACC,MAAM,EACzBC,6CACF,CAA0B;IAE1B,MAAMC,MAA+B,GAAG;MACtCrG,UAAU,EAAE,IAAI,CAACsD,UAAU,CAACtD,UAAU,EAAE,YAAY;IACtD,CAAC;IACDqG,MAAM,CAACpG,KAAK,GAAGA,KAAK;IACpBoG,MAAM,CAAChG,aAAa,GAAGwF,qBAAqB;IAE5C,MAAMS,aAAa,GAChB,MAAMP,aAAa,CAACQ,OAAO,CAACF,MAAM,CAAC,CAACG,IAAI,CAAC,CAAC,CAACC,IAAI,CAAC,CAEzC;IACV,IAAI,EAACH,aAAa,YAAbA,aAAa,CAAEvF,gBAAgB,GAAE;MACpC,MAAM,IAAImB,KAAK,CAAC,4CAA4C,CAAC;IAC/D;IACA,MAAMwE,yBAAyB,GAAG,MAAM,IAAI,CAAC3B,uBAAuB,CAClEuB,aAAa,CAACvF,gBAChB,CAAC;IACD,IAAI,CAAChB,OAAO,CAAC0C,IAAI,CAAC,oDAAoD,CAAC;IACvE,OAAOiE,yBAAyB;EAClC;EAEUC,aAAaA,CAAA,EAAkC;IACvD,IAAI,CAAC,IAAI,CAACnG,sBAAsB,EAAE,OAAOuD,SAAS;IAClD,OAAOvE,qBAAqB,CAAC6C,WAAW,CAAC7E,GAAG,CAAC,IAAI,CAACgD,sBAAsB,CAAC;EAC3E;EAEA,MAAgBlB,sBAAsBA,CAAA,EAA+B;IACnE,IAAI,IAAI,CAACmB,iBAAiB,EAAE;MAC1B,OAAO,IAAI,CAACA,iBAAiB;IAC/B;IAEA,IAAI,IAAI,CAACD,sBAAsB,EAAE;MAC/B,MAAM4B,QAAQ,GAAG,IAAI,CAACuE,aAAa,CAAC,CAAC;MACrC,IAAIvE,QAAQ,IAAIA,QAAQ,CAACE,UAAU,CAACC,UAAU,KAAK,CAAC,EAAE;QACpD,OAAOH,QAAQ;MACjB;IACF;IAEA,MAAMwE,WAAW,GAAG,MAAM,IAAI,CAAChB,2BAA2B,CACxD,IAAI,CAAC5F,UAAU,EACf,IAAI,CAACC,KAAK,EACV,IAAI,CAACI,aACP,CAAC;IACD,IAAI,CAACG,sBAAsB,GAAGoG,WAAW;IACzC,IAAI,CAACnG,iBAAiB,GAAG,IAAI,CAAC0B,2BAA2B,CAACyE,WAAW,CAAC;IACtE,OAAO,IAAI,CAACnG,iBAAiB;EAC/B;EAEA,MAAMoG,4BAA4BA,CAAC9F,gBAAwB,EAAiB;IAC1E,MAAMqB,QAAQ,GAAG5C,qBAAqB,CAAC6C,WAAW,CAAC7E,GAAG,CAACuD,gBAAgB,CAAC;IACxE,IAAI,CAACqB,QAAQ,EAAE;IACf,IAAI;MACF,MAAMA,QAAQ,CAAC0E,UAAU,CAAC,CAAC;MAC3B,IAAI,CAAC/G,OAAO,CAAC0C,IAAI,CAAC,iCAAiC,IAAI,CAAC3B,qBAAqB,CAACC,gBAAgB,CAAC,GAAG,CAAC;IACrG,CAAC,CAAC,OAAOkC,KAAK,EAAE;MACd,IAAI,CAAClD,OAAO,CAACkD,KAAK,CAAC,wCAAwC,IAAI,CAACnC,qBAAqB,CAACC,gBAAgB,CAAC,GAAG,EAAEkC,KAAK,CAAC;IACpH,CAAC,SAAS;MACRzD,qBAAqB,CAAC6C,WAAW,CAAC0E,MAAM,CAAChG,gBAAgB,CAAC;IAC5D;EACF;EAEA,MAAMiG,gBAAgBA,CAAA,EAAkB;IACtC,MAAMJ,WAAW,GAAG,MAAM,IAAI,CAAChB,2BAA2B,CACxD,IAAI,CAAC5F,UAAU,EACf,IAAI,CAACC,KACP,CAAC;IACD,MAAM,IAAI,CAAC4G,4BAA4B,CAACD,WAAW,CAAC;IACpD,IAAI,CAACpG,sBAAsB,GAAGuD,SAAS;IACvC,IAAI,CAACtD,iBAAiB,GAAGsD,SAAS;EACpC;EAEUkD,cAAcA,CACtBC,SAAiB,EACjBf,MAAmB,EACnBgB,cAAuB,EACX;IACZ,MAAM7E,UAAU,GAAG,IAAI,CAACqE,aAAa,CAAC,CAAC;IACvC,IAAI,CAACrE,UAAU,EAAE;MACf,MAAM,IAAIJ,KAAK,CAAC,qCAAqC,CAAC;IACxD;IACA,OAAO,IAAI,CAAC8D,QAAQ,CAAC1D,UAAU,EAAE4E,SAAS,EAAEf,MAAM,EAAEgB,cAAc,CAAC;EACrE;EAEUC,KAAKA,CAAIA,KAAe,EAAED,cAAuB,EAAY;IACrE,OAAO,IAAI,CAACF,cAAc,CACxBG,KAAK,CAACF,SAAS,EACfE,KAAK,CAACjB,MAAM,EACZgB,cACF,CAAC;EACH;EAEUnB,QAAQA,CAChB1D,UAA6B,EAC7B4E,SAAiB,EACjBf,MAAmB,EACnBgB,cAAuB,EACX;IACZ,IAAI7E,UAAU,CAAC+E,MAAM,CAACH,SAAS,CAAC,EAAE;MAChC,OAAO5E,UAAU,CAAC+E,MAAM,CAACH,SAAS,CAAC;IACrC;IACA,OAAO5E,UAAU,CAAC8E,KAAK,CAACF,SAAS,EAAEf,MAAM,EAAEgB,cAAc,CAAC;EAC5D;AACF,CAAC,EAAAxK,sBAAA,CAnVgB0F,WAAW,GAAkB,IAAIiF,GAAG,CAAC,CAAC,EAAA3K,sBAAA,GAAAoB,yBAAA,CAAArB,MAAA,CAAA6K,SAAA,2CAAAhL,IAAA,GAAAqB,MAAA,CAAAE,wBAAA,CAAApB,MAAA,CAAA6K,SAAA,2CAAA7K,MAAA,CAAA6K,SAAA,GAAAxJ,yBAAA,CAAArB,MAAA,CAAA6K,SAAA,mCAAA/K,KAAA,GAAAoB,MAAA,CAAAE,wBAAA,CAAApB,MAAA,CAAA6K,SAAA,mCAAA7K,MAAA,CAAA6K,SAAA,GAAAxJ,yBAAA,CAAArB,MAAA,CAAA6K,SAAA,kCAAA9K,KAAA,GAAAmB,MAAA,CAAAE,wBAAA,CAAApB,MAAA,CAAA6K,SAAA,kCAAA7K,MAAA,CAAA6K,SAAA,GAAA7K,MAAA;AAqVhD,MAAe8K,qBAAqB,SAAYhI,qBAAqB,CAAC;EAAAW,YAAA,GAAAd,IAAA;IAAA,SAAAA,IAAA;IAAA,KAC/CoI,QAAQ;EAAA;EAEpC,IAAcC,OAAOA,CAAA,EAAa;IAChC,OAAO,IAAI,CAACN,KAAK,CAAC,IAAI,CAACK,QAAQ,CAAC;EAClC;AACF;AAAChI,OAAA,CAAA+H,qBAAA,GAAAA,qBAAA","ignoreList":[]}
|