passbolt-browser-extension 5.3.0 → 5.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/CHANGELOG.md +30 -1
  2. package/Gruntfile.js +1 -1
  3. package/RELEASE_NOTES.md +29 -48
  4. package/package.json +5 -5
  5. package/src/all/background_page/controller/clipboard/cancelClipboardContentFlushController.js +51 -0
  6. package/src/all/background_page/controller/clipboard/cancelClipboardContentFlushController.test.js +46 -0
  7. package/src/all/background_page/controller/clipboard/copyTemporarilyToClipboardController.js +53 -0
  8. package/src/all/background_page/controller/clipboard/copyTemporarilyToClipboardController.test.js +47 -0
  9. package/src/all/background_page/controller/clipboard/{clipboardController.js → copyToClipboardController.js} +8 -8
  10. package/src/all/background_page/controller/clipboard/copyToClipboardController.test.js +47 -0
  11. package/src/all/background_page/controller/extension/getExtensionVersionController.test.js +1 -1
  12. package/src/all/background_page/controller/metadata/getOrFindMetadataKeysSettingsController.js +53 -0
  13. package/src/all/background_page/controller/metadata/getOrFindMetadataKeysSettingsController.test.js +106 -0
  14. package/src/all/background_page/controller/user/deleteDryRunUserController.js +73 -0
  15. package/src/all/background_page/controller/user/deleteDryRunUserController.test.js +129 -0
  16. package/src/all/background_page/controller/user/deleteUserController.js +76 -0
  17. package/src/all/background_page/controller/user/deleteUserController.test.js +141 -0
  18. package/src/all/background_page/event/actionLogEvents.js +5 -12
  19. package/src/all/background_page/event/appEvents.js +33 -0
  20. package/src/all/background_page/event/findAllForActionLogController.js +58 -0
  21. package/src/all/background_page/event/findAllForActionLogController.test.js +43 -0
  22. package/src/all/background_page/event/quickAccessEvents.js +32 -0
  23. package/src/all/background_page/event/userEvents.js +7 -20
  24. package/src/all/background_page/event/webIntegrationEvents.js +11 -0
  25. package/src/all/background_page/model/actionLog/{actionLogModel.js → findActionLogService.js} +25 -5
  26. package/src/all/background_page/model/actionLog/findActionLogService.test.js +61 -0
  27. package/src/all/background_page/model/comment/commentModel.js +5 -5
  28. package/src/all/background_page/model/entity/actionLog/actionLogsCollection.test.data.js +18 -0
  29. package/src/all/background_page/model/entity/actionLog/defaultActionLogEntity.test.data.js +34 -0
  30. package/src/all/background_page/model/import/resources/resourcesKdbxImportParser.test.js +0 -1
  31. package/src/all/background_page/model/user/userModel.js +0 -60
  32. package/src/all/background_page/pagemod/appPagemod.js +0 -2
  33. package/src/all/background_page/pagemod/appPagemod.test.js +2 -6
  34. package/src/all/background_page/service/alarm/globalAlarmService.js +2 -0
  35. package/src/all/background_page/service/api/actionLog/{actionLogService.js → actionLogApiService.js} +5 -4
  36. package/src/all/background_page/service/api/actionLog/actionLogApiService.test.js +55 -0
  37. package/src/all/background_page/service/api/comment/{commentService.js → commentApiService.js} +6 -7
  38. package/src/all/background_page/service/api/comment/commentApiService.test.js +122 -0
  39. package/src/all/background_page/service/auth/postLogoutService.js +2 -0
  40. package/src/all/background_page/service/auth/postLogoutService.test.js +4 -1
  41. package/src/all/background_page/service/browser/browserService.js +22 -0
  42. package/src/all/background_page/service/clipboard/clipboardProviderService.js +40 -0
  43. package/src/all/background_page/service/clipboard/clipboardProviderService.test.js +61 -0
  44. package/src/all/background_page/service/clipboard/copyToClipboardService.js +123 -0
  45. package/src/all/background_page/service/clipboard/copyToClipboardService.test.js +174 -0
  46. package/src/all/background_page/service/user/deleteUserService.js +97 -0
  47. package/src/all/background_page/service/user/deleteUserService.test.js +178 -0
  48. package/src/chrome/manifest.json +1 -1
  49. package/src/chrome/polyfill/clipboard/edgeBackgroundPageClipboardService.js +31 -0
  50. package/src/chrome/polyfill/clipboard/edgeBackgroundPageClipboardService.test.js +51 -0
  51. package/src/chrome-mv3/index.js +3 -3
  52. package/src/chrome-mv3/manifest.json +1 -1
  53. package/src/chrome-mv3/offscreens/{fetch.html → offscreen.html} +1 -1
  54. package/src/chrome-mv3/offscreens/{fetch.js → offscreen.js} +2 -2
  55. package/src/chrome-mv3/offscreens/service/clipboard/writeClipobardOffscreenService.js +54 -0
  56. package/src/chrome-mv3/offscreens/service/clipboard/writeClipobardOffscreenService.test.js +56 -0
  57. package/src/chrome-mv3/offscreens/service/network/fetchOffscreenService.js +36 -44
  58. package/src/chrome-mv3/offscreens/service/network/fetchOffscreenService.test.data.js +0 -1
  59. package/src/chrome-mv3/offscreens/service/network/fetchOffscreenService.test.js +90 -120
  60. package/src/chrome-mv3/offscreens/service/offscreen/handleOffscreenRequestService.js +85 -0
  61. package/src/chrome-mv3/offscreens/service/offscreen/handleOffscreenRequestService.test.js +99 -0
  62. package/src/chrome-mv3/polyfill/clipboardOffscreenPolyfill.js +19 -0
  63. package/src/chrome-mv3/serviceWorker/service/clipboard/requestClipboardOffscreenService.js +51 -0
  64. package/src/chrome-mv3/serviceWorker/service/clipboard/requestClipboardOffscreenService.test.js +70 -0
  65. package/src/chrome-mv3/serviceWorker/service/clipboard/responseClipboardOffscreenService.js +25 -0
  66. package/src/chrome-mv3/serviceWorker/service/clipboard/responseClipboardOffscreenService.test.data.js +21 -0
  67. package/src/chrome-mv3/serviceWorker/service/clipboard/responseClipboardOffscreenService.test.js +33 -0
  68. package/src/chrome-mv3/serviceWorker/service/network/requestFetchOffscreenService.js +25 -50
  69. package/src/chrome-mv3/serviceWorker/service/network/requestFetchOffscreenService.test.js +16 -39
  70. package/src/chrome-mv3/serviceWorker/service/network/responseFetchOffscreenService.js +14 -45
  71. package/src/chrome-mv3/serviceWorker/service/network/responseFetchOffscreenService.test.js +5 -37
  72. package/src/chrome-mv3/serviceWorker/service/offscreen/createOffscreenDocumentService.js +43 -0
  73. package/src/chrome-mv3/serviceWorker/service/offscreen/createOffscreenDocumentService.test.js +48 -0
  74. package/src/chrome-mv3/serviceWorker/service/offscreen/handleOffscreenResponseService.js +119 -0
  75. package/src/chrome-mv3/serviceWorker/service/offscreen/handleOffscreenResponseService.test.js +159 -0
  76. package/src/firefox/manifest.json +1 -1
  77. package/src/safari/manifest.json +1 -1
  78. package/test/jest.setup.js +4 -0
  79. package/test/mocks/mockNavigatorClipboard.js +40 -0
  80. package/test/mocks/mockWebExtensionPolyfill.js +2 -1
  81. package/{webpack-offscreens.fetch.config.js → webpack-offscreens.config.js} +1 -1
  82. package/webpack.service-worker.config.js +1 -0
  83. package/src/all/background_page/controller/clipboard/clipboardController.test.js +0 -68
  84. package/src/all/background_page/event/clipboardEvents.js +0 -28
@@ -0,0 +1,43 @@
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.4.0
13
+ */
14
+ import AccountEntity from "../model/entity/account/accountEntity";
15
+ import {defaultAccountDto} from "../model/entity/account/accountEntity.test.data";
16
+ import {defaultApiClientOptions} from "passbolt-styleguide/src/shared/lib/apiClient/apiClientOptions.test.data";
17
+ import FindAllForActionLogController from "./findAllForActionLogController";
18
+ import {defaultActionLogsCollection} from "../model/entity/actionLog/actionLogsCollection.test.data";
19
+ import ActionLogsCollection from "../model/entity/actionLog/actionLogsCollection";
20
+ import {v4 as uuid} from "uuid";
21
+
22
+ describe("FindAllForActionLogController", () => {
23
+ let controller, account, apiClientOptions;
24
+
25
+ beforeEach(async() => {
26
+ account = new AccountEntity(defaultAccountDto());
27
+ apiClientOptions = defaultApiClientOptions();
28
+ controller = new FindAllForActionLogController(null, null, apiClientOptions, account);
29
+ });
30
+
31
+ describe("FindAllForActionLogController::exec", () => {
32
+ it("Find all action logs for the resource", async() => {
33
+ expect.assertions(2);
34
+
35
+ const actionLogsDto = defaultActionLogsCollection;
36
+ jest.spyOn(controller.findAllForActionLogService, "findAllFor").mockImplementationOnce(() => new ActionLogsCollection(actionLogsDto));
37
+
38
+ const actionLogsCollection = await controller.exec("Resource", uuid(), {page: 1, limit: 5});
39
+ expect(actionLogsCollection).toBeInstanceOf(ActionLogsCollection);
40
+ expect(actionLogsCollection.toDto()).toEqual(actionLogsDto);
41
+ });
42
+ });
43
+ });
@@ -13,6 +13,8 @@ import GetOrFindPasswordPoliciesController from "../controller/passwordPolicies/
13
13
  import AutofillController from "../controller/autofill/AutofillController";
14
14
  import GetOrFindPasswordExpirySettingsController from "../controller/passwordExpiry/getOrFindPasswordExpirySettingsController";
15
15
  import GetOrFindMetadataTypesController from "../controller/metadata/getMetadataTypesSettingsController";
16
+ import CopyToClipboardController from "../controller/clipboard/copyToClipboardController";
17
+ import CopyTemporarilyToClipboardController from "../controller/clipboard/copyTemporarilyToClipboardController";
16
18
 
17
19
  /**
18
20
  * Listens to the quickaccess application events
@@ -158,6 +160,36 @@ const listen = function(worker, apiClientOptions, account) {
158
160
  const controller = new GetOrFindMetadataTypesController(worker, requestId, apiClientOptions, account);
159
161
  await controller._exec();
160
162
  });
163
+
164
+ /*
165
+ * ==================================================================================
166
+ * Clipboard events.
167
+ * ==================================================================================
168
+ */
169
+
170
+ /**
171
+ * Copies the given content into the clipboard and clear any clipboard flush alarms.
172
+ *
173
+ * @listens assbolt.clipboard.copy
174
+ * @param {string} requestId The request identifier
175
+ * @param {string} text the content to copy
176
+ */
177
+ worker.port.on('passbolt.clipboard.copy', async(requestId, text) => {
178
+ const clipboardController = new CopyToClipboardController(worker, requestId);
179
+ await clipboardController._exec(text);
180
+ });
181
+
182
+ /**
183
+ * Copies temporarily the given content into the clipboard and set a clipboard flush alarm.
184
+ *
185
+ * @listens assbolt.clipboard.copy-temporarily
186
+ * @param {string} requestId The request identifier
187
+ * @param {string} text the content to copy
188
+ */
189
+ worker.port.on('passbolt.clipboard.copy-temporarily', async(requestId, text) => {
190
+ const clipboardController = new CopyTemporarilyToClipboardController(worker, requestId);
191
+ await clipboardController._exec(text);
192
+ });
161
193
  };
162
194
 
163
195
  export const QuickAccessEvents = {listen};
@@ -9,13 +9,14 @@
9
9
  import UserModel from "../model/user/userModel";
10
10
  import AccountModel from "../model/account/accountModel";
11
11
  import UpdatePrivateKeyController from "../controller/account/updatePrivateKeyController";
12
- import UserDeleteTransferEntity from "../model/entity/user/transfer/userDeleteTransferEntity";
13
12
  import UserEntity from "../model/entity/user/userEntity";
14
13
  import SecurityTokenEntity from "../model/entity/securityToken/securityTokenEntity";
15
14
  import AvatarUpdateEntity from "../model/entity/avatar/update/avatarUpdateEntity";
16
15
  import UpdateUserLocalStorageController from "../controller/user/updateUserLocalStorageController";
17
16
  import GetOrFindLoggedInUserController from "../controller/user/getOrFindLoggedInUserController";
18
17
  import UpdateUserController from "../controller/user/updateUserController";
18
+ import DeleteDryRunUserController from "../controller/user/deleteDryRunUserController";
19
+ import DeleteUserController from "../controller/user/deleteUserController";
19
20
 
20
21
  /**
21
22
  * Listens the user events
@@ -154,16 +155,9 @@ const listen = function(worker, apiClientOptions, account) {
154
155
  * @param {string} requestId The request identifier uuid
155
156
  * @param {string} userId The user uuid
156
157
  */
157
- worker.port.on('passbolt.users.delete-dry-run', async(requestId, userId, transferDto) => {
158
- try {
159
- const userModel = new UserModel(apiClientOptions, account);
160
- const transferEntity = transferDto ? new UserDeleteTransferEntity(transferDto) : null;
161
- await userModel.deleteDryRun(userId, transferEntity);
162
- worker.port.emit(requestId, 'SUCCESS');
163
- } catch (error) {
164
- console.error(error);
165
- worker.port.emit(requestId, 'ERROR', error);
166
- }
158
+ worker.port.on('passbolt.users.delete-dry-run', async(requestId, userId) => {
159
+ const controller = new DeleteDryRunUserController(worker, requestId, apiClientOptions, account);
160
+ await controller._exec(userId);
167
161
  });
168
162
 
169
163
  /*
@@ -174,15 +168,8 @@ const listen = function(worker, apiClientOptions, account) {
174
168
  * @param {object} [transferDto] optional data ownership transfer
175
169
  */
176
170
  worker.port.on('passbolt.users.delete', async(requestId, userId, transferDto) => {
177
- try {
178
- const userModel = new UserModel(apiClientOptions, account);
179
- const transferEntity = transferDto ? new UserDeleteTransferEntity(transferDto) : null;
180
- await userModel.delete(userId, transferEntity);
181
- worker.port.emit(requestId, 'SUCCESS');
182
- } catch (error) {
183
- console.error(error);
184
- worker.port.emit(requestId, 'ERROR', error);
185
- }
171
+ const controller = new DeleteUserController(worker, requestId, apiClientOptions, account);
172
+ await controller._exec(userId, transferDto);
186
173
  });
187
174
 
188
175
  /*
@@ -12,6 +12,7 @@
12
12
  */
13
13
  import WebIntegrationController from "../controller/webIntegration/webIntegrationController";
14
14
  import RemovePortController from "../controller/port/removePortController";
15
+ import CancelClipboardContentFlushController from "../controller/clipboard/cancelClipboardContentFlushController";
15
16
 
16
17
  /**
17
18
  * Listens the web integration events
@@ -33,6 +34,16 @@ const listen = function(worker) {
33
34
  const removePortController = new RemovePortController(worker);
34
35
  await removePortController._exec(applicationName);
35
36
  });
37
+
38
+ /*
39
+ * Whenever a cut or a copy event happens on a web page to ensure the clipboard flush alarm is not triggered
40
+ * @listens passbolt.clipboard.cancel-content-flush
41
+ * @param requestId {uuid} The request identifier
42
+ */
43
+ worker.port.on('passbolt.clipboard.cancel-content-flush', async requestId => {
44
+ const clipboardController = new CancelClipboardContentFlushController(worker, requestId);
45
+ await clipboardController._exec();
46
+ });
36
47
  };
37
48
 
38
49
  export const WebIntegrationEvents = {listen};
@@ -11,9 +11,11 @@
11
11
  * @link https://www.passbolt.com Passbolt(tm)
12
12
  */
13
13
  import ActionLogsCollection from "../entity/actionLog/actionLogsCollection";
14
- import ActionLogService from "../../service/api/actionLog/actionLogService";
14
+ import {assertUuid, assertNonEmptyString, assertNumber} from "../../utils/assertions";
15
+ import AbstractActionLogEntity from "../entity/actionLog/abstractActionLogEntity";
16
+ import ActionLogApiService from "../../service/api/actionLog/actionLogApiService";
15
17
 
16
- class ActionLogModel {
18
+ class FindActionLogService {
17
19
  /**
18
20
  * Constructor
19
21
  *
@@ -21,7 +23,7 @@ class ActionLogModel {
21
23
  * @public
22
24
  */
23
25
  constructor(apiClientOptions) {
24
- this.actionLogService = new ActionLogService(apiClientOptions);
26
+ this.actionLogApiService = new ActionLogApiService(apiClientOptions);
25
27
  }
26
28
 
27
29
  /*
@@ -42,9 +44,27 @@ class ActionLogModel {
42
44
  * @public
43
45
  */
44
46
  async findAllFor(foreignModel, foreignId, page, limit) {
45
- const actionLogsDto = await this.actionLogService.findAllFor(foreignModel, foreignId, page, limit);
47
+ this.assertValidForeignModel(foreignModel);
48
+ assertUuid(foreignId);
49
+ assertNumber(page);
50
+ assertNumber(limit);
51
+ const actionLogsDto = await this.actionLogApiService.findAllFor(foreignModel, foreignId, page, limit);
46
52
  return new ActionLogsCollection(actionLogsDto);
47
53
  }
54
+
55
+ /**
56
+ * Assert a foreign model name is supported by the API
57
+ *
58
+ * @param {string} foreignModel for example 'Resource'
59
+ * @throw {TypeError} if the name is not a valid string or is not supported
60
+ * @public
61
+ */
62
+ assertValidForeignModel(foreignModel) {
63
+ assertNonEmptyString(foreignModel, 'ActionLog foreign model should be a valid string.');
64
+ if (!AbstractActionLogEntity.ALLOWED_FOREIGN_MODELS.includes(foreignModel)) {
65
+ throw new TypeError(`ActionLog foreign model ${foreignModel} is not in the list of supported models.`);
66
+ }
67
+ }
48
68
  }
49
69
 
50
- export default ActionLogModel;
70
+ export default FindActionLogService;
@@ -0,0 +1,61 @@
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.4.0
13
+ */
14
+ import BuildApiClientOptionsService from "../../service/account/buildApiClientOptionsService";
15
+ import AccountEntity from "../../model/entity/account/accountEntity";
16
+ import {defaultAccountDto} from "../../model/entity/account/accountEntity.test.data";
17
+ import {v4 as uuidv4} from "uuid";
18
+ import {enableFetchMocks} from "jest-fetch-mock";
19
+ import ActionLogApiService from "../../service/api/actionLog/actionLogApiService";
20
+ import FindActionLogService from "./findActionLogService";
21
+ import {defaultActionLogsCollection} from "../../model/entity/actionLog/actionLogsCollection.test.data";
22
+
23
+ describe("FindActionLogService", () => {
24
+ let apiClientOptions, account,
25
+ service;
26
+
27
+ beforeEach(async() => {
28
+ enableFetchMocks();
29
+ jest.clearAllMocks();
30
+ fetch.resetMocks();
31
+ account = new AccountEntity(defaultAccountDto());
32
+ apiClientOptions = BuildApiClientOptionsService.buildFromAccount(account);
33
+ service = new FindActionLogService(apiClientOptions, account);
34
+ });
35
+
36
+ describe('::findAllFor', () => {
37
+ it("Should call the actionLog service API to get the acitonlog collection", async() => {
38
+ expect.assertions(1);
39
+ const foreignId = uuidv4();
40
+ const actionLogsDto = defaultActionLogsCollection;
41
+
42
+ jest.spyOn(ActionLogApiService.prototype, "findAllFor").mockImplementation(() => actionLogsDto);
43
+
44
+ const actionLogs = await service.findAllFor("Resource", foreignId, 1, 5);
45
+ expect(actionLogs).toHaveLength(actionLogsDto.length);
46
+ });
47
+
48
+ it("should throw an error if id is not defined", async() => {
49
+ expect.assertions(1);
50
+ const promise = service.findAllFor({unknown: true});
51
+ await expect(promise).rejects.toThrowError("ActionLog foreign model should be a valid string.");
52
+ });
53
+
54
+ it("should throw an error if foreign model is unsupported", async() => {
55
+ expect.assertions(1);
56
+ const foreignId = uuidv4();
57
+ const promise = service.findAllFor("ChangeTheme", foreignId, 1, 5);
58
+ await expect(promise).rejects.toThrowError("ActionLog foreign model ChangeTheme is not in the list of supported models.");
59
+ });
60
+ });
61
+ });
@@ -13,7 +13,7 @@
13
13
  */
14
14
  import CommentEntity from "../entity/comment/commentEntity";
15
15
  import CommentsCollection from "../entity/comment/commentsCollection";
16
- import CommentService from "../../service/api/comment/commentService";
16
+ import CommentApiService from "../../service/api/comment/commentApiService";
17
17
 
18
18
  class CommentModel {
19
19
  /**
@@ -23,7 +23,7 @@ class CommentModel {
23
23
  * @public
24
24
  */
25
25
  constructor(apiClientOptions) {
26
- this.commentService = new CommentService(apiClientOptions);
26
+ this.commentApiService = new CommentApiService(apiClientOptions);
27
27
  }
28
28
 
29
29
  /**
@@ -35,7 +35,7 @@ class CommentModel {
35
35
  */
36
36
  async findAllByResourceId(resourceId) {
37
37
  const foreignKey = 'Resource';
38
- const commentsDtos = await this.commentService.findAll(foreignKey, resourceId, {creator: true, modifier: false});
38
+ const commentsDtos = await this.commentApiService.findAll(foreignKey, resourceId, {creator: true, modifier: false});
39
39
  return new CommentsCollection(commentsDtos);
40
40
  }
41
41
 
@@ -46,7 +46,7 @@ class CommentModel {
46
46
  * @returns {Promise<CommentEntity>}
47
47
  */
48
48
  async create(commentEntity) {
49
- const commentDto = await this.commentService.create(commentEntity.toDto({creator: false, modifier: false}));
49
+ const commentDto = await this.commentApiService.create(commentEntity.toDto({creator: false, modifier: false}));
50
50
  return new CommentEntity(commentDto);
51
51
  }
52
52
 
@@ -57,7 +57,7 @@ class CommentModel {
57
57
  * @returns {Promise<void>}
58
58
  */
59
59
  async delete(commentId) {
60
- await this.commentService.delete(commentId);
60
+ await this.commentApiService.delete(commentId);
61
61
  }
62
62
  }
63
63
 
@@ -0,0 +1,18 @@
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.4.0
13
+ */
14
+ import {defaultData} from "./defaultActionLogEntity.test.data";
15
+
16
+ export const defaultActionLogsCollection = [
17
+ defaultData
18
+ ];
@@ -0,0 +1,34 @@
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.4.0
13
+ */
14
+ import {v4 as uuidv4} from "uuid";
15
+
16
+ export const defaultData = {
17
+ "id": uuidv4(),
18
+ "action_log_id": uuidv4(),
19
+ "type": "Resources.created",
20
+ "creator": {
21
+ "id": uuidv4(),
22
+ "username": "ada@passbolt.com",
23
+ "profile": {
24
+ "first_name": "Ada",
25
+ "last_name": "Lovelace",
26
+ "avatar": {
27
+ "url": {
28
+ "medium": "img\/public\/Avatar\/22\/47\/85\/50adf80e3534413abdd8e34c9be6d1b6\/50adf80e3534413abdd8e34c9be6d1b6.a99472d5.png",
29
+ "small": "img\/public\/Avatar\/22\/47\/85\/50adf80e3534413abdd8e34c9be6d1b6\/50adf80e3534413abdd8e34c9be6d1b6.65a0ba70.png"
30
+ }
31
+ }
32
+ },
33
+ }
34
+ };
@@ -371,7 +371,6 @@ describe("ResourcesKdbxImportParser", () => {
371
371
  const importEntity = new ImportResourcesFileEntity(importDto);
372
372
  const parser = new ResourcesKdbxImportParser(importEntity, resourceTypesCollection, metadataTypesSettings);
373
373
  await parser.parseImport();
374
- console.log(importEntity);
375
374
 
376
375
  // Assert resources
377
376
  expect(importEntity.importResources.items).toHaveLength(2);
@@ -12,12 +12,9 @@
12
12
  * @since 3.0.0
13
13
  */
14
14
  import UserLocalStorage from "../../service/local_storage/userLocalStorage";
15
- import DeleteDryRunError from "../../error/deleteDryRunError";
16
15
  import UserService from "../../service/api/user/userService";
17
- import UserDeleteTransferEntity from "../entity/user/transfer/userDeleteTransferEntity";
18
16
  import UserEntity from "../entity/user/userEntity";
19
17
  import UsersCollection from "../entity/user/usersCollection";
20
- import PassboltApiFetchError from "passbolt-styleguide/src/shared/lib/Error/PassboltApiFetchError";
21
18
  import Validator from "validator";
22
19
  import RoleEntity from "passbolt-styleguide/src/shared/models/entity/role/roleEntity";
23
20
  import UserMeSessionStorageService from "../../service/sessionStorage/userMeSessionStorageService";
@@ -208,63 +205,6 @@ class UserModel {
208
205
  return new UserEntity(userDto, {ignoreInvalidEntity});
209
206
  }
210
207
 
211
- /**
212
- * Check if a user can be deleted
213
- *
214
- * A user can not be deleted if:
215
- * - they are the only owner of a shared resource
216
- * - they are the only group manager of a group that owns a shared resource
217
- * In such case ownership transfer is required.
218
- *
219
- * @param {string} userId The user id
220
- * @param {UserDeleteTransferEntity} [transfer] optional ownership transfer information if needed
221
- * @returns {Promise<void>}
222
- * @throws {DeleteDryRunError} if some permissions must be transferred
223
- * @public
224
- */
225
- async deleteDryRun(userId, transfer) {
226
- try {
227
- const deleteData = (transfer && transfer instanceof UserDeleteTransferEntity) ? transfer.toDto() : {};
228
- await this.userService.delete(userId, deleteData, true);
229
- } catch (error) {
230
- if (error instanceof PassboltApiFetchError && error.data.code === 400 && error.data.body.errors) {
231
- /*
232
- * recast generic 400 error into a delete dry run error
233
- * allowing validation of the returned entities and reuse down the line to transfer permissions
234
- */
235
- throw new DeleteDryRunError(error.message, error.data.body.errors);
236
- }
237
- throw error;
238
- }
239
- }
240
-
241
- /**
242
- * Delete a user and transfer ownership if needed
243
- *
244
- * @param {string} userId The user id
245
- * @param {UserDeleteTransferEntity} [transfer] optional ownership transfer information if needed
246
- * @returns {Promise<void>}
247
- * @public
248
- */
249
- async delete(userId, transfer) {
250
- try {
251
- const deleteData = (transfer && transfer instanceof UserDeleteTransferEntity) ? transfer.toDto() : {};
252
- await this.userService.delete(userId, deleteData);
253
- } catch (error) {
254
- if (error instanceof PassboltApiFetchError && error.data.code === 400 && error.data.body.errors) {
255
- /*
256
- * recast generic 400 error into a delete dry run error
257
- * allowing validation of the returned entities and reuse down the line to transfer permissions
258
- */
259
- throw new DeleteDryRunError(error.message, error.data.body.errors);
260
- }
261
- throw error;
262
- }
263
-
264
- // Update local storage
265
- await UserLocalStorage.delete(userId);
266
- }
267
-
268
208
  /**
269
209
  * Request help when a user lost its credentials.
270
210
  * @param {AbstractAccountEntity} account The account the credentials have been lost for.
@@ -39,7 +39,6 @@ import {LocaleEvents} from "../event/localeEvents";
39
39
  import {MobileEvents} from "../event/mobileEvents";
40
40
  import {PownedPasswordEvents} from '../event/pownedPasswordEvents';
41
41
  import {MfaEvents} from "../event/mfaEvents";
42
- import {ClipboardEvents} from "../event/clipboardEvents";
43
42
  import BuildApiClientOptionsService from "../service/account/buildApiClientOptionsService";
44
43
  import {RememberMeEvents} from "../event/rememberMeEvents";
45
44
  import CheckAuthStatusService from "../service/auth/checkAuthStatusService";
@@ -87,7 +86,6 @@ class App extends Pagemod {
87
86
  MobileEvents,
88
87
  PownedPasswordEvents,
89
88
  MfaEvents,
90
- ClipboardEvents,
91
89
  RememberMeEvents,
92
90
  PermissionEvents,
93
91
  AccountEvents
@@ -38,7 +38,6 @@ import {ThemeEvents} from "../event/themeEvents";
38
38
  import {MobileEvents} from "../event/mobileEvents";
39
39
  import {PownedPasswordEvents} from '../event/pownedPasswordEvents';
40
40
  import {MfaEvents} from "../event/mfaEvents";
41
- import {ClipboardEvents} from "../event/clipboardEvents";
42
41
  import {v4 as uuid} from "uuid";
43
42
  import BuildApiClientOptionsService from "../service/account/buildApiClientOptionsService";
44
43
  import {enableFetchMocks} from "jest-fetch-mock";
@@ -75,13 +74,12 @@ jest.spyOn(LocaleEvents, "listen").mockImplementation(jest.fn());
75
74
  jest.spyOn(MobileEvents, "listen").mockImplementation(jest.fn());
76
75
  jest.spyOn(PownedPasswordEvents, "listen").mockImplementation(jest.fn());
77
76
  jest.spyOn(MfaEvents, "listen").mockImplementation(jest.fn());
78
- jest.spyOn(ClipboardEvents, "listen").mockImplementation(jest.fn());
79
77
  jest.spyOn(RememberMeEvents, "listen").mockImplementation(jest.fn());
80
78
  jest.spyOn(PermissionEvents, "listen").mockImplementation(jest.fn());
81
79
  jest.spyOn(AccountEvents, "listen").mockImplementation(jest.fn());
82
80
 
83
81
  describe("App", () => {
84
- beforeEach(async() => {
82
+ beforeEach(() => {
85
83
  jest.resetModules();
86
84
  jest.clearAllMocks();
87
85
  enableFetchMocks();
@@ -89,7 +87,7 @@ describe("App", () => {
89
87
 
90
88
  describe("App::attachEvents", () => {
91
89
  it("Should attach events", async() => {
92
- expect.assertions(34);
90
+ expect.assertions(33);
93
91
  // data mocked
94
92
  const port = {
95
93
  _port: {
@@ -137,7 +135,6 @@ describe("App", () => {
137
135
  expect(MobileEvents.listen).toHaveBeenCalledWith(expectedPortAndTab, mockApiClient, mockedAccount);
138
136
  expect(PownedPasswordEvents.listen).toHaveBeenCalledWith(expectedPortAndTab, mockApiClient, mockedAccount);
139
137
  expect(MfaEvents.listen).toHaveBeenCalledWith(expectedPortAndTab, mockApiClient, mockedAccount);
140
- expect(ClipboardEvents.listen).toHaveBeenCalledWith(expectedPortAndTab, mockApiClient, mockedAccount);
141
138
  expect(RememberMeEvents.listen).toHaveBeenCalledWith(expectedPortAndTab, mockApiClient, mockedAccount);
142
139
  expect(PermissionEvents.listen).toHaveBeenCalledWith(expectedPortAndTab, mockApiClient, mockedAccount);
143
140
  expect(AccountEvents.listen).toHaveBeenCalledWith(expectedPortAndTab, mockApiClient, mockedAccount);
@@ -168,7 +165,6 @@ describe("App", () => {
168
165
  MobileEvents,
169
166
  PownedPasswordEvents,
170
167
  MfaEvents,
171
- ClipboardEvents,
172
168
  RememberMeEvents,
173
169
  PermissionEvents,
174
170
  AccountEvents
@@ -13,6 +13,7 @@
13
13
  */
14
14
 
15
15
  import StartLoopAuthSessionCheckService from "../auth/startLoopAuthSessionCheckService";
16
+ import CopyToClipboardService from "../clipboard/copyToClipboardService";
16
17
  import KeepSessionAliveService from "../session_storage/keepSessionAliveService";
17
18
  import PassphraseStorageService from "../session_storage/passphraseStorageService";
18
19
 
@@ -20,6 +21,7 @@ const topLevelAlarmMapping = {
20
21
  [StartLoopAuthSessionCheckService.ALARM_NAME]: StartLoopAuthSessionCheckService.handleAuthStatusCheckAlarm,
21
22
  [PassphraseStorageService.ALARM_NAME]: PassphraseStorageService.handleFlushEvent,
22
23
  [KeepSessionAliveService.ALARM_NAME]: KeepSessionAliveService.handleKeepSessionAlive,
24
+ [CopyToClipboardService.ALARM_NAME]: CopyToClipboardService.handleClipboardTemporaryContentFlushEvent,
23
25
  };
24
26
 
25
27
  /**
@@ -11,6 +11,7 @@
11
11
  * @link https://www.passbolt.com Passbolt(tm)
12
12
  */
13
13
  import AbstractActionLogEntity from "../../../model/entity/actionLog/abstractActionLogEntity";
14
+ import {assertUuid, assertNonEmptyString, assertNumber} from "../../../utils/assertions";
14
15
  import AbstractService from "../abstract/abstractService";
15
16
 
16
17
  const RESOURCE_SERVICE_RESOURCE_NAME = 'actionlog';
@@ -76,7 +77,9 @@ class ActionLogService extends AbstractService {
76
77
  */
77
78
  async findAllFor(foreignModel, foreignId, page, limit) {
78
79
  this.assertValidForeignModel(foreignModel);
79
- this.assertValidId(foreignId);
80
+ assertNumber(page);
81
+ assertNumber(limit);
82
+ assertUuid(foreignId);
80
83
  if (!page || typeof page !== 'number') {
81
84
  throw new TypeError(`ActionLog page should be a valid integer.`);
82
85
  }
@@ -102,9 +105,7 @@ class ActionLogService extends AbstractService {
102
105
  * @public
103
106
  */
104
107
  assertValidForeignModel(foreignModel) {
105
- if (!foreignModel || typeof foreignModel !== 'string') {
106
- throw new TypeError(`ActionLog foreign model should be a valid string.`);
107
- }
108
+ assertNonEmptyString(foreignModel, 'ActionLog foreign model should be a valid string.');
108
109
  if (!AbstractActionLogEntity.ALLOWED_FOREIGN_MODELS.includes(foreignModel)) {
109
110
  throw new TypeError(`ActionLog foreign model ${foreignModel} in not in the list of supported models.`);
110
111
  }
@@ -0,0 +1,55 @@
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.4.0
13
+ */
14
+
15
+ import {enableFetchMocks} from "jest-fetch-mock";
16
+ import {v4 as uuidv4} from "uuid";
17
+ import {mockApiResponse} from '../../../../../../test/mocks/mockApiResponse';
18
+ import ActionLogApiService from "./actionLogApiService";
19
+ import AccountEntity from "../../../model/entity/account/accountEntity";
20
+ import {defaultAccountDto} from "../../../model/entity/account/accountEntity.test.data";
21
+ import BuildApiClientOptionsService from "../../account/buildApiClientOptionsService";
22
+ import {defaultActionLogsCollection} from "../../../model/entity/actionLog/actionLogsCollection.test.data";
23
+
24
+ describe("ActionLogService", () => {
25
+ let apiClientOptions, account;
26
+ beforeEach(async() => {
27
+ enableFetchMocks();
28
+ fetch.resetMocks();
29
+ account = new AccountEntity(defaultAccountDto());
30
+ apiClientOptions = BuildApiClientOptionsService.buildFromAccount(account);
31
+ });
32
+
33
+ describe('::findAllFor', () => {
34
+ it("Retrieves all action logs for a foreign model", async() => {
35
+ expect.assertions(2);
36
+
37
+ const apiResponse = [defaultActionLogsCollection];
38
+ fetch.doMockOnceIf(/actionlog\/resource/, () => mockApiResponse(apiResponse));
39
+
40
+ const service = new ActionLogApiService(apiClientOptions, account);
41
+ const result = await service.findAllFor("Resource", uuidv4(), 1, 5);
42
+
43
+ expect(result).toBeInstanceOf(Array);
44
+ expect(result).toHaveLength(apiResponse.length);
45
+ });
46
+
47
+ it("throws API error if the API encountered an issue", async() => {
48
+ expect.assertions(1);
49
+
50
+ const service = new ActionLogApiService(apiClientOptions, account);
51
+
52
+ await expect(() => service.findAllFor("Resource", uuidv4())).rejects.toThrow(TypeError);
53
+ });
54
+ });
55
+ });