@culturefy/shared 1.0.56 → 1.0.58

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.
Files changed (42) hide show
  1. package/build/cjs/index.js +6 -0
  2. package/build/cjs/index.js.map +1 -1
  3. package/build/cjs/middlewares/verify-middleware.js +7 -6
  4. package/build/cjs/middlewares/verify-middleware.js.map +1 -1
  5. package/build/cjs/models/config-mapping.model.js +41 -0
  6. package/build/cjs/models/config-mapping.model.js.map +1 -0
  7. package/build/cjs/repositories/index.js +16 -0
  8. package/build/cjs/repositories/index.js.map +1 -0
  9. package/build/cjs/repositories/multi-tenant.repository.js +266 -0
  10. package/build/cjs/repositories/multi-tenant.repository.js.map +1 -0
  11. package/build/cjs/repositories/tenant-base.repository.js +52 -0
  12. package/build/cjs/repositories/tenant-base.repository.js.map +1 -0
  13. package/build/esm/index.js +1 -0
  14. package/build/esm/index.js.map +1 -1
  15. package/build/esm/middlewares/verify-middleware.js +7 -6
  16. package/build/esm/middlewares/verify-middleware.js.map +1 -1
  17. package/build/esm/models/config-mapping.model.js +36 -0
  18. package/build/esm/models/config-mapping.model.js.map +1 -0
  19. package/build/esm/repositories/index.js +3 -0
  20. package/build/esm/repositories/index.js.map +1 -0
  21. package/build/esm/repositories/multi-tenant.repository.js +259 -0
  22. package/build/esm/repositories/multi-tenant.repository.js.map +1 -0
  23. package/build/esm/repositories/tenant-base.repository.js +48 -0
  24. package/build/esm/repositories/tenant-base.repository.js.map +1 -0
  25. package/build/src/index.d.ts +1 -0
  26. package/build/src/index.js +1 -0
  27. package/build/src/index.js.map +1 -1
  28. package/build/src/middlewares/verify-middleware.js +12 -11
  29. package/build/src/middlewares/verify-middleware.js.map +1 -1
  30. package/build/src/models/config-mapping.model.d.ts +20 -0
  31. package/build/src/models/config-mapping.model.js +41 -0
  32. package/build/src/models/config-mapping.model.js.map +1 -0
  33. package/build/src/repositories/index.d.ts +2 -0
  34. package/build/src/repositories/index.js +6 -0
  35. package/build/src/repositories/index.js.map +1 -0
  36. package/build/src/repositories/multi-tenant.repository.d.ts +44 -0
  37. package/build/src/repositories/multi-tenant.repository.js +295 -0
  38. package/build/src/repositories/multi-tenant.repository.js.map +1 -0
  39. package/build/src/repositories/tenant-base.repository.d.ts +17 -0
  40. package/build/src/repositories/tenant-base.repository.js +141 -0
  41. package/build/src/repositories/tenant-base.repository.js.map +1 -0
  42. package/package.json +1 -1
@@ -37,4 +37,10 @@ Object.keys(_constants).forEach(function (key) {
37
37
  if (key in exports && exports[key] === _constants[key]) return;
38
38
  exports[key] = _constants[key];
39
39
  });
40
+ var _repositories = require("./repositories");
41
+ Object.keys(_repositories).forEach(function (key) {
42
+ if (key === "default" || key === "__esModule") return;
43
+ if (key in exports && exports[key] === _repositories[key]) return;
44
+ exports[key] = _repositories[key];
45
+ });
40
46
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["_types","require","Object","keys","forEach","key","exports","_enums","_utils","_cache","_middlewares","_constants"],"sources":["../../src/index.ts"],"sourcesContent":["export * from './types';\nexport * from './enums';\nexport * from './utils';\nexport * from './utils/cache';\nexport * from './middlewares';\nexport * from './constants';\n"],"mappings":";;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAH,MAAA,EAAAI,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAL,MAAA,CAAAK,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAL,MAAA,CAAAK,GAAA;AAAA;AACA,IAAAE,MAAA,GAAAN,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAI,MAAA,EAAAH,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAE,MAAA,CAAAF,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAE,MAAA,CAAAF,GAAA;AAAA;AACA,IAAAG,MAAA,GAAAP,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAK,MAAA,EAAAJ,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAG,MAAA,CAAAH,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAG,MAAA,CAAAH,GAAA;AAAA;AACA,IAAAI,MAAA,GAAAR,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAM,MAAA,EAAAL,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAI,MAAA,CAAAJ,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAI,MAAA,CAAAJ,GAAA;AAAA;AACA,IAAAK,YAAA,GAAAT,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAO,YAAA,EAAAN,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAK,YAAA,CAAAL,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAK,YAAA,CAAAL,GAAA;AAAA;AACA,IAAAM,UAAA,GAAAV,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAQ,UAAA,EAAAP,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAM,UAAA,CAAAN,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAM,UAAA,CAAAN,GAAA;AAAA","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["_types","require","Object","keys","forEach","key","exports","_enums","_utils","_cache","_middlewares","_constants","_repositories"],"sources":["../../src/index.ts"],"sourcesContent":["export * from './types';\nexport * from './enums';\nexport * from './utils';\nexport * from './utils/cache';\nexport * from './middlewares';\nexport * from './constants';\nexport * from './repositories';\n"],"mappings":";;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAH,MAAA,EAAAI,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAL,MAAA,CAAAK,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAL,MAAA,CAAAK,GAAA;AAAA;AACA,IAAAE,MAAA,GAAAN,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAI,MAAA,EAAAH,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAE,MAAA,CAAAF,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAE,MAAA,CAAAF,GAAA;AAAA;AACA,IAAAG,MAAA,GAAAP,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAK,MAAA,EAAAJ,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAG,MAAA,CAAAH,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAG,MAAA,CAAAH,GAAA;AAAA;AACA,IAAAI,MAAA,GAAAR,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAM,MAAA,EAAAL,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAI,MAAA,CAAAJ,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAI,MAAA,CAAAJ,GAAA;AAAA;AACA,IAAAK,YAAA,GAAAT,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAO,YAAA,EAAAN,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAK,YAAA,CAAAL,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAK,YAAA,CAAAL,GAAA;AAAA;AACA,IAAAM,UAAA,GAAAV,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAQ,UAAA,EAAAP,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAM,UAAA,CAAAN,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAM,UAAA,CAAAN,GAAA;AAAA;AACA,IAAAO,aAAA,GAAAX,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAS,aAAA,EAAAR,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAO,aAAA,CAAAP,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAO,aAAA,CAAAP,GAAA;AAAA","ignoreList":[]}
@@ -234,7 +234,7 @@ async function getNewRefreshToken(req, ctx, appId, realmId, clientId, rt, mappin
234
234
 
235
235
  // Call auth service to refresh
236
236
  try {
237
- var _ref7, _ref7$state, _p2$sub, _ref8, _p2$cfy_bid, _ref9, _p2$email, _p2$name, _ref0, _p2$resource_access$c, _p2$resource_access, _p2$realm_access;
237
+ var _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;
238
238
  const resp = await fetch(apiURL, {
239
239
  method: "POST",
240
240
  headers: {
@@ -299,7 +299,7 @@ async function getNewRefreshToken(req, ctx, appId, realmId, clientId, rt, mappin
299
299
  };
300
300
  }
301
301
  const tokenMappingService = new _tokenMapping.TokenMappingService(ctx, dbUrl);
302
- await tokenMappingService.updateTokenMapping(mapping, {
302
+ const updatedMapping = await tokenMappingService.updateTokenMapping(mapping, {
303
303
  accessToken: newAT,
304
304
  refreshToken: newRT,
305
305
  // expires_in is a duration (seconds); store absolute expiry for later checks
@@ -358,12 +358,13 @@ async function getNewRefreshToken(req, ctx, appId, realmId, clientId, rt, mappin
358
358
  const tenantId2 = realmId.toString();
359
359
  ctx.state.auth = {
360
360
  appId,
361
- userId: (_p2$sub = p2.sub) != null ? _p2$sub : null,
362
- businessId: (_ref8 = (_p2$cfy_bid = p2.cfy_bid) != null ? _p2$cfy_bid : tenantId2) != null ? _ref8 : null,
361
+ userId: (_ref8 = (_updatedMapping$userI = updatedMapping == null || (_updatedMapping$userI2 = updatedMapping.userId) == null || _updatedMapping$userI2.toString == null ? void 0 : _updatedMapping$userI2.toString()) != null ? _updatedMapping$userI : p2.sub) != null ? _ref8 : null,
362
+ keycloakUserId: (_ref9 = (_p2$sub = p2.sub) != null ? _p2$sub : updatedMapping == null ? void 0 : updatedMapping.keycloakUserId) != null ? _ref9 : null,
363
+ businessId: (_ref0 = (_p2$cfy_bid = p2.cfy_bid) != null ? _p2$cfy_bid : tenantId2) != null ? _ref0 : null,
363
364
  tenantId: tenantId2,
364
- email: (_ref9 = (_p2$email = p2.email) != null ? _p2$email : p2.preferred_username) != null ? _ref9 : null,
365
+ email: (_ref1 = (_p2$email = p2.email) != null ? _p2$email : p2.preferred_username) != null ? _ref1 : null,
365
366
  name: (_p2$name = p2.name) != null ? _p2$name : undefined,
366
- roles: (_ref0 = (_p2$resource_access$c = (_p2$resource_access = p2.resource_access) == null || (_p2$resource_access = _p2$resource_access[clientId]) == null ? void 0 : _p2$resource_access.roles) != null ? _p2$resource_access$c : (_p2$realm_access = p2.realm_access) == null ? void 0 : _p2$realm_access.roles) != null ? _ref0 : [],
367
+ roles: (_ref10 = (_p2$resource_access$c = (_p2$resource_access = p2.resource_access) == null || (_p2$resource_access = _p2$resource_access[clientId]) == null ? void 0 : _p2$resource_access.roles) != null ? _p2$resource_access$c : (_p2$realm_access = p2.realm_access) == null ? void 0 : _p2$realm_access.roles) != null ? _ref10 : [],
367
368
  exp: p2.exp
368
369
  };
369
370
 
@@ -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","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","undefined","roles","resource_access","realm_access","exports","info","_ref7","_ref7$state","_p2$sub","_ref8","_p2$cfy_bid","_ref9","_p2$email","_p2$name","_ref0","_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","updateTokenMapping","expiresAt","expires_in","mappingMaxAge","refresh_expires_in","setCookieKV","httpOnly","secure","sameSite","maxAge","p2","audOk2","tenantId2","e","error","value","Buffer","from","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\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 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 // 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 setCookieKV(ctx, `__Secure-session-v1.${appId}.mapping`, mapping, {\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 });\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: p2.sub ?? 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","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","undefined","roles","resource_access","realm_access","exports","info","_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","mappingMaxAge","refresh_expires_in","setCookieKV","httpOnly","secure","sameSite","maxAge","p2","audOk2","tenantId2","e","error","value","Buffer","from","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\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 // 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 setCookieKV(ctx, `__Secure-session-v1.${appId}.mapping`, mapping, {\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 });\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":[]}
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.ConfigMappingModel = exports.CONFIG_MAPPING_DOCUMENT_NAME = exports.CONFIG_MAPPING_COLLECTION_NAME = void 0;
5
+ var _mongoose = _interopRequireWildcard(require("mongoose"));
6
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
7
+ const CONFIG_MAPPING_DOCUMENT_NAME = exports.CONFIG_MAPPING_DOCUMENT_NAME = 'ConfigMapping';
8
+ const CONFIG_MAPPING_COLLECTION_NAME = exports.CONFIG_MAPPING_COLLECTION_NAME = 'configMappings';
9
+ const schema = new _mongoose.Schema({
10
+ _id: {
11
+ type: _mongoose.Schema.Types.ObjectId,
12
+ required: true,
13
+ unique: true,
14
+ auto: true
15
+ },
16
+ businessId: {
17
+ type: _mongoose.Schema.Types.ObjectId,
18
+ required: true
19
+ },
20
+ connectionString: {
21
+ type: String,
22
+ required: true
23
+ },
24
+ domain: {
25
+ type: String,
26
+ required: false
27
+ },
28
+ appId: {
29
+ type: String,
30
+ required: false
31
+ },
32
+ serviceDBType: {
33
+ type: String,
34
+ required: false
35
+ }
36
+ }, {
37
+ timestamps: true,
38
+ collection: CONFIG_MAPPING_COLLECTION_NAME
39
+ });
40
+ const ConfigMappingModel = exports.ConfigMappingModel = _mongoose.default.models.ConfigMapping || (0, _mongoose.model)(CONFIG_MAPPING_DOCUMENT_NAME, schema);
41
+ //# sourceMappingURL=config-mapping.model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-mapping.model.js","names":["_mongoose","_interopRequireWildcard","require","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","CONFIG_MAPPING_DOCUMENT_NAME","exports","CONFIG_MAPPING_COLLECTION_NAME","schema","Schema","_id","type","Types","ObjectId","required","unique","auto","businessId","connectionString","String","domain","appId","serviceDBType","timestamps","collection","ConfigMappingModel","mongoose","models","ConfigMapping","model"],"sources":["../../../src/models/config-mapping.model.ts"],"sourcesContent":["import mongoose, { model, Schema } from 'mongoose';\n\nexport const CONFIG_MAPPING_DOCUMENT_NAME = 'ConfigMapping';\nexport const CONFIG_MAPPING_COLLECTION_NAME = 'configMappings';\n\nexport type ServiceDbType = 'main' | 'chatDB';\n\nexport interface IConfigMapping {\n _id?: Schema.Types.ObjectId;\n businessId: Schema.Types.ObjectId;\n connectionString: string;\n domain?: string;\n appId?: string;\n serviceDBType?: ServiceDbType;\n}\n\nexport interface ICreateConfigMapping {\n businessId: string;\n connectionString: string;\n domain?: string;\n appId?: string;\n serviceDBType?: ServiceDbType;\n}\n\nconst schema = new Schema<IConfigMapping>(\n {\n _id: {\n type: Schema.Types.ObjectId,\n required: true,\n unique: true,\n auto: true,\n },\n businessId: {\n type: Schema.Types.ObjectId,\n required: true,\n },\n connectionString: {\n type: String,\n required: true,\n },\n domain: {\n type: String,\n required: false,\n },\n appId: {\n type: String,\n required: false,\n },\n serviceDBType: {\n type: String,\n required: false,\n },\n },\n {\n timestamps: true,\n collection: CONFIG_MAPPING_COLLECTION_NAME,\n },\n);\n\nexport const ConfigMappingModel =\n mongoose.models.ConfigMapping ||\n model<IConfigMapping>(CONFIG_MAPPING_DOCUMENT_NAME, schema);\n"],"mappings":";;;;AAAA,IAAAA,SAAA,GAAAC,uBAAA,CAAAC,OAAA;AAAmD,SAAAD,wBAAAE,CAAA,EAAAC,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAJ,uBAAA,YAAAA,CAAAE,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;AAE5C,MAAMkB,4BAA4B,GAAAC,OAAA,CAAAD,4BAAA,GAAG,eAAe;AACpD,MAAME,8BAA8B,GAAAD,OAAA,CAAAC,8BAAA,GAAG,gBAAgB;AAqB9D,MAAMC,MAAM,GAAG,IAAIC,gBAAM,CACvB;EACEC,GAAG,EAAE;IACHC,IAAI,EAAEF,gBAAM,CAACG,KAAK,CAACC,QAAQ;IAC3BC,QAAQ,EAAE,IAAI;IACdC,MAAM,EAAE,IAAI;IACZC,IAAI,EAAE;EACR,CAAC;EACDC,UAAU,EAAE;IACVN,IAAI,EAAEF,gBAAM,CAACG,KAAK,CAACC,QAAQ;IAC3BC,QAAQ,EAAE;EACZ,CAAC;EACDI,gBAAgB,EAAE;IAChBP,IAAI,EAAEQ,MAAM;IACZL,QAAQ,EAAE;EACZ,CAAC;EACDM,MAAM,EAAE;IACNT,IAAI,EAAEQ,MAAM;IACZL,QAAQ,EAAE;EACZ,CAAC;EACDO,KAAK,EAAE;IACLV,IAAI,EAAEQ,MAAM;IACZL,QAAQ,EAAE;EACZ,CAAC;EACDQ,aAAa,EAAE;IACbX,IAAI,EAAEQ,MAAM;IACZL,QAAQ,EAAE;EACZ;AACF,CAAC,EACD;EACES,UAAU,EAAE,IAAI;EAChBC,UAAU,EAAEjB;AACd,CACF,CAAC;AAEM,MAAMkB,kBAAkB,GAAAnB,OAAA,CAAAmB,kBAAA,GAC7BC,iBAAQ,CAACC,MAAM,CAACC,aAAa,IAC7B,IAAAC,eAAK,EAAiBxB,4BAA4B,EAAEG,MAAM,CAAC","ignoreList":[]}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ var _multiTenant = require("./multi-tenant.repository");
5
+ Object.keys(_multiTenant).forEach(function (key) {
6
+ if (key === "default" || key === "__esModule") return;
7
+ if (key in exports && exports[key] === _multiTenant[key]) return;
8
+ exports[key] = _multiTenant[key];
9
+ });
10
+ var _tenantBase = require("./tenant-base.repository");
11
+ Object.keys(_tenantBase).forEach(function (key) {
12
+ if (key === "default" || key === "__esModule") return;
13
+ if (key in exports && exports[key] === _tenantBase[key]) return;
14
+ exports[key] = _tenantBase[key];
15
+ });
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["_multiTenant","require","Object","keys","forEach","key","exports","_tenantBase"],"sources":["../../../src/repositories/index.ts"],"sourcesContent":["export * from \"./multi-tenant.repository\";\nexport * from \"./tenant-base.repository\";\n"],"mappings":";;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAH,YAAA,EAAAI,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAL,YAAA,CAAAK,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAL,YAAA,CAAAK,GAAA;AAAA;AACA,IAAAE,WAAA,GAAAN,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAI,WAAA,EAAAH,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAE,WAAA,CAAAF,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAE,WAAA,CAAAF,GAAA;AAAA","ignoreList":[]}
@@ -0,0 +1,266 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.TenantModelRepository = exports.MultiTenantRepository = void 0;
5
+ exports.WithTenantDb = WithTenantDb;
6
+ var _mongoose = _interopRequireWildcard(require("mongoose"));
7
+ var crypto = _interopRequireWildcard(require("crypto"));
8
+ var _identity = require("@azure/identity");
9
+ var _keyvaultSecrets = require("@azure/keyvault-secrets");
10
+ var _enums = require("../enums");
11
+ var _cache = require("../utils/cache");
12
+ var _secrets = require("../utils/secrets");
13
+ var _configMapping = require("../models/config-mapping.model");
14
+ var _dec, _dec2, _dec3, _class, _MultiTenantRepository;
15
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
16
+ function _applyDecoratedDescriptor(i, e, r, n, l) { var a = {}; return Object.keys(n).forEach(function (i) { a[i] = n[i]; }), a.enumerable = !!a.enumerable, a.configurable = !!a.configurable, ("value" in a || a.initializer) && (a.writable = !0), a = r.slice().reverse().reduce(function (r, n) { return n(i, e, r) || r; }, a), l && void 0 !== a.initializer && (a.value = a.initializer ? a.initializer.call(l) : void 0, a.initializer = void 0), void 0 === a.initializer ? (Object.defineProperty(i, e, a), null) : a; }
17
+ const tenantDbCache = (0, _cache.createCache)("tenant-db", 600);
18
+ const tenantBridgeCache = (0, _cache.createCache)("tenant-bridge-db-connection-string", 1800);
19
+ const encryptionKeyCache = (0, _cache.createCache)("db-enc-key", 1800);
20
+
21
+ /**
22
+ * Decorator that ensures tenant DB is connected before the method runs.
23
+ */
24
+ function WithTenantDb(_target, _propertyKey, descriptor) {
25
+ if (!descriptor.value) return;
26
+ const originalMethod = descriptor.value;
27
+ descriptor.value = async function (...args) {
28
+ await this.ensureClientConnection();
29
+ return originalMethod.apply(this, args);
30
+ };
31
+ }
32
+ let MultiTenantRepository = exports.MultiTenantRepository = (_dec = (0, _cache.Cacheable)({
33
+ cache: tenantBridgeCache,
34
+ key: () => ["tenant-bridge"],
35
+ getContext: instance => instance.context
36
+ }), _dec2 = (0, _cache.Cacheable)({
37
+ cache: encryptionKeyCache,
38
+ key: () => ["key"],
39
+ getContext: instance => instance.context
40
+ }), _dec3 = (0, _cache.Cacheable)({
41
+ cache: tenantDbCache,
42
+ key: (businessId, appId, serviceDbType) => [businessId, appId, serviceDbType],
43
+ getContext: instance => instance.context
44
+ }), _class = (_MultiTenantRepository = class MultiTenantRepository {
45
+ constructor(context, businessId, appId, config, serviceDBType) {
46
+ this.context = void 0;
47
+ this.tenantBridgeConfig = void 0;
48
+ this.businessId = void 0;
49
+ this.appId = void 0;
50
+ this.serviceDBType = void 0;
51
+ this.dbConnectionEncryptionKey = void 0;
52
+ this.clientConnectionString = void 0;
53
+ this.connectionPromise = void 0;
54
+ this.context = context;
55
+ this.businessId = businessId;
56
+ this.appId = appId;
57
+ this.serviceDBType = serviceDBType != null ? serviceDBType : "main";
58
+ this.tenantBridgeConfig = {
59
+ tenantBridgeEnvKey: "TENANT_BRIDGE_DB_URI",
60
+ tenantBridgeSecretKey: _enums.AzureSecretKeysEnum.DB_CONNECTING_STRING_TENANT_BRIDGE,
61
+ ...config
62
+ };
63
+ this.connectionPromise = this.ensureClientConnection();
64
+ }
65
+ getEncryptionIv() {
66
+ const iv = process.env.DB_CONNECTION_STRING_ENCRYPTION_IV;
67
+ if (!iv) {
68
+ return Buffer.alloc(16, 0);
69
+ }
70
+ return this.normalizeFixedSize(iv, "IV");
71
+ }
72
+ normalizeFixedSize(value, label) {
73
+ const utf8Value = Buffer.from(value, "utf8");
74
+ if (utf8Value.length === 16) {
75
+ return utf8Value;
76
+ }
77
+ const base64Value = Buffer.from(value, "base64");
78
+ if (base64Value.length === 16) {
79
+ return base64Value;
80
+ }
81
+ const hexValue = Buffer.from(value, "hex");
82
+ if (hexValue.length === 16) {
83
+ return hexValue;
84
+ }
85
+ throw new Error(`${label} must be 16 bytes for aes-128-cbc (got ${utf8Value.length})`);
86
+ }
87
+ async getOrCreateCachedConnection(connectionString) {
88
+ const existing = MultiTenantRepository.connections.get(connectionString);
89
+ if (existing && existing.connection.readyState === 1) {
90
+ return existing;
91
+ }
92
+ this.context.info(`Initializing database connection... ${connectionString}`);
93
+ const instance = new _mongoose.default.Mongoose();
94
+ try {
95
+ await instance.connect(connectionString, {
96
+ serverSelectionTimeoutMS: 10000,
97
+ connectTimeoutMS: 10000,
98
+ socketTimeoutMS: 45000
99
+ });
100
+ this.context.info(`✅ MongoDB connected successfully ${connectionString}`);
101
+ MultiTenantRepository.connections.set(connectionString, instance);
102
+ return instance;
103
+ } catch (err) {
104
+ this.context.error(`❌ MongoDB connection error for ${connectionString}`, {
105
+ message: err.message,
106
+ name: err.name,
107
+ code: err.code,
108
+ stack: err.stack
109
+ });
110
+ throw new Error(`Failed to connect to MongoDB: ${err.message}`);
111
+ }
112
+ }
113
+ toObjectId(id, fieldName) {
114
+ if (!_mongoose.Types.ObjectId.isValid(id)) {
115
+ throw new Error(`Invalid ${fieldName}`);
116
+ }
117
+ return new _mongoose.Types.ObjectId(id);
118
+ }
119
+ async getTenantBridgeSrvDbConnectionString() {
120
+ const envKey = this.tenantBridgeConfig.tenantBridgeEnvKey;
121
+ const localUri = envKey ? process.env[envKey] : undefined;
122
+ if (localUri) {
123
+ return localUri;
124
+ }
125
+ const vault = process.env.AZURE_KEY_VAULT_NAME || "";
126
+ const secretKey = this.tenantBridgeConfig.tenantBridgeSecretKey || _enums.AzureSecretKeysEnum.DB_CONNECTING_STRING_TENANT_BRIDGE;
127
+ const dbUrl = await (0, _secrets.getAzureVaultSecretByKey)(this.context, vault, secretKey);
128
+ if (!dbUrl) {
129
+ throw new Error("TenantBridge database connection string not found");
130
+ }
131
+ return dbUrl;
132
+ }
133
+ async getDbConnectionEncryptionKey() {
134
+ var _secret$value;
135
+ if (this.dbConnectionEncryptionKey) {
136
+ return this.dbConnectionEncryptionKey;
137
+ }
138
+ const envKey = process.env.DB_CONNECTION_STRING_ENCRYPTION_KEY;
139
+ if (envKey) {
140
+ this.dbConnectionEncryptionKey = envKey;
141
+ return envKey;
142
+ }
143
+ const vault = process.env.AZURE_KEY_VAULT_NAME || "";
144
+ if (!vault) {
145
+ throw new Error("AZURE_KEY_VAULT_NAME is required to fetch encryption key");
146
+ }
147
+ const vaultUrl = `https://${vault}.vault.azure.net`;
148
+ const credential = new _identity.DefaultAzureCredential();
149
+ const client = new _keyvaultSecrets.SecretClient(vaultUrl, credential);
150
+ const secret = await client.getSecret("DB-CONNECTION-STRING-ENCRYPTION-KEY");
151
+ const key = (_secret$value = secret.value) != null ? _secret$value : "";
152
+ if (!key) {
153
+ throw new Error("DB connection string encryption key not found");
154
+ }
155
+ this.dbConnectionEncryptionKey = key;
156
+ return key;
157
+ }
158
+ async decryptConnectionString(encryptedValue) {
159
+ const key = await this.getDbConnectionEncryptionKey();
160
+ const keyBuffer = this.normalizeEncryptionKey(key);
161
+ const ivBuffer = this.getEncryptionIv();
162
+ const decipher = crypto.createDecipheriv("aes-128-cbc", keyBuffer, ivBuffer);
163
+ let decrypted = decipher.update(encryptedValue, "base64", "utf8");
164
+ decrypted += decipher.final("utf8");
165
+ return decrypted;
166
+ }
167
+ normalizeEncryptionKey(key) {
168
+ const utf8Key = Buffer.from(key, "utf8");
169
+ if (utf8Key.length === 16) {
170
+ return utf8Key;
171
+ }
172
+ const base64Key = Buffer.from(key, "base64");
173
+ if (base64Key.length === 16) {
174
+ return base64Key;
175
+ }
176
+ const hexKey = Buffer.from(key, "hex");
177
+ if (hexKey.length === 16) {
178
+ return hexKey;
179
+ }
180
+ throw new Error(`DB connection string encryption key must be 16 bytes for aes-128-cbc (got ${utf8Key.length})`);
181
+ }
182
+ async getClientDbConnectionString(businessId, appId, serviceDBType) {
183
+ const resolvedServiceDbType = serviceDBType != null ? serviceDBType : "main";
184
+ const tenantBridgeUrl = await this.getTenantBridgeSrvDbConnectionString();
185
+ const connection = await this.getOrCreateCachedConnection(tenantBridgeUrl);
186
+ const ConfigMapping = this.getModel(connection, _configMapping.CONFIG_MAPPING_DOCUMENT_NAME, _configMapping.ConfigMappingModel.schema, _configMapping.CONFIG_MAPPING_COLLECTION_NAME);
187
+ const filter = {
188
+ businessId: this.toObjectId(businessId, "businessId")
189
+ };
190
+ if (appId) {
191
+ filter.appId = appId;
192
+ }
193
+ filter.serviceDBType = resolvedServiceDbType;
194
+ const configMapping = await ConfigMapping.findOne(filter).lean().exec();
195
+ if (!(configMapping != null && configMapping.connectionString)) {
196
+ throw new Error("Config mapping not found for this business");
197
+ }
198
+ const decryptedConnectionString = await this.decryptConnectionString(configMapping.connectionString);
199
+ this.context.info(`Resolved tenant DB connection string from bridge: ${decryptedConnectionString}`);
200
+ return decryptedConnectionString;
201
+ }
202
+ getConnection() {
203
+ if (!this.clientConnectionString) return undefined;
204
+ return MultiTenantRepository.connections.get(this.clientConnectionString);
205
+ }
206
+ async ensureClientConnection() {
207
+ if (this.connectionPromise) {
208
+ return this.connectionPromise;
209
+ }
210
+ if (this.clientConnectionString) {
211
+ const existing = this.getConnection();
212
+ if (existing && existing.connection.readyState === 1) {
213
+ return existing;
214
+ }
215
+ }
216
+ const clientDbUrl = await this.getClientDbConnectionString(this.businessId, this.appId, this.serviceDBType);
217
+ this.clientConnectionString = clientDbUrl;
218
+ this.connectionPromise = this.getOrCreateCachedConnection(clientDbUrl);
219
+ return this.connectionPromise;
220
+ }
221
+ async disconnectByConnectionString(connectionString) {
222
+ const existing = MultiTenantRepository.connections.get(connectionString);
223
+ if (!existing) return;
224
+ try {
225
+ await existing.disconnect();
226
+ this.context.info(`✅ Disconnected from database: ${connectionString}`);
227
+ } catch (error) {
228
+ this.context.error(`❌ Error disconnecting from database: ${connectionString}`, error);
229
+ } finally {
230
+ MultiTenantRepository.connections.delete(connectionString);
231
+ }
232
+ }
233
+ async disconnectClient() {
234
+ const clientDbUrl = await this.getClientDbConnectionString(this.businessId, this.appId);
235
+ await this.disconnectByConnectionString(clientDbUrl);
236
+ this.clientConnectionString = undefined;
237
+ this.connectionPromise = undefined;
238
+ }
239
+ getTenantModel(modelName, schema, collectionName) {
240
+ const connection = this.getConnection();
241
+ if (!connection) {
242
+ throw new Error("database connection not established");
243
+ }
244
+ return this.getModel(connection, modelName, schema, collectionName);
245
+ }
246
+ model(model, collectionName) {
247
+ return this.getTenantModel(model.modelName, model.schema, collectionName);
248
+ }
249
+ getModel(connection, modelName, schema, collectionName) {
250
+ if (connection.models[modelName]) {
251
+ return connection.models[modelName];
252
+ }
253
+ return connection.model(modelName, schema, collectionName);
254
+ }
255
+ }, _MultiTenantRepository.connections = new Map(), _MultiTenantRepository), _applyDecoratedDescriptor(_class.prototype, "getTenantBridgeSrvDbConnectionString", [_dec], Object.getOwnPropertyDescriptor(_class.prototype, "getTenantBridgeSrvDbConnectionString"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "getDbConnectionEncryptionKey", [_dec2], Object.getOwnPropertyDescriptor(_class.prototype, "getDbConnectionEncryptionKey"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "getClientDbConnectionString", [_dec3], Object.getOwnPropertyDescriptor(_class.prototype, "getClientDbConnectionString"), _class.prototype), _class);
256
+ class TenantModelRepository extends MultiTenantRepository {
257
+ constructor(...args) {
258
+ super(...args);
259
+ this.modelDef = void 0;
260
+ }
261
+ get dbModel() {
262
+ return this.model(this.modelDef);
263
+ }
264
+ }
265
+ exports.TenantModelRepository = TenantModelRepository;
266
+ //# sourceMappingURL=multi-tenant.repository.js.map
@@ -0,0 +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":[]}