passbolt-browser-extension 5.12.1 → 5.13.0
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/safe-chain-config.json +2 -1
- package/.github/ISSUE_TEMPLATE/bug_report.md +30 -22
- package/.github/ISSUE_TEMPLATE/config.yml +11 -0
- package/.jpmignore +0 -1
- package/CHANGELOG.md +82 -1
- package/CONTRIBUTING.md +1 -12
- package/README.md +5 -16
- package/RELEASE_NOTES.md +2 -3
- package/SECURITY.md +7 -0
- package/i18next.config.js +28 -0
- package/jest.config.json +1 -0
- package/package.json +20 -40
- package/src/all/background_page/controller/accountRecovery/reviewRequestController.test.js +1 -1
- package/src/all/background_page/{event → controller/actionLog}/findAllForActionLogController.js +1 -1
- package/src/all/background_page/{event → controller/actionLog}/findAllForActionLogController.test.js +4 -4
- package/src/all/background_page/controller/export/exportResourcesFileController.test.js +7 -2
- package/src/all/background_page/controller/folder/folderCreateController.js +3 -1
- package/src/all/background_page/controller/group/findMyGroupsController.test.js +2 -2
- package/src/all/background_page/controller/group/getOrFindGroupsController.js +61 -0
- package/src/all/background_page/controller/group/getOrFindGroupsController.test.js +69 -0
- package/src/all/background_page/controller/group/getOrFindGroupsUsersController.js +62 -0
- package/src/all/background_page/controller/group/getOrFindGroupsUsersController.test.js +69 -0
- package/src/all/background_page/controller/group/groupCreateController.js +1 -1
- package/src/all/background_page/controller/group/groupCreateController.test.js +1 -1
- package/src/all/background_page/controller/group/groupUpdateController.js +1 -1
- package/src/all/background_page/controller/group/updateAllGroupsLocalStorageController.test.js +1 -1
- package/src/all/background_page/controller/keyring/synchroniseKeyringController.js +51 -0
- package/src/all/background_page/controller/keyring/synchroniseKeyringController.test.js +49 -0
- package/src/all/background_page/controller/metadata/shareMetadataKeyPrivateController.test.js +1 -1
- package/src/all/background_page/controller/move/moveFolderController.js +0 -2
- package/src/all/background_page/controller/permission/FindAcoPermissionsForDisplayController.js +1 -1
- package/src/all/background_page/controller/permission/FindAcoPermissionsForDisplayController.test.js +2 -2
- package/src/all/background_page/controller/resource/findAllByIdsForDisplayPermissionsController.test.js +8 -3
- package/src/all/background_page/controller/resource/findAllIdsByIsSharedWithGroupController.test.js +9 -4
- package/src/all/background_page/controller/resource/resourceUpdateController.test.js +1 -2
- package/src/all/background_page/controller/resourceLocalStorage/resourceUpdateLocalStorageController.test.js +5 -2
- package/src/all/background_page/controller/share/findFoldersForShareController.js +66 -0
- package/src/all/background_page/controller/share/findFoldersForShareController.test.js +70 -0
- package/src/all/background_page/controller/share/searchUsersAndGroupsController.js +4 -4
- package/src/all/background_page/controller/share/searchUsersAndGroupsController.test.js +8 -23
- package/src/all/background_page/controller/share/shareResourcesController.test.js +2 -2
- package/src/all/background_page/controller/subscription/createSubscriptionKeyController.js +63 -0
- package/src/all/background_page/controller/subscription/createSubscriptionKeyController.test.js +56 -0
- package/src/all/background_page/controller/subscription/deleteSubscriptionKeyController.js +55 -0
- package/src/all/background_page/controller/subscription/deleteSubscriptionKeyController.test.js +50 -0
- package/src/all/background_page/controller/user/deleteUserController.test.js +1 -1
- package/src/all/background_page/controller/user/getOrFindUsersController.js +61 -0
- package/src/all/background_page/controller/user/getOrFindUsersController.test.js +69 -0
- package/src/all/background_page/error/deleteDryRunError.js +1 -1
- package/src/all/background_page/event/actionLogEvents.js +1 -1
- package/src/all/background_page/event/appEvents.js +25 -0
- package/src/all/background_page/event/groupEvents.js +26 -0
- package/src/all/background_page/event/keyringEvents.js +12 -0
- package/src/all/background_page/event/shareEvents.js +3 -9
- package/src/all/background_page/event/userEvents.js +13 -0
- package/src/all/background_page/model/config.js +12 -2
- package/src/all/background_page/model/entity/folder/folderEntity.js +2 -2
- package/src/all/background_page/model/entity/folder/folderEntity.test.js +2 -2
- package/src/all/background_page/model/entity/folder/foldersCollection.test.js +1 -1
- package/src/all/background_page/model/entity/group/update/groupUpdateEntity.js +1 -1
- package/src/all/background_page/model/entity/group/update/groupUpdateEntity.test.js +1 -1
- package/src/all/background_page/model/entity/permission/actionLog/updatedPermissionEntity.js +2 -2
- package/src/all/background_page/model/entity/permission/actionLog/updatedPermissionEntity.test.data.js +1 -1
- package/src/all/background_page/model/entity/permission/change/permissionChangeEntity.js +1 -1
- package/src/all/background_page/model/entity/permission/change/permissionChangesCollection.js +2 -2
- package/src/all/background_page/model/entity/permission/change/permissionChangesCollection.test.js +2 -2
- package/src/all/background_page/model/entity/resource/resourceEntity.js +2 -2
- package/src/all/background_page/model/entity/resource/resourceEntity.test.js +1 -1
- package/src/all/background_page/model/entity/user/userEntity.js +16 -377
- package/src/all/background_page/model/entity/user/userEntity.test.js +22 -297
- package/src/all/background_page/model/entity/userAndGroupSearchResultEntity/userAndGroupSearchResultEntity.js +1 -1
- package/src/all/background_page/model/folder/folderModel.js +5 -154
- package/src/all/background_page/model/group/groupModel.js +1 -1
- package/src/all/background_page/model/keyring.js +52 -17
- package/src/all/background_page/model/keyring.test.js +110 -0
- package/src/all/background_page/model/resource/resourceModel.js +2 -55
- package/src/all/background_page/model/setup/setupModel.js +2 -2
- package/src/all/background_page/model/user/userModel.js +18 -15
- package/src/all/background_page/model/user/userModel.test.js +1 -3
- package/src/all/background_page/service/api/abstract/abstractService.js +3 -17
- package/src/all/background_page/service/api/edition/passboltEditionApiService.js +64 -0
- package/src/all/background_page/service/api/edition/passboltEditionApiService.test.js +99 -0
- package/src/all/background_page/service/api/group/groupApiService.js +22 -23
- package/src/all/background_page/service/api/group/groupApiService.test.js +70 -0
- package/src/all/background_page/service/api/resource/resourceService.js +18 -12
- package/src/all/background_page/service/api/share/{shareService.js → shareApiService.js} +10 -7
- package/src/all/background_page/service/api/share/{shareService.test.js → shareApiService.test.js} +5 -5
- package/src/all/background_page/service/group/createGroupService.js +1 -1
- package/src/all/background_page/service/group/createGroupService.test.js +1 -1
- package/src/all/background_page/service/group/findAndUpdateGroupsLocalStorageService.js +56 -1
- package/src/all/background_page/service/group/findAndUpdateGroupsLocalStorageService.test.js +84 -2
- package/src/all/background_page/service/group/findGroupsService.js +5 -9
- package/src/all/background_page/service/group/findGroupsService.test.data.js +1 -1
- package/src/all/background_page/service/group/findGroupsService.test.js +10 -15
- package/src/all/background_page/service/group/getOrFindGroupsService.js +65 -0
- package/src/all/background_page/service/group/getOrFindGroupsService.test.js +168 -0
- package/src/all/background_page/service/group/getOrFindGroupsUsersService.js +51 -0
- package/src/all/background_page/service/group/getOrFindGroupsUsersService.test.js +94 -0
- package/src/all/background_page/service/group/groupUpdateService.js +5 -3
- package/src/all/background_page/service/group/groupUpdateService.test.js +10 -2
- package/src/all/background_page/service/local_storage/groupLocalStorage.js +2 -2
- package/src/all/background_page/service/local_storage/groupLocalStorage.test.js +3 -3
- package/src/all/background_page/service/local_storage/userLocalStorage.js +57 -36
- package/src/all/background_page/service/local_storage/userLocalStorage.test.js +282 -0
- package/src/all/background_page/service/metadata/createMetadataKeyService.test.js +1 -1
- package/src/all/background_page/service/metadata/saveMetadataSettingsService.test.js +1 -1
- package/src/all/background_page/service/metadata/shareMetadataKeyPrivateService.test.js +1 -1
- package/src/all/background_page/service/migrateMetadata/migrateMetadataResourcesService.js +1 -1
- package/src/all/background_page/service/move/calculatePermissionsChangesForMoveService.js +113 -0
- package/src/all/background_page/service/move/calculatePermissionsChangesForMoveService.test.data.js +38 -0
- package/src/all/background_page/service/move/calculatePermissionsChangesForMoveService.test.js +158 -0
- package/src/all/background_page/service/move/moveOneFolderService.js +6 -7
- package/src/all/background_page/service/move/moveOneFolderService.test.js +90 -90
- package/src/all/background_page/service/move/moveResourcesService.js +2 -5
- package/src/all/background_page/service/permission/findPermissionsService.js +1 -1
- package/src/all/background_page/service/resource/create/resourceCreateService.js +13 -31
- package/src/all/background_page/service/resource/create/resourceCreateService.test.js +25 -18
- package/src/all/background_page/service/resource/export/exportResourcesService.test.js +13 -4
- package/src/all/background_page/service/resource/findAndUpdateResourcesLocalStorageService.test.js +35 -28
- package/src/all/background_page/service/resource/findResourcesService.js +78 -2
- package/src/all/background_page/service/resource/findResourcesService.test.data.js +1 -1
- package/src/all/background_page/service/resource/findResourcesService.test.js +90 -31
- package/src/all/background_page/service/resource/getOrFindResourcesService.test.js +18 -8
- package/src/all/background_page/service/session_storage/keepSessionAliveService.js +3 -3
- package/src/all/background_page/service/session_storage/keepSessionAliveService.test.js +5 -3
- package/src/all/background_page/service/share/searchUsersAndGroupsService.js +41 -0
- package/src/all/background_page/service/share/searchUsersAndGroupsService.test.js +64 -0
- package/src/all/background_page/service/share/shareFoldersService.js +3 -3
- package/src/all/background_page/service/share/shareFoldersService.test.js +3 -3
- package/src/all/background_page/service/share/shareResourceService.js +4 -4
- package/src/all/background_page/service/share/shareResourceService.test.js +8 -8
- package/src/all/background_page/service/subscription/createSubscriptionKeyService.js +57 -0
- package/src/all/background_page/service/subscription/createSubscriptionKeyService.test.js +111 -0
- package/src/all/background_page/service/subscription/deleteSubscriptionKeyService.js +35 -0
- package/src/all/background_page/service/subscription/deleteSubscriptionKeyService.test.js +55 -0
- package/src/all/background_page/service/user/deleteUserService.js +4 -4
- package/src/all/background_page/service/user/deleteUserService.test.js +10 -10
- package/src/all/background_page/service/user/findAndUpdateUsersLocalStorageService.js +81 -0
- package/src/all/background_page/service/user/findAndUpdateUsersLocalStorageService.test.js +132 -0
- package/src/all/background_page/service/user/findUsersService.js +6 -6
- package/src/all/background_page/service/user/findUsersService.test.js +39 -38
- package/src/all/background_page/service/user/getOrFindUsersService.js +60 -0
- package/src/all/background_page/service/user/getOrFindUsersService.test.js +110 -0
- package/src/all/background_page/utils/assertions.js +1 -0
- package/src/all/locales/ko-KR/common.json +1 -1
- package/src/chrome/manifest.json +1 -1
- package/src/chrome-mv3/manifest.json +1 -1
- package/src/firefox/manifest.json +3 -3
- package/src/safari/manifest.json +2 -2
- package/test/jest.env-setup.js +31 -0
- package/webpack/applyOutputClean.js +69 -0
- package/webpack/base.config.js +33 -0
- package/webpack/common-blocks.js +91 -0
- package/webpack/expectedBuildArtifacts.js +51 -0
- package/webpack/i18nextExtractionPlugin.js +43 -0
- package/webpack/passboltEnvPlugin.js +41 -0
- package/webpack/webExtPlugin/index.js +75 -0
- package/webpack.chromium-mv2.config.js +40 -0
- package/webpack.chromium-mv3.config.js +40 -0
- package/webpack.common.config.js +186 -0
- package/webpack.config.js +38 -0
- package/webpack.firefox.config.js +40 -0
- package/webpack.mv2.config.js +65 -0
- package/webpack.mv3.config.js +99 -0
- package/webpack.safari-background-page.config.js +66 -57
- package/webpack.safari.config.js +44 -0
- package/Gruntfile.js +0 -471
- package/am_i_compromised.py +0 -1036
- package/am_i_compromised.sh +0 -688
- package/i18next-parser.config.js +0 -22
- package/src/all/background_page/config/config.json +0 -7
- package/src/all/background_page/config/config.json.debug +0 -7
- package/src/all/background_page/config/config.json.default +0 -7
- package/src/all/background_page/model/entity/group/groupEntity.js +0 -241
- package/src/all/background_page/model/entity/group/groupEntity.test.js +0 -136
- package/src/all/background_page/model/entity/group/groupsCollection.js +0 -166
- package/src/all/background_page/model/entity/group/groupsCollection.test.data.js +0 -34
- package/src/all/background_page/model/entity/group/groupsCollection.test.js +0 -227
- package/src/all/background_page/model/entity/permission/permissionEntity.js +0 -485
- package/src/all/background_page/model/entity/permission/permissionEntity.test.js +0 -263
- package/src/all/background_page/model/entity/permission/permissionsCollection.js +0 -486
- package/src/all/background_page/model/entity/permission/permissionsCollection.test.js +0 -700
- package/src/all/background_page/model/entity/user/usersCollection.js +0 -147
- package/src/all/background_page/model/entity/user/usersCollection.test.js +0 -223
- package/src/all/background_page/model/share/shareModel.js +0 -183
- package/src/all/background_page/model/share/shareModel.test.js +0 -61
- package/src/all/background_page/service/api/user/userService.js +0 -260
- package/src/all/background_page/service/resource/create/resourceCreateService.test.data.js +0 -55
- package/webpack-content-scripts.browser-integration.config.js +0 -57
- package/webpack-content-scripts.config.js +0 -61
- package/webpack-content-scripts.public-website-sign-in.config.js +0 -57
- package/webpack-data.config.js +0 -102
- package/webpack-data.download.config.js +0 -59
- package/webpack-data.in-form-call-to-action.config.js +0 -97
- package/webpack-data.in-form-menu.config.js +0 -97
- package/webpack-offscreens.config.js +0 -55
- package/webpack.background-page.config.js +0 -62
- package/webpack.service-worker.config.js +0 -65
|
@@ -0,0 +1,65 @@
|
|
|
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 5.13.0
|
|
13
|
+
*/
|
|
14
|
+
import FindAndUpdateGroupsLocalStorageService from "./findAndUpdateGroupsLocalStorageService";
|
|
15
|
+
import GroupLocalStorage from "../local_storage/groupLocalStorage";
|
|
16
|
+
import GroupsCollection from "passbolt-styleguide/src/shared/models/entity/group/groupsCollection";
|
|
17
|
+
import { assertArrayUUID } from "../../utils/assertions";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The service aims to get groups from the local storage if it is set, or retrieve them from the API and
|
|
21
|
+
* set the local storage.
|
|
22
|
+
*/
|
|
23
|
+
export default class GetOrFindGroupsService {
|
|
24
|
+
/**
|
|
25
|
+
*
|
|
26
|
+
* @param {AccountEntity} account The user account
|
|
27
|
+
* @param {ApiClientOptions} apiClientOptions The api client options
|
|
28
|
+
*/
|
|
29
|
+
constructor(account, apiClientOptions) {
|
|
30
|
+
this.account = account;
|
|
31
|
+
this.groupLocalStorage = new GroupLocalStorage(account);
|
|
32
|
+
this.findAndUpdateGroupsLocalStorage = new FindAndUpdateGroupsLocalStorageService(account, apiClientOptions);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Get or find all groups.
|
|
37
|
+
* @returns {Promise<GroupsCollection>}
|
|
38
|
+
*/
|
|
39
|
+
async getOrFindAll() {
|
|
40
|
+
const hasRuntimeCache = GroupLocalStorage.hasCachedData(this.account.id);
|
|
41
|
+
const groupsDto = await this.groupLocalStorage.get();
|
|
42
|
+
// Return local storage data if the storage was initialized.
|
|
43
|
+
if (groupsDto) {
|
|
44
|
+
// No validation is required if the data is in the runtime cache, as validation was done by the process that set the cache.
|
|
45
|
+
return new GroupsCollection(groupsDto, { validate: !hasRuntimeCache });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Otherwise retrieve the groups and update the local storage.
|
|
49
|
+
return this.findAndUpdateGroupsLocalStorage.findAndUpdateAll();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Get or find all the groups matching the given ids.
|
|
54
|
+
* @param {Array<string>} groupIds The groups to find.
|
|
55
|
+
* @return {Promise<GroupsCollection>}
|
|
56
|
+
*/
|
|
57
|
+
async getOrFindByIds(groupIds) {
|
|
58
|
+
assertArrayUUID(groupIds);
|
|
59
|
+
|
|
60
|
+
const groupsCollection = await this.getOrFindAll();
|
|
61
|
+
groupsCollection.filterByPropertyValueIn("id", groupIds);
|
|
62
|
+
|
|
63
|
+
return groupsCollection;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
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 5.13.0
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { v4 as uuidv4 } from "uuid";
|
|
16
|
+
import AccountEntity from "../../model/entity/account/accountEntity";
|
|
17
|
+
import { defaultAccountDto } from "../../model/entity/account/accountEntity.test.data";
|
|
18
|
+
import { defaultApiClientOptions } from "passbolt-styleguide/src/shared/lib/apiClient/apiClientOptions.test.data";
|
|
19
|
+
import GetOrFindGroupsService from "./getOrFindGroupsService";
|
|
20
|
+
import FindAndUpdateGroupsLocalStorageService from "./findAndUpdateGroupsLocalStorageService";
|
|
21
|
+
import FindGroupsService from "./findGroupsService";
|
|
22
|
+
import GroupsCollection from "passbolt-styleguide/src/shared/models/entity/group/groupsCollection";
|
|
23
|
+
import GroupLocalStorage from "../local_storage/groupLocalStorage";
|
|
24
|
+
import { defaultGroupsDtos } from "passbolt-styleguide/src/shared/models/entity/group/groupsCollection.test.data";
|
|
25
|
+
|
|
26
|
+
describe("GetOrFindGroupsService", () => {
|
|
27
|
+
let service, account;
|
|
28
|
+
|
|
29
|
+
beforeEach(async () => {
|
|
30
|
+
jest.clearAllMocks();
|
|
31
|
+
account = new AccountEntity(defaultAccountDto());
|
|
32
|
+
service = new GetOrFindGroupsService(account, defaultApiClientOptions());
|
|
33
|
+
// flush account related storage before each.
|
|
34
|
+
await service.groupLocalStorage.flush();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
describe("::getOrFindAll", () => {
|
|
38
|
+
it("fetches from the API and initializes the local storage with an empty array when the API returns no groups.", async () => {
|
|
39
|
+
expect.assertions(4);
|
|
40
|
+
jest
|
|
41
|
+
.spyOn(FindGroupsService.prototype, "findAllForLocalStorage")
|
|
42
|
+
.mockImplementation(() => new GroupsCollection([]));
|
|
43
|
+
jest.spyOn(FindAndUpdateGroupsLocalStorageService.prototype, "findAndUpdateAll");
|
|
44
|
+
|
|
45
|
+
const groups = await service.getOrFindAll();
|
|
46
|
+
|
|
47
|
+
expect(FindAndUpdateGroupsLocalStorageService.prototype.findAndUpdateAll).toHaveBeenCalledTimes(1);
|
|
48
|
+
expect(groups).toBeInstanceOf(GroupsCollection);
|
|
49
|
+
expect(groups).toHaveLength(0);
|
|
50
|
+
expect(await service.groupLocalStorage.get()).toEqual([]);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("fetches the groups from the API and populates the local storage when the local storage is not initialized.", async () => {
|
|
54
|
+
expect.assertions(4);
|
|
55
|
+
const groupsDto = defaultGroupsDtos();
|
|
56
|
+
jest
|
|
57
|
+
.spyOn(FindGroupsService.prototype, "findAllForLocalStorage")
|
|
58
|
+
.mockImplementation(() => new GroupsCollection(groupsDto));
|
|
59
|
+
|
|
60
|
+
const groups = await service.getOrFindAll();
|
|
61
|
+
|
|
62
|
+
expect(groups).toHaveLength(groupsDto.length);
|
|
63
|
+
expect(groups.toDto(GroupLocalStorage.DEFAULT_CONTAIN)).toEqual(groupsDto);
|
|
64
|
+
expect(GroupLocalStorage.hasCachedData(account.id)).toBeTruthy();
|
|
65
|
+
expect(await service.groupLocalStorage.get()).toEqual(groupsDto);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("retrieves groups from the local storage when the local storage is initialized.", async () => {
|
|
69
|
+
expect.assertions(5);
|
|
70
|
+
const groupsDto = defaultGroupsDtos();
|
|
71
|
+
jest.spyOn(FindGroupsService.prototype, "findAllForLocalStorage");
|
|
72
|
+
await service.groupLocalStorage.set(new GroupsCollection(groupsDto));
|
|
73
|
+
|
|
74
|
+
const groups = await service.getOrFindAll();
|
|
75
|
+
|
|
76
|
+
expect(FindGroupsService.prototype.findAllForLocalStorage).not.toHaveBeenCalled();
|
|
77
|
+
expect(groups).toHaveLength(groupsDto.length);
|
|
78
|
+
expect(groups.toDto(GroupLocalStorage.DEFAULT_CONTAIN)).toEqual(groupsDto);
|
|
79
|
+
expect(GroupLocalStorage.hasCachedData(account.id)).toBeTruthy();
|
|
80
|
+
expect(await service.groupLocalStorage.get()).toEqual(groupsDto);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("does not validate the groups collection if the information is retrieved from the runtime cache.", async () => {
|
|
84
|
+
expect.assertions(2);
|
|
85
|
+
jest.spyOn(FindGroupsService.prototype, "findAllForLocalStorage");
|
|
86
|
+
await service.groupLocalStorage.set(new GroupsCollection(defaultGroupsDtos()));
|
|
87
|
+
jest.spyOn(GroupsCollection.prototype, "validateSchema");
|
|
88
|
+
|
|
89
|
+
await service.getOrFindAll();
|
|
90
|
+
|
|
91
|
+
expect(FindGroupsService.prototype.findAllForLocalStorage).not.toHaveBeenCalled();
|
|
92
|
+
// Validation must not be triggered by getOrFindAll when the data comes from the runtime cache.
|
|
93
|
+
expect(GroupsCollection.prototype.validateSchema).not.toHaveBeenCalled();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("validates groups collection if the local storage has no runtime cache and the information is retrieved from the local storage.", async () => {
|
|
97
|
+
expect.assertions(2);
|
|
98
|
+
jest.spyOn(FindGroupsService.prototype, "findAllForLocalStorage");
|
|
99
|
+
await service.groupLocalStorage.set(new GroupsCollection(defaultGroupsDtos()));
|
|
100
|
+
delete GroupLocalStorage._runtimeCachedData[account.id];
|
|
101
|
+
jest.spyOn(GroupsCollection.prototype, "validateSchema");
|
|
102
|
+
|
|
103
|
+
await service.getOrFindAll();
|
|
104
|
+
|
|
105
|
+
expect(FindGroupsService.prototype.findAllForLocalStorage).not.toHaveBeenCalled();
|
|
106
|
+
// Validation must be triggered by getOrFindAll when the data is loaded from the disk cache.
|
|
107
|
+
expect(GroupsCollection.prototype.validateSchema).toHaveBeenCalled();
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe("::getOrFindByIds", () => {
|
|
112
|
+
it("returns only the groups whose ids are in the requested set.", async () => {
|
|
113
|
+
expect.assertions(2);
|
|
114
|
+
const groupsDto = defaultGroupsDtos();
|
|
115
|
+
await service.groupLocalStorage.set(new GroupsCollection(groupsDto));
|
|
116
|
+
const requestedIds = [groupsDto[1].id, groupsDto[3].id, groupsDto[5].id];
|
|
117
|
+
|
|
118
|
+
const groups = await service.getOrFindByIds(requestedIds);
|
|
119
|
+
|
|
120
|
+
expect(groups).toHaveLength(3);
|
|
121
|
+
expect(groups.extract("id").sort()).toEqual([...requestedIds].sort());
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("returns an empty collection when none of the ids match.", async () => {
|
|
125
|
+
expect.assertions(1);
|
|
126
|
+
const groupsDto = defaultGroupsDtos();
|
|
127
|
+
await service.groupLocalStorage.set(new GroupsCollection(groupsDto));
|
|
128
|
+
|
|
129
|
+
const groups = await service.getOrFindByIds([uuidv4(), uuidv4()]);
|
|
130
|
+
|
|
131
|
+
expect(groups).toHaveLength(0);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it("returns all groups when every group id is requested.", async () => {
|
|
135
|
+
expect.assertions(2);
|
|
136
|
+
const groupsDto = defaultGroupsDtos();
|
|
137
|
+
await service.groupLocalStorage.set(new GroupsCollection(groupsDto));
|
|
138
|
+
const allIds = groupsDto.map((group) => group.id);
|
|
139
|
+
|
|
140
|
+
const groups = await service.getOrFindByIds(allIds);
|
|
141
|
+
|
|
142
|
+
expect(groups).toHaveLength(groupsDto.length);
|
|
143
|
+
expect(groups.extract("id").sort()).toEqual([...allIds].sort());
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it("fetches from the API when the local storage is not initialized, then filters.", async () => {
|
|
147
|
+
expect.assertions(3);
|
|
148
|
+
const groupsDto = defaultGroupsDtos();
|
|
149
|
+
jest
|
|
150
|
+
.spyOn(FindGroupsService.prototype, "findAllForLocalStorage")
|
|
151
|
+
.mockImplementation(() => new GroupsCollection(groupsDto));
|
|
152
|
+
const requestedIds = [groupsDto[0].id, groupsDto[2].id];
|
|
153
|
+
|
|
154
|
+
const groups = await service.getOrFindByIds(requestedIds);
|
|
155
|
+
|
|
156
|
+
expect(FindGroupsService.prototype.findAllForLocalStorage).toHaveBeenCalledTimes(1);
|
|
157
|
+
expect(groups).toHaveLength(2);
|
|
158
|
+
expect(groups.extract("id").sort()).toEqual([...requestedIds].sort());
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it("should assert its parameter.", async () => {
|
|
162
|
+
expect.assertions(1);
|
|
163
|
+
await expect(() => service.getOrFindByIds(["not-a-uuid"])).rejects.toThrow(
|
|
164
|
+
"The given parameter is not a valid array of uuid",
|
|
165
|
+
);
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
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 5.13.0
|
|
13
|
+
*/
|
|
14
|
+
import GroupsUsersCollection from "passbolt-styleguide/src/shared/models/entity/groupUser/groupsUsersCollection";
|
|
15
|
+
import GetOrFindGroupsService from "./getOrFindGroupsService";
|
|
16
|
+
import { assertUuid } from "../../utils/assertions";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The service aims to retrieve the group members of a given group from the local storage cache
|
|
20
|
+
* served by `GetOrFindGroupsService`, falling back to the API on a cold cache.
|
|
21
|
+
*/
|
|
22
|
+
class GetOrFindGroupsUsersService {
|
|
23
|
+
/**
|
|
24
|
+
* Constructor.
|
|
25
|
+
* @param {AccountEntity} account The user account.
|
|
26
|
+
* @param {ApiClientOptions} apiClientOptions The api client options.
|
|
27
|
+
*/
|
|
28
|
+
constructor(account, apiClientOptions) {
|
|
29
|
+
this.getOrFindGroupsService = new GetOrFindGroupsService(account, apiClientOptions);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Get or find the members of the group matching the given id.
|
|
34
|
+
* @param {string} groupId The id of the group whose members are requested.
|
|
35
|
+
* @returns {Promise<GroupsUsersCollection>}
|
|
36
|
+
* @throws {Error} If no group is found for the given id.
|
|
37
|
+
*/
|
|
38
|
+
async getOrFindByGroupId(groupId) {
|
|
39
|
+
assertUuid(groupId);
|
|
40
|
+
|
|
41
|
+
const groupsCollection = await this.getOrFindGroupsService.getOrFindAll();
|
|
42
|
+
const group = groupsCollection.getFirst("id", groupId);
|
|
43
|
+
if (!group) {
|
|
44
|
+
throw new Error(`The group with id ${groupId} could not be found.`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return group.groupsUsers ?? new GroupsUsersCollection([]);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default GetOrFindGroupsUsersService;
|
|
@@ -0,0 +1,94 @@
|
|
|
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 5.13.0
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { v4 as uuidv4 } from "uuid";
|
|
16
|
+
import AccountEntity from "../../model/entity/account/accountEntity";
|
|
17
|
+
import { defaultAccountDto } from "../../model/entity/account/accountEntity.test.data";
|
|
18
|
+
import { defaultApiClientOptions } from "passbolt-styleguide/src/shared/lib/apiClient/apiClientOptions.test.data";
|
|
19
|
+
import GetOrFindGroupsUsersService from "./getOrFindGroupsUsersService";
|
|
20
|
+
import FindGroupsService from "./findGroupsService";
|
|
21
|
+
import GroupsCollection from "passbolt-styleguide/src/shared/models/entity/group/groupsCollection";
|
|
22
|
+
import GroupsUsersCollection from "passbolt-styleguide/src/shared/models/entity/groupUser/groupsUsersCollection";
|
|
23
|
+
import { defaultGroupsDtos } from "passbolt-styleguide/src/shared/models/entity/group/groupsCollection.test.data";
|
|
24
|
+
|
|
25
|
+
describe("GetOrFindGroupsUsersService", () => {
|
|
26
|
+
let service, account;
|
|
27
|
+
|
|
28
|
+
beforeEach(async () => {
|
|
29
|
+
jest.clearAllMocks();
|
|
30
|
+
account = new AccountEntity(defaultAccountDto());
|
|
31
|
+
service = new GetOrFindGroupsUsersService(account, defaultApiClientOptions());
|
|
32
|
+
// flush account related storage before each.
|
|
33
|
+
await service.getOrFindGroupsService.groupLocalStorage.flush();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
describe("::getOrFindByGroupId", () => {
|
|
37
|
+
it("returns the members of the requested group when the local storage is populated.", async () => {
|
|
38
|
+
expect.assertions(3);
|
|
39
|
+
const groupsDto = defaultGroupsDtos(5, { withGroupsUsers: 3 });
|
|
40
|
+
await service.getOrFindGroupsService.groupLocalStorage.set(new GroupsCollection(groupsDto));
|
|
41
|
+
const targetGroup = groupsDto[2];
|
|
42
|
+
|
|
43
|
+
const result = await service.getOrFindByGroupId(targetGroup.id);
|
|
44
|
+
|
|
45
|
+
expect(result).toBeInstanceOf(GroupsUsersCollection);
|
|
46
|
+
expect(result).toHaveLength(3);
|
|
47
|
+
expect(result.items.every((groupUser) => groupUser.groupId === targetGroup.id)).toBe(true);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("returns an empty GroupsUsersCollection when the group has no members.", async () => {
|
|
51
|
+
expect.assertions(2);
|
|
52
|
+
const groupsDto = defaultGroupsDtos(1, { withGroupsUsers: 0 });
|
|
53
|
+
await service.getOrFindGroupsService.groupLocalStorage.set(new GroupsCollection(groupsDto));
|
|
54
|
+
|
|
55
|
+
const result = await service.getOrFindByGroupId(groupsDto[0].id);
|
|
56
|
+
|
|
57
|
+
expect(result).toBeInstanceOf(GroupsUsersCollection);
|
|
58
|
+
expect(result).toHaveLength(0);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("fetches from the API when the local storage is not initialized, then returns the requested group's members.", async () => {
|
|
62
|
+
expect.assertions(3);
|
|
63
|
+
const groupsDto = defaultGroupsDtos(3, { withGroupsUsers: 2 });
|
|
64
|
+
jest
|
|
65
|
+
.spyOn(FindGroupsService.prototype, "findAllForLocalStorage")
|
|
66
|
+
.mockImplementation(() => new GroupsCollection(groupsDto));
|
|
67
|
+
const targetGroup = groupsDto[1];
|
|
68
|
+
|
|
69
|
+
const result = await service.getOrFindByGroupId(targetGroup.id);
|
|
70
|
+
|
|
71
|
+
expect(FindGroupsService.prototype.findAllForLocalStorage).toHaveBeenCalledTimes(1);
|
|
72
|
+
expect(result).toBeInstanceOf(GroupsUsersCollection);
|
|
73
|
+
expect(result).toHaveLength(2);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("throws when the group id does not exist.", async () => {
|
|
77
|
+
expect.assertions(1);
|
|
78
|
+
const groupsDto = defaultGroupsDtos();
|
|
79
|
+
await service.getOrFindGroupsService.groupLocalStorage.set(new GroupsCollection(groupsDto));
|
|
80
|
+
const missingId = uuidv4();
|
|
81
|
+
|
|
82
|
+
await expect(() => service.getOrFindByGroupId(missingId)).rejects.toThrow(
|
|
83
|
+
`The group with id ${missingId} could not be found.`,
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("should assert its parameter.", async () => {
|
|
88
|
+
expect.assertions(1);
|
|
89
|
+
await expect(() => service.getOrFindByGroupId("not-a-uuid")).rejects.toThrow(
|
|
90
|
+
"The given parameter is not a valid UUID",
|
|
91
|
+
);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
});
|
|
@@ -16,7 +16,7 @@ import Keyring from "../../model/keyring";
|
|
|
16
16
|
import EncryptMessageService from "../../service/crypto/encryptMessageService";
|
|
17
17
|
import DecryptMessageService from "../../service/crypto/decryptMessageService";
|
|
18
18
|
import GroupModel from "../../model/group/groupModel";
|
|
19
|
-
import GroupEntity from "
|
|
19
|
+
import GroupEntity from "passbolt-styleguide/src/shared/models/entity/group/groupEntity";
|
|
20
20
|
import GroupUpdateEntity from "../../model/entity/group/update/groupUpdateEntity";
|
|
21
21
|
import i18n from "../../sdk/i18n";
|
|
22
22
|
import SecretEntity from "passbolt-styleguide/src/shared/models/entity/secret/secretEntity";
|
|
@@ -37,7 +37,7 @@ import GroupApiService from "../api/group/groupApiService";
|
|
|
37
37
|
* - Done
|
|
38
38
|
*/
|
|
39
39
|
const PROGRESS_GOAL = 6;
|
|
40
|
-
const YIELD_INTERVAL_MS =
|
|
40
|
+
const YIELD_INTERVAL_MS = 8000; // PB-51648 yield reduce to 8s due to chrome 148 more strict to ping service worker
|
|
41
41
|
|
|
42
42
|
class GroupUpdateService {
|
|
43
43
|
/**
|
|
@@ -216,7 +216,9 @@ class GroupUpdateService {
|
|
|
216
216
|
|
|
217
217
|
this.progressService.updateStepMessage(progressMessage);
|
|
218
218
|
const groupUpdateOperation = groupUpdateSingleOperationList.items[i];
|
|
219
|
-
const groupDto = await this.groupApiService.update(groupUpdateOperation.id, groupUpdateOperation.toDto()
|
|
219
|
+
const groupDto = await this.groupApiService.update(groupUpdateOperation.id, groupUpdateOperation.toDto(), {
|
|
220
|
+
my_group_user: true,
|
|
221
|
+
});
|
|
220
222
|
const updatedGroupEntity = new GroupEntity(groupDto, { ignoreInvalidEntity: true });
|
|
221
223
|
await this.groupLocalStorage.updateGroup(updatedGroupEntity);
|
|
222
224
|
}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* @since 4.10.1
|
|
13
13
|
*/
|
|
14
14
|
import GroupUpdateService from "./groupUpdateService";
|
|
15
|
-
import GroupEntity from "
|
|
15
|
+
import GroupEntity from "passbolt-styleguide/src/shared/models/entity/group/groupEntity";
|
|
16
16
|
import GroupUpdateEntity from "../../model/entity/group/update/groupUpdateEntity";
|
|
17
17
|
import GroupUpdateDryRunResultEntity from "../../model/entity/group/update/groupUpdateDryRunResultEntity";
|
|
18
18
|
import EncryptMessageService from "../crypto/encryptMessageService";
|
|
@@ -89,7 +89,11 @@ describe("GroupUpdateService", () => {
|
|
|
89
89
|
expect(spyOnGroupApiServiceUpdate).toHaveBeenCalledTimes(1);
|
|
90
90
|
const expectedDiffGropuUpdateEntityDto = diffGroupUpdateEntity.toDto();
|
|
91
91
|
delete expectedDiffGropuUpdateEntityDto.groups_users;
|
|
92
|
-
expect(spyOnGroupApiServiceUpdate).toHaveBeenCalledWith(
|
|
92
|
+
expect(spyOnGroupApiServiceUpdate).toHaveBeenCalledWith(
|
|
93
|
+
diffGroupUpdateEntity.id,
|
|
94
|
+
expectedDiffGropuUpdateEntityDto,
|
|
95
|
+
{ my_group_user: true },
|
|
96
|
+
);
|
|
93
97
|
|
|
94
98
|
//Exepctation for the progressSerivce when there is no crypto involved
|
|
95
99
|
expect(progressService.start).toHaveBeenCalledTimes(1);
|
|
@@ -171,10 +175,12 @@ describe("GroupUpdateService", () => {
|
|
|
171
175
|
expect(spyOnGroupApiServiceUpdate).toHaveBeenCalledWith(
|
|
172
176
|
diffGroupUpdateEntity.id,
|
|
173
177
|
expectedDiffGropuUpdateEntityDto1,
|
|
178
|
+
{ my_group_user: true },
|
|
174
179
|
);
|
|
175
180
|
expect(spyOnGroupApiServiceUpdate).toHaveBeenCalledWith(
|
|
176
181
|
diffGroupUpdateEntity.id,
|
|
177
182
|
expectedDiffGropuUpdateEntityDto2,
|
|
183
|
+
{ my_group_user: true },
|
|
178
184
|
);
|
|
179
185
|
});
|
|
180
186
|
|
|
@@ -243,10 +249,12 @@ describe("GroupUpdateService", () => {
|
|
|
243
249
|
expect(spyOnGroupApiServiceUpdate).toHaveBeenCalledWith(
|
|
244
250
|
diffGroupUpdateEntity.id,
|
|
245
251
|
expectedDiffGropuUpdateEntityDto1,
|
|
252
|
+
{ my_group_user: true },
|
|
246
253
|
);
|
|
247
254
|
expect(spyOnGroupApiServiceUpdate).toHaveBeenCalledWith(
|
|
248
255
|
diffGroupUpdateEntity.id,
|
|
249
256
|
expectedDiffGropuUpdateEntityDto2,
|
|
257
|
+
{ my_group_user: true },
|
|
250
258
|
);
|
|
251
259
|
});
|
|
252
260
|
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
* @since 2.13.0
|
|
13
13
|
*/
|
|
14
14
|
import Log from "../../model/log";
|
|
15
|
-
import GroupsCollection from "
|
|
16
|
-
import GroupEntity from "
|
|
15
|
+
import GroupsCollection from "passbolt-styleguide/src/shared/models/entity/group/groupsCollection";
|
|
16
|
+
import GroupEntity from "passbolt-styleguide/src/shared/models/entity/group/groupEntity";
|
|
17
17
|
import AccountEntity from "../../model/entity/account/accountEntity";
|
|
18
18
|
|
|
19
19
|
export const GROUP_LOCAL_STORAGE_KEY = "groups";
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
import { defaultGroupDto } from "passbolt-styleguide/src/shared/models/entity/group/groupEntity.test.data";
|
|
15
15
|
import AccountEntity from "../../model/entity/account/accountEntity";
|
|
16
16
|
import { defaultAccountDto } from "../../model/entity/account/accountEntity.test.data";
|
|
17
|
-
import GroupsCollection from "
|
|
18
|
-
import { defaultGroupsDtos } from "
|
|
17
|
+
import GroupsCollection from "passbolt-styleguide/src/shared/models/entity/group/groupsCollection";
|
|
18
|
+
import { defaultGroupsDtos } from "passbolt-styleguide/src/shared/models/entity/group/groupsCollection.test.data";
|
|
19
19
|
import GroupLocalStorage from "./groupLocalStorage";
|
|
20
|
-
import GroupEntity from "
|
|
20
|
+
import GroupEntity from "passbolt-styleguide/src/shared/models/entity/group/groupEntity";
|
|
21
21
|
|
|
22
22
|
beforeEach(() => {
|
|
23
23
|
jest.clearAllMocks();
|
|
@@ -12,14 +12,27 @@
|
|
|
12
12
|
* @since 2.13.0
|
|
13
13
|
*/
|
|
14
14
|
import Log from "../../model/log";
|
|
15
|
-
import UserEntity from "
|
|
16
|
-
import UsersCollection from "
|
|
17
|
-
import Lock from "../../utils/lock";
|
|
18
|
-
const lock = new Lock();
|
|
15
|
+
import UserEntity from "passbolt-styleguide/src/shared/models/entity/user/userEntity";
|
|
16
|
+
import UsersCollection from "passbolt-styleguide/src/shared/models/entity/user/usersCollection";
|
|
19
17
|
|
|
20
18
|
const USER_LOCAL_STORAGE_KEY = "users";
|
|
21
19
|
|
|
22
20
|
class UserLocalStorage {
|
|
21
|
+
/**
|
|
22
|
+
* Runtime cached data.
|
|
23
|
+
* @type {Array|null}
|
|
24
|
+
* @private
|
|
25
|
+
*/
|
|
26
|
+
static _runtimeCachedData = null;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Check if there is cached data.
|
|
30
|
+
* @returns {boolean}
|
|
31
|
+
*/
|
|
32
|
+
static hasCachedData() {
|
|
33
|
+
return UserLocalStorage._runtimeCachedData !== null && UserLocalStorage._runtimeCachedData !== undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
23
36
|
/**
|
|
24
37
|
* Flush the users local storage
|
|
25
38
|
*
|
|
@@ -27,40 +40,50 @@ class UserLocalStorage {
|
|
|
27
40
|
* @return {Promise<void>}
|
|
28
41
|
*/
|
|
29
42
|
static async flush() {
|
|
43
|
+
UserLocalStorage._runtimeCachedData = null;
|
|
30
44
|
Log.write({ level: "debug", message: "UserLocalStorage flushed" });
|
|
31
45
|
return await browser.storage.local.remove(UserLocalStorage.USER_LOCAL_STORAGE_KEY);
|
|
32
46
|
}
|
|
33
47
|
|
|
34
48
|
/**
|
|
35
|
-
*
|
|
49
|
+
* Get the users from the local storage.
|
|
36
50
|
*
|
|
37
51
|
* @throws {Error} if operation failed
|
|
38
52
|
* @return {Promise} results object, containing every object in keys that was found in the storage area.
|
|
39
53
|
* If storage is not set, undefined will be returned.
|
|
40
54
|
*/
|
|
41
55
|
static async get() {
|
|
56
|
+
if (UserLocalStorage._runtimeCachedData) {
|
|
57
|
+
return UserLocalStorage._runtimeCachedData;
|
|
58
|
+
}
|
|
42
59
|
const { users } = await browser.storage.local.get([UserLocalStorage.USER_LOCAL_STORAGE_KEY]);
|
|
43
|
-
|
|
60
|
+
if (!users) {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
UserLocalStorage._runtimeCachedData = users;
|
|
64
|
+
return UserLocalStorage._runtimeCachedData;
|
|
44
65
|
}
|
|
45
66
|
|
|
46
67
|
/**
|
|
47
68
|
* Set the users local storage.
|
|
48
69
|
*
|
|
49
70
|
* @param {UsersCollection} usersCollection The users to insert in the local storage.
|
|
50
|
-
* @return {void}
|
|
71
|
+
* @return {Promise<void>}
|
|
51
72
|
*/
|
|
52
73
|
static async set(usersCollection) {
|
|
53
|
-
await lock.acquire();
|
|
54
|
-
const users = [];
|
|
55
74
|
if (!(usersCollection instanceof UsersCollection)) {
|
|
56
75
|
throw new TypeError("UserLocalStorage::set expects a UsersCollection");
|
|
57
76
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
users
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
77
|
+
|
|
78
|
+
await navigator.locks.request(USER_LOCAL_STORAGE_KEY, async () => {
|
|
79
|
+
const users = [];
|
|
80
|
+
for (const userEntity of usersCollection) {
|
|
81
|
+
UserLocalStorage.assertEntityBeforeSave(userEntity);
|
|
82
|
+
users.push(userEntity.toDto(UserLocalStorage.DEFAULT_CONTAIN));
|
|
83
|
+
}
|
|
84
|
+
await browser.storage.local.set({ users: users });
|
|
85
|
+
UserLocalStorage._runtimeCachedData = users;
|
|
86
|
+
});
|
|
64
87
|
}
|
|
65
88
|
|
|
66
89
|
/**
|
|
@@ -77,30 +100,35 @@ class UserLocalStorage {
|
|
|
77
100
|
/**
|
|
78
101
|
* Add a user in the local storage
|
|
79
102
|
* @param {UserEntity} userEntity
|
|
103
|
+
* @throws {TypeError} If parameter userEntity is not of type UserEntity.
|
|
80
104
|
*/
|
|
81
105
|
static async addUser(userEntity) {
|
|
82
|
-
|
|
83
|
-
|
|
106
|
+
if (!userEntity || !(userEntity instanceof UserEntity)) {
|
|
107
|
+
throw new TypeError("UserLocalStorage expects an object of type UserEntity");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
await navigator.locks.request(USER_LOCAL_STORAGE_KEY, async () => {
|
|
84
111
|
UserLocalStorage.assertEntityBeforeSave(userEntity);
|
|
85
112
|
const users = await UserLocalStorage.get();
|
|
86
113
|
users.push(userEntity.toDto(UserLocalStorage.DEFAULT_CONTAIN));
|
|
87
114
|
await browser.storage.local.set({ users: users });
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
lock.release();
|
|
91
|
-
throw error;
|
|
92
|
-
}
|
|
115
|
+
UserLocalStorage._runtimeCachedData = users;
|
|
116
|
+
});
|
|
93
117
|
}
|
|
94
118
|
|
|
95
119
|
/**
|
|
96
120
|
* Update a user in the local storage.
|
|
97
121
|
*
|
|
98
122
|
* @param {UserEntity} userEntity The user to update
|
|
123
|
+
* @throws {TypeError} If parameter userEntity is not of type UserEntity.
|
|
99
124
|
* @throws {Error} if the user does not exist in the local storage
|
|
100
125
|
*/
|
|
101
126
|
static async updateUser(userEntity) {
|
|
102
|
-
|
|
103
|
-
|
|
127
|
+
if (!userEntity || !(userEntity instanceof UserEntity)) {
|
|
128
|
+
throw new TypeError("UserLocalStorage expects an object of type UserEntity");
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
await navigator.locks.request(USER_LOCAL_STORAGE_KEY, async () => {
|
|
104
132
|
UserLocalStorage.assertEntityBeforeSave(userEntity);
|
|
105
133
|
const users = await UserLocalStorage.get();
|
|
106
134
|
// If the local storage has been already initialized.
|
|
@@ -111,12 +139,9 @@ class UserLocalStorage {
|
|
|
111
139
|
}
|
|
112
140
|
users[userIndex] = Object.assign(users[userIndex], userEntity.toDto(UserLocalStorage.DEFAULT_CONTAIN));
|
|
113
141
|
await browser.storage.local.set({ users: users });
|
|
142
|
+
UserLocalStorage._runtimeCachedData = users;
|
|
114
143
|
}
|
|
115
|
-
|
|
116
|
-
} catch (error) {
|
|
117
|
-
lock.release();
|
|
118
|
-
throw error;
|
|
119
|
-
}
|
|
144
|
+
});
|
|
120
145
|
}
|
|
121
146
|
|
|
122
147
|
/**
|
|
@@ -124,8 +149,7 @@ class UserLocalStorage {
|
|
|
124
149
|
* @param {string} userId user uuid
|
|
125
150
|
*/
|
|
126
151
|
static async delete(userId) {
|
|
127
|
-
await
|
|
128
|
-
try {
|
|
152
|
+
await navigator.locks.request(USER_LOCAL_STORAGE_KEY, async () => {
|
|
129
153
|
const users = await UserLocalStorage.get();
|
|
130
154
|
if (users) {
|
|
131
155
|
const userIndex = users.findIndex((item) => item.id === userId);
|
|
@@ -133,12 +157,9 @@ class UserLocalStorage {
|
|
|
133
157
|
users.splice(userIndex, 1);
|
|
134
158
|
}
|
|
135
159
|
await browser.storage.local.set({ users: users });
|
|
136
|
-
|
|
160
|
+
UserLocalStorage._runtimeCachedData = users;
|
|
137
161
|
}
|
|
138
|
-
}
|
|
139
|
-
lock.release();
|
|
140
|
-
throw error;
|
|
141
|
-
}
|
|
162
|
+
});
|
|
142
163
|
}
|
|
143
164
|
|
|
144
165
|
/**
|