UNPKG

@universis/user-storage

Version:

Universis Api Server Extension for managing user remote storage

214 lines (147 loc) 7.64 kB
"use strict"; var _common = require("@themost/common"); var redis = _interopRequireWildcard(require("redis")); var _service = require("./service"); var _es6Promisify = require("es6-promisify"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } const REDIS_JSON_COMMANDS = ["json.del", "json.get", "json.mget", "json.set", "json.type", "json.numincrby", "json.nummultby", "json.strappend", "json.strlen", "json.arrappend", "json.arrindex", "json.arrinsert", "json.arrlen", "json.arrpop", "json.arrtrim", "json.objkeys", "json.objlen", "json.debug", "json.forget", "json.resp"]; function createJsonClient(options) { // add json commands REDIS_JSON_COMMANDS.forEach(command => { // noinspection JSUnresolvedFunction redis.addCommand(command); }); // and finally return client return redis.createClient(options); } class RedisUserStorageService extends _service.UserStorageService { /** * Formats a path like key string to a redis command compatible key e.g. user1/application1/lastAction to .user1.application1.lastAction * @param key * @returns {string|*} */ static escapeKey(key) { let res = key.replace(/\//ig, '.'); if (/^\./.test(res)) { return res; } return '.' + res; } /** * @param {IApplication} app */ constructor(app) { super(app); } /** * @name RedisClient#json_set * @param {*} ...args */ /** * @name RedisClient#json_get * @param {*} ...args */ /** * * @param {DataContext} context * @param {string} key * @param {*} value * @param {number=} expiration */ async setItem(context, key, value, expiration) { // validate user const hasAccess = await context.getConfiguration().getStrategy(_service.UserStorageAccessConfiguration).verify(context, `me/${key}`, 'write'); if (hasAccess == null) { throw new _common.AccessDeniedError('Write access to the specified user storage key is denied'); } // create redis client const client = createJsonClient(this.options); const json_set = (0, _es6Promisify.promisify)(client.json_set).bind(client); // noinspection JSUnresolvedVariable const json_type = (0, _es6Promisify.promisify)(client.json_type).bind(client); const quit = (0, _es6Promisify.promisify)(client.quit).bind(client); // validate root object //split key e.g. .key1.key2.key3 to an array of [ '', 'key1', 'key2', 'key3' ] const keys = _service.UserStorageService.escapeKey(key).split('.'); // enumerate existence of keys from [1] to [length - 1] in order to avoid redis errors for (let i = 0; i < keys.length - 1; i++) { let key1 = keys.slice(0, i + 1).join('.'); // ensure root key if (i === 0) { key1 = '.'; } // validate key e.g. .key1 and .key1.key2 const value1 = await json_type(`${context.user.name}`, key1); // if key does not exist if (value1 == null) { // set value await json_set(`${context.user.name}`, key1, JSON.stringify({})); } } if (typeof expiration === "number" && expiration > 0) { // call json_set() with expiration await json_set(`${context.user.name}`, _service.UserStorageService.escapeKey(key), 'EX', Math.ceil(expiration), JSON.stringify(value)); // close client await quit(); // and return return value; } // call json_set() with expiration await json_set(`${context.user.name}`, _service.UserStorageService.escapeKey(key), JSON.stringify(value)); // close client await quit(); // and return return value; } /** * @param {DataContext} context * @param {string} key */ async getItem(context, key) { // validate user const hasAccess = await context.getConfiguration().getStrategy(_service.UserStorageAccessConfiguration).verify(context, `me/${key}`, 'read'); if (hasAccess == null) { throw new _common.AccessDeniedError('Read access to the specified user storage key is denied'); } // create redis client const client = createJsonClient(this.options); // noinspection JSUnresolvedVariable const json_type = (0, _es6Promisify.promisify)(client.json_type).bind(client); const json_get = (0, _es6Promisify.promisify)(client.json_get).bind(client); // noinspection JSUnresolvedVariable const quit = (0, _es6Promisify.promisify)(client.quit).bind(client); // call json_get() const type = await json_type(`${context.user.name}`, _service.UserStorageService.escapeKey(key)); if (type == null) { return null; } // get value const res = await json_get(`${context.user.name}`, 'NOESCAPE', _service.UserStorageService.escapeKey(key)); // quit await quit(); // if value is not null if (res != null) { // parse string value and return return JSON.parse(res); } return res; } /** * @param {DataContext} context * @param {string} key * @returns Promise<*> */ async removeItem(context, key) { // validate user access const hasAccess = await context.getConfiguration().getStrategy(_service.UserStorageAccessConfiguration).verify(context, `me/${key}`, 'write'); if (hasAccess == null) { throw new _common.AccessDeniedError('Write access to the specified user storage key is denied'); } // create redis client const client = createJsonClient(this.options); // noinspection JSUnresolvedVariable const json_del = (0, _es6Promisify.promisify)(client.json_del).bind(client); const quit = (0, _es6Promisify.promisify)(client.quit).bind(client); // call json_del() const res = await json_del(`${context.user.name}`, _service.UserStorageService.escapeKey(key)); // close client await quit(); // and return return res === 1; } /** * @param {DataContext} context * @returns Promise<*> */ async clear(context) { // validate user access const hasAccess = context.getConfiguration().getStrategy(_service.UserStorageAccessConfiguration).verify(context, `me`, 'write'); if (hasAccess == null) { throw new _common.AccessDeniedError('Write access to the specified user storage key is denied'); } // create redis client const client = createJsonClient(this.options); const del = (0, _es6Promisify.promisify)(client.del).bind(client); const quit = (0, _es6Promisify.promisify)(client.quit).bind(client); // call json_del() const res = await del(`${context.user.name}`); await quit(); return res === 1; } } module.exports.RedisUserStorageService = RedisUserStorageService; //# sourceMappingURL=redis.js.map