Parcourir la source

feat(syncing-server): add notification for user upon declined shared vault invitation (#837)

Karol Sójko il y a 1 an
Parent
commit
31e7aaf253

+ 1 - 0
packages/domain-core/src/Domain/Notification/NotificationType.ts

@@ -7,6 +7,7 @@ export class NotificationType extends ValueObject<NotificationTypeProps> {
     SharedVaultItemRemoved: 'shared_vault_item_removed',
     RemovedFromSharedVault: 'removed_from_shared_vault',
     UserAddedToSharedVault: 'user_added_to_shared_vault',
+    SharedVaultInviteDeclined: 'shared_vault_invite_declined',
     SharedVaultFileUploaded: 'shared_vault_file_uploaded',
     SharedVaultFileRemoved: 'shared_vault_file_removed',
   }

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

@@ -723,7 +723,12 @@ export class ContainerConfigLoader {
       )
     container
       .bind<DeclineInviteToSharedVault>(TYPES.Sync_DeclineInviteToSharedVault)
-      .toConstantValue(new DeclineInviteToSharedVault(container.get(TYPES.Sync_SharedVaultInviteRepository)))
+      .toConstantValue(
+        new DeclineInviteToSharedVault(
+          container.get<SharedVaultInviteRepositoryInterface>(TYPES.Sync_SharedVaultInviteRepository),
+          container.get<AddNotificationForUser>(TYPES.Sync_AddNotificationForUser),
+        ),
+      )
     container
       .bind<DeleteSharedVaultInvitesToUser>(TYPES.Sync_DeleteSharedVaultInvitesToUser)
       .toConstantValue(

+ 38 - 2
packages/syncing-server/src/Domain/UseCase/SharedVaults/DeclineInviteToSharedVault/DeclineInviteToSharedVault.spec.ts

@@ -1,13 +1,15 @@
-import { SharedVaultUserPermission, Timestamps, Uuid } from '@standardnotes/domain-core'
+import { NotificationPayload, Result, SharedVaultUserPermission, Timestamps, Uuid } from '@standardnotes/domain-core'
 import { SharedVaultInviteRepositoryInterface } from '../../../SharedVault/User/Invite/SharedVaultInviteRepositoryInterface'
 import { DeclineInviteToSharedVault } from './DeclineInviteToSharedVault'
 import { SharedVaultInvite } from '../../../SharedVault/User/Invite/SharedVaultInvite'
+import { AddNotificationForUser } from '../../Messaging/AddNotificationForUser/AddNotificationForUser'
 
 describe('DeclineInviteToSharedVault', () => {
   let sharedVaultInviteRepository: SharedVaultInviteRepositoryInterface
   let invite: SharedVaultInvite
+  let addNotificationForUser: AddNotificationForUser
 
-  const createUseCase = () => new DeclineInviteToSharedVault(sharedVaultInviteRepository)
+  const createUseCase = () => new DeclineInviteToSharedVault(sharedVaultInviteRepository, addNotificationForUser)
 
   beforeEach(() => {
     invite = SharedVaultInvite.create({
@@ -22,6 +24,9 @@ describe('DeclineInviteToSharedVault', () => {
     sharedVaultInviteRepository = {} as jest.Mocked<SharedVaultInviteRepositoryInterface>
     sharedVaultInviteRepository.findByUuid = jest.fn().mockResolvedValue(invite)
     sharedVaultInviteRepository.remove = jest.fn()
+
+    addNotificationForUser = {} as jest.Mocked<AddNotificationForUser>
+    addNotificationForUser.execute = jest.fn().mockReturnValue(Result.ok())
   })
 
   it('should fail if invite uuid is invalid', async () => {
@@ -36,6 +41,37 @@ describe('DeclineInviteToSharedVault', () => {
     expect(result.getError()).toBe('Given value is not a valid uuid: invalid')
   })
 
+  it('should fail if adding a notification for user fails', async () => {
+    addNotificationForUser.execute = jest.fn().mockReturnValue(Result.fail('Error'))
+
+    const useCase = createUseCase()
+
+    const result = await useCase.execute({
+      inviteUuid: '00000000-0000-0000-0000-000000000000',
+      userUuid: '00000000-0000-0000-0000-000000000000',
+    })
+
+    expect(result.isFailed()).toBe(true)
+    expect(result.getError()).toBe('Error')
+  })
+
+  it('should return error if notification payload could not be created', async () => {
+    const mock = jest.spyOn(NotificationPayload, 'create')
+    mock.mockReturnValue(Result.fail('Oops'))
+
+    const useCase = createUseCase()
+
+    const result = await useCase.execute({
+      inviteUuid: '00000000-0000-0000-0000-000000000000',
+      userUuid: '00000000-0000-0000-0000-000000000000',
+    })
+
+    expect(result.isFailed()).toBe(true)
+    expect(result.getError()).toBe('Oops')
+
+    mock.mockRestore()
+  })
+
   it('should fail if originator uuid is invalid', async () => {
     const useCase = createUseCase()
 

+ 27 - 2
packages/syncing-server/src/Domain/UseCase/SharedVaults/DeclineInviteToSharedVault/DeclineInviteToSharedVault.ts

@@ -1,9 +1,14 @@
-import { Result, UseCaseInterface, Uuid } from '@standardnotes/domain-core'
+import { NotificationPayload, NotificationType, Result, UseCaseInterface, Uuid } from '@standardnotes/domain-core'
+
 import { DeclineInviteToSharedVaultDTO } from './DeclineInviteToSharedVaultDTO'
 import { SharedVaultInviteRepositoryInterface } from '../../../SharedVault/User/Invite/SharedVaultInviteRepositoryInterface'
+import { AddNotificationForUser } from '../../Messaging/AddNotificationForUser/AddNotificationForUser'
 
 export class DeclineInviteToSharedVault implements UseCaseInterface<void> {
-  constructor(private sharedVaultInviteRepository: SharedVaultInviteRepositoryInterface) {}
+  constructor(
+    private sharedVaultInviteRepository: SharedVaultInviteRepositoryInterface,
+    private addNotificationForUser: AddNotificationForUser,
+  ) {}
 
   async execute(dto: DeclineInviteToSharedVaultDTO): Promise<Result<void>> {
     const inviteUuidOrError = Uuid.create(dto.inviteUuid)
@@ -29,6 +34,26 @@ export class DeclineInviteToSharedVault implements UseCaseInterface<void> {
 
     await this.sharedVaultInviteRepository.remove(invite)
 
+    const notificationPayloadOrError = NotificationPayload.create({
+      sharedVaultUuid: invite.props.sharedVaultUuid,
+      type: NotificationType.create(NotificationType.TYPES.SharedVaultInviteDeclined).getValue(),
+      version: '1.0',
+    })
+    if (notificationPayloadOrError.isFailed()) {
+      return Result.fail(notificationPayloadOrError.getError())
+    }
+    const notificationPayload = notificationPayloadOrError.getValue()
+
+    const result = await this.addNotificationForUser.execute({
+      userUuid: invite.props.userUuid.value,
+      type: NotificationType.TYPES.SharedVaultInviteDeclined,
+      payload: notificationPayload,
+      version: '1.0',
+    })
+    if (result.isFailed()) {
+      return Result.fail(result.getError())
+    }
+
     return Result.ok()
   }
 }