chore: add method to designate a shared vault survivor (#2538)

This commit is contained in:
Karol Sójko
2023-09-26 13:48:36 +02:00
committed by GitHub
parent 60f96bc201
commit 2ce908da29
12 changed files with 160 additions and 5 deletions

View File

@@ -0,0 +1,66 @@
import { SharedVaultUsersServerInterface } from '@standardnotes/api'
import { DesignateSurvivor } from './DesignateSurvivor'
describe('DesignateSurvivor', () => {
let sharedVaultUserServer: SharedVaultUsersServerInterface
const createUseCase = () => new DesignateSurvivor(
sharedVaultUserServer,
)
beforeEach(() => {
sharedVaultUserServer = {} as jest.Mocked<SharedVaultUsersServerInterface>
sharedVaultUserServer.designateSurvivor = jest.fn().mockReturnValue({
status: 200,
})
})
it('should mark designated survivor', async () => {
const useCase = createUseCase()
const result = await useCase.execute({
sharedVaultUuid: '00000000-0000-0000-0000-000000000000',
sharedVaultMemberUuid: '00000000-0000-0000-0000-000000000000',
})
expect(result.isFailed()).toBe(false)
})
it('should fail if shared vault uuid is invalid', async () => {
const useCase = createUseCase()
const result = await useCase.execute({
sharedVaultUuid: 'invalid',
sharedVaultMemberUuid: '00000000-0000-0000-0000-000000000000',
})
expect(result.isFailed()).toBe(true)
})
it('should fail if shared vault member uuid is invalid', async () => {
const useCase = createUseCase()
const result = await useCase.execute({
sharedVaultUuid: '00000000-0000-0000-0000-000000000000',
sharedVaultMemberUuid: 'invalid',
})
expect(result.isFailed()).toBe(true)
})
it('should fail if shared vault user server fails', async () => {
sharedVaultUserServer.designateSurvivor = jest.fn().mockReturnValue({
status: 500,
})
const useCase = createUseCase()
const result = await useCase.execute({
sharedVaultUuid: '00000000-0000-0000-0000-000000000000',
sharedVaultMemberUuid: '00000000-0000-0000-0000-000000000000',
})
expect(result.isFailed()).toBe(true)
})
})

View File

@@ -0,0 +1,34 @@
import { Result, UseCaseInterface, Uuid } from '@standardnotes/domain-core'
import { SharedVaultUsersServerInterface } from '@standardnotes/api'
import { HttpStatusCode } from '@standardnotes/responses'
import { DesignateSurvivorDTO } from './DesignateSurvivorDTO'
export class DesignateSurvivor implements UseCaseInterface<void> {
constructor(private sharedVaultUserServer: SharedVaultUsersServerInterface) {}
async execute(dto: DesignateSurvivorDTO): Promise<Result<void>> {
const sharedVaultUuidOrError = Uuid.create(dto.sharedVaultUuid)
if (sharedVaultUuidOrError.isFailed()) {
return Result.fail(sharedVaultUuidOrError.getError())
}
const sharedVaultUuid = sharedVaultUuidOrError.getValue()
const sharedVaultMemberUuidOrError = Uuid.create(dto.sharedVaultMemberUuid)
if (sharedVaultMemberUuidOrError.isFailed()) {
return Result.fail(sharedVaultMemberUuidOrError.getError())
}
const sharedVaultMemberUuid = sharedVaultMemberUuidOrError.getValue()
const response = await this.sharedVaultUserServer.designateSurvivor({
sharedVaultUuid,
sharedVaultMemberUuid,
})
if (response.status !== HttpStatusCode.Success) {
return Result.fail('Failed to mark designated survivor on the server')
}
return Result.ok()
}
}

View File

@@ -0,0 +1,4 @@
export interface DesignateSurvivorDTO {
sharedVaultUuid: string
sharedVaultMemberUuid: string
}

View File

@@ -14,6 +14,7 @@ import { Result } from '@standardnotes/domain-core'
import { IsVaultOwner } from './UseCase/IsVaultOwner'
import { IsReadonlyVaultMember } from './UseCase/IsReadonlyVaultMember'
import { IsVaultAdmin } from './UseCase/IsVaultAdmin'
import { DesignateSurvivor } from './UseCase/DesignateSurvivor/DesignateSurvivor'
export class VaultUserService extends AbstractService<VaultUserServiceEvent> implements VaultUserServiceInterface {
constructor(
@@ -26,6 +27,7 @@ export class VaultUserService extends AbstractService<VaultUserServiceEvent> imp
private _isReadonlyVaultMember: IsReadonlyVaultMember,
private _getVault: GetVault,
private _leaveVault: LeaveVault,
private designateSurvivorUseCase: DesignateSurvivor,
eventBus: InternalEventBusInterface,
) {
super(eventBus)
@@ -41,6 +43,19 @@ export class VaultUserService extends AbstractService<VaultUserServiceEvent> imp
;(this._leaveVault as unknown) = undefined
}
async designateSurvivor(sharedVault: SharedVaultListingInterface, userUuid: string): Promise<Result<void>> {
const result = await this.designateSurvivorUseCase.execute({
sharedVaultMemberUuid: userUuid,
sharedVaultUuid: sharedVault.sharing.sharedVaultUuid,
})
if (result.isFailed()) {
return Result.fail(`Could not designate survivor: ${result.getError()}`)
}
return Result.ok()
}
async invalidateVaultUsersCache(sharedVaultUuid?: string) {
if (sharedVaultUuid) {
await this._getVaultUsers.execute({

View File

@@ -12,6 +12,7 @@ export interface VaultUserServiceInterface extends ApplicationServiceInterface<V
isCurrentUserSharedVaultAdmin(sharedVault: SharedVaultListingInterface): boolean
isCurrentUserReadonlyVaultMember(vault: VaultListingInterface): boolean
removeUserFromSharedVault(sharedVault: SharedVaultListingInterface, userUuid: string): Promise<Result<void>>
designateSurvivor(sharedVault: SharedVaultListingInterface, userUuid: string): Promise<Result<void>>
leaveSharedVault(sharedVault: SharedVaultListingInterface): Promise<ClientDisplayableError | void>
isVaultUserOwner(user: SharedVaultUserServerHash): boolean
getFormattedMemberPermission(permission: string): string

View File

@@ -203,6 +203,7 @@ export * from './User/UserServiceInterface'
export * from './User/UserServiceInterface'
export * from './UserEvent/NotificationService'
export * from './UserEvent/NotificationServiceEvent'
export * from './Vault/UseCase/AuthorizeVaultDeletion'
export * from './Vault/UseCase/ChangeVaultKeyOptions'
export * from './Vault/UseCase/ChangeVaultKeyOptionsDTO'
export * from './Vault/UseCase/ChangeVaultStorageMode'
@@ -231,9 +232,12 @@ export * from './VaultLock/UseCase/ValidateVaultPassword'
export * from './VaultLock/VaultLockService'
export * from './VaultLock/VaultLockServiceEvent'
export * from './VaultLock/VaultLockServiceInterface'
export * from './VaultUser/UseCase/GetVaultContacts'
export * from './VaultUser/UseCase/DesignateSurvivor/DesignateSurvivor'
export * from './VaultUser/UseCase/DesignateSurvivor/DesignateSurvivorDTO'
export * from './VaultUser/UseCase/GetVaultContacts'
export * from './VaultUser/UseCase/GetVaultUsers'
export * from './VaultUser/UseCase/IsReadonlyVaultMember'
export * from './VaultUser/UseCase/IsVaultAdmin'
export * from './VaultUser/UseCase/IsVaultOwner'
export * from './VaultUser/UseCase/LeaveSharedVault'
export * from './VaultUser/UseCase/RemoveSharedVaultMember'