passbolt-browser-extension 5.3.2 → 5.4.1
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/CHANGELOG.md +58 -1
- package/README.md +2 -2
- package/RELEASE_NOTES.md +8 -30
- package/crowdin.yml +1 -0
- package/package.json +4 -3
- package/src/all/_locales/cs/messages.json +10 -0
- package/src/all/background_page/controller/InformMenuController/InformMenuController.js +3 -3
- package/src/all/background_page/controller/auth/redirectPostLoginController.js +57 -0
- package/src/all/background_page/controller/auth/redirectPostLoginController.test.js +82 -0
- package/src/all/background_page/controller/auth/redirectToAdminWorkspaceController.js +50 -0
- package/src/all/background_page/controller/auth/redirectToAdminWorkspaceController.test.js +45 -0
- package/src/all/background_page/controller/comment/createCommentController.js +3 -3
- package/src/all/background_page/controller/comment/createCommentController.test.js +5 -5
- package/src/all/background_page/controller/comment/deleteCommentController.js +3 -3
- package/src/all/background_page/controller/comment/deleteCommentController.test.js +3 -3
- package/src/all/background_page/controller/comment/getCommentsByRessourceIdController.js +3 -3
- package/src/all/background_page/controller/comment/getCommentsByRessourceidController.test.js +2 -2
- package/src/all/background_page/controller/import/importResourcesFileController.test.js +23 -23
- package/src/all/background_page/controller/metadata/enableEncryptedMetadataForExistingInstanceController.js +54 -0
- package/src/all/background_page/controller/metadata/enableEncryptedMetadataForExistingInstanceController.test.js +54 -0
- package/src/all/background_page/controller/metadata/enableMetadataSetupSettingsController.js +54 -0
- package/src/all/background_page/controller/metadata/enableMetadataSetupSettingsController.test.js +64 -0
- package/src/all/background_page/controller/metadata/findAllNonDeletedMetadataKeysController.js +2 -3
- package/src/all/background_page/controller/metadata/findMetadataGettingStartedSettingsController.js +50 -0
- package/src/all/background_page/controller/metadata/findMetadataGettingStartedSettingsController.test.js +33 -0
- package/src/all/background_page/controller/metadata/findMetadataSetupSettingsController.js +50 -0
- package/src/all/background_page/controller/metadata/findMetadataSetupSettingsController.test.js +42 -0
- package/src/all/background_page/controller/metadata/keepCleartextMetadataForExistingInstanceController.js +51 -0
- package/src/all/background_page/controller/metadata/keepCleartextMetadataForExistingInstanceController.test.js +47 -0
- package/src/all/background_page/controller/permission/FindAcoPermissionsForDisplayController.js +1 -0
- package/src/all/background_page/controller/quickaccess/consumeInProgressCreationResourceController.js +53 -0
- package/src/all/background_page/controller/quickaccess/consumeInProgressCreationResourceController.test.js +40 -0
- package/src/all/background_page/controller/quickaccess/prepareResourceController.js +64 -0
- package/src/all/background_page/controller/quickaccess/prepareResourceController.test.js +73 -0
- package/src/all/background_page/controller/resource/resourceDeleteController.js +67 -0
- package/src/all/background_page/controller/resource/resourceDeleteController.test.js +114 -0
- package/src/all/background_page/controller/resourceLocalStorage/resourceUpdateLocalStorageController.js +1 -1
- package/src/all/background_page/controller/resourceLocalStorage/resourceUpdateLocalStorageController.test.js +5 -1
- package/src/all/background_page/controller/setup/signInSetupController.js +0 -10
- package/src/all/background_page/controller/setup/signInSetupController.test.js +11 -12
- package/src/all/background_page/controller/sso/saveSsoSettingsAsDraftController.test.data.js +1 -0
- package/src/all/background_page/controller/webIntegration/webIntegrationController.js +1 -1
- package/src/all/background_page/event/appEvents.js +47 -0
- package/src/all/background_page/event/authEvents.js +4 -8
- package/src/all/background_page/event/informMenuEvents.js +31 -0
- package/src/all/background_page/event/quickAccessEvents.js +18 -23
- package/src/all/background_page/event/recoverEvents.js +12 -0
- package/src/all/background_page/event/resourceEvents.js +4 -11
- package/src/all/background_page/event/setupEvents.js +55 -0
- package/src/all/background_page/model/comment/{commentModel.js → commentService.js} +6 -2
- package/src/all/background_page/model/comment/commentService.test.js +98 -0
- package/src/all/background_page/model/entity/actionLog/actionLogsCollection.js +3 -3
- package/src/all/background_page/model/entity/actionLog/permissionsUpdatedActionLogEntity.js +4 -0
- package/src/all/background_page/model/entity/import/importResourcesFileEntity.test.data.js +3 -3
- package/src/all/background_page/model/entity/organizationSettings/organizationSettingsEntity.test.data.js +4 -0
- package/src/all/background_page/model/entity/permission/actionLog/updatedPermissionEntity.test.data.js +23 -0
- package/src/all/background_page/model/entity/permission/actionLog/updatedPermissionEntity.test.js +18 -33
- package/src/all/background_page/model/entity/permission/actionLog/updatedPermissionsCollection.js +71 -2
- package/src/all/background_page/model/entity/permission/actionLog/updatedPermissionsCollection.test.js +204 -0
- package/src/all/background_page/model/entity/permission/permissionsCollection.js +78 -0
- package/src/all/background_page/model/entity/permission/permissionsCollection.test.js +139 -7
- package/src/all/background_page/model/entity/plaintext/plaintextEntity.js +9 -0
- package/src/all/background_page/model/entity/resource/external/externalResourceEntity.js +65 -8
- package/src/all/background_page/model/entity/resource/external/externalResourceEntity.test.data.js +5 -4
- package/src/all/background_page/model/entity/resource/external/externalResourceEntity.test.js +72 -16
- package/src/all/background_page/model/entity/resource/external/externalResourcesCollection.test.js +2 -1
- package/src/all/background_page/model/entity/totp/externalTotpEntity.js +2 -2
- package/src/all/background_page/model/entity/totp/totpEntity.test.js +1 -1
- package/src/all/background_page/model/export/resources/csvRowComposer/csv1PasswordRowComposer.test.js +2 -2
- package/src/all/background_page/model/export/resources/csvRowComposer/csv1passwordRowComposer.js +5 -1
- package/src/all/background_page/model/export/resources/csvRowComposer/csvBitWardenRowComposer.js +9 -1
- package/src/all/background_page/model/export/resources/csvRowComposer/csvBitWardenRowComposer.test.js +6 -4
- package/src/all/background_page/model/export/resources/csvRowComposer/csvChromiumRowComposer.js +5 -1
- package/src/all/background_page/model/export/resources/csvRowComposer/csvChromiumRowComposer.test.js +3 -2
- package/src/all/background_page/model/export/resources/csvRowComposer/csvDashlaneRowComposer.js +5 -1
- package/src/all/background_page/model/export/resources/csvRowComposer/csvDashlaneRowComposer.test.js +2 -3
- package/src/all/background_page/model/export/resources/csvRowComposer/csvKdbxRowComposer.js +3 -1
- package/src/all/background_page/model/export/resources/csvRowComposer/csvKdbxRowComposer.test.js +6 -4
- package/src/all/background_page/model/export/resources/csvRowComposer/csvLastPassRowComposer.js +5 -1
- package/src/all/background_page/model/export/resources/csvRowComposer/csvLastPassRowComposer.test.js +2 -3
- package/src/all/background_page/model/export/resources/csvRowComposer/csvLogMeOnceRowComposer.js +5 -1
- package/src/all/background_page/model/export/resources/csvRowComposer/csvLogMeOnceRowComposer.test.js +2 -3
- package/src/all/background_page/model/export/resources/csvRowComposer/csvMozillaPlatformRowComposer.js +6 -2
- package/src/all/background_page/model/export/resources/csvRowComposer/csvMozillaPlatformRowComposer.test.js +2 -2
- package/src/all/background_page/model/export/resources/csvRowComposer/csvNordpassRowComposer.js +5 -1
- package/src/all/background_page/model/export/resources/csvRowComposer/csvNordpassRowComposer.test.js +2 -2
- package/src/all/background_page/model/export/resources/csvRowComposer/csvSafariRowComposer.js +5 -1
- package/src/all/background_page/model/export/resources/csvRowComposer/csvSafariRowComposer.test.js +2 -2
- package/src/all/background_page/model/export/resources/resourcesKdbxExporter.js +44 -2
- package/src/all/background_page/model/export/resources/resourcesKdbxExporter.test.js +24 -3
- package/src/all/background_page/model/import/resources/csvRowParser/abstractCsvRowParser.js +1 -1
- package/src/all/background_page/model/import/resources/csvRowParser/csv1PasswordRowParser.js +5 -3
- package/src/all/background_page/model/import/resources/csvRowParser/csv1PasswordRowParser.test.js +3 -2
- package/src/all/background_page/model/import/resources/csvRowParser/csvBitWardenRowParser.js +22 -3
- package/src/all/background_page/model/import/resources/csvRowParser/csvBitWardenRowParser.test.js +92 -4
- package/src/all/background_page/model/import/resources/csvRowParser/csvChromiumRowParser.js +4 -2
- package/src/all/background_page/model/import/resources/csvRowParser/csvChromiumRowParser.test.js +2 -2
- package/src/all/background_page/model/import/resources/csvRowParser/csvDashlaneRowParser.js +4 -2
- package/src/all/background_page/model/import/resources/csvRowParser/csvDashlaneRowParser.test.js +3 -2
- package/src/all/background_page/model/import/resources/csvRowParser/csvKdbxRowParser.js +5 -3
- package/src/all/background_page/model/import/resources/csvRowParser/csvKdbxRowParser.test.js +4 -4
- package/src/all/background_page/model/import/resources/csvRowParser/csvLastPassRowParser.js +4 -2
- package/src/all/background_page/model/import/resources/csvRowParser/csvLastPassRowParser.test.js +2 -2
- package/src/all/background_page/model/import/resources/csvRowParser/csvLogMeOnceRowParser.js +5 -2
- package/src/all/background_page/model/import/resources/csvRowParser/csvLogMeOnceRowParser.test.js +2 -2
- package/src/all/background_page/model/import/resources/csvRowParser/csvMozillaPlatformRowParser.js +5 -3
- package/src/all/background_page/model/import/resources/csvRowParser/csvMozillaPlatformRowParser.test.js +2 -2
- package/src/all/background_page/model/import/resources/csvRowParser/csvNordpassRowParser.js +4 -2
- package/src/all/background_page/model/import/resources/csvRowParser/csvNordpassRowParser.test.js +2 -2
- package/src/all/background_page/model/import/resources/csvRowParser/csvSafariRowParser.js +4 -2
- package/src/all/background_page/model/import/resources/csvRowParser/csvSafariRowParser.test.js +2 -2
- package/src/all/background_page/model/import/resources/kdbx/kdbx-custom-fields-with-uris.kdbx +0 -0
- package/src/all/background_page/model/import/resources/kdbx/kdbx-multiple-uris-with-33-entries.kdbx +0 -0
- package/src/all/background_page/model/import/resources/kdbx/kdbx-multiple-uris.kdbx +0 -0
- package/src/all/background_page/model/import/resources/kdbx/kdbx-with-protected-custom-fields.kdbx +0 -0
- package/src/all/background_page/model/import/resources/resourcesCsvImportParser.test.js +1 -1
- package/src/all/background_page/model/import/resources/resourcesKdbxImportParser.js +124 -41
- package/src/all/background_page/model/import/resources/resourcesKdbxImportParser.test.js +133 -1
- package/src/all/background_page/model/import/resourcesImportParser.test.js +0 -1
- package/src/all/background_page/model/resource/resourceModel.js +0 -68
- package/src/all/background_page/service/api/comment/commentApiService.test.js +1 -1
- package/src/all/background_page/service/api/metadata/metadataSetupSettingsApiService.js +40 -0
- package/src/all/background_page/service/api/metadata/metadataSetupSettingsApiService.test.js +54 -0
- package/src/all/background_page/service/api/setup/setupService.js +2 -2
- package/src/all/background_page/service/api/setup/setupService.test.js +132 -0
- package/src/all/background_page/service/local_storage/resourceLocalStorage.js +25 -1
- package/src/all/background_page/service/local_storage/resourceLocalStorage.test.js +54 -0
- package/src/all/background_page/service/metadata/configureMetadataSettingsService.js +100 -0
- package/src/all/background_page/service/metadata/configureMetadataSettingsService.test.js +265 -0
- package/src/all/background_page/service/metadata/createMetadataKeyService.js +1 -1
- package/src/all/background_page/service/metadata/decryptMetadataPrivateKeysService.js +3 -19
- package/src/all/background_page/service/metadata/decryptMetadataService.js +5 -3
- package/src/all/background_page/service/metadata/decryptMetadataService.test.js +31 -24
- package/src/all/background_page/service/metadata/encryptMetadataService.js +2 -18
- package/src/all/background_page/service/metadata/findAndUpdateMetadataKeysSessionStorageService.js +5 -2
- package/src/all/background_page/service/metadata/findAndUpdateMetadataKeysSessionStorageService.test.js +4 -6
- package/src/all/background_page/service/metadata/findMetadataKeysService.js +8 -12
- package/src/all/background_page/service/metadata/findMetadataKeysService.test.js +21 -47
- package/src/all/background_page/service/metadata/findMetadataSetupSettingsService.js +45 -0
- package/src/all/background_page/service/metadata/findMetadataSetupSettingsService.test.js +68 -0
- package/src/all/background_page/service/metadata/generateMetadataKeyService.js +1 -1
- package/src/all/background_page/service/metadata/verifyOrTrustMetadataKeyService.test.js +16 -0
- package/src/all/background_page/service/passphrase/getPassphraseService.js +13 -0
- package/src/all/background_page/service/permission/findPermissionsService.js +3 -1
- package/src/all/background_page/service/resource/delete/deleteResourceService.js +60 -0
- package/src/all/background_page/service/resource/delete/deleteResourceService.test.js +75 -0
- package/src/all/background_page/service/resource/export/exportResourcesService.js +22 -0
- package/src/all/background_page/service/resource/export/exportResourcesService.test.js +48 -1
- package/src/all/background_page/service/resource/import/ImportResourcesService.js +34 -3
- package/src/all/background_page/service/resource/import/ImportResourcesService.test.js +55 -13
- package/src/all/background_page/service/sessionKey/decryptSessionKeysBundlesService.js +2 -18
- package/src/all/background_page/service/sessionKey/encryptSessionKeysBundlesService.js +1 -17
- package/src/all/locales/cs-CZ/common.json +130 -0
- package/src/all/locales/de-DE/common.json +11 -5
- package/src/all/locales/en-UK/common.json +6 -0
- package/src/all/locales/es-ES/common.json +6 -0
- package/src/all/locales/fr-FR/common.json +6 -0
- package/src/all/locales/it-IT/common.json +6 -0
- package/src/all/locales/ja-JP/common.json +6 -0
- package/src/all/locales/ko-KR/common.json +6 -0
- package/src/all/locales/lt-LT/common.json +6 -0
- package/src/all/locales/nl-NL/common.json +6 -0
- package/src/all/locales/pl-PL/common.json +6 -0
- package/src/all/locales/pt-BR/common.json +6 -0
- package/src/all/locales/ro-RO/common.json +6 -0
- package/src/all/locales/ru-RU/common.json +6 -0
- package/src/all/locales/sl-SI/common.json +6 -0
- package/src/all/locales/sv-SE/common.json +6 -0
- package/src/all/locales/uk-UA/common.json +6 -0
- package/src/chrome/manifest.json +1 -1
- package/src/chrome-mv3/manifest.json +1 -1
- package/src/firefox/manifest.json +1 -1
- package/src/safari/manifest.json +1 -1
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import MetadataKeysCollection from "passbolt-styleguide/src/shared/models/entity/metadata/metadataKeysCollection";
|
|
16
|
-
import DecryptMetadataPrivateKeysService from "../metadata/decryptMetadataPrivateKeysService";
|
|
17
16
|
import MetadataKeysApiService from "../api/metadata/metadataKeysApiService";
|
|
18
17
|
import {OpenpgpAssertion} from "../../utils/openpgp/openpgpAssertions";
|
|
19
18
|
import CollectionValidationError from "passbolt-styleguide/src/shared/models/entity/abstract/collectionValidationError";
|
|
@@ -24,12 +23,10 @@ class FindMetadataKeysService {
|
|
|
24
23
|
* Constructor
|
|
25
24
|
*
|
|
26
25
|
* @param {ApiClientOptions} apiClientOptions
|
|
27
|
-
* @param {AccountEntity} account the user account
|
|
28
26
|
* @public
|
|
29
27
|
*/
|
|
30
|
-
constructor(apiClientOptions
|
|
28
|
+
constructor(apiClientOptions) {
|
|
31
29
|
this.metadataKeysApiService = new MetadataKeysApiService(apiClientOptions);
|
|
32
|
-
this.decryptMetadataPrivateKeysService = new DecryptMetadataPrivateKeysService(account);
|
|
33
30
|
}
|
|
34
31
|
|
|
35
32
|
/**
|
|
@@ -37,12 +34,10 @@ class FindMetadataKeysService {
|
|
|
37
34
|
*
|
|
38
35
|
* @param {Object} [contains] Return entities associated models, example: {metadata_private_keys: true}.
|
|
39
36
|
* @param {Object} [filters] Return entities applied filters, example: {deleted: true}.
|
|
40
|
-
* @param {string|null} [passphrase = null] The passphrase to use to decrypt the metadata. Marked as optional as it
|
|
41
|
-
* might be available in the passphrase session storage.
|
|
42
37
|
* @returns {Promise<MetadataKeysCollection>}
|
|
43
38
|
* @public
|
|
44
39
|
*/
|
|
45
|
-
async findAll(contains = {}, filters = {}
|
|
40
|
+
async findAll(contains = {}, filters = {}) {
|
|
46
41
|
const supportedOptions = MetadataKeysApiService.getSupportedContainOptions();
|
|
47
42
|
if (contains && !Object.keys(contains).every(option => supportedOptions.includes(option))) {
|
|
48
43
|
throw new Error("Unsupported contains parameter used, please check supported contains");
|
|
@@ -59,7 +54,6 @@ class FindMetadataKeysService {
|
|
|
59
54
|
throw new Error("The metadata private keys should not be decrypted.");
|
|
60
55
|
}
|
|
61
56
|
|
|
62
|
-
await this.decryptMetadataPrivateKeysService.decryptAllFromMetadataKeysCollection(collection, passphrase);
|
|
63
57
|
await this.assertArmoredFingerprintPublicAndEntitysMatch(collection);
|
|
64
58
|
|
|
65
59
|
return collection;
|
|
@@ -67,13 +61,15 @@ class FindMetadataKeysService {
|
|
|
67
61
|
|
|
68
62
|
/**
|
|
69
63
|
* Retrieve the metadata keys from the API with the contained data necessary for the local storage.
|
|
70
|
-
* @param {string|null} [passphrase = null] The passphrase to use to decrypt the metadata. Marked as optional as it
|
|
71
|
-
* might be available in the passphrase session storage.
|
|
72
64
|
* @returns {Promise<MetadataKeysCollection>}
|
|
73
65
|
* @public
|
|
74
66
|
*/
|
|
75
|
-
findAllForSessionStorage(
|
|
76
|
-
|
|
67
|
+
async findAllForSessionStorage() {
|
|
68
|
+
const contains = {metadata_private_keys: true, creator: true, "creator.profile": true};
|
|
69
|
+
const filters = {deleted: false};
|
|
70
|
+
const metadataKeys = await this.findAll(contains, filters);
|
|
71
|
+
metadataKeys.filterOutMissingMetadataPrivateKeys();
|
|
72
|
+
return metadataKeys;
|
|
77
73
|
}
|
|
78
74
|
|
|
79
75
|
/**
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
import {enableFetchMocks} from "jest-fetch-mock";
|
|
16
16
|
import AccountEntity from "../../model/entity/account/accountEntity";
|
|
17
17
|
import {defaultAccountDto} from "../../model/entity/account/accountEntity.test.data";
|
|
18
|
-
import PassphraseStorageService from "../session_storage/passphraseStorageService";
|
|
19
18
|
import BuildApiClientOptionsService from "../account/buildApiClientOptionsService";
|
|
20
19
|
import FindMetadataKeysService from "./findMetadataKeysService";
|
|
21
20
|
import {mockApiResponseError} from "passbolt-styleguide/test/mocks/mockApiResponse";
|
|
@@ -43,43 +42,25 @@ describe("FindMetadataKeysApiService", () => {
|
|
|
43
42
|
});
|
|
44
43
|
|
|
45
44
|
describe('::findAll', () => {
|
|
46
|
-
it("retrieves the metadata keys from API with the right contains
|
|
45
|
+
it("retrieves the metadata keys from API with the right contains", async() => {
|
|
47
46
|
expect.assertions(5);
|
|
48
47
|
|
|
49
|
-
jest.spyOn(PassphraseStorageService, "get").mockReturnValue(pgpKeys.ada.passphrase);
|
|
50
|
-
|
|
51
48
|
const id = uuidv4();
|
|
52
49
|
const metadata_private_keys = [defaultMetadataPrivateKeyDto({metadata_key_id: id, data: pgpKeys.metadataKey.encryptedMetadataPrivateKeyDataMessage})];
|
|
53
50
|
const fingerprint = "c0dce0aaea4d8cce961c26bddfb6e74e598f025c";
|
|
54
51
|
const apiMetadataKeysCollection = [defaultMetadataKeyDto({id, metadata_private_keys, fingerprint})];
|
|
55
52
|
|
|
56
|
-
const service = new FindMetadataKeysService(apiClientOptions
|
|
53
|
+
const service = new FindMetadataKeysService(apiClientOptions);
|
|
57
54
|
jest.spyOn(service.metadataKeysApiService, "findAll").mockImplementation(() => apiMetadataKeysCollection);
|
|
58
55
|
const resultDto = await service.findAll();
|
|
59
56
|
|
|
60
57
|
expect(resultDto).toBeInstanceOf(MetadataKeysCollection);
|
|
61
58
|
expect(resultDto).toHaveLength(apiMetadataKeysCollection.length);
|
|
62
|
-
expect(resultDto.
|
|
59
|
+
expect(resultDto.hasDecryptedKeys()).toStrictEqual(false);
|
|
63
60
|
expect(service.metadataKeysApiService.findAll).toHaveBeenCalledTimes(1);
|
|
64
61
|
expect(service.metadataKeysApiService.findAll).toHaveBeenCalledWith({}, {});
|
|
65
62
|
});
|
|
66
63
|
|
|
67
|
-
it("does not retrieve the passphrase from the session storage if passed as parameter", async() => {
|
|
68
|
-
expect.assertions(1);
|
|
69
|
-
|
|
70
|
-
const id = uuidv4();
|
|
71
|
-
const metadata_private_keys = [defaultMetadataPrivateKeyDto({metadata_key_id: id, data: pgpKeys.metadataKey.encryptedMetadataPrivateKeyDataMessage})];
|
|
72
|
-
const fingerprint = "c0dce0aaea4d8cce961c26bddfb6e74e598f025c";
|
|
73
|
-
const apiMetadataKeysCollection = [defaultMetadataKeyDto({id, metadata_private_keys, fingerprint})];
|
|
74
|
-
|
|
75
|
-
const service = new FindMetadataKeysService(apiClientOptions, account);
|
|
76
|
-
jest.spyOn(PassphraseStorageService, "get");
|
|
77
|
-
jest.spyOn(service.metadataKeysApiService, "findAll").mockImplementation(() => apiMetadataKeysCollection);
|
|
78
|
-
await service.findAll({}, {}, pgpKeys.ada.passphrase);
|
|
79
|
-
|
|
80
|
-
expect(PassphraseStorageService.get).not.toHaveBeenCalled();
|
|
81
|
-
});
|
|
82
|
-
|
|
83
64
|
it("throw an error if fingerprint is not matching with the armored public key", async() => {
|
|
84
65
|
expect.assertions(2);
|
|
85
66
|
|
|
@@ -88,8 +69,7 @@ describe("FindMetadataKeysApiService", () => {
|
|
|
88
69
|
const fingerprint = "c0dce0aaea4d8cce961c26bddfb6e74e598f025d";
|
|
89
70
|
const apiMetadataKeysCollection = [defaultMetadataKeyDto({id, metadata_private_keys, fingerprint})];
|
|
90
71
|
|
|
91
|
-
const service = new FindMetadataKeysService(apiClientOptions
|
|
92
|
-
jest.spyOn(PassphraseStorageService, "get").mockReturnValue(pgpKeys.ada.passphrase);
|
|
72
|
+
const service = new FindMetadataKeysService(apiClientOptions);
|
|
93
73
|
jest.spyOn(service.metadataKeysApiService, "findAll").mockImplementation(() => apiMetadataKeysCollection);
|
|
94
74
|
|
|
95
75
|
try {
|
|
@@ -112,8 +92,7 @@ describe("FindMetadataKeysApiService", () => {
|
|
|
112
92
|
const metadata_private_keys = [decryptedMetadataPrivateKeyDto({metadata_key_id: id})];
|
|
113
93
|
const apiMetadataKeysCollection = [defaultMetadataKeyDto({id, metadata_private_keys})];
|
|
114
94
|
|
|
115
|
-
const service = new FindMetadataKeysService(apiClientOptions
|
|
116
|
-
jest.spyOn(PassphraseStorageService, "get").mockReturnValue(pgpKeys.ada.passphrase);
|
|
95
|
+
const service = new FindMetadataKeysService(apiClientOptions);
|
|
117
96
|
jest.spyOn(service.metadataKeysApiService, "findAll").mockImplementation(() => apiMetadataKeysCollection);
|
|
118
97
|
|
|
119
98
|
const expectedError = new Error("The metadata private keys should not be decrypted.");
|
|
@@ -162,7 +141,7 @@ describe("FindMetadataKeysApiService", () => {
|
|
|
162
141
|
});
|
|
163
142
|
|
|
164
143
|
describe('::findAllForSessionStorage', () => {
|
|
165
|
-
it("retrieves the metadata keys from API with the right contains
|
|
144
|
+
it("retrieves the metadata keys from API with the right contains ", async() => {
|
|
166
145
|
expect.assertions(5);
|
|
167
146
|
|
|
168
147
|
const id = uuidv4();
|
|
@@ -170,48 +149,43 @@ describe("FindMetadataKeysApiService", () => {
|
|
|
170
149
|
const fingerprint = "c0dce0aaea4d8cce961c26bddfb6e74e598f025c";
|
|
171
150
|
const apiMetadataKeysCollection = [defaultMetadataKeyDto({id, metadata_private_keys, fingerprint})];
|
|
172
151
|
|
|
173
|
-
const service = new FindMetadataKeysService(apiClientOptions
|
|
174
|
-
jest.spyOn(PassphraseStorageService, "get").mockReturnValue(pgpKeys.ada.passphrase);
|
|
152
|
+
const service = new FindMetadataKeysService(apiClientOptions);
|
|
175
153
|
jest.spyOn(service.metadataKeysApiService, "findAll").mockImplementation(() => apiMetadataKeysCollection);
|
|
176
154
|
const resultDto = await service.findAllForSessionStorage();
|
|
177
155
|
|
|
178
156
|
expect(resultDto).toBeInstanceOf(MetadataKeysCollection);
|
|
179
157
|
expect(resultDto).toHaveLength(apiMetadataKeysCollection.length);
|
|
180
|
-
expect(resultDto.
|
|
158
|
+
expect(resultDto.hasDecryptedKeys()).toStrictEqual(false);
|
|
181
159
|
expect(service.metadataKeysApiService.findAll).toHaveBeenCalledTimes(1);
|
|
182
160
|
expect(service.metadataKeysApiService.findAll).toHaveBeenCalledWith({metadata_private_keys: true, creator: true, "creator.profile": true}, {deleted: false});
|
|
183
161
|
});
|
|
184
162
|
|
|
185
|
-
it("
|
|
186
|
-
expect.assertions(
|
|
163
|
+
it("filter out metadata key not having at least a metadata private key.", async() => {
|
|
164
|
+
expect.assertions(3);
|
|
187
165
|
|
|
188
|
-
const id = uuidv4();
|
|
189
|
-
const metadata_private_keys = [defaultMetadataPrivateKeyDto({metadata_key_id: id, data: pgpKeys.metadataKey.encryptedMetadataPrivateKeyDataMessage})];
|
|
190
166
|
const fingerprint = "c0dce0aaea4d8cce961c26bddfb6e74e598f025c";
|
|
191
|
-
const apiMetadataKeysCollection = [
|
|
167
|
+
const apiMetadataKeysCollection = [
|
|
168
|
+
defaultMetadataKeyDto({fingerprint}, {withMetadataPrivateKeys: true}),
|
|
169
|
+
defaultMetadataKeyDto({fingerprint: pgpKeys.ada.fingerprint, armored_key: pgpKeys.ada.public})
|
|
170
|
+
];
|
|
192
171
|
|
|
193
|
-
const service = new FindMetadataKeysService(apiClientOptions
|
|
194
|
-
jest.spyOn(PassphraseStorageService, "get");
|
|
172
|
+
const service = new FindMetadataKeysService(apiClientOptions);
|
|
195
173
|
jest.spyOn(service.metadataKeysApiService, "findAll").mockImplementation(() => apiMetadataKeysCollection);
|
|
196
|
-
const resultDto = await service.findAllForSessionStorage(
|
|
174
|
+
const resultDto = await service.findAllForSessionStorage();
|
|
197
175
|
|
|
198
|
-
expect(PassphraseStorageService.get).not.toHaveBeenCalled();
|
|
199
176
|
expect(resultDto).toBeInstanceOf(MetadataKeysCollection);
|
|
200
|
-
expect(resultDto).toHaveLength(
|
|
201
|
-
expect(resultDto.
|
|
202
|
-
expect(service.metadataKeysApiService.findAll).toHaveBeenCalledTimes(1);
|
|
203
|
-
expect(service.metadataKeysApiService.findAll).toHaveBeenCalledWith({metadata_private_keys: true, creator: true, "creator.profile": true}, {deleted: false});
|
|
177
|
+
expect(resultDto).toHaveLength(1);
|
|
178
|
+
expect(resultDto.hasDecryptedKeys()).toStrictEqual(false);
|
|
204
179
|
});
|
|
205
180
|
|
|
206
|
-
it("throws an error if the
|
|
181
|
+
it("throws an error if one of the key from the API is already decrypted", async() => {
|
|
207
182
|
expect.assertions(1);
|
|
208
183
|
|
|
209
184
|
const id = uuidv4();
|
|
210
185
|
const metadata_private_keys = [decryptedMetadataPrivateKeyDto({metadata_key_id: id})];
|
|
211
186
|
const apiMetadataKeysCollection = [defaultMetadataKeyDto({id, metadata_private_keys})];
|
|
212
187
|
|
|
213
|
-
const service = new FindMetadataKeysService(apiClientOptions
|
|
214
|
-
jest.spyOn(PassphraseStorageService, "get").mockReturnValue(pgpKeys.ada.passphrase);
|
|
188
|
+
const service = new FindMetadataKeysService(apiClientOptions);
|
|
215
189
|
jest.spyOn(service.metadataKeysApiService, "findAll").mockImplementation(() => apiMetadataKeysCollection);
|
|
216
190
|
|
|
217
191
|
const expectedError = new Error("The metadata private keys should not be decrypted.");
|
|
@@ -242,7 +216,7 @@ describe("FindMetadataKeysApiService", () => {
|
|
|
242
216
|
expect.assertions(3);
|
|
243
217
|
|
|
244
218
|
const apiMetadataKeysCollection = defaultMetadataKeysDtos();
|
|
245
|
-
const service = new FindMetadataKeysService(apiClientOptions
|
|
219
|
+
const service = new FindMetadataKeysService(apiClientOptions);
|
|
246
220
|
jest.spyOn(service, "findAll")
|
|
247
221
|
.mockImplementation(() => new MetadataKeysCollection(apiMetadataKeysCollection));
|
|
248
222
|
|
|
@@ -0,0 +1,45 @@
|
|
|
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 MetadataSetupSettingsApiService from "../api/metadata/metadataSetupSettingsApiService";
|
|
16
|
+
import MetadataSetupSettingsEntity from "passbolt-styleguide/src/shared/models/entity/metadata/metadataSetupSettingsEntity";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The service aims to find metadata setup settings.
|
|
20
|
+
*/
|
|
21
|
+
export default class FindMetadataSetupSettingsService {
|
|
22
|
+
/**
|
|
23
|
+
* @constructor
|
|
24
|
+
* @param {ApiClientOptions} apiClientOptions The api client options
|
|
25
|
+
*/
|
|
26
|
+
constructor(apiClientOptions) {
|
|
27
|
+
this.metadataSetupSettingsApiService = new MetadataSetupSettingsApiService(apiClientOptions);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Finds the metadata setup settings.
|
|
32
|
+
* @returns {Promise<MetadataSetupSettingsEntity>}
|
|
33
|
+
*/
|
|
34
|
+
async findSetupSettings() {
|
|
35
|
+
try {
|
|
36
|
+
const passboltResponse = await this.metadataSetupSettingsApiService.find();
|
|
37
|
+
return MetadataSetupSettingsEntity.createFromDefault(passboltResponse.body);
|
|
38
|
+
} catch (e) {
|
|
39
|
+
if (e?.data?.code === 404) {
|
|
40
|
+
return MetadataSetupSettingsEntity.createFromDefault();
|
|
41
|
+
}
|
|
42
|
+
throw e;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
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 {enableFetchMocks} from "jest-fetch-mock";
|
|
15
|
+
import FindMetadataSetupSettingsService from "./findMetadataSetupSettingsService";
|
|
16
|
+
import {defaultApiClientOptions} from "passbolt-styleguide/src/shared/lib/apiClient/apiClientOptions.test.data";
|
|
17
|
+
import MetadataSetupSettingsEntity from "passbolt-styleguide/src/shared/models/entity/metadata/metadataSetupSettingsEntity";
|
|
18
|
+
import {enableMetadataSetupSettingsDto} from "passbolt-styleguide/src/shared/models/entity/metadata/metadataSetupSettingsEntity.test.data";
|
|
19
|
+
import {mockApiResponse, mockApiResponseError} from "../../../../../test/mocks/mockApiResponse";
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
jest.clearAllMocks();
|
|
23
|
+
enableFetchMocks();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe("FindMetadataSetupSettingsService", () => {
|
|
27
|
+
describe("::findSetupSettings", () => {
|
|
28
|
+
it("retrieve the metadata setup settings.", async() => {
|
|
29
|
+
expect.assertions(2);
|
|
30
|
+
|
|
31
|
+
const expectedSettings = enableMetadataSetupSettingsDto();
|
|
32
|
+
const apiClientOptions = defaultApiClientOptions();
|
|
33
|
+
const service = new FindMetadataSetupSettingsService(apiClientOptions);
|
|
34
|
+
|
|
35
|
+
fetch.doMockOnceIf(/\/metadata\/setup\/settings\.json/, () => mockApiResponse(expectedSettings));
|
|
36
|
+
|
|
37
|
+
const metadataSetupSettingsEntity = await service.findSetupSettings();
|
|
38
|
+
|
|
39
|
+
expect(metadataSetupSettingsEntity).toBeInstanceOf(MetadataSetupSettingsEntity);
|
|
40
|
+
expect(metadataSetupSettingsEntity.enableEncryptedMetadataOnInstall).toStrictEqual(true);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("should consider default disabled settings if the API sends back a 404", async() => {
|
|
44
|
+
expect.assertions(2);
|
|
45
|
+
|
|
46
|
+
const apiClientOptions = defaultApiClientOptions();
|
|
47
|
+
const service = new FindMetadataSetupSettingsService(apiClientOptions);
|
|
48
|
+
|
|
49
|
+
fetch.doMockOnceIf(/\/metadata\/setup\/settings.json/, () => mockApiResponseError(404, "Endpoint does not exists"));
|
|
50
|
+
|
|
51
|
+
const metadataSetupSettingsEntity = await service.findSetupSettings();
|
|
52
|
+
|
|
53
|
+
expect(metadataSetupSettingsEntity).toBeInstanceOf(MetadataSetupSettingsEntity);
|
|
54
|
+
expect(metadataSetupSettingsEntity.enableEncryptedMetadataOnInstall).toStrictEqual(false);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("should not intercept the error from the API if something goes wrong and it is not a 404", async() => {
|
|
58
|
+
expect.assertions(1);
|
|
59
|
+
|
|
60
|
+
const apiClientOptions = defaultApiClientOptions();
|
|
61
|
+
const service = new FindMetadataSetupSettingsService(apiClientOptions);
|
|
62
|
+
|
|
63
|
+
fetch.doMockOnce(/\/metadata\/setup\/settings.json/, () => mockApiResponseError(500, "Something went wrong!"));
|
|
64
|
+
|
|
65
|
+
await expect(() => service.findSetupSettings()).rejects.toThrowError();
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
});
|
|
@@ -29,7 +29,7 @@ class GenerateMetadataKeyService {
|
|
|
29
29
|
/**
|
|
30
30
|
* Generate metadata key.
|
|
31
31
|
* @param {string} passphrase The user passphrase.
|
|
32
|
-
* @return {ExternalGpgKeyPairEntity}
|
|
32
|
+
* @return {Promise<ExternalGpgKeyPairEntity>}
|
|
33
33
|
*/
|
|
34
34
|
async generateKey(passphrase) {
|
|
35
35
|
assertString(passphrase);
|
|
@@ -100,6 +100,22 @@ describe("VerifyOrTrustMetadataKeyService", () => {
|
|
|
100
100
|
expect(service.confirmMetadataKeyContentCodeService.requestConfirm).not.toHaveBeenCalled();
|
|
101
101
|
});
|
|
102
102
|
|
|
103
|
+
it("does nothing if the user does not have a metadata private key shared with the active metadata key returned by the server.", async() => {
|
|
104
|
+
expect.assertions(2);
|
|
105
|
+
|
|
106
|
+
const metadataKeyDto = defaultMetadataKeyDto();
|
|
107
|
+
const metadataKeysCollection = new MetadataKeysCollection([metadataKeyDto]);
|
|
108
|
+
|
|
109
|
+
jest.spyOn(service.getOrFindMetadataKeysService.findAndUpdateMetadataKeysService.findMetadataKeysService, "findAll").mockReturnValue(metadataKeysCollection);
|
|
110
|
+
jest.spyOn(service.trustMetadataKeyService, "trust").mockImplementationOnce(jest.fn);
|
|
111
|
+
jest.spyOn(service.confirmMetadataKeyContentCodeService, "requestConfirm").mockImplementationOnce(jest.fn);
|
|
112
|
+
|
|
113
|
+
await service.verifyTrustedOrTrustNewMetadataKey(pgpKeys.ada.passphrase);
|
|
114
|
+
|
|
115
|
+
expect(service.trustMetadataKeyService.trust).not.toHaveBeenCalled();
|
|
116
|
+
expect(service.confirmMetadataKeyContentCodeService.requestConfirm).not.toHaveBeenCalled();
|
|
117
|
+
});
|
|
118
|
+
|
|
103
119
|
it("throws if the active metadata key is not the one already trusted, and the user does not trust it.", async() => {
|
|
104
120
|
expect.assertions(2);
|
|
105
121
|
|
|
@@ -37,6 +37,19 @@ export default class GetPassphraseService {
|
|
|
37
37
|
return this.requestPassphrase(worker);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Read the user master password from the storage.
|
|
42
|
+
* @return {Promise<string>}
|
|
43
|
+
* @throw Error if the passphrase is not available.
|
|
44
|
+
*/
|
|
45
|
+
async getFromStorageOrFail() {
|
|
46
|
+
const passphrase = await PassphraseStorageService.get();
|
|
47
|
+
if (!passphrase) {
|
|
48
|
+
throw new Error("No passphrase found in the session storage.");
|
|
49
|
+
}
|
|
50
|
+
return passphrase;
|
|
51
|
+
}
|
|
52
|
+
|
|
40
53
|
/**
|
|
41
54
|
* Request the user passphrase.
|
|
42
55
|
*
|
|
@@ -38,7 +38,9 @@ class FindPermissionsService {
|
|
|
38
38
|
async findAllByAcoForeignKeyForDisplay(resourceId) {
|
|
39
39
|
assertUuid(resourceId, `Service error. The id '${resourceId}' is not a valid uuid.`);
|
|
40
40
|
const permissionsCollectionDto = await this.permissionService.findAllByAcoForeignKey(resourceId, FindPermissionsService.DEFAULT_CONTAIN);
|
|
41
|
-
|
|
41
|
+
const collection = new PermissionsCollection(permissionsCollectionDto);
|
|
42
|
+
collection.sort();
|
|
43
|
+
return collection;
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
/**
|
|
@@ -0,0 +1,60 @@
|
|
|
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 ResourceService from "../../api/resource/resourceService";
|
|
15
|
+
import ResourceLocalStorage from "../../local_storage/resourceLocalStorage";
|
|
16
|
+
import i18n from "../../../sdk/i18n";
|
|
17
|
+
import {assertArrayUUID} from "../../../utils/assertions";
|
|
18
|
+
import ExecuteConcurrentlyService from "../../execute/executeConcurrentlyService";
|
|
19
|
+
class DeleteResourceService {
|
|
20
|
+
/**
|
|
21
|
+
* Constructor
|
|
22
|
+
* @param {AccountEntity} account The user account
|
|
23
|
+
* @param {ApiClientOptions} apiClientOptions The api client options
|
|
24
|
+
* @param {ProgressService} progressService
|
|
25
|
+
*/
|
|
26
|
+
constructor(account, apiClientOptions, progressService) {
|
|
27
|
+
this.account = account;
|
|
28
|
+
this.resourceService = new ResourceService(apiClientOptions);
|
|
29
|
+
this.progressService = progressService;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Delete a bulk of resources
|
|
34
|
+
* @param {Array<string>} resourceIds The resourceIds
|
|
35
|
+
* @returns {Promise<void>}
|
|
36
|
+
*/
|
|
37
|
+
async deleteResources(resourceIds) {
|
|
38
|
+
assertArrayUUID(resourceIds);
|
|
39
|
+
/**
|
|
40
|
+
* 1. Delete the Resources
|
|
41
|
+
* 2. Update the local storage
|
|
42
|
+
*/
|
|
43
|
+
this.progressService.finishStep(i18n.t("Deleting Resource(s)"), true);
|
|
44
|
+
let deleteCounter = 0;
|
|
45
|
+
const deleteCallBacks = resourceId => {
|
|
46
|
+
this.progressService.updateStepMessage(i18n.t("Deleting resource(s) {{counter}}/{{total}}", {counter: ++deleteCounter, total: resourceIds.length}));
|
|
47
|
+
return this.resourceService.delete(resourceId);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const callbacks = resourceIds.map(resourceId => () => deleteCallBacks(resourceId));
|
|
51
|
+
const executeConcurrentlyService = new ExecuteConcurrentlyService();
|
|
52
|
+
await executeConcurrentlyService.execute(callbacks, 5);
|
|
53
|
+
|
|
54
|
+
this.progressService.finishStep(i18n.t("Updating resources local storage"), true);
|
|
55
|
+
await ResourceLocalStorage.deleteResources(resourceIds);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
export default DeleteResourceService;
|
|
@@ -0,0 +1,75 @@
|
|
|
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 {defaultApiClientOptions} from "passbolt-styleguide/src/shared/lib/apiClient/apiClientOptions.test.data";
|
|
16
|
+
import AccountEntity from "../../../model/entity/account/accountEntity";
|
|
17
|
+
import {defaultAccountDto} from "../../../model/entity/account/accountEntity.test.data";
|
|
18
|
+
import {defaultResourceDto} from "passbolt-styleguide/src/shared/models/entity/resource/resourceEntity.test.data";
|
|
19
|
+
import DeleteResourceService from "./deleteResourceService";
|
|
20
|
+
import ResourceLocalStorage from "../../local_storage/resourceLocalStorage";
|
|
21
|
+
import ProgressService from "../../progress/progressService";
|
|
22
|
+
|
|
23
|
+
jest.mock("../../../service/progress/progressService");
|
|
24
|
+
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
jest.clearAllMocks();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe("DeleteResourceService", () => {
|
|
30
|
+
let deleteResourceService, worker;
|
|
31
|
+
const account = new AccountEntity(defaultAccountDto());
|
|
32
|
+
const apiClientOptions = defaultApiClientOptions();
|
|
33
|
+
|
|
34
|
+
beforeEach(async() => {
|
|
35
|
+
worker = {
|
|
36
|
+
port: {
|
|
37
|
+
emit: jest.fn()
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
deleteResourceService = new DeleteResourceService(account, apiClientOptions, new ProgressService(worker, ""));
|
|
41
|
+
jest.spyOn(ResourceLocalStorage, "deleteResources");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe("DeleteResourceService::deleteResources", () => {
|
|
45
|
+
it("Should delete the resources and call local storage update", async() => {
|
|
46
|
+
expect.assertions(5);
|
|
47
|
+
|
|
48
|
+
const resourceDto1 = defaultResourceDto();
|
|
49
|
+
const resourceDto2 = defaultResourceDto();
|
|
50
|
+
const resourceDto3 = defaultResourceDto();
|
|
51
|
+
jest.spyOn(deleteResourceService.resourceService, "delete").mockImplementation(() => {});
|
|
52
|
+
await deleteResourceService.deleteResources([resourceDto1.id, resourceDto2.id, resourceDto3.id]);
|
|
53
|
+
|
|
54
|
+
expect(deleteResourceService.resourceService.delete).toHaveBeenCalledTimes(3);
|
|
55
|
+
expect(deleteResourceService.resourceService.delete).toHaveBeenCalledWith(resourceDto1.id);
|
|
56
|
+
expect(deleteResourceService.resourceService.delete).toHaveBeenCalledWith(resourceDto2.id);
|
|
57
|
+
expect(deleteResourceService.resourceService.delete).toHaveBeenCalledWith(resourceDto3.id);
|
|
58
|
+
expect(ResourceLocalStorage.deleteResources).toHaveBeenCalledWith([resourceDto1.id, resourceDto2.id, resourceDto3.id]);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("Should call progress service during the different steps of deletion", async() => {
|
|
62
|
+
expect.assertions(3);
|
|
63
|
+
|
|
64
|
+
const resourceDto1 = defaultResourceDto();
|
|
65
|
+
const resourceDto2 = defaultResourceDto();
|
|
66
|
+
const resourceDto3 = defaultResourceDto();
|
|
67
|
+
jest.spyOn(deleteResourceService.resourceService, "delete").mockImplementation(() => {});
|
|
68
|
+
await deleteResourceService.deleteResources([resourceDto1.id, resourceDto2.id, resourceDto3.id]);
|
|
69
|
+
|
|
70
|
+
expect(deleteResourceService.progressService.finishStep).toHaveBeenCalledTimes(2);
|
|
71
|
+
expect(deleteResourceService.progressService.finishStep).toHaveBeenCalledWith('Deleting Resource(s)', true);
|
|
72
|
+
expect(deleteResourceService.progressService.finishStep).toHaveBeenCalledWith("Updating resources local storage", true);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
});
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* @since 4.10.1
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
+
import CustomFieldEntity from "passbolt-styleguide/src/shared/models/entity/customField/customFieldEntity";
|
|
15
16
|
import ExternalFoldersCollection from "../../../model/entity/folder/external/externalFoldersCollection";
|
|
16
17
|
import ExternalResourcesCollection from "../../../model/entity/resource/external/externalResourcesCollection";
|
|
17
18
|
import ExternalTotpEntity from "../../../model/entity/totp/externalTotpEntity";
|
|
@@ -23,6 +24,7 @@ import DecryptPrivateKeyService from "../../crypto/decryptPrivateKeyService";
|
|
|
23
24
|
import DecryptMetadataService from "../../metadata/decryptMetadataService";
|
|
24
25
|
import DecryptAndParseResourceSecretService from "../../secret/decryptAndParseResourceSecretService";
|
|
25
26
|
import FindResourcesService from "../findResourcesService";
|
|
27
|
+
import CustomFieldsCollection from "passbolt-styleguide/src/shared/models/entity/customField/customFieldsCollection";
|
|
26
28
|
|
|
27
29
|
/**
|
|
28
30
|
* The service aim to export the resources to a file.
|
|
@@ -99,9 +101,29 @@ class ExportResourcesService {
|
|
|
99
101
|
if (plaintextSecret.totp) {
|
|
100
102
|
exportResourceEntity.totp = new ExternalTotpEntity(plaintextSecret.totp);
|
|
101
103
|
}
|
|
104
|
+
if (plaintextSecret.customFields) {
|
|
105
|
+
exportResourceEntity.customFields = this.buildCustomFieldWithSecretDto(exportResourceEntity, plaintextSecret);
|
|
106
|
+
}
|
|
102
107
|
}
|
|
103
108
|
}
|
|
104
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Build custom fields with secret
|
|
112
|
+
* @param {ExternalResourceEntity} exportResourcesFileEntity The export object
|
|
113
|
+
* @param {Object} plaintextSecret The plaintext secret
|
|
114
|
+
* @returns {CustomFieldsCollection}
|
|
115
|
+
*/
|
|
116
|
+
buildCustomFieldWithSecretDto(exportResourceEntity, plaintextSecret) {
|
|
117
|
+
const customFieldsDto = [];
|
|
118
|
+
exportResourceEntity.customFields?.items?.forEach(customField => {
|
|
119
|
+
const customFieldDto = customField.toDto();
|
|
120
|
+
const secret = plaintextSecret.customFields.find(customFieldSecret => customFieldSecret.id === customFieldDto.id);
|
|
121
|
+
customFieldDto.secret_value = secret?.secret_value;
|
|
122
|
+
customFieldsDto.push(new CustomFieldEntity(customFieldDto));
|
|
123
|
+
});
|
|
124
|
+
return new CustomFieldsCollection(customFieldsDto);
|
|
125
|
+
}
|
|
126
|
+
|
|
105
127
|
/**
|
|
106
128
|
* Export
|
|
107
129
|
* @param {ExportResourcesFileEntity} exportResourcesFileEntity The export object
|
|
@@ -46,6 +46,8 @@ import {defaultDecryptedSharedMetadataKeysDtos} from "passbolt-styleguide/src/sh
|
|
|
46
46
|
import MetadataKeysCollection from "passbolt-styleguide/src/shared/models/entity/metadata/metadataKeysCollection";
|
|
47
47
|
import EncryptMetadataService from "../../metadata/encryptMetadataService";
|
|
48
48
|
import {defaultMetadataKeysSettingsDto} from "passbolt-styleguide/src/shared/models/entity/metadata/metadataKeysSettingsEntity.test.data";
|
|
49
|
+
import CustomFieldsCollection from "passbolt-styleguide/src/shared/models/entity/customField/customFieldsCollection";
|
|
50
|
+
import {defaultCustomFieldsCollection} from "passbolt-styleguide/src/shared/models/entity/customField/customFieldsCollection.test.data";
|
|
49
51
|
|
|
50
52
|
jest.mock("../../../service/progress/progressService");
|
|
51
53
|
|
|
@@ -88,7 +90,6 @@ describe("ExportResourcesService", () => {
|
|
|
88
90
|
{format: FORMAT_CSV_LASTPASS, expected: lastpassCsvFile},
|
|
89
91
|
{format: FORMAT_CSV_1PASSWORD, expected: onePasswordCsvFile},
|
|
90
92
|
{format: FORMAT_CSV_CHROMIUM, expected: chromiumCsvFile},
|
|
91
|
-
{format: FORMAT_CSV_BITWARDEN, expected: bitwardenCsvFile},
|
|
92
93
|
{format: FORMAT_CSV_MOZILLA, expected: mozillaCsvFile},
|
|
93
94
|
{format: FORMAT_CSV_SAFARI, expected: safariCsvFile},
|
|
94
95
|
{format: FORMAT_CSV_DASHLANE, expected: dashlaneCsvFile},
|
|
@@ -136,6 +137,7 @@ describe("ExportResourcesService", () => {
|
|
|
136
137
|
});
|
|
137
138
|
});
|
|
138
139
|
each([
|
|
140
|
+
{format: FORMAT_CSV_BITWARDEN, expected: bitwardenCsvFile},
|
|
139
141
|
{format: FORMAT_CSV_KDBX, expected: KdbxCsvFile},
|
|
140
142
|
]).describe("Should export the csv file with password, description and totp.", test => {
|
|
141
143
|
each([
|
|
@@ -322,4 +324,49 @@ describe("ExportResourcesService", () => {
|
|
|
322
324
|
expect(service.progressService.finishStep).toHaveBeenCalledWith("Decrypting 1/1");
|
|
323
325
|
});
|
|
324
326
|
});
|
|
327
|
+
|
|
328
|
+
describe("::buildCustomFieldWithSecretDto", () => {
|
|
329
|
+
it("Should build custom fields with secret", () => {
|
|
330
|
+
expect.assertions(4);
|
|
331
|
+
|
|
332
|
+
const customFieldsCollection = defaultCustomFieldsCollection();
|
|
333
|
+
|
|
334
|
+
const plaintextSecret = {
|
|
335
|
+
customFields: [
|
|
336
|
+
{id: customFieldsCollection[0].id, secret_value: "Secret Value 1"},
|
|
337
|
+
{id: customFieldsCollection[1].id, secret_value: "Secret Value 2"}
|
|
338
|
+
]
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
const exportResourceEntity = {
|
|
342
|
+
customFields: new CustomFieldsCollection(customFieldsCollection)
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
const result = service.buildCustomFieldWithSecretDto(exportResourceEntity, plaintextSecret);
|
|
346
|
+
|
|
347
|
+
expect(result).toBeInstanceOf(CustomFieldsCollection);
|
|
348
|
+
expect(result.items).toHaveLength(2);
|
|
349
|
+
expect(result.items[0].value).toEqual("Secret Value 1");
|
|
350
|
+
expect(result.items[1].value).toEqual("Secret Value 2");
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
it("Should handle missing custom fields", () => {
|
|
354
|
+
expect.assertions(2);
|
|
355
|
+
|
|
356
|
+
const exportResourceEntity = {
|
|
357
|
+
customFields: {
|
|
358
|
+
items: []
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
const plaintextSecret = {
|
|
363
|
+
customFields: []
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
const result = service.buildCustomFieldWithSecretDto(exportResourceEntity, plaintextSecret);
|
|
367
|
+
|
|
368
|
+
expect(result).toBeInstanceOf(CustomFieldsCollection);
|
|
369
|
+
expect(result.items).toHaveLength(0);
|
|
370
|
+
});
|
|
371
|
+
});
|
|
325
372
|
});
|