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
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Passbolt ~ Open source password manager for teams
|
|
3
|
+
* Copyright (c) Passbolt SA (https://www.passbolt.com)
|
|
4
|
+
*
|
|
5
|
+
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
|
6
|
+
* For full copyright and license information, please see the LICENSE.txt
|
|
7
|
+
* Redistributions of files must retain the above copyright notice.
|
|
8
|
+
*
|
|
9
|
+
* @copyright Copyright (c) Passbolt SA (https://www.passbolt.com)
|
|
10
|
+
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
|
11
|
+
* @link https://www.passbolt.com Passbolt(tm)
|
|
12
|
+
* @since 6.0.0
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import AccountEntity from "../../model/entity/account/accountEntity";
|
|
16
|
+
import { defaultAccountDto } from "../../model/entity/account/accountEntity.test.data";
|
|
17
|
+
import { TestEntityLocalStorage, TestLocalStorage } from "./abstractLocalStorage.test.data";
|
|
18
|
+
import { v4 as uuidv4 } from "uuid";
|
|
19
|
+
import LocalStorageMetadataEntity from "../../model/entity/localStorage/localStorageMetadataEntity";
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
jest.clearAllMocks();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe("AbstractLocalStorage", () => {
|
|
26
|
+
let account, storage;
|
|
27
|
+
beforeEach(() => {
|
|
28
|
+
account = new AccountEntity(defaultAccountDto());
|
|
29
|
+
storage = new TestLocalStorage(account);
|
|
30
|
+
// flush account related storage before each.
|
|
31
|
+
storage.flush();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe("::constructor", () => {
|
|
35
|
+
it("throws an error if no account is provided.", () => {
|
|
36
|
+
expect.assertions(1);
|
|
37
|
+
expect(() => new TestLocalStorage()).toThrow(TypeError);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("throws an error if parameter account is not a valid AccountEntity.", () => {
|
|
41
|
+
expect.assertions(1);
|
|
42
|
+
expect(() => new TestLocalStorage({})).toThrow(TypeError);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
describe("::getMetadata", () => {
|
|
47
|
+
it("returns undefined if nothing is stored in the local storage.", async () => {
|
|
48
|
+
expect.assertions(1);
|
|
49
|
+
const result = await storage.getMetadata();
|
|
50
|
+
expect(result).toBeUndefined();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("returns content stored in the local storage.", async () => {
|
|
54
|
+
const dto = {
|
|
55
|
+
last_updated: new Date().toISOString(),
|
|
56
|
+
};
|
|
57
|
+
expect.assertions(1);
|
|
58
|
+
browser.storage.local.set({ [storage.storageMetadataKey]: dto });
|
|
59
|
+
const result = await storage.getMetadata();
|
|
60
|
+
expect(result).toEqual(dto);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("returns content stored in the runtime cache.", async () => {
|
|
64
|
+
const dto = {
|
|
65
|
+
last_updated: new Date().toISOString(),
|
|
66
|
+
};
|
|
67
|
+
expect.assertions(2);
|
|
68
|
+
// Force the runtime cache, to ensure it is hit even if the local storage is empty.
|
|
69
|
+
TestLocalStorage._runtimeCachedMetadata[storage.storageMetadataKey] = dto;
|
|
70
|
+
const result = await storage.getMetadata();
|
|
71
|
+
expect(result).toEqual(dto);
|
|
72
|
+
// Control the local storage was well empty.
|
|
73
|
+
expect(browser.storage.local.store[storage.storageMetadataKey]).toBeUndefined();
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
describe("::getData", () => {
|
|
78
|
+
it("returns undefined if nothing is stored in the local storage.", async () => {
|
|
79
|
+
expect.assertions(1);
|
|
80
|
+
const result = await storage.getData();
|
|
81
|
+
expect(result).toBeUndefined();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("returns content stored in the local storage.", async () => {
|
|
85
|
+
const dto = {
|
|
86
|
+
id: uuidv4(),
|
|
87
|
+
name: "test",
|
|
88
|
+
};
|
|
89
|
+
expect.assertions(1);
|
|
90
|
+
browser.storage.local.set({ [storage.storageDataKey]: dto });
|
|
91
|
+
const result = await storage.getData();
|
|
92
|
+
expect(result).toEqual(dto);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("returns content stored in the runtime cache.", async () => {
|
|
96
|
+
const dto = {
|
|
97
|
+
id: uuidv4(),
|
|
98
|
+
name: "test",
|
|
99
|
+
};
|
|
100
|
+
expect.assertions(2);
|
|
101
|
+
// Force the runtime cache, to ensure it is hit even if the local storage is empty.
|
|
102
|
+
TestLocalStorage._runtimeCachedData[storage.storageDataKey] = dto;
|
|
103
|
+
const result = await storage.getData();
|
|
104
|
+
expect(result).toEqual(dto);
|
|
105
|
+
// Control the local storage was well empty.
|
|
106
|
+
expect(browser.storage.local.store[storage.storageDataKey]).toBeUndefined();
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
describe("::setMetadata", () => {
|
|
111
|
+
it("stores content in the local storage.", async () => {
|
|
112
|
+
expect.assertions(3);
|
|
113
|
+
const dto = {
|
|
114
|
+
last_updated: new Date().toISOString(),
|
|
115
|
+
};
|
|
116
|
+
const entity = new LocalStorageMetadataEntity(dto);
|
|
117
|
+
await storage.setMetadata(entity);
|
|
118
|
+
// Expect the local storage (mocked here) to be set.
|
|
119
|
+
expect(browser.storage.local.store[storage.storageMetadataKey]).toEqual(dto);
|
|
120
|
+
// Expect the runtime cache to be set.
|
|
121
|
+
expect(TestLocalStorage._runtimeCachedMetadata[storage.storageMetadataKey]).toEqual(dto);
|
|
122
|
+
// Expect the get to retrieve the set metadata.
|
|
123
|
+
const resultGetMetadata = await storage.getMetadata();
|
|
124
|
+
expect(resultGetMetadata).toEqual(dto);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("throws if no metadata is given to store.", async () => {
|
|
128
|
+
expect.assertions(3);
|
|
129
|
+
await expect(() => storage.setMetadata()).rejects.toThrow(TypeError);
|
|
130
|
+
// Expect the local storage (mocked here) to not be set.
|
|
131
|
+
expect(browser.storage.local.store[storage.storageMetadataKey]).toBeUndefined();
|
|
132
|
+
// Expect the runtime cache to not be set.
|
|
133
|
+
expect(TestLocalStorage._runtimeCachedMetadata[storage.storageMetadataKey]).toBeUndefined();
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it("throws if invalid metadata is given to store.", async () => {
|
|
137
|
+
expect.assertions(3);
|
|
138
|
+
await expect(() => storage.setMetadata({})).rejects.toThrow(TypeError);
|
|
139
|
+
// Expect the local storage (mocked here) to not be set.
|
|
140
|
+
expect(browser.storage.local.store[storage.storageMetadataKey]).toBeUndefined();
|
|
141
|
+
// Expect the runtime cache to not be set.
|
|
142
|
+
expect(TestLocalStorage._runtimeCachedMetadata[storage.storageMetadataKey]).toBeUndefined();
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("waits any on-going call to set to perform another set.", async () => {
|
|
146
|
+
expect.assertions(3);
|
|
147
|
+
const promisesResolvers = [];
|
|
148
|
+
|
|
149
|
+
jest.spyOn(storage, "_setBrowserStorage").mockImplementation(() => {
|
|
150
|
+
let resolve;
|
|
151
|
+
const promise = new Promise((_resolve) => (resolve = _resolve));
|
|
152
|
+
promisesResolvers.push(resolve);
|
|
153
|
+
return promise;
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
const dto1 = {
|
|
157
|
+
last_updated: new Date().toISOString(),
|
|
158
|
+
};
|
|
159
|
+
const resultPromise1 = storage.setMetadata(new LocalStorageMetadataEntity(dto1));
|
|
160
|
+
const dto2 = {
|
|
161
|
+
last_updated: "2026-05-04T20:31:45+00:00",
|
|
162
|
+
};
|
|
163
|
+
const resultPromise2 = storage.setMetadata(new LocalStorageMetadataEntity(dto2));
|
|
164
|
+
expect(storage._setBrowserStorage).toHaveBeenCalledWith({ [storage.storageMetadataKey]: dto1 });
|
|
165
|
+
expect(storage._setBrowserStorage).not.toHaveBeenCalledWith({ [storage.storageMetadataKey]: dto2 });
|
|
166
|
+
promisesResolvers[0]();
|
|
167
|
+
await resultPromise1;
|
|
168
|
+
expect(storage._setBrowserStorage).toHaveBeenCalledWith({ [storage.storageMetadataKey]: dto2 });
|
|
169
|
+
promisesResolvers[1]();
|
|
170
|
+
await resultPromise2;
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
describe("::setData", () => {
|
|
175
|
+
it("stores content in the local storage.", async () => {
|
|
176
|
+
expect.assertions(4);
|
|
177
|
+
const dto = {
|
|
178
|
+
id: uuidv4(),
|
|
179
|
+
name: "test",
|
|
180
|
+
};
|
|
181
|
+
const entity = new TestEntityLocalStorage(dto);
|
|
182
|
+
await storage.setData(entity);
|
|
183
|
+
// Expect the local storage (mocked here) to be set.
|
|
184
|
+
expect(browser.storage.local.store[storage.storageDataKey]).toEqual(dto);
|
|
185
|
+
// Expect the runtime cache to be set.
|
|
186
|
+
expect(TestLocalStorage._runtimeCachedData[storage.storageDataKey]).toEqual(dto);
|
|
187
|
+
// Expect the get to retrieve the set data.
|
|
188
|
+
const resultGet = await storage.getData();
|
|
189
|
+
const resultGetMetadata = await storage.getMetadata();
|
|
190
|
+
expect(resultGet).toEqual(dto);
|
|
191
|
+
expect(resultGetMetadata.last_updated.slice(0, 10)).toEqual(new Date().toISOString().slice(0, 10));
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it("throws if no data is given to store.", async () => {
|
|
195
|
+
expect.assertions(3);
|
|
196
|
+
await expect(() => storage.setData()).rejects.toThrow(TypeError);
|
|
197
|
+
// Expect the local storage (mocked here) to not be set.
|
|
198
|
+
expect(browser.storage.local.store[storage.storageDataKey]).toBeUndefined();
|
|
199
|
+
// Expect the runtime cache to not be set.
|
|
200
|
+
expect(TestLocalStorage._runtimeCachedData[storage.storageDataKey]).toBeUndefined();
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it("throws if invalid data is given to store.", async () => {
|
|
204
|
+
expect.assertions(3);
|
|
205
|
+
await expect(() => storage.setData({})).rejects.toThrow(TypeError);
|
|
206
|
+
// Expect the local storage (mocked here) to not be set.
|
|
207
|
+
expect(browser.storage.local.store[storage.storageDataKey]).toBeUndefined();
|
|
208
|
+
// Expect the runtime cache to not be set.
|
|
209
|
+
expect(TestLocalStorage._runtimeCachedData[storage.storageDataKey]).toBeUndefined();
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it("waits any on-going call to set to perform another set.", async () => {
|
|
213
|
+
expect.assertions(3);
|
|
214
|
+
const promisesResolvers = [];
|
|
215
|
+
|
|
216
|
+
jest.spyOn(storage, "_setBrowserStorage").mockImplementation(() => {
|
|
217
|
+
let resolve;
|
|
218
|
+
const promise = new Promise((_resolve) => (resolve = _resolve));
|
|
219
|
+
promisesResolvers.push(resolve);
|
|
220
|
+
return promise;
|
|
221
|
+
});
|
|
222
|
+
jest.spyOn(storage, "setMetadata").mockImplementation(() => {});
|
|
223
|
+
|
|
224
|
+
const dto1 = {
|
|
225
|
+
id: uuidv4(),
|
|
226
|
+
name: "test",
|
|
227
|
+
};
|
|
228
|
+
const resultPromise1 = storage.setData(new TestEntityLocalStorage(dto1));
|
|
229
|
+
const dto2 = {
|
|
230
|
+
id: uuidv4(),
|
|
231
|
+
name: "test2",
|
|
232
|
+
};
|
|
233
|
+
const resultPromise2 = storage.setData(new TestEntityLocalStorage(dto2));
|
|
234
|
+
expect(storage._setBrowserStorage).toHaveBeenCalledWith({ [storage.storageDataKey]: dto1 });
|
|
235
|
+
expect(storage._setBrowserStorage).not.toHaveBeenCalledWith({ [storage.storageDataKey]: dto2 });
|
|
236
|
+
promisesResolvers[0]();
|
|
237
|
+
await resultPromise1;
|
|
238
|
+
expect(storage._setBrowserStorage).toHaveBeenCalledWith({ [storage.storageDataKey]: dto2 });
|
|
239
|
+
promisesResolvers[1]();
|
|
240
|
+
await resultPromise2;
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
describe("::flush", () => {
|
|
245
|
+
it("flushes works with not initialized local storage.", async () => {
|
|
246
|
+
expect.assertions(3);
|
|
247
|
+
await storage.flush();
|
|
248
|
+
// Expect the local storage (mocked here) to not be set.
|
|
249
|
+
expect(browser.storage.local.store[storage.storageDataKey]).toBeUndefined();
|
|
250
|
+
// Expect the runtime cache to not be set.
|
|
251
|
+
expect(TestLocalStorage._runtimeCachedData[storage.storageDataKey]).toBeUndefined();
|
|
252
|
+
expect(TestLocalStorage._runtimeCachedMetadata[storage.storageMetadataKey]).toBeUndefined();
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it("flushes content of the local storage.", async () => {
|
|
256
|
+
expect.assertions(3);
|
|
257
|
+
const dto = {
|
|
258
|
+
id: uuidv4(),
|
|
259
|
+
name: "test",
|
|
260
|
+
};
|
|
261
|
+
const entity = new TestEntityLocalStorage(dto);
|
|
262
|
+
await storage.setData(entity);
|
|
263
|
+
await storage.flush();
|
|
264
|
+
// Expect the local storage (mocked here) to not be set.
|
|
265
|
+
expect(browser.storage.local.store[storage.storageDataKey]).toBeUndefined();
|
|
266
|
+
// Expect the runtime cache to not be set.
|
|
267
|
+
expect(TestLocalStorage._runtimeCachedData[storage.storageDataKey]).toBeUndefined();
|
|
268
|
+
expect(TestLocalStorage._runtimeCachedMetadata[storage.storageMetadataKey]).toBeUndefined();
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
});
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Passbolt ~ Open source password manager for teams
|
|
3
|
+
* Copyright (c) Passbolt SA (https://www.passbolt.com)
|
|
4
|
+
*
|
|
5
|
+
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
|
6
|
+
* For full copyright and license information, please see the LICENSE.txt
|
|
7
|
+
* Redistributions of files must retain the above copyright notice.
|
|
8
|
+
*
|
|
9
|
+
* @copyright Copyright (c) Passbolt SA (https://www.passbolt.com)
|
|
10
|
+
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
|
11
|
+
* @link https://www.passbolt.com Passbolt(tm)
|
|
12
|
+
* @since 6.0.0
|
|
13
|
+
*/
|
|
14
|
+
import OnlineSessionEntity from "passbolt-styleguide/src/shared/models/entity/session/onlineSessionEntity";
|
|
15
|
+
import Log from "../../model/log";
|
|
16
|
+
import { assertType } from "../../utils/assertions";
|
|
17
|
+
import AbstractAccountEntity from "../../model/entity/account/abstractAccountEntity";
|
|
18
|
+
|
|
19
|
+
export const ACTIVE_SESSION_LOCAL_STORAGE_KEY = "active_session";
|
|
20
|
+
|
|
21
|
+
class ActiveSessionLocalStorage {
|
|
22
|
+
/**
|
|
23
|
+
* Runtime cached data.
|
|
24
|
+
* @type {Object} Key: account_id, value: cached data as dto.
|
|
25
|
+
* @private
|
|
26
|
+
*/
|
|
27
|
+
static _runtimeCachedData = {};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Constructor
|
|
31
|
+
* @param account the user account
|
|
32
|
+
*/
|
|
33
|
+
constructor(account) {
|
|
34
|
+
if (!account || !(account instanceof AbstractAccountEntity)) {
|
|
35
|
+
throw new TypeError("Parameter `account` should be of type AbstractAccountEntity.");
|
|
36
|
+
}
|
|
37
|
+
this.account = account;
|
|
38
|
+
this.storageKey = this.getStorageKey(account);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Get the storage key.
|
|
43
|
+
* @param {AbstractAccountEntity} account The account to get the key for.
|
|
44
|
+
* @returns {string}
|
|
45
|
+
* @throws {Error} If it cannot retrieve account id.
|
|
46
|
+
*/
|
|
47
|
+
getStorageKey(account) {
|
|
48
|
+
return `${ACTIVE_SESSION_LOCAL_STORAGE_KEY}-${account.id}`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Flush the active session from local storage and runtime cached data.
|
|
53
|
+
* @return {Promise<void>}
|
|
54
|
+
*/
|
|
55
|
+
async flush() {
|
|
56
|
+
await browser.storage.local.remove(this.storageKey);
|
|
57
|
+
delete ActiveSessionLocalStorage._runtimeCachedData[this.account.id];
|
|
58
|
+
Log.write({ level: "debug", message: `ActiveSessionLocalStorage flushed for (${this.account.id})` });
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Get the active session from the local storage.
|
|
63
|
+
* @return {Promise<object|undefined>}
|
|
64
|
+
*/
|
|
65
|
+
async get() {
|
|
66
|
+
if (!ActiveSessionLocalStorage._runtimeCachedData[this.account.id]) {
|
|
67
|
+
const data = await browser.storage.local.get([this.storageKey]);
|
|
68
|
+
if (!data[this.storageKey]) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
ActiveSessionLocalStorage._runtimeCachedData[this.account.id] = data[this.storageKey];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return ActiveSessionLocalStorage._runtimeCachedData[this.account.id];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Set the active session in the local storage.
|
|
79
|
+
* @param {OnlineSessionEntity} activeSession The active session to insert in the local storage.
|
|
80
|
+
* @return {Promise<void>}
|
|
81
|
+
* @throws {TypeError} If parameter settings is not of type OnlineSessionEntity.
|
|
82
|
+
*/
|
|
83
|
+
async set(activeSession) {
|
|
84
|
+
assertType(activeSession, OnlineSessionEntity, "Parameter `activeSession` should be of type OnlineSessionEntity");
|
|
85
|
+
await navigator.locks.request(this.storageKey, async () => {
|
|
86
|
+
const activeSessionDto = activeSession.toDto();
|
|
87
|
+
await this._setBrowserStorage({ [this.storageKey]: activeSessionDto });
|
|
88
|
+
ActiveSessionLocalStorage._runtimeCachedData[this.account.id] = activeSessionDto;
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Set the browser storage.
|
|
94
|
+
* @todo Tool to test the semaphore. A dedicated local storage service could be implemented later on top
|
|
95
|
+
* of the browser provided one to ease the testing.
|
|
96
|
+
* @param {object} data The data to store in the local storage.
|
|
97
|
+
* @returns {Promise<void>}
|
|
98
|
+
* @private
|
|
99
|
+
*/
|
|
100
|
+
async _setBrowserStorage(data) {
|
|
101
|
+
await browser.storage.local.set(data);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export default ActiveSessionLocalStorage;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Passbolt ~ Open source password manager for teams
|
|
3
|
+
* Copyright (c) Passbolt SA (https://www.passbolt.com)
|
|
4
|
+
*
|
|
5
|
+
* Licensed under GNU Affero General Public License version 3 of the or any later version.
|
|
6
|
+
* For full copyright and license information, please see the LICENSE.txt
|
|
7
|
+
* Redistributions of files must retain the above copyright notice.
|
|
8
|
+
*
|
|
9
|
+
* @copyright Copyright (c) Passbolt SA (https://www.passbolt.com)
|
|
10
|
+
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
|
|
11
|
+
* @link https://www.passbolt.com Passbolt(tm)
|
|
12
|
+
* @since 6.0.0
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import AccountEntity from "../../model/entity/account/accountEntity";
|
|
16
|
+
import { defaultAccountDto } from "../../model/entity/account/accountEntity.test.data";
|
|
17
|
+
import { defaultOnlineSessionDto } from "passbolt-styleguide/src/shared/models/entity/session/onlineSessionEntity.test.data";
|
|
18
|
+
import ActiveSessionLocalStorage from "./activeSessionLocalStorage";
|
|
19
|
+
import OnlineSessionEntity from "passbolt-styleguide/src/shared/models/entity/session/onlineSessionEntity";
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
jest.clearAllMocks();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe("ActiveSessionLocalStorage", () => {
|
|
26
|
+
let account, storage;
|
|
27
|
+
beforeEach(() => {
|
|
28
|
+
account = new AccountEntity(defaultAccountDto());
|
|
29
|
+
storage = new ActiveSessionLocalStorage(account);
|
|
30
|
+
// flush account related storage before each.
|
|
31
|
+
storage.flush();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe("::constructor", () => {
|
|
35
|
+
it("throws an error if no account is provided.", () => {
|
|
36
|
+
expect.assertions(1);
|
|
37
|
+
expect(() => new ActiveSessionLocalStorage()).toThrow(TypeError);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("throws an error if parameter account is not a valid AccountEntity.", () => {
|
|
41
|
+
expect.assertions(1);
|
|
42
|
+
expect(() => new ActiveSessionLocalStorage({})).toThrow(TypeError);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
describe("::get", () => {
|
|
47
|
+
it("returns undefined if nothing is stored in the local storage.", async () => {
|
|
48
|
+
expect.assertions(1);
|
|
49
|
+
const result = await storage.get();
|
|
50
|
+
expect(result).toBeUndefined();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("returns content stored in the local storage.", async () => {
|
|
54
|
+
const activeSessionDto = defaultOnlineSessionDto();
|
|
55
|
+
expect.assertions(1);
|
|
56
|
+
browser.storage.local.set({ [storage.storageKey]: activeSessionDto });
|
|
57
|
+
const result = await storage.get();
|
|
58
|
+
expect(result).toEqual(activeSessionDto);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("returns content stored in the runtime cache.", async () => {
|
|
62
|
+
const activeSessionDto = defaultOnlineSessionDto();
|
|
63
|
+
expect.assertions(2);
|
|
64
|
+
// Force the runtime cache, to ensure it is hit even if the local storage is empty.
|
|
65
|
+
ActiveSessionLocalStorage._runtimeCachedData[account.id] = activeSessionDto;
|
|
66
|
+
const result = await storage.get();
|
|
67
|
+
expect(result).toEqual(activeSessionDto);
|
|
68
|
+
// Control the local storage was well empty.
|
|
69
|
+
expect(browser.storage.local.store[storage.storageKey]).toBeUndefined();
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe("::set", () => {
|
|
74
|
+
it("stores content in the local storage.", async () => {
|
|
75
|
+
expect.assertions(3);
|
|
76
|
+
const activeSessionDto = new OnlineSessionEntity(defaultOnlineSessionDto());
|
|
77
|
+
await storage.set(activeSessionDto);
|
|
78
|
+
// Expect the local storage (mocked here) to be set.
|
|
79
|
+
expect(browser.storage.local.store[storage.storageKey]).toEqual(activeSessionDto.toDto());
|
|
80
|
+
// Expect the runtime cache to be set.
|
|
81
|
+
expect(ActiveSessionLocalStorage._runtimeCachedData[account.id]).toEqual(activeSessionDto.toDto());
|
|
82
|
+
// Expect the get to retrieve the set data.
|
|
83
|
+
const resultGet = await storage.get();
|
|
84
|
+
expect(resultGet).toEqual(activeSessionDto.toDto());
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("throws if no data is given to store.", async () => {
|
|
88
|
+
expect.assertions(3);
|
|
89
|
+
await expect(() => storage.set()).rejects.toThrow(TypeError);
|
|
90
|
+
// Expect the local storage (mocked here) to not be set.
|
|
91
|
+
expect(browser.storage.local.store[storage.storageKey]).toBeUndefined();
|
|
92
|
+
// Expect the runtime cache to not be set.
|
|
93
|
+
expect(ActiveSessionLocalStorage._runtimeCachedData[account.id]).toBeUndefined();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("throws if invalid data is given to store.", async () => {
|
|
97
|
+
expect.assertions(3);
|
|
98
|
+
await expect(() => storage.set({})).rejects.toThrow(TypeError);
|
|
99
|
+
// Expect the local storage (mocked here) to not be set.
|
|
100
|
+
expect(browser.storage.local.store[storage.storageKey]).toBeUndefined();
|
|
101
|
+
// Expect the runtime cache to not be set.
|
|
102
|
+
expect(ActiveSessionLocalStorage._runtimeCachedData[account.id]).toBeUndefined();
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it("waits any on-going call to set to perform another set.", async () => {
|
|
106
|
+
expect.assertions(3);
|
|
107
|
+
const promisesResolvers = [];
|
|
108
|
+
|
|
109
|
+
jest.spyOn(storage, "_setBrowserStorage").mockImplementation(() => {
|
|
110
|
+
let resolve;
|
|
111
|
+
const promise = new Promise((_resolve) => (resolve = _resolve));
|
|
112
|
+
promisesResolvers.push(resolve);
|
|
113
|
+
return promise;
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const resultPromise1 = storage.set(new OnlineSessionEntity(defaultOnlineSessionDto()));
|
|
117
|
+
const onlineSessionUpdated = defaultOnlineSessionDto({
|
|
118
|
+
is_mfa_authenticated: false,
|
|
119
|
+
last_online_logged_in: "2022-05-05T12:41:45.000Z",
|
|
120
|
+
});
|
|
121
|
+
const resultPromise2 = storage.set(new OnlineSessionEntity(onlineSessionUpdated));
|
|
122
|
+
expect(storage._setBrowserStorage).toHaveBeenCalledWith({ [storage.storageKey]: defaultOnlineSessionDto() });
|
|
123
|
+
expect(storage._setBrowserStorage).not.toHaveBeenCalledWith({ [storage.storageKey]: onlineSessionUpdated });
|
|
124
|
+
promisesResolvers[0]();
|
|
125
|
+
await resultPromise1;
|
|
126
|
+
expect(storage._setBrowserStorage).toHaveBeenCalledWith({ [storage.storageKey]: onlineSessionUpdated });
|
|
127
|
+
promisesResolvers[1]();
|
|
128
|
+
await resultPromise2;
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
describe("::flush", () => {
|
|
133
|
+
it("flushes works with not initialized local storage.", async () => {
|
|
134
|
+
expect.assertions(2);
|
|
135
|
+
await storage.flush();
|
|
136
|
+
// Expect the local storage (mocked here) to not be set.
|
|
137
|
+
expect(browser.storage.local.store[storage.storageKey]).toBeUndefined();
|
|
138
|
+
// Expect the runtime cache to not be set.
|
|
139
|
+
expect(ActiveSessionLocalStorage._runtimeCachedData[account.id]).toBeUndefined();
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it("flushes content of the local storage.", async () => {
|
|
143
|
+
expect.assertions(2);
|
|
144
|
+
const activeSessionDto = new OnlineSessionEntity(defaultOnlineSessionDto());
|
|
145
|
+
await storage.set(activeSessionDto);
|
|
146
|
+
await storage.flush();
|
|
147
|
+
// Expect the local storage (mocked here) to not be set.
|
|
148
|
+
expect(browser.storage.local.store[storage.storageKey]).toBeUndefined();
|
|
149
|
+
// Expect the runtime cache to not be set.
|
|
150
|
+
expect(ActiveSessionLocalStorage._runtimeCachedData[account.id]).toBeUndefined();
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
});
|
|
@@ -11,98 +11,26 @@
|
|
|
11
11
|
* @link https://www.passbolt.com Passbolt(tm)
|
|
12
12
|
* @since 4.1.0
|
|
13
13
|
*/
|
|
14
|
-
import Log from "../../model/log";
|
|
15
|
-
import RbacEntity from "passbolt-styleguide/src/shared/models/entity/rbac/rbacEntity";
|
|
16
14
|
import RbacsCollection from "passbolt-styleguide/src/shared/models/entity/rbac/rbacsCollection";
|
|
15
|
+
import AbstractLocalStorage from "./abstractLocalStorage";
|
|
17
16
|
|
|
18
17
|
export const RBACS_LOCAL_STORAGE_KEY = "rbac";
|
|
19
18
|
|
|
20
|
-
class RbacsLocalStorage {
|
|
19
|
+
class RbacsLocalStorage extends AbstractLocalStorage {
|
|
21
20
|
/**
|
|
22
|
-
*
|
|
23
|
-
* @
|
|
21
|
+
* Get the key property
|
|
22
|
+
* @return {string}
|
|
24
23
|
*/
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
get key() {
|
|
25
|
+
return RBACS_LOCAL_STORAGE_KEY;
|
|
27
26
|
}
|
|
28
27
|
|
|
29
28
|
/**
|
|
30
|
-
* Get the
|
|
31
|
-
* @
|
|
32
|
-
* @returns {string}
|
|
33
|
-
* @throws {Error} If it cannot retrieve account id.
|
|
29
|
+
* Get the entity class
|
|
30
|
+
* @return {RbacsCollection}
|
|
34
31
|
*/
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
throw new Error("Cannot retrieve account id, necessary to get a rbac storage key.");
|
|
38
|
-
}
|
|
39
|
-
return `${RBACS_LOCAL_STORAGE_KEY}-${account.id}`;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Flush the rbacs local storage
|
|
44
|
-
* @throws {Error} if operation failed
|
|
45
|
-
* @return {Promise<void>}
|
|
46
|
-
*/
|
|
47
|
-
async flush() {
|
|
48
|
-
Log.write({ level: "debug", message: "RbacLocalStorage flushed" });
|
|
49
|
-
return await browser.storage.local.remove(this.storageKey);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Get the rbacs local storage.
|
|
54
|
-
* @throws {Error} if operation failed
|
|
55
|
-
* @return {Promise<array|undefined>} results object, containing every object in keys that was found in the storage area.
|
|
56
|
-
* If storage is not set, undefined will be returned.
|
|
57
|
-
*/
|
|
58
|
-
async get() {
|
|
59
|
-
const data = await browser.storage.local.get([this.storageKey]);
|
|
60
|
-
return data[this.storageKey];
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Set the rbacs in local storage.
|
|
65
|
-
* @param {RbacsCollection} rbacsCollection The rbacs collection to insert in the local storage.
|
|
66
|
-
* @return {Promise<void>}
|
|
67
|
-
*/
|
|
68
|
-
async set(rbacsCollection) {
|
|
69
|
-
await navigator.locks.request(this.storageKey, async () => {
|
|
70
|
-
const rbacs = [];
|
|
71
|
-
if (rbacsCollection) {
|
|
72
|
-
if (!(rbacsCollection instanceof RbacsCollection)) {
|
|
73
|
-
throw new TypeError("RbacsLocalStorage::set expects a RbacsCollection");
|
|
74
|
-
}
|
|
75
|
-
for (const rbacEntity of rbacsCollection) {
|
|
76
|
-
RbacsLocalStorage.assertEntityBeforeSave(rbacEntity);
|
|
77
|
-
rbacs.push(rbacEntity.toDto(RbacEntity.ALL_CONTAIN_OPTIONS));
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
await browser.storage.local.set({ [this.storageKey]: rbacs });
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/*
|
|
85
|
-
* =================================================
|
|
86
|
-
* Static methods
|
|
87
|
-
* =================================================
|
|
88
|
-
*/
|
|
89
|
-
/**
|
|
90
|
-
* Make sure the entity meet some minimal requirements before being stored
|
|
91
|
-
*
|
|
92
|
-
* @param {RbacEntity} rbacEntity
|
|
93
|
-
* @throw {TypeError} if requirements are not met
|
|
94
|
-
* @private
|
|
95
|
-
*/
|
|
96
|
-
static assertEntityBeforeSave(rbacEntity) {
|
|
97
|
-
if (!rbacEntity) {
|
|
98
|
-
throw new TypeError("RolesLocalStorage expects a RbacEntity to be set");
|
|
99
|
-
}
|
|
100
|
-
if (!(rbacEntity instanceof RbacEntity)) {
|
|
101
|
-
throw new TypeError("RolesLocalStorage expects an object of type RbacEntity");
|
|
102
|
-
}
|
|
103
|
-
if (!rbacEntity.id) {
|
|
104
|
-
throw new TypeError("RolesLocalStorage expects RbacEntity id to be set");
|
|
105
|
-
}
|
|
32
|
+
get entityClass() {
|
|
33
|
+
return RbacsCollection;
|
|
106
34
|
}
|
|
107
35
|
}
|
|
108
36
|
|
|
@@ -29,7 +29,7 @@ describe("RbacLocalStorage", () => {
|
|
|
29
29
|
it("Should return undefined if nothing stored in the storage", async () => {
|
|
30
30
|
expect.assertions(1);
|
|
31
31
|
const rbacLocalstorage = new RbacLocalStorage(account);
|
|
32
|
-
const result = await rbacLocalstorage.
|
|
32
|
+
const result = await rbacLocalstorage.getData();
|
|
33
33
|
expect(result).toEqual(undefined);
|
|
34
34
|
});
|
|
35
35
|
|
|
@@ -37,20 +37,20 @@ describe("RbacLocalStorage", () => {
|
|
|
37
37
|
const rbacs = [defaultRbacWithUiActionData()];
|
|
38
38
|
expect.assertions(1);
|
|
39
39
|
const rbacLocalstorage = new RbacLocalStorage(account);
|
|
40
|
-
browser.storage.local.set({ [rbacLocalstorage.
|
|
41
|
-
const result = await rbacLocalstorage.
|
|
40
|
+
browser.storage.local.set({ [rbacLocalstorage.storageDataKey]: rbacs });
|
|
41
|
+
const result = await rbacLocalstorage.getData();
|
|
42
42
|
expect(result).toEqual(rbacs);
|
|
43
43
|
});
|
|
44
44
|
});
|
|
45
45
|
|
|
46
|
-
describe("RbacLocalStorage::
|
|
47
|
-
it("Should
|
|
46
|
+
describe("RbacLocalStorage::setData", () => {
|
|
47
|
+
it("Should setData a rbac colection in the local storage", async () => {
|
|
48
48
|
expect.assertions(2);
|
|
49
49
|
const rbacLocalstorage = new RbacLocalStorage(account);
|
|
50
50
|
const rbac = new RbacEntity(defaultRbacWithUiActionData());
|
|
51
51
|
const rbacsCollection = new RbacsCollection([rbac]);
|
|
52
|
-
await rbacLocalstorage.
|
|
53
|
-
const rbacs = await rbacLocalstorage.
|
|
52
|
+
await rbacLocalstorage.setData(rbacsCollection);
|
|
53
|
+
const rbacs = await rbacLocalstorage.getData();
|
|
54
54
|
expect(rbacs).toHaveLength(1);
|
|
55
55
|
expect(rbacs[0]).toEqual(rbac.toDto(RbacEntity.ALL_CONTAIN_OPTIONS));
|
|
56
56
|
});
|
|
@@ -61,7 +61,7 @@ describe("RbacLocalStorage", () => {
|
|
|
61
61
|
expect.assertions(1);
|
|
62
62
|
const rbacLocalstorage = new RbacLocalStorage(account);
|
|
63
63
|
await rbacLocalstorage.flush();
|
|
64
|
-
const rbacs = await rbacLocalstorage.
|
|
64
|
+
const rbacs = await rbacLocalstorage.getData();
|
|
65
65
|
expect(rbacs).toEqual(undefined);
|
|
66
66
|
});
|
|
67
67
|
});
|