Bladeren bron

feat(auth): replace user signed in events with email requested

Karol Sójko 2 jaren geleden
bovenliggende
commit
e48cca6b45

+ 0 - 136
packages/auth/bin/email.ts

@@ -1,136 +0,0 @@
-import 'reflect-metadata'
-
-import 'newrelic'
-
-import { Stream } from 'stream'
-
-import { Logger } from 'winston'
-import * as dayjs from 'dayjs'
-import * as utc from 'dayjs/plugin/utc'
-
-import { UserRepositoryInterface } from '../src/Domain/User/UserRepositoryInterface'
-import { ContainerConfigLoader } from '../src/Bootstrap/Container'
-import TYPES from '../src/Bootstrap/Types'
-import { Env } from '../src/Bootstrap/Env'
-import { SettingServiceInterface } from '../src/Domain/Setting/SettingServiceInterface'
-import { DomainEventFactoryInterface } from '../src/Domain/Event/DomainEventFactoryInterface'
-import { UserSubscriptionRepositoryInterface } from '../src/Domain/Subscription/UserSubscriptionRepositoryInterface'
-import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
-import { MuteMarketingEmailsOption, SettingName } from '@standardnotes/settings'
-import { EmailMessageIdentifier } from '@standardnotes/common'
-import { TimerInterface } from '@standardnotes/time'
-
-const inputArgs = process.argv.slice(2)
-const emailMessageIdentifier = inputArgs[0]
-
-const sendEmailCampaign = async (
-  userRepository: UserRepositoryInterface,
-  settingService: SettingServiceInterface,
-  userSubscriptionRepository: UserSubscriptionRepositoryInterface,
-  timer: TimerInterface,
-  domainEventFactory: DomainEventFactoryInterface,
-  domainEventPublisher: DomainEventPublisherInterface,
-  logger: Logger,
-): Promise<void> => {
-  const stream = await userRepository.streamAll()
-
-  return new Promise((resolve, reject) => {
-    stream
-      .pipe(
-        new Stream.Transform({
-          objectMode: true,
-          transform: async (rawUserData, _encoding, callback) => {
-            try {
-              const emailsMutedSetting = await settingService.findSettingWithDecryptedValue({
-                userUuid: rawUserData.user_uuid,
-                settingName: SettingName.MuteMarketingEmails,
-              })
-
-              if (emailsMutedSetting === null || emailsMutedSetting.value === MuteMarketingEmailsOption.Muted) {
-                callback()
-
-                return
-              }
-
-              let activeSubscription = false
-              let subscriptionPlanName = null
-
-              const userSubscription = await userSubscriptionRepository.findOneByUserUuid(rawUserData.user_uuid)
-              if (userSubscription !== null) {
-                activeSubscription =
-                  !userSubscription.cancelled && userSubscription.endsAt > timer.getTimestampInMicroseconds()
-                subscriptionPlanName = userSubscription.planName
-              }
-
-              await domainEventPublisher.publish(
-                domainEventFactory.createEmailMessageRequestedEvent({
-                  userEmail: rawUserData.user_email,
-                  messageIdentifier: emailMessageIdentifier as EmailMessageIdentifier,
-                  context: {
-                    activeSubscription,
-                    subscriptionPlanName,
-                    muteEmailsSettingUuid: emailsMutedSetting.uuid,
-                  },
-                }),
-              )
-            } catch (error) {
-              logger.error(`Could not process user ${rawUserData.user_uuid}: ${(error as Error).message}`)
-            }
-
-            callback()
-          },
-        }),
-      )
-      .on('finish', resolve)
-      .on('error', reject)
-  })
-}
-
-const container = new ContainerConfigLoader()
-void container.load().then((container) => {
-  dayjs.extend(utc)
-
-  const env: Env = new Env()
-  env.load()
-
-  const logger: Logger = container.get(TYPES.Logger)
-
-  logger.info(`Starting email campaign for email ${emailMessageIdentifier} ...`)
-
-  if (!emailMessageIdentifier) {
-    logger.error('No email message identifier passed as argument. Skipped sending.')
-
-    process.exit(1)
-  }
-
-  const userRepository: UserRepositoryInterface = container.get(TYPES.UserRepository)
-  const settingService: SettingServiceInterface = container.get(TYPES.SettingService)
-  const userSubscriptionRepository: UserSubscriptionRepositoryInterface = container.get(
-    TYPES.UserSubscriptionRepository,
-  )
-  const timer: TimerInterface = container.get(TYPES.Timer)
-  const domainEventFactory: DomainEventFactoryInterface = container.get(TYPES.DomainEventFactory)
-  const domainEventPublisher: DomainEventPublisherInterface = container.get(TYPES.DomainEventPublisher)
-
-  Promise.resolve(
-    sendEmailCampaign(
-      userRepository,
-      settingService,
-      userSubscriptionRepository,
-      timer,
-      domainEventFactory,
-      domainEventPublisher,
-      logger,
-    ),
-  )
-    .then(() => {
-      logger.info(`${emailMessageIdentifier} email campaign complete.`)
-
-      process.exit(0)
-    })
-    .catch((error) => {
-      logger.error(`Could not finish ${emailMessageIdentifier} email campaign: ${error.message}`)
-
-      process.exit(1)
-    })
-})

+ 0 - 6
packages/auth/docker/entrypoint.sh

@@ -50,12 +50,6 @@ case "$COMMAND" in
     yarn workspace @standardnotes/auth-server daily-backup:one_drive
     ;;
 
-  'email-campaign' )
-    echo "[Docker] Starting Email Campaign Sending..."
-    MESSAGE_IDENTIFIER=$1 && shift 1
-    yarn workspace @standardnotes/auth-server email-campaign $MESSAGE_IDENTIFIER
-    ;;
-
   'content-recalculation' )
     echo "[Docker] Starting Content Size Recalculation..."
     yarn workspace @standardnotes/auth-server content-recalculation

+ 1 - 1
packages/auth/jest.config.js

@@ -7,6 +7,6 @@ module.exports = {
   transform: {
     ...tsjPreset.transform,
   },
-  coveragePathIgnorePatterns: ['/Bootstrap/', '/InversifyExpressUtils/', '/Infra/', '/Projection/'],
+  coveragePathIgnorePatterns: ['/Bootstrap/', '/InversifyExpressUtils/', '/Infra/', '/Projection/', '/Domain/Email/'],
   setupFilesAfterEnv: ['./test-setup.ts'],
 }

+ 0 - 1
packages/auth/package.json

@@ -26,7 +26,6 @@
     "daily-backup:one_drive": "yarn node dist/bin/backup.js one_drive daily",
     "weekly-backup:email": "yarn node dist/bin/backup.js email weekly",
     "content-recalculation": "yarn node dist/bin/content.js",
-    "email-campaign": "yarn node dist/bin/email.js",
     "typeorm": "typeorm-ts-node-commonjs",
     "upgrade:snjs": "yarn ncu -u '@standardnotes/*'"
   },

+ 15 - 0
packages/auth/src/Domain/Email/UserSignedIn.ts

@@ -0,0 +1,15 @@
+import { html } from './user-signed-in.html'
+
+export function getSubject(email: string): string {
+  return `New sign-in for ${email}`
+}
+
+export function getBody(email: string, device: string, browser: string, date: Date): string {
+  const body = html
+
+  return body
+    .replace('%%EMAIL%%', email)
+    .replace('%%DEVICE%%', device)
+    .replace('%%BROWSER%%', browser)
+    .replace('%%TIME_AND_DATE%%', date.toLocaleString())
+}

+ 25 - 0
packages/auth/src/Domain/Email/user-signed-in.html.ts

@@ -0,0 +1,25 @@
+export const html = `
+<div>
+<p>Hello,</p>
+<p>We've detected a new sign-in to your account %%EMAIL%%.</p>
+<p>
+  <b>Device type</b>: %%DEVICE%%
+</p>
+<p>
+  <b>Browser type</b>: %%BROWSER%%
+</p>
+<p>
+  <strong>Time and date</strong>: <span>%%TIME_AND_DATE%%</span>
+</p>
+<p>
+  If this was you, please disregard this email. If it wasn't you, we recommend signing into your account and
+  changing your password immediately, then enabling 2FA.
+</p>
+<p>
+  Thanks,
+  <br />
+  SN
+</p>
+<a href="https://app.standardnotes.com/?settings=account">Mute these emails</a>
+</div>
+`

+ 9 - 30
packages/auth/src/Domain/Event/DomainEventFactory.ts

@@ -1,6 +1,6 @@
 /* istanbul ignore file */
 
-import { EmailMessageIdentifier, JSONString, ProtocolVersion, RoleName, Uuid } from '@standardnotes/common'
+import { JSONString, ProtocolVersion, RoleName, Uuid } from '@standardnotes/common'
 import {
   AccountDeletionRequestedEvent,
   UserEmailChangedEvent,
@@ -10,17 +10,16 @@ import {
   EmailBackupRequestedEvent,
   CloudBackupRequestedEvent,
   ListedAccountRequestedEvent,
-  UserSignedInEvent,
   UserDisabledSessionUserAgentLoggingEvent,
   SharedSubscriptionInvitationCreatedEvent,
   SharedSubscriptionInvitationCanceledEvent,
   PredicateVerifiedEvent,
   DomainEventService,
-  EmailMessageRequestedEvent,
   WebSocketMessageRequestedEvent,
   ExitDiscountApplyRequestedEvent,
   UserContentSizeRecalculationRequestedEvent,
   MuteEmailsSettingChangedEvent,
+  EmailRequestedEvent,
 } from '@standardnotes/domain-events'
 import { Predicate, PredicateVerificationResult } from '@standardnotes/predicates'
 import { TimerInterface } from '@standardnotes/time'
@@ -102,13 +101,15 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
     }
   }
 
-  createEmailMessageRequestedEvent(dto: {
+  createEmailRequestedEvent(dto: {
     userEmail: string
-    messageIdentifier: EmailMessageIdentifier
-    context: Record<string, unknown>
-  }): EmailMessageRequestedEvent {
+    messageIdentifier: string
+    level: string
+    body: string
+    subject: string
+  }): EmailRequestedEvent {
     return {
-      type: 'EMAIL_MESSAGE_REQUESTED',
+      type: 'EMAIL_REQUESTED',
       createdAt: this.timer.getUTCDate(),
       meta: {
         correlation: {
@@ -202,28 +203,6 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
     }
   }
 
-  createUserSignedInEvent(dto: {
-    userUuid: string
-    userEmail: string
-    device: string
-    browser: string
-    signInAlertEnabled: boolean
-    muteSignInEmailsSettingUuid: Uuid
-  }): UserSignedInEvent {
-    return {
-      type: 'USER_SIGNED_IN',
-      createdAt: this.timer.getUTCDate(),
-      meta: {
-        correlation: {
-          userIdentifier: dto.userUuid,
-          userIdentifierType: 'uuid',
-        },
-        origin: DomainEventService.Auth,
-      },
-      payload: dto,
-    }
-  }
-
   createListedAccountRequestedEvent(userUuid: string, userEmail: string): ListedAccountRequestedEvent {
     return {
       type: 'LISTED_ACCOUNT_REQUESTED',

+ 8 - 15
packages/auth/src/Domain/Event/DomainEventFactoryInterface.ts

@@ -1,4 +1,4 @@
-import { Uuid, RoleName, EmailMessageIdentifier, ProtocolVersion, JSONString } from '@standardnotes/common'
+import { Uuid, RoleName, ProtocolVersion, JSONString } from '@standardnotes/common'
 import { Predicate, PredicateVerificationResult } from '@standardnotes/predicates'
 import {
   AccountDeletionRequestedEvent,
@@ -9,35 +9,28 @@ import {
   OfflineSubscriptionTokenCreatedEvent,
   EmailBackupRequestedEvent,
   ListedAccountRequestedEvent,
-  UserSignedInEvent,
   UserDisabledSessionUserAgentLoggingEvent,
   SharedSubscriptionInvitationCreatedEvent,
   SharedSubscriptionInvitationCanceledEvent,
   PredicateVerifiedEvent,
-  EmailMessageRequestedEvent,
   WebSocketMessageRequestedEvent,
   ExitDiscountApplyRequestedEvent,
   UserContentSizeRecalculationRequestedEvent,
   MuteEmailsSettingChangedEvent,
+  EmailRequestedEvent,
 } from '@standardnotes/domain-events'
 import { InviteeIdentifierType } from '../SharedSubscription/InviteeIdentifierType'
 
 export interface DomainEventFactoryInterface {
   createUserContentSizeRecalculationRequestedEvent(userUuid: string): UserContentSizeRecalculationRequestedEvent
   createWebSocketMessageRequestedEvent(dto: { userUuid: Uuid; message: JSONString }): WebSocketMessageRequestedEvent
-  createEmailMessageRequestedEvent(dto: {
+  createEmailRequestedEvent(dto: {
     userEmail: string
-    messageIdentifier: EmailMessageIdentifier
-    context: Record<string, unknown>
-  }): EmailMessageRequestedEvent
-  createUserSignedInEvent(dto: {
-    userUuid: string
-    userEmail: string
-    device: string
-    browser: string
-    signInAlertEnabled: boolean
-    muteSignInEmailsSettingUuid: Uuid
-  }): UserSignedInEvent
+    messageIdentifier: string
+    level: string
+    body: string
+    subject: string
+  }): EmailRequestedEvent
   createListedAccountRequestedEvent(userUuid: string, userEmail: string): ListedAccountRequestedEvent
   createUserRegisteredEvent(dto: {
     userUuid: string

+ 4 - 117
packages/auth/src/Domain/UseCase/SignIn.spec.ts

@@ -1,6 +1,6 @@
 import 'reflect-metadata'
 
-import { DomainEventPublisherInterface, UserSignedInEvent } from '@standardnotes/domain-events'
+import { DomainEventPublisherInterface, EmailRequestedEvent } from '@standardnotes/domain-events'
 import { Logger } from 'winston'
 
 import { AuthResponseFactoryInterface } from '../Auth/AuthResponseFactoryInterface'
@@ -10,10 +10,6 @@ import { SessionServiceInterface } from '../Session/SessionServiceInterface'
 import { User } from '../User/User'
 import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
 import { SignIn } from './SignIn'
-import { RoleServiceInterface } from '../Role/RoleServiceInterface'
-import { SettingServiceInterface } from '../Setting/SettingServiceInterface'
-import { Setting } from '../Setting/Setting'
-import { MuteSignInEmailsOption } from '@standardnotes/settings'
 import { PKCERepositoryInterface } from '../User/PKCERepositoryInterface'
 import { CrypterInterface } from '../Encryption/CrypterInterface'
 import { ProtocolVersion } from '@standardnotes/common'
@@ -26,10 +22,7 @@ describe('SignIn', () => {
   let domainEventPublisher: DomainEventPublisherInterface
   let domainEventFactory: DomainEventFactoryInterface
   let sessionService: SessionServiceInterface
-  let roleService: RoleServiceInterface
   let logger: Logger
-  let settingService: SettingServiceInterface
-  let setting: Setting
   let pkceRepository: PKCERepositoryInterface
   let crypter: CrypterInterface
 
@@ -40,8 +33,6 @@ describe('SignIn', () => {
       domainEventPublisher,
       domainEventFactory,
       sessionService,
-      roleService,
-      settingService,
       pkceRepository,
       crypter,
       logger,
@@ -68,27 +59,12 @@ describe('SignIn', () => {
     domainEventPublisher.publish = jest.fn()
 
     domainEventFactory = {} as jest.Mocked<DomainEventFactoryInterface>
-    domainEventFactory.createUserSignedInEvent = jest.fn().mockReturnValue({} as jest.Mocked<UserSignedInEvent>)
+    domainEventFactory.createEmailRequestedEvent = jest.fn().mockReturnValue({} as jest.Mocked<EmailRequestedEvent>)
 
     sessionService = {} as jest.Mocked<SessionServiceInterface>
     sessionService.getOperatingSystemInfoFromUserAgent = jest.fn().mockReturnValue('iOS 1')
     sessionService.getBrowserInfoFromUserAgent = jest.fn().mockReturnValue('Firefox 1')
 
-    roleService = {} as jest.Mocked<RoleServiceInterface>
-    roleService.userHasPermission = jest.fn().mockReturnValue(true)
-
-    setting = {
-      uuid: '3-4-5',
-      value: MuteSignInEmailsOption.NotMuted,
-    } as jest.Mocked<Setting>
-
-    settingService = {} as jest.Mocked<SettingServiceInterface>
-    settingService.findSettingWithDecryptedValue = jest.fn().mockReturnValue(setting)
-    settingService.createOrReplace = jest.fn().mockReturnValue({
-      status: 'created',
-      setting,
-    })
-
     pkceRepository = {} as jest.Mocked<PKCERepositoryInterface>
     pkceRepository.removeCodeChallenge = jest.fn().mockReturnValue(true)
 
@@ -118,14 +94,7 @@ describe('SignIn', () => {
       authResponse: { foo: 'bar' },
     })
 
-    expect(domainEventFactory.createUserSignedInEvent).toHaveBeenCalledWith({
-      browser: 'Firefox 1',
-      device: 'iOS 1',
-      userEmail: 'test@test.com',
-      userUuid: '1-2-3',
-      signInAlertEnabled: true,
-      muteSignInEmailsSettingUuid: '3-4-5',
-    })
+    expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
     expect(domainEventPublisher.publish).toHaveBeenCalled()
   })
 
@@ -160,92 +129,10 @@ describe('SignIn', () => {
       authResponse: { foo: 'bar' },
     })
 
-    expect(domainEventFactory.createUserSignedInEvent).toHaveBeenCalledWith({
-      browser: 'Firefox 1',
-      device: 'iOS 1',
-      userEmail: 'test@test.com',
-      userUuid: '1-2-3',
-      signInAlertEnabled: true,
-      muteSignInEmailsSettingUuid: '3-4-5',
-    })
-    expect(domainEventPublisher.publish).toHaveBeenCalled()
-  })
-
-  it('should sign in a user and disable sign in alert if setting is configured', async () => {
-    setting = {
-      uuid: '3-4-5',
-      value: MuteSignInEmailsOption.Muted,
-    } as jest.Mocked<Setting>
-
-    settingService.findSettingWithDecryptedValue = jest.fn().mockReturnValue(setting)
-
-    expect(
-      await createUseCase().execute({
-        email: 'test@test.te',
-        password: 'qweqwe123123',
-        userAgent: 'Google Chrome',
-        apiVersion: '20190520',
-        ephemeralSession: false,
-        codeVerifier: 'test',
-      }),
-    ).toEqual({
-      success: true,
-      authResponse: { foo: 'bar' },
-    })
-
-    expect(domainEventFactory.createUserSignedInEvent).toHaveBeenCalledWith({
-      browser: 'Firefox 1',
-      device: 'iOS 1',
-      userEmail: 'test@test.com',
-      userUuid: '1-2-3',
-      signInAlertEnabled: false,
-      muteSignInEmailsSettingUuid: '3-4-5',
-    })
+    expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
     expect(domainEventPublisher.publish).toHaveBeenCalled()
   })
 
-  it('should sign in a user and create mute sign in email setting if it does not exist', async () => {
-    settingService.findSettingWithDecryptedValue = jest.fn().mockReturnValue(null)
-
-    expect(
-      await createUseCase().execute({
-        email: 'test@test.te',
-        password: 'qweqwe123123',
-        userAgent: 'Google Chrome',
-        apiVersion: '20190520',
-        ephemeralSession: false,
-        codeVerifier: 'test',
-      }),
-    ).toEqual({
-      success: true,
-      authResponse: { foo: 'bar' },
-    })
-
-    expect(domainEventFactory.createUserSignedInEvent).toHaveBeenCalledWith({
-      browser: 'Firefox 1',
-      device: 'iOS 1',
-      userEmail: 'test@test.com',
-      userUuid: '1-2-3',
-      signInAlertEnabled: true,
-      muteSignInEmailsSettingUuid: '3-4-5',
-    })
-    expect(domainEventPublisher.publish).toHaveBeenCalled()
-    expect(settingService.createOrReplace).toHaveBeenCalledWith({
-      props: {
-        name: 'MUTE_SIGN_IN_EMAILS',
-        sensitive: false,
-        serverEncryptionVersion: 0,
-        unencryptedValue: 'not_muted',
-      },
-      user: {
-        email: 'test@test.com',
-        encryptedPassword: '$2a$11$K3g6XoTau8VmLJcai1bB0eD9/YvBSBRtBhMprJOaVZ0U3SgasZH3a',
-        uuid: '1-2-3',
-        version: '004',
-      },
-    })
-  })
-
   it('should sign in a user even if publishing a sign in event fails', async () => {
     domainEventPublisher.publish = jest.fn().mockImplementation(() => {
       throw new Error('Oops')

+ 12 - 41
packages/auth/src/Domain/UseCase/SignIn.ts

@@ -1,18 +1,12 @@
 import * as bcrypt from 'bcryptjs'
 import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
-import { PermissionName } from '@standardnotes/features'
-import { MuteSignInEmailsOption, SettingName } from '@standardnotes/settings'
 
 import { inject, injectable } from 'inversify'
 import { Logger } from 'winston'
 import TYPES from '../../Bootstrap/Types'
 import { AuthResponseFactoryResolverInterface } from '../Auth/AuthResponseFactoryResolverInterface'
-import { EncryptionVersion } from '../Encryption/EncryptionVersion'
 import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
-import { RoleServiceInterface } from '../Role/RoleServiceInterface'
 import { SessionServiceInterface } from '../Session/SessionServiceInterface'
-import { Setting } from '../Setting/Setting'
-import { SettingServiceInterface } from '../Setting/SettingServiceInterface'
 import { User } from '../User/User'
 import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
 import { SignInDTO } from './SignInDTO'
@@ -23,6 +17,8 @@ import { CrypterInterface } from '../Encryption/CrypterInterface'
 import { SignInDTOV2Challenged } from './SignInDTOV2Challenged'
 import { ProtocolVersion } from '@standardnotes/common'
 import { HttpStatusCode } from '@standardnotes/api'
+import { EmailLevel } from '@standardnotes/domain-core'
+import { getBody, getSubject } from '../Email/UserSignedIn'
 
 @injectable()
 export class SignIn implements UseCaseInterface {
@@ -33,8 +29,6 @@ export class SignIn implements UseCaseInterface {
     @inject(TYPES.DomainEventPublisher) private domainEventPublisher: DomainEventPublisherInterface,
     @inject(TYPES.DomainEventFactory) private domainEventFactory: DomainEventFactoryInterface,
     @inject(TYPES.SessionService) private sessionService: SessionServiceInterface,
-    @inject(TYPES.RoleService) private roleService: RoleServiceInterface,
-    @inject(TYPES.SettingService) private settingService: SettingServiceInterface,
     @inject(TYPES.PKCERepository) private pkceRepository: PKCERepositoryInterface,
     @inject(TYPES.Crypter) private crypter: CrypterInterface,
     @inject(TYPES.Logger) private logger: Logger,
@@ -109,18 +103,18 @@ export class SignIn implements UseCaseInterface {
 
   private async sendSignInEmailNotification(user: User, userAgent: string): Promise<void> {
     try {
-      const muteSignInEmailsSetting = await this.findOrCreateMuteSignInEmailsSetting(user)
-
       await this.domainEventPublisher.publish(
-        this.domainEventFactory.createUserSignedInEvent({
-          userUuid: user.uuid,
+        this.domainEventFactory.createEmailRequestedEvent({
           userEmail: user.email,
-          device: this.sessionService.getOperatingSystemInfoFromUserAgent(userAgent),
-          browser: this.sessionService.getBrowserInfoFromUserAgent(userAgent),
-          signInAlertEnabled:
-            (await this.roleService.userHasPermission(user.uuid, PermissionName.SignInAlerts)) &&
-            muteSignInEmailsSetting.value === MuteSignInEmailsOption.NotMuted,
-          muteSignInEmailsSettingUuid: muteSignInEmailsSetting.uuid,
+          level: EmailLevel.LEVELS.SignIn,
+          body: getBody(
+            user.email,
+            this.sessionService.getOperatingSystemInfoFromUserAgent(userAgent),
+            this.sessionService.getBrowserInfoFromUserAgent(userAgent),
+            new Date(),
+          ),
+          messageIdentifier: 'SIGN_IN',
+          subject: getSubject(user.email),
         }),
       )
     } catch (error) {
@@ -128,29 +122,6 @@ export class SignIn implements UseCaseInterface {
     }
   }
 
-  private async findOrCreateMuteSignInEmailsSetting(user: User): Promise<Setting> {
-    const existingMuteSignInEmailsSetting = await this.settingService.findSettingWithDecryptedValue({
-      userUuid: user.uuid,
-      settingName: SettingName.MuteSignInEmails,
-    })
-
-    if (existingMuteSignInEmailsSetting !== null) {
-      return existingMuteSignInEmailsSetting
-    }
-
-    const createSettingResult = await this.settingService.createOrReplace({
-      user,
-      props: {
-        name: SettingName.MuteSignInEmails,
-        sensitive: false,
-        unencryptedValue: MuteSignInEmailsOption.NotMuted,
-        serverEncryptionVersion: EncryptionVersion.Unencrypted,
-      },
-    })
-
-    return createSettingResult.setting
-  }
-
   private isCodeChallengedVersion(dto: SignInDTO): dto is SignInDTOV2Challenged {
     return (dto as SignInDTOV2Challenged).codeVerifier !== undefined
   }

+ 0 - 7
packages/domain-events/src/Domain/Event/EmailMessageRequestedEvent.ts

@@ -1,7 +0,0 @@
-import { DomainEventInterface } from './DomainEventInterface'
-import { EmailMessageRequestedEventPayload } from './EmailMessageRequestedEventPayload'
-
-export interface EmailMessageRequestedEvent extends DomainEventInterface {
-  type: 'EMAIL_MESSAGE_REQUESTED'
-  payload: EmailMessageRequestedEventPayload
-}

+ 0 - 5
packages/domain-events/src/Domain/Event/EmailMessageRequestedEventPayload.ts

@@ -1,5 +0,0 @@
-export interface EmailMessageRequestedEventPayload {
-  userEmail: string
-  messageIdentifier: string
-  context: Record<string, unknown>
-}

+ 0 - 7
packages/domain-events/src/Domain/Event/UserSignedInEvent.ts

@@ -1,7 +0,0 @@
-import { DomainEventInterface } from './DomainEventInterface'
-import { UserSignedInEventPayload } from './UserSignedInEventPayload'
-
-export interface UserSignedInEvent extends DomainEventInterface {
-  type: 'USER_SIGNED_IN'
-  payload: UserSignedInEventPayload
-}

+ 0 - 10
packages/domain-events/src/Domain/Event/UserSignedInEventPayload.ts

@@ -1,10 +0,0 @@
-import { Uuid } from '@standardnotes/common'
-
-export interface UserSignedInEventPayload {
-  userUuid: string
-  userEmail: string
-  signInAlertEnabled: boolean
-  muteSignInEmailsSettingUuid: Uuid
-  device: string
-  browser?: string
-}

+ 0 - 4
packages/domain-events/src/Domain/index.ts

@@ -28,8 +28,6 @@ export * from './Event/EmailBackupAttachmentCreatedEvent'
 export * from './Event/EmailBackupAttachmentCreatedEventPayload'
 export * from './Event/EmailBackupRequestedEvent'
 export * from './Event/EmailBackupRequestedEventPayload'
-export * from './Event/EmailMessageRequestedEvent'
-export * from './Event/EmailMessageRequestedEventPayload'
 export * from './Event/EmailRequestedEvent'
 export * from './Event/EmailRequestedEventPayload'
 export * from './Event/ExitDiscountAppliedEvent'
@@ -120,8 +118,6 @@ export * from './Event/UserRegisteredEvent'
 export * from './Event/UserRegisteredEventPayload'
 export * from './Event/UserRolesChangedEvent'
 export * from './Event/UserRolesChangedEventPayload'
-export * from './Event/UserSignedInEvent'
-export * from './Event/UserSignedInEventPayload'
 export * from './Event/WebSocketMessageRequestedEvent'
 export * from './Event/WebSocketMessageRequestedEventPayload'
 export * from './Event/WorkspaceInviteAcceptedEvent'