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
package/src/all/background_page/model/import/resources/csvRowParser/csvLogMeOnceRowParser.js
CHANGED
|
@@ -23,7 +23,7 @@ class CsvLogMeOnceRowParser extends AbstractCsvRowParser {
|
|
|
23
23
|
static get mapping() {
|
|
24
24
|
return {
|
|
25
25
|
"name": "name",
|
|
26
|
-
"
|
|
26
|
+
"uris": "url",
|
|
27
27
|
"description": "note",
|
|
28
28
|
"folder_parent_path": "group",
|
|
29
29
|
"username": "username",
|
|
@@ -44,10 +44,13 @@ class CsvLogMeOnceRowParser extends AbstractCsvRowParser {
|
|
|
44
44
|
const externalResourceDto = {};
|
|
45
45
|
|
|
46
46
|
for (const propertyName in this.mapping) {
|
|
47
|
-
if (
|
|
47
|
+
if (propertyName === "uris") {
|
|
48
|
+
externalResourceDto[propertyName] = [data[this.mapping[propertyName]]];
|
|
49
|
+
} else if (data[this.mapping[propertyName]]) {
|
|
48
50
|
externalResourceDto[propertyName] = data[this.mapping[propertyName]];
|
|
49
51
|
}
|
|
50
52
|
}
|
|
53
|
+
|
|
51
54
|
resourceTypesCollection.filterByResourceTypeVersion(metadataTypesSettings.defaultResourceTypes);
|
|
52
55
|
const scores = ResourcesTypeImportParser.getScores(externalResourceDto, resourceTypesCollection);
|
|
53
56
|
let resourceType = ResourcesTypeImportParser.findMatchingResourceType(resourceTypesCollection, scores);
|
package/src/all/background_page/model/import/resources/csvRowParser/csvLogMeOnceRowParser.test.js
CHANGED
|
@@ -68,7 +68,7 @@ describe("CsvLogMeOnceRowParser", () => {
|
|
|
68
68
|
const expectedEntity = new ExternalResourceEntity({
|
|
69
69
|
name: data.name,
|
|
70
70
|
username: data.username,
|
|
71
|
-
|
|
71
|
+
uris: [data.url],
|
|
72
72
|
resource_type_id: expectedResourceType.id,
|
|
73
73
|
secret_clear: data.password,
|
|
74
74
|
description: data.note,
|
|
@@ -105,7 +105,7 @@ describe("CsvLogMeOnceRowParser", () => {
|
|
|
105
105
|
const expectedEntity = new ExternalResourceEntity({
|
|
106
106
|
name: data.name,
|
|
107
107
|
username: data.username,
|
|
108
|
-
|
|
108
|
+
uris: [data.url],
|
|
109
109
|
resource_type_id: expectedResourceType.id,
|
|
110
110
|
secret_clear: data.password,
|
|
111
111
|
description: data.note,
|
package/src/all/background_page/model/import/resources/csvRowParser/csvMozillaPlatformRowParser.js
CHANGED
|
@@ -24,7 +24,7 @@ class CsvMozillaPlatformRowParser extends AbstractCsvRowParser {
|
|
|
24
24
|
return {
|
|
25
25
|
"name": "url",
|
|
26
26
|
"username": "username",
|
|
27
|
-
"
|
|
27
|
+
"uris": "url",
|
|
28
28
|
"secret_clear": "password",
|
|
29
29
|
};
|
|
30
30
|
}
|
|
@@ -41,7 +41,9 @@ class CsvMozillaPlatformRowParser extends AbstractCsvRowParser {
|
|
|
41
41
|
const externalResourceDto = {};
|
|
42
42
|
|
|
43
43
|
for (const propertyName in this.mapping) {
|
|
44
|
-
if (
|
|
44
|
+
if (propertyName === "uris") {
|
|
45
|
+
externalResourceDto[propertyName] = [data[this.mapping[propertyName]]];
|
|
46
|
+
} else if (data[this.mapping[propertyName]]) {
|
|
45
47
|
externalResourceDto[propertyName] = data[this.mapping[propertyName]];
|
|
46
48
|
}
|
|
47
49
|
}
|
|
@@ -56,7 +58,7 @@ class CsvMozillaPlatformRowParser extends AbstractCsvRowParser {
|
|
|
56
58
|
}
|
|
57
59
|
if (!resourceType) {
|
|
58
60
|
//Fallback default content type not supported
|
|
59
|
-
resourceType = ResourcesTypeImportParser.fallbackDefaulResourceType(resourceTypesCollection,
|
|
61
|
+
resourceType = ResourcesTypeImportParser.fallbackDefaulResourceType(resourceTypesCollection, metadataTypesSettings);
|
|
60
62
|
importEntity.importResourcesErrors.push(new ImportError("Imported with default content type", externalResourceDto, new Error("No resource type associated to this row.")));
|
|
61
63
|
}
|
|
62
64
|
}
|
|
@@ -65,7 +65,7 @@ describe("CsvMozillaPlatformRowParser", () => {
|
|
|
65
65
|
const expectedEntity = new ExternalResourceEntity({
|
|
66
66
|
name: data.name,
|
|
67
67
|
username: data.username,
|
|
68
|
-
|
|
68
|
+
uris: [data.url],
|
|
69
69
|
resource_type_id: expectedResourceType.id,
|
|
70
70
|
secret_clear: data.password,
|
|
71
71
|
});
|
|
@@ -98,7 +98,7 @@ describe("CsvMozillaPlatformRowParser", () => {
|
|
|
98
98
|
const expectedEntity = new ExternalResourceEntity({
|
|
99
99
|
name: data.name,
|
|
100
100
|
username: data.username,
|
|
101
|
-
|
|
101
|
+
uris: [data.url],
|
|
102
102
|
resource_type_id: expectedResourceType.id,
|
|
103
103
|
secret_clear: data.password,
|
|
104
104
|
});
|
|
@@ -23,7 +23,7 @@ class CsvNordpassRowParser extends AbstractCsvRowParser {
|
|
|
23
23
|
static get mapping() {
|
|
24
24
|
return {
|
|
25
25
|
"name": "name",
|
|
26
|
-
"
|
|
26
|
+
"uris": "url",
|
|
27
27
|
"username": "username",
|
|
28
28
|
"secret_clear": "password",
|
|
29
29
|
"description": "note",
|
|
@@ -57,7 +57,9 @@ class CsvNordpassRowParser extends AbstractCsvRowParser {
|
|
|
57
57
|
const externalResourceDto = {};
|
|
58
58
|
|
|
59
59
|
for (const propertyName in this.mapping) {
|
|
60
|
-
if (
|
|
60
|
+
if (propertyName === "uris") {
|
|
61
|
+
externalResourceDto[propertyName] = [data[this.mapping[propertyName]]];
|
|
62
|
+
} else if (data[this.mapping[propertyName]]) {
|
|
61
63
|
externalResourceDto[propertyName] = data[this.mapping[propertyName]];
|
|
62
64
|
}
|
|
63
65
|
}
|
package/src/all/background_page/model/import/resources/csvRowParser/csvNordpassRowParser.test.js
CHANGED
|
@@ -66,7 +66,7 @@ describe("CsvNordpassRowParser", () => {
|
|
|
66
66
|
const expectedEntity = new ExternalResourceEntity({
|
|
67
67
|
name: data.name,
|
|
68
68
|
username: data.username,
|
|
69
|
-
|
|
69
|
+
uris: [data.url],
|
|
70
70
|
resource_type_id: expectedResourceType.id,
|
|
71
71
|
secret_clear: data.password,
|
|
72
72
|
description: data.note,
|
|
@@ -102,7 +102,7 @@ describe("CsvNordpassRowParser", () => {
|
|
|
102
102
|
const expectedEntity = new ExternalResourceEntity({
|
|
103
103
|
name: data.name,
|
|
104
104
|
username: data.username,
|
|
105
|
-
|
|
105
|
+
uris: [data.url],
|
|
106
106
|
resource_type_id: expectedResourceType.id,
|
|
107
107
|
secret_clear: data.password,
|
|
108
108
|
description: data.note,
|
|
@@ -23,7 +23,7 @@ class CsvSafariRowParser extends AbstractCsvRowParser {
|
|
|
23
23
|
static get mapping() {
|
|
24
24
|
return {
|
|
25
25
|
"name": "Title",
|
|
26
|
-
"
|
|
26
|
+
"uris": "URL",
|
|
27
27
|
"username": "Username",
|
|
28
28
|
"secret_clear": "Password",
|
|
29
29
|
"description": "Notes",
|
|
@@ -42,7 +42,9 @@ class CsvSafariRowParser extends AbstractCsvRowParser {
|
|
|
42
42
|
static parse(data, importEntity, resourceTypesCollection, metadataTypesSettings) {
|
|
43
43
|
const externalResourceDto = {};
|
|
44
44
|
for (const propertyName in this.mapping) {
|
|
45
|
-
if (
|
|
45
|
+
if (propertyName === "uris") {
|
|
46
|
+
externalResourceDto[propertyName] = [data[this.mapping[propertyName]]];
|
|
47
|
+
} else if (data[this.mapping[propertyName]]) {
|
|
46
48
|
externalResourceDto[propertyName] = data[this.mapping[propertyName]];
|
|
47
49
|
}
|
|
48
50
|
}
|
package/src/all/background_page/model/import/resources/csvRowParser/csvSafariRowParser.test.js
CHANGED
|
@@ -65,7 +65,7 @@ describe("CsvSafariRowParser", () => {
|
|
|
65
65
|
const expectedEntity = new ExternalResourceEntity({
|
|
66
66
|
name: data.Title,
|
|
67
67
|
username: data.Username,
|
|
68
|
-
|
|
68
|
+
uris: [data.URL],
|
|
69
69
|
resource_type_id: expectedResourceType.id,
|
|
70
70
|
secret_clear: data.Password,
|
|
71
71
|
description: data.Notes,
|
|
@@ -99,7 +99,7 @@ describe("CsvSafariRowParser", () => {
|
|
|
99
99
|
const expectedEntity = new ExternalResourceEntity({
|
|
100
100
|
name: data.Title,
|
|
101
101
|
username: data.Username,
|
|
102
|
-
|
|
102
|
+
uris: [data.URL],
|
|
103
103
|
resource_type_id: expectedResourceType.id,
|
|
104
104
|
secret_clear: data.Password,
|
|
105
105
|
description: data.Notes,
|
|
Binary file
|
package/src/all/background_page/model/import/resources/kdbx/kdbx-multiple-uris-with-33-entries.kdbx
ADDED
|
Binary file
|
|
Binary file
|
package/src/all/background_page/model/import/resources/kdbx/kdbx-with-protected-custom-fields.kdbx
ADDED
|
Binary file
|
|
@@ -315,7 +315,7 @@ describe("ResourcesCsvImportParser", () => {
|
|
|
315
315
|
return Object.assign({
|
|
316
316
|
name: `Password ${num}`,
|
|
317
317
|
username: `username${num}`,
|
|
318
|
-
|
|
318
|
+
uris: [`https://url${num}.com`],
|
|
319
319
|
description: `Description ${num}`,
|
|
320
320
|
secret_clear: `Secret ${num}`,
|
|
321
321
|
folder_parent_path: ``,
|
|
@@ -17,6 +17,11 @@ import * as kdbxweb from 'kdbxweb';
|
|
|
17
17
|
import ExternalTotpEntity from "../../entity/totp/externalTotpEntity";
|
|
18
18
|
import ResourcesTypeImportParser from "./resourcesTypeImportParser";
|
|
19
19
|
import {ICON_TYPE_KEEPASS_ICON_SET} from "passbolt-styleguide/src/shared/models/entity/resource/metadata/IconEntity";
|
|
20
|
+
import {CUSTOM_FIELD_TYPE} from "passbolt-styleguide/src/shared/models/entity/customField/customFieldEntity";
|
|
21
|
+
import {v4 as uuidv4} from "uuid";
|
|
22
|
+
|
|
23
|
+
const KDBX_SUPPORTED_FIELDS = ['Title', 'URL', 'UserName', 'Notes', 'otp', 'TimeOtp-Secret-Base32', 'TimeOtp-Algorithm', 'TimeOtp-Length', 'TimeOtp-Period', 'Password'];
|
|
24
|
+
|
|
20
25
|
|
|
21
26
|
class ResourcesKdbxImportParser {
|
|
22
27
|
/**
|
|
@@ -126,7 +131,6 @@ class ResourcesKdbxImportParser {
|
|
|
126
131
|
parseResource(kdbxEntry) {
|
|
127
132
|
const externalResourceDto = {
|
|
128
133
|
name: kdbxEntry.fields.get('Title') ? kdbxEntry.fields.get('Title').trim() : "",
|
|
129
|
-
uri: kdbxEntry.fields.get('URL') ? kdbxEntry.fields.get('URL').trim() : "",
|
|
130
134
|
username: kdbxEntry.fields.get('UserName') ? kdbxEntry.fields.get('UserName').trim() : "",
|
|
131
135
|
description: kdbxEntry.fields.get('Notes') ? kdbxEntry.fields.get('Notes').trim() : "",
|
|
132
136
|
folder_parent_path: this.getKdbxEntryPath(kdbxEntry),
|
|
@@ -137,44 +141,14 @@ class ResourcesKdbxImportParser {
|
|
|
137
141
|
if (typeof kdbxEntry.fields.get('Password') === 'object') {
|
|
138
142
|
externalResourceDto.secret_clear = kdbxEntry.fields.get('Password').getText();
|
|
139
143
|
}
|
|
140
|
-
|
|
141
144
|
try {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
externalResourceDto.totp = totp;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
this.resourceTypesCollection.filterByResourceTypeVersion(this.metadataTypesSettings.defaultResourceTypes);
|
|
148
|
-
|
|
149
|
-
const scores = ResourcesTypeImportParser.getScores(externalResourceDto, this.resourceTypesCollection);
|
|
150
|
-
|
|
151
|
-
let resourceType = ResourcesTypeImportParser.findMatchingResourceType(this.resourceTypesCollection, scores);
|
|
152
|
-
|
|
153
|
-
if (!resourceType) {
|
|
154
|
-
resourceType = ResourcesTypeImportParser.findPartialResourceType(this.resourceTypesCollection, scores);
|
|
155
|
-
if (resourceType) {
|
|
156
|
-
this.importEntity.importResourcesErrors.push(new ImportError("Resource partially imported", externalResourceDto));
|
|
157
|
-
}
|
|
158
|
-
if (!resourceType) {
|
|
159
|
-
//Fallback default content type not supported
|
|
160
|
-
resourceType = ResourcesTypeImportParser.fallbackDefaulResourceType(this.resourceTypesCollection, this.metadataTypesSettings);
|
|
161
|
-
this.importEntity.importResourcesErrors.push(new ImportError("Content type not supported but imported with default resource type", externalResourceDto));
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
if ((kdbxEntry.bgColor || kdbxEntry.icon) && resourceType.isV5()) {
|
|
166
|
-
externalResourceDto.icon = {};
|
|
167
|
-
|
|
168
|
-
if (kdbxEntry.icon) {
|
|
169
|
-
externalResourceDto.icon.type = ICON_TYPE_KEEPASS_ICON_SET;
|
|
170
|
-
externalResourceDto.icon.value = kdbxEntry.icon;
|
|
171
|
-
}
|
|
145
|
+
this.parseUris(kdbxEntry, externalResourceDto);
|
|
146
|
+
this.parseTotp(kdbxEntry, externalResourceDto);
|
|
172
147
|
|
|
173
|
-
|
|
174
|
-
externalResourceDto.icon.background_color = kdbxEntry.bgColor;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
148
|
+
const resourceType = this.getResourceType(externalResourceDto);
|
|
177
149
|
|
|
150
|
+
this.parseIcon(kdbxEntry, externalResourceDto, resourceType);
|
|
151
|
+
this.parseCustomFields(kdbxEntry, externalResourceDto, resourceType);
|
|
178
152
|
//resourceType should never be empty to not block end user
|
|
179
153
|
externalResourceDto.resource_type_id = resourceType.id;
|
|
180
154
|
|
|
@@ -189,20 +163,129 @@ class ResourcesKdbxImportParser {
|
|
|
189
163
|
}
|
|
190
164
|
|
|
191
165
|
/**
|
|
192
|
-
*
|
|
166
|
+
* Parse URIs from a kdbx entry
|
|
167
|
+
* @param {KdbxEntry} kdbxEntry The kdbx entry
|
|
168
|
+
* @param {ExternalResourceDto} externalResourceDto The external resource dto
|
|
169
|
+
* @private
|
|
170
|
+
* @return {void}
|
|
171
|
+
*/
|
|
172
|
+
parseUris(kdbxEntry, externalResourceDto) {
|
|
173
|
+
const uri = kdbxEntry.fields.get('URL') ? kdbxEntry.fields.get('URL').trim() : "";
|
|
174
|
+
const additionalUris = [uri];
|
|
175
|
+
|
|
176
|
+
let additionalEntriesUris = [...kdbxEntry.fields.entries()]
|
|
177
|
+
.filter(([key]) => key.startsWith('KP2A_URL'))
|
|
178
|
+
.map(([, value]) => (value));
|
|
179
|
+
|
|
180
|
+
if (additionalEntriesUris.length > 31) {
|
|
181
|
+
this.importEntity.importResourcesErrors.push(new ImportError(
|
|
182
|
+
"Resource has more than 32 URIs, only the first 32 will be imported",
|
|
183
|
+
externalResourceDto
|
|
184
|
+
));
|
|
185
|
+
}
|
|
186
|
+
additionalEntriesUris = additionalEntriesUris.slice(0, 31);
|
|
187
|
+
|
|
188
|
+
for (const additionalUri of additionalEntriesUris) {
|
|
189
|
+
additionalUris.push(additionalUri.trim());
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
externalResourceDto.uris = additionalUris;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Parse the icon of the kdbx entry
|
|
196
|
+
* @param {kdbxweb.KdbxEntry} kdbxEntry
|
|
197
|
+
* @param {ExternalResourceDto} externalResourceDto
|
|
198
|
+
* @param {ResourceTypeEntity} resourceType
|
|
199
|
+
* @private
|
|
200
|
+
* @returns {void}
|
|
201
|
+
*/
|
|
202
|
+
parseIcon(kdbxEntry, externalResourceDto, resourceType) {
|
|
203
|
+
if ((kdbxEntry.bgColor || kdbxEntry.icon) && resourceType.isV5()) {
|
|
204
|
+
externalResourceDto.icon = {};
|
|
205
|
+
|
|
206
|
+
if (kdbxEntry.icon) {
|
|
207
|
+
externalResourceDto.icon.type = ICON_TYPE_KEEPASS_ICON_SET;
|
|
208
|
+
externalResourceDto.icon.value = kdbxEntry.icon;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (kdbxEntry.bgColor) {
|
|
212
|
+
externalResourceDto.icon.background_color = kdbxEntry.bgColor;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Parse the custom fields of the kdbx entry
|
|
219
|
+
* @param {kdbxEntry} kdbxEntry
|
|
220
|
+
* @param {ExternalResourceDto} externalResourceDto
|
|
221
|
+
* @param {ResourceTypeEntity} resourceType
|
|
222
|
+
* @private
|
|
223
|
+
* @returns {void}
|
|
224
|
+
*/
|
|
225
|
+
parseCustomFields(kdbxEntry, externalResourceDto, resourceType) {
|
|
226
|
+
if (resourceType.isV5()) {
|
|
227
|
+
const customFields = [];
|
|
228
|
+
kdbxEntry.fields.forEach((value, key) => {
|
|
229
|
+
if (!KDBX_SUPPORTED_FIELDS.includes(key) && !key.startsWith('KP2A_URL')) {
|
|
230
|
+
const customFieldValue = typeof value === 'string' ? value : value.getText();
|
|
231
|
+
customFields.push({
|
|
232
|
+
id: uuidv4(),
|
|
233
|
+
type: CUSTOM_FIELD_TYPE.TEXT,
|
|
234
|
+
metadata_key: key,
|
|
235
|
+
secret_value: customFieldValue
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
if (customFields.length > 0) {
|
|
240
|
+
externalResourceDto.custom_fields = customFields;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* parse the totp of the kdbx entry
|
|
193
247
|
* @param {kdbxweb.KdbxEntry} kdbxEntry
|
|
194
|
-
* @
|
|
248
|
+
* @param {ExternalResourceDto} externalResourceDto
|
|
249
|
+
* @private
|
|
250
|
+
* @returns {void}
|
|
195
251
|
*/
|
|
196
|
-
|
|
252
|
+
parseTotp(kdbxEntry, externalResourceDto) {
|
|
197
253
|
if (kdbxEntry.fields.get('otp')) {
|
|
198
254
|
const totpUrl = typeof kdbxEntry.fields.get('otp') === 'object' ? kdbxEntry.fields.get('otp').getText() : kdbxEntry.fields.get('otp');
|
|
199
255
|
const totpUrlDecoded = new URL(decodeURIComponent(totpUrl));
|
|
200
256
|
const totp = ExternalTotpEntity.createTotpFromUrl(totpUrlDecoded);
|
|
201
|
-
|
|
257
|
+
externalResourceDto.totp = totp.toDto();
|
|
202
258
|
} else if (typeof kdbxEntry.fields.get('TimeOtp-Secret-Base32') === 'object') {
|
|
203
259
|
const totp = ExternalTotpEntity.createTotpFromKdbxWindows(kdbxEntry.fields);
|
|
204
|
-
|
|
260
|
+
externalResourceDto.totp = totp.toDto();
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Get the resource type
|
|
266
|
+
* @param {ExternalResourceDto} externalResourceDto
|
|
267
|
+
* @return {ResourceTypeDto}
|
|
268
|
+
*/
|
|
269
|
+
getResourceType(externalResourceDto) {
|
|
270
|
+
this.resourceTypesCollection.filterByResourceTypeVersion(this.metadataTypesSettings.defaultResourceTypes);
|
|
271
|
+
|
|
272
|
+
const scores = ResourcesTypeImportParser.getScores(externalResourceDto, this.resourceTypesCollection);
|
|
273
|
+
|
|
274
|
+
let resourceType = ResourcesTypeImportParser.findMatchingResourceType(this.resourceTypesCollection, scores);
|
|
275
|
+
|
|
276
|
+
if (resourceType) {
|
|
277
|
+
return resourceType;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
resourceType = ResourcesTypeImportParser.findPartialResourceType(this.resourceTypesCollection, scores);
|
|
281
|
+
if (resourceType) {
|
|
282
|
+
this.importEntity.importResourcesErrors.push(new ImportError("Resource partially imported", externalResourceDto));
|
|
283
|
+
} else {
|
|
284
|
+
//Fallback default content type not supported
|
|
285
|
+
resourceType = ResourcesTypeImportParser.fallbackDefaulResourceType(this.resourceTypesCollection, this.metadataTypesSettings);
|
|
286
|
+
this.importEntity.importResourcesErrors.push(new ImportError("Content type not supported but imported with default resource type", externalResourceDto));
|
|
205
287
|
}
|
|
288
|
+
return resourceType;
|
|
206
289
|
}
|
|
207
290
|
|
|
208
291
|
/**
|
|
@@ -129,7 +129,7 @@ describe("ResourcesKdbxImportParser", () => {
|
|
|
129
129
|
return Object.assign({
|
|
130
130
|
name: `Password ${num}`,
|
|
131
131
|
username: `username${num}`,
|
|
132
|
-
|
|
132
|
+
uris: [`https://url${num}.com`],
|
|
133
133
|
description: `Description ${num}`,
|
|
134
134
|
secret_clear: `Secret ${num}`,
|
|
135
135
|
folder_parent_path: ``,
|
|
@@ -355,6 +355,138 @@ describe("ResourcesKdbxImportParser", () => {
|
|
|
355
355
|
expect(importEntity.importResources.items[1]._icon).toBeUndefined();
|
|
356
356
|
});
|
|
357
357
|
|
|
358
|
+
|
|
359
|
+
it("should import the multiple uris", async() => {
|
|
360
|
+
expect.assertions(2);
|
|
361
|
+
|
|
362
|
+
const metadataTypesSettings = new MetadataTypesSettingsEntity(defaultMetadataTypesSettingsV6Dto());
|
|
363
|
+
|
|
364
|
+
const file = fs.readFileSync("./src/all/background_page/model/import/resources/kdbx/kdbx-multiple-uris.kdbx", {encoding: 'base64'});
|
|
365
|
+
const importDto = {
|
|
366
|
+
"ref": "import-ref",
|
|
367
|
+
"file_type": "kdbx",
|
|
368
|
+
"file": file,
|
|
369
|
+
"options": {
|
|
370
|
+
"credentials": {
|
|
371
|
+
"password": "passbolt"
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
const importEntity = new ImportResourcesFileEntity(importDto);
|
|
376
|
+
const parser = new ResourcesKdbxImportParser(importEntity, resourceTypesCollection, metadataTypesSettings);
|
|
377
|
+
await parser.parseImport();
|
|
378
|
+
|
|
379
|
+
// Assert resources
|
|
380
|
+
expect(importEntity.importResources.items).toHaveLength(1);
|
|
381
|
+
expect(importEntity.importResources.items[0].uris).toEqual([
|
|
382
|
+
'https://main.url',
|
|
383
|
+
'https://additional1.url',
|
|
384
|
+
'https://additional2.url',
|
|
385
|
+
'https://additional3.url'
|
|
386
|
+
]);
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it("should import max 32 multiple uris", async() => {
|
|
390
|
+
expect.assertions(3);
|
|
391
|
+
|
|
392
|
+
const metadataTypesSettings = new MetadataTypesSettingsEntity(defaultMetadataTypesSettingsV6Dto());
|
|
393
|
+
|
|
394
|
+
const file = fs.readFileSync("./src/all/background_page/model/import/resources/kdbx/kdbx-multiple-uris-with-33-entries.kdbx", {encoding: 'base64'});
|
|
395
|
+
const importDto = {
|
|
396
|
+
"ref": "import-ref",
|
|
397
|
+
"file_type": "kdbx",
|
|
398
|
+
"file": file,
|
|
399
|
+
"options": {
|
|
400
|
+
"credentials": {
|
|
401
|
+
"password": "passbolt"
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
const importEntity = new ImportResourcesFileEntity(importDto);
|
|
406
|
+
const parser = new ResourcesKdbxImportParser(importEntity, resourceTypesCollection, metadataTypesSettings);
|
|
407
|
+
await parser.parseImport();
|
|
408
|
+
|
|
409
|
+
// Assert resources
|
|
410
|
+
expect(importEntity.importResources.items).toHaveLength(1);
|
|
411
|
+
expect(importEntity.importResources.items[0].uris).toHaveLength(32);
|
|
412
|
+
expect(importEntity.importResourcesErrors).toHaveLength(1);
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
it("should import custom fields", async() => {
|
|
416
|
+
expect.assertions(4);
|
|
417
|
+
|
|
418
|
+
const metadataTypesSettings = new MetadataTypesSettingsEntity(defaultMetadataTypesSettingsV6Dto());
|
|
419
|
+
|
|
420
|
+
const file = fs.readFileSync("./src/all/background_page/model/import/resources/kdbx/kdbx-custom-fields-with-uris.kdbx", {encoding: 'base64'});
|
|
421
|
+
const importDto = {
|
|
422
|
+
"ref": "import-ref",
|
|
423
|
+
"file_type": "kdbx",
|
|
424
|
+
"file": file,
|
|
425
|
+
"options": {
|
|
426
|
+
"credentials": {
|
|
427
|
+
"password": "passbolt"
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
};
|
|
431
|
+
const importEntity = new ImportResourcesFileEntity(importDto);
|
|
432
|
+
const parser = new ResourcesKdbxImportParser(importEntity, resourceTypesCollection, metadataTypesSettings);
|
|
433
|
+
await parser.parseImport();
|
|
434
|
+
|
|
435
|
+
// Assert resources
|
|
436
|
+
expect(importEntity.importResources.items).toHaveLength(1);
|
|
437
|
+
expect(importEntity.importResources.items[0].customFields).toHaveLength(3);
|
|
438
|
+
expect(importEntity.importResources.items[0].uris).toHaveLength(3);
|
|
439
|
+
expect(importEntity.importResourcesErrors).toHaveLength(0);
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
it("should import custom fields with protected values", async() => {
|
|
443
|
+
expect.assertions(4);
|
|
444
|
+
|
|
445
|
+
const metadataTypesSettings = new MetadataTypesSettingsEntity(defaultMetadataTypesSettingsV6Dto());
|
|
446
|
+
|
|
447
|
+
const file = fs.readFileSync("./src/all/background_page/model/import/resources/kdbx/kdbx-with-protected-custom-fields.kdbx", {encoding: 'base64'});
|
|
448
|
+
const importDto = {
|
|
449
|
+
"ref": "import-ref",
|
|
450
|
+
"file_type": "kdbx",
|
|
451
|
+
"file": file,
|
|
452
|
+
"options": {
|
|
453
|
+
"credentials": {
|
|
454
|
+
"password": "passbolt"
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
};
|
|
458
|
+
const importEntity = new ImportResourcesFileEntity(importDto);
|
|
459
|
+
const parser = new ResourcesKdbxImportParser(importEntity, resourceTypesCollection, metadataTypesSettings);
|
|
460
|
+
await parser.parseImport();
|
|
461
|
+
|
|
462
|
+
// Assert resources
|
|
463
|
+
expect(importEntity.importResources.items).toHaveLength(1);
|
|
464
|
+
expect(importEntity.importResources.items[0].customFields).toHaveLength(1);
|
|
465
|
+
expect(importEntity.importResources.items[0].uris).toHaveLength(1);
|
|
466
|
+
expect(importEntity.importResourcesErrors).toHaveLength(1);
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
it("should not import custom fields if the default is v4", async() => {
|
|
470
|
+
expect.assertions(2);
|
|
471
|
+
const file = fs.readFileSync("./src/all/background_page/model/import/resources/kdbx/kdbx-custom-fields-with-uris.kdbx", {encoding: 'base64'});
|
|
472
|
+
const importDto = {
|
|
473
|
+
"ref": "import-ref",
|
|
474
|
+
"file_type": "kdbx",
|
|
475
|
+
"file": file,
|
|
476
|
+
"options": {
|
|
477
|
+
"credentials": {
|
|
478
|
+
"password": "passbolt"
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
};
|
|
482
|
+
const importEntity = new ImportResourcesFileEntity(importDto);
|
|
483
|
+
const parser = new ResourcesKdbxImportParser(importEntity, resourceTypesCollection, metadataTypesSettings);
|
|
484
|
+
await parser.parseImport();
|
|
485
|
+
|
|
486
|
+
// Assert resources
|
|
487
|
+
expect(importEntity.importResources.items).toHaveLength(1);
|
|
488
|
+
expect(importEntity.importResources.items[0].customFields).toBeNull();
|
|
489
|
+
});
|
|
358
490
|
it("should not import the icon if the default is v4", async() => {
|
|
359
491
|
expect.assertions(3);
|
|
360
492
|
const file = fs.readFileSync("./src/all/background_page/model/import/resources/kdbx/kdbx-protected-with-color-and-icon.kdbx", {encoding: 'base64'});
|
|
@@ -18,7 +18,6 @@ import ResourcesImportParser from "./resourcesImportParser";
|
|
|
18
18
|
import ImportResourcesFileEntity from "../entity/import/importResourcesFileEntity";
|
|
19
19
|
import ResourcesCsvImportParser from "./resources/resourcesCsvImportParser";
|
|
20
20
|
|
|
21
|
-
|
|
22
21
|
describe("ResourcesImportParser", () => {
|
|
23
22
|
it("should be able to parse CSV file", async() => {
|
|
24
23
|
const file = "VGl0bGUsVXNlcm5hbWUsVVJMLFBhc3N3b3JkLE5vdGVzLEdyb3VwClBhc3N3b3JkIDEsdXNlcm5hbWUxLGh0dHBzOi8vdXJsMS5jb20sU2VjcmV0IDEsRGVzY3JpcHRpb24gMSxGb2xkZXIgMS9Gb2xkZXIgMgpQYXNzd29yZCAyLHVzZXJuYW1lMixodHRwczovL3VybDIuY29tLFNlY3JldCAyLERlc2NyaXB0aW9uIDIsRm9sZGVyIDEKUGFzc3dvcmQgMyx1c2VybmFtZTMsaHR0cHM6Ly91cmwzLmNvbSxTZWNyZXQgMyxEZXNjcmlwdGlvbiAzLEZvbGRlciAzL0ZvbGRlciA0ClBhc3N3b3JkIDQsdXNlcm5hbWU0LGh0dHBzOi8vdXJsNC5jb20sU2VjcmV0IDQsRGVzY3JpcHRpb24gNCxGb2xkZXIgMi9Gb2xkZXIgMQ==";
|
|
@@ -19,9 +19,7 @@ import ResourceEntity from "../entity/resource/resourceEntity";
|
|
|
19
19
|
import PermissionChangesCollection from "../entity/permission/change/permissionChangesCollection";
|
|
20
20
|
import ResourceService from "../../service/api/resource/resourceService";
|
|
21
21
|
import PlaintextEntity from "../entity/plaintext/plaintextEntity";
|
|
22
|
-
import splitBySize from "../../utils/array/splitBySize";
|
|
23
22
|
|
|
24
|
-
const BULK_OPERATION_SIZE = 5;
|
|
25
23
|
const MAX_LENGTH_PLAINTEXT = 4096;
|
|
26
24
|
|
|
27
25
|
class ResourceModel {
|
|
@@ -199,72 +197,6 @@ class ResourceModel {
|
|
|
199
197
|
await ResourceLocalStorage.updateResourcesCollection(resourcesCollection);
|
|
200
198
|
}
|
|
201
199
|
|
|
202
|
-
/**
|
|
203
|
-
* Delete a resource using Passbolt API and remove the resource from the local storage
|
|
204
|
-
*
|
|
205
|
-
* @param {string} resourceId The resource id
|
|
206
|
-
* @returns {Promise<void>}
|
|
207
|
-
*/
|
|
208
|
-
async delete(resourceId) {
|
|
209
|
-
await this.resourceService.delete(resourceId);
|
|
210
|
-
await ResourceLocalStorage.delete(resourceId);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/*
|
|
214
|
-
* ==============================================================
|
|
215
|
-
* Bulk operations
|
|
216
|
-
* ==============================================================
|
|
217
|
-
*/
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Delete a bulk of resources
|
|
221
|
-
* @param {Array<string>} resourcesIds collection The list of uuids to delete
|
|
222
|
-
* @param {{successCallback: function, errorCallback: function}?} callbacks The intermediate operation callbacks
|
|
223
|
-
* @returns {Promise<array<*>>}
|
|
224
|
-
*/
|
|
225
|
-
async bulkDelete(resourcesIds, callbacks) {
|
|
226
|
-
let result = [];
|
|
227
|
-
|
|
228
|
-
// Parallelize the operations by chunk of BULK_OPERATION_SIZE operations.
|
|
229
|
-
const chunks = splitBySize(resourcesIds, BULK_OPERATION_SIZE);
|
|
230
|
-
for (const chunkIndex in chunks) {
|
|
231
|
-
const chunk = chunks[chunkIndex];
|
|
232
|
-
const promises = chunk.map(async(resourceId, mapIndex) => {
|
|
233
|
-
const collectionIndex = (chunkIndex * BULK_OPERATION_SIZE) + mapIndex;
|
|
234
|
-
return this._bulkDelete_deleteResource(resourceId, collectionIndex, callbacks);
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
const bulkPromises = await Promise.allSettled(promises);
|
|
238
|
-
const intermediateResult = bulkPromises.map(promiseResult => promiseResult.value);
|
|
239
|
-
result = [...result, ...intermediateResult];
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
return result;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* Delete a resource for the bulkDelete function.
|
|
247
|
-
* @param {string} resourceId The resource to delete
|
|
248
|
-
* @param {int} collectionIndex The index of the resource in the initial collection
|
|
249
|
-
* @param {{successCallback: function, errorCallback: function}?} callbacks The intermediate operation callbacks
|
|
250
|
-
* @returns {Promise<ResourceEntity|Error>}
|
|
251
|
-
* @private
|
|
252
|
-
*/
|
|
253
|
-
async _bulkDelete_deleteResource(resourceId, collectionIndex, callbacks) {
|
|
254
|
-
callbacks = callbacks || {};
|
|
255
|
-
const successCallback = callbacks.successCallback || (() => {});
|
|
256
|
-
const errorCallback = callbacks.errorCallback || (() => {});
|
|
257
|
-
|
|
258
|
-
try {
|
|
259
|
-
await this.delete(resourceId);
|
|
260
|
-
successCallback(collectionIndex);
|
|
261
|
-
} catch (error) {
|
|
262
|
-
console.error(error);
|
|
263
|
-
errorCallback(error, collectionIndex);
|
|
264
|
-
throw error;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
200
|
/*
|
|
269
201
|
* ==============================================================
|
|
270
202
|
* Secret plaintext serialization
|
|
@@ -25,7 +25,7 @@ import PassboltServiceUnavailableError from "passbolt-styleguide/src/shared/lib/
|
|
|
25
25
|
import CommentEntity from "../../../model/entity/comment/commentEntity";
|
|
26
26
|
import {mockApiResponseError} from "../../../../../../test/mocks/mockApiResponse";
|
|
27
27
|
|
|
28
|
-
describe
|
|
28
|
+
describe("ActionLogService", () => {
|
|
29
29
|
let apiClientOptions, account;
|
|
30
30
|
beforeEach(async() => {
|
|
31
31
|
enableFetchMocks();
|