passbolt-browser-extension 5.13.0 → 5.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (282) hide show
  1. package/.devcontainer/Dockerfile +33 -3
  2. package/.devcontainer/devcontainer-lock.json +9 -0
  3. package/.devcontainer/post-start.sh +1 -2
  4. package/.github/workflows/codeql-analysis.yml +2 -1
  5. package/.github/workflows/release_candidate.yaml +3 -1
  6. package/.gitlab-ci.yml +1 -0
  7. package/CHANGELOG.md +202 -70
  8. package/CODEOWNERS +2 -0
  9. package/RELEASE_NOTES.md +4 -2
  10. package/package.json +9 -7
  11. package/renovate.json +6 -0
  12. package/src/all/background_page/controller/InformMenuController/InformMenuController.js +2 -5
  13. package/src/all/background_page/controller/InformMenuController/InformMenuController.test.js +31 -1
  14. package/src/all/background_page/controller/account/getAndInitializeAccountLocaleController.js +1 -1
  15. package/src/all/background_page/controller/account/getAndInitializeAccountLocaleController.test.js +6 -14
  16. package/src/all/background_page/controller/account/updatePrivateKeyController.js +7 -5
  17. package/src/all/background_page/controller/account/updatePrivateKeyController.test.js +18 -13
  18. package/src/all/background_page/controller/accountRecovery/accountRecoveryGenerateOrganizationKeyController.js +4 -2
  19. package/src/all/background_page/controller/accountRecovery/accountRecoveryGenerateOrganizationKeyController.test.js +25 -2
  20. package/src/all/background_page/controller/accountRecovery/accountRecoveryLoginController.js +1 -1
  21. package/src/all/background_page/controller/accountRecovery/accountRecoveryLoginController.test.js +10 -5
  22. package/src/all/background_page/controller/accountRecovery/recoverAccountController.js +6 -2
  23. package/src/all/background_page/controller/accountRecovery/recoverAccountController.test.js +11 -4
  24. package/src/all/background_page/controller/auth/authCheckStatus.test.data.js +6 -6
  25. package/src/all/background_page/controller/auth/authCheckStatusController.js +11 -3
  26. package/src/all/background_page/controller/auth/authCheckStatusController.test.js +74 -44
  27. package/src/all/background_page/controller/auth/authIsMfaRequiredController.js +11 -3
  28. package/src/all/background_page/controller/auth/authIsMfaRequiredController.test.js +18 -9
  29. package/src/all/background_page/controller/auth/authLoginController.js +1 -1
  30. package/src/all/background_page/controller/auth/authLoginController.test.js +10 -5
  31. package/src/all/background_page/controller/autofill/AutofillController.js +3 -3
  32. package/src/all/background_page/controller/autofill/AutofillController.test.js +20 -12
  33. package/src/all/background_page/controller/export/exportResourcesFileController.js +6 -3
  34. package/src/all/background_page/controller/export/exportResourcesFileController.test.js +34 -4
  35. package/src/all/background_page/controller/extension/onExtensionInstalledController.js +8 -2
  36. package/src/all/background_page/controller/extension/onExtensionInstalledController.test.js +5 -1
  37. package/src/all/background_page/controller/group/{getOrFindGroupsController.js → findGroupsByIdsForShareController.js} +9 -10
  38. package/src/all/background_page/controller/group/{getOrFindGroupsController.test.js → findGroupsByIdsForShareController.test.js} +8 -8
  39. package/src/all/background_page/controller/group/groupUpdateController.test.js +1 -0
  40. package/src/all/background_page/controller/import/importResourcesFileController.test.js +8 -1
  41. package/src/all/background_page/controller/informCallToActionController/informCallToActionController.js +2 -2
  42. package/src/all/background_page/controller/informCallToActionController/informCallToActionController.test.js +7 -4
  43. package/src/all/background_page/controller/locale/getLocaleController.js +3 -2
  44. package/src/all/background_page/controller/metadata/findMetadataTypesSettingsController.test.js +9 -15
  45. package/src/all/background_page/controller/metadata/getMetadataTypesSettingsController.test.js +9 -15
  46. package/src/all/background_page/controller/metadata/getOrFindMetadataKeysSettingsController.test.js +12 -22
  47. package/src/all/background_page/controller/metadata/shareMetadataKeyPrivateController.test.js +14 -2
  48. package/src/all/background_page/controller/move/moveFolderController.test.js +8 -0
  49. package/src/all/background_page/controller/move/moveResourcesController.test.js +8 -0
  50. package/src/all/background_page/controller/passwordExpiry/getOrFindPasswordExpirySettingsController.test.js +13 -8
  51. package/src/all/background_page/controller/passwordExpiry/savePasswordExpirySettingsController.js +4 -4
  52. package/src/all/background_page/controller/passwordExpiry/savePasswordExpirySettingsController.test.js +8 -10
  53. package/src/all/background_page/controller/permission/findPermissionsByIdsForShareController.js +62 -0
  54. package/src/all/background_page/controller/permission/findPermissionsByIdsForShareController.test.js +71 -0
  55. package/src/all/background_page/controller/recover/generateRecoverAccountRecoveryRequestKeyController.js +1 -1
  56. package/src/all/background_page/controller/resource/resourceCreateController.js +11 -4
  57. package/src/all/background_page/controller/resource/resourceCreateController.test.js +12 -1
  58. package/src/all/background_page/controller/resource/resourceUpdateController.js +11 -4
  59. package/src/all/background_page/controller/resource/resourceUpdateController.test.js +35 -2
  60. package/src/all/background_page/controller/resourceType/getResourceTypesController.js +5 -4
  61. package/src/all/background_page/controller/resourceType/getResourceTypesController.test.js +5 -2
  62. package/src/all/background_page/controller/resourceType/updateAllResourceTypesDeletedStatusController.js +3 -2
  63. package/src/all/background_page/controller/resourceType/updateAllResourceTypesDeletedStatusController.test.js +16 -3
  64. package/src/all/background_page/controller/secret/findSecretByResourceIdController.js +3 -3
  65. package/src/all/background_page/controller/secret/findSecretByResourceIdController.test.js +24 -0
  66. package/src/all/background_page/controller/secretRevision/findResourceSecretRevisionsForDisplayController.js +2 -1
  67. package/src/all/background_page/controller/setup/generateSetupKeyPairController.js +6 -3
  68. package/src/all/background_page/controller/setup/generateSetupKeyPairController.test.js +11 -1
  69. package/src/all/background_page/controller/setup/getAndInitSetupLocaleController.js +1 -1
  70. package/src/all/background_page/controller/setup/getAndInitSetupLocaleController.test.js +14 -18
  71. package/src/all/background_page/controller/setup/setSetupLocaleController.js +1 -1
  72. package/src/all/background_page/controller/setup/setSetupLocaleController.test.js +6 -10
  73. package/src/all/background_page/controller/setup/signInSetupController.js +6 -2
  74. package/src/all/background_page/controller/setup/signInSetupController.test.js +10 -5
  75. package/src/all/background_page/controller/share/shareOneFolderController.test.js +8 -0
  76. package/src/all/background_page/controller/share/shareResourcesController.test.js +9 -1
  77. package/src/all/background_page/controller/siteSettings/getOrFindSiteSettingsController.js +59 -0
  78. package/src/all/background_page/controller/siteSettings/getOrFindSiteSettingsController.test.js +150 -0
  79. package/src/all/background_page/controller/{group/getOrFindGroupsUsersController.js → user/getOrFindAllUsersController.js} +12 -17
  80. package/src/all/background_page/controller/user/getOrFindAllUsersController.test.js +55 -0
  81. package/src/all/background_page/controller/user/getOrFindLoggedInUserController.js +3 -3
  82. package/src/all/background_page/controller/user/getOrFindLoggedInUserController.test.js +19 -15
  83. package/src/all/background_page/controller/user/updateUserLocalStorageController.test.js +8 -5
  84. package/src/all/background_page/event/accountRecoveryEvents.js +4 -4
  85. package/src/all/background_page/event/appEvents.js +7 -2
  86. package/src/all/background_page/event/authEvents.js +2 -2
  87. package/src/all/background_page/event/groupEvents.js +4 -17
  88. package/src/all/background_page/event/informCallToActionEvents.js +1 -1
  89. package/src/all/background_page/event/informMenuEvents.js +1 -1
  90. package/src/all/background_page/event/localeEvents.js +4 -3
  91. package/src/all/background_page/event/permissionEvents.js +13 -0
  92. package/src/all/background_page/event/recoverEvents.js +4 -4
  93. package/src/all/background_page/event/resourceEvents.js +6 -15
  94. package/src/all/background_page/event/resourceTypeEvents.js +4 -3
  95. package/src/all/background_page/event/setupEvents.js +4 -4
  96. package/src/all/background_page/event/siteSettingsEvents.js +29 -0
  97. package/src/all/background_page/event/userEvents.js +4 -8
  98. package/src/all/background_page/index.js +0 -37
  99. package/src/all/background_page/model/entity/account/abstractAccountEntity.js +2 -2
  100. package/src/all/background_page/model/entity/account/accountAccountRecoveryEntity.js +7 -17
  101. package/src/all/background_page/model/entity/account/accountEntity.js +7 -14
  102. package/src/all/background_page/model/entity/account/accountKitEntity.js +1 -2
  103. package/src/all/background_page/model/entity/account/accountRecoverEntity.js +4 -14
  104. package/src/all/background_page/model/entity/account/accountSetupEntity.js +4 -14
  105. package/src/all/background_page/model/entity/account/accountTemporaryEntity.js +2 -5
  106. package/src/all/background_page/model/entity/gpgkey/generate/generateGpgKeyPairOptionsEntity.test.js +5 -5
  107. package/src/all/background_page/model/entity/localStorage/localStorageMetadataEntity.js +49 -0
  108. package/src/all/background_page/model/entity/localStorage/localStorageMetadataEntity.test.data.js +23 -0
  109. package/src/all/background_page/model/entity/localStorage/localStorageMetadataEntity.test.js +51 -0
  110. package/src/all/background_page/model/entity/{organizationSettings/organizationSettingsEntity.js → siteSettings/siteSettingsEntity.js} +17 -24
  111. package/src/all/background_page/model/entity/{organizationSettings/organizationSettingsEntity.test.data.js → siteSettings/siteSettingsEntity.test.data.js} +9 -9
  112. package/src/all/background_page/model/entity/{organizationSettings/organizationSettingsEntity.test.js → siteSettings/siteSettingsEntity.test.js} +30 -39
  113. package/src/all/background_page/model/entity/user/userEntity.test.js +6 -6
  114. package/src/all/background_page/model/export/resources/resourcesKdbxExporter.js +40 -3
  115. package/src/all/background_page/model/export/resources/resourcesKdbxExporter.test.js +122 -0
  116. package/src/all/background_page/model/import/resources/resourcesKdbxImportParser.js +1 -1
  117. package/src/all/background_page/model/locale/localeModel.js +13 -8
  118. package/src/all/background_page/model/passwordExpiry/passwordExpirySettingsModel.js +6 -6
  119. package/src/all/background_page/model/passwordExpiry/passwordExpirySettingsModel.test.js +3 -2
  120. package/src/all/background_page/model/resource/resourceModel.js +4 -4
  121. package/src/all/background_page/model/user/userModel.js +7 -28
  122. package/src/all/background_page/model/user/userModel.test.js +51 -99
  123. package/src/all/background_page/pagemod/appBootstrapPagemod.js +4 -1
  124. package/src/all/background_page/pagemod/appBootstrapPagemod.test.js +5 -2
  125. package/src/all/background_page/pagemod/appPagemod.js +32 -6
  126. package/src/all/background_page/pagemod/appPagemod.test.js +22 -10
  127. package/src/all/background_page/pagemod/authPagemod.js +2 -10
  128. package/src/all/background_page/pagemod/authPagemod.test.js +4 -4
  129. package/src/all/background_page/pagemod/pagemodManager.test.js +5 -2
  130. package/src/all/background_page/pagemod/quickAccessPagemod.js +2 -2
  131. package/src/all/background_page/pagemod/quickAccessPagemod.test.js +4 -4
  132. package/src/all/background_page/pagemod/recoverPagemod.js +2 -2
  133. package/src/all/background_page/pagemod/recoverPagemod.test.js +6 -0
  134. package/src/all/background_page/pagemod/setupPagemod.js +2 -2
  135. package/src/all/background_page/pagemod/setupPagemod.test.js +6 -0
  136. package/src/all/background_page/pagemod/webIntegrationPagemod.js +21 -2
  137. package/src/all/background_page/pagemod/webIntegrationPagemod.test.js +16 -25
  138. package/src/all/background_page/service/account/getActiveAccountService.js +2 -3
  139. package/src/all/background_page/service/account/getLegacyAccountService.js +3 -14
  140. package/src/all/background_page/service/account/updateSsoCredentialsService.js +9 -5
  141. package/src/all/background_page/service/api/group/groupApiService.js +9 -16
  142. package/src/all/background_page/service/api/group/groupApiService.test.js +59 -26
  143. package/src/all/background_page/service/api/siteSettings/siteSettingsApiService.js +46 -0
  144. package/src/all/background_page/service/api/siteSettings/siteSettingsApiService.test.js +63 -0
  145. package/src/all/background_page/service/auth/checkAuthStatusService.js +27 -14
  146. package/src/all/background_page/service/auth/checkAuthStatusService.test.js +80 -62
  147. package/src/all/background_page/service/auth/postLoginService.js +3 -3
  148. package/src/all/background_page/service/auth/postLoginService.test.js +4 -4
  149. package/src/all/background_page/service/auth/startLoopAuthSessionCheckService.js +5 -1
  150. package/src/all/background_page/service/auth/startLoopAuthSessionCheckService.test.js +14 -8
  151. package/src/all/background_page/service/authenticationStatusService.js +13 -18
  152. package/src/all/background_page/service/authenticationStatusService.test.js +9 -6
  153. package/src/all/background_page/service/crypto/generateGpgKeyPairService.test.js +5 -5
  154. package/src/all/background_page/service/crypto/getGpgKeyCreationDateService.js +7 -6
  155. package/src/all/background_page/service/crypto/getGpgKeyCreationDateService.test.js +10 -7
  156. package/src/all/background_page/service/extension/onExtensionUpdateAvailableService.js +7 -2
  157. package/src/all/background_page/service/extension/onExtensionUpdateAvailableService.test.js +5 -5
  158. package/src/all/background_page/service/group/findGroupsService.js +42 -1
  159. package/src/all/background_page/service/group/findGroupsService.test.js +82 -0
  160. package/src/all/background_page/service/group/groupUpdateSecretsCryptoService.js +82 -0
  161. package/src/all/background_page/service/group/groupUpdateSecretsCryptoService.test.js +102 -0
  162. package/src/all/background_page/service/group/groupUpdateService.js +49 -78
  163. package/src/all/background_page/service/group/groupUpdateService.test.js +136 -0
  164. package/src/all/background_page/service/localStorage/localStorageService.js +8 -6
  165. package/src/all/background_page/service/localStorage/localStorageService.test.js +33 -15
  166. package/src/all/background_page/service/local_storage/abstractLocalStorage.js +193 -0
  167. package/src/all/background_page/service/local_storage/abstractLocalStorage.test.data.js +45 -0
  168. package/src/all/background_page/service/local_storage/abstractLocalStorage.test.js +271 -0
  169. package/src/all/background_page/service/local_storage/activeSessionLocalStorage.js +105 -0
  170. package/src/all/background_page/service/local_storage/activeSessionLocalStorage.test.js +153 -0
  171. package/src/all/background_page/service/local_storage/rbacLocalStorage.js +10 -82
  172. package/src/all/background_page/service/local_storage/rbacLocalStorage.test.js +8 -8
  173. package/src/all/background_page/service/local_storage/resourceTypeLocalStorage.js +10 -43
  174. package/src/all/background_page/service/local_storage/resourceTypeLocalStorage.test.js +68 -0
  175. package/src/all/background_page/service/local_storage/siteSettingsLocalStorage.js +104 -0
  176. package/src/all/background_page/service/local_storage/siteSettingsLocalStorage.test.js +114 -0
  177. package/src/all/background_page/service/local_storage/userMeLocalStorage.js +50 -0
  178. package/src/all/background_page/service/{sessionStorage/userMeSessionStorageService.test.js → local_storage/userMeLocalStorage.test.js} +55 -36
  179. package/src/all/background_page/service/metadata/encryptMetadataService.js +3 -3
  180. package/src/all/background_page/service/metadata/encryptMetadataService.test.js +11 -11
  181. package/src/all/background_page/service/metadata/findAndUpdateMetadataSettingsLocalStorageService.js +4 -4
  182. package/src/all/background_page/service/metadata/findAndUpdateMetadataSettingsLocalStorageService.test.js +18 -16
  183. package/src/all/background_page/service/metadata/getOrFindMetadataSettingsService.test.js +6 -8
  184. package/src/all/background_page/service/metadata/rotateMetadata/rotateResourcesMetadataKeyService.test.js +4 -4
  185. package/src/all/background_page/service/metadata/shareMetadataKeyPrivateService.js +3 -3
  186. package/src/all/background_page/service/metadata/shareMetadataKeyPrivateService.test.js +1 -1
  187. package/src/all/background_page/service/metadata/verifyOrTrustMetadataKeyService.js +4 -4
  188. package/src/all/background_page/service/metadata/verifyOrTrustMetadataKeyService.test.js +9 -7
  189. package/src/all/background_page/service/migrateMetadata/migrateMetadataResourcesService.js +4 -4
  190. package/src/all/background_page/service/migrateMetadata/migrateMetadataResourcesService.test.js +6 -6
  191. package/src/all/background_page/service/rbac/findAndUpdateRbacsLocalStorageService.js +2 -2
  192. package/src/all/background_page/service/rbac/getOrFindRbacService.js +1 -1
  193. package/src/all/background_page/service/resource/create/resourceCreateService.js +41 -51
  194. package/src/all/background_page/service/resource/create/resourceCreateService.test.js +100 -98
  195. package/src/all/background_page/service/resource/export/exportResourcesService.js +7 -7
  196. package/src/all/background_page/service/resource/findAndUpdateResourcesLocalStorageService.js +4 -4
  197. package/src/all/background_page/service/resource/findResourcesService.js +13 -16
  198. package/src/all/background_page/service/resource/findResourcesService.test.js +12 -11
  199. package/src/all/background_page/service/resource/getOrFindResourcesService.js +3 -3
  200. package/src/all/background_page/service/resource/import/ImportResourcesService.js +9 -9
  201. package/src/all/background_page/service/resource/import/ImportResourcesService.test.js +30 -15
  202. package/src/all/background_page/service/resource/update/resourceUpdateService.js +38 -19
  203. package/src/all/background_page/service/resource/update/resourceUpdateService.test.js +64 -31
  204. package/src/all/background_page/service/resourceType/getOrFindResourceTypesService.js +49 -0
  205. package/src/all/background_page/service/resourceType/getOrFindResourceTypesService.test.js +61 -0
  206. package/src/all/background_page/service/resourceType/getSecretSchemaResourceTypeService.js +44 -0
  207. package/src/all/background_page/service/resourceType/updateResourceTypesService.js +6 -4
  208. package/src/all/background_page/service/resourceType/updateResourceTypesService.test.js +19 -14
  209. package/src/all/background_page/service/secretRevisions/findAndDecryptSecretRevisionsService.js +5 -4
  210. package/src/all/background_page/service/secretRevisions/findAndDecryptSecretRevisionsService.test.js +16 -9
  211. package/src/all/background_page/service/share/shareResourceService.js +4 -4
  212. package/src/all/background_page/service/share/shareResourceService.test.js +6 -6
  213. package/src/all/background_page/service/siteSettings/findAndUpdateSiteSettingsLocalStorageService.js +77 -0
  214. package/src/all/background_page/service/siteSettings/findAndUpdateSiteSettingsLocalStorageService.test.js +130 -0
  215. package/src/all/background_page/service/siteSettings/findSiteSettingsService.js +47 -0
  216. package/src/all/background_page/service/siteSettings/findSiteSettingsService.test.js +68 -0
  217. package/src/all/background_page/service/siteSettings/getOrFindSiteSettingsService.js +84 -0
  218. package/src/all/background_page/service/siteSettings/getOrFindSiteSettingsService.test.js +175 -0
  219. package/src/all/background_page/service/siteSettings/siteSettingsRuntimeCache.js +70 -0
  220. package/src/all/background_page/service/sso/generateSsoKitService.test.js +2 -2
  221. package/src/all/background_page/service/toolbar/toolbarService.js +6 -4
  222. package/src/all/background_page/service/toolbar/toolbarService.test.js +14 -13
  223. package/src/all/background_page/service/user/findAndUpdateUsersLocalStorageService.js +4 -4
  224. package/src/all/background_page/service/user/findAndUpdateUsersLocalStorageService.test.js +3 -3
  225. package/src/all/background_page/service/user/getOrFindMeService.js +64 -0
  226. package/src/all/background_page/service/user/getOrFindMeService.test.js +65 -0
  227. package/src/all/background_page/service/userKeyPolicies/findUserKeyPoliciesSettingsService.js +5 -4
  228. package/src/all/background_page/service/userKeyPolicies/findUserKeyPoliciesSettingsService.test.js +12 -11
  229. package/src/all/background_page/service/validator/appEmailValidatorService.js +11 -6
  230. package/src/all/background_page/service/validator/appEmailValidatorService.test.js +11 -11
  231. package/src/all/common/polyfill/browserPolyfill.js +8 -8
  232. package/src/all/locales/cs-CZ/common.json +1 -4
  233. package/src/all/locales/de-DE/common.json +1 -4
  234. package/src/all/locales/en-UK/common.json +0 -3
  235. package/src/all/locales/es-ES/common.json +1 -4
  236. package/src/all/locales/fr-FR/common.json +1 -4
  237. package/src/all/locales/it-IT/common.json +1 -4
  238. package/src/all/locales/ja-JP/common.json +1 -4
  239. package/src/all/locales/ko-KR/common.json +0 -3
  240. package/src/all/locales/lt-LT/common.json +1 -4
  241. package/src/all/locales/nl-NL/common.json +1 -4
  242. package/src/all/locales/pl-PL/common.json +1 -4
  243. package/src/all/locales/pt-BR/common.json +1 -4
  244. package/src/all/locales/ro-RO/common.json +1 -4
  245. package/src/all/locales/ru-RU/common.json +1 -4
  246. package/src/all/locales/sl-SI/common.json +1 -4
  247. package/src/all/locales/sv-SE/common.json +1 -4
  248. package/src/all/locales/uk-UA/common.json +1 -4
  249. package/src/all/webAccessibleResources/js/app/QuickAccess.js +7 -0
  250. package/src/chrome/manifest.json +1 -1
  251. package/src/chrome-mv3/manifest.json +1 -1
  252. package/src/chrome-mv3/offscreens/service/group/addUsersToGroupOffscreenService.js +132 -0
  253. package/src/chrome-mv3/offscreens/service/group/addUsersToGroupOffscreenService.test.js +125 -0
  254. package/src/chrome-mv3/offscreens/service/offscreen/handleOffscreenRequestService.js +4 -0
  255. package/src/chrome-mv3/serviceWorker/service/addUsersToGroup/requestAddUsersToGroupOffscreenService.js +83 -0
  256. package/src/chrome-mv3/serviceWorker/service/addUsersToGroup/requestAddUsersToGroupOffscreenService.test.js +116 -0
  257. package/src/chrome-mv3/serviceWorker/service/addUsersToGroup/responseAddUsersToGroupOffscreenService.js +99 -0
  258. package/src/chrome-mv3/serviceWorker/service/addUsersToGroup/responseAddUsersToGroupOffscreenService.test.data.js +45 -0
  259. package/src/chrome-mv3/serviceWorker/service/addUsersToGroup/responseAddUsersToGroupOffscreenService.test.js +87 -0
  260. package/src/chrome-mv3/serviceWorker/service/network/requestFetchOffscreenService.js +0 -1
  261. package/src/chrome-mv3/serviceWorker/service/offscreen/handleOffscreenResponseService.js +15 -0
  262. package/src/firefox/manifest.json +1 -1
  263. package/src/safari/background_page/index.js +0 -37
  264. package/src/safari/common/polyfill/safariBrowserPolyfill.js +10 -10
  265. package/src/safari/manifest.json +1 -1
  266. package/test/jest.setup.js +4 -2
  267. package/src/all/background_page/controller/group/getOrFindGroupsUsersController.test.js +0 -69
  268. package/src/all/background_page/controller/organizationSettings/getOrganizationSettingsController.js +0 -55
  269. package/src/all/background_page/controller/organizationSettings/getOrganizationSettingsController.test.js +0 -45
  270. package/src/all/background_page/controller/resource/findAllByIdsForDisplayPermissionsController.js +0 -76
  271. package/src/all/background_page/controller/resource/findAllByIdsForDisplayPermissionsController.test.js +0 -102
  272. package/src/all/background_page/event/organizationSettingsEvents.js +0 -37
  273. package/src/all/background_page/model/organizationSettings/organizationSettingsModel.js +0 -93
  274. package/src/all/background_page/model/resourceType/resourceTypeModel.js +0 -72
  275. package/src/all/background_page/model/resourceType/resourceTypeModel.test.js +0 -101
  276. package/src/all/background_page/service/api/organizationSettings/organizationSettingsService.js +0 -58
  277. package/src/all/background_page/service/group/getOrFindGroupsService.js +0 -65
  278. package/src/all/background_page/service/group/getOrFindGroupsService.test.js +0 -168
  279. package/src/all/background_page/service/group/getOrFindGroupsUsersService.js +0 -51
  280. package/src/all/background_page/service/group/getOrFindGroupsUsersService.test.js +0 -94
  281. package/src/all/background_page/service/local_storage/authStatusLocalStorage.js +0 -70
  282. package/src/all/background_page/service/sessionStorage/userMeSessionStorageService.js +0 -94
@@ -38,6 +38,7 @@ import { defaultDecryptedSharedMetadataKeysDtos } from "passbolt-styleguide/src/
38
38
  import PassphraseStorageService from "../session_storage/passphraseStorageService";
39
39
  import { OpenpgpAssertion } from "../../utils/openpgp/openpgpAssertions";
40
40
  import { mockPassboltResponse } from "passbolt-styleguide/test/mocks/mockApiResponse";
41
+ import DecryptMetadataService from "../metadata/decryptMetadataService";
41
42
 
42
43
  beforeEach(() => {
43
44
  jest.clearAllMocks();
@@ -492,42 +493,43 @@ describe("FindResourcesService", () => {
492
493
  });
493
494
  });
494
495
 
495
- describe("::findAllByIdsForDisplayPermissions", () => {
496
+ describe("::findAllPermissionsByIdsForShare", () => {
496
497
  let service, expectedContains;
497
498
 
498
499
  beforeEach(() => {
499
500
  service = new FindResourcesService(account, apiClientOptions);
500
501
  expectedContains = {
501
- permission: true,
502
502
  "permissions.user.profile": true,
503
503
  "permissions.group": true,
504
504
  };
505
505
  });
506
506
 
507
- it("should call the api only 1 times when the resource is less than 80", async () => {
508
- expect.assertions(3);
507
+ it("should request the permissions without the metadata and without decrypting it", async () => {
508
+ expect.assertions(4);
509
509
 
510
510
  const collectionDto = Array.from({ length: 80 }, () => defaultResourceDto());
511
511
  const collectionIds = collectionDto.map((collection) => collection.id);
512
512
 
513
513
  jest.spyOn(ResourceService.prototype, "findAll").mockImplementation(() => mockPassboltResponse(collectionDto));
514
+ jest.spyOn(DecryptMetadataService.prototype, "decryptAllFromForeignModels");
514
515
 
515
- const result = await service.findAllByIdsForDisplayPermissions(collectionIds);
516
+ const result = await service.findAllPermissionsByIdsForShare(collectionIds);
516
517
 
517
518
  expect(result).toEqual(new ResourcesCollection(collectionDto));
518
- expect(ResourceService.prototype.findAll).toHaveBeenCalledTimes(1);
519
519
  expect(ResourceService.prototype.findAll).toHaveBeenCalledWith(expectedContains, {
520
520
  "has-id": collectionIds,
521
521
  });
522
+ expect(ResourceService.prototype.findAll).toHaveBeenCalledTimes(1);
523
+ // No metadata is requested, so the operator is never prompted for a passphrase to decrypt it.
524
+ expect(DecryptMetadataService.prototype.decryptAllFromForeignModels).not.toHaveBeenCalled();
522
525
  });
523
526
 
524
- it("should call the api only 2 times when the resource is more than 80", async () => {
525
- expect.assertions(4);
527
+ it("should chunk the ids by 80 to avoid a too long url", async () => {
528
+ expect.assertions(3);
526
529
 
527
530
  const collectionDto = Array.from({ length: 82 }, () => defaultResourceDto());
528
531
  const resultCollectionDto = [...collectionDto];
529
532
  const collectionIds = collectionDto.map((collection) => collection.id);
530
- jest.spyOn(ResourceService.prototype, "findAll").mockImplementation(() => mockPassboltResponse(collectionDto));
531
533
 
532
534
  jest.spyOn(ResourceService.prototype, "findAll").mockImplementation((contains, filters) => {
533
535
  expect(contains).toEqual(expectedContains);
@@ -535,9 +537,8 @@ describe("FindResourcesService", () => {
535
537
  return mockPassboltResponse(splicedCollection);
536
538
  });
537
539
 
538
- const result = await service.findAllByIdsForDisplayPermissions(collectionIds);
540
+ await service.findAllPermissionsByIdsForShare(collectionIds);
539
541
 
540
- expect(result.toDto()).toEqual(collectionDto);
541
542
  expect(ResourceService.prototype.findAll).toHaveBeenCalledTimes(2);
542
543
  });
543
544
  });
@@ -14,8 +14,8 @@
14
14
  import ResourceLocalStorage from "../local_storage/resourceLocalStorage";
15
15
  import ResourcesCollection from "../../model/entity/resource/resourcesCollection";
16
16
  import FindAndUpdateResourcesLocalStorage from "./findAndUpdateResourcesLocalStorageService";
17
- import ResourceTypeModel from "../../model/resourceType/resourceTypeModel";
18
17
  import { assertArrayUUID } from "../../utils/assertions";
18
+ import GetOrFindResourceTypesService from "../resourceType/getOrFindResourceTypesService";
19
19
 
20
20
  /**
21
21
  * The service aims to get resources from the local storage if it is set, or retrieve them from the API and
@@ -29,7 +29,7 @@ export default class GetOrFindResourcesService {
29
29
  */
30
30
  constructor(account, apiClientOptions) {
31
31
  this.account = account;
32
- this.resourceTypeModel = new ResourceTypeModel(apiClientOptions);
32
+ this.getOrFindResourceTypesService = new GetOrFindResourceTypesService(account, apiClientOptions);
33
33
  this.findAndUpdateResourcesLocalStorage = new FindAndUpdateResourcesLocalStorage(account, apiClientOptions);
34
34
  }
35
35
 
@@ -65,7 +65,7 @@ export default class GetOrFindResourcesService {
65
65
  }
66
66
 
67
67
  const resourcesCollection = await this.getOrFindAll();
68
- const resourceTypesCollection = await this.resourceTypeModel.getOrFindAll();
68
+ const resourceTypesCollection = await this.getOrFindResourceTypesService.getOrFindAll();
69
69
 
70
70
  // Filter resource types according to what we need
71
71
  if (fieldType === "otp") {
@@ -22,7 +22,6 @@ import FolderModel from "../../../model/folder/folderModel";
22
22
  import ResourcesImportParser from "../../../model/import/resourcesImportParser";
23
23
  import Keyring from "../../../model/keyring";
24
24
  import ResourceModel from "../../../model/resource/resourceModel";
25
- import ResourceTypeModel from "../../../model/resourceType/resourceTypeModel";
26
25
  import { OpenpgpAssertion } from "../../../utils/openpgp/openpgpAssertions";
27
26
  import ResourceService from "../../api/resource/resourceService";
28
27
  import EncryptMessageService from "../../crypto/encryptMessageService";
@@ -36,8 +35,9 @@ import DecryptPrivateKeyService from "../../crypto/decryptPrivateKeyService";
36
35
  import DecryptMetadataService from "../../metadata/decryptMetadataService";
37
36
  import ResourceMetadataEntity from "passbolt-styleguide/src/shared/models/entity/resource/metadata/resourceMetadataEntity";
38
37
  import PasswordExpirySettingsGetOrFindService from "../../passwordExpirySettings/passwordExpirySettingsGetOrFindService";
39
- import OrganizationSettingsModel from "../../../model/organizationSettings/organizationSettingsModel";
38
+ import GetOrFindSiteSettingsService from "../../siteSettings/getOrFindSiteSettingsService";
40
39
  import UpdateResourceTagsService from "../../tag/updateResourceTagsService";
40
+ import GetOrFindResourceTypesService from "../../resourceType/getOrFindResourceTypesService";
41
41
 
42
42
  /**
43
43
  * The service aim to import the resources from a file and save it to the API / localstorage.
@@ -54,7 +54,6 @@ class ImportResourcesService {
54
54
  //Models
55
55
  this.resourceModel = new ResourceModel(apiClientOptions, account);
56
56
  this.folderModel = new FolderModel(apiClientOptions, account);
57
- this.resourceTypeModel = new ResourceTypeModel(apiClientOptions);
58
57
  //Services
59
58
  this.resourceService = new ResourceService(apiClientOptions);
60
59
  this.executeConcurrentlyService = new ExecuteConcurrentlyService();
@@ -63,8 +62,9 @@ class ImportResourcesService {
63
62
  this.getOrFindMetadataSettingsService = new GetOrFindMetadataSettingsService(account, apiClientOptions);
64
63
  this.encryptMetadataService = new EncryptMetadataService(apiClientOptions, account);
65
64
  this.decryptMetadataService = new DecryptMetadataService(apiClientOptions, account);
66
- this.organisationSettingsModel = new OrganizationSettingsModel(apiClientOptions);
65
+ this.getOrFindSiteSettingsService = new GetOrFindSiteSettingsService(account, apiClientOptions);
67
66
  this.passwordExpirySettingsGetOrFindService = new PasswordExpirySettingsGetOrFindService(account, apiClientOptions);
67
+ this.getOrFindResourceTypesService = new GetOrFindResourceTypesService(account, apiClientOptions);
68
68
  this.account = account;
69
69
  }
70
70
 
@@ -76,7 +76,7 @@ class ImportResourcesService {
76
76
  */
77
77
  async importFile(importResourcesFile, passphrase) {
78
78
  const userId = User.getInstance().get().id;
79
- const organizationSettings = await this.organisationSettingsModel.getOrFind();
79
+ const organizationSettings = await this.getOrFindSiteSettingsService.getOrFind(false);
80
80
  const privateKey = await DecryptPrivateKeyService.decryptArmoredKey(this.account.userPrivateArmoredKey, passphrase);
81
81
  await this.encryptSecrets(importResourcesFile, userId, privateKey);
82
82
  importResourcesFile.mustImportFolders && (await this.bulkImportFolders(importResourcesFile));
@@ -102,7 +102,7 @@ class ImportResourcesService {
102
102
  async parseFile(importResourcesFile) {
103
103
  const metadataTypesSettings = await this.getOrFindMetadataSettingsService.getOrFindTypesSettings();
104
104
  const importParser = new ResourcesImportParser();
105
- const resourceTypesCollection = await this.resourceTypeModel.getOrFindAll();
105
+ const resourceTypesCollection = await this.getOrFindResourceTypesService.getOrFindAll();
106
106
  await importParser.parseImport(importResourcesFile, resourceTypesCollection, metadataTypesSettings);
107
107
 
108
108
  // Now that we know about the content of the import, update the progress bar goals.
@@ -133,7 +133,7 @@ class ImportResourcesService {
133
133
  if (passwordExpirySettings?.isFeatureEnabled) {
134
134
  const passwordExpiryDate = passwordExpirySettings.calculateDefaultResourceExpiryDate();
135
135
  if (passwordExpiryDate) {
136
- const resourceTypesCollection = await this.resourceTypeModel.getOrFindAll();
136
+ const resourceTypesCollection = await this.getOrFindResourceTypesService.getOrFindAll();
137
137
  resourcesCollection.setExpiryDateIfUnset(passwordExpiryDate, resourceTypesCollection);
138
138
  }
139
139
  }
@@ -165,7 +165,7 @@ class ImportResourcesService {
165
165
  let i = 0;
166
166
  const userPublicArmoredKey = this.keyring.findPublic(userId).armoredKey;
167
167
  const userPublicKey = await OpenpgpAssertion.readKeyOrFail(userPublicArmoredKey);
168
- const resourceTypes = await this.resourceTypeModel.getOrFindAll();
168
+ const resourceTypes = await this.getOrFindResourceTypesService.getOrFindAll();
169
169
  for (const importResourceEntity of importResourcesFile.importResources) {
170
170
  i++;
171
171
  await this.progressService.finishStep(
@@ -353,7 +353,7 @@ class ImportResourcesService {
353
353
  */
354
354
  async bulkImportResources(importResourcesFile, resourcesCollection, clearTextMetadataResourcesCollection) {
355
355
  let importedCount = 0;
356
- const resourceTypesCollection = await this.resourceTypeModel.getOrFindAll();
356
+ const resourceTypesCollection = await this.getOrFindResourceTypesService.getOrFindAll();
357
357
 
358
358
  const callbacks = resourcesCollection.items.map((resourceEntity, index) => async () => {
359
359
  try {
@@ -72,11 +72,15 @@ import DecryptMetadataService from "../../metadata/decryptMetadataService";
72
72
  import { defaultPasswordExpirySettingsDtoFromApi } from "passbolt-styleguide/src/shared/models/entity/passwordExpiry/passwordExpirySettingsEntity.test.data";
73
73
  import PasswordExpirySettingsService from "../../api/passwordExpiry/passwordExpirySettingsService";
74
74
  import {
75
- defaultCeOrganizationSettings,
76
- defaultProOrganizationSettings,
77
- } from "../../../model/entity/organizationSettings/organizationSettingsEntity.test.data";
78
- import OrganizationSettingsService from "../../api/organizationSettings/organizationSettingsService";
75
+ anonymousSiteSettings,
76
+ defaultCeSiteSettings,
77
+ defaultProSiteSettings,
78
+ } from "passbolt-styleguide/src/shared/models/entity/siteSettings/siteSettingsEntity.test.data";
79
+ import GetOrFindSiteSettingsService from "../../siteSettings/getOrFindSiteSettingsService";
80
+ import SiteSettingsEntity from "passbolt-styleguide/src/shared/models/entity/siteSettings/siteSettingsEntity";
79
81
  import PassboltResponseEntity from "passbolt-styleguide/src/shared/models/entity/apiService/PassboltResponseEntity";
82
+ import GetOrFindResourceTypesService from "../../resourceType/getOrFindResourceTypesService";
83
+ import ResourceTypesCollection from "passbolt-styleguide/src/shared/models/entity/resourceType/resourceTypesCollection";
80
84
 
81
85
  jest.mock("../../../service/progress/progressService");
82
86
 
@@ -119,6 +123,9 @@ describe("ImportResourcesService", () => {
119
123
  };
120
124
  decryptMetadataService = new DecryptMetadataService(apiClientOptions, account);
121
125
  importResourcesService = new ImportResourcesService(account, apiClientOptions, new ProgressService(worker, ""));
126
+ jest
127
+ .spyOn(GetOrFindSiteSettingsService.prototype, "getOrFind")
128
+ .mockImplementation(() => new SiteSettingsEntity(anonymousSiteSettings()));
122
129
  collection = resourceTypesCollectionDto();
123
130
  jest.spyOn(ResourceTypeService.prototype, "findAll").mockImplementation(() => collection);
124
131
  importResourceFileCSV = new ImportResourcesFileEntity(defaultImportResourceFileCSVDto());
@@ -402,7 +409,9 @@ describe("ImportResourcesService", () => {
402
409
  it("Should throw an error if the resource type cannot be found", async () => {
403
410
  expect.assertions(5);
404
411
 
405
- jest.spyOn(ResourceTypeService.prototype, "findAll").mockImplementation(() => []);
412
+ jest
413
+ .spyOn(GetOrFindResourceTypesService.prototype, "getOrFindAll")
414
+ .mockImplementationOnce(() => new ResourceTypesCollection([]));
406
415
 
407
416
  importResourceFileCSV = new ImportResourcesFileEntity(
408
417
  defaultImportResourceFileCSVDto({
@@ -711,8 +720,8 @@ describe("ImportResourcesService", () => {
711
720
  expect.assertions(3);
712
721
 
713
722
  jest
714
- .spyOn(OrganizationSettingsService.prototype, "find")
715
- .mockImplementation(() => defaultProOrganizationSettings());
723
+ .spyOn(GetOrFindSiteSettingsService.prototype, "getOrFind")
724
+ .mockImplementation(() => new SiteSettingsEntity(defaultProSiteSettings()));
716
725
 
717
726
  jest.spyOn(PasswordExpirySettingsService.prototype, "find").mockImplementation(() =>
718
727
  defaultPasswordExpirySettingsDtoFromApi({
@@ -737,10 +746,12 @@ describe("ImportResourcesService", () => {
737
746
  it("password expiry plugin is disabled", async () => {
738
747
  expect.assertions(3);
739
748
 
740
- const organizationSettings = defaultProOrganizationSettings();
749
+ const organizationSettings = defaultProSiteSettings();
741
750
  organizationSettings.passbolt.plugins.passwordExpiry.enabled = false;
742
751
 
743
- jest.spyOn(OrganizationSettingsService.prototype, "find").mockImplementation(() => organizationSettings);
752
+ jest
753
+ .spyOn(GetOrFindSiteSettingsService.prototype, "getOrFind")
754
+ .mockImplementation(() => new SiteSettingsEntity(organizationSettings));
744
755
 
745
756
  jest.spyOn(PasswordExpirySettingsService.prototype, "find").mockImplementation(() =>
746
757
  defaultPasswordExpirySettingsDtoFromApi({
@@ -764,10 +775,12 @@ describe("ImportResourcesService", () => {
764
775
  it("password expiry policies feature is disabled", async () => {
765
776
  expect.assertions(3);
766
777
 
767
- const organizationSettings = defaultProOrganizationSettings();
778
+ const organizationSettings = defaultProSiteSettings();
768
779
  organizationSettings.passbolt.plugins.passwordExpiryPolicies.enabled = false;
769
780
 
770
- jest.spyOn(OrganizationSettingsService.prototype, "find").mockImplementation(() => organizationSettings);
781
+ jest
782
+ .spyOn(GetOrFindSiteSettingsService.prototype, "getOrFind")
783
+ .mockImplementation(() => new SiteSettingsEntity(organizationSettings));
771
784
 
772
785
  jest.spyOn(PasswordExpirySettingsService.prototype, "find").mockImplementation(() =>
773
786
  defaultPasswordExpirySettingsDtoFromApi({
@@ -792,8 +805,8 @@ describe("ImportResourcesService", () => {
792
805
  expect.assertions(3);
793
806
 
794
807
  jest
795
- .spyOn(OrganizationSettingsService.prototype, "find")
796
- .mockImplementation(() => defaultProOrganizationSettings());
808
+ .spyOn(GetOrFindSiteSettingsService.prototype, "getOrFind")
809
+ .mockImplementation(() => new SiteSettingsEntity(defaultProSiteSettings()));
797
810
 
798
811
  jest
799
812
  .spyOn(PasswordExpirySettingsService.prototype, "find")
@@ -824,13 +837,15 @@ describe("ImportResourcesService", () => {
824
837
  it("Should not set expiry date even when password expiry plugin is enabled", async () => {
825
838
  expect.assertions(3);
826
839
 
827
- const organizationSettings = defaultCeOrganizationSettings();
840
+ const organizationSettings = defaultCeSiteSettings();
828
841
  organizationSettings.passbolt.plugins.passwordExpiry = {
829
842
  version: "1.0.0",
830
843
  enabled: true,
831
844
  };
832
845
 
833
- jest.spyOn(OrganizationSettingsService.prototype, "find").mockImplementation(() => organizationSettings);
846
+ jest
847
+ .spyOn(GetOrFindSiteSettingsService.prototype, "getOrFind")
848
+ .mockImplementation(() => new SiteSettingsEntity(organizationSettings));
834
849
 
835
850
  jest
836
851
  .spyOn(PasswordExpirySettingsService.prototype, "find")
@@ -24,8 +24,10 @@ import { OpenpgpAssertion } from "../../../utils/openpgp/openpgpAssertions";
24
24
  import EncryptMessageService from "../../crypto/encryptMessageService";
25
25
  import ResourceSecretsCollection from "../../../model/entity/secret/resource/resourceSecretsCollection";
26
26
  import EncryptMetadataKeysService from "../../metadata/encryptMetadataService";
27
- import ResourceTypeModel from "../../../model/resourceType/resourceTypeModel";
28
27
  import FindPermissionsService from "../../permission/findPermissionsService";
28
+ import GetOrFindResourceTypesService from "../../resourceType/getOrFindResourceTypesService";
29
+ import PermissionChangesCollection from "../../../model/entity/permission/change/permissionChangesCollection";
30
+ import ShareResourceService, { PROGRESS_STEPS_SHARE_RESOURCES_SHARE_ALL } from "../../share/shareResourceService";
29
31
 
30
32
  class ResourceUpdateService {
31
33
  /**
@@ -37,13 +39,14 @@ class ResourceUpdateService {
37
39
  constructor(account, apiClientOptions, progressService) {
38
40
  this.account = account;
39
41
  this.resourceService = new ResourceService(apiClientOptions);
40
- this.resourceTypeModel = new ResourceTypeModel(apiClientOptions);
42
+ this.getOrFindResourcetypesService = new GetOrFindResourceTypesService(account, apiClientOptions);
41
43
  this.progressService = progressService;
42
44
  this.findPermissionsService = new FindPermissionsService(account, apiClientOptions);
43
- this.resourceModel = new ResourceModel(apiClientOptions);
45
+ this.resourceModel = new ResourceModel(apiClientOptions, account);
44
46
  this.encryptMetadataKeysService = new EncryptMetadataKeysService(apiClientOptions, this.account);
45
47
  this.userModel = new UserModel(apiClientOptions);
46
48
  this.keyring = new Keyring();
49
+ this.shareResourceService = new ShareResourceService(apiClientOptions, account, progressService);
47
50
  }
48
51
 
49
52
  /**
@@ -52,21 +55,37 @@ class ResourceUpdateService {
52
55
  * @param {object} resourceDto The resource data
53
56
  * @param {string|object|null} plaintextDto The secret to encrypt, or null to keep the existing secret
54
57
  * @param {string} passphrase The user passphrase
58
+ * @param {Array<object>} [permissionChanges] Optional permission changes applied after the update.
55
59
  * @return {Promise<ResourceEntity>} resourceEntity
56
60
  */
57
- async exec(resourceDto, plaintextDto, passphrase) {
61
+ async exec(resourceDto, plaintextDto, passphrase, permissionChanges) {
58
62
  const resourceEntity = new ResourceEntity(resourceDto);
59
- const resourceTypesCollection = await this.resourceTypeModel.getOrFindAll();
63
+
64
+ permissionChanges = permissionChanges ?? [];
65
+ // Apply the operator-confirmed permission changes (re-share) in the spec-mandated safe order.
66
+ if (permissionChanges.length > 0) {
67
+ // The styleguide emits deltas with aco_foreign_key unset (or null); stamp the resource id
68
+ // before handing them to the share orchestration.
69
+ const stampedChanges = permissionChanges.map((change) => ({
70
+ ...change,
71
+ aco_foreign_key: resourceEntity.id,
72
+ }));
73
+ await this.shareResourceService.shareAll(
74
+ [resourceEntity.id],
75
+ new PermissionChangesCollection(stampedChanges),
76
+ passphrase,
77
+ );
78
+ }
79
+
80
+ const resourceTypesCollection = await this.getOrFindResourcetypesService.getOrFindAll();
60
81
  const resourceTypeEntity = resourceTypesCollection.getFirstById(resourceEntity.resourceTypeId);
61
- const permissionsCollection = await this.findPermissionsService.findAllByAcoForeignKey(resourceEntity.id);
62
82
 
63
83
  // Get users ids of those who have access to the resource
64
84
  const usersIds = await this.userModel.findAllIdsForResourceUpdate(resourceEntity.id);
65
- // Set personal property only if resource is not shared with user and group
66
- resourceEntity.personal = usersIds.length === 1 && !permissionsCollection.hasGroupPermission;
67
85
  // Set goals
68
- const goals = this.calculateGoals(plaintextDto, resourceTypeEntity, usersIds.length);
86
+ const goals = this.calculateGoals(plaintextDto, resourceTypeEntity, usersIds.length, permissionChanges.length);
69
87
  this.progressService.updateGoals(goals);
88
+
70
89
  // Keep metadata decrypted to update it in the local storage
71
90
  const metadataDecrypted = resourceEntity.metadata;
72
91
  if (resourceTypeEntity.isV5()) {
@@ -74,12 +93,14 @@ class ResourceUpdateService {
74
93
  await this.progressService.finishStep(i18n.t("Encrypting Metadata"), true);
75
94
  await this.encryptMetadataKeysService.encryptOneForForeignModel(resourceEntity, passphrase);
76
95
  }
96
+
77
97
  if (plaintextDto !== null) {
78
98
  // Update secret
79
99
  await this.updateSecret(resourceEntity, plaintextDto, passphrase, usersIds);
80
100
  }
101
+
81
102
  // Update resource
82
- return this.update(resourceEntity, resourceTypeEntity, metadataDecrypted);
103
+ return await this.update(resourceEntity, resourceTypeEntity, metadataDecrypted);
83
104
  }
84
105
 
85
106
  /**
@@ -95,10 +116,6 @@ class ResourceUpdateService {
95
116
  // Get the passphrase if needed and decrypt secret key
96
117
  const privateKey = await DecryptPrivateKeyService.decryptArmoredKey(this.account.userPrivateArmoredKey, passphrase);
97
118
 
98
- // Sync keyring
99
- await this.progressService.finishStep(i18n.t("Synchronizing keyring"), true);
100
- await this.keyring.sync();
101
-
102
119
  // Encrypt
103
120
  const plaintext = await this.resourceModel.serializePlaintextDto(resourceEntity.resourceTypeId, plaintextDto);
104
121
  resourceEntity.secrets = await this.encryptSecrets(plaintext, usersIds, privateKey);
@@ -162,15 +179,17 @@ class ResourceUpdateService {
162
179
  * @param {string|object} plaintextDto The secret to encrypt
163
180
  * @param {ResourceTypeEntity} resourceType The resource type
164
181
  * @param {number} usersLength The number of users
182
+ * @param {number} [permissionChangesLength] The number of permission changes applied after the update
165
183
  * @returns {number}
166
184
  */
167
- calculateGoals(plaintextDto, resourceType, usersLength) {
185
+ calculateGoals(plaintextDto, resourceType, usersLength, permissionChangesLength = 0) {
186
+ const shareSteps = permissionChangesLength > 0 ? PROGRESS_STEPS_SHARE_RESOURCES_SHARE_ALL : 0;
168
187
  if (resourceType.isV5()) {
169
- // encrypt metadata + save + done or encrypt secret * users + encrypt metadata + keyring sync + save + done
170
- return plaintextDto === null ? 3 : usersLength + 4;
188
+ // encrypt metadata + save + done or encrypt secret * users + encrypt metadata + save + done
189
+ return (plaintextDto === null ? 3 : usersLength + 3) + shareSteps;
171
190
  } else if (resourceType.isV4()) {
172
- // save + done or encrypt secret * users + keyring sync + save + done
173
- return plaintextDto === null ? 2 : usersLength + 3;
191
+ // save + done or encrypt secret * users + save + done
192
+ return (plaintextDto === null ? 2 : usersLength + 2) + shareSteps;
174
193
  }
175
194
  }
176
195
  }
@@ -116,7 +116,7 @@ describe("ResourceUpdateService", () => {
116
116
 
117
117
  describe("ResourceUpdateService::exec", () => {
118
118
  it("Should call progress service during the different steps of creation", async () => {
119
- expect.assertions(8);
119
+ expect.assertions(7);
120
120
 
121
121
  const resourceDto = defaultResourceDto();
122
122
  const entity = new ResourceEntity(resourceDto);
@@ -140,9 +140,8 @@ describe("ResourceUpdateService", () => {
140
140
  );
141
141
 
142
142
  expect(resourceUpdateService.progressService.updateGoals).toHaveBeenCalledTimes(1);
143
- expect(resourceUpdateService.progressService.updateGoals).toHaveBeenCalledWith(6);
144
- expect(resourceUpdateService.progressService.finishStep).toHaveBeenCalledTimes(5);
145
- expect(resourceUpdateService.progressService.finishStep).toHaveBeenCalledWith("Synchronizing keyring", true);
143
+ expect(resourceUpdateService.progressService.updateGoals).toHaveBeenCalledWith(5);
144
+ expect(resourceUpdateService.progressService.finishStep).toHaveBeenCalledTimes(4);
146
145
  expect(resourceUpdateService.progressService.finishStep).toHaveBeenCalledWith("Encrypting Secret", true);
147
146
  expect(resourceUpdateService.progressService.finishStep).toHaveBeenCalledWith("Saving resource", true);
148
147
  expect(ResourceLocalStorage.updateResource).toHaveBeenCalledTimes(1);
@@ -151,6 +150,67 @@ describe("ResourceUpdateService", () => {
151
150
  );
152
151
  });
153
152
 
153
+ it("Should apply the permission changes via shareAll after the update, stamping the resource id", async () => {
154
+ expect.assertions(3);
155
+
156
+ const resourceDto = defaultResourceDto();
157
+ await ResourceLocalStorage.addResource(new ResourceEntity(resourceDto));
158
+ jest
159
+ .spyOn(resourceUpdateService.resourceService, "update")
160
+ .mockImplementation((resourceIdToUpdate, resourceDtoToUpdate) => {
161
+ const resourceEntity = new ResourceEntity(resourceDto);
162
+ resourceEntity.secrets = new ResourceSecretsCollection([resourceDtoToUpdate.secrets[0]]);
163
+ return resourceEntity.toV4Dto(ResourceLocalStorage.DEFAULT_CONTAIN);
164
+ });
165
+ const shareAllSpy = jest
166
+ .spyOn(resourceUpdateService.shareResourceService, "shareAll")
167
+ .mockImplementation(jest.fn);
168
+
169
+ const permissionChanges = [
170
+ {
171
+ aco: "Resource",
172
+ aro: "User",
173
+ aro_foreign_key: pgpKeys.betty.userId,
174
+ aco_foreign_key: null,
175
+ type: 1,
176
+ is_new: true,
177
+ },
178
+ ];
179
+ await resourceUpdateService.exec(
180
+ resourceDto,
181
+ plaintextSecretPasswordAndDescriptionDto(),
182
+ pgpKeys.ada.passphrase,
183
+ permissionChanges,
184
+ );
185
+
186
+ expect(shareAllSpy).toHaveBeenCalledTimes(1);
187
+ const [resourcesIds, changesCollection] = shareAllSpy.mock.calls[0];
188
+ expect(resourcesIds).toEqual([resourceDto.id]);
189
+ // The delta's aco_foreign_key must be stamped with the resource id before sharing.
190
+ expect(changesCollection.toDto()[0].aco_foreign_key).toEqual(resourceDto.id);
191
+ });
192
+
193
+ it("Should not call shareAll when no permission changes are provided", async () => {
194
+ expect.assertions(1);
195
+
196
+ const resourceDto = defaultResourceDto();
197
+ await ResourceLocalStorage.addResource(new ResourceEntity(resourceDto));
198
+ jest
199
+ .spyOn(resourceUpdateService.resourceService, "update")
200
+ .mockImplementation((resourceIdToUpdate, resourceDtoToUpdate) => {
201
+ const resourceEntity = new ResourceEntity(resourceDto);
202
+ resourceEntity.secrets = new ResourceSecretsCollection([resourceDtoToUpdate.secrets[0]]);
203
+ return resourceEntity.toV4Dto(ResourceLocalStorage.DEFAULT_CONTAIN);
204
+ });
205
+ const shareAllSpy = jest
206
+ .spyOn(resourceUpdateService.shareResourceService, "shareAll")
207
+ .mockImplementation(jest.fn);
208
+
209
+ await resourceUpdateService.exec(resourceDto, plaintextSecretPasswordAndDescriptionDto(), pgpKeys.ada.passphrase);
210
+
211
+ expect(shareAllSpy).not.toHaveBeenCalled();
212
+ });
213
+
154
214
  it("Should Update the resource with encrypted secrets (password and description) and dto", async () => {
155
215
  expect.assertions(14);
156
216
 
@@ -905,33 +965,6 @@ describe("ResourceUpdateService", () => {
905
965
  }
906
966
  });
907
967
 
908
- it("Should set personal to true when resource has only 1 user and no groups", async () => {
909
- expect.assertions(2);
910
-
911
- const resourceDto = defaultResourceDto();
912
- const entity = new ResourceEntity(resourceDto);
913
- await ResourceLocalStorage.addResource(entity);
914
-
915
- jest
916
- .spyOn(resourceUpdateService.userModel, "findAllIdsForResourceUpdate")
917
- .mockImplementationOnce(() => [pgpKeys.ada.userId]);
918
- jest.spyOn(PermissionService.prototype, "findAllByAcoForeignKey").mockImplementationOnce(() => []);
919
-
920
- let resourceUpdated;
921
- jest
922
- .spyOn(resourceUpdateService.resourceService, "update")
923
- .mockImplementation((resourceIdToUpdate, resourceDtoToUpdate) => {
924
- resourceUpdated = resourceDtoToUpdate;
925
- const resourceEntity = new ResourceEntity(resourceDto);
926
- return resourceEntity.toV4Dto(ResourceLocalStorage.DEFAULT_CONTAIN);
927
- });
928
-
929
- await resourceUpdateService.exec(resourceDto, null, pgpKeys.ada.passphrase);
930
-
931
- expect(resourceUpdated.personal).toBe(true);
932
- expect(resourceUpdateService.resourceService.update).toHaveBeenCalledTimes(1);
933
- });
934
-
935
968
  it("Should set personal to false when resource has 1 user but is shared with groups", async () => {
936
969
  expect.assertions(1);
937
970
 
@@ -0,0 +1,49 @@
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 6.0.0
13
+ */
14
+ import ResourceTypeLocalStorage from "../local_storage/resourceTypeLocalStorage";
15
+ import ResourceTypeService from "../api/resourceType/resourceTypeService";
16
+ import ResourceTypesCollection from "passbolt-styleguide/src/shared/models/entity/resourceType/resourceTypesCollection";
17
+
18
+ /**
19
+ * The service aims to get resource types from the local storage if it is set, or retrieve them from the API and
20
+ * set the local storage.
21
+ */
22
+ class GetOrFindResourceTypesService {
23
+ /**
24
+ * Constructor.
25
+ * @param {AccountEntity} account The user account.
26
+ * @param {ApiClientOptions} apiClientOptions The api client options.
27
+ */
28
+ constructor(account, apiClientOptions) {
29
+ this.resourceTypeService = new ResourceTypeService(apiClientOptions);
30
+ this.resourceTypeLocalStorage = new ResourceTypeLocalStorage(account);
31
+ }
32
+
33
+ /**
34
+ * Get or find all resource types.
35
+ * @returns {Promise<ResourceTypesCollection>}
36
+ */
37
+ async getOrFindAll() {
38
+ const resourceTypesDto = await this.resourceTypeLocalStorage.getData();
39
+ if (typeof resourceTypesDto !== "undefined") {
40
+ return new ResourceTypesCollection(resourceTypesDto);
41
+ }
42
+ const resourceTypeDtos = await this.resourceTypeService.findAll();
43
+ const resourceTypesCollection = new ResourceTypesCollection(resourceTypeDtos);
44
+ await this.resourceTypeLocalStorage.setData(resourceTypesCollection);
45
+ return resourceTypesCollection;
46
+ }
47
+ }
48
+
49
+ export default GetOrFindResourceTypesService;
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Passbolt ~ Open source password manager for teams
3
+ * Copyright (c) Passbolt SA (https://www.passbolt.com)
4
+ *
5
+ * Licensed under GNU Affero General Public License version 3 of the or any later version.
6
+ * For full copyright and license information, please see the LICENSE.txt
7
+ * Redistributions of files must retain the above copyright notice.
8
+ *
9
+ * @copyright Copyright (c) Passbolt SA (https://www.passbolt.com)
10
+ * @license https://opensource.org/licenses/AGPL-3.0 AGPL License
11
+ * @link https://www.passbolt.com Passbolt(tm)
12
+ * @since 6.0.0
13
+ */
14
+
15
+ import AccountEntity from "../../model/entity/account/accountEntity";
16
+ import { defaultAccountDto } from "../../model/entity/account/accountEntity.test.data";
17
+ import { defaultApiClientOptions } from "passbolt-styleguide/src/shared/lib/apiClient/apiClientOptions.test.data";
18
+ import GetOrFindResourceTypesService from "./getOrFindResourceTypesService";
19
+ import ResourceTypeLocalStorage from "../local_storage/resourceTypeLocalStorage";
20
+ import ResourceTypesCollection from "passbolt-styleguide/src/shared/models/entity/resourceType/resourceTypesCollection";
21
+ import { resourceTypesCollectionDto } from "passbolt-styleguide/src/shared/models/entity/resourceType/resourceTypesCollection.test.data";
22
+
23
+ describe("GetOrFindResourceTypesService", () => {
24
+ let service, account, storage;
25
+
26
+ beforeEach(async () => {
27
+ jest.clearAllMocks();
28
+ account = new AccountEntity(defaultAccountDto());
29
+ service = new GetOrFindResourceTypesService(account, defaultApiClientOptions());
30
+ storage = new ResourceTypeLocalStorage(account);
31
+ await storage.flush();
32
+ });
33
+
34
+ describe("::getOrFindAll", () => {
35
+ it("returns the resource types collection from the local storage on hot cache without delegating to the find-all service.", async () => {
36
+ expect.assertions(2);
37
+ const resourceTypesDto = resourceTypesCollectionDto();
38
+ await storage.setData(new ResourceTypesCollection(resourceTypesDto));
39
+ jest.spyOn(service.resourceTypeService, "findAll");
40
+
41
+ const result = await service.getOrFindAll();
42
+
43
+ expect(service.resourceTypeService.findAll).not.toHaveBeenCalled();
44
+ expect(result.toDto(storage.DEFAULT_CONTAIN)).toEqual(
45
+ new ResourceTypesCollection(resourceTypesDto).toDto(storage.DEFAULT_CONTAIN),
46
+ );
47
+ });
48
+
49
+ it("delegates to the find-and-update service on cold cache and returns its result.", async () => {
50
+ expect.assertions(2);
51
+ const resourceTypesDto = resourceTypesCollectionDto();
52
+ const expected = new ResourceTypesCollection(resourceTypesDto);
53
+ jest.spyOn(service.resourceTypeService, "findAll").mockImplementation(() => expected);
54
+
55
+ const result = await service.getOrFindAll();
56
+
57
+ expect(service.resourceTypeService.findAll).toHaveBeenCalledTimes(1);
58
+ expect(result).toStrictEqual(expected);
59
+ });
60
+ });
61
+ });