UNPKG

dsl-builder

Version:

OpenSearch Query Builder - Extract from OpenSearch Dashboards

275 lines (274 loc) 10.1 kB
"use strict"; /* * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 */ Object.defineProperty(exports, "__esModule", { value: true }); exports.ACL = exports.PrincipalType = void 0; var PrincipalType; (function (PrincipalType) { PrincipalType["Users"] = "users"; PrincipalType["Groups"] = "groups"; })(PrincipalType = exports.PrincipalType || (exports.PrincipalType = {})); const addToPrincipals = ({ principals = {}, users, groups, }) => { if (users) { if (!principals.users) { principals.users = []; } principals.users = Array.from(new Set([...principals.users, ...users])); } if (groups) { if (!principals.groups) { principals.groups = []; } principals.groups = Array.from(new Set([...principals.groups, ...groups])); } return principals; }; const deleteFromPrincipals = ({ principals, users, groups, }) => { if (!principals) { return principals; } if (users && principals.users) { principals.users = principals.users.filter((item) => !users.includes(item)); } if (groups && principals.groups) { principals.groups = principals.groups.filter((item) => !groups.includes(item)); } return principals; }; const checkPermission = (allowedPrincipals, requestedPrincipals) => { return (((allowedPrincipals === null || allowedPrincipals === void 0 ? void 0 : allowedPrincipals.users) && (requestedPrincipals === null || requestedPrincipals === void 0 ? void 0 : requestedPrincipals.users) && checkPermissionForSinglePrincipalType(allowedPrincipals.users, requestedPrincipals.users)) || ((allowedPrincipals === null || allowedPrincipals === void 0 ? void 0 : allowedPrincipals.groups) && (requestedPrincipals === null || requestedPrincipals === void 0 ? void 0 : requestedPrincipals.groups) && checkPermissionForSinglePrincipalType(allowedPrincipals.groups, requestedPrincipals.groups))); }; const checkPermissionForSinglePrincipalType = (allowedPrincipalArray, requestedPrincipalArray) => { return (allowedPrincipalArray && requestedPrincipalArray && (allowedPrincipalArray.includes('*') || requestedPrincipalArray.some((item) => allowedPrincipalArray.includes(item)))); }; class ACL { constructor(initialPermissions) { this.permissions = initialPermissions || {}; } /** * A function that parses the permissions object to check whether the specific principal has the specific permission types or not * * @param {Array} permissionTypes permission types * @param {Object} principals the users or groups * @returns true if the principal has the specified permission types, false if the principal has no permission * * @public */ hasPermission(permissionTypes, principals) { if (!permissionTypes || permissionTypes.length === 0 || !this.permissions || !principals) { return false; } const currentPermissions = this.permissions; return permissionTypes.some((permissionType) => checkPermission(currentPermissions[permissionType], principals)); } /** * A permissions object build function that adds principal with specific permission to the object * * This function is used to contruct a new permissions object or add principals with specified permissions to * the existing permissions object. The usage is: * * const permissionObject = new ACL() * .addPermission(['write', 'library_write'], { * users: ['user2'], * }) * .addPermission(['write', 'library_write'], { * groups: ['group1'], * }) * .getPermissions(); * * @param {Array} permissionTypes the permission types * @param {Object} principals the users or groups * @returns the permissions object * * @public */ addPermission(permissionTypes, principals) { if (!permissionTypes || !principals) { return this; } if (!this.permissions) { this.permissions = {}; } for (const permissionType of permissionTypes) { this.permissions[permissionType] = addToPrincipals({ principals: this.permissions[permissionType], users: principals.users, groups: principals.groups, }); } return this; } /** * A permissions object build function that removes specific permission of specific principal from the object * * This function is used to remove principals with specified permissions to * the existing permissions object. The usage is: * * const newPermissionObject = new ACL() * .removePermission(['write', 'library_write'], { * users: ['user2'], * }) * .removePermission(['write', 'library_write'], { * groups: ['group1'], * }) * .getPermissions(); * * @param {Array} permissionTypes the permission types * @param {Object} principals the users or groups * @returns the permissions object * * @public */ removePermission(permissionTypes, principals) { if (!permissionTypes || !principals) { return this; } if (!this.permissions) { this.permissions = {}; } for (const permissionType of permissionTypes) { const result = deleteFromPrincipals({ principals: this.permissions[permissionType], users: principals.users, groups: principals.groups, }); if (result) { this.permissions[permissionType] = result; } } return this; } /** * A function that transforms permissions format, change the format from permissionType->principals to principal->permissionTypes, * which is used to clearyly dispaly user/group list and their granted permissions in the UI * * for example: * the original permissions object is: { * read: { * users:['user1'] * }, * write:{ * groups:['group1'] * } * } * * the transformed permissions object will be: [ * {type:'users', name:'user1', permissions:['read']}, * {type:'groups', name:'group1', permissions:['write']}, * ] * * @returns the flat list of the permissions object * * @public */ toFlatList() { var _a; const result = []; if (!this.permissions) { return result; } for (const permissionType in this.permissions) { if (Object.prototype.hasOwnProperty.call(this.permissions, permissionType)) { const { users = [], groups = [] } = (_a = this.permissions[permissionType]) !== null && _a !== void 0 ? _a : {}; users.forEach((user) => { const found = result.find((r) => r.type === PrincipalType.Users && r.name === user); if (found) { found.permissions.push(permissionType); } else { result.push({ type: PrincipalType.Users, name: user, permissions: [permissionType] }); } }); groups.forEach((group) => { const found = result.find((r) => r.type === PrincipalType.Groups && r.name === group); if (found) { found.permissions.push(permissionType); } else { result.push({ type: PrincipalType.Groups, name: group, permissions: [permissionType] }); } }); } } return result; } /** * A permissions object build function that resets the permissions object * * @public */ resetPermissions() { // reset permissions this.permissions = {}; } /** * A function that gets the premissions object * * @public */ getPermissions() { return this.permissions; } /** * A function that generates query DSL by the specific conditions, used for fetching saved objects from the saved objects index * * @param {Array} permissionTypes the permission types * @param {Object} principals the users or groups * @param {String | Array} savedObjectType saved object type, such as workspace, index-pattern etc. * @returns the generated query DSL * * @public * @static */ static generateGetPermittedSavedObjectsQueryDSL(permissionTypes, principals, savedObjectType) { if (!principals || !permissionTypes) { return { query: { match_none: {}, }, }; } const bool = { filter: [], }; const subBool = { should: [], }; permissionTypes.forEach((permissionType) => { Object.entries(principals).forEach(([principalType, principalsInCurrentType]) => { subBool.should.push({ terms: { ['permissions.' + permissionType + `.${principalType}`]: principalsInCurrentType, }, }); subBool.should.push({ term: { ['permissions.' + permissionType + `.${principalType}`]: '*', }, }); }); }); bool.filter.push({ bool: subBool, }); if (savedObjectType) { bool.filter.push({ terms: { type: Array.isArray(savedObjectType) ? savedObjectType : [savedObjectType], }, }); } return { query: { bool } }; } } exports.ACL = ACL;