diff --git a/packages/auth/bin/fix_subscriptions.ts b/packages/auth/bin/fix_subscriptions.ts new file mode 100644 index 000000000..078996439 --- /dev/null +++ b/packages/auth/bin/fix_subscriptions.ts @@ -0,0 +1,74 @@ +import 'reflect-metadata' + +import { Logger } from 'winston' + +import { ContainerConfigLoader } from '../src/Bootstrap/Container' +import TYPES from '../src/Bootstrap/Types' +import { Env } from '../src/Bootstrap/Env' +import { UserSubscriptionRepositoryInterface } from '../src/Domain/Subscription/UserSubscriptionRepositoryInterface' +import { DomainEventFactoryInterface } from '../src/Domain/Event/DomainEventFactoryInterface' +import { DomainEventPublisherInterface } from '@standardnotes/domain-events' +import { UserRepositoryInterface } from '../src/Domain/User/UserRepositoryInterface' +import { Uuid } from '@standardnotes/domain-core' + +const fixSubscriptions = async ( + userRepository: UserRepositoryInterface, + userSubscriptionRepository: UserSubscriptionRepositoryInterface, + domainEventFactory: DomainEventFactoryInterface, + domainEventPublisher: DomainEventPublisherInterface, +): Promise => { + const subscriptions = await userSubscriptionRepository.findBySubscriptionId(0) + + for (const subscription of subscriptions) { + const userUuidOrError = Uuid.create(subscription.userUuid) + if (userUuidOrError.isFailed()) { + continue + } + const userUuid = userUuidOrError.getValue() + + const user = await userRepository.findOneByUuid(userUuid) + if (!user) { + continue + } + + await domainEventPublisher.publish( + domainEventFactory.createSubscriptionStateRequestedEvent({ + userEmail: user.email, + }), + ) + } +} + +const container = new ContainerConfigLoader('worker') +void container.load().then((container) => { + const env: Env = new Env() + env.load() + + const logger: Logger = container.get(TYPES.Auth_Logger) + + logger.info('Starting to fix subscriptions with missing subscriptionId ...') + + const userRepository = container.get(TYPES.Auth_UserRepository) + const userSubscriptionRepository = container.get( + TYPES.Auth_UserSubscriptionRepository, + ) + const domainEventFactory = container.get(TYPES.Auth_DomainEventFactory) + const domainEventPublisher = container.get(TYPES.Auth_DomainEventPublisher) + + Promise.resolve( + fixSubscriptions(userRepository, userSubscriptionRepository, domainEventFactory, domainEventPublisher), + ) + .then(() => { + logger.info('Finished fixing subscriptions with missing subscriptionId.') + + process.exit(0) + }) + .catch((error) => { + logger.error('Failed to fix subscriptions with missing subscriptionId.', { + error: error.message, + stack: error.stack, + }) + + process.exit(1) + }) +}) diff --git a/packages/auth/docker/entrypoint-fix-subscriptions.js b/packages/auth/docker/entrypoint-fix-subscriptions.js new file mode 100644 index 000000000..33046ee6b --- /dev/null +++ b/packages/auth/docker/entrypoint-fix-subscriptions.js @@ -0,0 +1,11 @@ +'use strict' + +const path = require('path') + +const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup() + +const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/fix_subscriptions.js'))) + +Object.defineProperty(exports, '__esModule', { value: true }) + +exports.default = index diff --git a/packages/auth/docker/entrypoint.sh b/packages/auth/docker/entrypoint.sh index 95ffcab4f..bd1faff3d 100755 --- a/packages/auth/docker/entrypoint.sh +++ b/packages/auth/docker/entrypoint.sh @@ -42,6 +42,10 @@ case "$COMMAND" in exec node docker/entrypoint-fix-roles.js ;; + 'fix-subscriptions' ) + exec node docker/entrypoint-fix-subscriptions.js + ;; + 'delete-accounts' ) FILE_NAME=$1 && shift 1 MODE=$1 && shift 1 diff --git a/packages/auth/src/Bootstrap/Container.ts b/packages/auth/src/Bootstrap/Container.ts index f14a75a8a..634d87315 100644 --- a/packages/auth/src/Bootstrap/Container.ts +++ b/packages/auth/src/Bootstrap/Container.ts @@ -285,6 +285,7 @@ import { RenewSharedSubscriptions } from '../Domain/UseCase/RenewSharedSubscript import { FixStorageQuotaForUser } from '../Domain/UseCase/FixStorageQuotaForUser/FixStorageQuotaForUser' import { FileQuotaRecalculatedEventHandler } from '../Domain/Handler/FileQuotaRecalculatedEventHandler' import { SessionServiceInterface } from '../Domain/Session/SessionServiceInterface' +import { SubscriptionStateFetchedEventHandler } from '../Domain/Handler/SubscriptionStateFetchedEventHandler' export class ContainerConfigLoader { constructor(private mode: 'server' | 'worker' = 'server') {} @@ -1579,6 +1580,16 @@ export class ContainerConfigLoader { container.get(TYPES.Auth_Logger), ), ) + container + .bind(TYPES.Auth_SubscriptionStateFetchedEventHandler) + .toConstantValue( + new SubscriptionStateFetchedEventHandler( + container.get(TYPES.Auth_UserRepository), + container.get(TYPES.Auth_UserSubscriptionRepository), + container.get(TYPES.Auth_OfflineUserSubscriptionRepository), + container.get(TYPES.Auth_Logger), + ), + ) const eventHandlers: Map = new Map([ ['ACCOUNT_DELETION_REQUESTED', container.get(TYPES.Auth_AccountDeletionRequestedEventHandler)], @@ -1620,6 +1631,7 @@ export class ContainerConfigLoader { 'FILE_QUOTA_RECALCULATED', container.get(TYPES.Auth_FileQuotaRecalculatedEventHandler), ], + ['SUBSCRIPTION_STATE_FETCHED', container.get(TYPES.Auth_SubscriptionStateFetchedEventHandler)], ]) if (isConfiguredForHomeServer) { diff --git a/packages/auth/src/Bootstrap/Types.ts b/packages/auth/src/Bootstrap/Types.ts index 5a68791aa..2a04b5000 100644 --- a/packages/auth/src/Bootstrap/Types.ts +++ b/packages/auth/src/Bootstrap/Types.ts @@ -205,6 +205,7 @@ const TYPES = { ), Auth_UserInvitedToSharedVaultEventHandler: Symbol.for('Auth_UserInvitedToSharedVaultEventHandler'), Auth_FileQuotaRecalculatedEventHandler: Symbol.for('Auth_FileQuotaRecalculatedEventHandler'), + Auth_SubscriptionStateFetchedEventHandler: Symbol.for('Auth_SubscriptionStateFetchedEventHandler'), // Services Auth_DeviceDetector: Symbol.for('Auth_DeviceDetector'), Auth_SessionService: Symbol.for('Auth_SessionService'), diff --git a/packages/auth/src/Domain/Event/DomainEventFactory.ts b/packages/auth/src/Domain/Event/DomainEventFactory.ts index f32146be9..4d3940923 100644 --- a/packages/auth/src/Domain/Event/DomainEventFactory.ts +++ b/packages/auth/src/Domain/Event/DomainEventFactory.ts @@ -22,6 +22,7 @@ import { SessionRefreshedEvent, AccountDeletionVerificationRequestedEvent, FileQuotaRecalculationRequestedEvent, + SubscriptionStateRequestedEvent, } from '@standardnotes/domain-events' import { Predicate, PredicateVerificationResult } from '@standardnotes/predicates' import { TimerInterface } from '@standardnotes/time' @@ -34,6 +35,21 @@ import { KeyParamsData } from '@standardnotes/responses' @injectable() export class DomainEventFactory implements DomainEventFactoryInterface { constructor(@inject(TYPES.Auth_Timer) private timer: TimerInterface) {} + createSubscriptionStateRequestedEvent(dto: { userEmail: string }): SubscriptionStateRequestedEvent { + return { + type: 'SUBSCRIPTION_STATE_REQUESTED', + createdAt: this.timer.getUTCDate(), + meta: { + correlation: { + userIdentifier: dto.userEmail, + userIdentifierType: 'email', + }, + origin: DomainEventService.Auth, + }, + payload: dto, + } + } + createFileQuotaRecalculationRequestedEvent(dto: { userUuid: string }): FileQuotaRecalculationRequestedEvent { return { type: 'FILE_QUOTA_RECALCULATION_REQUESTED', diff --git a/packages/auth/src/Domain/Event/DomainEventFactoryInterface.ts b/packages/auth/src/Domain/Event/DomainEventFactoryInterface.ts index 9e3247439..693d5b04b 100644 --- a/packages/auth/src/Domain/Event/DomainEventFactoryInterface.ts +++ b/packages/auth/src/Domain/Event/DomainEventFactoryInterface.ts @@ -20,11 +20,13 @@ import { SessionRefreshedEvent, AccountDeletionVerificationRequestedEvent, FileQuotaRecalculationRequestedEvent, + SubscriptionStateRequestedEvent, } from '@standardnotes/domain-events' import { InviteeIdentifierType } from '../SharedSubscription/InviteeIdentifierType' import { KeyParamsData } from '@standardnotes/responses' export interface DomainEventFactoryInterface { + createSubscriptionStateRequestedEvent(dto: { userEmail: string }): SubscriptionStateRequestedEvent createFileQuotaRecalculationRequestedEvent(dto: { userUuid: string }): FileQuotaRecalculationRequestedEvent createWebSocketMessageRequestedEvent(dto: { userUuid: string; message: JSONString }): WebSocketMessageRequestedEvent createEmailRequestedEvent(dto: { diff --git a/packages/auth/src/Domain/Handler/SubscriptionCancelledEventHandler.ts b/packages/auth/src/Domain/Handler/SubscriptionCancelledEventHandler.ts index c13767da9..4c0b9a192 100644 --- a/packages/auth/src/Domain/Handler/SubscriptionCancelledEventHandler.ts +++ b/packages/auth/src/Domain/Handler/SubscriptionCancelledEventHandler.ts @@ -4,6 +4,7 @@ import { inject, injectable } from 'inversify' import TYPES from '../../Bootstrap/Types' import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface' import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/OfflineUserSubscriptionRepositoryInterface' +import { Logger } from 'winston' @injectable() export class SubscriptionCancelledEventHandler implements DomainEventHandlerInterface { @@ -12,9 +13,20 @@ export class SubscriptionCancelledEventHandler implements DomainEventHandlerInte private userSubscriptionRepository: UserSubscriptionRepositoryInterface, @inject(TYPES.Auth_OfflineUserSubscriptionRepository) private offlineUserSubscriptionRepository: OfflineUserSubscriptionRepositoryInterface, + @inject(TYPES.Auth_Logger) private logger: Logger, ) {} async handle(event: SubscriptionCancelledEvent): Promise { + if (!event.payload.subscriptionId) { + this.logger.error('Subscription ID is missing', { + codeTag: 'SubscriptionCancelledEventHandler.handle', + subscriptionId: event.payload.subscriptionId, + userId: event.payload.userEmail, + }) + + return + } + if (event.payload.offline) { await this.updateOfflineSubscriptionCancelled(event.payload.subscriptionId, event.payload.timestamp) diff --git a/packages/auth/src/Domain/Handler/SubscriptionExpiredEventHandler.ts b/packages/auth/src/Domain/Handler/SubscriptionExpiredEventHandler.ts index a56f4c91a..8381b26df 100644 --- a/packages/auth/src/Domain/Handler/SubscriptionExpiredEventHandler.ts +++ b/packages/auth/src/Domain/Handler/SubscriptionExpiredEventHandler.ts @@ -22,6 +22,16 @@ export class SubscriptionExpiredEventHandler implements DomainEventHandlerInterf ) {} async handle(event: SubscriptionExpiredEvent): Promise { + if (!event.payload.subscriptionId) { + this.logger.error('Subscription ID is missing', { + codeTag: 'SubscriptionExpiredEventHandler.handle', + subscriptionId: event.payload.subscriptionId, + userId: event.payload.userEmail, + }) + + return + } + if (event.payload.offline) { await this.updateOfflineSubscriptionEndsAt(event.payload.subscriptionId, event.payload.timestamp) diff --git a/packages/auth/src/Domain/Handler/SubscriptionPurchasedEventHandler.ts b/packages/auth/src/Domain/Handler/SubscriptionPurchasedEventHandler.ts index bcfc560cc..955f4c6ec 100644 --- a/packages/auth/src/Domain/Handler/SubscriptionPurchasedEventHandler.ts +++ b/packages/auth/src/Domain/Handler/SubscriptionPurchasedEventHandler.ts @@ -25,6 +25,16 @@ export class SubscriptionPurchasedEventHandler implements DomainEventHandlerInte ) {} async handle(event: SubscriptionPurchasedEvent): Promise { + if (!event.payload.subscriptionId) { + this.logger.error('Subscription ID is missing', { + codeTag: 'SubscriptionPurchasedEventHandler.handle', + subscriptionId: event.payload.subscriptionId, + userId: event.payload.userEmail, + }) + + return + } + if (event.payload.offline) { const offlineUserSubscription = await this.createOfflineSubscription( event.payload.subscriptionId, diff --git a/packages/auth/src/Domain/Handler/SubscriptionReassignedEventHandler.ts b/packages/auth/src/Domain/Handler/SubscriptionReassignedEventHandler.ts index 3b4e6cbd7..34320fa0a 100644 --- a/packages/auth/src/Domain/Handler/SubscriptionReassignedEventHandler.ts +++ b/packages/auth/src/Domain/Handler/SubscriptionReassignedEventHandler.ts @@ -22,6 +22,16 @@ export class SubscriptionReassignedEventHandler implements DomainEventHandlerInt ) {} async handle(event: SubscriptionReassignedEvent): Promise { + if (!event.payload.subscriptionId) { + this.logger.error('Subscription ID is missing', { + codeTag: 'SubscriptionReassignedEventHandler.handle', + subscriptionId: event.payload.subscriptionId, + userId: event.payload.userEmail, + }) + + return + } + const usernameOrError = Username.create(event.payload.userEmail) if (usernameOrError.isFailed()) { return diff --git a/packages/auth/src/Domain/Handler/SubscriptionRefundedEventHandler.ts b/packages/auth/src/Domain/Handler/SubscriptionRefundedEventHandler.ts index 1e7902132..f62441131 100644 --- a/packages/auth/src/Domain/Handler/SubscriptionRefundedEventHandler.ts +++ b/packages/auth/src/Domain/Handler/SubscriptionRefundedEventHandler.ts @@ -22,6 +22,16 @@ export class SubscriptionRefundedEventHandler implements DomainEventHandlerInter ) {} async handle(event: SubscriptionRefundedEvent): Promise { + if (!event.payload.subscriptionId) { + this.logger.error('Subscription ID is missing', { + codeTag: 'SubscriptionRefundedEventHandler.handle', + subscriptionId: event.payload.subscriptionId, + userId: event.payload.userEmail, + }) + + return + } + if (event.payload.offline) { await this.updateOfflineSubscriptionEndsAt(event.payload.subscriptionId, event.payload.timestamp) diff --git a/packages/auth/src/Domain/Handler/SubscriptionRenewedEventHandler.ts b/packages/auth/src/Domain/Handler/SubscriptionRenewedEventHandler.ts index 237de4a44..586b1d1ff 100644 --- a/packages/auth/src/Domain/Handler/SubscriptionRenewedEventHandler.ts +++ b/packages/auth/src/Domain/Handler/SubscriptionRenewedEventHandler.ts @@ -23,6 +23,16 @@ export class SubscriptionRenewedEventHandler implements DomainEventHandlerInterf ) {} async handle(event: SubscriptionRenewedEvent): Promise { + if (!event.payload.subscriptionId) { + this.logger.error('Subscription ID is missing', { + codeTag: 'SubscriptionRenewedEventHandler.handle', + subscriptionId: event.payload.subscriptionId, + userId: event.payload.userEmail, + }) + + return + } + if (event.payload.offline) { const offlineUserSubscription = await this.offlineUserSubscriptionRepository.findOneBySubscriptionId( event.payload.subscriptionId, diff --git a/packages/auth/src/Domain/Handler/SubscriptionStateFetchedEventHandler.ts b/packages/auth/src/Domain/Handler/SubscriptionStateFetchedEventHandler.ts new file mode 100644 index 000000000..ff8b9ef4a --- /dev/null +++ b/packages/auth/src/Domain/Handler/SubscriptionStateFetchedEventHandler.ts @@ -0,0 +1,123 @@ +import { Username } from '@standardnotes/domain-core' +import { DomainEventHandlerInterface, SubscriptionStateFetchedEvent } from '@standardnotes/domain-events' +import { Logger } from 'winston' + +import { UserRepositoryInterface } from '../User/UserRepositoryInterface' +import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface' +import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/OfflineUserSubscriptionRepositoryInterface' + +export class SubscriptionStateFetchedEventHandler implements DomainEventHandlerInterface { + constructor( + private userRepository: UserRepositoryInterface, + private userSubscriptionRepository: UserSubscriptionRepositoryInterface, + private offlineUserSubscriptionRepository: OfflineUserSubscriptionRepositoryInterface, + private logger: Logger, + ) {} + + async handle(event: SubscriptionStateFetchedEvent): Promise { + if (!event.payload.subscriptionId) { + this.logger.error('Subscription ID is missing', { + codeTag: 'SubscriptionStateFetchedEventHandler.handle', + subscriptionId: event.payload.subscriptionId, + userId: event.payload.userEmail, + }) + + return + } + + this.logger.info('Subscription state update fetched', { + subscriptionId: event.payload.subscriptionId, + }) + + if (event.payload.offline) { + this.logger.info('Updating offline subscription', { + subscriptionId: event.payload.subscriptionId, + }) + + const subscription = await this.offlineUserSubscriptionRepository.findOneByEmailAndSubscriptionId( + event.payload.userEmail, + 0, + ) + if (!subscription) { + this.logger.error('Offline subscription not found', { + subscriptionId: event.payload.subscriptionId, + }) + + return + } + + subscription.planName = event.payload.subscriptionName + subscription.email = event.payload.userEmail + subscription.endsAt = event.payload.subscriptionExpiresAt + subscription.cancelled = event.payload.canceled + if (subscription.subscriptionId !== event.payload.subscriptionId) { + this.logger.warn('Subscription IDs do not match', { + previousSubscriptionId: subscription.subscriptionId, + subscriptionId: event.payload.subscriptionId, + }) + } + subscription.subscriptionId = event.payload.subscriptionId + + await this.offlineUserSubscriptionRepository.save(subscription) + + this.logger.info('Offline subscription updated', { + subscriptionId: event.payload.subscriptionId, + }) + + return + } + + const usernameOrError = Username.create(event.payload.userEmail) + if (usernameOrError.isFailed()) { + this.logger.warn(`Could not update subscription: ${usernameOrError.getError()}`, { + subscriptionId: event.payload.subscriptionId, + }) + + return + } + const username = usernameOrError.getValue() + + const user = await this.userRepository.findOneByUsernameOrEmail(username) + + if (user === null) { + this.logger.warn(`Could not find user with email: ${username.value}`, { + subscriptionId: event.payload.subscriptionId, + }) + + return + } + + this.logger.info('Updating subscription', { + userId: user.uuid, + subscriptionId: event.payload.subscriptionId, + }) + + const subscription = await this.userSubscriptionRepository.findOneByUserUuidAndSubscriptionId(user.uuid, 0) + if (!subscription) { + this.logger.error('Subscription not found', { + userId: user.uuid, + subscriptionId: event.payload.subscriptionId, + }) + + return + } + + subscription.planName = event.payload.subscriptionName + subscription.endsAt = event.payload.subscriptionExpiresAt + subscription.cancelled = event.payload.canceled + if (subscription.subscriptionId !== event.payload.subscriptionId) { + this.logger.warn('Subscription IDs do not match', { + previousSubscriptionId: subscription.subscriptionId, + subscriptionId: event.payload.subscriptionId, + }) + } + subscription.subscriptionId = event.payload.subscriptionId + + await this.userSubscriptionRepository.save(subscription) + + this.logger.info('Subscription updated to current state', { + userId: user.uuid, + subscriptionId: event.payload.subscriptionId, + }) + } +} diff --git a/packages/auth/src/Domain/Handler/SubscriptionSyncRequestedEventHandler.ts b/packages/auth/src/Domain/Handler/SubscriptionSyncRequestedEventHandler.ts index a8b74463a..8c4d9e2b3 100644 --- a/packages/auth/src/Domain/Handler/SubscriptionSyncRequestedEventHandler.ts +++ b/packages/auth/src/Domain/Handler/SubscriptionSyncRequestedEventHandler.ts @@ -33,6 +33,16 @@ export class SubscriptionSyncRequestedEventHandler implements DomainEventHandler ) {} async handle(event: SubscriptionSyncRequestedEvent): Promise { + if (!event.payload.subscriptionId) { + this.logger.error('Subscription ID is missing', { + codeTag: 'SubscriptionSyncRequestedEventHandler.handle', + subscriptionId: event.payload.subscriptionId, + userId: event.payload.userEmail, + }) + + return + } + this.logger.info('Subscription sync requested', { subscriptionId: event.payload.subscriptionId, }) diff --git a/packages/auth/src/Domain/Subscription/OfflineUserSubscriptionRepositoryInterface.ts b/packages/auth/src/Domain/Subscription/OfflineUserSubscriptionRepositoryInterface.ts index f047603d2..a97d0eff6 100644 --- a/packages/auth/src/Domain/Subscription/OfflineUserSubscriptionRepositoryInterface.ts +++ b/packages/auth/src/Domain/Subscription/OfflineUserSubscriptionRepositoryInterface.ts @@ -2,6 +2,7 @@ import { OfflineUserSubscription } from './OfflineUserSubscription' export interface OfflineUserSubscriptionRepositoryInterface { findOneByEmail(email: string): Promise + findOneByEmailAndSubscriptionId(email: string, subscriptionId: number): Promise findOneBySubscriptionId(subscriptionId: number): Promise findByEmail(email: string, activeAfter: number): Promise updateEndsAt(subscriptionId: number, endsAt: number, updatedAt: number): Promise diff --git a/packages/auth/src/Infra/TypeORM/TypeORMOfflineUserSubscriptionRepository.ts b/packages/auth/src/Infra/TypeORM/TypeORMOfflineUserSubscriptionRepository.ts index 3f4545f54..3b5d34f71 100644 --- a/packages/auth/src/Infra/TypeORM/TypeORMOfflineUserSubscriptionRepository.ts +++ b/packages/auth/src/Infra/TypeORM/TypeORMOfflineUserSubscriptionRepository.ts @@ -12,6 +12,19 @@ export class TypeORMOfflineUserSubscriptionRepository implements OfflineUserSubs private ormRepository: Repository, ) {} + async findOneByEmailAndSubscriptionId( + email: string, + subscriptionId: number, + ): Promise { + return await this.ormRepository + .createQueryBuilder() + .where('email = :email AND subscription_id = :subscriptionId', { + email, + subscriptionId, + }) + .getOne() + } + async save(offlineUserSubscription: OfflineUserSubscription): Promise { return this.ormRepository.save(offlineUserSubscription) } diff --git a/packages/domain-events/src/Domain/Event/SubscriptionStateFetchedEvent.ts b/packages/domain-events/src/Domain/Event/SubscriptionStateFetchedEvent.ts new file mode 100644 index 000000000..52f4746c0 --- /dev/null +++ b/packages/domain-events/src/Domain/Event/SubscriptionStateFetchedEvent.ts @@ -0,0 +1,8 @@ +import { DomainEventInterface } from './DomainEventInterface' + +import { SubscriptionStateFetchedEventPayload } from './SubscriptionStateFetchedEventPayload' + +export interface SubscriptionStateFetchedEvent extends DomainEventInterface { + type: 'SUBSCRIPTION_STATE_FETCHED' + payload: SubscriptionStateFetchedEventPayload +} diff --git a/packages/domain-events/src/Domain/Event/SubscriptionStateFetchedEventPayload.ts b/packages/domain-events/src/Domain/Event/SubscriptionStateFetchedEventPayload.ts new file mode 100644 index 000000000..0d0527819 --- /dev/null +++ b/packages/domain-events/src/Domain/Event/SubscriptionStateFetchedEventPayload.ts @@ -0,0 +1,11 @@ +export interface SubscriptionStateFetchedEventPayload { + userEmail: string + subscriptionId: number + subscriptionName: string + subscriptionExpiresAt: number + timestamp: number + offline: boolean + canceled: boolean + extensionKey: string + offlineFeaturesToken: string +} diff --git a/packages/domain-events/src/Domain/Event/SubscriptionStateRequestedEvent.ts b/packages/domain-events/src/Domain/Event/SubscriptionStateRequestedEvent.ts new file mode 100644 index 000000000..30397d051 --- /dev/null +++ b/packages/domain-events/src/Domain/Event/SubscriptionStateRequestedEvent.ts @@ -0,0 +1,8 @@ +import { DomainEventInterface } from './DomainEventInterface' + +import { SubscriptionStateRequestedEventPayload } from './SubscriptionStateRequestedEventPayload' + +export interface SubscriptionStateRequestedEvent extends DomainEventInterface { + type: 'SUBSCRIPTION_STATE_REQUESTED' + payload: SubscriptionStateRequestedEventPayload +} diff --git a/packages/domain-events/src/Domain/Event/SubscriptionStateRequestedEventPayload.ts b/packages/domain-events/src/Domain/Event/SubscriptionStateRequestedEventPayload.ts new file mode 100644 index 000000000..8e8fdf807 --- /dev/null +++ b/packages/domain-events/src/Domain/Event/SubscriptionStateRequestedEventPayload.ts @@ -0,0 +1,3 @@ +export interface SubscriptionStateRequestedEventPayload { + userEmail: string +} diff --git a/packages/domain-events/src/Domain/index.ts b/packages/domain-events/src/Domain/index.ts index 6ada66822..864eb4fd1 100644 --- a/packages/domain-events/src/Domain/index.ts +++ b/packages/domain-events/src/Domain/index.ts @@ -110,6 +110,10 @@ export * from './Event/SubscriptionExpiredEvent' export * from './Event/SubscriptionExpiredEventPayload' export * from './Event/SubscriptionRevertRequestedEvent' export * from './Event/SubscriptionRevertRequestedEventPayload' +export * from './Event/SubscriptionStateFetchedEvent' +export * from './Event/SubscriptionStateFetchedEventPayload' +export * from './Event/SubscriptionStateRequestedEvent' +export * from './Event/SubscriptionStateRequestedEventPayload' export * from './Event/SubscriptionSyncRequestedEvent' export * from './Event/SubscriptionSyncRequestedEventPayload' export * from './Event/UserAddedToSharedVaultEvent'