refactor: key rotation (#2383)
This commit is contained in:
@@ -1,207 +1,66 @@
|
||||
import { MutatorClientInterface, SyncServiceInterface } from '@standardnotes/services'
|
||||
import {
|
||||
KeySystemPasswordType,
|
||||
KeySystemRootKeyStorageMode,
|
||||
VaultListingInterface,
|
||||
VaultListingMutator,
|
||||
} from '@standardnotes/models'
|
||||
import { RotateVaultKey } from './RotateVaultKey'
|
||||
import { SyncServiceInterface } from '@standardnotes/services'
|
||||
import { KeySystemPasswordType, KeySystemRootKeyStorageMode } from '@standardnotes/models'
|
||||
import { ChangeVaultKeyOptionsDTO } from './ChangeVaultKeyOptionsDTO'
|
||||
import { GetVault } from './GetVault'
|
||||
import { EncryptionProviderInterface } from '../../Encryption/EncryptionProviderInterface'
|
||||
import { KeySystemKeyManagerInterface } from '../../KeySystem/KeySystemKeyManagerInterface'
|
||||
import { Result, UseCaseInterface } from '@standardnotes/domain-core'
|
||||
import { ChangeVaultStorageMode } from './ChangeVaultStorageMode'
|
||||
|
||||
export class ChangeVaultKeyOptions implements UseCaseInterface<void> {
|
||||
constructor(
|
||||
private mutator: MutatorClientInterface,
|
||||
private sync: SyncServiceInterface,
|
||||
private encryption: EncryptionProviderInterface,
|
||||
private keys: KeySystemKeyManagerInterface,
|
||||
private getVault: GetVault,
|
||||
private _rotateVaultKey: RotateVaultKey,
|
||||
private _changeVaultStorageMode: ChangeVaultStorageMode,
|
||||
) {}
|
||||
|
||||
async execute(dto: ChangeVaultKeyOptionsDTO): Promise<Result<void>> {
|
||||
if (dto.newPasswordType) {
|
||||
const result = await this.handleNewPasswordType(dto)
|
||||
if (result.isFailed()) {
|
||||
return result
|
||||
let newStorageMode = dto.newStorageMode
|
||||
let vault = dto.vault
|
||||
|
||||
if (dto.newPasswordOptions) {
|
||||
if (
|
||||
dto.newPasswordOptions.passwordType === KeySystemPasswordType.Randomized &&
|
||||
dto.newStorageMode &&
|
||||
dto.newStorageMode !== KeySystemRootKeyStorageMode.Synced
|
||||
) {
|
||||
return Result.fail('Cannot change storage mode to non-synced for randomized vault')
|
||||
}
|
||||
}
|
||||
|
||||
if (dto.newStorageMode) {
|
||||
const result = await this.handleNewStorageMode(dto)
|
||||
if (result.isFailed()) {
|
||||
return result
|
||||
if (
|
||||
dto.newPasswordOptions.passwordType === KeySystemPasswordType.UserInputted &&
|
||||
!dto.newPasswordOptions.userInputtedPassword
|
||||
) {
|
||||
return Result.fail('User inputted password required')
|
||||
}
|
||||
}
|
||||
|
||||
await this.sync.sync()
|
||||
|
||||
return Result.ok()
|
||||
}
|
||||
|
||||
private async handleNewPasswordType(dto: ChangeVaultKeyOptionsDTO): Promise<Result<void>> {
|
||||
if (!dto.newPasswordType) {
|
||||
return Result.ok()
|
||||
}
|
||||
|
||||
if (dto.vault.keyPasswordType === dto.newPasswordType.passwordType) {
|
||||
return Result.fail('Vault password type is already set to this type')
|
||||
}
|
||||
|
||||
if (dto.newPasswordType.passwordType === KeySystemPasswordType.UserInputted) {
|
||||
if (!dto.newPasswordType.userInputtedPassword) {
|
||||
return Result.fail('User inputted password is required')
|
||||
}
|
||||
const useStorageMode = dto.newStorageMode ?? dto.vault.keyStorageMode
|
||||
const result = await this.changePasswordTypeToUserInputted(
|
||||
dto.vault,
|
||||
dto.newPasswordType.userInputtedPassword,
|
||||
useStorageMode,
|
||||
)
|
||||
if (result.isFailed()) {
|
||||
return result
|
||||
}
|
||||
} else if (dto.newPasswordType.passwordType === KeySystemPasswordType.Randomized) {
|
||||
const result = await this.changePasswordTypeToRandomized(dto.vault)
|
||||
if (result.isFailed()) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
return Result.ok()
|
||||
}
|
||||
|
||||
private async handleNewStorageMode(dto: ChangeVaultKeyOptionsDTO): Promise<Result<void>> {
|
||||
if (!dto.newStorageMode) {
|
||||
return Result.ok()
|
||||
}
|
||||
|
||||
const result = this.getVault.execute({ keySystemIdentifier: dto.vault.systemIdentifier })
|
||||
if (result.isFailed()) {
|
||||
return Result.fail('Vault not found')
|
||||
}
|
||||
|
||||
const latestVault = result.getValue()
|
||||
|
||||
if (latestVault.rootKeyParams.passwordType !== KeySystemPasswordType.UserInputted) {
|
||||
return Result.fail('Vault uses randomized password and cannot change its storage preference')
|
||||
}
|
||||
|
||||
if (dto.newStorageMode === latestVault.keyStorageMode) {
|
||||
return Result.fail('Vault already uses this storage preference')
|
||||
}
|
||||
|
||||
if (
|
||||
dto.newStorageMode === KeySystemRootKeyStorageMode.Local ||
|
||||
dto.newStorageMode === KeySystemRootKeyStorageMode.Ephemeral
|
||||
) {
|
||||
const result = await this.changeStorageModeToLocalOrEphemeral(latestVault, dto.newStorageMode)
|
||||
if (result.isFailed()) {
|
||||
return result
|
||||
}
|
||||
} else if (dto.newStorageMode === KeySystemRootKeyStorageMode.Synced) {
|
||||
const result = await this.changeStorageModeToSynced(latestVault)
|
||||
if (result.isFailed()) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
return Result.ok()
|
||||
}
|
||||
|
||||
private async changePasswordTypeToUserInputted(
|
||||
vault: VaultListingInterface,
|
||||
userInputtedPassword: string,
|
||||
storageMode: KeySystemRootKeyStorageMode,
|
||||
): Promise<Result<void>> {
|
||||
const newRootKey = this.encryption.createUserInputtedKeySystemRootKey({
|
||||
systemIdentifier: vault.systemIdentifier,
|
||||
userInputtedPassword: userInputtedPassword,
|
||||
})
|
||||
|
||||
if (storageMode === KeySystemRootKeyStorageMode.Synced) {
|
||||
await this.mutator.insertItem(newRootKey, true)
|
||||
} else {
|
||||
this.keys.cacheKey(newRootKey, storageMode)
|
||||
}
|
||||
|
||||
await this.mutator.changeItem<VaultListingMutator>(vault, (mutator) => {
|
||||
mutator.rootKeyParams = newRootKey.keyParams
|
||||
})
|
||||
|
||||
await this.keys.queueVaultItemsKeysForReencryption(vault.systemIdentifier)
|
||||
|
||||
return Result.ok()
|
||||
}
|
||||
|
||||
private async changePasswordTypeToRandomized(vault: VaultListingInterface): Promise<Result<void>> {
|
||||
if (vault.keyStorageMode !== KeySystemRootKeyStorageMode.Synced) {
|
||||
this.keys.removeKeyFromCache(vault.systemIdentifier)
|
||||
|
||||
await this.mutator.changeItem<VaultListingMutator>(vault, (mutator) => {
|
||||
mutator.keyStorageMode = KeySystemRootKeyStorageMode.Synced
|
||||
const result = await this._rotateVaultKey.execute({
|
||||
vault: dto.vault,
|
||||
userInputtedPassword:
|
||||
dto.newPasswordOptions.passwordType === KeySystemPasswordType.UserInputted
|
||||
? dto.newPasswordOptions.userInputtedPassword
|
||||
: undefined,
|
||||
})
|
||||
}
|
||||
|
||||
const newRootKey = this.encryption.createRandomizedKeySystemRootKey({
|
||||
systemIdentifier: vault.systemIdentifier,
|
||||
})
|
||||
|
||||
await this.mutator.changeItem<VaultListingMutator>(vault, (mutator) => {
|
||||
mutator.rootKeyParams = newRootKey.keyParams
|
||||
})
|
||||
|
||||
await this.mutator.insertItem(newRootKey, true)
|
||||
|
||||
await this.keys.queueVaultItemsKeysForReencryption(vault.systemIdentifier)
|
||||
|
||||
return Result.ok()
|
||||
}
|
||||
|
||||
private async changeStorageModeToLocalOrEphemeral(
|
||||
vault: VaultListingInterface,
|
||||
newStorageMode: KeySystemRootKeyStorageMode,
|
||||
): Promise<Result<void>> {
|
||||
const primaryKey = this.keys.getPrimaryKeySystemRootKey(vault.systemIdentifier)
|
||||
if (!primaryKey) {
|
||||
return Result.fail('No primary key found')
|
||||
}
|
||||
|
||||
if (newStorageMode === KeySystemRootKeyStorageMode.Ephemeral) {
|
||||
this.keys.removeKeyFromCache(vault.systemIdentifier)
|
||||
}
|
||||
|
||||
this.keys.cacheKey(primaryKey, newStorageMode)
|
||||
await this.keys.deleteAllSyncedKeySystemRootKeys(vault.systemIdentifier)
|
||||
|
||||
await this.mutator.changeItem<VaultListingMutator>(vault, (mutator) => {
|
||||
mutator.keyStorageMode = newStorageMode
|
||||
})
|
||||
|
||||
await this.sync.sync()
|
||||
|
||||
return Result.ok()
|
||||
}
|
||||
|
||||
private async changeStorageModeToSynced(vault: VaultListingInterface): Promise<Result<void>> {
|
||||
const allRootKeys = this.keys.getAllKeySystemRootKeysForVault(vault.systemIdentifier)
|
||||
const syncedRootKeys = this.keys.getSyncedKeySystemRootKeysForVault(vault.systemIdentifier)
|
||||
|
||||
this.keys.removeKeyFromCache(vault.systemIdentifier)
|
||||
|
||||
for (const key of allRootKeys) {
|
||||
const existingSyncedKey = syncedRootKeys.find((syncedKey) => syncedKey.token === key.token)
|
||||
if (existingSyncedKey) {
|
||||
continue
|
||||
if (result.isFailed()) {
|
||||
return result
|
||||
}
|
||||
|
||||
await this.mutator.insertItem(key)
|
||||
vault = result.getValue()
|
||||
|
||||
if (dto.newPasswordOptions.passwordType === KeySystemPasswordType.Randomized) {
|
||||
newStorageMode = KeySystemRootKeyStorageMode.Synced
|
||||
}
|
||||
}
|
||||
|
||||
await this.mutator.changeItem<VaultListingMutator>(vault, (mutator) => {
|
||||
mutator.keyStorageMode = KeySystemRootKeyStorageMode.Synced
|
||||
})
|
||||
if (newStorageMode && newStorageMode !== vault.keyStorageMode) {
|
||||
const result = await this._changeVaultStorageMode.execute({
|
||||
vault: vault,
|
||||
newStorageMode: newStorageMode,
|
||||
})
|
||||
if (result.isFailed()) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
await this.sync.sync()
|
||||
|
||||
return Result.ok()
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { KeySystemPasswordType, KeySystemRootKeyStorageMode, VaultListingInterfa
|
||||
|
||||
export type ChangeVaultKeyOptionsDTO = {
|
||||
vault: VaultListingInterface
|
||||
newPasswordType:
|
||||
newPasswordOptions:
|
||||
| { passwordType: KeySystemPasswordType.Randomized }
|
||||
| { passwordType: KeySystemPasswordType.UserInputted; userInputtedPassword: string }
|
||||
| undefined
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
import { MutatorClientInterface, SyncServiceInterface } from '@standardnotes/services'
|
||||
import {
|
||||
KeySystemPasswordType,
|
||||
KeySystemRootKeyStorageMode,
|
||||
VaultListingInterface,
|
||||
VaultListingMutator,
|
||||
} from '@standardnotes/models'
|
||||
import { GetVault } from './GetVault'
|
||||
import { KeySystemKeyManagerInterface } from '../../KeySystem/KeySystemKeyManagerInterface'
|
||||
import { Result, UseCaseInterface } from '@standardnotes/domain-core'
|
||||
|
||||
export class ChangeVaultStorageMode implements UseCaseInterface<VaultListingInterface> {
|
||||
constructor(
|
||||
private mutator: MutatorClientInterface,
|
||||
private sync: SyncServiceInterface,
|
||||
private keys: KeySystemKeyManagerInterface,
|
||||
private _getVault: GetVault,
|
||||
) {}
|
||||
|
||||
async execute(dto: {
|
||||
vault: VaultListingInterface
|
||||
newStorageMode: KeySystemRootKeyStorageMode
|
||||
}): Promise<Result<VaultListingInterface>> {
|
||||
const result = this._getVault.execute({ keySystemIdentifier: dto.vault.systemIdentifier })
|
||||
if (result.isFailed()) {
|
||||
return Result.fail('Vault not found')
|
||||
}
|
||||
|
||||
const vault = result.getValue()
|
||||
if (
|
||||
vault.keyPasswordType === KeySystemPasswordType.Randomized &&
|
||||
dto.newStorageMode !== KeySystemRootKeyStorageMode.Synced
|
||||
) {
|
||||
return Result.fail('Cannot change storage mode to non-synced for randomized vault')
|
||||
}
|
||||
|
||||
const latestVault = result.getValue()
|
||||
|
||||
if (dto.newStorageMode === latestVault.keyStorageMode) {
|
||||
return Result.fail('Vault already uses this storage preference')
|
||||
}
|
||||
|
||||
if (
|
||||
dto.newStorageMode === KeySystemRootKeyStorageMode.Local ||
|
||||
dto.newStorageMode === KeySystemRootKeyStorageMode.Ephemeral
|
||||
) {
|
||||
const result = await this.changeStorageModeToLocalOrEphemeral(latestVault, dto.newStorageMode)
|
||||
if (result.isFailed()) {
|
||||
return result
|
||||
}
|
||||
} else if (dto.newStorageMode === KeySystemRootKeyStorageMode.Synced) {
|
||||
const result = await this.changeStorageModeToSynced(latestVault)
|
||||
if (result.isFailed()) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
return Result.ok()
|
||||
}
|
||||
|
||||
private async changeStorageModeToLocalOrEphemeral(
|
||||
vault: VaultListingInterface,
|
||||
newStorageMode: KeySystemRootKeyStorageMode,
|
||||
): Promise<Result<VaultListingInterface>> {
|
||||
const primaryKey = this.keys.getPrimaryKeySystemRootKey(vault.systemIdentifier)
|
||||
if (!primaryKey) {
|
||||
return Result.fail('No primary key found')
|
||||
}
|
||||
|
||||
if (newStorageMode === KeySystemRootKeyStorageMode.Ephemeral) {
|
||||
this.keys.removeKeyFromCache(vault.systemIdentifier)
|
||||
}
|
||||
|
||||
this.keys.cacheKey(primaryKey, newStorageMode)
|
||||
await this.keys.deleteAllSyncedKeySystemRootKeys(vault.systemIdentifier)
|
||||
|
||||
const updatedVault = await this.mutator.changeItem<VaultListingMutator, VaultListingInterface>(vault, (mutator) => {
|
||||
mutator.keyStorageMode = newStorageMode
|
||||
})
|
||||
|
||||
await this.sync.sync()
|
||||
|
||||
return Result.ok(updatedVault)
|
||||
}
|
||||
|
||||
private async changeStorageModeToSynced(vault: VaultListingInterface): Promise<Result<VaultListingInterface>> {
|
||||
const allRootKeys = this.keys.getAllKeySystemRootKeysForVault(vault.systemIdentifier)
|
||||
const syncedRootKeys = this.keys.getSyncedKeySystemRootKeysForVault(vault.systemIdentifier)
|
||||
|
||||
this.keys.removeKeyFromCache(vault.systemIdentifier)
|
||||
|
||||
for (const key of allRootKeys) {
|
||||
const existingSyncedKey = syncedRootKeys.find((syncedKey) => syncedKey.token === key.token)
|
||||
if (existingSyncedKey) {
|
||||
continue
|
||||
}
|
||||
|
||||
await this.mutator.insertItem(key)
|
||||
}
|
||||
|
||||
const updatedVault = await this.mutator.changeItem<VaultListingMutator, VaultListingInterface>(vault, (mutator) => {
|
||||
mutator.keyStorageMode = KeySystemRootKeyStorageMode.Synced
|
||||
})
|
||||
|
||||
return Result.ok(updatedVault)
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
import { IsVaultOwner } from './../../VaultUser/UseCase/IsVaultOwner'
|
||||
import { NotifyVaultUsersOfKeyRotation } from './../../SharedVaults/UseCase/NotifyVaultUsersOfKeyRotation'
|
||||
import { UuidGenerator, assert } from '@standardnotes/utils'
|
||||
import { ClientDisplayableError, isClientDisplayableError } from '@standardnotes/responses'
|
||||
import {
|
||||
KeySystemIdentifier,
|
||||
KeySystemRootKeyInterface,
|
||||
KeySystemPasswordType,
|
||||
KeySystemRootKeyStorageMode,
|
||||
VaultListingInterface,
|
||||
VaultListingMutator,
|
||||
@@ -11,19 +11,47 @@ import {
|
||||
import { MutatorClientInterface } from '../../Mutator/MutatorClientInterface'
|
||||
import { EncryptionProviderInterface } from '../../Encryption/EncryptionProviderInterface'
|
||||
import { KeySystemKeyManagerInterface } from '../../KeySystem/KeySystemKeyManagerInterface'
|
||||
import { Result, UseCaseInterface } from '@standardnotes/domain-core'
|
||||
|
||||
export class RotateVaultKey {
|
||||
export class RotateVaultKey implements UseCaseInterface<VaultListingInterface> {
|
||||
constructor(
|
||||
private mutator: MutatorClientInterface,
|
||||
private encryption: EncryptionProviderInterface,
|
||||
private keys: KeySystemKeyManagerInterface,
|
||||
private _notifyVaultUsersOfKeyRotation: NotifyVaultUsersOfKeyRotation,
|
||||
private _isVaultOwner: IsVaultOwner,
|
||||
) {}
|
||||
|
||||
async execute(params: {
|
||||
vault: VaultListingInterface
|
||||
sharedVaultUuid: string | undefined
|
||||
userInputtedPassword: string | undefined
|
||||
}): Promise<undefined | ClientDisplayableError[]> {
|
||||
}): Promise<Result<VaultListingInterface>> {
|
||||
const { newRootKey, updatedVault } = await this.updateRootKeyparams(params)
|
||||
|
||||
await this.createNewKeySystemItemsKey({
|
||||
keySystemIdentifier: updatedVault.systemIdentifier,
|
||||
sharedVaultUuid: updatedVault.isSharedVaultListing() ? updatedVault.sharing.sharedVaultUuid : undefined,
|
||||
rootKeyToken: newRootKey.token,
|
||||
})
|
||||
|
||||
await this.keys.queueVaultItemsKeysForReencryption(updatedVault.systemIdentifier)
|
||||
|
||||
const shareResult = await this.shareNewKeyWithMembers({
|
||||
vault: updatedVault,
|
||||
newRootKey,
|
||||
})
|
||||
|
||||
if (shareResult.isFailed()) {
|
||||
return Result.fail(shareResult.getError())
|
||||
}
|
||||
|
||||
return Result.ok(updatedVault)
|
||||
}
|
||||
|
||||
private async updateRootKeyparams(params: {
|
||||
vault: VaultListingInterface
|
||||
userInputtedPassword: string | undefined
|
||||
}): Promise<{ newRootKey: KeySystemRootKeyInterface; updatedVault: VaultListingInterface }> {
|
||||
const currentRootKey = this.keys.getPrimaryKeySystemRootKey(params.vault.systemIdentifier)
|
||||
if (!currentRootKey) {
|
||||
throw new Error('Cannot rotate key system root key; key system root key not found')
|
||||
@@ -31,16 +59,12 @@ export class RotateVaultKey {
|
||||
|
||||
let newRootKey: KeySystemRootKeyInterface | undefined
|
||||
|
||||
if (currentRootKey.keyParams.passwordType === KeySystemPasswordType.UserInputted) {
|
||||
if (!params.userInputtedPassword) {
|
||||
throw new Error('Cannot rotate key system root key; user inputted password required')
|
||||
}
|
||||
|
||||
if (params.userInputtedPassword) {
|
||||
newRootKey = this.encryption.createUserInputtedKeySystemRootKey({
|
||||
systemIdentifier: params.vault.systemIdentifier,
|
||||
userInputtedPassword: params.userInputtedPassword,
|
||||
})
|
||||
} else if (currentRootKey.keyParams.passwordType === KeySystemPasswordType.Randomized) {
|
||||
} else {
|
||||
newRootKey = this.encryption.createRandomizedKeySystemRootKey({
|
||||
systemIdentifier: params.vault.systemIdentifier,
|
||||
})
|
||||
@@ -50,39 +74,28 @@ export class RotateVaultKey {
|
||||
throw new Error('Cannot rotate key system root key; new root key not created')
|
||||
}
|
||||
|
||||
if (params.vault.keyStorageMode === KeySystemRootKeyStorageMode.Synced) {
|
||||
if (!params.userInputtedPassword || params.vault.keyStorageMode === KeySystemRootKeyStorageMode.Synced) {
|
||||
await this.mutator.insertItem(newRootKey, true)
|
||||
} else {
|
||||
this.keys.cacheKey(newRootKey, params.vault.keyStorageMode)
|
||||
}
|
||||
|
||||
await this.mutator.changeItem<VaultListingMutator>(params.vault, (mutator) => {
|
||||
assert(newRootKey)
|
||||
mutator.rootKeyParams = newRootKey.keyParams
|
||||
})
|
||||
const updatedVault = await this.mutator.changeItem<VaultListingMutator, VaultListingInterface>(
|
||||
params.vault,
|
||||
(mutator) => {
|
||||
assert(newRootKey)
|
||||
mutator.rootKeyParams = newRootKey.keyParams
|
||||
},
|
||||
)
|
||||
|
||||
const errors: ClientDisplayableError[] = []
|
||||
|
||||
const updateKeySystemItemsKeyResult = await this.createNewKeySystemItemsKey({
|
||||
keySystemIdentifier: params.vault.systemIdentifier,
|
||||
sharedVaultUuid: params.sharedVaultUuid,
|
||||
rootKeyToken: newRootKey.token,
|
||||
})
|
||||
|
||||
if (isClientDisplayableError(updateKeySystemItemsKeyResult)) {
|
||||
errors.push(updateKeySystemItemsKeyResult)
|
||||
}
|
||||
|
||||
await this.keys.queueVaultItemsKeysForReencryption(params.vault.systemIdentifier)
|
||||
|
||||
return errors
|
||||
return { newRootKey, updatedVault }
|
||||
}
|
||||
|
||||
private async createNewKeySystemItemsKey(params: {
|
||||
keySystemIdentifier: KeySystemIdentifier
|
||||
sharedVaultUuid: string | undefined
|
||||
rootKeyToken: string
|
||||
}): Promise<ClientDisplayableError | void> {
|
||||
}): Promise<void> {
|
||||
const newItemsKeyUuid = UuidGenerator.GenerateUuid()
|
||||
const newItemsKey = this.encryption.createKeySystemItemsKey(
|
||||
newItemsKeyUuid,
|
||||
@@ -92,4 +105,25 @@ export class RotateVaultKey {
|
||||
)
|
||||
await this.mutator.insertItem(newItemsKey)
|
||||
}
|
||||
|
||||
private async shareNewKeyWithMembers(params: {
|
||||
vault: VaultListingInterface
|
||||
newRootKey: KeySystemRootKeyInterface
|
||||
}): Promise<Result<void>> {
|
||||
if (!params.vault.isSharedVaultListing()) {
|
||||
return Result.ok()
|
||||
}
|
||||
|
||||
const isOwner = this._isVaultOwner.execute({ sharedVault: params.vault }).getValue()
|
||||
|
||||
if (!isOwner) {
|
||||
return Result.ok()
|
||||
}
|
||||
|
||||
const result = await this._notifyVaultUsersOfKeyRotation.execute({
|
||||
sharedVault: params.vault,
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { SendVaultDataChangedMessage } from './../SharedVaults/UseCase/SendVaultDataChangedMessage'
|
||||
import { isClientDisplayableError } from '@standardnotes/responses'
|
||||
import {
|
||||
DecryptedItemInterface,
|
||||
@@ -46,6 +47,7 @@ export class VaultService
|
||||
private _removeItemFromVault: RemoveItemFromVault,
|
||||
private _deleteVault: DeleteVault,
|
||||
private _rotateVaultKey: RotateVaultKey,
|
||||
private _sendVaultDataChangeMessage: SendVaultDataChangedMessage,
|
||||
eventBus: InternalEventBusInterface,
|
||||
) {
|
||||
super(eventBus)
|
||||
@@ -192,6 +194,12 @@ export class VaultService
|
||||
|
||||
await this.sync.sync()
|
||||
|
||||
if (updatedVault.isSharedVaultListing()) {
|
||||
await this._sendVaultDataChangeMessage.execute({
|
||||
vault: updatedVault,
|
||||
})
|
||||
}
|
||||
|
||||
return updatedVault
|
||||
}
|
||||
|
||||
@@ -202,12 +210,9 @@ export class VaultService
|
||||
|
||||
await this._rotateVaultKey.execute({
|
||||
vault,
|
||||
sharedVaultUuid: vault.isSharedVaultListing() ? vault.sharing.sharedVaultUuid : undefined,
|
||||
userInputtedPassword: vaultPassword,
|
||||
})
|
||||
|
||||
await this.notifyEventSync(VaultServiceEvent.VaultRootKeyRotated, { vault })
|
||||
|
||||
await this.sync.sync()
|
||||
}
|
||||
|
||||
@@ -228,17 +233,13 @@ export class VaultService
|
||||
return this.getVault({ keySystemIdentifier: latestItem.key_system_identifier })
|
||||
}
|
||||
|
||||
async changeVaultOptions(dto: ChangeVaultKeyOptionsDTO): Promise<Result<void>> {
|
||||
async changeVaultKeyOptions(dto: ChangeVaultKeyOptionsDTO): Promise<Result<void>> {
|
||||
if (this.vaultLocks.isVaultLocked(dto.vault)) {
|
||||
throw new Error('Attempting to change vault options on a locked vault')
|
||||
}
|
||||
|
||||
const result = await this._changeVaultKeyOptions.execute(dto)
|
||||
|
||||
if (dto.newPasswordType) {
|
||||
await this.notifyEventSync(VaultServiceEvent.VaultRootKeyRotated, { vault: dto.vault })
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
import { VaultListingInterface } from '@standardnotes/models'
|
||||
export enum VaultServiceEvent {}
|
||||
|
||||
export enum VaultServiceEvent {
|
||||
VaultRootKeyRotated = 'VaultRootKeyRotated',
|
||||
}
|
||||
|
||||
export type VaultServiceEventPayload = {
|
||||
[VaultServiceEvent.VaultRootKeyRotated]: {
|
||||
vault: VaultListingInterface
|
||||
}
|
||||
}
|
||||
export type VaultServiceEventPayload = Record<string, unknown>
|
||||
|
||||
@@ -36,5 +36,5 @@ export interface VaultServiceInterface
|
||||
params: { name: string; description: string },
|
||||
): Promise<VaultListingInterface>
|
||||
rotateVaultRootKey(vault: VaultListingInterface, vaultPassword?: string): Promise<void>
|
||||
changeVaultOptions(dto: ChangeVaultKeyOptionsDTO): Promise<Result<void>>
|
||||
changeVaultKeyOptions(dto: ChangeVaultKeyOptionsDTO): Promise<Result<void>>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user