瀏覽代碼

feat: remove inbound shared vault invites. (#646)

Co-authored-by: Mo <mo@standardnotes.com>
Karol Sójko 1 年之前
父節點
當前提交
92a5eb0d98

+ 1 - 0
packages/syncing-server/src/Domain/SharedVault/User/Invite/SharedVaultInviteRepositoryInterface.ts

@@ -7,5 +7,6 @@ export interface SharedVaultInviteRepositoryInterface {
   save(sharedVaultInvite: SharedVaultInvite): Promise<void>
   remove(sharedVaultInvite: SharedVaultInvite): Promise<void>
   removeBySharedVaultUuid(sharedVaultUuid: Uuid): Promise<void>
+  findByUserUuid(userUuid: Uuid): Promise<SharedVaultInvite[]>
   findByUserUuidAndSharedVaultUuid(dto: { userUuid: Uuid; sharedVaultUuid: Uuid }): Promise<SharedVaultInvite | null>
 }

+ 65 - 0
packages/syncing-server/src/Domain/UseCase/DeleteSharedVaultInvitesToUser/DeleteSharedVaultInvitesToUser.spec.ts

@@ -0,0 +1,65 @@
+import { Result, Timestamps, Uuid } from '@standardnotes/domain-core'
+import { SharedVaultInviteRepositoryInterface } from '../../SharedVault/User/Invite/SharedVaultInviteRepositoryInterface'
+import { DeclineInviteToSharedVault } from '../DeclineInviteToSharedVault/DeclineInviteToSharedVault'
+import { DeleteSharedVaultInvitesToUser } from './DeleteSharedVaultInvitesToUser'
+import { SharedVaultInvite } from '../../SharedVault/User/Invite/SharedVaultInvite'
+import { SharedVaultUserPermission } from '../../SharedVault/User/SharedVaultUserPermission'
+
+describe('DeleteSharedVaultInvitesToUser', () => {
+  let sharedVaultInviteRepository: SharedVaultInviteRepositoryInterface
+  let declineInviteToSharedVault: DeclineInviteToSharedVault
+  let sharedVaultInvite: SharedVaultInvite
+
+  const createUseCase = () =>
+    new DeleteSharedVaultInvitesToUser(sharedVaultInviteRepository, declineInviteToSharedVault)
+
+  beforeEach(() => {
+    sharedVaultInvite = SharedVaultInvite.create({
+      sharedVaultUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
+      userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
+      senderUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
+      encryptedMessage: 'encrypted-message',
+      permission: SharedVaultUserPermission.create(SharedVaultUserPermission.PERMISSIONS.Read).getValue(),
+      timestamps: Timestamps.create(123, 123).getValue(),
+    }).getValue()
+
+    sharedVaultInviteRepository = {} as jest.Mocked<SharedVaultInviteRepositoryInterface>
+    sharedVaultInviteRepository.findByUserUuid = jest.fn().mockReturnValue([sharedVaultInvite])
+
+    declineInviteToSharedVault = {} as jest.Mocked<DeclineInviteToSharedVault>
+    declineInviteToSharedVault.execute = jest.fn().mockReturnValue(Result.ok())
+  })
+
+  it('should decline all invites to user', async () => {
+    const useCase = createUseCase()
+
+    const result = await useCase.execute({
+      userUuid: '00000000-0000-0000-0000-000000000000',
+    })
+
+    expect(result.isFailed()).toBeFalsy()
+    expect(declineInviteToSharedVault.execute).toHaveBeenCalled()
+  })
+
+  it('should return error when user uuid is invalid', async () => {
+    const useCase = createUseCase()
+
+    const result = await useCase.execute({
+      userUuid: 'invalid-uuid',
+    })
+
+    expect(result.isFailed()).toBeTruthy()
+  })
+
+  it('should return error when declineInviteToSharedVault fails', async () => {
+    declineInviteToSharedVault.execute = jest.fn().mockReturnValue(Result.fail('error'))
+
+    const useCase = createUseCase()
+
+    const result = await useCase.execute({
+      userUuid: '00000000-0000-0000-0000-000000000000',
+    })
+
+    expect(result.isFailed()).toBeTruthy()
+  })
+})

+ 32 - 0
packages/syncing-server/src/Domain/UseCase/DeleteSharedVaultInvitesToUser/DeleteSharedVaultInvitesToUser.ts

@@ -0,0 +1,32 @@
+import { Result, UseCaseInterface, Uuid } from '@standardnotes/domain-core'
+import { DeleteSharedVaultInvitesToUserDTO } from './DeleteSharedVaultInvitesToUserDTO'
+import { DeclineInviteToSharedVault } from '../DeclineInviteToSharedVault/DeclineInviteToSharedVault'
+import { SharedVaultInviteRepositoryInterface } from '../../SharedVault/User/Invite/SharedVaultInviteRepositoryInterface'
+
+export class DeleteSharedVaultInvitesToUser implements UseCaseInterface<void> {
+  constructor(
+    private sharedVaultInviteRepository: SharedVaultInviteRepositoryInterface,
+    private declineInviteToSharedVault: DeclineInviteToSharedVault,
+  ) {}
+
+  async execute(dto: DeleteSharedVaultInvitesToUserDTO): Promise<Result<void>> {
+    const userUuidOrError = Uuid.create(dto.userUuid)
+    if (userUuidOrError.isFailed()) {
+      return Result.fail(userUuidOrError.getError())
+    }
+    const userUuid = userUuidOrError.getValue()
+
+    const inboundInvites = await this.sharedVaultInviteRepository.findByUserUuid(userUuid)
+    for (const invite of inboundInvites) {
+      const result = await this.declineInviteToSharedVault.execute({
+        inviteUuid: invite.id.toString(),
+        originatorUuid: userUuid.value,
+      })
+      if (result.isFailed()) {
+        return Result.fail(result.getError())
+      }
+    }
+
+    return Result.ok()
+  }
+}

+ 3 - 0
packages/syncing-server/src/Domain/UseCase/DeleteSharedVaultInvitesToUser/DeleteSharedVaultInvitesToUserDTO.ts

@@ -0,0 +1,3 @@
+export interface DeleteSharedVaultInvitesToUserDTO {
+  userUuid: string
+}

+ 11 - 0
packages/syncing-server/src/Infra/TypeORM/TypeORMSharedVaultInviteRepository.ts

@@ -11,6 +11,17 @@ export class TypeORMSharedVaultInviteRepository implements SharedVaultInviteRepo
     private mapper: MapperInterface<SharedVaultInvite, TypeORMSharedVaultInvite>,
   ) {}
 
+  async findByUserUuid(userUuid: Uuid): Promise<SharedVaultInvite[]> {
+    const persistence = await this.ormRepository
+      .createQueryBuilder('shared_vault_invite')
+      .where('shared_vault_invite.user_uuid = :userUuid', {
+        userUuid: userUuid.value,
+      })
+      .getMany()
+
+    return persistence.map((p) => this.mapper.toDomain(p))
+  }
+
   async removeBySharedVaultUuid(sharedVaultUuid: Uuid): Promise<void> {
     await this.ormRepository
       .createQueryBuilder('shared_vault_invite')