UNPKG

@forestadmin/forestadmin-client

Version:

This package contains the logic to use the ForestAdmin API inside an agent.

156 lines 14.5 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const hash_chart_1 = require("./hash-chart"); const is_segment_query_allowed_on_connection_1 = __importDefault(require("./is-segment-query-allowed-on-connection")); const is_segment_query_authorized_1 = __importDefault(require("./is-segment-query-authorized")); const types_1 = require("./types"); const verify_sql_query_1 = __importDefault(require("./verify-sql-query")); const context_variables_1 = __importDefault(require("../utils/context-variables")); const context_variables_injector_1 = __importDefault(require("../utils/context-variables-injector")); const ttl_cache_1 = __importDefault(require("../utils/ttl-cache")); class RenderingPermissionService { constructor(options, userPermissions, forestAdminServerInterface) { this.options = options; this.userPermissions = userPermissions; this.forestAdminServerInterface = forestAdminServerInterface; this.permissionsByRendering = new ttl_cache_1.default(async (renderingId) => this.loadPermissions(Number(renderingId)), this.options.permissionsCacheDurationInSeconds * 1000); } async getScope({ renderingId, collectionName, userId, }) { return this.getScopeOrRetry({ renderingId, collectionName, userId, // Only allow retry when not using server events allowRetry: !this.options.instantCacheRefresh, }); } async getScopeOrRetry({ renderingId, collectionName, userId, allowRetry, }) { const [permissions, userInfo] = await Promise.all([ this.permissionsByRendering.fetch(`${renderingId}`), this.userPermissions.getUserInfo(userId), ]); const collectionPermissions = permissions?.collections?.[collectionName]; if (!collectionPermissions) { if (allowRetry) { this.invalidateCache(renderingId); return this.getScopeOrRetry({ renderingId, collectionName, userId, allowRetry: false, }); } return null; } return context_variables_injector_1.default.injectContextInFilter(collectionPermissions.scope, new context_variables_1.default({ team: permissions.team, user: userInfo })); } async canExecuteSegmentQuery({ renderingId, collectionName, segmentQuery, connectionName, userId, }) { return ((await this.canExecuteSegmentQueryOrRetry({ renderingId, collectionName, segmentQuery, connectionName, userId, // Only allow retry when not using server events allowRetry: !this.options.instantCacheRefresh, })) && (0, verify_sql_query_1.default)(segmentQuery)); } async canExecuteSegmentQueryOrRetry({ renderingId, collectionName, segmentQuery, connectionName, allowRetry, userId, }) { const [userInfo, permissions] = await Promise.all([ this.userPermissions.getUserInfo(userId), this.permissionsByRendering.fetch(`${renderingId}`), ]); if ([types_1.PermissionLevel.Admin, types_1.PermissionLevel.Developer, types_1.PermissionLevel.Editor].includes(userInfo?.permissionLevel)) { this.options.logger('Debug', `User ${userId} can retrieve SQL segment on rendering ${renderingId}`); return true; } const collectionPermissions = permissions?.collections?.[collectionName]; if (!collectionPermissions || (connectionName && !(0, is_segment_query_allowed_on_connection_1.default)(collectionPermissions, segmentQuery, connectionName)) || !(0, is_segment_query_authorized_1.default)(segmentQuery, collectionPermissions.segments)) { if (allowRetry) { this.invalidateCache(renderingId); return this.canExecuteSegmentQueryOrRetry({ renderingId, collectionName, segmentQuery, connectionName, userId, allowRetry: false, }); } this.options.logger('Debug', `User ${userId} cannot retrieve SQL segment on rendering ${renderingId}`); return false; } this.options.logger('Debug', `User ${userId} can retrieve SQL segment on rendering ${renderingId}`); return true; } async loadPermissions(renderingId) { this.options.logger('Debug', `Loading rendering permissions for rendering ${renderingId}`); const rawPermissions = await this.forestAdminServerInterface.getRenderingPermissions(renderingId, this.options); const charts = (0, hash_chart_1.hashServerCharts)(rawPermissions.stats); return { team: rawPermissions.team, collections: rawPermissions.collections, charts, }; } isQueryChart(chartRequest) { return 'query' in chartRequest; } async canExecuteChart({ renderingId, chartRequest, userId, }) { const chartHash = (0, hash_chart_1.hashChartRequest)(chartRequest); return ((await this.canRetrieveChartHashOrRetry({ renderingId, chartHash, userId, // Only allow retry when not using server events allowRetry: !this.options.instantCacheRefresh, })) && (!this.isQueryChart(chartRequest) || (0, verify_sql_query_1.default)(chartRequest.query))); } async canRetrieveChartHashOrRetry({ renderingId, userId, chartHash, allowRetry, }) { const [userInfo, permissions] = await Promise.all([ this.userPermissions.getUserInfo(userId), this.permissionsByRendering.fetch(`${renderingId}`), ]); if ([types_1.PermissionLevel.Admin, types_1.PermissionLevel.Developer, types_1.PermissionLevel.Editor].includes(userInfo?.permissionLevel) || permissions.charts.has(chartHash)) { this.options.logger('Debug', `User ${userId} can retrieve chart on rendering ${renderingId}`); return true; } if (allowRetry) { this.invalidateCache(renderingId); this.userPermissions.invalidateCache(); return this.canRetrieveChartHashOrRetry({ renderingId, userId, chartHash, allowRetry: false, }); } this.options.logger('Debug', `User ${userId} cannot retrieve chart on rendering ${renderingId}`); return false; } invalidateCache(renderingId) { this.options.logger('Debug', `Invalidating rendering permissions cache for rendering ${renderingId}`); this.permissionsByRendering.delete(`${renderingId}`); } invalidateAllCache() { this.options.logger('Debug', `Invalidating rendering permissions cache for all renderings`); this.permissionsByRendering.clear(); } async getUser(userId) { return this.userPermissions.getUserInfo(userId); } async getTeam(renderingId) { const permissions = await this.permissionsByRendering.fetch(`${renderingId}`); return permissions.team; } } exports.default = RenderingPermissionService; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVuZGVyaW5nLXBlcm1pc3Npb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcGVybWlzc2lvbnMvcmVuZGVyaW5nLXBlcm1pc3Npb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw2Q0FBa0U7QUFDbEUsc0hBQXlGO0FBQ3pGLGdHQUFrRTtBQUNsRSxtQ0FNaUI7QUFFakIsMEVBQWdEO0FBR2hELG1GQUEwRDtBQUMxRCxxR0FBMkU7QUFDM0UsbUVBQTBDO0FBUTFDLE1BQXFCLDBCQUEwQjtJQUc3QyxZQUNtQixPQUE2QyxFQUM3QyxlQUFzQyxFQUN0QywwQkFBc0Q7UUFGdEQsWUFBTyxHQUFQLE9BQU8sQ0FBc0M7UUFDN0Msb0JBQWUsR0FBZixlQUFlLENBQXVCO1FBQ3RDLCtCQUEwQixHQUExQiwwQkFBMEIsQ0FBNEI7UUFFdkUsSUFBSSxDQUFDLHNCQUFzQixHQUFHLElBQUksbUJBQVEsQ0FDeEMsS0FBSyxFQUFDLFdBQVcsRUFBQyxFQUFFLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUMsRUFDOUQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQ0FBaUMsR0FBRyxJQUFJLENBQ3RELENBQUM7SUFDSixDQUFDO0lBRU0sS0FBSyxDQUFDLFFBQVEsQ0FBQyxFQUNwQixXQUFXLEVBQ1gsY0FBYyxFQUNkLE1BQU0sR0FLUDtRQUNDLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQztZQUMxQixXQUFXO1lBQ1gsY0FBYztZQUNkLE1BQU07WUFDTixnREFBZ0Q7WUFDaEQsVUFBVSxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxtQkFBbUI7U0FDOUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVPLEtBQUssQ0FBQyxlQUFlLENBQUMsRUFDNUIsV0FBVyxFQUNYLGNBQWMsRUFDZCxNQUFNLEVBQ04sVUFBVSxHQU1YO1FBQ0MsTUFBTSxDQUFDLFdBQVcsRUFBRSxRQUFRLENBQUMs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