diff --git a/packages/auth/src/Bootstrap/Container.ts b/packages/auth/src/Bootstrap/Container.ts index 3679272e9..94ba33bac 100644 --- a/packages/auth/src/Bootstrap/Container.ts +++ b/packages/auth/src/Bootstrap/Container.ts @@ -791,7 +791,16 @@ export class ContainerConfigLoader { container .bind(TYPES.Auth_SubscriptionSettingsAssociationService) .to(SubscriptionSettingsAssociationService) - container.bind(TYPES.Auth_FeatureService).to(FeatureService) + container + .bind(TYPES.Auth_FeatureService) + .toConstantValue( + new FeatureService( + container.get(TYPES.Auth_RoleToSubscriptionMap), + container.get(TYPES.Auth_OfflineUserSubscriptionRepository), + container.get(TYPES.Auth_Timer), + container.get(TYPES.Auth_UserSubscriptionRepository), + ), + ) container .bind>(TYPES.Auth_BooleanSelector) .toConstantValue(new DeterministicSelector()) @@ -1104,6 +1113,7 @@ export class ContainerConfigLoader { new DeleteAccount( container.get(TYPES.Auth_UserRepository), container.get(TYPES.Auth_GetRegularSubscriptionForUser), + container.get(TYPES.Auth_GetSharedSubscriptionForUser), container.get(TYPES.Auth_DomainEventPublisher), container.get(TYPES.Auth_DomainEventFactory), container.get(TYPES.Auth_Timer), diff --git a/packages/auth/src/Domain/Event/DomainEventFactory.ts b/packages/auth/src/Domain/Event/DomainEventFactory.ts index 2ab9d70b4..5a1fa8f8f 100644 --- a/packages/auth/src/Domain/Event/DomainEventFactory.ts +++ b/packages/auth/src/Domain/Event/DomainEventFactory.ts @@ -281,9 +281,16 @@ export class DomainEventFactory implements DomainEventFactoryInterface { createAccountDeletionRequestedEvent(dto: { userUuid: string + email: string userCreatedAtTimestamp: number - regularSubscriptionUuid: string | undefined - roleNames: string[] + regularSubscription?: { + uuid: string + ownerUuid: string + } + sharedSubscription?: { + uuid: string + ownerUuid: string + } }): AccountDeletionRequestedEvent { return { type: 'ACCOUNT_DELETION_REQUESTED', diff --git a/packages/auth/src/Domain/Event/DomainEventFactoryInterface.ts b/packages/auth/src/Domain/Event/DomainEventFactoryInterface.ts index 584155380..e915bb54b 100644 --- a/packages/auth/src/Domain/Event/DomainEventFactoryInterface.ts +++ b/packages/auth/src/Domain/Event/DomainEventFactoryInterface.ts @@ -45,9 +45,16 @@ export interface DomainEventFactoryInterface { ): EmailBackupRequestedEvent createAccountDeletionRequestedEvent(dto: { userUuid: string + email: string userCreatedAtTimestamp: number - regularSubscriptionUuid: string | undefined - roleNames: string[] + regularSubscription?: { + uuid: string + ownerUuid: string + } + sharedSubscription?: { + uuid: string + ownerUuid: string + } }): AccountDeletionRequestedEvent createUserRolesChangedEvent(userUuid: string, email: string, currentRoles: string[]): UserRolesChangedEvent createUserEmailChangedEvent(userUuid: string, fromEmail: string, toEmail: string): UserEmailChangedEvent diff --git a/packages/auth/src/Domain/Feature/FeatureService.spec.ts b/packages/auth/src/Domain/Feature/FeatureService.spec.ts index 476cd0e8b..de53fff6e 100644 --- a/packages/auth/src/Domain/Feature/FeatureService.spec.ts +++ b/packages/auth/src/Domain/Feature/FeatureService.spec.ts @@ -35,6 +35,7 @@ import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/Offl import { TimerInterface } from '@standardnotes/time' import { OfflineUserSubscription } from '../Subscription/OfflineUserSubscription' import { UserSubscriptionType } from '../Subscription/UserSubscriptionType' +import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface' describe('FeatureService', () => { let roleToSubscriptionMap: RoleToSubscriptionMapInterface @@ -52,8 +53,10 @@ describe('FeatureService', () => { let offlineUserSubscriptionRepository: OfflineUserSubscriptionRepositoryInterface let timer: TimerInterface let offlineUserSubscription: OfflineUserSubscription + let userSubscriptionRepository: UserSubscriptionRepositoryInterface - const createService = () => new FeatureService(roleToSubscriptionMap, offlineUserSubscriptionRepository, timer) + const createService = () => + new FeatureService(roleToSubscriptionMap, offlineUserSubscriptionRepository, timer, userSubscriptionRepository) beforeEach(() => { roleToSubscriptionMap = {} as jest.Mocked @@ -107,7 +110,7 @@ describe('FeatureService', () => { renewedAt: null, planName: SubscriptionName.PlusPlan, endsAt: 555, - user: Promise.resolve(user), + userUuid: 'user-1-1-1', cancelled: false, subscriptionId: 1, subscriptionType: UserSubscriptionType.Regular, @@ -120,7 +123,7 @@ describe('FeatureService', () => { renewedAt: null, planName: SubscriptionName.ProPlan, endsAt: 777, - user: Promise.resolve(user), + userUuid: 'user-1-1-1', cancelled: false, subscriptionId: 2, subscriptionType: UserSubscriptionType.Regular, @@ -133,7 +136,7 @@ describe('FeatureService', () => { renewedAt: null, planName: SubscriptionName.PlusPlan, endsAt: 333, - user: Promise.resolve(user), + userUuid: 'user-1-1-1', cancelled: true, subscriptionId: 3, subscriptionType: UserSubscriptionType.Regular, @@ -146,7 +149,7 @@ describe('FeatureService', () => { renewedAt: null, planName: SubscriptionName.PlusPlan, endsAt: 333, - user: Promise.resolve(user), + userUuid: 'user-1-1-1', cancelled: true, subscriptionId: 4, subscriptionType: UserSubscriptionType.Regular, @@ -155,9 +158,11 @@ describe('FeatureService', () => { user = { uuid: 'user-1-1-1', roles: Promise.resolve([role1]), - subscriptions: Promise.resolve([subscription1]), } as jest.Mocked + userSubscriptionRepository = {} as jest.Mocked + userSubscriptionRepository.findByUserUuid = jest.fn().mockReturnValue([subscription1]) + offlineUserSubscription = { roles: Promise.resolve([role1]), uuid: 'subscription-1-1-1', @@ -247,9 +252,10 @@ describe('FeatureService', () => { user = { uuid: 'user-1-1-1', roles: Promise.resolve([role1, role2, nonSubscriptionRole]), - subscriptions: Promise.resolve([subscription1, subscription2]), } as jest.Mocked + userSubscriptionRepository.findByUserUuid = jest.fn().mockReturnValue([subscription1, subscription2]) + expect(await createService().userIsEntitledToFeature(user, 'files-beta')).toBe(true) }) @@ -269,9 +275,12 @@ describe('FeatureService', () => { user = { uuid: 'user-1-1-1', roles: Promise.resolve([role1]), - subscriptions: Promise.resolve([subscription3, subscription1, subscription4]), } as jest.Mocked + userSubscriptionRepository.findByUserUuid = jest + .fn() + .mockReturnValue([subscription3, subscription1, subscription4]) + const features = await createService().getFeaturesForUser(user) expect(features).toEqual( expect.arrayContaining([ @@ -284,14 +293,13 @@ describe('FeatureService', () => { }) it('should not return user features if a subscription could not be found', async () => { - const subscriptions: Array = [] - user = { uuid: 'user-1-1-1', roles: Promise.resolve([role1]), - subscriptions: Promise.resolve(subscriptions), } as jest.Mocked + userSubscriptionRepository.findByUserUuid = jest.fn().mockReturnValue([]) + expect(await createService().getFeaturesForUser(user)).toEqual([]) }) @@ -307,9 +315,12 @@ describe('FeatureService', () => { user = { uuid: 'user-1-1-1', roles: Promise.resolve([role1]), - subscriptions: Promise.resolve([subscription3, subscription1, subscription4]), } as jest.Mocked + userSubscriptionRepository.findByUserUuid = jest + .fn() + .mockReturnValue([subscription3, subscription1, subscription4]) + expect(await createService().getFeaturesForUser(user)).toEqual([]) }) @@ -321,7 +332,7 @@ describe('FeatureService', () => { renewedAt: null, planName: 'non existing plan name' as SubscriptionName, endsAt: 555, - user: Promise.resolve(user), + userUuid: 'user-1-1-1', cancelled: false, subscriptionId: 1, subscriptionType: UserSubscriptionType.Regular, @@ -330,9 +341,10 @@ describe('FeatureService', () => { user = { uuid: 'user-1-1-1', roles: Promise.resolve([role1]), - subscriptions: Promise.resolve([subscription1]), } as jest.Mocked + userSubscriptionRepository.findByUserUuid = jest.fn().mockReturnValue([subscription1]) + expect(await createService().getFeaturesForUser(user)).toEqual([]) }) @@ -351,9 +363,10 @@ describe('FeatureService', () => { user = { uuid: 'user-1-1-1', roles: Promise.resolve([role1, role2]), - subscriptions: Promise.resolve([subscription1, subscription2]), } as jest.Mocked + userSubscriptionRepository.findByUserUuid = jest.fn().mockReturnValue([subscription1, subscription2]) + const features = await createService().getFeaturesForUser(user) expect(features).toEqual( expect.arrayContaining([ @@ -409,9 +422,10 @@ describe('FeatureService', () => { user = { uuid: 'user-1-1-1', roles: Promise.resolve([role1, role2, nonSubscriptionRole]), - subscriptions: Promise.resolve([subscription1, subscription2]), } as jest.Mocked + userSubscriptionRepository.findByUserUuid = jest.fn().mockReturnValue([subscription1, subscription2]) + const features = await createService().getFeaturesForUser(user) expect(features).toEqual( expect.arrayContaining([ @@ -445,9 +459,10 @@ describe('FeatureService', () => { user = { uuid: 'user-1-1-1', roles: Promise.resolve([role1, role2]), - subscriptions: Promise.resolve([subscription1, subscription2]), } as jest.Mocked + userSubscriptionRepository.findByUserUuid = jest.fn().mockReturnValue([subscription1, subscription2]) + const longestExpireAt = 777 const features = await createService().getFeaturesForUser(user) @@ -482,9 +497,10 @@ describe('FeatureService', () => { user = { uuid: 'user-1-1-1', roles: Promise.resolve([role1, role2]), - subscriptions: Promise.resolve([subscription1, subscription2]), } as jest.Mocked + userSubscriptionRepository.findByUserUuid = jest.fn().mockReturnValue([subscription1, subscription2]) + const features = await createService().getFeaturesForUser(user) expect(features).toEqual( expect.arrayContaining([ diff --git a/packages/auth/src/Domain/Feature/FeatureService.ts b/packages/auth/src/Domain/Feature/FeatureService.ts index 968718d44..f3e8a20b3 100644 --- a/packages/auth/src/Domain/Feature/FeatureService.ts +++ b/packages/auth/src/Domain/Feature/FeatureService.ts @@ -1,24 +1,22 @@ import { SubscriptionName } from '@standardnotes/common' import { FeatureDescription, GetFeatures } from '@standardnotes/features' -import { inject, injectable } from 'inversify' -import TYPES from '../../Bootstrap/Types' -import { RoleToSubscriptionMapInterface } from '../Role/RoleToSubscriptionMapInterface' +import { TimerInterface } from '@standardnotes/time' +import { RoleToSubscriptionMapInterface } from '../Role/RoleToSubscriptionMapInterface' import { User } from '../User/User' import { UserSubscription } from '../Subscription/UserSubscription' import { FeatureServiceInterface } from './FeatureServiceInterface' import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/OfflineUserSubscriptionRepositoryInterface' import { Role } from '../Role/Role' import { OfflineUserSubscription } from '../Subscription/OfflineUserSubscription' -import { TimerInterface } from '@standardnotes/time' +import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface' -@injectable() export class FeatureService implements FeatureServiceInterface { constructor( - @inject(TYPES.Auth_RoleToSubscriptionMap) private roleToSubscriptionMap: RoleToSubscriptionMapInterface, - @inject(TYPES.Auth_OfflineUserSubscriptionRepository) + private roleToSubscriptionMap: RoleToSubscriptionMapInterface, private offlineUserSubscriptionRepository: OfflineUserSubscriptionRepositoryInterface, - @inject(TYPES.Auth_Timer) private timer: TimerInterface, + private timer: TimerInterface, + private userSubscriptionRepository: UserSubscriptionRepositoryInterface, ) {} async userIsEntitledToFeature(user: User, featureIdentifier: string): Promise { @@ -61,7 +59,7 @@ export class FeatureService implements FeatureServiceInterface { } async getFeaturesForUser(user: User): Promise> { - const userSubscriptions = await user.subscriptions + const userSubscriptions = await this.userSubscriptionRepository.findByUserUuid(user.uuid) return this.getFeaturesForSubscriptions(userSubscriptions, await user.roles) } diff --git a/packages/auth/src/Domain/Handler/SubscriptionExpiredEventHandler.ts b/packages/auth/src/Domain/Handler/SubscriptionExpiredEventHandler.ts index 12ade71e4..a56f4c91a 100644 --- a/packages/auth/src/Domain/Handler/SubscriptionExpiredEventHandler.ts +++ b/packages/auth/src/Domain/Handler/SubscriptionExpiredEventHandler.ts @@ -7,7 +7,7 @@ import { RoleServiceInterface } from '../Role/RoleServiceInterface' import { UserRepositoryInterface } from '../User/UserRepositoryInterface' import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface' import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/OfflineUserSubscriptionRepositoryInterface' -import { Username } from '@standardnotes/domain-core' +import { Username, Uuid } from '@standardnotes/domain-core' @injectable() export class SubscriptionExpiredEventHandler implements DomainEventHandlerInterface { @@ -48,7 +48,22 @@ export class SubscriptionExpiredEventHandler implements DomainEventHandlerInterf private async removeRoleFromSubscriptionUsers(subscriptionId: number, subscriptionName: string): Promise { const userSubscriptions = await this.userSubscriptionRepository.findBySubscriptionId(subscriptionId) for (const userSubscription of userSubscriptions) { - await this.roleService.removeUserRoleBasedOnSubscription(await userSubscription.user, subscriptionName) + const userUuidOrError = Uuid.create(userSubscription.userUuid) + if (userUuidOrError.isFailed()) { + this.logger.warn(`Could not remove role from user with uuid: ${userUuidOrError.getError()}`) + + continue + } + const userUuid = userUuidOrError.getValue() + + const user = await this.userRepository.findOneByUuid(userUuid) + if (user === null) { + this.logger.warn(`Could not find user with uuid: ${userUuid.value}`) + + continue + } + + await this.roleService.removeUserRoleBasedOnSubscription(user, subscriptionName) } } diff --git a/packages/auth/src/Domain/Handler/SubscriptionPurchasedEventHandler.ts b/packages/auth/src/Domain/Handler/SubscriptionPurchasedEventHandler.ts index 68453462b..668cec7ca 100644 --- a/packages/auth/src/Domain/Handler/SubscriptionPurchasedEventHandler.ts +++ b/packages/auth/src/Domain/Handler/SubscriptionPurchasedEventHandler.ts @@ -84,7 +84,7 @@ export class SubscriptionPurchasedEventHandler implements DomainEventHandlerInte ): Promise { const subscription = new UserSubscription() subscription.planName = subscriptionName - subscription.user = Promise.resolve(user) + subscription.userUuid = user.uuid subscription.createdAt = timestamp subscription.updatedAt = timestamp subscription.endsAt = subscriptionExpiresAt diff --git a/packages/auth/src/Domain/Handler/SubscriptionReassignedEventHandler.ts b/packages/auth/src/Domain/Handler/SubscriptionReassignedEventHandler.ts index a5bf23b9c..3b4e6cbd7 100644 --- a/packages/auth/src/Domain/Handler/SubscriptionReassignedEventHandler.ts +++ b/packages/auth/src/Domain/Handler/SubscriptionReassignedEventHandler.ts @@ -80,7 +80,7 @@ export class SubscriptionReassignedEventHandler implements DomainEventHandlerInt ): Promise { const subscription = new UserSubscription() subscription.planName = subscriptionName - subscription.user = Promise.resolve(user) + subscription.userUuid = user.uuid subscription.createdAt = timestamp subscription.updatedAt = timestamp subscription.endsAt = subscriptionExpiresAt diff --git a/packages/auth/src/Domain/Handler/SubscriptionRefundedEventHandler.ts b/packages/auth/src/Domain/Handler/SubscriptionRefundedEventHandler.ts index deacd22fb..1e7902132 100644 --- a/packages/auth/src/Domain/Handler/SubscriptionRefundedEventHandler.ts +++ b/packages/auth/src/Domain/Handler/SubscriptionRefundedEventHandler.ts @@ -7,7 +7,7 @@ import { RoleServiceInterface } from '../Role/RoleServiceInterface' import { UserRepositoryInterface } from '../User/UserRepositoryInterface' import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface' import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/OfflineUserSubscriptionRepositoryInterface' -import { Username } from '@standardnotes/domain-core' +import { Username, Uuid } from '@standardnotes/domain-core' @injectable() export class SubscriptionRefundedEventHandler implements DomainEventHandlerInterface { @@ -48,7 +48,22 @@ export class SubscriptionRefundedEventHandler implements DomainEventHandlerInter private async removeRoleFromSubscriptionUsers(subscriptionId: number, subscriptionName: string): Promise { const userSubscriptions = await this.userSubscriptionRepository.findBySubscriptionId(subscriptionId) for (const userSubscription of userSubscriptions) { - await this.roleService.removeUserRoleBasedOnSubscription(await userSubscription.user, subscriptionName) + const userUuidOrError = Uuid.create(userSubscription.userUuid) + if (userUuidOrError.isFailed()) { + this.logger.warn(`Could not remove role from user with uuid: ${userUuidOrError.getError()}`) + + continue + } + const userUuid = userUuidOrError.getValue() + + const user = await this.userRepository.findOneByUuid(userUuid) + if (user === null) { + this.logger.warn(`Could not find user with uuid: ${userUuid.value}`) + + continue + } + + await this.roleService.removeUserRoleBasedOnSubscription(user, subscriptionName) } } diff --git a/packages/auth/src/Domain/Handler/SubscriptionRenewedEventHandler.ts b/packages/auth/src/Domain/Handler/SubscriptionRenewedEventHandler.ts index edff0b617..237de4a44 100644 --- a/packages/auth/src/Domain/Handler/SubscriptionRenewedEventHandler.ts +++ b/packages/auth/src/Domain/Handler/SubscriptionRenewedEventHandler.ts @@ -8,7 +8,7 @@ import { RoleServiceInterface } from '../Role/RoleServiceInterface' import { UserRepositoryInterface } from '../User/UserRepositoryInterface' import { Logger } from 'winston' import { OfflineUserSubscription } from '../Subscription/OfflineUserSubscription' -import { Username } from '@standardnotes/domain-core' +import { Username, Uuid } from '@standardnotes/domain-core' @injectable() export class SubscriptionRenewedEventHandler implements DomainEventHandlerInterface { @@ -71,7 +71,20 @@ export class SubscriptionRenewedEventHandler implements DomainEventHandlerInterf private async addRoleToSubscriptionUsers(subscriptionId: number, subscriptionName: string): Promise { const userSubscriptions = await this.userSubscriptionRepository.findBySubscriptionId(subscriptionId) for (const userSubscription of userSubscriptions) { - const user = await userSubscription.user + const userUuidOrError = Uuid.create(userSubscription.userUuid) + if (userUuidOrError.isFailed()) { + this.logger.warn(`Could not add role to user with uuid: ${userUuidOrError.getError()}`) + + continue + } + const userUuid = userUuidOrError.getValue() + + const user = await this.userRepository.findOneByUuid(userUuid) + if (user === null) { + this.logger.warn(`Could not find user with uuid: ${userUuid.value}`) + + continue + } await this.roleService.addUserRoleBasedOnSubscription(user, subscriptionName) } diff --git a/packages/auth/src/Domain/Handler/SubscriptionSyncRequestedEventHandler.ts b/packages/auth/src/Domain/Handler/SubscriptionSyncRequestedEventHandler.ts index a571f5c25..76e40ea7e 100644 --- a/packages/auth/src/Domain/Handler/SubscriptionSyncRequestedEventHandler.ts +++ b/packages/auth/src/Domain/Handler/SubscriptionSyncRequestedEventHandler.ts @@ -128,7 +128,7 @@ export class SubscriptionSyncRequestedEventHandler implements DomainEventHandler } subscription.planName = subscriptionName - subscription.user = Promise.resolve(user) + subscription.userUuid = user.uuid subscription.createdAt = timestamp subscription.updatedAt = timestamp subscription.endsAt = subscriptionExpiresAt diff --git a/packages/auth/src/Domain/Subscription/UserSubscription.ts b/packages/auth/src/Domain/Subscription/UserSubscription.ts index 1cc71165b..f550783a2 100644 --- a/packages/auth/src/Domain/Subscription/UserSubscription.ts +++ b/packages/auth/src/Domain/Subscription/UserSubscription.ts @@ -1,5 +1,4 @@ -import { Column, Entity, Index, JoinColumn, ManyToOne, PrimaryGeneratedColumn } from 'typeorm' -import { User } from '../User/User' +import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm' import { UserSubscriptionType } from './UserSubscriptionType' @Entity({ name: 'user_subscriptions' }) @@ -63,14 +62,9 @@ export class UserSubscription { }) declare subscriptionType: UserSubscriptionType - @ManyToOne( - /* istanbul ignore next */ - () => User, - /* istanbul ignore next */ - (user) => user.subscriptions, - /* istanbul ignore next */ - { onDelete: 'CASCADE', nullable: false, lazy: true, eager: false }, - ) - @JoinColumn({ name: 'user_uuid', referencedColumnName: 'uuid' }) - declare user: Promise + @Column({ + name: 'user_uuid', + length: 36, + }) + declare userUuid: string } diff --git a/packages/auth/src/Domain/UseCase/AcceptSharedSubscriptionInvitation/AcceptSharedSubscriptionInvitation.spec.ts b/packages/auth/src/Domain/UseCase/AcceptSharedSubscriptionInvitation/AcceptSharedSubscriptionInvitation.spec.ts index 1e973b66a..a8df4f600 100644 --- a/packages/auth/src/Domain/UseCase/AcceptSharedSubscriptionInvitation/AcceptSharedSubscriptionInvitation.spec.ts +++ b/packages/auth/src/Domain/UseCase/AcceptSharedSubscriptionInvitation/AcceptSharedSubscriptionInvitation.spec.ts @@ -107,7 +107,7 @@ describe('AcceptSharedSubscriptionInvitation', () => { subscriptionId: 3, subscriptionType: 'shared', updatedAt: 1, - user: Promise.resolve(invitee), + userUuid: '123', }) expect(roleService.addUserRoleBasedOnSubscription).toHaveBeenCalledWith(invitee, 'PLUS_PLAN') expect(applyDefaultSubscriptionSettings.execute).toHaveBeenCalled() @@ -145,7 +145,7 @@ describe('AcceptSharedSubscriptionInvitation', () => { subscriptionId: 3, subscriptionType: 'shared', updatedAt: 3, - user: Promise.resolve(invitee), + userUuid: '123', }) expect(roleService.addUserRoleBasedOnSubscription).toHaveBeenCalledWith(invitee, 'PLUS_PLAN') expect(applyDefaultSubscriptionSettings.execute).toHaveBeenCalled() diff --git a/packages/auth/src/Domain/UseCase/AcceptSharedSubscriptionInvitation/AcceptSharedSubscriptionInvitation.ts b/packages/auth/src/Domain/UseCase/AcceptSharedSubscriptionInvitation/AcceptSharedSubscriptionInvitation.ts index f16f1f9d9..70af840e5 100644 --- a/packages/auth/src/Domain/UseCase/AcceptSharedSubscriptionInvitation/AcceptSharedSubscriptionInvitation.ts +++ b/packages/auth/src/Domain/UseCase/AcceptSharedSubscriptionInvitation/AcceptSharedSubscriptionInvitation.ts @@ -115,7 +115,7 @@ export class AcceptSharedSubscriptionInvitation implements UseCaseInterface { ): Promise { const subscription = new UserSubscription() subscription.planName = subscriptionName - subscription.user = Promise.resolve(user) + subscription.userUuid = user.uuid const timestamp = this.timer.getTimestampInMicroseconds() subscription.createdAt = timestamp subscription.updatedAt = timestamp diff --git a/packages/auth/src/Domain/UseCase/ActivatePremiumFeatures/ActivatePremiumFeatures.ts b/packages/auth/src/Domain/UseCase/ActivatePremiumFeatures/ActivatePremiumFeatures.ts index f90c65d31..4efdd54b6 100644 --- a/packages/auth/src/Domain/UseCase/ActivatePremiumFeatures/ActivatePremiumFeatures.ts +++ b/packages/auth/src/Domain/UseCase/ActivatePremiumFeatures/ActivatePremiumFeatures.ts @@ -53,7 +53,7 @@ export class ActivatePremiumFeatures implements UseCaseInterface { const subscription = new UserSubscription() subscription.planName = subscriptionPlanName.value - subscription.user = Promise.resolve(user) + subscription.userUuid = user.uuid subscription.createdAt = timestamp subscription.updatedAt = timestamp subscription.endsAt = this.timer.convertDateToMicroseconds(endsAt) diff --git a/packages/auth/src/Domain/UseCase/CancelSharedSubscriptionInvitation/CancelSharedSubscriptionInvitation.spec.ts b/packages/auth/src/Domain/UseCase/CancelSharedSubscriptionInvitation/CancelSharedSubscriptionInvitation.spec.ts index 3d6dfeb47..63e74c1b7 100644 --- a/packages/auth/src/Domain/UseCase/CancelSharedSubscriptionInvitation/CancelSharedSubscriptionInvitation.spec.ts +++ b/packages/auth/src/Domain/UseCase/CancelSharedSubscriptionInvitation/CancelSharedSubscriptionInvitation.spec.ts @@ -80,7 +80,7 @@ describe('CancelSharedSubscriptionInvitation', () => { userSubscriptionRepository.findBySubscriptionIdAndType = jest.fn().mockReturnValue([inviterSubscription]) userSubscriptionRepository.findOneByUserUuidAndSubscriptionId = jest .fn() - .mockReturnValue({ user: Promise.resolve(invitee) } as jest.Mocked) + .mockReturnValue({ userUuid: '123' } as jest.Mocked) userSubscriptionRepository.save = jest.fn() roleService = {} as jest.Mocked @@ -120,7 +120,7 @@ describe('CancelSharedSubscriptionInvitation', () => { }) expect(userSubscriptionRepository.save).toHaveBeenCalledWith({ endsAt: 1, - user: Promise.resolve(invitee), + userUuid: '123', }) expect(roleService.removeUserRoleBasedOnSubscription).toHaveBeenCalledWith(invitee, 'PLUS_PLAN') expect(domainEventPublisher.publish).toHaveBeenCalled() diff --git a/packages/auth/src/Domain/UseCase/CreateValetToken/CreateValetToken.spec.ts b/packages/auth/src/Domain/UseCase/CreateValetToken/CreateValetToken.spec.ts index fb1af0705..1221c6d6b 100644 --- a/packages/auth/src/Domain/UseCase/CreateValetToken/CreateValetToken.spec.ts +++ b/packages/auth/src/Domain/UseCase/CreateValetToken/CreateValetToken.spec.ts @@ -5,7 +5,6 @@ import { TokenEncoderInterface, ValetTokenData, ValetTokenOperation } from '@sta import { CreateValetToken } from './CreateValetToken' import { UserSubscription } from '../../Subscription/UserSubscription' -import { User } from '../../User/User' import { UserSubscriptionType } from '../../Subscription/UserSubscriptionType' import { SubscriptionSettingsAssociationServiceInterface } from '../../Setting/SubscriptionSettingsAssociationServiceInterface' import { GetRegularSubscriptionForUser } from '../GetRegularSubscriptionForUser/GetRegularSubscriptionForUser' @@ -25,7 +24,6 @@ describe('CreateValetToken', () => { const valetTokenTTL = 123 let regularSubscription: UserSubscription let sharedSubscription: UserSubscription - let user: User const createUseCase = () => new CreateValetToken( @@ -59,20 +57,16 @@ describe('CreateValetToken', () => { subscriptionSettingsAssociationService = {} as jest.Mocked subscriptionSettingsAssociationService.getFileUploadLimit = jest.fn().mockReturnValue(5_368_709_120) - user = { - uuid: '123', - } as jest.Mocked - regularSubscription = { uuid: '1-2-3', subscriptionType: UserSubscriptionType.Regular, - user: Promise.resolve(user), + userUuid: '123', } as jest.Mocked sharedSubscription = { uuid: '2-3-4', subscriptionType: UserSubscriptionType.Shared, - user: Promise.resolve(user), + userUuid: '123', } as jest.Mocked getRegularSubscription = {} as jest.Mocked diff --git a/packages/auth/src/Domain/UseCase/DeleteAccount/DeleteAccount.spec.ts b/packages/auth/src/Domain/UseCase/DeleteAccount/DeleteAccount.spec.ts index 25eda53ca..70f7b3768 100644 --- a/packages/auth/src/Domain/UseCase/DeleteAccount/DeleteAccount.spec.ts +++ b/packages/auth/src/Domain/UseCase/DeleteAccount/DeleteAccount.spec.ts @@ -11,29 +11,46 @@ import { TimerInterface } from '@standardnotes/time' import { Result, RoleName } from '@standardnotes/domain-core' import { Role } from '../../Role/Role' import { GetRegularSubscriptionForUser } from '../GetRegularSubscriptionForUser/GetRegularSubscriptionForUser' +import { GetSharedSubscriptionForUser } from '../GetSharedSubscriptionForUser/GetSharedSubscriptionForUser' describe('DeleteAccount', () => { let userRepository: UserRepositoryInterface let domainEventPublisher: DomainEventPublisherInterface let domainEventFactory: DomainEventFactoryInterface let getRegularSubscription: GetRegularSubscriptionForUser + let getSharedSubscription: GetSharedSubscriptionForUser let user: User let regularSubscription: UserSubscription + let sharedSubscription: UserSubscription let timer: TimerInterface const createUseCase = () => - new DeleteAccount(userRepository, getRegularSubscription, domainEventPublisher, domainEventFactory, timer) + new DeleteAccount( + userRepository, + getRegularSubscription, + getSharedSubscription, + domainEventPublisher, + domainEventFactory, + timer, + ) beforeEach(() => { user = { uuid: '1-2-3', + email: 'test@test.te', } as jest.Mocked user.roles = Promise.resolve([{ name: RoleName.NAMES.CoreUser } as jest.Mocked]) regularSubscription = { uuid: '1-2-3', subscriptionType: UserSubscriptionType.Regular, - user: Promise.resolve(user), + userUuid: 'u-1-2-3', + } as jest.Mocked + + sharedSubscription = { + uuid: '1-2-3', + subscriptionType: UserSubscriptionType.Shared, + userUuid: 'u-1-2-3', } as jest.Mocked userRepository = {} as jest.Mocked @@ -43,6 +60,9 @@ describe('DeleteAccount', () => { getRegularSubscription = {} as jest.Mocked getRegularSubscription.execute = jest.fn().mockReturnValue(Result.ok(regularSubscription)) + getSharedSubscription = {} as jest.Mocked + getSharedSubscription.execute = jest.fn().mockReturnValue(Result.ok(sharedSubscription)) + domainEventPublisher = {} as jest.Mocked domainEventPublisher.publish = jest.fn() @@ -58,6 +78,7 @@ describe('DeleteAccount', () => { describe('when user uuid is provided', () => { it('should trigger account deletion - no subscription', async () => { getRegularSubscription.execute = jest.fn().mockReturnValue(Result.fail('not found')) + getSharedSubscription.execute = jest.fn().mockReturnValue(Result.fail('not found')) const result = await createUseCase().execute({ userUuid: '00000000-0000-0000-0000-000000000000' }) @@ -66,12 +87,11 @@ describe('DeleteAccount', () => { expect(domainEventFactory.createAccountDeletionRequestedEvent).toHaveBeenLastCalledWith({ userUuid: '1-2-3', userCreatedAtTimestamp: 1, - regularSubscriptionUuid: undefined, - roleNames: ['CORE_USER'], + email: 'test@test.te', }) }) - it('should trigger account deletion - subscription present', async () => { + it('should trigger account deletion - shared subscription present', async () => { const result = await createUseCase().execute({ userUuid: '00000000-0000-0000-0000-000000000000' }) expect(result.isFailed()).toBeFalsy() @@ -79,9 +99,35 @@ describe('DeleteAccount', () => { expect(domainEventPublisher.publish).toHaveBeenCalledTimes(1) expect(domainEventFactory.createAccountDeletionRequestedEvent).toHaveBeenLastCalledWith({ userUuid: '1-2-3', + email: 'test@test.te', userCreatedAtTimestamp: 1, - regularSubscriptionUuid: '1-2-3', - roleNames: ['CORE_USER'], + regularSubscription: { + ownerUuid: 'u-1-2-3', + uuid: '1-2-3', + }, + sharedSubscription: { + ownerUuid: 'u-1-2-3', + uuid: '1-2-3', + }, + }) + }) + + it('should trigger account deletion - regular subscription present', async () => { + getSharedSubscription.execute = jest.fn().mockReturnValue(Result.fail('not found')) + + const result = await createUseCase().execute({ userUuid: '00000000-0000-0000-0000-000000000000' }) + + expect(result.isFailed()).toBeFalsy() + + expect(domainEventPublisher.publish).toHaveBeenCalledTimes(1) + expect(domainEventFactory.createAccountDeletionRequestedEvent).toHaveBeenLastCalledWith({ + userUuid: '1-2-3', + email: 'test@test.te', + userCreatedAtTimestamp: 1, + regularSubscription: { + ownerUuid: 'u-1-2-3', + uuid: '1-2-3', + }, }) }) @@ -109,6 +155,7 @@ describe('DeleteAccount', () => { describe('when username is provided', () => { it('should trigger account deletion - no subscription', async () => { getRegularSubscription.execute = jest.fn().mockReturnValue(Result.fail('not found')) + getSharedSubscription.execute = jest.fn().mockReturnValue(Result.fail('not found')) const result = await createUseCase().execute({ username: 'test@test.te' }) @@ -116,13 +163,12 @@ describe('DeleteAccount', () => { expect(domainEventPublisher.publish).toHaveBeenCalledTimes(1) expect(domainEventFactory.createAccountDeletionRequestedEvent).toHaveBeenLastCalledWith({ userUuid: '1-2-3', + email: 'test@test.te', userCreatedAtTimestamp: 1, - regularSubscriptionUuid: undefined, - roleNames: ['CORE_USER'], }) }) - it('should trigger account deletion - subscription present', async () => { + it('should trigger account deletion - shared subscription present', async () => { const result = await createUseCase().execute({ username: 'test@test.te' }) expect(result.isFailed()).toBeFalsy() @@ -130,9 +176,35 @@ describe('DeleteAccount', () => { expect(domainEventPublisher.publish).toHaveBeenCalledTimes(1) expect(domainEventFactory.createAccountDeletionRequestedEvent).toHaveBeenLastCalledWith({ userUuid: '1-2-3', + email: 'test@test.te', userCreatedAtTimestamp: 1, - regularSubscriptionUuid: '1-2-3', - roleNames: ['CORE_USER'], + regularSubscription: { + ownerUuid: 'u-1-2-3', + uuid: '1-2-3', + }, + sharedSubscription: { + ownerUuid: 'u-1-2-3', + uuid: '1-2-3', + }, + }) + }) + + it('should trigger account deletion - regular subscription present', async () => { + getSharedSubscription.execute = jest.fn().mockReturnValue(Result.fail('not found')) + + const result = await createUseCase().execute({ username: 'test@test.te' }) + + expect(result.isFailed()).toBeFalsy() + + expect(domainEventPublisher.publish).toHaveBeenCalledTimes(1) + expect(domainEventFactory.createAccountDeletionRequestedEvent).toHaveBeenLastCalledWith({ + userUuid: '1-2-3', + email: 'test@test.te', + userCreatedAtTimestamp: 1, + regularSubscription: { + ownerUuid: 'u-1-2-3', + uuid: '1-2-3', + }, }) }) diff --git a/packages/auth/src/Domain/UseCase/DeleteAccount/DeleteAccount.ts b/packages/auth/src/Domain/UseCase/DeleteAccount/DeleteAccount.ts index 4b7b120b3..f9fe7d160 100644 --- a/packages/auth/src/Domain/UseCase/DeleteAccount/DeleteAccount.ts +++ b/packages/auth/src/Domain/UseCase/DeleteAccount/DeleteAccount.ts @@ -8,11 +8,14 @@ import { UserRepositoryInterface } from '../../User/UserRepositoryInterface' import { DeleteAccountDTO } from './DeleteAccountDTO' import { User } from '../../User/User' import { GetRegularSubscriptionForUser } from '../GetRegularSubscriptionForUser/GetRegularSubscriptionForUser' +import { UserSubscription } from '../../Subscription/UserSubscription' +import { GetSharedSubscriptionForUser } from '../GetSharedSubscriptionForUser/GetSharedSubscriptionForUser' export class DeleteAccount implements UseCaseInterface { constructor( private userRepository: UserRepositoryInterface, private getRegularSubscription: GetRegularSubscriptionForUser, + private getSharedSubscription: GetSharedSubscriptionForUser, private domainEventPublisher: DomainEventPublisherInterface, private domainEventFactory: DomainEventFactoryInterface, private timer: TimerInterface, @@ -44,23 +47,39 @@ export class DeleteAccount implements UseCaseInterface { return Result.ok('User already deleted.') } - const roles = await user.roles - - let regularSubscriptionUuid: string | undefined - const result = await this.getRegularSubscription.execute({ + let sharedSubscription: UserSubscription | undefined + const sharedSubscriptionOrError = await this.getSharedSubscription.execute({ userUuid: user.uuid, }) - if (!result.isFailed()) { - const regularSubscription = result.getValue() - regularSubscriptionUuid = regularSubscription.uuid + if (!sharedSubscriptionOrError.isFailed()) { + sharedSubscription = sharedSubscriptionOrError.getValue() + } + + let regularSubscription: UserSubscription | undefined + const regularSubscriptionOrError = await this.getRegularSubscription.execute({ + userUuid: user.uuid, + }) + if (!regularSubscriptionOrError.isFailed()) { + regularSubscription = regularSubscriptionOrError.getValue() } await this.domainEventPublisher.publish( this.domainEventFactory.createAccountDeletionRequestedEvent({ userUuid: user.uuid, + email: user.email, userCreatedAtTimestamp: this.timer.convertDateToMicroseconds(user.createdAt), - regularSubscriptionUuid, - roleNames: roles.map((role) => role.name), + regularSubscription: regularSubscription + ? { + ownerUuid: regularSubscription.userUuid, + uuid: regularSubscription.uuid, + } + : undefined, + sharedSubscription: sharedSubscription + ? { + ownerUuid: sharedSubscription.userUuid, + uuid: sharedSubscription.uuid, + } + : undefined, }), ) diff --git a/packages/auth/src/Domain/UseCase/UpdateStorageQuotaUsedForUser/UpdateStorageQuotaUsedForUser.spec.ts b/packages/auth/src/Domain/UseCase/UpdateStorageQuotaUsedForUser/UpdateStorageQuotaUsedForUser.spec.ts index d1e0cd61d..48ab34668 100644 --- a/packages/auth/src/Domain/UseCase/UpdateStorageQuotaUsedForUser/UpdateStorageQuotaUsedForUser.spec.ts +++ b/packages/auth/src/Domain/UseCase/UpdateStorageQuotaUsedForUser/UpdateStorageQuotaUsedForUser.spec.ts @@ -45,13 +45,13 @@ describe('UpdateStorageQuotaUsedForUser', () => { regularSubscription = { uuid: '00000000-0000-0000-0000-000000000000', subscriptionType: UserSubscriptionType.Regular, - user: Promise.resolve(user), + userUuid: '123', } as jest.Mocked sharedSubscription = { uuid: '2-3-4', subscriptionType: UserSubscriptionType.Shared, - user: Promise.resolve(user), + userUuid: '123', } as jest.Mocked getSharedSubscription = {} as jest.Mocked diff --git a/packages/auth/src/Domain/UseCase/UpdateStorageQuotaUsedForUser/UpdateStorageQuotaUsedForUser.ts b/packages/auth/src/Domain/UseCase/UpdateStorageQuotaUsedForUser/UpdateStorageQuotaUsedForUser.ts index 10c56fc69..af03d5de8 100644 --- a/packages/auth/src/Domain/UseCase/UpdateStorageQuotaUsedForUser/UpdateStorageQuotaUsedForUser.ts +++ b/packages/auth/src/Domain/UseCase/UpdateStorageQuotaUsedForUser/UpdateStorageQuotaUsedForUser.ts @@ -56,7 +56,6 @@ export class UpdateStorageQuotaUsedForUser implements UseCaseInterface { private async updateUploadBytesUsedSetting(subscription: UserSubscription, bytesUsed: number): Promise { let bytesAlreadyUsed = '0' - const subscriptionUser = await subscription.user const bytesUsedSettingExists = await this.getSubscriptionSetting.execute({ userSubscriptionUuid: subscription.uuid, @@ -77,7 +76,7 @@ export class UpdateStorageQuotaUsedForUser implements UseCaseInterface { /* istanbul ignore next */ if (result.isFailed()) { - this.logger.error(`Could not set file upload bytes used for user ${subscriptionUser.uuid}`) + this.logger.error(`Could not set file upload bytes used for subscription ${subscription.uuid}`) } } } diff --git a/packages/auth/src/Domain/User/User.ts b/packages/auth/src/Domain/User/User.ts index c0e9faafc..a91f0e485 100644 --- a/packages/auth/src/Domain/User/User.ts +++ b/packages/auth/src/Domain/User/User.ts @@ -1,7 +1,6 @@ import { Column, Entity, Index, JoinTable, ManyToMany, OneToMany, PrimaryGeneratedColumn } from 'typeorm' import { RevokedSession } from '../Session/RevokedSession' import { Role } from '../Role/Role' -import { UserSubscription } from '../Subscription/UserSubscription' import { ProtocolVersion } from '@standardnotes/common' import { TypeORMEmergencyAccessInvitation } from '../../Infra/TypeORM/TypeORMEmergencyAccessInvitation' @@ -161,16 +160,6 @@ export class User { }) declare roles: Promise> - @OneToMany( - /* istanbul ignore next */ - () => UserSubscription, - /* istanbul ignore next */ - (subscription) => subscription.user, - /* istanbul ignore next */ - { lazy: true, eager: false }, - ) - declare subscriptions: Promise - @OneToMany( /* istanbul ignore next */ () => TypeORMEmergencyAccessInvitation, diff --git a/packages/domain-events/src/Domain/Event/AccountDeletionRequestedEventPayload.ts b/packages/domain-events/src/Domain/Event/AccountDeletionRequestedEventPayload.ts index fcbbb7a70..818e6d0bf 100644 --- a/packages/domain-events/src/Domain/Event/AccountDeletionRequestedEventPayload.ts +++ b/packages/domain-events/src/Domain/Event/AccountDeletionRequestedEventPayload.ts @@ -1,5 +1,13 @@ export interface AccountDeletionRequestedEventPayload { userUuid: string + email: string userCreatedAtTimestamp: number - regularSubscriptionUuid: string | undefined + regularSubscription?: { + uuid: string + ownerUuid: string + } + sharedSubscription?: { + uuid: string + ownerUuid: string + } } diff --git a/packages/domain-events/src/Domain/Event/FileRemovedEventPayload.ts b/packages/domain-events/src/Domain/Event/FileRemovedEventPayload.ts index ab5e37120..42a496ed6 100644 --- a/packages/domain-events/src/Domain/Event/FileRemovedEventPayload.ts +++ b/packages/domain-events/src/Domain/Event/FileRemovedEventPayload.ts @@ -1,6 +1,5 @@ export interface FileRemovedEventPayload { userUuid: string - regularSubscriptionUuid: string fileByteSize: number filePath: string fileName: string diff --git a/packages/files/src/Domain/Event/DomainEventFactory.ts b/packages/files/src/Domain/Event/DomainEventFactory.ts index 326c79025..f3ce5a150 100644 --- a/packages/files/src/Domain/Event/DomainEventFactory.ts +++ b/packages/files/src/Domain/Event/DomainEventFactory.ts @@ -18,7 +18,6 @@ export class DomainEventFactory implements DomainEventFactoryInterface { filePath: string fileName: string fileByteSize: number - regularSubscriptionUuid: string }): FileRemovedEvent { return { type: 'FILE_REMOVED', diff --git a/packages/files/src/Domain/Event/DomainEventFactoryInterface.ts b/packages/files/src/Domain/Event/DomainEventFactoryInterface.ts index 423c377af..5d1003f75 100644 --- a/packages/files/src/Domain/Event/DomainEventFactoryInterface.ts +++ b/packages/files/src/Domain/Event/DomainEventFactoryInterface.ts @@ -18,7 +18,6 @@ export interface DomainEventFactoryInterface { filePath: string fileName: string fileByteSize: number - regularSubscriptionUuid: string }): FileRemovedEvent createSharedVaultFileMovedEvent(payload: { fileByteSize: number diff --git a/packages/files/src/Domain/Handler/AccountDeletionRequestedEventHandler.ts b/packages/files/src/Domain/Handler/AccountDeletionRequestedEventHandler.ts index ed200db24..fb48d23c1 100644 --- a/packages/files/src/Domain/Handler/AccountDeletionRequestedEventHandler.ts +++ b/packages/files/src/Domain/Handler/AccountDeletionRequestedEventHandler.ts @@ -17,7 +17,7 @@ export class AccountDeletionRequestedEventHandler implements DomainEventHandlerI ) {} async handle(event: AccountDeletionRequestedEvent): Promise { - if (event.payload.regularSubscriptionUuid === undefined) { + if (event.payload.regularSubscription === undefined) { return } @@ -38,7 +38,6 @@ export class AccountDeletionRequestedEventHandler implements DomainEventHandlerI for (const fileRemoved of filesRemoved) { await this.domainEventPublisher.publish( this.domainEventFactory.createFileRemovedEvent({ - regularSubscriptionUuid: event.payload.regularSubscriptionUuid, userUuid: fileRemoved.userOrSharedVaultUuid, filePath: fileRemoved.filePath, fileName: fileRemoved.fileName, diff --git a/packages/files/src/Domain/Handler/SharedSubscriptionInvitationCanceledEventHandler.ts b/packages/files/src/Domain/Handler/SharedSubscriptionInvitationCanceledEventHandler.ts index 70cec95db..a981a23f7 100644 --- a/packages/files/src/Domain/Handler/SharedSubscriptionInvitationCanceledEventHandler.ts +++ b/packages/files/src/Domain/Handler/SharedSubscriptionInvitationCanceledEventHandler.ts @@ -40,7 +40,6 @@ export class SharedSubscriptionInvitationCanceledEventHandler implements DomainE for (const fileRemoved of filesRemoved) { await this.domainEventPublisher.publish( this.domainEventFactory.createFileRemovedEvent({ - regularSubscriptionUuid: event.payload.inviterSubscriptionUuid, userUuid: fileRemoved.userOrSharedVaultUuid, filePath: fileRemoved.filePath, fileName: fileRemoved.fileName, diff --git a/packages/files/src/Domain/UseCase/RemoveFile/RemoveFile.ts b/packages/files/src/Domain/UseCase/RemoveFile/RemoveFile.ts index 4ba6f8ce7..3d0595c0f 100644 --- a/packages/files/src/Domain/UseCase/RemoveFile/RemoveFile.ts +++ b/packages/files/src/Domain/UseCase/RemoveFile/RemoveFile.ts @@ -36,7 +36,6 @@ export class RemoveFile implements UseCaseInterface { filePath: `${dto.userInput.userUuid}/${dto.userInput.resourceRemoteIdentifier}`, fileName: dto.userInput.resourceRemoteIdentifier, fileByteSize: removedFileSize, - regularSubscriptionUuid: dto.userInput.regularSubscriptionUuid, }), ) } else if (dto.vaultInput !== undefined) { diff --git a/packages/revisions/src/Domain/Handler/AccountDeletionRequestedEventHandler.spec.ts b/packages/revisions/src/Domain/Handler/AccountDeletionRequestedEventHandler.spec.ts deleted file mode 100644 index f3901c313..000000000 --- a/packages/revisions/src/Domain/Handler/AccountDeletionRequestedEventHandler.spec.ts +++ /dev/null @@ -1,46 +0,0 @@ -import 'reflect-metadata' - -import { AccountDeletionRequestedEvent } from '@standardnotes/domain-events' -import { Logger } from 'winston' -import { AccountDeletionRequestedEventHandler } from './AccountDeletionRequestedEventHandler' -import { RevisionRepositoryInterface } from '../Revision/RevisionRepositoryInterface' - -describe('AccountDeletionRequestedEventHandler', () => { - let revisionRepository: RevisionRepositoryInterface - let logger: Logger - let event: AccountDeletionRequestedEvent - - const createHandler = () => new AccountDeletionRequestedEventHandler(revisionRepository, logger) - - beforeEach(() => { - revisionRepository = {} as jest.Mocked - revisionRepository.removeByUserUuid = jest.fn() - - logger = {} as jest.Mocked - logger.info = jest.fn() - logger.warn = jest.fn() - logger.error = jest.fn() - - event = {} as jest.Mocked - event.createdAt = new Date(1) - event.payload = { - userUuid: '2-3-4', - userCreatedAtTimestamp: 1, - regularSubscriptionUuid: '1-2-3', - } - }) - - it('should remove all revisions for a user', async () => { - event.payload.userUuid = '84c0f8e8-544a-4c7e-9adf-26209303bc1d' - - await createHandler().handle(event) - - expect(revisionRepository.removeByUserUuid).toHaveBeenCalled() - }) - - it('should not remove all revisions for an invalid user uuid', async () => { - await createHandler().handle(event) - - expect(revisionRepository.removeByUserUuid).not.toHaveBeenCalled() - }) -})