UNPKG

passbolt-styleguide

Version:

Passbolt styleguide contains common styling assets used by the different sites, plugin, etc.

332 lines (295 loc) 11.1 kB
/** * Passbolt ~ Open source password manager for teams * Copyright (c) Passbolt SA (https://www.passbolt.com) * * Licensed under GNU Affero General Public License version 3 of the or any later version. * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice. * * @copyright Copyright (c) Passbolt SA (https://www.passbolt.com) * @license https://opensource.org/licenses/AGPL-3.0 AGPL License * @link https://www.passbolt.com Passbolt(tm) * @since 2.13.0 */ import EntityV2Collection from "../../entity/abstract/entityV2Collection"; import { RESOURCE_TYPE_VERSION_4 } from "../metadata/metadataTypesSettingsEntity"; import { RESOURCE_TYPE_PASSWORD_AND_DESCRIPTION_SLUG, RESOURCE_TYPE_PASSWORD_DESCRIPTION_TOTP_SLUG, RESOURCE_TYPE_PASSWORD_STRING_SLUG, RESOURCE_TYPE_TOTP_SLUG, RESOURCE_TYPE_V5_CUSTOM_FIELDS_SLUG, RESOURCE_TYPE_V5_DEFAULT_SLUG, RESOURCE_TYPE_V5_DEFAULT_TOTP_SLUG, RESOURCE_TYPE_V5_PASSWORD_STRING_SLUG, RESOURCE_TYPE_V5_TOTP_SLUG, RESOURCE_TYPE_V5_STANDALONE_NOTE_SLUG, } from "./resourceTypeSchemasDefinition"; import ResourceTypeEntity, { PASSWORD_RESOURCE_TYPES, TOTP_RESOURCE_TYPES } from "./resourceTypeEntity"; import assertString from "validator/es/lib/util/assertString"; const SUPPORTED_RESOURCE_TYPES = [ RESOURCE_TYPE_PASSWORD_STRING_SLUG, RESOURCE_TYPE_PASSWORD_AND_DESCRIPTION_SLUG, RESOURCE_TYPE_PASSWORD_DESCRIPTION_TOTP_SLUG, RESOURCE_TYPE_TOTP_SLUG, RESOURCE_TYPE_V5_DEFAULT_SLUG, RESOURCE_TYPE_V5_DEFAULT_TOTP_SLUG, RESOURCE_TYPE_V5_PASSWORD_STRING_SLUG, RESOURCE_TYPE_V5_TOTP_SLUG, RESOURCE_TYPE_V5_CUSTOM_FIELDS_SLUG, RESOURCE_TYPE_V5_STANDALONE_NOTE_SLUG, ]; class ResourceTypesCollection extends EntityV2Collection { /** * @inheritDoc */ get entityClass() { return ResourceTypeEntity; } /** * @inheritDoc * @throws {EntityCollectionError} Build Rule: Ensure all items in the collection are unique by ID. * @throws {EntityCollectionError} Build Rule: Ensure all items in the collection are unique by slug. */ constructor(dtos = [], options = {}) { super(dtos, options); } /** * Get resources entity schema * * @returns {Object} schema */ static getSchema() { return { type: "array", items: ResourceTypeEntity.getSchema(), }; } /** * @inheritDoc * @param {Set} [options.uniqueIdsSetCache] A set of unique ids. * @param {Set} [options.uniqueSlugsSetCache] A set of unique slugs. * @throws {EntityValidationError} If a permission already exists with the same id. */ validateBuildRules(item, options = {}) { this.assertNotExist("id", item._props.id, { haystackSet: options?.uniqueIdsSetCache }); this.assertNotExist("slug", item._props.slug, { haystackSet: options?.uniqueSlugsSetCache }); } /* * ================================================== * Assertions * ================================================== */ /** * Is resource type id present (supported) * @param id The id * @return {boolean} */ isResourceTypeIdPresent(id) { return this._items.some((resourceType) => resourceType.id === id); } /* * ================================================== * Filter * ================================================== */ /** * Filter by password resource types. * @return {void} The function alters the collection itself. */ filterByPasswordResourceTypes() { this.filterByPropertyValueIn("slug", PASSWORD_RESOURCE_TYPES); } /** * Filter by TOTP resource types. * @return {void} The function alters the collection itself. */ filterByTOTPResourceTypes() { this.filterByPropertyValueIn("slug", TOTP_RESOURCE_TYPES); } /** * Filter by resource type version. * @param {string} version the version used to filter the resource types * @return {void} The function alters the collection itself. */ filterByResourceTypeVersion(version) { this.filterByCallback((resourceType) => resourceType.version === version); } /* * ================================================== * Getters * ================================================== */ /** * Get first by id * @param {string} id * @returns {ResourceTypeEntity} */ getFirstById(id) { return this.getFirst("id", id); } /** * Get first by slug * @param {string} slug * @returns {ResourceTypeEntity} */ getFirstBySlug(slug) { return this.getFirst("slug", slug); } /** * Has one with slug * @param {string} slug * @returns {boolean} */ hasOneWithSlug(slug) { return Boolean(this.getFirstBySlug(slug)); } /** * Has some passwords resource types * @param {string} [version] The version @todo adapt when v5 will be the default * @returns {boolean} */ hasSomePasswordResourceTypes(version = RESOURCE_TYPE_VERSION_4) { return this.items.some((resourceType) => resourceType.hasPassword() && resourceType.version === version); } /** * Has some totp resource types * @param {string} [version] The version @todo adapt when v5 will be the default * @returns {boolean} */ hasSomeTotpResourceTypes(version = RESOURCE_TYPE_VERSION_4) { return this.items.some((resourceType) => resourceType.hasTotp() && resourceType.version === version); } /** * Has some custom fields resource types * @param {string} [version] The version @todo adapt when v5 will be the default * @returns {boolean} */ hasSomeCustomFieldsResourceTypes(version = RESOURCE_TYPE_VERSION_4) { return this.items.some((resourceType) => resourceType.hasCustomFields() && resourceType.version === version); } /** * Has some note resource types * @param {string} [version] The version @todo adapt when v5 will be the default * @returns {boolean} */ hasSomeNoteResourceTypes(version = RESOURCE_TYPE_VERSION_4) { return this.items.some((resourceType) => resourceType.hasSecretDescription() && resourceType.version === version); } /** * Has some metadata description resource types * @param {string} [version] The version @todo adapt when v5 will be the default * @returns {boolean} */ hasSomeMetadataDescriptionResourceTypes(version = RESOURCE_TYPE_VERSION_4) { return this.items.some((resourceType) => resourceType.hasMetadataDescription() && resourceType.version === version); } /** * Has some of the given version * @param {string} [version] The version * @returns {boolean} */ hasSomeOfVersion(version = RESOURCE_TYPE_VERSION_4) { return this.items.some((resourceType) => resourceType.version === version); } /** * Get the resource type matching the resource DTO in a specific version * * Note: This function returns only resource type that match in a specific version. Not supported: * - password string v4; * - password string v5; * - several resource type having the same number of properties that match the resource DTO * * How the match is done: * - First do not check resource type that is not matching the version * - Second check all secret properties from resourceDto are include in the properties of a resource type (exclude some resource types) * - Third count the number of secrets that is not set in the resource type vby the resourceDto * - If all is set then it's a perfect match and return directly the resource type * - Else count the number of property unset and keep the lowest * * Example: For a secret description only * There is no perfect match, so there is one unset property for v5 default and 2 for v5 default and TOTP * The best match is v5 default * * @param {object} resourceDto * @param {string} version * * @returns {ResourceTypeEntity} The resource type that match the resource DTO * @throws {Error} If the version is not a string. * @throws {Error} If the resource DTO is not an object with secret object. */ getResourceTypeMatchingResource(resourceDto, version = RESOURCE_TYPE_VERSION_4) { assertString(version); // Check if the DTO is not null and a secret object if (resourceDto?.secret == null || typeof resourceDto.secret !== "object") { throw new TypeError("The resource DTO is not an expected object"); } // The resource type that matched the most let resourceTypeMatch = null; // Score that should be closest to 0 if no resource type match perfectly let score = null; // The secret fields of the resource DTO const resourceSecretFields = Object.keys(resourceDto.secret); // Loop on all resource types for (const resourceType of this.items) { // Do not check for resource type that not match version or password string if (resourceType.version !== version || resourceType.isPasswordString()) { continue; } // Get all secret property fields const secretsFields = Object.keys(resourceType.definition.secret.properties); // Check if all secret fields from the DTO are in the resource type secret property fields const hasAllPropertyFields = resourceSecretFields.every((secretField) => secretsFields.includes(secretField)); if (hasAllPropertyFields) { // Get the number of properties that is not set to match the resource type const unsetPropertyCount = secretsFields.filter((field) => !resourceSecretFields.includes(field)).length; // If all properties are set, that is a perfect match if (unsetPropertyCount === 0) { return resourceType; } // Else set the score and the resource type that matched the most if (!score || score > unsetPropertyCount) { score = unsetPropertyCount; resourceTypeMatch = resourceType; } } } // If no perfect match, return the resource type that matched the most return resourceTypeMatch; } /* * ================================================== * Setters * ================================================== */ /** * @inheritDoc */ pushMany(data, entityOptions = {}, options = {}) { const uniqueIdsSetCache = new Set(this.extract("id")); const uniqueSlugsSetCache = new Set(this.extract("slug")); const onItemPushed = (item) => { uniqueIdsSetCache.add(item.id); uniqueSlugsSetCache.add(item.slug); }; options = { onItemPushed: onItemPushed, validateBuildRules: { ...options?.validateBuildRules, uniqueIdsSetCache, uniqueSlugsSetCache }, ...options, }; super.pushMany(data, entityOptions, options); } /** * The resource type is checked to ensure that it is supported first. * If it's not supported, the resource type is not added and does not throw any Error. * * @inheritDoc */ push(data, entityOptions = {}, options = {}) { if (!SUPPORTED_RESOURCE_TYPES.includes(data?.slug)) { return; } super.push(data, entityOptions, options); } } export default ResourceTypesCollection;