passbolt-browser-extension 5.13.0 → 5.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.devcontainer/Dockerfile +33 -3
- package/.devcontainer/devcontainer-lock.json +9 -0
- package/.devcontainer/post-start.sh +1 -2
- package/.github/workflows/codeql-analysis.yml +2 -1
- package/.github/workflows/release_candidate.yaml +3 -1
- package/.gitlab-ci.yml +1 -0
- package/CHANGELOG.md +202 -70
- package/CODEOWNERS +2 -0
- package/RELEASE_NOTES.md +4 -2
- package/package.json +9 -7
- package/renovate.json +6 -0
- package/src/all/background_page/controller/InformMenuController/InformMenuController.js +2 -5
- package/src/all/background_page/controller/InformMenuController/InformMenuController.test.js +31 -1
- package/src/all/background_page/controller/account/getAndInitializeAccountLocaleController.js +1 -1
- package/src/all/background_page/controller/account/getAndInitializeAccountLocaleController.test.js +6 -14
- package/src/all/background_page/controller/account/updatePrivateKeyController.js +7 -5
- package/src/all/background_page/controller/account/updatePrivateKeyController.test.js +18 -13
- package/src/all/background_page/controller/accountRecovery/accountRecoveryGenerateOrganizationKeyController.js +4 -2
- package/src/all/background_page/controller/accountRecovery/accountRecoveryGenerateOrganizationKeyController.test.js +25 -2
- package/src/all/background_page/controller/accountRecovery/accountRecoveryLoginController.js +1 -1
- package/src/all/background_page/controller/accountRecovery/accountRecoveryLoginController.test.js +10 -5
- package/src/all/background_page/controller/accountRecovery/recoverAccountController.js +6 -2
- package/src/all/background_page/controller/accountRecovery/recoverAccountController.test.js +11 -4
- package/src/all/background_page/controller/auth/authCheckStatus.test.data.js +6 -6
- package/src/all/background_page/controller/auth/authCheckStatusController.js +11 -3
- package/src/all/background_page/controller/auth/authCheckStatusController.test.js +74 -44
- package/src/all/background_page/controller/auth/authIsMfaRequiredController.js +11 -3
- package/src/all/background_page/controller/auth/authIsMfaRequiredController.test.js +18 -9
- package/src/all/background_page/controller/auth/authLoginController.js +1 -1
- package/src/all/background_page/controller/auth/authLoginController.test.js +10 -5
- package/src/all/background_page/controller/autofill/AutofillController.js +3 -3
- package/src/all/background_page/controller/autofill/AutofillController.test.js +20 -12
- package/src/all/background_page/controller/export/exportResourcesFileController.js +6 -3
- package/src/all/background_page/controller/export/exportResourcesFileController.test.js +34 -4
- package/src/all/background_page/controller/extension/onExtensionInstalledController.js +8 -2
- package/src/all/background_page/controller/extension/onExtensionInstalledController.test.js +5 -1
- package/src/all/background_page/controller/group/{getOrFindGroupsController.js → findGroupsByIdsForShareController.js} +9 -10
- package/src/all/background_page/controller/group/{getOrFindGroupsController.test.js → findGroupsByIdsForShareController.test.js} +8 -8
- package/src/all/background_page/controller/group/groupUpdateController.test.js +1 -0
- package/src/all/background_page/controller/import/importResourcesFileController.test.js +8 -1
- package/src/all/background_page/controller/informCallToActionController/informCallToActionController.js +2 -2
- package/src/all/background_page/controller/informCallToActionController/informCallToActionController.test.js +7 -4
- package/src/all/background_page/controller/locale/getLocaleController.js +3 -2
- package/src/all/background_page/controller/metadata/findMetadataTypesSettingsController.test.js +9 -15
- package/src/all/background_page/controller/metadata/getMetadataTypesSettingsController.test.js +9 -15
- package/src/all/background_page/controller/metadata/getOrFindMetadataKeysSettingsController.test.js +12 -22
- package/src/all/background_page/controller/metadata/shareMetadataKeyPrivateController.test.js +14 -2
- package/src/all/background_page/controller/move/moveFolderController.test.js +8 -0
- package/src/all/background_page/controller/move/moveResourcesController.test.js +8 -0
- package/src/all/background_page/controller/passwordExpiry/getOrFindPasswordExpirySettingsController.test.js +13 -8
- package/src/all/background_page/controller/passwordExpiry/savePasswordExpirySettingsController.js +4 -4
- package/src/all/background_page/controller/passwordExpiry/savePasswordExpirySettingsController.test.js +8 -10
- package/src/all/background_page/controller/permission/findPermissionsByIdsForShareController.js +62 -0
- package/src/all/background_page/controller/permission/findPermissionsByIdsForShareController.test.js +71 -0
- package/src/all/background_page/controller/recover/generateRecoverAccountRecoveryRequestKeyController.js +1 -1
- package/src/all/background_page/controller/resource/resourceCreateController.js +11 -4
- package/src/all/background_page/controller/resource/resourceCreateController.test.js +12 -1
- package/src/all/background_page/controller/resource/resourceUpdateController.js +11 -4
- package/src/all/background_page/controller/resource/resourceUpdateController.test.js +35 -2
- package/src/all/background_page/controller/resourceType/getResourceTypesController.js +5 -4
- package/src/all/background_page/controller/resourceType/getResourceTypesController.test.js +5 -2
- package/src/all/background_page/controller/resourceType/updateAllResourceTypesDeletedStatusController.js +3 -2
- package/src/all/background_page/controller/resourceType/updateAllResourceTypesDeletedStatusController.test.js +16 -3
- package/src/all/background_page/controller/secret/findSecretByResourceIdController.js +3 -3
- package/src/all/background_page/controller/secret/findSecretByResourceIdController.test.js +24 -0
- package/src/all/background_page/controller/secretRevision/findResourceSecretRevisionsForDisplayController.js +2 -1
- package/src/all/background_page/controller/setup/generateSetupKeyPairController.js +6 -3
- package/src/all/background_page/controller/setup/generateSetupKeyPairController.test.js +11 -1
- package/src/all/background_page/controller/setup/getAndInitSetupLocaleController.js +1 -1
- package/src/all/background_page/controller/setup/getAndInitSetupLocaleController.test.js +14 -18
- package/src/all/background_page/controller/setup/setSetupLocaleController.js +1 -1
- package/src/all/background_page/controller/setup/setSetupLocaleController.test.js +6 -10
- package/src/all/background_page/controller/setup/signInSetupController.js +6 -2
- package/src/all/background_page/controller/setup/signInSetupController.test.js +10 -5
- package/src/all/background_page/controller/share/shareOneFolderController.test.js +8 -0
- package/src/all/background_page/controller/share/shareResourcesController.test.js +9 -1
- package/src/all/background_page/controller/siteSettings/getOrFindSiteSettingsController.js +59 -0
- package/src/all/background_page/controller/siteSettings/getOrFindSiteSettingsController.test.js +150 -0
- package/src/all/background_page/controller/{group/getOrFindGroupsUsersController.js → user/getOrFindAllUsersController.js} +12 -17
- package/src/all/background_page/controller/user/getOrFindAllUsersController.test.js +55 -0
- package/src/all/background_page/controller/user/getOrFindLoggedInUserController.js +3 -3
- package/src/all/background_page/controller/user/getOrFindLoggedInUserController.test.js +19 -15
- package/src/all/background_page/controller/user/updateUserLocalStorageController.test.js +8 -5
- package/src/all/background_page/event/accountRecoveryEvents.js +4 -4
- package/src/all/background_page/event/appEvents.js +7 -2
- package/src/all/background_page/event/authEvents.js +2 -2
- package/src/all/background_page/event/groupEvents.js +4 -17
- package/src/all/background_page/event/informCallToActionEvents.js +1 -1
- package/src/all/background_page/event/informMenuEvents.js +1 -1
- package/src/all/background_page/event/localeEvents.js +4 -3
- package/src/all/background_page/event/permissionEvents.js +13 -0
- package/src/all/background_page/event/recoverEvents.js +4 -4
- package/src/all/background_page/event/resourceEvents.js +6 -15
- package/src/all/background_page/event/resourceTypeEvents.js +4 -3
- package/src/all/background_page/event/setupEvents.js +4 -4
- package/src/all/background_page/event/siteSettingsEvents.js +29 -0
- package/src/all/background_page/event/userEvents.js +4 -8
- package/src/all/background_page/index.js +0 -37
- package/src/all/background_page/model/entity/account/abstractAccountEntity.js +2 -2
- package/src/all/background_page/model/entity/account/accountAccountRecoveryEntity.js +7 -17
- package/src/all/background_page/model/entity/account/accountEntity.js +7 -14
- package/src/all/background_page/model/entity/account/accountKitEntity.js +1 -2
- package/src/all/background_page/model/entity/account/accountRecoverEntity.js +4 -14
- package/src/all/background_page/model/entity/account/accountSetupEntity.js +4 -14
- package/src/all/background_page/model/entity/account/accountTemporaryEntity.js +2 -5
- package/src/all/background_page/model/entity/gpgkey/generate/generateGpgKeyPairOptionsEntity.test.js +5 -5
- package/src/all/background_page/model/entity/localStorage/localStorageMetadataEntity.js +49 -0
- package/src/all/background_page/model/entity/localStorage/localStorageMetadataEntity.test.data.js +23 -0
- package/src/all/background_page/model/entity/localStorage/localStorageMetadataEntity.test.js +51 -0
- package/src/all/background_page/model/entity/{organizationSettings/organizationSettingsEntity.js → siteSettings/siteSettingsEntity.js} +17 -24
- package/src/all/background_page/model/entity/{organizationSettings/organizationSettingsEntity.test.data.js → siteSettings/siteSettingsEntity.test.data.js} +9 -9
- package/src/all/background_page/model/entity/{organizationSettings/organizationSettingsEntity.test.js → siteSettings/siteSettingsEntity.test.js} +30 -39
- package/src/all/background_page/model/entity/user/userEntity.test.js +6 -6
- package/src/all/background_page/model/export/resources/resourcesKdbxExporter.js +40 -3
- package/src/all/background_page/model/export/resources/resourcesKdbxExporter.test.js +122 -0
- package/src/all/background_page/model/import/resources/resourcesKdbxImportParser.js +1 -1
- package/src/all/background_page/model/locale/localeModel.js +13 -8
- package/src/all/background_page/model/passwordExpiry/passwordExpirySettingsModel.js +6 -6
- package/src/all/background_page/model/passwordExpiry/passwordExpirySettingsModel.test.js +3 -2
- package/src/all/background_page/model/resource/resourceModel.js +4 -4
- package/src/all/background_page/model/user/userModel.js +7 -28
- package/src/all/background_page/model/user/userModel.test.js +51 -99
- package/src/all/background_page/pagemod/appBootstrapPagemod.js +4 -1
- package/src/all/background_page/pagemod/appBootstrapPagemod.test.js +5 -2
- package/src/all/background_page/pagemod/appPagemod.js +32 -6
- package/src/all/background_page/pagemod/appPagemod.test.js +22 -10
- package/src/all/background_page/pagemod/authPagemod.js +2 -10
- package/src/all/background_page/pagemod/authPagemod.test.js +4 -4
- package/src/all/background_page/pagemod/pagemodManager.test.js +5 -2
- package/src/all/background_page/pagemod/quickAccessPagemod.js +2 -2
- package/src/all/background_page/pagemod/quickAccessPagemod.test.js +4 -4
- package/src/all/background_page/pagemod/recoverPagemod.js +2 -2
- package/src/all/background_page/pagemod/recoverPagemod.test.js +6 -0
- package/src/all/background_page/pagemod/setupPagemod.js +2 -2
- package/src/all/background_page/pagemod/setupPagemod.test.js +6 -0
- package/src/all/background_page/pagemod/webIntegrationPagemod.js +21 -2
- package/src/all/background_page/pagemod/webIntegrationPagemod.test.js +16 -25
- package/src/all/background_page/service/account/getActiveAccountService.js +2 -3
- package/src/all/background_page/service/account/getLegacyAccountService.js +3 -14
- package/src/all/background_page/service/account/updateSsoCredentialsService.js +9 -5
- package/src/all/background_page/service/api/group/groupApiService.js +9 -16
- package/src/all/background_page/service/api/group/groupApiService.test.js +59 -26
- package/src/all/background_page/service/api/siteSettings/siteSettingsApiService.js +46 -0
- package/src/all/background_page/service/api/siteSettings/siteSettingsApiService.test.js +63 -0
- package/src/all/background_page/service/auth/checkAuthStatusService.js +27 -14
- package/src/all/background_page/service/auth/checkAuthStatusService.test.js +80 -62
- package/src/all/background_page/service/auth/postLoginService.js +3 -3
- package/src/all/background_page/service/auth/postLoginService.test.js +4 -4
- package/src/all/background_page/service/auth/startLoopAuthSessionCheckService.js +5 -1
- package/src/all/background_page/service/auth/startLoopAuthSessionCheckService.test.js +14 -8
- package/src/all/background_page/service/authenticationStatusService.js +13 -18
- package/src/all/background_page/service/authenticationStatusService.test.js +9 -6
- package/src/all/background_page/service/crypto/generateGpgKeyPairService.test.js +5 -5
- package/src/all/background_page/service/crypto/getGpgKeyCreationDateService.js +7 -6
- package/src/all/background_page/service/crypto/getGpgKeyCreationDateService.test.js +10 -7
- package/src/all/background_page/service/extension/onExtensionUpdateAvailableService.js +7 -2
- package/src/all/background_page/service/extension/onExtensionUpdateAvailableService.test.js +5 -5
- package/src/all/background_page/service/group/findGroupsService.js +42 -1
- package/src/all/background_page/service/group/findGroupsService.test.js +82 -0
- package/src/all/background_page/service/group/groupUpdateSecretsCryptoService.js +82 -0
- package/src/all/background_page/service/group/groupUpdateSecretsCryptoService.test.js +102 -0
- package/src/all/background_page/service/group/groupUpdateService.js +49 -78
- package/src/all/background_page/service/group/groupUpdateService.test.js +136 -0
- package/src/all/background_page/service/localStorage/localStorageService.js +8 -6
- package/src/all/background_page/service/localStorage/localStorageService.test.js +33 -15
- package/src/all/background_page/service/local_storage/abstractLocalStorage.js +193 -0
- package/src/all/background_page/service/local_storage/abstractLocalStorage.test.data.js +45 -0
- package/src/all/background_page/service/local_storage/abstractLocalStorage.test.js +271 -0
- package/src/all/background_page/service/local_storage/activeSessionLocalStorage.js +105 -0
- package/src/all/background_page/service/local_storage/activeSessionLocalStorage.test.js +153 -0
- package/src/all/background_page/service/local_storage/rbacLocalStorage.js +10 -82
- package/src/all/background_page/service/local_storage/rbacLocalStorage.test.js +8 -8
- package/src/all/background_page/service/local_storage/resourceTypeLocalStorage.js +10 -43
- package/src/all/background_page/service/local_storage/resourceTypeLocalStorage.test.js +68 -0
- package/src/all/background_page/service/local_storage/siteSettingsLocalStorage.js +104 -0
- package/src/all/background_page/service/local_storage/siteSettingsLocalStorage.test.js +114 -0
- package/src/all/background_page/service/local_storage/userMeLocalStorage.js +50 -0
- package/src/all/background_page/service/{sessionStorage/userMeSessionStorageService.test.js → local_storage/userMeLocalStorage.test.js} +55 -36
- package/src/all/background_page/service/metadata/encryptMetadataService.js +3 -3
- package/src/all/background_page/service/metadata/encryptMetadataService.test.js +11 -11
- package/src/all/background_page/service/metadata/findAndUpdateMetadataSettingsLocalStorageService.js +4 -4
- package/src/all/background_page/service/metadata/findAndUpdateMetadataSettingsLocalStorageService.test.js +18 -16
- package/src/all/background_page/service/metadata/getOrFindMetadataSettingsService.test.js +6 -8
- package/src/all/background_page/service/metadata/rotateMetadata/rotateResourcesMetadataKeyService.test.js +4 -4
- package/src/all/background_page/service/metadata/shareMetadataKeyPrivateService.js +3 -3
- package/src/all/background_page/service/metadata/shareMetadataKeyPrivateService.test.js +1 -1
- package/src/all/background_page/service/metadata/verifyOrTrustMetadataKeyService.js +4 -4
- package/src/all/background_page/service/metadata/verifyOrTrustMetadataKeyService.test.js +9 -7
- package/src/all/background_page/service/migrateMetadata/migrateMetadataResourcesService.js +4 -4
- package/src/all/background_page/service/migrateMetadata/migrateMetadataResourcesService.test.js +6 -6
- package/src/all/background_page/service/rbac/findAndUpdateRbacsLocalStorageService.js +2 -2
- package/src/all/background_page/service/rbac/getOrFindRbacService.js +1 -1
- package/src/all/background_page/service/resource/create/resourceCreateService.js +41 -51
- package/src/all/background_page/service/resource/create/resourceCreateService.test.js +100 -98
- package/src/all/background_page/service/resource/export/exportResourcesService.js +7 -7
- package/src/all/background_page/service/resource/findAndUpdateResourcesLocalStorageService.js +4 -4
- package/src/all/background_page/service/resource/findResourcesService.js +13 -16
- package/src/all/background_page/service/resource/findResourcesService.test.js +12 -11
- package/src/all/background_page/service/resource/getOrFindResourcesService.js +3 -3
- package/src/all/background_page/service/resource/import/ImportResourcesService.js +9 -9
- package/src/all/background_page/service/resource/import/ImportResourcesService.test.js +30 -15
- package/src/all/background_page/service/resource/update/resourceUpdateService.js +38 -19
- package/src/all/background_page/service/resource/update/resourceUpdateService.test.js +64 -31
- package/src/all/background_page/service/resourceType/getOrFindResourceTypesService.js +49 -0
- package/src/all/background_page/service/resourceType/getOrFindResourceTypesService.test.js +61 -0
- package/src/all/background_page/service/resourceType/getSecretSchemaResourceTypeService.js +44 -0
- package/src/all/background_page/service/resourceType/updateResourceTypesService.js +6 -4
- package/src/all/background_page/service/resourceType/updateResourceTypesService.test.js +19 -14
- package/src/all/background_page/service/secretRevisions/findAndDecryptSecretRevisionsService.js +5 -4
- package/src/all/background_page/service/secretRevisions/findAndDecryptSecretRevisionsService.test.js +16 -9
- package/src/all/background_page/service/share/shareResourceService.js +4 -4
- package/src/all/background_page/service/share/shareResourceService.test.js +6 -6
- package/src/all/background_page/service/siteSettings/findAndUpdateSiteSettingsLocalStorageService.js +77 -0
- package/src/all/background_page/service/siteSettings/findAndUpdateSiteSettingsLocalStorageService.test.js +130 -0
- package/src/all/background_page/service/siteSettings/findSiteSettingsService.js +47 -0
- package/src/all/background_page/service/siteSettings/findSiteSettingsService.test.js +68 -0
- package/src/all/background_page/service/siteSettings/getOrFindSiteSettingsService.js +84 -0
- package/src/all/background_page/service/siteSettings/getOrFindSiteSettingsService.test.js +175 -0
- package/src/all/background_page/service/siteSettings/siteSettingsRuntimeCache.js +70 -0
- package/src/all/background_page/service/sso/generateSsoKitService.test.js +2 -2
- package/src/all/background_page/service/toolbar/toolbarService.js +6 -4
- package/src/all/background_page/service/toolbar/toolbarService.test.js +14 -13
- package/src/all/background_page/service/user/findAndUpdateUsersLocalStorageService.js +4 -4
- package/src/all/background_page/service/user/findAndUpdateUsersLocalStorageService.test.js +3 -3
- package/src/all/background_page/service/user/getOrFindMeService.js +64 -0
- package/src/all/background_page/service/user/getOrFindMeService.test.js +65 -0
- package/src/all/background_page/service/userKeyPolicies/findUserKeyPoliciesSettingsService.js +5 -4
- package/src/all/background_page/service/userKeyPolicies/findUserKeyPoliciesSettingsService.test.js +12 -11
- package/src/all/background_page/service/validator/appEmailValidatorService.js +11 -6
- package/src/all/background_page/service/validator/appEmailValidatorService.test.js +11 -11
- package/src/all/common/polyfill/browserPolyfill.js +8 -8
- package/src/all/locales/cs-CZ/common.json +1 -4
- package/src/all/locales/de-DE/common.json +1 -4
- package/src/all/locales/en-UK/common.json +0 -3
- package/src/all/locales/es-ES/common.json +1 -4
- package/src/all/locales/fr-FR/common.json +1 -4
- package/src/all/locales/it-IT/common.json +1 -4
- package/src/all/locales/ja-JP/common.json +1 -4
- package/src/all/locales/ko-KR/common.json +0 -3
- package/src/all/locales/lt-LT/common.json +1 -4
- package/src/all/locales/nl-NL/common.json +1 -4
- package/src/all/locales/pl-PL/common.json +1 -4
- package/src/all/locales/pt-BR/common.json +1 -4
- package/src/all/locales/ro-RO/common.json +1 -4
- package/src/all/locales/ru-RU/common.json +1 -4
- package/src/all/locales/sl-SI/common.json +1 -4
- package/src/all/locales/sv-SE/common.json +1 -4
- package/src/all/locales/uk-UA/common.json +1 -4
- package/src/all/webAccessibleResources/js/app/QuickAccess.js +7 -0
- package/src/chrome/manifest.json +1 -1
- package/src/chrome-mv3/manifest.json +1 -1
- package/src/chrome-mv3/offscreens/service/group/addUsersToGroupOffscreenService.js +132 -0
- package/src/chrome-mv3/offscreens/service/group/addUsersToGroupOffscreenService.test.js +125 -0
- package/src/chrome-mv3/offscreens/service/offscreen/handleOffscreenRequestService.js +4 -0
- package/src/chrome-mv3/serviceWorker/service/addUsersToGroup/requestAddUsersToGroupOffscreenService.js +83 -0
- package/src/chrome-mv3/serviceWorker/service/addUsersToGroup/requestAddUsersToGroupOffscreenService.test.js +116 -0
- package/src/chrome-mv3/serviceWorker/service/addUsersToGroup/responseAddUsersToGroupOffscreenService.js +99 -0
- package/src/chrome-mv3/serviceWorker/service/addUsersToGroup/responseAddUsersToGroupOffscreenService.test.data.js +45 -0
- package/src/chrome-mv3/serviceWorker/service/addUsersToGroup/responseAddUsersToGroupOffscreenService.test.js +87 -0
- package/src/chrome-mv3/serviceWorker/service/network/requestFetchOffscreenService.js +0 -1
- package/src/chrome-mv3/serviceWorker/service/offscreen/handleOffscreenResponseService.js +15 -0
- package/src/firefox/manifest.json +1 -1
- package/src/safari/background_page/index.js +0 -37
- package/src/safari/common/polyfill/safariBrowserPolyfill.js +10 -10
- package/src/safari/manifest.json +1 -1
- package/test/jest.setup.js +4 -2
- package/src/all/background_page/controller/group/getOrFindGroupsUsersController.test.js +0 -69
- package/src/all/background_page/controller/organizationSettings/getOrganizationSettingsController.js +0 -55
- package/src/all/background_page/controller/organizationSettings/getOrganizationSettingsController.test.js +0 -45
- package/src/all/background_page/controller/resource/findAllByIdsForDisplayPermissionsController.js +0 -76
- package/src/all/background_page/controller/resource/findAllByIdsForDisplayPermissionsController.test.js +0 -102
- package/src/all/background_page/event/organizationSettingsEvents.js +0 -37
- package/src/all/background_page/model/organizationSettings/organizationSettingsModel.js +0 -93
- package/src/all/background_page/model/resourceType/resourceTypeModel.js +0 -72
- package/src/all/background_page/model/resourceType/resourceTypeModel.test.js +0 -101
- package/src/all/background_page/service/api/organizationSettings/organizationSettingsService.js +0 -58
- package/src/all/background_page/service/group/getOrFindGroupsService.js +0 -65
- package/src/all/background_page/service/group/getOrFindGroupsService.test.js +0 -168
- package/src/all/background_page/service/group/getOrFindGroupsUsersService.js +0 -51
- package/src/all/background_page/service/group/getOrFindGroupsUsersService.test.js +0 -94
- package/src/all/background_page/service/local_storage/authStatusLocalStorage.js +0 -70
- package/src/all/background_page/service/sessionStorage/userMeSessionStorageService.js +0 -94
|
@@ -14,30 +14,23 @@
|
|
|
14
14
|
import Entity from "passbolt-styleguide/src/shared/models/entity/abstract/entity";
|
|
15
15
|
import EntitySchema from "passbolt-styleguide/src/shared/models/entity/abstract/entitySchema";
|
|
16
16
|
|
|
17
|
-
const ENTITY_NAME = "
|
|
17
|
+
const ENTITY_NAME = "SiteSettings";
|
|
18
18
|
|
|
19
19
|
// Organization status
|
|
20
20
|
const ORGANIZATION_ENABLED = "enabled";
|
|
21
21
|
const ORGANIZATION_DISABLED = "disabled";
|
|
22
22
|
const ORGANIZATION_NOT_FOUND = "not found";
|
|
23
23
|
|
|
24
|
-
class
|
|
24
|
+
class SiteSettingsEntity extends Entity {
|
|
25
25
|
/**
|
|
26
26
|
* @inheritDoc
|
|
27
27
|
* Sanitize: Override default settings using the data provided in the DTO.
|
|
28
28
|
*/
|
|
29
|
-
constructor(
|
|
29
|
+
constructor(siteSettingsDto, options = {}) {
|
|
30
30
|
// Default properties values
|
|
31
|
-
const props = Object.assign(
|
|
32
|
-
const sanitizedDto =
|
|
33
|
-
super(
|
|
34
|
-
EntitySchema.validate(
|
|
35
|
-
OrganizationSettingsEntity.ENTITY_NAME,
|
|
36
|
-
sanitizedDto,
|
|
37
|
-
OrganizationSettingsEntity.getSchema(),
|
|
38
|
-
),
|
|
39
|
-
options,
|
|
40
|
-
);
|
|
31
|
+
const props = Object.assign(SiteSettingsEntity.getDefault(), siteSettingsDto);
|
|
32
|
+
const sanitizedDto = SiteSettingsEntity.sanitizeDto(props);
|
|
33
|
+
super(EntitySchema.validate(SiteSettingsEntity.ENTITY_NAME, sanitizedDto, SiteSettingsEntity.getSchema()), options);
|
|
41
34
|
}
|
|
42
35
|
|
|
43
36
|
/**
|
|
@@ -46,7 +39,7 @@ class OrganizationSettingsEntity extends Entity {
|
|
|
46
39
|
*/
|
|
47
40
|
static getDefault() {
|
|
48
41
|
return {
|
|
49
|
-
status:
|
|
42
|
+
status: SiteSettingsEntity.ORGANIZATION_ENABLED,
|
|
50
43
|
};
|
|
51
44
|
}
|
|
52
45
|
|
|
@@ -62,9 +55,9 @@ class OrganizationSettingsEntity extends Entity {
|
|
|
62
55
|
status: {
|
|
63
56
|
type: "string",
|
|
64
57
|
enum: [
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
58
|
+
SiteSettingsEntity.ORGANIZATION_ENABLED,
|
|
59
|
+
SiteSettingsEntity.ORGANIZATION_DISABLED,
|
|
60
|
+
SiteSettingsEntity.ORGANIZATION_NOT_FOUND,
|
|
68
61
|
],
|
|
69
62
|
},
|
|
70
63
|
app: {
|
|
@@ -84,7 +77,7 @@ class OrganizationSettingsEntity extends Entity {
|
|
|
84
77
|
/**
|
|
85
78
|
* Return a disabled organization settings.
|
|
86
79
|
*/
|
|
87
|
-
static get
|
|
80
|
+
static get disabledSiteSettings() {
|
|
88
81
|
return {
|
|
89
82
|
status: this.ORGANIZATION_DISABLED,
|
|
90
83
|
};
|
|
@@ -100,7 +93,7 @@ class OrganizationSettingsEntity extends Entity {
|
|
|
100
93
|
static sanitizeDto(dto) {
|
|
101
94
|
const sanitizedDto = JSON.parse(JSON.stringify(dto));
|
|
102
95
|
|
|
103
|
-
|
|
96
|
+
SiteSettingsEntity.sanitizeEmailValidateRegex(sanitizedDto);
|
|
104
97
|
|
|
105
98
|
return sanitizedDto;
|
|
106
99
|
}
|
|
@@ -215,7 +208,7 @@ class OrganizationSettingsEntity extends Entity {
|
|
|
215
208
|
* ==================================================
|
|
216
209
|
*/
|
|
217
210
|
/**
|
|
218
|
-
*
|
|
211
|
+
* SiteSettingsEntity.ENTITY_NAME
|
|
219
212
|
* @returns {string}
|
|
220
213
|
*/
|
|
221
214
|
static get ENTITY_NAME() {
|
|
@@ -223,7 +216,7 @@ class OrganizationSettingsEntity extends Entity {
|
|
|
223
216
|
}
|
|
224
217
|
|
|
225
218
|
/**
|
|
226
|
-
*
|
|
219
|
+
* SiteSettingsEntity.ORGANIZATION_ENABLED
|
|
227
220
|
* @returns {string}
|
|
228
221
|
*/
|
|
229
222
|
static get ORGANIZATION_ENABLED() {
|
|
@@ -231,7 +224,7 @@ class OrganizationSettingsEntity extends Entity {
|
|
|
231
224
|
}
|
|
232
225
|
|
|
233
226
|
/**
|
|
234
|
-
*
|
|
227
|
+
* SiteSettingsEntity.ORGANIZATION_DISABLED
|
|
235
228
|
* @returns {string}
|
|
236
229
|
*/
|
|
237
230
|
static get ORGANIZATION_DISABLED() {
|
|
@@ -239,7 +232,7 @@ class OrganizationSettingsEntity extends Entity {
|
|
|
239
232
|
}
|
|
240
233
|
|
|
241
234
|
/**
|
|
242
|
-
*
|
|
235
|
+
* SiteSettingsEntity.ORGANIZATION_NOT_FOUND
|
|
243
236
|
* @returns {string}
|
|
244
237
|
*/
|
|
245
238
|
static get ORGANIZATION_NOT_FOUND() {
|
|
@@ -247,4 +240,4 @@ class OrganizationSettingsEntity extends Entity {
|
|
|
247
240
|
}
|
|
248
241
|
}
|
|
249
242
|
|
|
250
|
-
export default
|
|
243
|
+
export default SiteSettingsEntity;
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
* @since 3.6.0
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import
|
|
15
|
+
import SiteSettingsEntity from "./siteSettingsEntity";
|
|
16
16
|
|
|
17
|
-
export const
|
|
17
|
+
export const anonymousSiteSettings = (data = {}) => {
|
|
18
18
|
const defaultData = {
|
|
19
|
-
status:
|
|
19
|
+
status: SiteSettingsEntity.ORGANIZATION_ENABLED,
|
|
20
20
|
app: {
|
|
21
21
|
url: "http://127.0.0.1:3001",
|
|
22
22
|
locale: "en-UK",
|
|
@@ -132,8 +132,8 @@ export const anonymousOrganizationSettings = (data = {}) => {
|
|
|
132
132
|
return Object.assign(defaultData, data);
|
|
133
133
|
};
|
|
134
134
|
|
|
135
|
-
export const
|
|
136
|
-
const defaultData =
|
|
135
|
+
export const defaultCeSiteSettings = (siteSettings) => {
|
|
136
|
+
const defaultData = anonymousSiteSettings();
|
|
137
137
|
defaultData.app = {
|
|
138
138
|
url: "http://127.0.0.1:3001",
|
|
139
139
|
locale: "en-UK",
|
|
@@ -214,8 +214,8 @@ export const defaultCeOrganizationSettings = (siteSettings) => {
|
|
|
214
214
|
return Object.assign(defaultData, siteSettings);
|
|
215
215
|
};
|
|
216
216
|
|
|
217
|
-
export const
|
|
218
|
-
const defaultData =
|
|
217
|
+
export const defaultProSiteSettings = (siteSettings) => {
|
|
218
|
+
const defaultData = defaultCeSiteSettings();
|
|
219
219
|
defaultData.passbolt.edition = "pro";
|
|
220
220
|
defaultData.passbolt.plugins = Object.assign(defaultData.passbolt.plugins, {
|
|
221
221
|
accountRecoveryRequestHelp: {
|
|
@@ -267,8 +267,8 @@ export const defaultProOrganizationSettings = (siteSettings) => {
|
|
|
267
267
|
return Object.assign(defaultData, siteSettings);
|
|
268
268
|
};
|
|
269
269
|
|
|
270
|
-
export const
|
|
271
|
-
const defaultData =
|
|
270
|
+
export const customEmailValidationProSiteSettings = (siteSettings) => {
|
|
271
|
+
const defaultData = defaultProSiteSettings();
|
|
272
272
|
defaultData.passbolt.email = {
|
|
273
273
|
validate: {
|
|
274
274
|
regex: "\/.*@passbolt.(c|com)$\/",
|
|
@@ -13,25 +13,22 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import EntitySchema from "passbolt-styleguide/src/shared/models/entity/abstract/entitySchema";
|
|
16
|
-
import
|
|
17
|
-
import {
|
|
18
|
-
customEmailValidationProOrganizationSettings,
|
|
19
|
-
defaultProOrganizationSettings,
|
|
20
|
-
} from "./organizationSettingsEntity.test.data";
|
|
16
|
+
import SiteSettingsEntity from "./siteSettingsEntity";
|
|
17
|
+
import { customEmailValidationProSiteSettings, defaultProSiteSettings } from "./siteSettingsEntity.test.data";
|
|
21
18
|
import * as assertEntityProperty from "passbolt-styleguide/test/assert/assertEntityProperty";
|
|
22
19
|
|
|
23
|
-
describe("
|
|
24
|
-
describe("
|
|
20
|
+
describe("SiteSettingsEntity entity", () => {
|
|
21
|
+
describe("SiteSettingsEntity::getSchema", () => {
|
|
25
22
|
it("schema must validate", () => {
|
|
26
|
-
EntitySchema.validateSchema(
|
|
23
|
+
EntitySchema.validateSchema(SiteSettingsEntity.ENTITY_NAME, SiteSettingsEntity.getSchema());
|
|
27
24
|
});
|
|
28
25
|
|
|
29
26
|
it("validates status property", () => {
|
|
30
27
|
const successValues = ["enabled", "disabled", "not found"];
|
|
31
28
|
const failValues = ["string"];
|
|
32
29
|
|
|
33
|
-
assertEntityProperty.enumeration(
|
|
34
|
-
assertEntityProperty.notRequired(
|
|
30
|
+
assertEntityProperty.enumeration(SiteSettingsEntity, "status", successValues, failValues);
|
|
31
|
+
assertEntityProperty.notRequired(SiteSettingsEntity, "status");
|
|
35
32
|
});
|
|
36
33
|
|
|
37
34
|
it("validates app property", () => {
|
|
@@ -42,8 +39,8 @@ describe("OrganizationSettingsEntity entity", () => {
|
|
|
42
39
|
*/
|
|
43
40
|
const failingScenarios = [];
|
|
44
41
|
|
|
45
|
-
assertEntityProperty.assert(
|
|
46
|
-
assertEntityProperty.notRequired(
|
|
42
|
+
assertEntityProperty.assert(SiteSettingsEntity, "app", successScenarios, failingScenarios, "type");
|
|
43
|
+
assertEntityProperty.notRequired(SiteSettingsEntity, "app");
|
|
47
44
|
});
|
|
48
45
|
|
|
49
46
|
it("validates passbolt property", () => {
|
|
@@ -54,8 +51,8 @@ describe("OrganizationSettingsEntity entity", () => {
|
|
|
54
51
|
*/
|
|
55
52
|
const failingScenarios = [];
|
|
56
53
|
|
|
57
|
-
assertEntityProperty.assert(
|
|
58
|
-
assertEntityProperty.notRequired(
|
|
54
|
+
assertEntityProperty.assert(SiteSettingsEntity, "passbolt", successScenarios, failingScenarios, "type");
|
|
55
|
+
assertEntityProperty.notRequired(SiteSettingsEntity, "passbolt");
|
|
59
56
|
});
|
|
60
57
|
|
|
61
58
|
it("validates serverTimeDiff property", () => {
|
|
@@ -66,52 +63,46 @@ describe("OrganizationSettingsEntity entity", () => {
|
|
|
66
63
|
assertEntityProperty.SCENARIO_OBJECT,
|
|
67
64
|
];
|
|
68
65
|
|
|
69
|
-
assertEntityProperty.assert(
|
|
70
|
-
|
|
71
|
-
"serverTimeDiff",
|
|
72
|
-
successScenarios,
|
|
73
|
-
failingScenarios,
|
|
74
|
-
"type",
|
|
75
|
-
);
|
|
76
|
-
assertEntityProperty.notRequired(OrganizationSettingsEntity, "serverTimeDiff");
|
|
66
|
+
assertEntityProperty.assert(SiteSettingsEntity, "serverTimeDiff", successScenarios, failingScenarios, "type");
|
|
67
|
+
assertEntityProperty.notRequired(SiteSettingsEntity, "serverTimeDiff");
|
|
77
68
|
});
|
|
78
69
|
});
|
|
79
70
|
|
|
80
|
-
describe("
|
|
81
|
-
it("Should instantiate an
|
|
71
|
+
describe("SiteSettingsEntity::constructor", () => {
|
|
72
|
+
it("Should instantiate an SiteSettingsEntity with a minimal DTO", () => {
|
|
82
73
|
expect.assertions(2);
|
|
83
74
|
const dto = {};
|
|
84
|
-
expect(() => new
|
|
85
|
-
expect(new
|
|
75
|
+
expect(() => new SiteSettingsEntity(dto)).not.toThrow();
|
|
76
|
+
expect(new SiteSettingsEntity(dto).toDto()).toStrictEqual({
|
|
86
77
|
status: "enabled",
|
|
87
78
|
});
|
|
88
79
|
});
|
|
89
80
|
|
|
90
|
-
it("Should instantiate an
|
|
81
|
+
it("Should instantiate an SiteSettingsEntity with full DTO", () => {
|
|
91
82
|
expect.assertions(2);
|
|
92
|
-
const dto =
|
|
93
|
-
expect(() => new
|
|
94
|
-
expect(new
|
|
83
|
+
const dto = defaultProSiteSettings();
|
|
84
|
+
expect(() => new SiteSettingsEntity(dto)).not.toThrow();
|
|
85
|
+
expect(new SiteSettingsEntity(dto).toDto()).toStrictEqual(dto);
|
|
95
86
|
});
|
|
96
87
|
});
|
|
97
88
|
|
|
98
|
-
describe("
|
|
89
|
+
describe("SiteSettingsEntity::sanitizeEmailValidateRegex", () => {
|
|
99
90
|
it("should sanitize API regex and remove starting and trailing slash", () => {
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
expect(
|
|
91
|
+
const siteSettings = customEmailValidationProSiteSettings();
|
|
92
|
+
SiteSettingsEntity.sanitizeEmailValidateRegex(siteSettings);
|
|
93
|
+
expect(siteSettings.passbolt.email.validate.regex).toEqual(".*@passbolt.(c|com)$");
|
|
103
94
|
});
|
|
104
95
|
});
|
|
105
96
|
|
|
106
|
-
describe("
|
|
97
|
+
describe("SiteSettingsEntity::emailValidateRegex", () => {
|
|
107
98
|
it("should return null if undefined", () => {
|
|
108
|
-
const
|
|
109
|
-
const entity = new
|
|
99
|
+
const siteSettings = defaultProSiteSettings();
|
|
100
|
+
const entity = new SiteSettingsEntity(siteSettings);
|
|
110
101
|
expect(entity.emailValidateRegex).toBeNull();
|
|
111
102
|
});
|
|
112
103
|
it("should return the customized setting if any", () => {
|
|
113
|
-
const
|
|
114
|
-
const entity = new
|
|
104
|
+
const siteSettings = customEmailValidationProSiteSettings();
|
|
105
|
+
const entity = new SiteSettingsEntity(siteSettings);
|
|
115
106
|
expect(entity.emailValidateRegex).toEqual(".*@passbolt.(c|com)$");
|
|
116
107
|
});
|
|
117
108
|
});
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import BextUserEntity from "./userEntity";
|
|
15
15
|
import AppEmailValidatorService from "../../../service/validator/appEmailValidatorService";
|
|
16
|
-
import
|
|
17
|
-
import
|
|
18
|
-
import { customEmailValidationProOrganizationSettings } from "../organizationSettings/organizationSettingsEntity.test.data";
|
|
16
|
+
import SiteSettingsEntity from "passbolt-styleguide/src/shared/models/entity/siteSettings/siteSettingsEntity";
|
|
17
|
+
import { customEmailValidationProSiteSettings } from "passbolt-styleguide/src/shared/models/entity/siteSettings/siteSettingsEntity.test.data";
|
|
19
18
|
import { defaultUserDto } from "passbolt-styleguide/src/shared/models/entity/user/userEntity.test.data";
|
|
20
19
|
import GroupsUsersCollection from "passbolt-styleguide/src/shared/models/entity/groupUser/groupsUsersCollection";
|
|
21
20
|
import * as assertEntityProperty from "passbolt-styleguide/test/assert/assertEntityProperty";
|
|
21
|
+
import SiteSettingsRuntimeCache from "../../../service/siteSettings/siteSettingsRuntimeCache";
|
|
22
22
|
|
|
23
23
|
describe("BextUserEntity", () => {
|
|
24
24
|
describe("BextUserEntity::getSchema", () => {
|
|
@@ -36,8 +36,8 @@ describe("BextUserEntity", () => {
|
|
|
36
36
|
|
|
37
37
|
it("validates username with custom validation rule", () => {
|
|
38
38
|
expect.assertions(2);
|
|
39
|
-
const organizationSettings =
|
|
40
|
-
|
|
39
|
+
const organizationSettings = customEmailValidationProSiteSettings();
|
|
40
|
+
SiteSettingsRuntimeCache.set(new SiteSettingsEntity(organizationSettings));
|
|
41
41
|
const dto = defaultUserDto({ username: "ada@passbolt.c" });
|
|
42
42
|
const entity = new BextUserEntity(dto);
|
|
43
43
|
expect(entity.username).toEqual("ada@passbolt.c");
|
|
@@ -45,7 +45,7 @@ describe("BextUserEntity", () => {
|
|
|
45
45
|
* Ensure that the custom formula used to validate the format of the email is dynamic, and can be changed even if the
|
|
46
46
|
* entity schema is cached. This formula might loaded after the schema was cached and could lead to user not valid.
|
|
47
47
|
*/
|
|
48
|
-
|
|
48
|
+
SiteSettingsRuntimeCache.flushAll();
|
|
49
49
|
expect(() => new BextUserEntity(dto)).toThrowEntityValidationError("username", "custom");
|
|
50
50
|
});
|
|
51
51
|
});
|
|
@@ -14,6 +14,7 @@ import ExternalFolderEntity from "../../entity/folder/external/externalFolderEnt
|
|
|
14
14
|
import * as kdbxweb from "kdbxweb";
|
|
15
15
|
import { FORMAT_KDBX, FORMAT_KDBX_OTHERS } from "../../entity/export/exportResourcesFileEntity";
|
|
16
16
|
import { ICON_TYPE_KEEPASS_ICON_SET } from "passbolt-styleguide/src/shared/models/entity/resource/metadata/IconEntity";
|
|
17
|
+
import { KDBX_SUPPORTED_FIELDS } from "../../import/resources/resourcesKdbxImportParser";
|
|
17
18
|
|
|
18
19
|
class ResourcesKdbxExporter {
|
|
19
20
|
/**
|
|
@@ -22,11 +23,12 @@ class ResourcesKdbxExporter {
|
|
|
22
23
|
*/
|
|
23
24
|
constructor(exportEntity) {
|
|
24
25
|
this.exportEntity = exportEntity;
|
|
26
|
+
this.customFieldsConflicts = [];
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
/**
|
|
28
30
|
* Export
|
|
29
|
-
* @returns {Promise<
|
|
31
|
+
* @returns {Promise<Array<{resourceName: string, originalKey: string, newKey: string}>>} The custom fields renamed to avoid conflicting with reserved KeePass field names
|
|
30
32
|
*/
|
|
31
33
|
async export() {
|
|
32
34
|
const kdbxDb = await this.createKdbxDb();
|
|
@@ -39,6 +41,7 @@ class ResourcesKdbxExporter {
|
|
|
39
41
|
this.createKdbxEntry(kdbxDb, childExportResource, kdbxDb.getDefaultGroup()),
|
|
40
42
|
);
|
|
41
43
|
this.exportEntity.file = await kdbxDb.save();
|
|
44
|
+
return this.customFieldsConflicts;
|
|
42
45
|
}
|
|
43
46
|
|
|
44
47
|
/**
|
|
@@ -120,7 +123,9 @@ class ResourcesKdbxExporter {
|
|
|
120
123
|
}
|
|
121
124
|
|
|
122
125
|
/**
|
|
123
|
-
* Set the custom fields according to the kdbx format
|
|
126
|
+
* Set the custom fields according to the kdbx format.
|
|
127
|
+
* A custom field whose key collides with a reserved KeePass field (e.g. "Password") or an already set field
|
|
128
|
+
* is renamed with a post-fix numeration ("Password (1)") to avoid overwriting the reserved field value.
|
|
124
129
|
* @param {kdbxweb.KdbxEntry} kdbxEntry
|
|
125
130
|
* @param {ExternalResourceEntity} externalResourceEntity
|
|
126
131
|
* @returns {void}
|
|
@@ -128,11 +133,43 @@ class ResourcesKdbxExporter {
|
|
|
128
133
|
setCustomFields(kdbxEntry, externalResourceEntity) {
|
|
129
134
|
if (externalResourceEntity.customFields) {
|
|
130
135
|
externalResourceEntity.customFields.items.forEach((customField) => {
|
|
131
|
-
|
|
136
|
+
const key = this.getNonConflictingFieldName(kdbxEntry, customField.key);
|
|
137
|
+
if (key !== customField.key) {
|
|
138
|
+
this.customFieldsConflicts.push({
|
|
139
|
+
resourceName: externalResourceEntity.name,
|
|
140
|
+
originalKey: customField.key,
|
|
141
|
+
newKey: key,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
kdbxEntry.fields.set(key, kdbxweb.ProtectedValue.fromString(customField.value));
|
|
132
145
|
});
|
|
133
146
|
}
|
|
134
147
|
}
|
|
135
148
|
|
|
149
|
+
/**
|
|
150
|
+
* Resolve a custom field key to a name that does not conflict with a reserved KeePass field or an already set field.
|
|
151
|
+
* A name conflicts when it is a reserved field or already present on the entry. The static reserved list is required
|
|
152
|
+
* because some reserved fields (e.g. "Notes") are set after the custom fields, while already set fields (including
|
|
153
|
+
* the multi-uri KP2A_URL fields, written before the custom fields) are caught by the entry lookup.
|
|
154
|
+
* @param {kdbxweb.KdbxEntry} kdbxEntry
|
|
155
|
+
* @param {string} key The custom field key
|
|
156
|
+
* @returns {string} The original key, or a numbered variant ("key (1)", "key (2)", ...) when it conflicts
|
|
157
|
+
*/
|
|
158
|
+
getNonConflictingFieldName(kdbxEntry, key) {
|
|
159
|
+
const isConflicting = (name) => KDBX_SUPPORTED_FIELDS.includes(name) || kdbxEntry.fields.has(name);
|
|
160
|
+
|
|
161
|
+
if (!isConflicting(key)) {
|
|
162
|
+
return key;
|
|
163
|
+
}
|
|
164
|
+
let index = 1;
|
|
165
|
+
let candidate = `${key} (${index})`;
|
|
166
|
+
while (isConflicting(candidate)) {
|
|
167
|
+
index++;
|
|
168
|
+
candidate = `${key} (${index})`;
|
|
169
|
+
}
|
|
170
|
+
return candidate;
|
|
171
|
+
}
|
|
172
|
+
|
|
136
173
|
/**
|
|
137
174
|
* Set the URL fields according to the kdbx format
|
|
138
175
|
* @param {kdbxweb.KdbxEntry} kdbxEntry
|
|
@@ -21,6 +21,7 @@ import fs from "fs";
|
|
|
21
21
|
import { defaultTotpDto } from "../../entity/totp/totpDto.test.data";
|
|
22
22
|
import { defaultIconDto } from "passbolt-styleguide/src/shared/models/entity/resource/metadata/iconEntity.test.data";
|
|
23
23
|
import { defaultCustomFieldsCollection } from "passbolt-styleguide/src/shared/models/entity/customField/customFieldsCollection.test.data";
|
|
24
|
+
import { defaultCustomField } from "passbolt-styleguide/src/shared/models/entity/customField/customFieldEntity.test.data";
|
|
24
25
|
|
|
25
26
|
global.kdbxweb = kdbxweb;
|
|
26
27
|
kdbxweb.CryptoEngine.argon2 = argon2;
|
|
@@ -398,4 +399,125 @@ describe("ResourcesKdbxExporter", () => {
|
|
|
398
399
|
const kdbxCredentials = new kdbxweb.Credentials(null, kdbxweb.ByteUtils.base64ToBytes(exportEntity.keyfile));
|
|
399
400
|
await kdbxweb.Kdbx.load(exportEntity.file, kdbxCredentials);
|
|
400
401
|
});
|
|
402
|
+
|
|
403
|
+
describe("custom field name conflicts", () => {
|
|
404
|
+
async function exportAndLoadFirstEntry(customFields, data = {}) {
|
|
405
|
+
const exportResource = buildImportResourceDto(1, {
|
|
406
|
+
name: "GitHub",
|
|
407
|
+
totp: undefined,
|
|
408
|
+
uris: [],
|
|
409
|
+
custom_fields: customFields,
|
|
410
|
+
...data,
|
|
411
|
+
});
|
|
412
|
+
const exportDto = { format: "kdbx", export_resources: [exportResource], export_folders: [] };
|
|
413
|
+
const exportEntity = new ExportResourcesFileEntity(exportDto);
|
|
414
|
+
const exporter = new ResourcesKdbxExporter(exportEntity);
|
|
415
|
+
const conflicts = await exporter.export();
|
|
416
|
+
const kdbxDb = await kdbxweb.Kdbx.load(exportEntity.file, new kdbxweb.Credentials(null, null));
|
|
417
|
+
return { entry: kdbxDb.groups[0].entries[0], conflicts };
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
it("should rename a custom field colliding with the reserved Password field and preserve the real password", async () => {
|
|
421
|
+
expect.assertions(3);
|
|
422
|
+
const { entry, conflicts } = await exportAndLoadFirstEntry([
|
|
423
|
+
defaultCustomField({ metadata_key: "Password", secret_value: "evil-password" }),
|
|
424
|
+
]);
|
|
425
|
+
|
|
426
|
+
expect(entry.fields.get("Password").getText()).toEqual("Secret 1");
|
|
427
|
+
expect(entry.fields.get("Password (1)").getText()).toEqual("evil-password");
|
|
428
|
+
expect(conflicts).toEqual([{ resourceName: "GitHub", originalKey: "Password", newKey: "Password (1)" }]);
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
it("should rename a custom field named Notes even though Notes is written after the custom fields", async () => {
|
|
432
|
+
expect.assertions(2);
|
|
433
|
+
const { entry } = await exportAndLoadFirstEntry(
|
|
434
|
+
[defaultCustomField({ metadata_key: "Notes", secret_value: "evil-notes" })],
|
|
435
|
+
{ description: "real description" },
|
|
436
|
+
);
|
|
437
|
+
|
|
438
|
+
expect(entry.fields.get("Notes")).toEqual("real description");
|
|
439
|
+
expect(entry.fields.get("Notes (1)").getText()).toEqual("evil-notes");
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
it("should number multiple custom fields colliding with the same reserved field", async () => {
|
|
443
|
+
expect.assertions(4);
|
|
444
|
+
const { entry, conflicts } = await exportAndLoadFirstEntry([
|
|
445
|
+
defaultCustomField({ metadata_key: "Password", secret_value: "v1" }),
|
|
446
|
+
defaultCustomField({ metadata_key: "Password", secret_value: "v2" }),
|
|
447
|
+
]);
|
|
448
|
+
|
|
449
|
+
expect(entry.fields.get("Password").getText()).toEqual("Secret 1");
|
|
450
|
+
expect(entry.fields.get("Password (1)").getText()).toEqual("v1");
|
|
451
|
+
expect(entry.fields.get("Password (2)").getText()).toEqual("v2");
|
|
452
|
+
expect(conflicts).toHaveLength(2);
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
it("should not lose data when a custom field is literally named like a renamed field", async () => {
|
|
456
|
+
expect.assertions(3);
|
|
457
|
+
const { entry } = await exportAndLoadFirstEntry([
|
|
458
|
+
defaultCustomField({ metadata_key: "Password", secret_value: "v1" }),
|
|
459
|
+
defaultCustomField({ metadata_key: "Password (1)", secret_value: "literal" }),
|
|
460
|
+
]);
|
|
461
|
+
|
|
462
|
+
expect(entry.fields.get("Password").getText()).toEqual("Secret 1");
|
|
463
|
+
expect(entry.fields.get("Password (1)").getText()).toEqual("v1");
|
|
464
|
+
expect(entry.fields.get("Password (1) (1)").getText()).toEqual("literal");
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
it("should rename a custom field colliding with the reserved Password field even when no real password is set", async () => {
|
|
468
|
+
expect.assertions(2);
|
|
469
|
+
const { entry } = await exportAndLoadFirstEntry(
|
|
470
|
+
[defaultCustomField({ metadata_key: "Password", secret_value: "value" })],
|
|
471
|
+
{ secret_clear: "" },
|
|
472
|
+
);
|
|
473
|
+
|
|
474
|
+
// The reserved Password slot keeps its default empty value rather than the custom value.
|
|
475
|
+
const passwordField = entry.fields.get("Password");
|
|
476
|
+
const passwordValue = typeof passwordField === "string" ? passwordField : passwordField?.getText();
|
|
477
|
+
expect(passwordValue).not.toEqual("value");
|
|
478
|
+
expect(entry.fields.get("Password (1)").getText()).toEqual("value");
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
it("should rename a custom field colliding with the multi-uri KP2A_URL field", async () => {
|
|
482
|
+
expect.assertions(2);
|
|
483
|
+
const { entry } = await exportAndLoadFirstEntry(
|
|
484
|
+
[defaultCustomField({ metadata_key: "KP2A_URL", secret_value: "custom-value" })],
|
|
485
|
+
{ uris: ["https://url.com", "https://alt.com"] },
|
|
486
|
+
);
|
|
487
|
+
|
|
488
|
+
expect(entry.fields.get("KP2A_URL")).toEqual("https://alt.com");
|
|
489
|
+
expect(entry.fields.get("KP2A_URL (1)").getText()).toEqual("custom-value");
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
it("should not rename custom fields that do not conflict and return no conflicts", async () => {
|
|
493
|
+
expect.assertions(3);
|
|
494
|
+
const { entry, conflicts } = await exportAndLoadFirstEntry([
|
|
495
|
+
defaultCustomField({ metadata_key: "Key 0", secret_value: "Value 0" }),
|
|
496
|
+
defaultCustomField({ metadata_key: "Key 1", secret_value: "Value 1" }),
|
|
497
|
+
]);
|
|
498
|
+
|
|
499
|
+
expect(entry.fields.get("Key 0").getText()).toEqual("Value 0");
|
|
500
|
+
expect(entry.fields.get("Key 1").getText()).toEqual("Value 1");
|
|
501
|
+
expect(conflicts).toEqual([]);
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
it("should rename a custom field colliding with the reserved otp field for other keepass", async () => {
|
|
505
|
+
expect.assertions(2);
|
|
506
|
+
const exportResource = buildImportResourceDto(1, {
|
|
507
|
+
name: "GitHub",
|
|
508
|
+
uris: [],
|
|
509
|
+
totp: defaultTotpDto(),
|
|
510
|
+
custom_fields: [defaultCustomField({ metadata_key: "otp", secret_value: "custom-otp" })],
|
|
511
|
+
});
|
|
512
|
+
const exportDto = { format: "kdbx-others", export_resources: [exportResource], export_folders: [] };
|
|
513
|
+
const exportEntity = new ExportResourcesFileEntity(exportDto);
|
|
514
|
+
const exporter = new ResourcesKdbxExporter(exportEntity);
|
|
515
|
+
await exporter.export();
|
|
516
|
+
const kdbxDb = await kdbxweb.Kdbx.load(exportEntity.file, new kdbxweb.Credentials(null, null));
|
|
517
|
+
const entry = kdbxDb.groups[0].entries[0];
|
|
518
|
+
|
|
519
|
+
expect(entry.fields.get("otp").getText()).toContain("otpauth://");
|
|
520
|
+
expect(entry.fields.get("otp (1)").getText()).toEqual("custom-otp");
|
|
521
|
+
});
|
|
522
|
+
});
|
|
401
523
|
});
|
|
@@ -21,7 +21,7 @@ import { CUSTOM_FIELD_TYPE } from "passbolt-styleguide/src/shared/models/entity/
|
|
|
21
21
|
import { v4 as uuidv4 } from "uuid";
|
|
22
22
|
import { RESOURCE_TYPE_VERSION_5 } from "passbolt-styleguide/src/shared/models/entity/metadata/metadataTypesSettingsEntity";
|
|
23
23
|
|
|
24
|
-
const KDBX_SUPPORTED_FIELDS = [
|
|
24
|
+
export const KDBX_SUPPORTED_FIELDS = [
|
|
25
25
|
"Title",
|
|
26
26
|
"URL",
|
|
27
27
|
"UserName",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* @link https://www.passbolt.com Passbolt(tm)
|
|
12
12
|
* @since 3.2.0
|
|
13
13
|
*/
|
|
14
|
-
import
|
|
14
|
+
import GetOrFindSiteSettingsService from "../../service/siteSettings/getOrFindSiteSettingsService";
|
|
15
15
|
import AccountSettingsService from "../../service/api/accountSettings/accountSettingsService";
|
|
16
16
|
import { Config } from "../config";
|
|
17
17
|
import i18n from "../../sdk/i18n";
|
|
@@ -42,11 +42,14 @@ class LocaleModel {
|
|
|
42
42
|
* Constructor
|
|
43
43
|
*
|
|
44
44
|
* @param {ApiClientOptions} apiClientOptions
|
|
45
|
+
* @param {AccountEntity} [account] The account. Required for the organization-locale finders that
|
|
46
|
+
* read the site settings; not needed by `updateUserLocale`.
|
|
45
47
|
* @public
|
|
46
48
|
*/
|
|
47
|
-
constructor(apiClientOptions) {
|
|
49
|
+
constructor(apiClientOptions, account) {
|
|
48
50
|
this.accountSettingsService = new AccountSettingsService(apiClientOptions);
|
|
49
|
-
this.
|
|
51
|
+
this.apiClientOptions = apiClientOptions;
|
|
52
|
+
this.account = account;
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
/**
|
|
@@ -71,8 +74,9 @@ class LocaleModel {
|
|
|
71
74
|
* @returns {Promise<LocaleEntity>}
|
|
72
75
|
*/
|
|
73
76
|
async getOrganizationLocale() {
|
|
74
|
-
const
|
|
75
|
-
|
|
77
|
+
const getOrFindSiteSettingsService = new GetOrFindSiteSettingsService(this.account, this.apiClientOptions);
|
|
78
|
+
const siteSettings = await getOrFindSiteSettingsService.getOrFind(false);
|
|
79
|
+
return this.getSupportedLocale(siteSettings.locale);
|
|
76
80
|
}
|
|
77
81
|
|
|
78
82
|
/**
|
|
@@ -80,11 +84,12 @@ class LocaleModel {
|
|
|
80
84
|
* @returns {Promise<LocalesCollection>}
|
|
81
85
|
*/
|
|
82
86
|
async getSupportedOrganizationLocales() {
|
|
83
|
-
const
|
|
84
|
-
const
|
|
87
|
+
const getOrFindSiteSettingsService = new GetOrFindSiteSettingsService(this.account, this.apiClientOptions);
|
|
88
|
+
const siteSettings = await getOrFindSiteSettingsService.getOrFind(false);
|
|
89
|
+
const localePluginEnabled = siteSettings.isPluginEnabled("locale");
|
|
85
90
|
|
|
86
91
|
if (localePluginEnabled) {
|
|
87
|
-
const localePluginSettings =
|
|
92
|
+
const localePluginSettings = siteSettings.getPluginSettings("locale");
|
|
88
93
|
return new LocalesCollection(localePluginSettings.options || []);
|
|
89
94
|
}
|
|
90
95
|
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
import PasswordExpirySettingsService from "../../service/api/passwordExpiry/passwordExpirySettingsService";
|
|
16
16
|
import { assertType, assertUuid } from "../../utils/assertions";
|
|
17
17
|
import PasswordExpirySettingsEntity from "passbolt-styleguide/src/shared/models/entity/passwordExpiry/passwordExpirySettingsEntity";
|
|
18
|
-
import
|
|
18
|
+
import GetOrFindSiteSettingsService from "../../service/siteSettings/getOrFindSiteSettingsService";
|
|
19
19
|
import PasswordExpiryProSettingsEntity from "passbolt-styleguide/src/shared/models/entity/passwordExpiryPro/passwordExpiryProSettingsEntity";
|
|
20
20
|
import PasswordExpirySettingsLocalStorage from "../../service/local_storage/passwordExpirySettingsLocalStorage";
|
|
21
21
|
|
|
@@ -30,7 +30,7 @@ class PasswordExpirySettingsModel {
|
|
|
30
30
|
constructor(account, apiClientOptions) {
|
|
31
31
|
this.passwordExpirySettingsLocalStorage = new PasswordExpirySettingsLocalStorage(account);
|
|
32
32
|
this.passwordExpirySettingsService = new PasswordExpirySettingsService(apiClientOptions);
|
|
33
|
-
this.
|
|
33
|
+
this.getOrFindSiteSettingsService = new GetOrFindSiteSettingsService(account, apiClientOptions);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
/**
|
|
@@ -68,8 +68,8 @@ class PasswordExpirySettingsModel {
|
|
|
68
68
|
* @returns {Promise<PasswordExpirySettingsEntity>}
|
|
69
69
|
*/
|
|
70
70
|
async save(passwordExpirySettingsEntity) {
|
|
71
|
-
const
|
|
72
|
-
const isAdvancedSettingsEnable =
|
|
71
|
+
const siteSettings = await this.getOrFindSiteSettingsService.getOrFind(false);
|
|
72
|
+
const isAdvancedSettingsEnable = siteSettings.isPluginEnabled("passwordExpiryPolicies");
|
|
73
73
|
if (!isAdvancedSettingsEnable) {
|
|
74
74
|
assertType(
|
|
75
75
|
passwordExpirySettingsEntity,
|
|
@@ -106,8 +106,8 @@ class PasswordExpirySettingsModel {
|
|
|
106
106
|
* @returns {Promise<PasswordExpirySettingsEntity|PasswordExpiryProSettingsEntity>}
|
|
107
107
|
*/
|
|
108
108
|
async createFromDefault(passwordExpirySettingsDto = {}) {
|
|
109
|
-
const
|
|
110
|
-
const isAdvancedSettingsEnabled =
|
|
109
|
+
const siteSettings = await this.getOrFindSiteSettingsService.getOrFind(false);
|
|
110
|
+
const isAdvancedSettingsEnabled = siteSettings.isPluginEnabled("passwordExpiryPolicies");
|
|
111
111
|
if (!isAdvancedSettingsEnabled) {
|
|
112
112
|
return PasswordExpirySettingsEntity.createFromDefault(passwordExpirySettingsDto);
|
|
113
113
|
}
|