UNPKG

@restorecommerce/acs-client

Version:

Access Control Service Client

185 lines 7.01 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.setCacheStatus = exports.flushCache = exports.get = exports.getOrFill = exports.initializeCache = void 0; const config_1 = require("../config"); const logger_1 = __importDefault(require("../logger")); const crypto = __importStar(require("crypto")); const redis_1 = require("redis"); let attempted = false; let redisInstance; let ttl; let cacheEnabled = true; let redisSubjectInstance; /** * Initialize ACS Cache */ const initializeCache = async () => { if (attempted || !cacheEnabled) { return; } attempted = true; try { const redisConfig = config_1.cfg.get('authorization:cache'); const redisSubConfig = config_1.cfg.get('redis'); if (redisConfig) { redisConfig.database = config_1.cfg.get('authorization:cache:db-index'); redisInstance = (0, redis_1.createClient)(redisConfig); redisInstance.on('error', (err) => logger_1.default.error('Redis Client Error in ACS cache', { code: err.code, message: err.message, stack: err.stack })); await redisInstance.connect(); ttl = config_1.cfg.get('authorization:cache:ttl'); } if (redisSubConfig) { // init redis subject instance redisSubConfig.database = redisSubConfig['db-indexes']['db-subject']; redisSubjectInstance = (0, redis_1.createClient)(redisSubConfig); redisSubjectInstance.on('error', (err) => logger_1.default.error('Redis Client Error in ACS cache', { code: err.code, message: err.message, stack: err.stack })); await redisSubjectInstance.connect(); } } catch (e) { attempted = false; } }; exports.initializeCache = initializeCache; /** * Find the object in cache. If not found, compute it using the filler function * * @param keyData The data to base the cache key on * @param filler The function to execute if key is not found in cache * @param prefix The prefix to apply to the object key in the cache */ const getOrFill = async (keyData, filler, useCache, prefix) => { if (!redisInstance || !cacheEnabled) { return filler(keyData); } const inputHash = crypto.createHash('md5').update(JSON.stringify(keyData)).digest().toString('base64'); let redisKey = `${inputHash}`; if (prefix) { redisKey = `${prefix}:` + redisKey; } const redisKeyResponse = await redisInstance.get(redisKey); if (redisKeyResponse && useCache) { const response = JSON.parse(redisKeyResponse); const evaluation_cacheable = response?.evaluation_cacheable || response?.policy_sets?.some(policy_set => policy_set?.policies?.some(policy => policy?.evaluation_cacheable !== false && policy.rules?.some(rule => rule?.evaluation_cacheable))); if (evaluation_cacheable) { logger_1.default.debug('Found key in cache: ' + redisKey); return response; } } if (!useCache) { // when useCache is false, dont store in cache return await filler(keyData); } logger_1.default.debug('Filling cache key: ' + redisKey); const acsResponse = await filler(keyData); if (acsResponse) { if (ttl) { await redisInstance.setEx(redisKey, ttl, JSON.stringify(acsResponse)); } else { await redisInstance.set(redisKey, JSON.stringify(acsResponse)); } } return acsResponse; }; exports.getOrFill = getOrFill; /** * Find the object in cache. * * @param key The key to be looked up in cache * @param filler The function to execute if key is not found in cache * @param prefix The prefix to apply to the object key in the cache */ const get = async (key) => { if (!redisSubjectInstance) { logger_1.default.warn('No Redis Subject Instance!'); return; } const redisResponse = await redisSubjectInstance.get(key); if (!redisResponse) { logger_1.default.info('Key does not exist', { key }); return; } if (redisResponse) { logger_1.default.debug('Found key in cache: ' + key); return JSON.parse(redisResponse); } }; exports.get = get; /** * Flush the ACS cache * * @param prefix An optional prefix to flush instead of entire cache */ const flushCache = async (prefix) => { if (!redisInstance || !cacheEnabled) { logger_1.default.info('Redis client not initialized in acs-client'); return; } if (prefix != undefined) { const flushPattern = `acs:${prefix}:*`; logger_1.default.debug(`Flushing cache with pattern ${flushPattern}`); let scanIterator; try { scanIterator = redisInstance.scanIterator({ MATCH: flushPattern, COUNT: 100 }); for await (const key of scanIterator) { await redisInstance.del(key); } logger_1.default.debug(`Successfully flushed cache pattern ${flushPattern}`); return; } catch (err) { logger_1.default.error('Error flushing ACS cache', { code: err.code, message: err.message, stack: err.stack }); return; } } logger_1.default.debug('Flushing ACS cache'); const reply = await redisInstance.flushDb(); if (reply) { logger_1.default.debug('Flushed ACS cache'); } }; exports.flushCache = flushCache; /** * Enable / Disable ACS Caching * * @param enabled Whether to enable or disable the cache */ const setCacheStatus = (enabled) => { cacheEnabled = enabled; if (enabled) { logger_1.default.debug('ACS Cache Enabled'); (0, exports.initializeCache)(); } else { logger_1.default.debug('ACS Cache Disabled'); } }; exports.setCacheStatus = setCacheStatus; //# sourceMappingURL=cache.js.map