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,282 @@
|
|
|
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 { defaultUserDto } from "passbolt-styleguide/src/shared/models/entity/user/userEntity.test.data";
|
|
15
|
+
import { defaultUsersDtos } from "passbolt-styleguide/src/shared/models/entity/user/usersCollection.test.data";
|
|
16
|
+
import UsersCollection from "passbolt-styleguide/src/shared/models/entity/user/usersCollection";
|
|
17
|
+
import UserEntity from "../../model/entity/user/userEntity";
|
|
18
|
+
import UserLocalStorage from "./userLocalStorage";
|
|
19
|
+
|
|
20
|
+
beforeEach(async () => {
|
|
21
|
+
jest.clearAllMocks();
|
|
22
|
+
await UserLocalStorage.flush();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe("UserLocalStorage", () => {
|
|
26
|
+
describe("::hasCachedData", () => {
|
|
27
|
+
it("should return false if there is no cached data", () => {
|
|
28
|
+
expect.assertions(1);
|
|
29
|
+
UserLocalStorage._runtimeCachedData = null;
|
|
30
|
+
expect(UserLocalStorage.hasCachedData()).toBe(false);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("should return false if the cached data is undefined", () => {
|
|
34
|
+
expect.assertions(1);
|
|
35
|
+
UserLocalStorage._runtimeCachedData = undefined;
|
|
36
|
+
expect(UserLocalStorage.hasCachedData()).toBe(false);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("should return true if there is cached data", () => {
|
|
40
|
+
expect.assertions(1);
|
|
41
|
+
UserLocalStorage._runtimeCachedData = [defaultUserDto()];
|
|
42
|
+
expect(UserLocalStorage.hasCachedData()).toBe(true);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
describe("::flush", () => {
|
|
47
|
+
it("flushes works with not initialized local storage.", async () => {
|
|
48
|
+
expect.assertions(2);
|
|
49
|
+
await UserLocalStorage.flush();
|
|
50
|
+
// Expect the local storage (mocked here) to not be set.
|
|
51
|
+
expect(browser.storage.local.store[UserLocalStorage.USER_LOCAL_STORAGE_KEY]).toBeUndefined();
|
|
52
|
+
// Expect the runtime cache to not be set.
|
|
53
|
+
expect(UserLocalStorage._runtimeCachedData).toBeNull();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("flushes local storage's content.", async () => {
|
|
57
|
+
expect.assertions(2);
|
|
58
|
+
const dtos = defaultUsersDtos();
|
|
59
|
+
const collection = new UsersCollection(dtos);
|
|
60
|
+
await UserLocalStorage.set(collection);
|
|
61
|
+
await UserLocalStorage.flush();
|
|
62
|
+
// Expect the local storage (mocked here) to not be set.
|
|
63
|
+
expect(browser.storage.local.store[UserLocalStorage.USER_LOCAL_STORAGE_KEY]).toBeUndefined();
|
|
64
|
+
// Expect the runtime cache to not be set.
|
|
65
|
+
expect(UserLocalStorage._runtimeCachedData).toBeNull();
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe("::get", () => {
|
|
70
|
+
it("returns undefined if nothing is stored in the local storage.", async () => {
|
|
71
|
+
expect.assertions(1);
|
|
72
|
+
const result = await UserLocalStorage.get();
|
|
73
|
+
expect(result).toBeUndefined();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("returns content stored in the local storage.", async () => {
|
|
77
|
+
expect.assertions(1);
|
|
78
|
+
const collectionDto = defaultUsersDtos();
|
|
79
|
+
browser.storage.local.set({ [UserLocalStorage.USER_LOCAL_STORAGE_KEY]: collectionDto });
|
|
80
|
+
const result = await UserLocalStorage.get();
|
|
81
|
+
expect(result).toEqual(collectionDto);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("returns content stored in the runtime cache.", async () => {
|
|
85
|
+
expect.assertions(2);
|
|
86
|
+
const collectionDto = defaultUsersDtos();
|
|
87
|
+
// Force the runtime cache, to ensure it is hit even if the local storage is empty.
|
|
88
|
+
UserLocalStorage._runtimeCachedData = collectionDto;
|
|
89
|
+
const result = await UserLocalStorage.get();
|
|
90
|
+
expect(result).toEqual(collectionDto);
|
|
91
|
+
// Control the local storage was well empty.
|
|
92
|
+
expect(browser.storage.local.store[UserLocalStorage.USER_LOCAL_STORAGE_KEY]).toBeUndefined();
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
describe("::set", () => {
|
|
97
|
+
it("stores content in the local storage.", async () => {
|
|
98
|
+
expect.assertions(3);
|
|
99
|
+
const dtos = defaultUsersDtos();
|
|
100
|
+
const collection = new UsersCollection(dtos);
|
|
101
|
+
await UserLocalStorage.set(collection);
|
|
102
|
+
// Expect the local storage (mocked here) to be set.
|
|
103
|
+
expect(browser.storage.local.store[UserLocalStorage.USER_LOCAL_STORAGE_KEY]).toBeDefined();
|
|
104
|
+
// Expect the runtime cache to be set.
|
|
105
|
+
expect(UserLocalStorage._runtimeCachedData).toBeDefined();
|
|
106
|
+
// Expect the get to retrieve the set data.
|
|
107
|
+
const resultGet = await UserLocalStorage.get();
|
|
108
|
+
expect(resultGet).toHaveLength(dtos.length);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("throws error if no data is given to store.", async () => {
|
|
112
|
+
expect.assertions(3);
|
|
113
|
+
await expect(() => UserLocalStorage.set()).rejects.toThrow(TypeError);
|
|
114
|
+
// Expect the local storage (mocked here) to not be set.
|
|
115
|
+
expect(browser.storage.local.store[UserLocalStorage.USER_LOCAL_STORAGE_KEY]).toBeUndefined();
|
|
116
|
+
// Expect the runtime cache to not be set.
|
|
117
|
+
expect(UserLocalStorage._runtimeCachedData).toBeNull();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("throws error if invalid data is given to store.", async () => {
|
|
121
|
+
expect.assertions(3);
|
|
122
|
+
await expect(() => UserLocalStorage.set({})).rejects.toThrow(TypeError);
|
|
123
|
+
// Expect the local storage (mocked here) to not be set.
|
|
124
|
+
expect(browser.storage.local.store[UserLocalStorage.USER_LOCAL_STORAGE_KEY]).toBeUndefined();
|
|
125
|
+
// Expect the runtime cache to not be set.
|
|
126
|
+
expect(UserLocalStorage._runtimeCachedData).toBeNull();
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
describe("::getUserById", () => {
|
|
131
|
+
it("returns a user by its id.", async () => {
|
|
132
|
+
expect.assertions(1);
|
|
133
|
+
const collectionDto = defaultUsersDtos();
|
|
134
|
+
const firstUserDto = collectionDto[0];
|
|
135
|
+
browser.storage.local.set({ [UserLocalStorage.USER_LOCAL_STORAGE_KEY]: collectionDto });
|
|
136
|
+
const result = await UserLocalStorage.getUserById(firstUserDto.id);
|
|
137
|
+
expect(result).toEqual(firstUserDto);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
describe("::addUser", () => {
|
|
142
|
+
it("adds a user to local storage.", async () => {
|
|
143
|
+
expect.assertions(2);
|
|
144
|
+
const collectionDto = defaultUsersDtos();
|
|
145
|
+
browser.storage.local.set({ [UserLocalStorage.USER_LOCAL_STORAGE_KEY]: collectionDto });
|
|
146
|
+
|
|
147
|
+
const newUserDto = defaultUserDto();
|
|
148
|
+
const newUserEntity = new UserEntity(newUserDto);
|
|
149
|
+
await UserLocalStorage.addUser(newUserEntity);
|
|
150
|
+
const result = await UserLocalStorage.getUserById(newUserDto.id);
|
|
151
|
+
expect(result).toBeDefined();
|
|
152
|
+
expect(collectionDto.length).toEqual(11);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("throws error when parameter is not a UserEntity.", async () => {
|
|
156
|
+
expect.assertions(2);
|
|
157
|
+
const collectionDto = defaultUsersDtos();
|
|
158
|
+
browser.storage.local.set({ [UserLocalStorage.USER_LOCAL_STORAGE_KEY]: collectionDto });
|
|
159
|
+
|
|
160
|
+
await expect(UserLocalStorage.addUser()).rejects.toThrow("UserLocalStorage expects an object of type UserEntity");
|
|
161
|
+
await expect(UserLocalStorage.addUser({})).rejects.toThrow(
|
|
162
|
+
"UserLocalStorage expects an object of type UserEntity",
|
|
163
|
+
);
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
describe("::updateUser", () => {
|
|
168
|
+
it("updates a user in local storage.", async () => {
|
|
169
|
+
expect.assertions(3);
|
|
170
|
+
const collectionDto = defaultUsersDtos();
|
|
171
|
+
const firstUserDto = collectionDto[0];
|
|
172
|
+
const secondUserDto = collectionDto[2];
|
|
173
|
+
|
|
174
|
+
browser.storage.local.set({ [UserLocalStorage.USER_LOCAL_STORAGE_KEY]: collectionDto });
|
|
175
|
+
let result = await UserLocalStorage.getUserById(firstUserDto.id);
|
|
176
|
+
expect(result).toEqual(firstUserDto);
|
|
177
|
+
|
|
178
|
+
// Modify the first user username and update
|
|
179
|
+
firstUserDto.username = "modified@passbolt.com";
|
|
180
|
+
const userEntity = new UserEntity(firstUserDto);
|
|
181
|
+
await UserLocalStorage.updateUser(userEntity);
|
|
182
|
+
|
|
183
|
+
result = await UserLocalStorage.getUserById(firstUserDto.id);
|
|
184
|
+
expect(result.username).toEqual("modified@passbolt.com");
|
|
185
|
+
|
|
186
|
+
// Ensure the second user hasn't been modified
|
|
187
|
+
result = await UserLocalStorage.getUserById(secondUserDto.id);
|
|
188
|
+
expect(result).toEqual(secondUserDto);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it("throws error when updating a user not in local storage.", async () => {
|
|
192
|
+
expect.assertions(1);
|
|
193
|
+
const collectionDto = defaultUsersDtos();
|
|
194
|
+
const unknownUserDto = defaultUserDto();
|
|
195
|
+
|
|
196
|
+
browser.storage.local.set({ [UserLocalStorage.USER_LOCAL_STORAGE_KEY]: collectionDto });
|
|
197
|
+
const userEntity = new UserEntity(unknownUserDto);
|
|
198
|
+
await expect(UserLocalStorage.updateUser(userEntity)).rejects.toThrow(
|
|
199
|
+
"The user could not be found in the local storage",
|
|
200
|
+
);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it("throws error when the userEntity parameter is not defined or not a UserEntity.", async () => {
|
|
204
|
+
expect.assertions(2);
|
|
205
|
+
const collectionDto = defaultUsersDtos();
|
|
206
|
+
browser.storage.local.set({ [UserLocalStorage.USER_LOCAL_STORAGE_KEY]: collectionDto });
|
|
207
|
+
|
|
208
|
+
await expect(UserLocalStorage.updateUser()).rejects.toThrow(
|
|
209
|
+
"UserLocalStorage expects an object of type UserEntity",
|
|
210
|
+
);
|
|
211
|
+
await expect(UserLocalStorage.updateUser({})).rejects.toThrow(
|
|
212
|
+
"UserLocalStorage expects an object of type UserEntity",
|
|
213
|
+
);
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
describe("::delete", () => {
|
|
218
|
+
it("deletes a user from local storage.", async () => {
|
|
219
|
+
expect.assertions(5);
|
|
220
|
+
const collectionDto = defaultUsersDtos();
|
|
221
|
+
const firstUserDto = collectionDto[0];
|
|
222
|
+
const secondUserDto = collectionDto[2];
|
|
223
|
+
|
|
224
|
+
browser.storage.local.set({ [UserLocalStorage.USER_LOCAL_STORAGE_KEY]: collectionDto });
|
|
225
|
+
let result = await UserLocalStorage.getUserById(firstUserDto.id);
|
|
226
|
+
expect(result).toEqual(firstUserDto);
|
|
227
|
+
expect(collectionDto.length).toEqual(10);
|
|
228
|
+
|
|
229
|
+
await UserLocalStorage.delete(firstUserDto.id);
|
|
230
|
+
result = await UserLocalStorage.getUserById(firstUserDto.id);
|
|
231
|
+
expect(result).toBeUndefined();
|
|
232
|
+
expect(collectionDto.length).toEqual(9);
|
|
233
|
+
|
|
234
|
+
// Ensure the second user hasn't been modified
|
|
235
|
+
result = await UserLocalStorage.getUserById(secondUserDto.id);
|
|
236
|
+
expect(result).toEqual(secondUserDto);
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
describe("::assertEntityBeforeSave", () => {
|
|
241
|
+
it("doesn't throw an error if the entity is a valid UserEntity.", () => {
|
|
242
|
+
expect.assertions(1);
|
|
243
|
+
const userDto = defaultUserDto();
|
|
244
|
+
const userEntity = new UserEntity(userDto);
|
|
245
|
+
expect(() => UserLocalStorage.assertEntityBeforeSave(userEntity)).not.toThrow();
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it("throws an error if the entity is not set.", () => {
|
|
249
|
+
expect.assertions(1);
|
|
250
|
+
expect(() => UserLocalStorage.assertEntityBeforeSave()).toThrow(
|
|
251
|
+
"UserLocalStorage expects a UserEntity to be set",
|
|
252
|
+
);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it("throws an error if the entity is not a UserEntity.", () => {
|
|
256
|
+
expect.assertions(1);
|
|
257
|
+
expect(() => UserLocalStorage.assertEntityBeforeSave({})).toThrow(
|
|
258
|
+
"UserLocalStorage expects an object of type UserEntity",
|
|
259
|
+
);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it("throws an error if the entity id is not set.", () => {
|
|
263
|
+
expect.assertions(1);
|
|
264
|
+
const userDto = defaultUserDto();
|
|
265
|
+
const userEntity = new UserEntity(userDto);
|
|
266
|
+
userEntity._props.id = null;
|
|
267
|
+
expect(() => UserLocalStorage.assertEntityBeforeSave(userEntity)).toThrow(
|
|
268
|
+
"UserLocalStorage expects UserEntity id to be set",
|
|
269
|
+
);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it("throws an error if the entity profile is not set.", () => {
|
|
273
|
+
expect.assertions(1);
|
|
274
|
+
const userDto = defaultUserDto();
|
|
275
|
+
const userEntity = new UserEntity(userDto);
|
|
276
|
+
delete userEntity._profile;
|
|
277
|
+
expect(() => UserLocalStorage.assertEntityBeforeSave(userEntity)).toThrow(
|
|
278
|
+
"UserLocalStorage::set expects UserEntity profile to be set",
|
|
279
|
+
);
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
});
|
|
@@ -21,7 +21,7 @@ import { OpenpgpAssertion } from "../../utils/openpgp/openpgpAssertions";
|
|
|
21
21
|
import { pgpKeys } from "passbolt-styleguide/test/fixture/pgpKeys/keys";
|
|
22
22
|
import MetadataKeyEntity from "passbolt-styleguide/src/shared/models/entity/metadata/metadataKeyEntity";
|
|
23
23
|
import ExternalGpgKeyPairEntity from "passbolt-styleguide/src/shared/models/entity/gpgkey/external/externalGpgKeyPairEntity";
|
|
24
|
-
import UsersCollection from "
|
|
24
|
+
import UsersCollection from "passbolt-styleguide/src/shared/models/entity/user/usersCollection";
|
|
25
25
|
import { users } from "passbolt-styleguide/src/shared/models/entity/user/userEntity.test.data";
|
|
26
26
|
import MetadataKeysSettingsEntity from "passbolt-styleguide/src/shared/models/entity/metadata/metadataKeysSettingsEntity";
|
|
27
27
|
import { defaultMetadataKeysSettingsDto } from "passbolt-styleguide/src/shared/models/entity/metadata/metadataKeysSettingsEntity.test.data";
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
} from "passbolt-styleguide/src/shared/models/entity/metadata/metadataTypesSettingsEntity.test.data";
|
|
24
24
|
import { defaultMetadataKeysSettingsDto } from "passbolt-styleguide/src/shared/models/entity/metadata/metadataKeysSettingsEntity.test.data";
|
|
25
25
|
import MetadataKeysSettingsEntity from "passbolt-styleguide/src/shared/models/entity/metadata/metadataKeysSettingsEntity";
|
|
26
|
-
import UsersCollection from "
|
|
26
|
+
import UsersCollection from "passbolt-styleguide/src/shared/models/entity/user/usersCollection";
|
|
27
27
|
import {
|
|
28
28
|
defaultMetadataKeyDto,
|
|
29
29
|
metadataKeyWithSignedMetadataPrivateKeyDataDto,
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
usersWithoutMissingMetadataKeysDto,
|
|
26
26
|
} from "./shareMetadataKeyPrivateService.test.data";
|
|
27
27
|
import RoleEntity from "passbolt-styleguide/src/shared/models/entity/role/roleEntity";
|
|
28
|
-
import UsersCollection from "
|
|
28
|
+
import UsersCollection from "passbolt-styleguide/src/shared/models/entity/user/usersCollection";
|
|
29
29
|
import MetadataKeysCollection from "passbolt-styleguide/src/shared/models/entity/metadata/metadataKeysCollection";
|
|
30
30
|
import { OpenpgpAssertion } from "../../utils/openpgp/openpgpAssertions";
|
|
31
31
|
import Keyring from "../../model/keyring";
|
|
@@ -18,7 +18,7 @@ import EncryptMetadataService from "../metadata/encryptMetadataService";
|
|
|
18
18
|
import { V4_TO_V5_RESOURCE_TYPE_MAPPING } from "passbolt-styleguide/src/shared/models/entity/resourceType/resourceTypeSchemasDefinition";
|
|
19
19
|
import ResourceEntity from "../../model/entity/resource/resourceEntity";
|
|
20
20
|
import i18n from "../../sdk/i18n";
|
|
21
|
-
import PermissionEntity from "
|
|
21
|
+
import PermissionEntity from "passbolt-styleguide/src/shared/models/entity/permission/permissionEntity";
|
|
22
22
|
|
|
23
23
|
const MAX_PROCESS_REPLAY = 3;
|
|
24
24
|
|
|
@@ -0,0 +1,113 @@
|
|
|
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 PermissionChangesCollection from "../../model/entity/permission/change/permissionChangesCollection";
|
|
15
|
+
import PermissionEntity from "passbolt-styleguide/src/shared/models/entity/permission/permissionEntity";
|
|
16
|
+
import PermissionsCollection from "passbolt-styleguide/src/shared/models/entity/permission/permissionsCollection";
|
|
17
|
+
|
|
18
|
+
class CalculatePermissionsChangesForMoveService {
|
|
19
|
+
/**
|
|
20
|
+
* Calculate permission changes when a folder moves from parentFolder to destFolder.
|
|
21
|
+
* From current permissions, remove the parent folder permissions, add the destination permissions.
|
|
22
|
+
* From this new set of permissions and the original permissions, calculate the needed changes.
|
|
23
|
+
*
|
|
24
|
+
* NOTE: This function requires permissions to be set for all objects.
|
|
25
|
+
*
|
|
26
|
+
* @param {FolderEntity} folderEntity
|
|
27
|
+
* @param {(FolderEntity|null)} parentFolder
|
|
28
|
+
* @param {(FolderEntity|null)} destFolder
|
|
29
|
+
* @returns {PermissionChangesCollection}
|
|
30
|
+
*/
|
|
31
|
+
static forFolder(folderEntity, parentFolder, destFolder) {
|
|
32
|
+
return CalculatePermissionsChangesForMoveService._calculate(
|
|
33
|
+
folderEntity,
|
|
34
|
+
parentFolder,
|
|
35
|
+
destFolder,
|
|
36
|
+
PermissionEntity.ACO_FOLDER,
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Calculate permission changes when a resource moves from parentFolder to destFolder.
|
|
42
|
+
* From current permissions, remove the parent folder permissions, add the destination permissions.
|
|
43
|
+
* From this new set of permissions and the original permissions, calculate the needed changes.
|
|
44
|
+
*
|
|
45
|
+
* NOTE: This function requires permissions to be set for all objects.
|
|
46
|
+
*
|
|
47
|
+
* @param {ResourceEntity} resource
|
|
48
|
+
* @param {(FolderEntity|null)} parentFolder
|
|
49
|
+
* @param {(FolderEntity|null)} destFolder
|
|
50
|
+
* @returns {PermissionChangesCollection}
|
|
51
|
+
*/
|
|
52
|
+
static forResource(resource, parentFolder, destFolder) {
|
|
53
|
+
return CalculatePermissionsChangesForMoveService._calculate(
|
|
54
|
+
resource,
|
|
55
|
+
parentFolder,
|
|
56
|
+
destFolder,
|
|
57
|
+
PermissionEntity.ACO_RESOURCE,
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Shared permission-change calculation for `forFolder` and `forResource`.
|
|
63
|
+
* Removes the parent folder permissions from the entity, adds the destination folder permissions,
|
|
64
|
+
* and returns the changes against the entity's original permissions. When moving to the root,
|
|
65
|
+
* the highest permission on the entity is preserved.
|
|
66
|
+
*
|
|
67
|
+
* @param {FolderEntity|ResourceEntity} entity The folder or resource being moved.
|
|
68
|
+
* @param {(FolderEntity|null)} parentFolder The current parent folder, or null if moving from the root.
|
|
69
|
+
* @param {(FolderEntity|null)} destFolder The destination folder, or null if moving to the root.
|
|
70
|
+
* @param {string} aco One of `PermissionEntity.ACO_FOLDER` or `PermissionEntity.ACO_RESOURCE`; not exposed on the public callers, which hardcode the value matching the entity type.
|
|
71
|
+
* @returns {PermissionChangesCollection}
|
|
72
|
+
* @private
|
|
73
|
+
*/
|
|
74
|
+
static _calculate(entity, parentFolder, destFolder, aco) {
|
|
75
|
+
let remainingPermissions = new PermissionsCollection([], { assertAtLeastOneOwner: false });
|
|
76
|
+
|
|
77
|
+
// Remove permissions from parent if any
|
|
78
|
+
if (parentFolder) {
|
|
79
|
+
if (!entity.permissions || !parentFolder.permissions) {
|
|
80
|
+
throw new TypeError("CalculatePermissionsChangesForMoveService requires permissions to be set.");
|
|
81
|
+
}
|
|
82
|
+
remainingPermissions = PermissionsCollection.diff(entity.permissions, parentFolder.permissions, false);
|
|
83
|
+
}
|
|
84
|
+
// Add destination permissions
|
|
85
|
+
let permissionsFromParent = new PermissionsCollection([], { assertAtLeastOneOwner: false });
|
|
86
|
+
if (destFolder) {
|
|
87
|
+
if (!destFolder.permissions) {
|
|
88
|
+
throw new TypeError("CalculatePermissionsChangesForMoveService requires destination permissions to be set.");
|
|
89
|
+
}
|
|
90
|
+
permissionsFromParent = destFolder.permissions.cloneForAco(aco, entity.id, false);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const newPermissions = PermissionsCollection.sum(remainingPermissions, permissionsFromParent, false);
|
|
94
|
+
if (!destFolder) {
|
|
95
|
+
/*
|
|
96
|
+
* If the move is toward the root, reuse highest permission.
|
|
97
|
+
*/
|
|
98
|
+
newPermissions.addOrReplace(
|
|
99
|
+
new PermissionEntity({
|
|
100
|
+
aco: aco,
|
|
101
|
+
aco_foreign_key: entity.id,
|
|
102
|
+
aro: entity.permission.aro,
|
|
103
|
+
aro_foreign_key: entity.permission.aroForeignKey,
|
|
104
|
+
type: PermissionEntity.PERMISSION_OWNER,
|
|
105
|
+
}),
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
newPermissions.assertAtLeastOneOwner();
|
|
109
|
+
return PermissionChangesCollection.calculateChanges(entity.permissions, newPermissions);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export default CalculatePermissionsChangesForMoveService;
|
package/src/all/background_page/service/move/calculatePermissionsChangesForMoveService.test.data.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
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 { v4 as uuidv4 } from "uuid";
|
|
15
|
+
import FolderEntity from "../../model/entity/folder/folderEntity";
|
|
16
|
+
import ResourceEntity from "../../model/entity/resource/resourceEntity";
|
|
17
|
+
import { defaultFolderDto } from "passbolt-styleguide/src/shared/models/entity/folder/folderEntity.test.data";
|
|
18
|
+
import { defaultResourceDto } from "passbolt-styleguide/src/shared/models/entity/resource/resourceEntity.test.data";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Build a FolderEntity whose ACL is the given `permissions` list.
|
|
22
|
+
* Each permission's `aco_foreign_key` is auto-bound to the folder id.
|
|
23
|
+
*/
|
|
24
|
+
export const buildFolder = (permissions) => {
|
|
25
|
+
const id = uuidv4();
|
|
26
|
+
const bound = permissions.map((p) => ({ ...p, aco_foreign_key: id }));
|
|
27
|
+
return new FolderEntity(defaultFolderDto({ id, permission: bound[0], permissions: bound }));
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Build a ResourceEntity whose ACL is the given `permissions` list.
|
|
32
|
+
* Each permission's `aco_foreign_key` is auto-bound to the resource id.
|
|
33
|
+
*/
|
|
34
|
+
export const buildResource = (permissions) => {
|
|
35
|
+
const id = uuidv4();
|
|
36
|
+
const bound = permissions.map((p) => ({ ...p, aco_foreign_key: id }));
|
|
37
|
+
return new ResourceEntity(defaultResourceDto({ id, permission: bound[0], permissions: bound }));
|
|
38
|
+
};
|
package/src/all/background_page/service/move/calculatePermissionsChangesForMoveService.test.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
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 CalculatePermissionsChangesForMoveService from "./calculatePermissionsChangesForMoveService";
|
|
15
|
+
import FolderEntity from "../../model/entity/folder/folderEntity";
|
|
16
|
+
import ResourceEntity from "../../model/entity/resource/resourceEntity";
|
|
17
|
+
import PermissionEntity from "passbolt-styleguide/src/shared/models/entity/permission/permissionEntity";
|
|
18
|
+
import { defaultFolderDto } from "passbolt-styleguide/src/shared/models/entity/folder/folderEntity.test.data";
|
|
19
|
+
import { defaultResourceDto } from "passbolt-styleguide/src/shared/models/entity/resource/resourceEntity.test.data";
|
|
20
|
+
import {
|
|
21
|
+
ownerFolderPermissionDto,
|
|
22
|
+
ownerPermissionDto,
|
|
23
|
+
readFolderPermissionDto,
|
|
24
|
+
readPermissionDto,
|
|
25
|
+
} from "passbolt-styleguide/src/shared/models/entity/permission/permissionEntity.test.data";
|
|
26
|
+
import { v4 as uuidv4 } from "uuid";
|
|
27
|
+
import { buildFolder, buildResource } from "./calculatePermissionsChangesForMoveService.test.data";
|
|
28
|
+
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
jest.clearAllMocks();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe("CalculatePermissionsChangesForMoveService", () => {
|
|
34
|
+
const owner = uuidv4();
|
|
35
|
+
const extra = uuidv4();
|
|
36
|
+
|
|
37
|
+
describe("::forFolder", () => {
|
|
38
|
+
it("should emit no changes when moving between folders with identical ACLs", () => {
|
|
39
|
+
expect.assertions(1);
|
|
40
|
+
const folder = buildFolder([ownerFolderPermissionDto({ aro_foreign_key: owner })]);
|
|
41
|
+
const parent = buildFolder([ownerFolderPermissionDto({ aro_foreign_key: owner })]);
|
|
42
|
+
const dest = buildFolder([ownerFolderPermissionDto({ aro_foreign_key: owner })]);
|
|
43
|
+
|
|
44
|
+
const changes = CalculatePermissionsChangesForMoveService.forFolder(folder, parent, dest);
|
|
45
|
+
|
|
46
|
+
expect(changes.length).toBe(0);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("should emit a change when destination has an additional aro", () => {
|
|
50
|
+
expect.assertions(3);
|
|
51
|
+
const folder = buildFolder([ownerFolderPermissionDto({ aro_foreign_key: owner })]);
|
|
52
|
+
const parent = buildFolder([ownerFolderPermissionDto({ aro_foreign_key: owner })]);
|
|
53
|
+
const dest = buildFolder([
|
|
54
|
+
ownerFolderPermissionDto({ aro_foreign_key: owner }),
|
|
55
|
+
readFolderPermissionDto({ aro_foreign_key: extra }),
|
|
56
|
+
]);
|
|
57
|
+
|
|
58
|
+
const changes = CalculatePermissionsChangesForMoveService.forFolder(folder, parent, dest);
|
|
59
|
+
|
|
60
|
+
expect(changes.length).toBe(1);
|
|
61
|
+
expect(changes.items[0].aroForeignKey).toBe(extra);
|
|
62
|
+
expect(changes.items[0].aco).toBe(PermissionEntity.ACO_FOLDER);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("should reuse the highest user permission on move to root", () => {
|
|
66
|
+
expect.assertions(2);
|
|
67
|
+
const folder = buildFolder([
|
|
68
|
+
ownerFolderPermissionDto({ aro_foreign_key: owner }),
|
|
69
|
+
readFolderPermissionDto({ aro_foreign_key: extra }),
|
|
70
|
+
]);
|
|
71
|
+
const parent = buildFolder([
|
|
72
|
+
ownerFolderPermissionDto({ aro_foreign_key: owner }),
|
|
73
|
+
readFolderPermissionDto({ aro_foreign_key: extra }),
|
|
74
|
+
]);
|
|
75
|
+
|
|
76
|
+
const changes = CalculatePermissionsChangesForMoveService.forFolder(folder, parent, null);
|
|
77
|
+
|
|
78
|
+
expect(changes.length).toBe(1);
|
|
79
|
+
expect(changes.items[0].aroForeignKey).toBe(extra);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("should throw when source permissions are missing", () => {
|
|
83
|
+
expect.assertions(1);
|
|
84
|
+
const folder = new FolderEntity(defaultFolderDto());
|
|
85
|
+
const parent = new FolderEntity(defaultFolderDto());
|
|
86
|
+
|
|
87
|
+
expect(() => CalculatePermissionsChangesForMoveService.forFolder(folder, parent, null)).toThrow(
|
|
88
|
+
new TypeError("CalculatePermissionsChangesForMoveService requires permissions to be set."),
|
|
89
|
+
);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("should throw when destination permissions are missing", () => {
|
|
93
|
+
expect.assertions(1);
|
|
94
|
+
const folder = buildFolder([ownerFolderPermissionDto({ aro_foreign_key: owner })]);
|
|
95
|
+
const dest = new FolderEntity(defaultFolderDto());
|
|
96
|
+
|
|
97
|
+
expect(() => CalculatePermissionsChangesForMoveService.forFolder(folder, null, dest)).toThrow(
|
|
98
|
+
new TypeError("CalculatePermissionsChangesForMoveService requires destination permissions to be set."),
|
|
99
|
+
);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
describe("::forResource", () => {
|
|
104
|
+
it("should emit ACO_RESOURCE changes when destination has an additional aro", () => {
|
|
105
|
+
expect.assertions(3);
|
|
106
|
+
const resource = buildResource([ownerPermissionDto({ aro_foreign_key: owner })]);
|
|
107
|
+
const parent = buildFolder([ownerFolderPermissionDto({ aro_foreign_key: owner })]);
|
|
108
|
+
const dest = buildFolder([
|
|
109
|
+
ownerFolderPermissionDto({ aro_foreign_key: owner }),
|
|
110
|
+
readFolderPermissionDto({ aro_foreign_key: extra }),
|
|
111
|
+
]);
|
|
112
|
+
|
|
113
|
+
const changes = CalculatePermissionsChangesForMoveService.forResource(resource, parent, dest);
|
|
114
|
+
|
|
115
|
+
expect(changes.length).toBe(1);
|
|
116
|
+
expect(changes.items[0].aroForeignKey).toBe(extra);
|
|
117
|
+
expect(changes.items[0].aco).toBe(PermissionEntity.ACO_RESOURCE);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("should reuse the highest permission with ACO_RESOURCE on move to root", () => {
|
|
121
|
+
expect.assertions(3);
|
|
122
|
+
const resource = buildResource([
|
|
123
|
+
ownerPermissionDto({ aro_foreign_key: owner }),
|
|
124
|
+
readPermissionDto({ aro_foreign_key: extra }),
|
|
125
|
+
]);
|
|
126
|
+
const parent = buildFolder([
|
|
127
|
+
ownerFolderPermissionDto({ aro_foreign_key: owner }),
|
|
128
|
+
readFolderPermissionDto({ aro_foreign_key: extra }),
|
|
129
|
+
]);
|
|
130
|
+
|
|
131
|
+
const changes = CalculatePermissionsChangesForMoveService.forResource(resource, parent, null);
|
|
132
|
+
|
|
133
|
+
expect(changes.length).toBe(1);
|
|
134
|
+
expect(changes.items[0].aroForeignKey).toBe(extra);
|
|
135
|
+
expect(changes.items[0].aco).toBe(PermissionEntity.ACO_RESOURCE);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it("should throw when source permissions are missing", () => {
|
|
139
|
+
expect.assertions(1);
|
|
140
|
+
const resource = new ResourceEntity(defaultResourceDto());
|
|
141
|
+
const parent = new FolderEntity(defaultFolderDto());
|
|
142
|
+
|
|
143
|
+
expect(() => CalculatePermissionsChangesForMoveService.forResource(resource, parent, null)).toThrow(
|
|
144
|
+
new TypeError("CalculatePermissionsChangesForMoveService requires permissions to be set."),
|
|
145
|
+
);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("should throw when destination permissions are missing", () => {
|
|
149
|
+
expect.assertions(1);
|
|
150
|
+
const resource = buildResource([ownerPermissionDto({ aro_foreign_key: owner })]);
|
|
151
|
+
const dest = new FolderEntity(defaultFolderDto());
|
|
152
|
+
|
|
153
|
+
expect(() => CalculatePermissionsChangesForMoveService.forResource(resource, null, dest)).toThrow(
|
|
154
|
+
new TypeError("CalculatePermissionsChangesForMoveService requires destination permissions to be set."),
|
|
155
|
+
);
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
});
|