Browse Source

fix(syncing-server): inviting already existing members to shared vault (#690)

* fix(syncing-server): inviting already existing members to shared vault

* fix(syncing-server): finding method for existing members
Karol Sójko 1 year ago
parent
commit
0a16ee64fe

+ 1 - 0
packages/syncing-server/src/Bootstrap/Container.ts

@@ -631,6 +631,7 @@ export class ContainerConfigLoader {
         new InviteUserToSharedVault(
           container.get(TYPES.Sync_SharedVaultRepository),
           container.get(TYPES.Sync_SharedVaultInviteRepository),
+          container.get(TYPES.Sync_SharedVaultUserRepository),
           container.get(TYPES.Sync_Timer),
         ),
       )

+ 32 - 1
packages/syncing-server/src/Domain/UseCase/SharedVaults/InviteUserToSharedVault/InviteUserToSharedVault.spec.ts

@@ -6,14 +6,19 @@ import { SharedVaultInviteRepositoryInterface } from '../../../SharedVault/User/
 import { InviteUserToSharedVault } from './InviteUserToSharedVault'
 import { SharedVault } from '../../../SharedVault/SharedVault'
 import { SharedVaultInvite } from '../../../SharedVault/User/Invite/SharedVaultInvite'
+import { SharedVaultUserRepositoryInterface } from '../../../SharedVault/User/SharedVaultUserRepositoryInterface'
+import { SharedVaultUser } from '../../../SharedVault/User/SharedVaultUser'
 
 describe('InviteUserToSharedVault', () => {
   let sharedVaultRepository: SharedVaultRepositoryInterface
   let sharedVaultInviteRepository: SharedVaultInviteRepositoryInterface
+  let sharedVaultUserRepository: SharedVaultUserRepositoryInterface
   let timer: TimerInterface
   let sharedVault: SharedVault
+  let sharedVaultUser: SharedVaultUser
 
-  const createUseCase = () => new InviteUserToSharedVault(sharedVaultRepository, sharedVaultInviteRepository, timer)
+  const createUseCase = () =>
+    new InviteUserToSharedVault(sharedVaultRepository, sharedVaultInviteRepository, sharedVaultUserRepository, timer)
 
   beforeEach(() => {
     sharedVault = SharedVault.create({
@@ -30,6 +35,16 @@ describe('InviteUserToSharedVault', () => {
     sharedVaultInviteRepository.save = jest.fn()
     sharedVaultInviteRepository.remove = jest.fn()
 
+    sharedVaultUser = SharedVaultUser.create({
+      sharedVaultUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
+      userUuid: Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
+      permission: SharedVaultUserPermission.create(SharedVaultUserPermission.PERMISSIONS.Read).getValue(),
+      timestamps: Timestamps.create(123, 123).getValue(),
+    }).getValue()
+
+    sharedVaultUserRepository = {} as jest.Mocked<SharedVaultUserRepositoryInterface>
+    sharedVaultUserRepository.findByUserUuidAndSharedVaultUuid = jest.fn().mockResolvedValue(null)
+
     timer = {} as jest.Mocked<TimerInterface>
     timer.getTimestampInMicroseconds = jest.fn().mockReturnValue(123)
   })
@@ -114,6 +129,22 @@ describe('InviteUserToSharedVault', () => {
     expect(sharedVaultInviteRepository.remove).toHaveBeenCalled()
   })
 
+  it('should return failure if the shared vault user is already a member of the shared vault', async () => {
+    const useCase = createUseCase()
+    sharedVaultUserRepository.findByUserUuidAndSharedVaultUuid = jest.fn().mockResolvedValue(sharedVaultUser)
+
+    const result = await useCase.execute({
+      sharedVaultUuid: '00000000-0000-0000-0000-000000000000',
+      senderUuid: '00000000-0000-0000-0000-000000000000',
+      recipientUuid: '00000000-0000-0000-0000-000000000000',
+      permission: SharedVaultUserPermission.PERMISSIONS.Read,
+      encryptedMessage: 'encryptedMessage',
+    })
+
+    expect(result.isFailed()).toBe(true)
+    expect(result.getError()).toBe('User is already a member of this shared vault')
+  })
+
   it('should create a shared vault invite', async () => {
     const useCase = createUseCase()
 

+ 10 - 0
packages/syncing-server/src/Domain/UseCase/SharedVaults/InviteUserToSharedVault/InviteUserToSharedVault.ts

@@ -5,11 +5,13 @@ import { SharedVaultInvite } from '../../../SharedVault/User/Invite/SharedVaultI
 import { SharedVaultRepositoryInterface } from '../../../SharedVault/SharedVaultRepositoryInterface'
 import { InviteUserToSharedVaultDTO } from './InviteUserToSharedVaultDTO'
 import { SharedVaultInviteRepositoryInterface } from '../../../SharedVault/User/Invite/SharedVaultInviteRepositoryInterface'
+import { SharedVaultUserRepositoryInterface } from '../../../SharedVault/User/SharedVaultUserRepositoryInterface'
 
 export class InviteUserToSharedVault implements UseCaseInterface<SharedVaultInvite> {
   constructor(
     private sharedVaultRepository: SharedVaultRepositoryInterface,
     private sharedVaultInviteRepository: SharedVaultInviteRepositoryInterface,
+    private sharedVaultUserRepository: SharedVaultUserRepositoryInterface,
     private timer: TimerInterface,
   ) {}
   async execute(dto: InviteUserToSharedVaultDTO): Promise<Result<SharedVaultInvite>> {
@@ -46,6 +48,14 @@ export class InviteUserToSharedVault implements UseCaseInterface<SharedVaultInvi
       return Result.fail('Only the owner of a shared vault can invite users to it')
     }
 
+    const alreadyExistingMember = await this.sharedVaultUserRepository.findByUserUuidAndSharedVaultUuid({
+      userUuid: recipientUuid,
+      sharedVaultUuid,
+    })
+    if (alreadyExistingMember) {
+      return Result.fail('User is already a member of this shared vault')
+    }
+
     const existingInvite = await this.sharedVaultInviteRepository.findByUserUuidAndSharedVaultUuid({
       userUuid: recipientUuid,
       sharedVaultUuid,