UNPKG

@sap-cloud-sdk/connectivity

Version:

SAP Cloud SDK for JavaScript connectivity

138 lines 6.03 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.destinationCache = exports.DestinationCache = exports.DefaultDestinationCache = void 0; exports.getDestinationCacheKey = getDestinationCacheKey; exports.setDestinationCache = setDestinationCache; exports.getDefaultIsolationStrategy = getDefaultIsolationStrategy; const util_1 = require("@sap-cloud-sdk/util"); const jwt_1 = require("../jwt"); const async_cache_1 = require("../async-cache"); const logger = (0, util_1.createLogger)({ package: 'connectivity', messageContext: 'destination-cache' }); /** * @internal * This wrapper class wraps methods of {@link Cache} class as asynchronous methods. */ class DefaultDestinationCache extends async_cache_1.AsyncCache { constructor(defaultValidityTime = 0) { super(defaultValidityTime); } } exports.DefaultDestinationCache = DefaultDestinationCache; /** * DestinationCache constructor. * @param cache - Cache object which is used in DestinationCache * @returns A destination cache object. * @internal */ const DestinationCache = (cache = new DefaultDestinationCache(300000)) => ({ retrieveDestinationFromCache: async (token, name, isolation) => cache.get(getDestinationCacheKey(token, name, isolation)), cacheRetrievedDestination: async (token, destination, isolation) => { cacheRetrievedDestination(token, destination, isolation, cache); }, cacheRetrievedDestinations: async (token, retrievedDestinations, isolation) => { retrievedDestinations.subaccount.forEach(dest => cacheRetrievedDestination(token, dest, isolation, cache)); retrievedDestinations.instance.forEach(dest => cacheRetrievedDestination(token, dest, isolation, cache)); }, clear: async () => { cache.clear(); }, getCacheInstance: () => cache }); exports.DestinationCache = DestinationCache; /** * Retrieve the token to use for tenant identification. * * For subscriber: * If `iss` or XSUAA user JWT was passed, this is the `serviceJwt`. * If a custom user JWT was passed, this is used. * * For provider: always use the token as passed. * @param token - Either the subscriber JWTs or one provider JWT. * @returns The decoded JWT to use for tenant identification. */ function getJwtForTenant(token) { return token?.serviceJwt?.decoded || token; } /** * Retrieve the token to use for user identification. * * For subscriber: * If a user token was passed, this is used. * If only `iss` was passed try to get the user from the service token. * * For provider: always use the token as passed. * @param token - Either the subscriber JWTs or one provider JWT. * @returns The decoded JWT to use for user identification. */ function getJwtForUser(token) { return token?.userJwt?.decoded || token; } /** * Calculates a cache key based on the JWT and destination name for the given isolation strategy. * Cache keys for strategies are non-overlapping, i.e. using a cache key for strategy {@link 'tenant'} * will not result in a cache hit for a destination that has been cached with strategy {@link 'tenant-user'}. * @param decodedJwt - The decoded JWT of the current request. * @param destinationName - The name of the destination. * @param isolationStrategy - The strategy used to isolate cache entries. * @returns The cache key. * @internal */ function getDestinationCacheKey(token, destinationName, isolationStrategy = 'tenant-user') { if (isolationStrategy === 'tenant') { return getTenantCacheKey(destinationName, (0, jwt_1.getTenantId)(getJwtForTenant(token))); } if (isolationStrategy === 'tenant-user') { return getTenantUserCacheKey(destinationName, (0, jwt_1.getTenantId)(getJwtForTenant(token)), (0, jwt_1.userId)(getJwtForUser(token))); } logger.warn(`Could not build destination cache key. Isolation strategy '${isolationStrategy}' is not supported.`); } function getTenantCacheKey(destinationName, tenant) { if (tenant) { return `${tenant}::${destinationName}`; } logger.warn("Could not build destination cache key. Isolation strategy 'tenant' is used, but tenant ID is undefined in JWT."); } function getTenantUserCacheKey(destinationName, tenant, user) { if (tenant && user) { return `${user}:${tenant}:${destinationName}`; } logger.warn("Could not build destination cache key. Isolation strategy 'tenant-user' is used, but tenant id or user id is undefined in JWT."); } async function cacheRetrievedDestination(token, destination, isolation, cache) { if (!destination.name) { throw new Error('The destination name is undefined.'); } const key = getDestinationCacheKey(token, destination.name, isolation); const expiresIn = (0, util_1.first)(destination.authTokens || [])?.expiresIn; const expirationTime = expiresIn ? Date.now() + parseInt(expiresIn) * 1000 : undefined; cache.set(key, { entry: destination, expires: expirationTime }); } /** * Sets the custom destination cache instance. * Call this method with an instance of {@link DestinationCacheInterface} to override the default cache instance set by the SDK. * * NOTE: This function should be called at the beginning before any calls to either {@link getDestination} or {@link @sap-cloud-sdk/http-client!executeHttpRequest}. * @param cache - An instance of {@link DestinationCacheInterface}. */ function setDestinationCache(cache) { exports.destinationCache = (0, exports.DestinationCache)(cache); } /** * @internal */ exports.destinationCache = (0, exports.DestinationCache)(); /** * Determine the default isolation strategy if not given as option. * @param jwt - JWT to determine the default isolation strategy * @returns The isolation strategy based on the JWT. If no JWT is given it defaults to tenant isolation. * @internal */ function getDefaultIsolationStrategy(jwt) { return jwt && (0, jwt_1.userId)(jwt) ? 'tenant-user' : 'tenant'; } //# sourceMappingURL=destination-cache.js.map