mirror of
https://github.com/standardnotes/server
synced 2026-04-26 21:01:31 -04:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7e74261f62 | |||
| 32601f34f1 | |||
| aef69a1a96 | |||
| 130f90bdb6 | |||
| 851c7de87f | |||
| 118156c62d | |||
| cdad3143c9 | |||
| 00fe32136e | |||
| 52f56eeb68 | |||
| b595264e31 | |||
| bf04262170 | |||
| fd589922bb | |||
| fb7029f5c1 | |||
| cc4b4f9bf8 | |||
| b048d6d7e3 | |||
| cffc1f442f | |||
| 91fe710741 | |||
| 5a1eb9fdac | |||
| a64ef6e750 | |||
| 47d2012b3d | |||
| 2c99cd2e21 | |||
| 435cd2f66a | |||
| 372b12dfc2 | |||
| 3a12f5c1c4 | |||
| 781de224b6 | |||
| eff09454c3 | |||
| 473feba6a8 | |||
| e9f0704fb0 | |||
| 8c99469d88 | |||
| 8ec1311dfc | |||
| e48cca6b45 | |||
| d660721f95 | |||
| c52bb93d79 | |||
| ffb6bfd0c9 | |||
| 6e0855f9b3 |
@@ -3056,6 +3056,7 @@ const RAW_RUNTIME_STATE =
|
|||||||
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.0"],\
|
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.0"],\
|
||||||
["@sentry/node", "npm:7.19.0"],\
|
["@sentry/node", "npm:7.19.0"],\
|
||||||
["@standardnotes/common", "workspace:packages/common"],\
|
["@standardnotes/common", "workspace:packages/common"],\
|
||||||
|
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
|
||||||
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
|
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
|
||||||
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
|
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
|
||||||
["@standardnotes/predicates", "workspace:packages/predicates"],\
|
["@standardnotes/predicates", "workspace:packages/predicates"],\
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "all",
|
||||||
|
"printWidth": 120,
|
||||||
|
"semi": false
|
||||||
|
}
|
||||||
@@ -3,6 +3,50 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [2.12.17](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.12.16...@standardnotes/analytics@2.12.17) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
|
## [2.12.16](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.12.15...@standardnotes/analytics@2.12.16) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
|
## [2.12.15](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.12.14...@standardnotes/analytics@2.12.15) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
|
## [2.12.14](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.12.13...@standardnotes/analytics@2.12.14) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
|
## [2.12.13](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.12.12...@standardnotes/analytics@2.12.13) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
|
## [2.12.12](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.12.11...@standardnotes/analytics@2.12.12) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
|
## [2.12.11](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.12.10...@standardnotes/analytics@2.12.11) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
|
## [2.12.10](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.12.9...@standardnotes/analytics@2.12.10) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
|
## [2.12.9](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.12.8...@standardnotes/analytics@2.12.9) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
|
## [2.12.8](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.12.7...@standardnotes/analytics@2.12.8) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
|
## [2.12.7](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.12.6...@standardnotes/analytics@2.12.7) (2022-12-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|
||||||
## [2.12.6](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.12.5...@standardnotes/analytics@2.12.6) (2022-12-07)
|
## [2.12.6](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.12.5...@standardnotes/analytics@2.12.6) (2022-12-07)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/analytics
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/analytics",
|
"name": "@standardnotes/analytics",
|
||||||
"version": "2.12.6",
|
"version": "2.12.17",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <19.0.0"
|
"node": ">=18.0.0 <19.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,50 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.39.21](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.39.20...@standardnotes/api-gateway@1.39.21) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
## [1.39.20](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.39.19...@standardnotes/api-gateway@1.39.20) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
## [1.39.19](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.39.18...@standardnotes/api-gateway@1.39.19) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
## [1.39.18](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.39.17...@standardnotes/api-gateway@1.39.18) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
## [1.39.17](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.39.16...@standardnotes/api-gateway@1.39.17) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
## [1.39.16](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.39.15...@standardnotes/api-gateway@1.39.16) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
## [1.39.15](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.39.14...@standardnotes/api-gateway@1.39.15) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
## [1.39.14](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.39.13...@standardnotes/api-gateway@1.39.14) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
## [1.39.13](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.39.12...@standardnotes/api-gateway@1.39.13) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
## [1.39.12](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.39.11...@standardnotes/api-gateway@1.39.12) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
## [1.39.11](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.39.10...@standardnotes/api-gateway@1.39.11) (2022-12-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
## [1.39.10](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.39.9...@standardnotes/api-gateway@1.39.10) (2022-12-07)
|
## [1.39.10](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.39.9...@standardnotes/api-gateway@1.39.10) (2022-12-07)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/api-gateway",
|
"name": "@standardnotes/api-gateway",
|
||||||
"version": "1.39.10",
|
"version": "1.39.21",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <19.0.0"
|
"node": ">=18.0.0 <19.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,64 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.66.3](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.66.2...@standardnotes/auth-server@1.66.3) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
|
## [1.66.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.66.1...@standardnotes/auth-server@1.66.2) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
|
## [1.66.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.66.0...@standardnotes/auth-server@1.66.1) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
|
# [1.66.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.65.0...@standardnotes/auth-server@1.66.0) (2022-12-09)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **email:** replace offline subscription token created event in favour of email requested ([b595264](https://github.com/standardnotes/server/commit/b595264e313ac5ae5404f6a4a05b90b8c11f7f02))
|
||||||
|
|
||||||
|
# [1.65.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.64.7...@standardnotes/auth-server@1.65.0) (2022-12-09)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **auth:** remove offline subscription token created event in favour of email requested ([fd58992](https://github.com/standardnotes/server/commit/fd589922bba29595a0dfd154a42fe158024fad28))
|
||||||
|
|
||||||
|
## [1.64.7](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.64.6...@standardnotes/auth-server@1.64.7) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
|
## [1.64.6](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.64.5...@standardnotes/auth-server@1.64.6) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
|
## [1.64.5](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.64.4...@standardnotes/auth-server@1.64.5) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
|
## [1.64.4](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.64.3...@standardnotes/auth-server@1.64.4) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
|
## [1.64.3](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.64.2...@standardnotes/auth-server@1.64.3) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
|
## [1.64.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.64.1...@standardnotes/auth-server@1.64.2) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
|
## [1.64.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.64.0...@standardnotes/auth-server@1.64.1) (2022-12-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
|
# [1.64.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.63.2...@standardnotes/auth-server@1.64.0) (2022-12-07)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **auth:** replace user signed in events with email requested ([e48cca6](https://github.com/standardnotes/server/commit/e48cca6b45b02876f2d82b726c1d2f124d90b587))
|
||||||
|
|
||||||
## [1.63.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.63.1...@standardnotes/auth-server@1.63.2) (2022-12-07)
|
## [1.63.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.63.1...@standardnotes/auth-server@1.63.2) (2022-12-07)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/auth-server
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|||||||
@@ -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)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -50,12 +50,6 @@ case "$COMMAND" in
|
|||||||
yarn workspace @standardnotes/auth-server daily-backup:one_drive
|
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' )
|
'content-recalculation' )
|
||||||
echo "[Docker] Starting Content Size Recalculation..."
|
echo "[Docker] Starting Content Size Recalculation..."
|
||||||
yarn workspace @standardnotes/auth-server content-recalculation
|
yarn workspace @standardnotes/auth-server content-recalculation
|
||||||
|
|||||||
@@ -7,6 +7,6 @@ module.exports = {
|
|||||||
transform: {
|
transform: {
|
||||||
...tsjPreset.transform,
|
...tsjPreset.transform,
|
||||||
},
|
},
|
||||||
coveragePathIgnorePatterns: ['/Bootstrap/', '/InversifyExpressUtils/', '/Infra/', '/Projection/'],
|
coveragePathIgnorePatterns: ['/Bootstrap/', '/InversifyExpressUtils/', '/Infra/', '/Projection/', '/Domain/Email/'],
|
||||||
setupFilesAfterEnv: ['./test-setup.ts'],
|
setupFilesAfterEnv: ['./test-setup.ts'],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/auth-server",
|
"name": "@standardnotes/auth-server",
|
||||||
"version": "1.63.2",
|
"version": "1.66.3",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <19.0.0"
|
"node": ">=18.0.0 <19.0.0"
|
||||||
},
|
},
|
||||||
@@ -26,7 +26,6 @@
|
|||||||
"daily-backup:one_drive": "yarn node dist/bin/backup.js one_drive daily",
|
"daily-backup:one_drive": "yarn node dist/bin/backup.js one_drive daily",
|
||||||
"weekly-backup:email": "yarn node dist/bin/backup.js email weekly",
|
"weekly-backup:email": "yarn node dist/bin/backup.js email weekly",
|
||||||
"content-recalculation": "yarn node dist/bin/content.js",
|
"content-recalculation": "yarn node dist/bin/content.js",
|
||||||
"email-campaign": "yarn node dist/bin/email.js",
|
|
||||||
"typeorm": "typeorm-ts-node-commonjs",
|
"typeorm": "typeorm-ts-node-commonjs",
|
||||||
"upgrade:snjs": "yarn ncu -u '@standardnotes/*'"
|
"upgrade:snjs": "yarn ncu -u '@standardnotes/*'"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { html } from './offline-subscription-token-created.html'
|
||||||
|
|
||||||
|
export function getSubject(): string {
|
||||||
|
return 'Access to your Standard Notes Subscription Dashboard'
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getBody(email: string, offlineSubscriptionDashboardUrl: string): string {
|
||||||
|
return html(email, offlineSubscriptionDashboardUrl)
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { html } from './shared-subscription-invitation-created.html'
|
||||||
|
|
||||||
|
export function getSubject(): string {
|
||||||
|
return 'You have been invited to a Standard Notes subscription'
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getBody(inviterIdentifier: string, inviteUuid: string): string {
|
||||||
|
return html(inviterIdentifier, inviteUuid)
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
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 {
|
||||||
|
return html(email, device, browser, date.toLocaleString())
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
export const html = (userEmail: string, offlineSubscriptionDashboardUrl: string) => `<div class="sn-component">
|
||||||
|
<div class="sk-panel static">
|
||||||
|
<div class="sk-panel-content">
|
||||||
|
<div class="sk-panel-section">
|
||||||
|
<h1 class="h1 title sk-panel-row">
|
||||||
|
<div class="sk-panel-column">
|
||||||
|
Access your Standard Notes Subscription Dashboard,
|
||||||
|
</div>
|
||||||
|
</h1>
|
||||||
|
<div class="faded sk-panel-row small">Registered as ${userEmail}</div>
|
||||||
|
</div>
|
||||||
|
<div class="sk-panel-section">
|
||||||
|
<div class="title">Link to your subscription dashboard: <a
|
||||||
|
href="${offlineSubscriptionDashboardUrl}">${offlineSubscriptionDashboardUrl}</a></div>
|
||||||
|
</div>
|
||||||
|
<div class="sk-panel-section">
|
||||||
|
<p>
|
||||||
|
Get help any time by visiting our <a href="https://standardnotes.com/help">Help page</a>
|
||||||
|
or by replying directly to this email.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>`
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
export const html = (inviterIdentifier: string, inviteUuid: string) => `<p>Hello,</p>
|
||||||
|
<p>You've been invited to join a Standard Notes premium subscription at no cost. ${inviterIdentifier} has invited you to share the benefits of their subscription plan.</p>
|
||||||
|
<p>
|
||||||
|
<a href='https://app.standardnotes.com/?accept-subscription-invite=${inviteUuid}'>Accept Invite</a>
|
||||||
|
</p>`
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
export const html = (email: string, device: string, browser: string, timeAndDate: string) => `
|
||||||
|
<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>${timeAndDate}</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>
|
||||||
|
`
|
||||||
@@ -1,26 +1,24 @@
|
|||||||
/* istanbul ignore file */
|
/* istanbul ignore file */
|
||||||
|
|
||||||
import { EmailMessageIdentifier, JSONString, ProtocolVersion, RoleName, Uuid } from '@standardnotes/common'
|
import { JSONString, ProtocolVersion, RoleName, Uuid } from '@standardnotes/common'
|
||||||
import {
|
import {
|
||||||
AccountDeletionRequestedEvent,
|
AccountDeletionRequestedEvent,
|
||||||
UserEmailChangedEvent,
|
UserEmailChangedEvent,
|
||||||
UserRegisteredEvent,
|
UserRegisteredEvent,
|
||||||
UserRolesChangedEvent,
|
UserRolesChangedEvent,
|
||||||
OfflineSubscriptionTokenCreatedEvent,
|
|
||||||
EmailBackupRequestedEvent,
|
EmailBackupRequestedEvent,
|
||||||
CloudBackupRequestedEvent,
|
CloudBackupRequestedEvent,
|
||||||
ListedAccountRequestedEvent,
|
ListedAccountRequestedEvent,
|
||||||
UserSignedInEvent,
|
|
||||||
UserDisabledSessionUserAgentLoggingEvent,
|
UserDisabledSessionUserAgentLoggingEvent,
|
||||||
SharedSubscriptionInvitationCreatedEvent,
|
SharedSubscriptionInvitationCreatedEvent,
|
||||||
SharedSubscriptionInvitationCanceledEvent,
|
SharedSubscriptionInvitationCanceledEvent,
|
||||||
PredicateVerifiedEvent,
|
PredicateVerifiedEvent,
|
||||||
DomainEventService,
|
DomainEventService,
|
||||||
EmailMessageRequestedEvent,
|
|
||||||
WebSocketMessageRequestedEvent,
|
WebSocketMessageRequestedEvent,
|
||||||
ExitDiscountApplyRequestedEvent,
|
ExitDiscountApplyRequestedEvent,
|
||||||
UserContentSizeRecalculationRequestedEvent,
|
UserContentSizeRecalculationRequestedEvent,
|
||||||
MuteEmailsSettingChangedEvent,
|
MuteEmailsSettingChangedEvent,
|
||||||
|
EmailRequestedEvent,
|
||||||
} from '@standardnotes/domain-events'
|
} from '@standardnotes/domain-events'
|
||||||
import { Predicate, PredicateVerificationResult } from '@standardnotes/predicates'
|
import { Predicate, PredicateVerificationResult } from '@standardnotes/predicates'
|
||||||
import { TimerInterface } from '@standardnotes/time'
|
import { TimerInterface } from '@standardnotes/time'
|
||||||
@@ -102,13 +100,15 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createEmailMessageRequestedEvent(dto: {
|
createEmailRequestedEvent(dto: {
|
||||||
userEmail: string
|
userEmail: string
|
||||||
messageIdentifier: EmailMessageIdentifier
|
messageIdentifier: string
|
||||||
context: Record<string, unknown>
|
level: string
|
||||||
}): EmailMessageRequestedEvent {
|
body: string
|
||||||
|
subject: string
|
||||||
|
}): EmailRequestedEvent {
|
||||||
return {
|
return {
|
||||||
type: 'EMAIL_MESSAGE_REQUESTED',
|
type: 'EMAIL_REQUESTED',
|
||||||
createdAt: this.timer.getUTCDate(),
|
createdAt: this.timer.getUTCDate(),
|
||||||
meta: {
|
meta: {
|
||||||
correlation: {
|
correlation: {
|
||||||
@@ -202,28 +202,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 {
|
createListedAccountRequestedEvent(userUuid: string, userEmail: string): ListedAccountRequestedEvent {
|
||||||
return {
|
return {
|
||||||
type: 'LISTED_ACCOUNT_REQUESTED',
|
type: 'LISTED_ACCOUNT_REQUESTED',
|
||||||
@@ -311,24 +289,6 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createOfflineSubscriptionTokenCreatedEvent(token: string, email: string): OfflineSubscriptionTokenCreatedEvent {
|
|
||||||
return {
|
|
||||||
type: 'OFFLINE_SUBSCRIPTION_TOKEN_CREATED',
|
|
||||||
createdAt: this.timer.getUTCDate(),
|
|
||||||
meta: {
|
|
||||||
correlation: {
|
|
||||||
userIdentifier: email,
|
|
||||||
userIdentifierType: 'email',
|
|
||||||
},
|
|
||||||
origin: DomainEventService.Auth,
|
|
||||||
},
|
|
||||||
payload: {
|
|
||||||
token,
|
|
||||||
email,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
createUserRegisteredEvent(dto: {
|
createUserRegisteredEvent(dto: {
|
||||||
userUuid: string
|
userUuid: string
|
||||||
email: string
|
email: string
|
||||||
|
|||||||
@@ -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 { Predicate, PredicateVerificationResult } from '@standardnotes/predicates'
|
||||||
import {
|
import {
|
||||||
AccountDeletionRequestedEvent,
|
AccountDeletionRequestedEvent,
|
||||||
@@ -6,38 +6,30 @@ import {
|
|||||||
UserRegisteredEvent,
|
UserRegisteredEvent,
|
||||||
UserRolesChangedEvent,
|
UserRolesChangedEvent,
|
||||||
UserEmailChangedEvent,
|
UserEmailChangedEvent,
|
||||||
OfflineSubscriptionTokenCreatedEvent,
|
|
||||||
EmailBackupRequestedEvent,
|
EmailBackupRequestedEvent,
|
||||||
ListedAccountRequestedEvent,
|
ListedAccountRequestedEvent,
|
||||||
UserSignedInEvent,
|
|
||||||
UserDisabledSessionUserAgentLoggingEvent,
|
UserDisabledSessionUserAgentLoggingEvent,
|
||||||
SharedSubscriptionInvitationCreatedEvent,
|
SharedSubscriptionInvitationCreatedEvent,
|
||||||
SharedSubscriptionInvitationCanceledEvent,
|
SharedSubscriptionInvitationCanceledEvent,
|
||||||
PredicateVerifiedEvent,
|
PredicateVerifiedEvent,
|
||||||
EmailMessageRequestedEvent,
|
|
||||||
WebSocketMessageRequestedEvent,
|
WebSocketMessageRequestedEvent,
|
||||||
ExitDiscountApplyRequestedEvent,
|
ExitDiscountApplyRequestedEvent,
|
||||||
UserContentSizeRecalculationRequestedEvent,
|
UserContentSizeRecalculationRequestedEvent,
|
||||||
MuteEmailsSettingChangedEvent,
|
MuteEmailsSettingChangedEvent,
|
||||||
|
EmailRequestedEvent,
|
||||||
} from '@standardnotes/domain-events'
|
} from '@standardnotes/domain-events'
|
||||||
import { InviteeIdentifierType } from '../SharedSubscription/InviteeIdentifierType'
|
import { InviteeIdentifierType } from '../SharedSubscription/InviteeIdentifierType'
|
||||||
|
|
||||||
export interface DomainEventFactoryInterface {
|
export interface DomainEventFactoryInterface {
|
||||||
createUserContentSizeRecalculationRequestedEvent(userUuid: string): UserContentSizeRecalculationRequestedEvent
|
createUserContentSizeRecalculationRequestedEvent(userUuid: string): UserContentSizeRecalculationRequestedEvent
|
||||||
createWebSocketMessageRequestedEvent(dto: { userUuid: Uuid; message: JSONString }): WebSocketMessageRequestedEvent
|
createWebSocketMessageRequestedEvent(dto: { userUuid: Uuid; message: JSONString }): WebSocketMessageRequestedEvent
|
||||||
createEmailMessageRequestedEvent(dto: {
|
createEmailRequestedEvent(dto: {
|
||||||
userEmail: string
|
userEmail: string
|
||||||
messageIdentifier: EmailMessageIdentifier
|
messageIdentifier: string
|
||||||
context: Record<string, unknown>
|
level: string
|
||||||
}): EmailMessageRequestedEvent
|
body: string
|
||||||
createUserSignedInEvent(dto: {
|
subject: string
|
||||||
userUuid: string
|
}): EmailRequestedEvent
|
||||||
userEmail: string
|
|
||||||
device: string
|
|
||||||
browser: string
|
|
||||||
signInAlertEnabled: boolean
|
|
||||||
muteSignInEmailsSettingUuid: Uuid
|
|
||||||
}): UserSignedInEvent
|
|
||||||
createListedAccountRequestedEvent(userUuid: string, userEmail: string): ListedAccountRequestedEvent
|
createListedAccountRequestedEvent(userUuid: string, userEmail: string): ListedAccountRequestedEvent
|
||||||
createUserRegisteredEvent(dto: {
|
createUserRegisteredEvent(dto: {
|
||||||
userUuid: string
|
userUuid: string
|
||||||
@@ -63,7 +55,6 @@ export interface DomainEventFactoryInterface {
|
|||||||
}): AccountDeletionRequestedEvent
|
}): AccountDeletionRequestedEvent
|
||||||
createUserRolesChangedEvent(userUuid: string, email: string, currentRoles: RoleName[]): UserRolesChangedEvent
|
createUserRolesChangedEvent(userUuid: string, email: string, currentRoles: RoleName[]): UserRolesChangedEvent
|
||||||
createUserEmailChangedEvent(userUuid: string, fromEmail: string, toEmail: string): UserEmailChangedEvent
|
createUserEmailChangedEvent(userUuid: string, fromEmail: string, toEmail: string): UserEmailChangedEvent
|
||||||
createOfflineSubscriptionTokenCreatedEvent(token: string, email: string): OfflineSubscriptionTokenCreatedEvent
|
|
||||||
createUserDisabledSessionUserAgentLoggingEvent(dto: {
|
createUserDisabledSessionUserAgentLoggingEvent(dto: {
|
||||||
userUuid: Uuid
|
userUuid: Uuid
|
||||||
email: string
|
email: string
|
||||||
|
|||||||
+7
-10
@@ -5,7 +5,7 @@ import { TimerInterface } from '@standardnotes/time'
|
|||||||
import { OfflineSubscriptionTokenRepositoryInterface } from '../../Auth/OfflineSubscriptionTokenRepositoryInterface'
|
import { OfflineSubscriptionTokenRepositoryInterface } from '../../Auth/OfflineSubscriptionTokenRepositoryInterface'
|
||||||
|
|
||||||
import { CreateOfflineSubscriptionToken } from './CreateOfflineSubscriptionToken'
|
import { CreateOfflineSubscriptionToken } from './CreateOfflineSubscriptionToken'
|
||||||
import { DomainEventPublisherInterface, OfflineSubscriptionTokenCreatedEvent } from '@standardnotes/domain-events'
|
import { DomainEventPublisherInterface, EmailRequestedEvent } from '@standardnotes/domain-events'
|
||||||
import { DomainEventFactoryInterface } from '../../Event/DomainEventFactoryInterface'
|
import { DomainEventFactoryInterface } from '../../Event/DomainEventFactoryInterface'
|
||||||
import { OfflineUserSubscriptionRepositoryInterface } from '../../Subscription/OfflineUserSubscriptionRepositoryInterface'
|
import { OfflineUserSubscriptionRepositoryInterface } from '../../Subscription/OfflineUserSubscriptionRepositoryInterface'
|
||||||
import { OfflineUserSubscription } from '../../Subscription/OfflineUserSubscription'
|
import { OfflineUserSubscription } from '../../Subscription/OfflineUserSubscription'
|
||||||
@@ -47,9 +47,9 @@ describe('CreateOfflineSubscriptionToken', () => {
|
|||||||
domainEventPublisher.publish = jest.fn()
|
domainEventPublisher.publish = jest.fn()
|
||||||
|
|
||||||
domainEventFactory = {} as jest.Mocked<DomainEventFactoryInterface>
|
domainEventFactory = {} as jest.Mocked<DomainEventFactoryInterface>
|
||||||
domainEventFactory.createOfflineSubscriptionTokenCreatedEvent = jest
|
domainEventFactory.createEmailRequestedEvent = jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockReturnValue({} as jest.Mocked<OfflineSubscriptionTokenCreatedEvent>)
|
.mockReturnValue({} as jest.Mocked<EmailRequestedEvent>)
|
||||||
|
|
||||||
timer = {} as jest.Mocked<TimerInterface>
|
timer = {} as jest.Mocked<TimerInterface>
|
||||||
timer.convertStringDateToMicroseconds = jest.fn().mockReturnValue(1)
|
timer.convertStringDateToMicroseconds = jest.fn().mockReturnValue(1)
|
||||||
@@ -71,10 +71,7 @@ describe('CreateOfflineSubscriptionToken', () => {
|
|||||||
expiresAt: 1,
|
expiresAt: 1,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(domainEventFactory.createOfflineSubscriptionTokenCreatedEvent).toHaveBeenCalledWith(
|
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
|
||||||
'random-string',
|
|
||||||
'test@test.com',
|
|
||||||
)
|
|
||||||
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -91,7 +88,7 @@ describe('CreateOfflineSubscriptionToken', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
expect(offlineSubscriptionTokenRepository.save).not.toHaveBeenCalled()
|
expect(offlineSubscriptionTokenRepository.save).not.toHaveBeenCalled()
|
||||||
expect(domainEventFactory.createOfflineSubscriptionTokenCreatedEvent).not.toHaveBeenCalled()
|
expect(domainEventFactory.createEmailRequestedEvent).not.toHaveBeenCalled()
|
||||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -110,7 +107,7 @@ describe('CreateOfflineSubscriptionToken', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
expect(offlineSubscriptionTokenRepository.save).not.toHaveBeenCalled()
|
expect(offlineSubscriptionTokenRepository.save).not.toHaveBeenCalled()
|
||||||
expect(domainEventFactory.createOfflineSubscriptionTokenCreatedEvent).not.toHaveBeenCalled()
|
expect(domainEventFactory.createEmailRequestedEvent).not.toHaveBeenCalled()
|
||||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -129,7 +126,7 @@ describe('CreateOfflineSubscriptionToken', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
expect(offlineSubscriptionTokenRepository.save).not.toHaveBeenCalled()
|
expect(offlineSubscriptionTokenRepository.save).not.toHaveBeenCalled()
|
||||||
expect(domainEventFactory.createOfflineSubscriptionTokenCreatedEvent).not.toHaveBeenCalled()
|
expect(domainEventFactory.createEmailRequestedEvent).not.toHaveBeenCalled()
|
||||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
+9
-1
@@ -1,4 +1,5 @@
|
|||||||
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
||||||
|
import { EmailLevel } from '@standardnotes/domain-core'
|
||||||
import { CryptoNode } from '@standardnotes/sncrypto-node'
|
import { CryptoNode } from '@standardnotes/sncrypto-node'
|
||||||
import { TimerInterface } from '@standardnotes/time'
|
import { TimerInterface } from '@standardnotes/time'
|
||||||
import { inject, injectable } from 'inversify'
|
import { inject, injectable } from 'inversify'
|
||||||
@@ -6,6 +7,7 @@ import { Logger } from 'winston'
|
|||||||
|
|
||||||
import TYPES from '../../../Bootstrap/Types'
|
import TYPES from '../../../Bootstrap/Types'
|
||||||
import { OfflineSubscriptionTokenRepositoryInterface } from '../../Auth/OfflineSubscriptionTokenRepositoryInterface'
|
import { OfflineSubscriptionTokenRepositoryInterface } from '../../Auth/OfflineSubscriptionTokenRepositoryInterface'
|
||||||
|
import { getBody, getSubject } from '../../Email/OfflineSubscriptionTokenCreated'
|
||||||
import { DomainEventFactoryInterface } from '../../Event/DomainEventFactoryInterface'
|
import { DomainEventFactoryInterface } from '../../Event/DomainEventFactoryInterface'
|
||||||
import { OfflineUserSubscriptionRepositoryInterface } from '../../Subscription/OfflineUserSubscriptionRepositoryInterface'
|
import { OfflineUserSubscriptionRepositoryInterface } from '../../Subscription/OfflineUserSubscriptionRepositoryInterface'
|
||||||
import { UseCaseInterface } from '../UseCaseInterface'
|
import { UseCaseInterface } from '../UseCaseInterface'
|
||||||
@@ -62,7 +64,13 @@ export class CreateOfflineSubscriptionToken implements UseCaseInterface {
|
|||||||
await this.offlineSubscriptionTokenRepository.save(offlineSubscriptionToken)
|
await this.offlineSubscriptionTokenRepository.save(offlineSubscriptionToken)
|
||||||
|
|
||||||
await this.domainEventPublisher.publish(
|
await this.domainEventPublisher.publish(
|
||||||
this.domainEventFactory.createOfflineSubscriptionTokenCreatedEvent(token, dto.userEmail),
|
this.domainEventFactory.createEmailRequestedEvent({
|
||||||
|
body: getBody(dto.userEmail, `https://standardnotes.com/dashboard/offline?subscription_token=${token}`),
|
||||||
|
level: EmailLevel.LEVELS.System,
|
||||||
|
subject: getSubject(),
|
||||||
|
messageIdentifier: 'OFFLINE_SUBSCRIPTION_ACCESS',
|
||||||
|
userEmail: dto.userEmail,
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
+6
-1
@@ -1,6 +1,10 @@
|
|||||||
import 'reflect-metadata'
|
import 'reflect-metadata'
|
||||||
|
|
||||||
import { DomainEventPublisherInterface, SharedSubscriptionInvitationCreatedEvent } from '@standardnotes/domain-events'
|
import {
|
||||||
|
DomainEventPublisherInterface,
|
||||||
|
SharedSubscriptionInvitationCreatedEvent,
|
||||||
|
EmailRequestedEvent,
|
||||||
|
} from '@standardnotes/domain-events'
|
||||||
import { TimerInterface } from '@standardnotes/time'
|
import { TimerInterface } from '@standardnotes/time'
|
||||||
import { DomainEventFactoryInterface } from '../../Event/DomainEventFactoryInterface'
|
import { DomainEventFactoryInterface } from '../../Event/DomainEventFactoryInterface'
|
||||||
import { SharedSubscriptionInvitationRepositoryInterface } from '../../SharedSubscription/SharedSubscriptionInvitationRepositoryInterface'
|
import { SharedSubscriptionInvitationRepositoryInterface } from '../../SharedSubscription/SharedSubscriptionInvitationRepositoryInterface'
|
||||||
@@ -51,6 +55,7 @@ describe('InviteToSharedSubscription', () => {
|
|||||||
domainEventFactory.createSharedSubscriptionInvitationCreatedEvent = jest
|
domainEventFactory.createSharedSubscriptionInvitationCreatedEvent = jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockReturnValue({} as jest.Mocked<SharedSubscriptionInvitationCreatedEvent>)
|
.mockReturnValue({} as jest.Mocked<SharedSubscriptionInvitationCreatedEvent>)
|
||||||
|
domainEventFactory.createEmailRequestedEvent = jest.fn().mockReturnValue({} as jest.Mocked<EmailRequestedEvent>)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not create an inivitation for sharing the subscription if inviter has no subscription', async () => {
|
it('should not create an inivitation for sharing the subscription if inviter has no subscription', async () => {
|
||||||
|
|||||||
+12
@@ -1,9 +1,11 @@
|
|||||||
import { RoleName } from '@standardnotes/common'
|
import { RoleName } from '@standardnotes/common'
|
||||||
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
||||||
|
import { EmailLevel } from '@standardnotes/domain-core'
|
||||||
import { TimerInterface } from '@standardnotes/time'
|
import { TimerInterface } from '@standardnotes/time'
|
||||||
import { inject, injectable } from 'inversify'
|
import { inject, injectable } from 'inversify'
|
||||||
|
|
||||||
import TYPES from '../../../Bootstrap/Types'
|
import TYPES from '../../../Bootstrap/Types'
|
||||||
|
import { getBody, getSubject } from '../../Email/SharedSubscriptionInvitationCreated'
|
||||||
import { DomainEventFactoryInterface } from '../../Event/DomainEventFactoryInterface'
|
import { DomainEventFactoryInterface } from '../../Event/DomainEventFactoryInterface'
|
||||||
import { InvitationStatus } from '../../SharedSubscription/InvitationStatus'
|
import { InvitationStatus } from '../../SharedSubscription/InvitationStatus'
|
||||||
import { InviteeIdentifierType } from '../../SharedSubscription/InviteeIdentifierType'
|
import { InviteeIdentifierType } from '../../SharedSubscription/InviteeIdentifierType'
|
||||||
@@ -89,6 +91,16 @@ export class InviteToSharedSubscription implements UseCaseInterface {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
await this.domainEventPublisher.publish(
|
||||||
|
this.domainEventFactory.createEmailRequestedEvent({
|
||||||
|
userEmail: dto.inviteeIdentifier,
|
||||||
|
level: EmailLevel.LEVELS.System,
|
||||||
|
body: getBody(dto.inviterEmail, savedInvitation.uuid),
|
||||||
|
messageIdentifier: 'SHARED_SUBSCRIPTION_INVITATION',
|
||||||
|
subject: getSubject(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
sharedSubscriptionInvitationUuid: savedInvitation.uuid,
|
sharedSubscriptionInvitationUuid: savedInvitation.uuid,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import 'reflect-metadata'
|
import 'reflect-metadata'
|
||||||
|
|
||||||
import { DomainEventPublisherInterface, UserSignedInEvent } from '@standardnotes/domain-events'
|
import { DomainEventPublisherInterface, EmailRequestedEvent } from '@standardnotes/domain-events'
|
||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
|
|
||||||
import { AuthResponseFactoryInterface } from '../Auth/AuthResponseFactoryInterface'
|
import { AuthResponseFactoryInterface } from '../Auth/AuthResponseFactoryInterface'
|
||||||
@@ -10,10 +10,6 @@ import { SessionServiceInterface } from '../Session/SessionServiceInterface'
|
|||||||
import { User } from '../User/User'
|
import { User } from '../User/User'
|
||||||
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
|
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
|
||||||
import { SignIn } from './SignIn'
|
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 { PKCERepositoryInterface } from '../User/PKCERepositoryInterface'
|
||||||
import { CrypterInterface } from '../Encryption/CrypterInterface'
|
import { CrypterInterface } from '../Encryption/CrypterInterface'
|
||||||
import { ProtocolVersion } from '@standardnotes/common'
|
import { ProtocolVersion } from '@standardnotes/common'
|
||||||
@@ -26,10 +22,7 @@ describe('SignIn', () => {
|
|||||||
let domainEventPublisher: DomainEventPublisherInterface
|
let domainEventPublisher: DomainEventPublisherInterface
|
||||||
let domainEventFactory: DomainEventFactoryInterface
|
let domainEventFactory: DomainEventFactoryInterface
|
||||||
let sessionService: SessionServiceInterface
|
let sessionService: SessionServiceInterface
|
||||||
let roleService: RoleServiceInterface
|
|
||||||
let logger: Logger
|
let logger: Logger
|
||||||
let settingService: SettingServiceInterface
|
|
||||||
let setting: Setting
|
|
||||||
let pkceRepository: PKCERepositoryInterface
|
let pkceRepository: PKCERepositoryInterface
|
||||||
let crypter: CrypterInterface
|
let crypter: CrypterInterface
|
||||||
|
|
||||||
@@ -40,8 +33,6 @@ describe('SignIn', () => {
|
|||||||
domainEventPublisher,
|
domainEventPublisher,
|
||||||
domainEventFactory,
|
domainEventFactory,
|
||||||
sessionService,
|
sessionService,
|
||||||
roleService,
|
|
||||||
settingService,
|
|
||||||
pkceRepository,
|
pkceRepository,
|
||||||
crypter,
|
crypter,
|
||||||
logger,
|
logger,
|
||||||
@@ -68,27 +59,12 @@ describe('SignIn', () => {
|
|||||||
domainEventPublisher.publish = jest.fn()
|
domainEventPublisher.publish = jest.fn()
|
||||||
|
|
||||||
domainEventFactory = {} as jest.Mocked<DomainEventFactoryInterface>
|
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 = {} as jest.Mocked<SessionServiceInterface>
|
||||||
sessionService.getOperatingSystemInfoFromUserAgent = jest.fn().mockReturnValue('iOS 1')
|
sessionService.getOperatingSystemInfoFromUserAgent = jest.fn().mockReturnValue('iOS 1')
|
||||||
sessionService.getBrowserInfoFromUserAgent = jest.fn().mockReturnValue('Firefox 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 = {} as jest.Mocked<PKCERepositoryInterface>
|
||||||
pkceRepository.removeCodeChallenge = jest.fn().mockReturnValue(true)
|
pkceRepository.removeCodeChallenge = jest.fn().mockReturnValue(true)
|
||||||
|
|
||||||
@@ -118,18 +94,33 @@ describe('SignIn', () => {
|
|||||||
authResponse: { foo: 'bar' },
|
authResponse: { foo: 'bar' },
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(domainEventFactory.createUserSignedInEvent).toHaveBeenCalledWith({
|
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
|
||||||
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(domainEventPublisher.publish).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not sign in a user without code verifier', async () => {
|
it('should not sign in 004 user without code verifier', async () => {
|
||||||
|
expect(
|
||||||
|
await createUseCase().execute({
|
||||||
|
email: 'test@test.te',
|
||||||
|
password: 'qweqwe123123',
|
||||||
|
userAgent: 'Google Chrome',
|
||||||
|
apiVersion: '20190520',
|
||||||
|
ephemeralSession: false,
|
||||||
|
}),
|
||||||
|
).toEqual({
|
||||||
|
success: false,
|
||||||
|
errorCode: 410,
|
||||||
|
errorMessage: 'Please update your client application.',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not sign in 005 user without code verifier', async () => {
|
||||||
|
user = {
|
||||||
|
uuid: '1-2-3',
|
||||||
|
email: 'test@test.com',
|
||||||
|
version: '005',
|
||||||
|
} as jest.Mocked<User>
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await createUseCase().execute({
|
await createUseCase().execute({
|
||||||
email: 'test@test.te',
|
email: 'test@test.te',
|
||||||
@@ -160,92 +151,10 @@ describe('SignIn', () => {
|
|||||||
authResponse: { foo: 'bar' },
|
authResponse: { foo: 'bar' },
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(domainEventFactory.createUserSignedInEvent).toHaveBeenCalledWith({
|
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
|
||||||
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(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(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 () => {
|
it('should sign in a user even if publishing a sign in event fails', async () => {
|
||||||
domainEventPublisher.publish = jest.fn().mockImplementation(() => {
|
domainEventPublisher.publish = jest.fn().mockImplementation(() => {
|
||||||
throw new Error('Oops')
|
throw new Error('Oops')
|
||||||
|
|||||||
@@ -1,18 +1,12 @@
|
|||||||
import * as bcrypt from 'bcryptjs'
|
import * as bcrypt from 'bcryptjs'
|
||||||
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
||||||
import { PermissionName } from '@standardnotes/features'
|
|
||||||
import { MuteSignInEmailsOption, SettingName } from '@standardnotes/settings'
|
|
||||||
|
|
||||||
import { inject, injectable } from 'inversify'
|
import { inject, injectable } from 'inversify'
|
||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
import TYPES from '../../Bootstrap/Types'
|
import TYPES from '../../Bootstrap/Types'
|
||||||
import { AuthResponseFactoryResolverInterface } from '../Auth/AuthResponseFactoryResolverInterface'
|
import { AuthResponseFactoryResolverInterface } from '../Auth/AuthResponseFactoryResolverInterface'
|
||||||
import { EncryptionVersion } from '../Encryption/EncryptionVersion'
|
|
||||||
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
|
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
|
||||||
import { RoleServiceInterface } from '../Role/RoleServiceInterface'
|
|
||||||
import { SessionServiceInterface } from '../Session/SessionServiceInterface'
|
import { SessionServiceInterface } from '../Session/SessionServiceInterface'
|
||||||
import { Setting } from '../Setting/Setting'
|
|
||||||
import { SettingServiceInterface } from '../Setting/SettingServiceInterface'
|
|
||||||
import { User } from '../User/User'
|
import { User } from '../User/User'
|
||||||
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
|
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
|
||||||
import { SignInDTO } from './SignInDTO'
|
import { SignInDTO } from './SignInDTO'
|
||||||
@@ -21,8 +15,10 @@ import { UseCaseInterface } from './UseCaseInterface'
|
|||||||
import { PKCERepositoryInterface } from '../User/PKCERepositoryInterface'
|
import { PKCERepositoryInterface } from '../User/PKCERepositoryInterface'
|
||||||
import { CrypterInterface } from '../Encryption/CrypterInterface'
|
import { CrypterInterface } from '../Encryption/CrypterInterface'
|
||||||
import { SignInDTOV2Challenged } from './SignInDTOV2Challenged'
|
import { SignInDTOV2Challenged } from './SignInDTOV2Challenged'
|
||||||
import { ProtocolVersion } from '@standardnotes/common'
|
import { leftVersionGreaterThanOrEqualToRight, ProtocolVersion } from '@standardnotes/common'
|
||||||
import { HttpStatusCode } from '@standardnotes/api'
|
import { HttpStatusCode } from '@standardnotes/api'
|
||||||
|
import { EmailLevel } from '@standardnotes/domain-core'
|
||||||
|
import { getBody, getSubject } from '../Email/UserSignedIn'
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class SignIn implements UseCaseInterface {
|
export class SignIn implements UseCaseInterface {
|
||||||
@@ -33,8 +29,6 @@ export class SignIn implements UseCaseInterface {
|
|||||||
@inject(TYPES.DomainEventPublisher) private domainEventPublisher: DomainEventPublisherInterface,
|
@inject(TYPES.DomainEventPublisher) private domainEventPublisher: DomainEventPublisherInterface,
|
||||||
@inject(TYPES.DomainEventFactory) private domainEventFactory: DomainEventFactoryInterface,
|
@inject(TYPES.DomainEventFactory) private domainEventFactory: DomainEventFactoryInterface,
|
||||||
@inject(TYPES.SessionService) private sessionService: SessionServiceInterface,
|
@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.PKCERepository) private pkceRepository: PKCERepositoryInterface,
|
||||||
@inject(TYPES.Crypter) private crypter: CrypterInterface,
|
@inject(TYPES.Crypter) private crypter: CrypterInterface,
|
||||||
@inject(TYPES.Logger) private logger: Logger,
|
@inject(TYPES.Logger) private logger: Logger,
|
||||||
@@ -65,7 +59,12 @@ export class SignIn implements UseCaseInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user.version === ProtocolVersion.V004 && !performingCodeChallengedSignIn) {
|
const userVersionIs004OrGreater = leftVersionGreaterThanOrEqualToRight(
|
||||||
|
user.version as ProtocolVersion,
|
||||||
|
ProtocolVersion.V004,
|
||||||
|
)
|
||||||
|
|
||||||
|
if (userVersionIs004OrGreater && !performingCodeChallengedSignIn) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
errorMessage: 'Please update your client application.',
|
errorMessage: 'Please update your client application.',
|
||||||
@@ -109,18 +108,18 @@ export class SignIn implements UseCaseInterface {
|
|||||||
|
|
||||||
private async sendSignInEmailNotification(user: User, userAgent: string): Promise<void> {
|
private async sendSignInEmailNotification(user: User, userAgent: string): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const muteSignInEmailsSetting = await this.findOrCreateMuteSignInEmailsSetting(user)
|
|
||||||
|
|
||||||
await this.domainEventPublisher.publish(
|
await this.domainEventPublisher.publish(
|
||||||
this.domainEventFactory.createUserSignedInEvent({
|
this.domainEventFactory.createEmailRequestedEvent({
|
||||||
userUuid: user.uuid,
|
|
||||||
userEmail: user.email,
|
userEmail: user.email,
|
||||||
device: this.sessionService.getOperatingSystemInfoFromUserAgent(userAgent),
|
level: EmailLevel.LEVELS.SignIn,
|
||||||
browser: this.sessionService.getBrowserInfoFromUserAgent(userAgent),
|
body: getBody(
|
||||||
signInAlertEnabled:
|
user.email,
|
||||||
(await this.roleService.userHasPermission(user.uuid, PermissionName.SignInAlerts)) &&
|
this.sessionService.getOperatingSystemInfoFromUserAgent(userAgent),
|
||||||
muteSignInEmailsSetting.value === MuteSignInEmailsOption.NotMuted,
|
this.sessionService.getBrowserInfoFromUserAgent(userAgent),
|
||||||
muteSignInEmailsSettingUuid: muteSignInEmailsSetting.uuid,
|
new Date(),
|
||||||
|
),
|
||||||
|
messageIdentifier: 'SIGN_IN',
|
||||||
|
subject: getSubject(user.email),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -128,29 +127,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 {
|
private isCodeChallengedVersion(dto: SignInDTO): dto is SignInDTOV2Challenged {
|
||||||
return (dto as SignInDTOV2Challenged).codeVerifier !== undefined
|
return (dto as SignInDTOV2Challenged).codeVerifier !== undefined
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,50 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.9.51](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.50...@standardnotes/domain-events-infra@1.9.51) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||||
|
|
||||||
|
## [1.9.50](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.49...@standardnotes/domain-events-infra@1.9.50) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||||
|
|
||||||
|
## [1.9.49](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.48...@standardnotes/domain-events-infra@1.9.49) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||||
|
|
||||||
|
## [1.9.48](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.47...@standardnotes/domain-events-infra@1.9.48) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||||
|
|
||||||
|
## [1.9.47](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.46...@standardnotes/domain-events-infra@1.9.47) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||||
|
|
||||||
|
## [1.9.46](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.45...@standardnotes/domain-events-infra@1.9.46) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||||
|
|
||||||
|
## [1.9.45](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.44...@standardnotes/domain-events-infra@1.9.45) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||||
|
|
||||||
|
## [1.9.44](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.43...@standardnotes/domain-events-infra@1.9.44) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||||
|
|
||||||
|
## [1.9.43](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.42...@standardnotes/domain-events-infra@1.9.43) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||||
|
|
||||||
|
## [1.9.42](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.41...@standardnotes/domain-events-infra@1.9.42) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||||
|
|
||||||
|
## [1.9.41](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.40...@standardnotes/domain-events-infra@1.9.41) (2022-12-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||||
|
|
||||||
## [1.9.40](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.39...@standardnotes/domain-events-infra@1.9.40) (2022-12-07)
|
## [1.9.40](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.39...@standardnotes/domain-events-infra@1.9.40) (2022-12-07)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/domain-events-infra",
|
"name": "@standardnotes/domain-events-infra",
|
||||||
"version": "1.9.40",
|
"version": "1.9.51",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <19.0.0"
|
"node": ">=18.0.0 <19.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,72 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [2.102.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.101.0...@standardnotes/domain-events@2.102.0) (2022-12-09)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **syncing-server:** replace email backup attachment created with email requested ([32601f3](https://github.com/standardnotes/server/commit/32601f34f181b29b7c62cd2926111a0887d97fbf))
|
||||||
|
|
||||||
|
# [2.101.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.100.0...@standardnotes/domain-events@2.101.0) (2022-12-09)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **syncing-server:** replace one drive backup failed event with email requested ([130f90b](https://github.com/standardnotes/server/commit/130f90bdb6cc88e073b9380e8aed5eebe8c49c1e))
|
||||||
|
|
||||||
|
# [2.100.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.99.0...@standardnotes/domain-events@2.100.0) (2022-12-09)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **syncing-server:** remove google drive backup failed event in favour of email requested ([00fe321](https://github.com/standardnotes/server/commit/00fe32136e7add627e58e8ea223f7f484f1d3718))
|
||||||
|
|
||||||
|
# [2.99.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.98.4...@standardnotes/domain-events@2.99.0) (2022-12-09)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **auth:** remove offline subscription token created event in favour of email requested ([fd58992](https://github.com/standardnotes/server/commit/fd589922bba29595a0dfd154a42fe158024fad28))
|
||||||
|
|
||||||
|
## [2.98.4](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.98.3...@standardnotes/domain-events@2.98.4) (2022-12-09)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **domain-events:** remove unused event ([cc4b4f9](https://github.com/standardnotes/server/commit/cc4b4f9bf831b9aabec7d506d977ee1df50d5222))
|
||||||
|
|
||||||
|
## [2.98.3](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.98.2...@standardnotes/domain-events@2.98.3) (2022-12-08)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **domain-events:** remove unused event ([cffc1f4](https://github.com/standardnotes/server/commit/cffc1f442f3c6f781c4468ac96245e13f57115d5))
|
||||||
|
|
||||||
|
## [2.98.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.98.1...@standardnotes/domain-events@2.98.2) (2022-12-08)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **domain-events:** remove unused event ([5a1eb9f](https://github.com/standardnotes/server/commit/5a1eb9fdacb8cfe8fde06df9e83fef1753b1a619))
|
||||||
|
|
||||||
|
## [2.98.1](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.98.0...@standardnotes/domain-events@2.98.1) (2022-12-08)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **domain-events:** remove unused event ([47d2012](https://github.com/standardnotes/server/commit/47d2012b3d96eddf5f6304f158659dc764f9b1c4))
|
||||||
|
|
||||||
|
# [2.98.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.97.0...@standardnotes/domain-events@2.98.0) (2022-12-08)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **domain-events:** remove unused events and add attachments option for sending emails ([435cd2f](https://github.com/standardnotes/server/commit/435cd2f66a1332a294001e87eed3ece1b8b991ae))
|
||||||
|
|
||||||
|
# [2.97.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.96.0...@standardnotes/domain-events@2.97.0) (2022-12-08)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **domain-events:** remove unused account reset requested event ([3a12f5c](https://github.com/standardnotes/server/commit/3a12f5c1c40ab6cb236b963bad2a987bacef55e4))
|
||||||
|
|
||||||
|
# [2.96.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.95.0...@standardnotes/domain-events@2.96.0) (2022-12-07)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **auth:** replace user signed in events with email requested ([e48cca6](https://github.com/standardnotes/server/commit/e48cca6b45b02876f2d82b726c1d2f124d90b587))
|
||||||
|
|
||||||
# [2.95.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.94.1...@standardnotes/domain-events@2.95.0) (2022-12-07)
|
# [2.95.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.94.1...@standardnotes/domain-events@2.95.0) (2022-12-07)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/domain-events",
|
"name": "@standardnotes/domain-events",
|
||||||
"version": "2.95.0",
|
"version": "2.102.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <19.0.0"
|
"node": ">=18.0.0 <19.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
import { DomainEventInterface } from './DomainEventInterface'
|
|
||||||
import { AccountClaimRequestedEventPayload } from './AccountClaimRequestedEventPayload'
|
|
||||||
|
|
||||||
export interface AccountClaimRequestedEvent extends DomainEventInterface {
|
|
||||||
type: 'ACCOUNT_CLAIM_REQUESTED'
|
|
||||||
payload: AccountClaimRequestedEventPayload
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
export interface AccountClaimRequestedEventPayload {
|
|
||||||
email: string
|
|
||||||
token: string
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import { DomainEventInterface } from './DomainEventInterface'
|
|
||||||
|
|
||||||
import { AccountResetRequestedEventPayload } from './AccountResetRequestedEventPayload'
|
|
||||||
|
|
||||||
export interface AccountResetRequestedEvent extends DomainEventInterface {
|
|
||||||
type: 'ACCOUNT_RESET_REQUESTED'
|
|
||||||
payload: AccountResetRequestedEventPayload
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
export interface AccountResetRequestedEventPayload {
|
|
||||||
resetRequestToken: string
|
|
||||||
userEmail: string
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { DomainEventInterface } from './DomainEventInterface'
|
|
||||||
import { ActivationCodeRequestedEventPayload } from './ActivationCodeRequestedEventPayload'
|
|
||||||
|
|
||||||
export interface ActivationCodeRequestedEvent extends DomainEventInterface {
|
|
||||||
type: 'ACTIVATION_CODE_REQUESTED'
|
|
||||||
payload: ActivationCodeRequestedEventPayload
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
export interface ActivationCodeRequestedEventPayload {
|
|
||||||
userEmail: string
|
|
||||||
offlineFeaturesToken: string
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import { DomainEventInterface } from './DomainEventInterface'
|
|
||||||
|
|
||||||
import { DiscountAppliedEventPayload } from './DiscountAppliedEventPayload'
|
|
||||||
|
|
||||||
export interface DiscountAppliedEvent extends DomainEventInterface {
|
|
||||||
type: 'DISCOUNT_APPLIED'
|
|
||||||
payload: DiscountAppliedEventPayload
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
export interface DiscountAppliedEventPayload {
|
|
||||||
userEmail: string
|
|
||||||
discountRate: number
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import { DomainEventInterface } from './DomainEventInterface'
|
|
||||||
|
|
||||||
import { DropboxBackupFailedEventPayload } from './DropboxBackupFailedEventPayload'
|
|
||||||
|
|
||||||
export interface DropboxBackupFailedEvent extends DomainEventInterface {
|
|
||||||
type: 'DROPBOX_BACKUP_FAILED'
|
|
||||||
payload: DropboxBackupFailedEventPayload
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
export interface DropboxBackupFailedEventPayload {
|
|
||||||
muteCloudEmailsSettingUuid: string
|
|
||||||
extensionSettingUuid?: string
|
|
||||||
email: string
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { DomainEventInterface } from './DomainEventInterface'
|
|
||||||
import { EmailBackupAttachmentCreatedEventPayload } from './EmailBackupAttachmentCreatedEventPayload'
|
|
||||||
|
|
||||||
export interface EmailBackupAttachmentCreatedEvent extends DomainEventInterface {
|
|
||||||
type: 'EMAIL_BACKUP_ATTACHMENT_CREATED'
|
|
||||||
payload: EmailBackupAttachmentCreatedEventPayload
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
export interface EmailBackupAttachmentCreatedEventPayload {
|
|
||||||
backupFileName: string
|
|
||||||
backupFileIndex: number
|
|
||||||
backupFilesTotal: number
|
|
||||||
email: string
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { DomainEventInterface } from './DomainEventInterface'
|
|
||||||
import { EmailMessageRequestedEventPayload } from './EmailMessageRequestedEventPayload'
|
|
||||||
|
|
||||||
export interface EmailMessageRequestedEvent extends DomainEventInterface {
|
|
||||||
type: 'EMAIL_MESSAGE_REQUESTED'
|
|
||||||
payload: EmailMessageRequestedEventPayload
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
export interface EmailMessageRequestedEventPayload {
|
|
||||||
userEmail: string
|
|
||||||
messageIdentifier: string
|
|
||||||
context: Record<string, unknown>
|
|
||||||
}
|
|
||||||
@@ -4,4 +4,11 @@ export interface EmailRequestedEventPayload {
|
|||||||
level: string
|
level: string
|
||||||
subject: string
|
subject: string
|
||||||
body: string
|
body: string
|
||||||
|
sender?: string
|
||||||
|
attachments?: Array<{
|
||||||
|
filePath: string
|
||||||
|
fileName: string
|
||||||
|
attachmentFileName: string
|
||||||
|
attachmentContentType: string
|
||||||
|
}>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
import { DomainEventInterface } from './DomainEventInterface'
|
|
||||||
|
|
||||||
import { GoogleDriveBackupFailedEventPayload } from './GoogleDriveBackupFailedEventPayload'
|
|
||||||
|
|
||||||
export interface GoogleDriveBackupFailedEvent extends DomainEventInterface {
|
|
||||||
type: 'GOOGLE_DRIVE_BACKUP_FAILED'
|
|
||||||
payload: GoogleDriveBackupFailedEventPayload
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
export interface GoogleDriveBackupFailedEventPayload {
|
|
||||||
muteCloudEmailsSettingUuid: string
|
|
||||||
extensionSettingUuid?: string
|
|
||||||
email: string
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import { DomainEventInterface } from './DomainEventInterface'
|
|
||||||
|
|
||||||
import { InvoiceGeneratedEventPayload } from './InvoiceGeneratedEventPayload'
|
|
||||||
|
|
||||||
export interface InvoiceGeneratedEvent extends DomainEventInterface {
|
|
||||||
type: 'INVOICE_GENERATED'
|
|
||||||
payload: InvoiceGeneratedEventPayload
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
export interface InvoiceGeneratedEventPayload {
|
|
||||||
userEmail: string
|
|
||||||
invoiceNumber: string
|
|
||||||
paymentDateFormatted: string
|
|
||||||
s3BucketName: string
|
|
||||||
s3InvoiceObjectKey: string
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import { DomainEventInterface } from './DomainEventInterface'
|
|
||||||
|
|
||||||
import { OfflineSubscriptionTokenCreatedEventPayload } from './OfflineSubscriptionTokenCreatedEventPayload'
|
|
||||||
|
|
||||||
export interface OfflineSubscriptionTokenCreatedEvent extends DomainEventInterface {
|
|
||||||
type: 'OFFLINE_SUBSCRIPTION_TOKEN_CREATED'
|
|
||||||
payload: OfflineSubscriptionTokenCreatedEventPayload
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
export interface OfflineSubscriptionTokenCreatedEventPayload {
|
|
||||||
token: string
|
|
||||||
email: string
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import { DomainEventInterface } from './DomainEventInterface'
|
|
||||||
|
|
||||||
import { OneDriveBackupFailedEventPayload } from './OneDriveBackupFailedEventPayload'
|
|
||||||
|
|
||||||
export interface OneDriveBackupFailedEvent extends DomainEventInterface {
|
|
||||||
type: 'ONE_DRIVE_BACKUP_FAILED'
|
|
||||||
payload: OneDriveBackupFailedEventPayload
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
export interface OneDriveBackupFailedEventPayload {
|
|
||||||
muteCloudEmailsSettingUuid: string
|
|
||||||
extensionSettingUuid?: string
|
|
||||||
email: string
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import { DomainEventInterface } from './DomainEventInterface'
|
|
||||||
|
|
||||||
import { RefundRequestedEventPayload } from './RefundRequestedEventPayload'
|
|
||||||
|
|
||||||
export interface RefundRequestedEvent extends DomainEventInterface {
|
|
||||||
type: 'REFUND_REQUESTED'
|
|
||||||
payload: RefundRequestedEventPayload
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
export interface RefundRequestedEventPayload {
|
|
||||||
userEmail: string
|
|
||||||
refundProcessingLink: string
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import { DomainEventInterface } from './DomainEventInterface'
|
|
||||||
|
|
||||||
import { StudentDiscountApprovedEventPayload } from './StudentDiscountApprovedEventPayload'
|
|
||||||
|
|
||||||
export interface StudentDiscountApprovedEvent extends DomainEventInterface {
|
|
||||||
type: 'STUDENT_DISCOUNT_APPROVED'
|
|
||||||
payload: StudentDiscountApprovedEventPayload
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export interface StudentDiscountApprovedEventPayload {
|
|
||||||
userEmail: string
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import { DomainEventInterface } from './DomainEventInterface'
|
|
||||||
|
|
||||||
import { StudentDiscountRequestedEventPayload } from './StudentDiscountRequestedEventPayload'
|
|
||||||
|
|
||||||
export interface StudentDiscountRequestedEvent extends DomainEventInterface {
|
|
||||||
type: 'STUDENT_DISCOUNT_REQUESTED'
|
|
||||||
payload: StudentDiscountRequestedEventPayload
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
export interface StudentDiscountRequestedEventPayload {
|
|
||||||
studentEmail: string
|
|
||||||
userEmail: string
|
|
||||||
adminApprovalLink: string
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import { DomainEventInterface } from './DomainEventInterface'
|
|
||||||
|
|
||||||
import { SubscriptionRateAdjustedEventPayload } from './SubscriptionRateAdjustedEventPayload'
|
|
||||||
|
|
||||||
export interface SubscriptionRateAdjustedEvent extends DomainEventInterface {
|
|
||||||
type: 'SUBSCRIPTION_RATE_ADJUSTED'
|
|
||||||
payload: SubscriptionRateAdjustedEventPayload
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
export interface SubscriptionRateAdjustedEventPayload {
|
|
||||||
userEmail: string
|
|
||||||
newRateFormatted: string
|
|
||||||
refundAmountInDollarsFormatted: string
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { DomainEventInterface } from './DomainEventInterface'
|
|
||||||
import { UserSignedInEventPayload } from './UserSignedInEventPayload'
|
|
||||||
|
|
||||||
export interface UserSignedInEvent extends DomainEventInterface {
|
|
||||||
type: 'USER_SIGNED_IN'
|
|
||||||
payload: UserSignedInEventPayload
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
import { Uuid } from '@standardnotes/common'
|
|
||||||
|
|
||||||
export interface UserSignedInEventPayload {
|
|
||||||
userUuid: string
|
|
||||||
userEmail: string
|
|
||||||
signInAlertEnabled: boolean
|
|
||||||
muteSignInEmailsSettingUuid: Uuid
|
|
||||||
device: string
|
|
||||||
browser?: string
|
|
||||||
}
|
|
||||||
@@ -1,35 +1,21 @@
|
|||||||
export * from './Event/AccountClaimRequestedEvent'
|
|
||||||
export * from './Event/AccountClaimRequestedEventPayload'
|
|
||||||
export * from './Event/AccountDeletionRequestedEvent'
|
export * from './Event/AccountDeletionRequestedEvent'
|
||||||
export * from './Event/AccountDeletionRequestedEventPayload'
|
export * from './Event/AccountDeletionRequestedEventPayload'
|
||||||
export * from './Event/AccountResetRequestedEvent'
|
|
||||||
export * from './Event/AccountResetRequestedEventPayload'
|
|
||||||
export * from './Event/ActivationCodeRequestedEvent'
|
|
||||||
export * from './Event/ActivationCodeRequestedEventPayload'
|
|
||||||
export * from './Event/CloudBackupRequestedEvent'
|
export * from './Event/CloudBackupRequestedEvent'
|
||||||
export * from './Event/CloudBackupRequestedEventPayload'
|
export * from './Event/CloudBackupRequestedEventPayload'
|
||||||
export * from './Event/DailyAnalyticsReportGeneratedEvent'
|
export * from './Event/DailyAnalyticsReportGeneratedEvent'
|
||||||
export * from './Event/DailyAnalyticsReportGeneratedEventPayload'
|
export * from './Event/DailyAnalyticsReportGeneratedEventPayload'
|
||||||
export * from './Event/DiscountAppliedEvent'
|
|
||||||
export * from './Event/DiscountAppliedEventPayload'
|
|
||||||
export * from './Event/DiscountApplyRequestedEvent'
|
export * from './Event/DiscountApplyRequestedEvent'
|
||||||
export * from './Event/DiscountApplyRequestedEventPayload'
|
export * from './Event/DiscountApplyRequestedEventPayload'
|
||||||
export * from './Event/DiscountWithdrawRequestedEvent'
|
export * from './Event/DiscountWithdrawRequestedEvent'
|
||||||
export * from './Event/DiscountWithdrawRequestedEventPayload'
|
export * from './Event/DiscountWithdrawRequestedEventPayload'
|
||||||
export * from './Event/DomainEventInterface'
|
export * from './Event/DomainEventInterface'
|
||||||
export * from './Event/DomainEventService'
|
export * from './Event/DomainEventService'
|
||||||
export * from './Event/DropboxBackupFailedEvent'
|
|
||||||
export * from './Event/DropboxBackupFailedEventPayload'
|
|
||||||
export * from './Event/DuplicateItemSyncedEvent'
|
export * from './Event/DuplicateItemSyncedEvent'
|
||||||
export * from './Event/DuplicateItemSyncedEventPayload'
|
export * from './Event/DuplicateItemSyncedEventPayload'
|
||||||
export * from './Event/EmailArchiveExtensionSyncedEvent'
|
export * from './Event/EmailArchiveExtensionSyncedEvent'
|
||||||
export * from './Event/EmailArchiveExtensionSyncedEventPayload'
|
export * from './Event/EmailArchiveExtensionSyncedEventPayload'
|
||||||
export * from './Event/EmailBackupAttachmentCreatedEvent'
|
|
||||||
export * from './Event/EmailBackupAttachmentCreatedEventPayload'
|
|
||||||
export * from './Event/EmailBackupRequestedEvent'
|
export * from './Event/EmailBackupRequestedEvent'
|
||||||
export * from './Event/EmailBackupRequestedEventPayload'
|
export * from './Event/EmailBackupRequestedEventPayload'
|
||||||
export * from './Event/EmailMessageRequestedEvent'
|
|
||||||
export * from './Event/EmailMessageRequestedEventPayload'
|
|
||||||
export * from './Event/EmailRequestedEvent'
|
export * from './Event/EmailRequestedEvent'
|
||||||
export * from './Event/EmailRequestedEventPayload'
|
export * from './Event/EmailRequestedEventPayload'
|
||||||
export * from './Event/ExitDiscountAppliedEvent'
|
export * from './Event/ExitDiscountAppliedEvent'
|
||||||
@@ -44,10 +30,6 @@ export * from './Event/FileRemovedEvent'
|
|||||||
export * from './Event/FileRemovedEventPayload'
|
export * from './Event/FileRemovedEventPayload'
|
||||||
export * from './Event/FileUploadedEvent'
|
export * from './Event/FileUploadedEvent'
|
||||||
export * from './Event/FileUploadedEventPayload'
|
export * from './Event/FileUploadedEventPayload'
|
||||||
export * from './Event/GoogleDriveBackupFailedEvent'
|
|
||||||
export * from './Event/GoogleDriveBackupFailedEventPayload'
|
|
||||||
export * from './Event/InvoiceGeneratedEvent'
|
|
||||||
export * from './Event/InvoiceGeneratedEventPayload'
|
|
||||||
export * from './Event/ItemDumpedEvent'
|
export * from './Event/ItemDumpedEvent'
|
||||||
export * from './Event/ItemDumpedEventPayload'
|
export * from './Event/ItemDumpedEventPayload'
|
||||||
export * from './Event/ItemRevisionCreationRequestedEvent'
|
export * from './Event/ItemRevisionCreationRequestedEvent'
|
||||||
@@ -62,10 +44,6 @@ export * from './Event/ListedAccountRequestedEvent'
|
|||||||
export * from './Event/ListedAccountRequestedEventPayload'
|
export * from './Event/ListedAccountRequestedEventPayload'
|
||||||
export * from './Event/MuteEmailsSettingChangedEvent'
|
export * from './Event/MuteEmailsSettingChangedEvent'
|
||||||
export * from './Event/MuteEmailsSettingChangedEventPayload'
|
export * from './Event/MuteEmailsSettingChangedEventPayload'
|
||||||
export * from './Event/OfflineSubscriptionTokenCreatedEvent'
|
|
||||||
export * from './Event/OfflineSubscriptionTokenCreatedEventPayload'
|
|
||||||
export * from './Event/OneDriveBackupFailedEvent'
|
|
||||||
export * from './Event/OneDriveBackupFailedEventPayload'
|
|
||||||
export * from './Event/PaymentFailedEvent'
|
export * from './Event/PaymentFailedEvent'
|
||||||
export * from './Event/PaymentFailedEventPayload'
|
export * from './Event/PaymentFailedEventPayload'
|
||||||
export * from './Event/PaymentSuccessEvent'
|
export * from './Event/PaymentSuccessEvent'
|
||||||
@@ -74,8 +52,6 @@ export * from './Event/PredicateVerificationRequestedEvent'
|
|||||||
export * from './Event/PredicateVerificationRequestedEventPayload'
|
export * from './Event/PredicateVerificationRequestedEventPayload'
|
||||||
export * from './Event/PredicateVerifiedEvent'
|
export * from './Event/PredicateVerifiedEvent'
|
||||||
export * from './Event/PredicateVerifiedEventPayload'
|
export * from './Event/PredicateVerifiedEventPayload'
|
||||||
export * from './Event/RefundRequestedEvent'
|
|
||||||
export * from './Event/RefundRequestedEventPayload'
|
|
||||||
export * from './Event/RefundProcessedEvent'
|
export * from './Event/RefundProcessedEvent'
|
||||||
export * from './Event/RefundProcessedEventPayload'
|
export * from './Event/RefundProcessedEventPayload'
|
||||||
export * from './Event/RevisionsCopyRequestedEvent'
|
export * from './Event/RevisionsCopyRequestedEvent'
|
||||||
@@ -86,16 +62,10 @@ export * from './Event/SharedSubscriptionInvitationCanceledEvent'
|
|||||||
export * from './Event/SharedSubscriptionInvitationCanceledEventPayload'
|
export * from './Event/SharedSubscriptionInvitationCanceledEventPayload'
|
||||||
export * from './Event/SharedSubscriptionInvitationCreatedEvent'
|
export * from './Event/SharedSubscriptionInvitationCreatedEvent'
|
||||||
export * from './Event/SharedSubscriptionInvitationCreatedEventPayload'
|
export * from './Event/SharedSubscriptionInvitationCreatedEventPayload'
|
||||||
export * from './Event/StudentDiscountApprovedEvent'
|
|
||||||
export * from './Event/StudentDiscountApprovedEventPayload'
|
|
||||||
export * from './Event/StudentDiscountRequestedEvent'
|
|
||||||
export * from './Event/StudentDiscountRequestedEventPayload'
|
|
||||||
export * from './Event/SubscriptionCancelledEvent'
|
export * from './Event/SubscriptionCancelledEvent'
|
||||||
export * from './Event/SubscriptionCancelledEventPayload'
|
export * from './Event/SubscriptionCancelledEventPayload'
|
||||||
export * from './Event/SubscriptionPurchasedEvent'
|
export * from './Event/SubscriptionPurchasedEvent'
|
||||||
export * from './Event/SubscriptionPurchasedEventPayload'
|
export * from './Event/SubscriptionPurchasedEventPayload'
|
||||||
export * from './Event/SubscriptionRateAdjustedEvent'
|
|
||||||
export * from './Event/SubscriptionRateAdjustedEventPayload'
|
|
||||||
export * from './Event/SubscriptionReactivatedEvent'
|
export * from './Event/SubscriptionReactivatedEvent'
|
||||||
export * from './Event/SubscriptionReactivatedEventPayload'
|
export * from './Event/SubscriptionReactivatedEventPayload'
|
||||||
export * from './Event/SubscriptionReassignedEvent'
|
export * from './Event/SubscriptionReassignedEvent'
|
||||||
@@ -120,8 +90,6 @@ export * from './Event/UserRegisteredEvent'
|
|||||||
export * from './Event/UserRegisteredEventPayload'
|
export * from './Event/UserRegisteredEventPayload'
|
||||||
export * from './Event/UserRolesChangedEvent'
|
export * from './Event/UserRolesChangedEvent'
|
||||||
export * from './Event/UserRolesChangedEventPayload'
|
export * from './Event/UserRolesChangedEventPayload'
|
||||||
export * from './Event/UserSignedInEvent'
|
|
||||||
export * from './Event/UserSignedInEventPayload'
|
|
||||||
export * from './Event/WebSocketMessageRequestedEvent'
|
export * from './Event/WebSocketMessageRequestedEvent'
|
||||||
export * from './Event/WebSocketMessageRequestedEventPayload'
|
export * from './Event/WebSocketMessageRequestedEventPayload'
|
||||||
export * from './Event/WorkspaceInviteAcceptedEvent'
|
export * from './Event/WorkspaceInviteAcceptedEvent'
|
||||||
|
|||||||
@@ -3,6 +3,57 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.6.48](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.47...@standardnotes/event-store@1.6.48) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
|
## [1.6.47](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.46...@standardnotes/event-store@1.6.47) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
|
## [1.6.46](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.45...@standardnotes/event-store@1.6.46) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
|
## [1.6.45](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.44...@standardnotes/event-store@1.6.45) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
|
## [1.6.44](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.43...@standardnotes/event-store@1.6.44) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
|
## [1.6.43](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.42...@standardnotes/event-store@1.6.43) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
|
## [1.6.42](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.41...@standardnotes/event-store@1.6.42) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
|
## [1.6.41](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.40...@standardnotes/event-store@1.6.41) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
|
## [1.6.40](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.39...@standardnotes/event-store@1.6.40) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
|
## [1.6.39](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.38...@standardnotes/event-store@1.6.39) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
|
## [1.6.38](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.37...@standardnotes/event-store@1.6.38) (2022-12-07)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **event-store:** add email requested subscription ([eff0945](https://github.com/standardnotes/server/commit/eff09454c3a28b0124b74c2850fed19313b9e2b2))
|
||||||
|
* **event-store:** reduce handlers ([473feba](https://github.com/standardnotes/server/commit/473feba6a8f008c9d73238be82e1d197082464c0))
|
||||||
|
|
||||||
|
## [1.6.37](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.36...@standardnotes/event-store@1.6.37) (2022-12-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|
||||||
## [1.6.36](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.35...@standardnotes/event-store@1.6.36) (2022-12-07)
|
## [1.6.36](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.35...@standardnotes/event-store@1.6.36) (2022-12-07)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/event-store
|
**Note:** Version bump only for package @standardnotes/event-store
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/event-store",
|
"name": "@standardnotes/event-store",
|
||||||
"version": "1.6.36",
|
"version": "1.6.48",
|
||||||
"description": "Event Store Service",
|
"description": "Event Store Service",
|
||||||
"private": true,
|
"private": true,
|
||||||
"main": "dist/src/index.js",
|
"main": "dist/src/index.js",
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ export class ContainerConfigLoader {
|
|||||||
['LISTED_ACCOUNT_REQUESTED', container.get(TYPES.EventHandler)],
|
['LISTED_ACCOUNT_REQUESTED', container.get(TYPES.EventHandler)],
|
||||||
['LISTED_ACCOUNT_CREATED', container.get(TYPES.EventHandler)],
|
['LISTED_ACCOUNT_CREATED', container.get(TYPES.EventHandler)],
|
||||||
['LISTED_ACCOUNT_DELETED', container.get(TYPES.EventHandler)],
|
['LISTED_ACCOUNT_DELETED', container.get(TYPES.EventHandler)],
|
||||||
['USER_SIGNED_IN', container.get(TYPES.EventHandler)],
|
['EMAIL_REQUESTED', container.get(TYPES.EventHandler)],
|
||||||
['SHARED_SUBSCRIPTION_INVITATION_CREATED', container.get(TYPES.EventHandler)],
|
['SHARED_SUBSCRIPTION_INVITATION_CREATED', container.get(TYPES.EventHandler)],
|
||||||
['EMAIL_BACKUP_ATTACHMENT_CREATED', container.get(TYPES.EventHandler)],
|
['EMAIL_BACKUP_ATTACHMENT_CREATED', container.get(TYPES.EventHandler)],
|
||||||
['EMAIL_BACKUP_REQUESTED', container.get(TYPES.EventHandler)],
|
['EMAIL_BACKUP_REQUESTED', container.get(TYPES.EventHandler)],
|
||||||
|
|||||||
@@ -3,6 +3,50 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.8.47](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.46...@standardnotes/files-server@1.8.47) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
|
## [1.8.46](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.45...@standardnotes/files-server@1.8.46) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
|
## [1.8.45](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.44...@standardnotes/files-server@1.8.45) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
|
## [1.8.44](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.43...@standardnotes/files-server@1.8.44) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
|
## [1.8.43](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.42...@standardnotes/files-server@1.8.43) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
|
## [1.8.42](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.41...@standardnotes/files-server@1.8.42) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
|
## [1.8.41](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.40...@standardnotes/files-server@1.8.41) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
|
## [1.8.40](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.39...@standardnotes/files-server@1.8.40) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
|
## [1.8.39](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.38...@standardnotes/files-server@1.8.39) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
|
## [1.8.38](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.37...@standardnotes/files-server@1.8.38) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
|
## [1.8.37](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.36...@standardnotes/files-server@1.8.37) (2022-12-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
## [1.8.36](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.35...@standardnotes/files-server@1.8.36) (2022-12-07)
|
## [1.8.36](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.35...@standardnotes/files-server@1.8.36) (2022-12-07)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/files-server
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/files-server",
|
"name": "@standardnotes/files-server",
|
||||||
"version": "1.8.36",
|
"version": "1.8.47",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <19.0.0"
|
"node": ">=18.0.0 <19.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,50 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.9.20](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.9.19...@standardnotes/revisions-server@1.9.20) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||||
|
|
||||||
|
## [1.9.19](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.9.18...@standardnotes/revisions-server@1.9.19) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||||
|
|
||||||
|
## [1.9.18](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.9.17...@standardnotes/revisions-server@1.9.18) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||||
|
|
||||||
|
## [1.9.17](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.9.16...@standardnotes/revisions-server@1.9.17) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||||
|
|
||||||
|
## [1.9.16](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.9.15...@standardnotes/revisions-server@1.9.16) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||||
|
|
||||||
|
## [1.9.15](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.9.14...@standardnotes/revisions-server@1.9.15) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||||
|
|
||||||
|
## [1.9.14](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.9.13...@standardnotes/revisions-server@1.9.14) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||||
|
|
||||||
|
## [1.9.13](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.9.12...@standardnotes/revisions-server@1.9.13) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||||
|
|
||||||
|
## [1.9.12](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.9.11...@standardnotes/revisions-server@1.9.12) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||||
|
|
||||||
|
## [1.9.11](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.9.10...@standardnotes/revisions-server@1.9.11) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||||
|
|
||||||
|
## [1.9.10](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.9.9...@standardnotes/revisions-server@1.9.10) (2022-12-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||||
|
|
||||||
## [1.9.9](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.9.8...@standardnotes/revisions-server@1.9.9) (2022-12-07)
|
## [1.9.9](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.9.8...@standardnotes/revisions-server@1.9.9) (2022-12-07)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/revisions-server",
|
"name": "@standardnotes/revisions-server",
|
||||||
"version": "1.9.9",
|
"version": "1.9.20",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <19.0.0"
|
"node": ">=18.0.0 <19.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,64 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.15.1](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.15.0...@standardnotes/scheduler-server@1.15.1) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||||
|
|
||||||
|
# [1.15.0](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.14.10...@standardnotes/scheduler-server@1.15.0) (2022-12-09)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **syncing-server:** replace one drive backup failed event with email requested ([130f90b](https://github.com/standardnotes/server/commit/130f90bdb6cc88e073b9380e8aed5eebe8c49c1e))
|
||||||
|
|
||||||
|
## [1.14.10](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.14.9...@standardnotes/scheduler-server@1.14.10) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||||
|
|
||||||
|
## [1.14.9](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.14.8...@standardnotes/scheduler-server@1.14.9) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||||
|
|
||||||
|
## [1.14.8](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.14.7...@standardnotes/scheduler-server@1.14.8) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||||
|
|
||||||
|
## [1.14.7](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.14.6...@standardnotes/scheduler-server@1.14.7) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||||
|
|
||||||
|
## [1.14.6](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.14.5...@standardnotes/scheduler-server@1.14.6) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||||
|
|
||||||
|
## [1.14.5](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.14.4...@standardnotes/scheduler-server@1.14.5) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||||
|
|
||||||
|
## [1.14.4](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.14.3...@standardnotes/scheduler-server@1.14.4) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||||
|
|
||||||
|
## [1.14.3](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.14.2...@standardnotes/scheduler-server@1.14.3) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||||
|
|
||||||
|
## [1.14.2](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.14.1...@standardnotes/scheduler-server@1.14.2) (2022-12-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||||
|
|
||||||
|
## [1.14.1](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.14.0...@standardnotes/scheduler-server@1.14.1) (2022-12-07)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **scheduler:** importing email contents ([c52bb93](https://github.com/standardnotes/server/commit/c52bb93d794447f04d3ea173f0aac9f26e4eba20))
|
||||||
|
|
||||||
|
# [1.14.0](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.13.37...@standardnotes/scheduler-server@1.14.0) (2022-12-07)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **scheduler:** add scheduled emails contents ([6e0855f](https://github.com/standardnotes/server/commit/6e0855f9b32c230c9ad5594fb6af6dd460300fc1))
|
||||||
|
|
||||||
## [1.13.37](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.13.36...@standardnotes/scheduler-server@1.13.37) (2022-12-07)
|
## [1.13.37](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.13.36...@standardnotes/scheduler-server@1.13.37) (2022-12-07)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||||
|
|||||||
@@ -7,4 +7,5 @@ module.exports = {
|
|||||||
transform: {
|
transform: {
|
||||||
...tsjPreset.transform,
|
...tsjPreset.transform,
|
||||||
},
|
},
|
||||||
|
coveragePathIgnorePatterns: ['/Bootstrap/', '/Infra/', '/Domain/Email/', '/Domain/Event/'],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/scheduler-server",
|
"name": "@standardnotes/scheduler-server",
|
||||||
"version": "1.13.37",
|
"version": "1.15.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <19.0.0"
|
"node": ">=18.0.0 <19.0.0"
|
||||||
},
|
},
|
||||||
@@ -27,6 +27,7 @@
|
|||||||
"@newrelic/winston-enricher": "^4.0.0",
|
"@newrelic/winston-enricher": "^4.0.0",
|
||||||
"@sentry/node": "^7.19.0",
|
"@sentry/node": "^7.19.0",
|
||||||
"@standardnotes/common": "workspace:*",
|
"@standardnotes/common": "workspace:*",
|
||||||
|
"@standardnotes/domain-core": "workspace:^",
|
||||||
"@standardnotes/domain-events": "workspace:*",
|
"@standardnotes/domain-events": "workspace:*",
|
||||||
"@standardnotes/domain-events-infra": "workspace:*",
|
"@standardnotes/domain-events-infra": "workspace:*",
|
||||||
"@standardnotes/predicates": "workspace:*",
|
"@standardnotes/predicates": "workspace:*",
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { html } from './encourage-email-backups.html'
|
||||||
|
|
||||||
|
export function getSubject(): string {
|
||||||
|
return 'Enable email backups for your account'
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getBody(): string {
|
||||||
|
return html
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { html } from './encourage-subscription-purchasing.html'
|
||||||
|
|
||||||
|
export function getSubject(): string {
|
||||||
|
return 'Checking in after one month with Standard Notes'
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getBody(registrationDate: string): string {
|
||||||
|
const body = html
|
||||||
|
|
||||||
|
return body.replace('%%REGISTRATION_DATE%%', registrationDate)
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { html } from './exit-interview.html'
|
||||||
|
|
||||||
|
export function getSubject(): string {
|
||||||
|
return 'Can we ask why you canceled?'
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getBody(): string {
|
||||||
|
return html
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
export const html = `<div>
|
||||||
|
<p>
|
||||||
|
Did you know you can enable daily email backups for your account? This <strong>free</strong> feature sends an
|
||||||
|
email to your inbox with an encrypted backup file including all your notes and tags.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Email backups are an important feature that help protect you against worst-case scenarios. Your backups can be
|
||||||
|
used to restore your account to a previous state, or to import old versions of notes into your present
|
||||||
|
account.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
To enable free email backups, use the Standard Notes web or desktop app, and open Preferences > Backups > Email Backups.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<a href="https://standardnotes.com/help/28/how-do-i-enable-daily-email-backups">
|
||||||
|
Learn more about daily email backups →
|
||||||
|
</a>
|
||||||
|
</div>`
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
export const html = `<div>
|
||||||
|
<p>Hi there,</p>
|
||||||
|
<p>
|
||||||
|
We hope you've been finding great use out of Standard Notes. We built Standard Notes to be a secure place for
|
||||||
|
your most sensitive notes and files.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
As a reminder,
|
||||||
|
<strong>
|
||||||
|
<em>you signed up for the Standard Notes free plan on %%REGISTRATION_DATE%%</em>
|
||||||
|
</strong>
|
||||||
|
Your free account comes with standard features like end-to-end encryption, multiple-device sync, and
|
||||||
|
two-factor authentication.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If you're ready to advance your usage of Standard Notes, we recommend upgrading to one of our more powerful
|
||||||
|
plans.
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
<strong>Productivity</strong> <strong>($59/year)</strong> powers up your editing experience with unique
|
||||||
|
and special-built note-types for markdown, rich text, spreadsheets, todo, and more.
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
<strong>Professional</strong> <strong>($99/year)</strong> gives you all the power of Productivity plus
|
||||||
|
100GB of end-to-end encrypted file storage for your private photos, videos, and documents, plus family
|
||||||
|
subscription sharing with up to 5 people.
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
Professional comes with a 90-day money back guarantee, so if you're not completely satisfied, we're happy to
|
||||||
|
refund your full purchase amount.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>
|
||||||
|
<a href="https://standardnotes.com/plans">Upgrade your plan →</a>
|
||||||
|
</strong>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>
|
||||||
|
<a href="https://standardnotes.com/features">Learn more about the features →</a>
|
||||||
|
</strong>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>Questions & Answers</strong>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<em>How does Standard Notes compare with conventional note-taking apps?</em>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Data you store with Standard Notes is encrypted with end-to-end encryption using a key only you know. Because
|
||||||
|
of this, we can't read your notes, and neither can anyone else.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<em>What kind of notes should I store in Standard Notes?</em>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This question can be reframed as: "What shouldn't I store in non-private services?" This would include
|
||||||
|
sensitive/sensual data related to your health and wellness, secrets and keys, notes and documents with
|
||||||
|
personally identifiable information that, if leaked, would lead to the theft of your identity, and business,
|
||||||
|
financial, or legal information which cover non-public or confidential information.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<em>Where can I access my notes?</em>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Providing you with easy access to your notes and files on all your devices is a key focus for us. We provide
|
||||||
|
secure and well-designed applications for your web browser, desktop (macOS, Windows, Linux,) and mobile
|
||||||
|
(Android and iOS).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<em>I have more questions.</em>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
We love questions. Head over to our Help page to see if your question is answered there. If not, reply
|
||||||
|
directly to this email or send an email to <a href="help@standardnotes.com">help@standardnotes.com</a> and
|
||||||
|
we'd be happy to help.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
export const html = `<div>
|
||||||
|
<p>
|
||||||
|
We're truly sad to see you leave. Our mission is simple: build the best, most private, and most secure
|
||||||
|
note-taking app available. It's clear we've fallen short of your expectations somewhere along the way.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
We just want you to know—if price was the reason you canceled, we're not willing to lose you. That's no issue
|
||||||
|
for us and we're happy to work out something that fits better with your budget. If price is your primary
|
||||||
|
concern, please click the link below, and we'll get in touch with some options.
|
||||||
|
</p>
|
||||||
|
<a href="https://app.standardnotes.com/?user-request=exit-discount">Apply For A Limited Discount Offer →</a>
|
||||||
|
<p>
|
||||||
|
If you canceled for another reason, such as a missing feature, or a feature that wasn't behaving or working as
|
||||||
|
you expected, please let us know! We build this product for you, and feedback from customers like yourself who
|
||||||
|
are willing to pay for a product is most crucial for us as we continue to evolve and iterate on Standard
|
||||||
|
Notes.
|
||||||
|
</p>
|
||||||
|
<p>If you have a minute, please fill out this brief exit interview: </p>
|
||||||
|
<a href="https://standardnotes.typeform.com/to/dX5lzPtm">Short Exit Interview →</a>
|
||||||
|
<p>
|
||||||
|
Our team reads every single response, and your feedback will be shared with the relevant department within our
|
||||||
|
team.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If you have any other thoughts or questions, please feel free to reply directly to this email, and a member of
|
||||||
|
our support team will be in touch with you.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
@@ -1,223 +0,0 @@
|
|||||||
import 'reflect-metadata'
|
|
||||||
|
|
||||||
import { EmailMessageIdentifier } from '@standardnotes/common'
|
|
||||||
import { TimerInterface } from '@standardnotes/time'
|
|
||||||
|
|
||||||
import { DomainEventFactory } from './DomainEventFactory'
|
|
||||||
import { PredicateAuthority, PredicateName } from '@standardnotes/predicates'
|
|
||||||
import { Job } from '../Job/Job'
|
|
||||||
import { Predicate } from '../Predicate/Predicate'
|
|
||||||
|
|
||||||
describe('DomainEventFactory', () => {
|
|
||||||
let timer: TimerInterface
|
|
||||||
|
|
||||||
const createFactory = () => new DomainEventFactory(timer)
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
timer = {} as jest.Mocked<TimerInterface>
|
|
||||||
timer.getTimestampInMicroseconds = jest.fn().mockReturnValue(1)
|
|
||||||
timer.getUTCDate = jest.fn().mockReturnValue(new Date(1))
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should create a DISCOUNT_APPLY_REQUESTED event', () => {
|
|
||||||
expect(
|
|
||||||
createFactory().createDiscountApplyRequestedEvent({
|
|
||||||
userEmail: 'test@test.te',
|
|
||||||
discountCode: 'off-10',
|
|
||||||
}),
|
|
||||||
).toEqual({
|
|
||||||
createdAt: expect.any(Date),
|
|
||||||
meta: {
|
|
||||||
correlation: {
|
|
||||||
userIdentifier: 'test@test.te',
|
|
||||||
userIdentifierType: 'email',
|
|
||||||
},
|
|
||||||
origin: 'scheduler',
|
|
||||||
},
|
|
||||||
payload: {
|
|
||||||
userEmail: 'test@test.te',
|
|
||||||
discountCode: 'off-10',
|
|
||||||
},
|
|
||||||
type: 'DISCOUNT_APPLY_REQUESTED',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should create a DISCOUNT_WITHDRAW_REQUESTED event', () => {
|
|
||||||
expect(
|
|
||||||
createFactory().createDiscountWithdrawRequestedEvent({
|
|
||||||
userEmail: 'test@test.te',
|
|
||||||
discountCode: 'off-10',
|
|
||||||
}),
|
|
||||||
).toEqual({
|
|
||||||
createdAt: expect.any(Date),
|
|
||||||
meta: {
|
|
||||||
correlation: {
|
|
||||||
userIdentifier: 'test@test.te',
|
|
||||||
userIdentifierType: 'email',
|
|
||||||
},
|
|
||||||
origin: 'scheduler',
|
|
||||||
},
|
|
||||||
payload: {
|
|
||||||
userEmail: 'test@test.te',
|
|
||||||
discountCode: 'off-10',
|
|
||||||
},
|
|
||||||
type: 'DISCOUNT_WITHDRAW_REQUESTED',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should create a EXIT_DISCOUNT_WITHDRAW_REQUESTED event', () => {
|
|
||||||
expect(
|
|
||||||
createFactory().createExitDiscountWithdrawRequestedEvent({
|
|
||||||
userEmail: 'test@test.te',
|
|
||||||
discountCode: 'exit-20',
|
|
||||||
}),
|
|
||||||
).toEqual({
|
|
||||||
createdAt: expect.any(Date),
|
|
||||||
meta: {
|
|
||||||
correlation: {
|
|
||||||
userIdentifier: 'test@test.te',
|
|
||||||
userIdentifierType: 'email',
|
|
||||||
},
|
|
||||||
origin: 'scheduler',
|
|
||||||
},
|
|
||||||
payload: {
|
|
||||||
userEmail: 'test@test.te',
|
|
||||||
discountCode: 'exit-20',
|
|
||||||
},
|
|
||||||
type: 'EXIT_DISCOUNT_WITHDRAW_REQUESTED',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should create a EMAIL_MESSAGE_REQUESTED event', () => {
|
|
||||||
expect(
|
|
||||||
createFactory().createEmailMessageRequestedEvent({
|
|
||||||
userEmail: 'test@test.te',
|
|
||||||
messageIdentifier: EmailMessageIdentifier.ENCOURAGE_EMAIL_BACKUPS,
|
|
||||||
context: {
|
|
||||||
foo: 'bar',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
).toEqual({
|
|
||||||
createdAt: expect.any(Date),
|
|
||||||
meta: {
|
|
||||||
correlation: {
|
|
||||||
userIdentifier: 'test@test.te',
|
|
||||||
userIdentifierType: 'email',
|
|
||||||
},
|
|
||||||
origin: 'scheduler',
|
|
||||||
},
|
|
||||||
payload: {
|
|
||||||
messageIdentifier: 'ENCOURAGE_EMAIL_BACKUPS',
|
|
||||||
userEmail: 'test@test.te',
|
|
||||||
context: {
|
|
||||||
foo: 'bar',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
type: 'EMAIL_MESSAGE_REQUESTED',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should create a PREDICATE_VERIFICATION_REQUESTED event dedicated for auth', () => {
|
|
||||||
expect(
|
|
||||||
createFactory().createPredicateVerificationRequestedEvent(
|
|
||||||
{
|
|
||||||
uuid: '1-2-3',
|
|
||||||
userIdentifier: '2-3-4',
|
|
||||||
userIdentifierType: 'uuid',
|
|
||||||
} as jest.Mocked<Job>,
|
|
||||||
{
|
|
||||||
authority: PredicateAuthority.Auth,
|
|
||||||
name: PredicateName.EmailBackupsEnabled,
|
|
||||||
status: 'pending',
|
|
||||||
} as jest.Mocked<Predicate>,
|
|
||||||
),
|
|
||||||
).toEqual({
|
|
||||||
createdAt: expect.any(Date),
|
|
||||||
meta: {
|
|
||||||
correlation: {
|
|
||||||
userIdentifier: '2-3-4',
|
|
||||||
userIdentifierType: 'uuid',
|
|
||||||
},
|
|
||||||
origin: 'scheduler',
|
|
||||||
target: 'auth',
|
|
||||||
},
|
|
||||||
payload: {
|
|
||||||
predicate: {
|
|
||||||
authority: 'auth',
|
|
||||||
jobUuid: '1-2-3',
|
|
||||||
name: 'email-backups-enabled',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
type: 'PREDICATE_VERIFICATION_REQUESTED',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should create a PREDICATE_VERIFICATION_REQUESTED event dedicated for syncing server', () => {
|
|
||||||
expect(
|
|
||||||
createFactory().createPredicateVerificationRequestedEvent(
|
|
||||||
{
|
|
||||||
uuid: '1-2-3',
|
|
||||||
userIdentifier: '2-3-4',
|
|
||||||
userIdentifierType: 'uuid',
|
|
||||||
} as jest.Mocked<Job>,
|
|
||||||
{
|
|
||||||
authority: PredicateAuthority.SyncingServer,
|
|
||||||
name: PredicateName.EmailBackupsEnabled,
|
|
||||||
status: 'pending',
|
|
||||||
} as jest.Mocked<Predicate>,
|
|
||||||
),
|
|
||||||
).toEqual({
|
|
||||||
createdAt: expect.any(Date),
|
|
||||||
meta: {
|
|
||||||
correlation: {
|
|
||||||
userIdentifier: '2-3-4',
|
|
||||||
userIdentifierType: 'uuid',
|
|
||||||
},
|
|
||||||
origin: 'scheduler',
|
|
||||||
target: 'syncing-server',
|
|
||||||
},
|
|
||||||
payload: {
|
|
||||||
predicate: {
|
|
||||||
authority: 'syncing-server',
|
|
||||||
jobUuid: '1-2-3',
|
|
||||||
name: 'email-backups-enabled',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
type: 'PREDICATE_VERIFICATION_REQUESTED',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should create a PREDICATE_VERIFICATION_REQUESTED event dedicated for unknown target', () => {
|
|
||||||
expect(
|
|
||||||
createFactory().createPredicateVerificationRequestedEvent(
|
|
||||||
{
|
|
||||||
uuid: '1-2-3',
|
|
||||||
userIdentifier: '2-3-4',
|
|
||||||
userIdentifierType: 'uuid',
|
|
||||||
} as jest.Mocked<Job>,
|
|
||||||
{
|
|
||||||
authority: 'foobar' as PredicateAuthority,
|
|
||||||
name: PredicateName.EmailBackupsEnabled,
|
|
||||||
status: 'pending',
|
|
||||||
} as jest.Mocked<Predicate>,
|
|
||||||
),
|
|
||||||
).toEqual({
|
|
||||||
createdAt: expect.any(Date),
|
|
||||||
meta: {
|
|
||||||
correlation: {
|
|
||||||
userIdentifier: '2-3-4',
|
|
||||||
userIdentifierType: 'uuid',
|
|
||||||
},
|
|
||||||
origin: 'scheduler',
|
|
||||||
},
|
|
||||||
payload: {
|
|
||||||
predicate: {
|
|
||||||
authority: 'foobar',
|
|
||||||
jobUuid: '1-2-3',
|
|
||||||
name: 'email-backups-enabled',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
type: 'PREDICATE_VERIFICATION_REQUESTED',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
import { EmailMessageIdentifier } from '@standardnotes/common'
|
|
||||||
import {
|
import {
|
||||||
DiscountApplyRequestedEvent,
|
DiscountApplyRequestedEvent,
|
||||||
DiscountWithdrawRequestedEvent,
|
DiscountWithdrawRequestedEvent,
|
||||||
DomainEventService,
|
DomainEventService,
|
||||||
EmailMessageRequestedEvent,
|
EmailRequestedEvent,
|
||||||
ExitDiscountWithdrawRequestedEvent,
|
ExitDiscountWithdrawRequestedEvent,
|
||||||
PredicateVerificationRequestedEvent,
|
PredicateVerificationRequestedEvent,
|
||||||
} from '@standardnotes/domain-events'
|
} from '@standardnotes/domain-events'
|
||||||
@@ -70,13 +69,15 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createEmailMessageRequestedEvent(dto: {
|
createEmailRequestedEvent(dto: {
|
||||||
userEmail: string
|
userEmail: string
|
||||||
messageIdentifier: EmailMessageIdentifier
|
messageIdentifier: string
|
||||||
context: Record<string, unknown>
|
level: string
|
||||||
}): EmailMessageRequestedEvent {
|
body: string
|
||||||
|
subject: string
|
||||||
|
}): EmailRequestedEvent {
|
||||||
return {
|
return {
|
||||||
type: 'EMAIL_MESSAGE_REQUESTED',
|
type: 'EMAIL_REQUESTED',
|
||||||
createdAt: this.timer.getUTCDate(),
|
createdAt: this.timer.getUTCDate(),
|
||||||
meta: {
|
meta: {
|
||||||
correlation: {
|
correlation: {
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import { EmailMessageIdentifier } from '@standardnotes/common'
|
|
||||||
import {
|
import {
|
||||||
DiscountApplyRequestedEvent,
|
DiscountApplyRequestedEvent,
|
||||||
DiscountWithdrawRequestedEvent,
|
DiscountWithdrawRequestedEvent,
|
||||||
EmailMessageRequestedEvent,
|
EmailRequestedEvent,
|
||||||
ExitDiscountWithdrawRequestedEvent,
|
ExitDiscountWithdrawRequestedEvent,
|
||||||
PredicateVerificationRequestedEvent,
|
PredicateVerificationRequestedEvent,
|
||||||
} from '@standardnotes/domain-events'
|
} from '@standardnotes/domain-events'
|
||||||
@@ -12,11 +11,13 @@ import { Predicate } from '../Predicate/Predicate'
|
|||||||
|
|
||||||
export interface DomainEventFactoryInterface {
|
export interface DomainEventFactoryInterface {
|
||||||
createPredicateVerificationRequestedEvent(job: Job, predicate: Predicate): PredicateVerificationRequestedEvent
|
createPredicateVerificationRequestedEvent(job: Job, predicate: Predicate): PredicateVerificationRequestedEvent
|
||||||
createEmailMessageRequestedEvent(dto: {
|
createEmailRequestedEvent(dto: {
|
||||||
userEmail: string
|
userEmail: string
|
||||||
messageIdentifier: EmailMessageIdentifier
|
messageIdentifier: string
|
||||||
context: Record<string, unknown>
|
level: string
|
||||||
}): EmailMessageRequestedEvent
|
body: string
|
||||||
|
subject: string
|
||||||
|
}): EmailRequestedEvent
|
||||||
createDiscountApplyRequestedEvent(dto: { userEmail: string; discountCode: string }): DiscountApplyRequestedEvent
|
createDiscountApplyRequestedEvent(dto: { userEmail: string; discountCode: string }): DiscountApplyRequestedEvent
|
||||||
createDiscountWithdrawRequestedEvent(dto: { userEmail: string; discountCode: string }): DiscountWithdrawRequestedEvent
|
createDiscountWithdrawRequestedEvent(dto: { userEmail: string; discountCode: string }): DiscountWithdrawRequestedEvent
|
||||||
createExitDiscountWithdrawRequestedEvent(dto: {
|
createExitDiscountWithdrawRequestedEvent(dto: {
|
||||||
|
|||||||
@@ -2,10 +2,11 @@ import {
|
|||||||
DiscountApplyRequestedEvent,
|
DiscountApplyRequestedEvent,
|
||||||
DiscountWithdrawRequestedEvent,
|
DiscountWithdrawRequestedEvent,
|
||||||
DomainEventPublisherInterface,
|
DomainEventPublisherInterface,
|
||||||
EmailMessageRequestedEvent,
|
EmailRequestedEvent,
|
||||||
ExitDiscountWithdrawRequestedEvent,
|
ExitDiscountWithdrawRequestedEvent,
|
||||||
} from '@standardnotes/domain-events'
|
} from '@standardnotes/domain-events'
|
||||||
import { PredicateName } from '@standardnotes/predicates'
|
import { PredicateName } from '@standardnotes/predicates'
|
||||||
|
import { TimerInterface } from '@standardnotes/time'
|
||||||
import 'reflect-metadata'
|
import 'reflect-metadata'
|
||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
|
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
|
||||||
@@ -26,13 +27,17 @@ describe('JobDoneInterpreter', () => {
|
|||||||
let domainEventPublisher: DomainEventPublisherInterface
|
let domainEventPublisher: DomainEventPublisherInterface
|
||||||
let job: Job
|
let job: Job
|
||||||
let logger: Logger
|
let logger: Logger
|
||||||
|
let timer: TimerInterface
|
||||||
|
|
||||||
const createInterpreter = () =>
|
const createInterpreter = () =>
|
||||||
new JobDoneInterpreter(jobRepository, predicateRepository, domainEventFactory, domainEventPublisher, logger)
|
new JobDoneInterpreter(jobRepository, predicateRepository, domainEventFactory, domainEventPublisher, timer, logger)
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
job = {} as jest.Mocked<Job>
|
job = {} as jest.Mocked<Job>
|
||||||
|
|
||||||
|
timer = {} as jest.Mocked<TimerInterface>
|
||||||
|
timer.convertMicrosecondsToDate = jest.fn().mockReturnValue(new Date())
|
||||||
|
|
||||||
jobRepository = {} as jest.Mocked<JobRepositoryInterface>
|
jobRepository = {} as jest.Mocked<JobRepositoryInterface>
|
||||||
jobRepository.findOneByUuid = jest.fn().mockReturnValue(job)
|
jobRepository.findOneByUuid = jest.fn().mockReturnValue(job)
|
||||||
|
|
||||||
@@ -40,9 +45,7 @@ describe('JobDoneInterpreter', () => {
|
|||||||
predicateRepository.findByJobUuid = jest.fn().mockReturnValue([])
|
predicateRepository.findByJobUuid = jest.fn().mockReturnValue([])
|
||||||
|
|
||||||
domainEventFactory = {} as jest.Mocked<DomainEventFactoryInterface>
|
domainEventFactory = {} as jest.Mocked<DomainEventFactoryInterface>
|
||||||
domainEventFactory.createEmailMessageRequestedEvent = jest
|
domainEventFactory.createEmailRequestedEvent = jest.fn().mockReturnValue({} as jest.Mocked<EmailRequestedEvent>)
|
||||||
.fn()
|
|
||||||
.mockReturnValue({} as jest.Mocked<EmailMessageRequestedEvent>)
|
|
||||||
domainEventFactory.createDiscountApplyRequestedEvent = jest
|
domainEventFactory.createDiscountApplyRequestedEvent = jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockReturnValue({} as jest.Mocked<DiscountApplyRequestedEvent>)
|
.mockReturnValue({} as jest.Mocked<DiscountApplyRequestedEvent>)
|
||||||
@@ -89,11 +92,7 @@ describe('JobDoneInterpreter', () => {
|
|||||||
|
|
||||||
await createInterpreter().interpret('1-2-3')
|
await createInterpreter().interpret('1-2-3')
|
||||||
|
|
||||||
expect(domainEventFactory.createEmailMessageRequestedEvent).toHaveBeenCalledWith({
|
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
|
||||||
context: {},
|
|
||||||
messageIdentifier: 'ENCOURAGE_EMAIL_BACKUPS',
|
|
||||||
userEmail: 'test@test.te',
|
|
||||||
})
|
|
||||||
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -111,7 +110,7 @@ describe('JobDoneInterpreter', () => {
|
|||||||
|
|
||||||
await createInterpreter().interpret('1-2-3')
|
await createInterpreter().interpret('1-2-3')
|
||||||
|
|
||||||
expect(domainEventFactory.createEmailMessageRequestedEvent).not.toHaveBeenCalled()
|
expect(domainEventFactory.createEmailRequestedEvent).not.toHaveBeenCalled()
|
||||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -124,7 +123,7 @@ describe('JobDoneInterpreter', () => {
|
|||||||
|
|
||||||
await createInterpreter().interpret('1-2-3')
|
await createInterpreter().interpret('1-2-3')
|
||||||
|
|
||||||
expect(domainEventFactory.createEmailMessageRequestedEvent).not.toHaveBeenCalled()
|
expect(domainEventFactory.createEmailRequestedEvent).not.toHaveBeenCalled()
|
||||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -143,11 +142,7 @@ describe('JobDoneInterpreter', () => {
|
|||||||
|
|
||||||
await createInterpreter().interpret('1-2-3')
|
await createInterpreter().interpret('1-2-3')
|
||||||
|
|
||||||
expect(domainEventFactory.createEmailMessageRequestedEvent).toHaveBeenCalledWith({
|
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
|
||||||
context: { userRegisteredAt: 123 },
|
|
||||||
messageIdentifier: 'ENCOURAGE_SUBSCRIPTION_PURCHASING',
|
|
||||||
userEmail: 'test@test.te',
|
|
||||||
})
|
|
||||||
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -160,7 +155,7 @@ describe('JobDoneInterpreter', () => {
|
|||||||
|
|
||||||
await createInterpreter().interpret('1-2-3')
|
await createInterpreter().interpret('1-2-3')
|
||||||
|
|
||||||
expect(domainEventFactory.createEmailMessageRequestedEvent).not.toHaveBeenCalled()
|
expect(domainEventFactory.createEmailRequestedEvent).not.toHaveBeenCalled()
|
||||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -173,11 +168,7 @@ describe('JobDoneInterpreter', () => {
|
|||||||
|
|
||||||
await createInterpreter().interpret('1-2-3')
|
await createInterpreter().interpret('1-2-3')
|
||||||
|
|
||||||
expect(domainEventFactory.createEmailMessageRequestedEvent).toHaveBeenCalledWith({
|
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
|
||||||
context: {},
|
|
||||||
messageIdentifier: 'EXIT_INTERVIEW',
|
|
||||||
userEmail: 'test@test.te',
|
|
||||||
})
|
|
||||||
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -190,7 +181,7 @@ describe('JobDoneInterpreter', () => {
|
|||||||
|
|
||||||
await createInterpreter().interpret('1-2-3')
|
await createInterpreter().interpret('1-2-3')
|
||||||
|
|
||||||
expect(domainEventFactory.createEmailMessageRequestedEvent).not.toHaveBeenCalled()
|
expect(domainEventFactory.createEmailRequestedEvent).not.toHaveBeenCalled()
|
||||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -295,7 +286,7 @@ describe('JobDoneInterpreter', () => {
|
|||||||
|
|
||||||
await createInterpreter().interpret('1-2-3')
|
await createInterpreter().interpret('1-2-3')
|
||||||
|
|
||||||
expect(domainEventFactory.createEmailMessageRequestedEvent).not.toHaveBeenCalled()
|
expect(domainEventFactory.createEmailRequestedEvent).not.toHaveBeenCalled()
|
||||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { EmailMessageIdentifier } from '@standardnotes/common'
|
|
||||||
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
||||||
import { PredicateName } from '@standardnotes/predicates'
|
import { PredicateName } from '@standardnotes/predicates'
|
||||||
import { inject, injectable } from 'inversify'
|
import { inject, injectable } from 'inversify'
|
||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
|
import { EmailLevel } from '@standardnotes/domain-core'
|
||||||
|
import { TimerInterface } from '@standardnotes/time'
|
||||||
|
|
||||||
import TYPES from '../../Bootstrap/Types'
|
import TYPES from '../../Bootstrap/Types'
|
||||||
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
|
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
|
||||||
@@ -13,6 +14,15 @@ import { Job } from './Job'
|
|||||||
import { JobDoneInterpreterInterface } from './JobDoneInterpreterInterface'
|
import { JobDoneInterpreterInterface } from './JobDoneInterpreterInterface'
|
||||||
import { JobName } from './JobName'
|
import { JobName } from './JobName'
|
||||||
import { JobRepositoryInterface } from './JobRepositoryInterface'
|
import { JobRepositoryInterface } from './JobRepositoryInterface'
|
||||||
|
import { getSubject as getExitInterviewSubject, getBody as getExitInterviewBody } from '../Email/ExitInterview'
|
||||||
|
import {
|
||||||
|
getSubject as getEncourageEmailBackupsSubject,
|
||||||
|
getBody as getEncourageEmailBackupsBody,
|
||||||
|
} from '../Email/EncourageEmailBackups'
|
||||||
|
import {
|
||||||
|
getSubject as getEncourageSubscriptionPurchasingSubject,
|
||||||
|
getBody as getEncourageSubscriptionPurchasingBody,
|
||||||
|
} from '../Email/EncourageSubscriptionPurchasing'
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class JobDoneInterpreter implements JobDoneInterpreterInterface {
|
export class JobDoneInterpreter implements JobDoneInterpreterInterface {
|
||||||
@@ -21,6 +31,7 @@ export class JobDoneInterpreter implements JobDoneInterpreterInterface {
|
|||||||
@inject(TYPES.PredicateRepository) private predicateRepository: PredicateRepositoryInterface,
|
@inject(TYPES.PredicateRepository) private predicateRepository: PredicateRepositoryInterface,
|
||||||
@inject(TYPES.DomainEventFactory) private domainEventFactory: DomainEventFactoryInterface,
|
@inject(TYPES.DomainEventFactory) private domainEventFactory: DomainEventFactoryInterface,
|
||||||
@inject(TYPES.DomainEventPublisher) private domainEventPublisher: DomainEventPublisherInterface,
|
@inject(TYPES.DomainEventPublisher) private domainEventPublisher: DomainEventPublisherInterface,
|
||||||
|
@inject(TYPES.Timer) private timer: TimerInterface,
|
||||||
@inject(TYPES.Logger) private logger: Logger,
|
@inject(TYPES.Logger) private logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@@ -81,10 +92,12 @@ export class JobDoneInterpreter implements JobDoneInterpreterInterface {
|
|||||||
this.logger.debug(`[${job.uuid}]${job.name}: requesting email backup encouragement email.`)
|
this.logger.debug(`[${job.uuid}]${job.name}: requesting email backup encouragement email.`)
|
||||||
|
|
||||||
await this.domainEventPublisher.publish(
|
await this.domainEventPublisher.publish(
|
||||||
this.domainEventFactory.createEmailMessageRequestedEvent({
|
this.domainEventFactory.createEmailRequestedEvent({
|
||||||
userEmail: job.userIdentifier,
|
userEmail: job.userIdentifier,
|
||||||
messageIdentifier: EmailMessageIdentifier.ENCOURAGE_EMAIL_BACKUPS,
|
messageIdentifier: 'ENCOURAGE_EMAIL_BACKUPS',
|
||||||
context: {},
|
subject: getEncourageEmailBackupsSubject(),
|
||||||
|
body: getEncourageEmailBackupsBody(),
|
||||||
|
level: EmailLevel.LEVELS.System,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -93,12 +106,14 @@ export class JobDoneInterpreter implements JobDoneInterpreterInterface {
|
|||||||
this.logger.debug(`[${job.uuid}]${job.name}: requesting subscription purchase encouragement email.`)
|
this.logger.debug(`[${job.uuid}]${job.name}: requesting subscription purchase encouragement email.`)
|
||||||
|
|
||||||
await this.domainEventPublisher.publish(
|
await this.domainEventPublisher.publish(
|
||||||
this.domainEventFactory.createEmailMessageRequestedEvent({
|
this.domainEventFactory.createEmailRequestedEvent({
|
||||||
userEmail: job.userIdentifier,
|
userEmail: job.userIdentifier,
|
||||||
messageIdentifier: EmailMessageIdentifier.ENCOURAGE_SUBSCRIPTION_PURCHASING,
|
messageIdentifier: 'ENCOURAGE_SUBSCRIPTION_PURCHASING',
|
||||||
context: {
|
subject: getEncourageSubscriptionPurchasingSubject(),
|
||||||
userRegisteredAt: job.createdAt,
|
body: getEncourageSubscriptionPurchasingBody(
|
||||||
},
|
this.timer.convertMicrosecondsToDate(job.createdAt).toLocaleString(),
|
||||||
|
),
|
||||||
|
level: EmailLevel.LEVELS.System,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -107,10 +122,12 @@ export class JobDoneInterpreter implements JobDoneInterpreterInterface {
|
|||||||
this.logger.debug(`[${job.uuid}]${job.name}: requesting exit interview email.`)
|
this.logger.debug(`[${job.uuid}]${job.name}: requesting exit interview email.`)
|
||||||
|
|
||||||
await this.domainEventPublisher.publish(
|
await this.domainEventPublisher.publish(
|
||||||
this.domainEventFactory.createEmailMessageRequestedEvent({
|
this.domainEventFactory.createEmailRequestedEvent({
|
||||||
userEmail: job.userIdentifier,
|
userEmail: job.userIdentifier,
|
||||||
messageIdentifier: EmailMessageIdentifier.EXIT_INTERVIEW,
|
messageIdentifier: 'EXIT_INTERVIEW',
|
||||||
context: {},
|
subject: getExitInterviewSubject(),
|
||||||
|
body: getExitInterviewBody(),
|
||||||
|
level: EmailLevel.LEVELS.System,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,62 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [1.24.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.23.0...@standardnotes/syncing-server@1.24.0) (2022-12-09)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **syncing-server:** replace email backup attachment created with email requested ([32601f3](https://github.com/standardnotes/syncing-server-js/commit/32601f34f181b29b7c62cd2926111a0887d97fbf))
|
||||||
|
|
||||||
|
# [1.23.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.22.0...@standardnotes/syncing-server@1.23.0) (2022-12-09)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **syncing-server:** replace one drive backup failed event with email requested ([130f90b](https://github.com/standardnotes/syncing-server-js/commit/130f90bdb6cc88e073b9380e8aed5eebe8c49c1e))
|
||||||
|
|
||||||
|
# [1.22.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.21.0...@standardnotes/syncing-server@1.22.0) (2022-12-09)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **syncing-serfver:** remove dropbox backup failed event in favour of email requested ([118156c](https://github.com/standardnotes/syncing-server-js/commit/118156c62de70eca8fd89414f6e409abd0363e62))
|
||||||
|
|
||||||
|
# [1.21.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.20.17...@standardnotes/syncing-server@1.21.0) (2022-12-09)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **syncing-server:** remove google drive backup failed event in favour of email requested ([00fe321](https://github.com/standardnotes/syncing-server-js/commit/00fe32136e7add627e58e8ea223f7f484f1d3718))
|
||||||
|
|
||||||
|
## [1.20.17](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.20.16...@standardnotes/syncing-server@1.20.17) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||||
|
|
||||||
|
## [1.20.16](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.20.15...@standardnotes/syncing-server@1.20.16) (2022-12-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||||
|
|
||||||
|
## [1.20.15](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.20.14...@standardnotes/syncing-server@1.20.15) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||||
|
|
||||||
|
## [1.20.14](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.20.13...@standardnotes/syncing-server@1.20.14) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||||
|
|
||||||
|
## [1.20.13](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.20.12...@standardnotes/syncing-server@1.20.13) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||||
|
|
||||||
|
## [1.20.12](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.20.11...@standardnotes/syncing-server@1.20.12) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||||
|
|
||||||
|
## [1.20.11](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.20.10...@standardnotes/syncing-server@1.20.11) (2022-12-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||||
|
|
||||||
|
## [1.20.10](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.20.9...@standardnotes/syncing-server@1.20.10) (2022-12-07)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||||
|
|
||||||
## [1.20.9](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.20.8...@standardnotes/syncing-server@1.20.9) (2022-12-07)
|
## [1.20.9](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.20.8...@standardnotes/syncing-server@1.20.9) (2022-12-07)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||||
|
|||||||
@@ -7,6 +7,6 @@ module.exports = {
|
|||||||
transform: {
|
transform: {
|
||||||
...tsjPreset.transform,
|
...tsjPreset.transform,
|
||||||
},
|
},
|
||||||
coveragePathIgnorePatterns: ['/Bootstrap/', 'HealthCheckController', '/Infra/'],
|
coveragePathIgnorePatterns: ['/Bootstrap/', 'HealthCheckController', '/Infra/', '/Domain/Email/'],
|
||||||
setupFilesAfterEnv: ['./test-setup.ts'],
|
setupFilesAfterEnv: ['./test-setup.ts'],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/syncing-server",
|
"name": "@standardnotes/syncing-server",
|
||||||
"version": "1.20.9",
|
"version": "1.24.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <19.0.0"
|
"node": ">=18.0.0 <19.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { html } from './dropbox-backup-failed.html'
|
||||||
|
|
||||||
|
export function getSubject(): string {
|
||||||
|
return 'Failed Daily Backup to Dropbox'
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getBody(): string {
|
||||||
|
return html
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { html } from './email-backup-attachment-created.html'
|
||||||
|
|
||||||
|
export function getSubject(fileIndex: number, numberOfFiles: number, date: string): string {
|
||||||
|
let subject = `Data Backup for ${date}`
|
||||||
|
if (numberOfFiles > 1) {
|
||||||
|
subject = `Data Backup for ${date} - Part ${fileIndex} Of ${numberOfFiles}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return subject
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getBody(email: string): string {
|
||||||
|
return html(email)
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { html } from './google-drive-backup-failed.html'
|
||||||
|
|
||||||
|
export function getSubject(): string {
|
||||||
|
return 'Failed Daily Backup to Google Drive Sync'
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getBody(): string {
|
||||||
|
return html
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { html } from './one-drive-backup-failed.html'
|
||||||
|
|
||||||
|
export function getSubject(): string {
|
||||||
|
return 'Failed Daily Backup to OneDrive Sync'
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getBody(): string {
|
||||||
|
return html
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
export const html = `<p>Hello,</p>
|
||||||
|
<p>We recently tried backing up your data to <strong>Dropbox</strong>, but an issue prevented us from doing so.</p>
|
||||||
|
<p>
|
||||||
|
The usual cause is an expired or revoked token from your sync provider. Please follow
|
||||||
|
<a href='https://standardnotes.com/help/27/how-do-i-enable-dropbox-google-drive-or-onedrive-backups'>these
|
||||||
|
instructions</a>
|
||||||
|
to use CloudLink on the web or desktop Standard Notes application to uninstall then reinstall this sync provider.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
We apologize for any inconvenience this may cause.
|
||||||
|
If you have any questions, please feel free to reply directly to this email.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Thanks,
|
||||||
|
<br>SN</br>
|
||||||
|
</p>
|
||||||
|
<a href='https://app.standardnotes.com/?settings=backups'>Mute these emails</a>`
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
export const html = (email: string) => `
|
||||||
|
<p>
|
||||||
|
Your encrypted data backup is attached for ${email}. You can import this file using
|
||||||
|
the Standard Notes web or desktop app, or by using the offline decryption script available at
|
||||||
|
<a style="text-decoration:none !important; text-decoration:none;">standardnotes.org/offline</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<strong>Please note:</strong>
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
We will never send anything other than a <code>txt</code> file
|
||||||
|
as part of your daily backups. To protect yourself against phishing attacks, never open
|
||||||
|
any other kind of file, and always open the <code>txt</code> file with a text editor to
|
||||||
|
verify its contents before decrypting.
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
We will never include clickable links in this email. Instead, manually verify
|
||||||
|
and copy/paste the offline link above in your browser.
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</p>
|
||||||
|
<hr />
|
||||||
|
<p>
|
||||||
|
<i>
|
||||||
|
Want to disable daily backups? Uninstall 'Daily Email Backups' from your Extensions
|
||||||
|
menu in Standard Notes to immediately disable backups.
|
||||||
|
Otherwise, reply to this email with "Stop". Note that it may
|
||||||
|
take up to 72 hours or more to perform manual removal via the "Stop" method.
|
||||||
|
</i>
|
||||||
|
</p>
|
||||||
|
`
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
export const html = `<p>Hello,</p>
|
||||||
|
<p>We recently tried backing up your data to <strong>Google Drive Sync</strong>, but an issue prevented us from
|
||||||
|
doing
|
||||||
|
so.</p>
|
||||||
|
<p>
|
||||||
|
The usual cause is an expired or revoked token from your sync provider. Please follow
|
||||||
|
<a href='https://standardnotes.com/help/27/how-do-i-enable-dropbox-google-drive-or-onedrive-backups'>these
|
||||||
|
instructions</a>
|
||||||
|
to use CloudLink on the web or desktop Standard Notes application to uninstall then reinstall this sync provider.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
We apologize for any inconvenience this may cause.
|
||||||
|
If you have any questions, please feel free to reply directly to this email.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Thanks,
|
||||||
|
<br>SN</br>
|
||||||
|
</p>
|
||||||
|
<a href='https://app.standardnotes.com/?settings=backups'>Mute these emails</a>`
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
export const html = `<p>Hello,</p>
|
||||||
|
<p>We recently tried backing up your data to <strong>OneDrive Sync</strong>, but an issue prevented us from doing
|
||||||
|
so.</p>
|
||||||
|
<p>
|
||||||
|
The usual cause is an expired or revoked token from your sync provider. Please follow
|
||||||
|
<a href='https://standardnotes.com/help/27/how-do-i-enable-dropbox-google-drive-or-onedrive-backups'>these
|
||||||
|
instructions</a>
|
||||||
|
to use CloudLink on the web or desktop Standard Notes application to uninstall then reinstall this sync provider.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
We apologize for any inconvenience this may cause.
|
||||||
|
If you have any questions, please feel free to reply directly to this email.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Thanks,
|
||||||
|
<br>SN</br>
|
||||||
|
</p>
|
||||||
|
<a href='https://app.standardnotes.com/?settings=backups'>Mute these emails</a>`
|
||||||
@@ -1,15 +1,12 @@
|
|||||||
/* istanbul ignore file */
|
/* istanbul ignore file */
|
||||||
import {
|
import {
|
||||||
DomainEventService,
|
DomainEventService,
|
||||||
DropboxBackupFailedEvent,
|
|
||||||
DuplicateItemSyncedEvent,
|
DuplicateItemSyncedEvent,
|
||||||
EmailArchiveExtensionSyncedEvent,
|
EmailArchiveExtensionSyncedEvent,
|
||||||
EmailBackupAttachmentCreatedEvent,
|
EmailRequestedEvent,
|
||||||
GoogleDriveBackupFailedEvent,
|
|
||||||
ItemDumpedEvent,
|
ItemDumpedEvent,
|
||||||
ItemRevisionCreationRequestedEvent,
|
ItemRevisionCreationRequestedEvent,
|
||||||
ItemsSyncedEvent,
|
ItemsSyncedEvent,
|
||||||
OneDriveBackupFailedEvent,
|
|
||||||
RevisionsCopyRequestedEvent,
|
RevisionsCopyRequestedEvent,
|
||||||
RevisionsOwnershipUpdateRequestedEvent,
|
RevisionsOwnershipUpdateRequestedEvent,
|
||||||
UserContentSizeRecalculationRequestedEvent,
|
UserContentSizeRecalculationRequestedEvent,
|
||||||
@@ -131,57 +128,31 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createDropboxBackupFailedEvent(muteCloudEmailsSettingUuid: string, email: string): DropboxBackupFailedEvent {
|
createEmailRequestedEvent(dto: {
|
||||||
|
userEmail: string
|
||||||
|
messageIdentifier: string
|
||||||
|
level: string
|
||||||
|
body: string
|
||||||
|
subject: string
|
||||||
|
sender?: string
|
||||||
|
attachments?: Array<{
|
||||||
|
filePath: string
|
||||||
|
fileName: string
|
||||||
|
attachmentFileName: string
|
||||||
|
attachmentContentType: string
|
||||||
|
}>
|
||||||
|
}): EmailRequestedEvent {
|
||||||
return {
|
return {
|
||||||
type: 'DROPBOX_BACKUP_FAILED',
|
type: 'EMAIL_REQUESTED',
|
||||||
createdAt: this.timer.getUTCDate(),
|
createdAt: this.timer.getUTCDate(),
|
||||||
meta: {
|
meta: {
|
||||||
correlation: {
|
correlation: {
|
||||||
userIdentifier: email,
|
userIdentifier: dto.userEmail,
|
||||||
userIdentifierType: 'email',
|
userIdentifierType: 'email',
|
||||||
},
|
},
|
||||||
origin: DomainEventService.SyncingServer,
|
origin: DomainEventService.SyncingServer,
|
||||||
},
|
},
|
||||||
payload: {
|
payload: dto,
|
||||||
muteCloudEmailsSettingUuid,
|
|
||||||
email,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
createGoogleDriveBackupFailedEvent(muteCloudEmailsSettingUuid: string, email: string): GoogleDriveBackupFailedEvent {
|
|
||||||
return {
|
|
||||||
type: 'GOOGLE_DRIVE_BACKUP_FAILED',
|
|
||||||
createdAt: this.timer.getUTCDate(),
|
|
||||||
meta: {
|
|
||||||
correlation: {
|
|
||||||
userIdentifier: email,
|
|
||||||
userIdentifierType: 'email',
|
|
||||||
},
|
|
||||||
origin: DomainEventService.SyncingServer,
|
|
||||||
},
|
|
||||||
payload: {
|
|
||||||
muteCloudEmailsSettingUuid,
|
|
||||||
email,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
createOneDriveBackupFailedEvent(muteCloudEmailsSettingUuid: string, email: string): OneDriveBackupFailedEvent {
|
|
||||||
return {
|
|
||||||
type: 'ONE_DRIVE_BACKUP_FAILED',
|
|
||||||
createdAt: this.timer.getUTCDate(),
|
|
||||||
meta: {
|
|
||||||
correlation: {
|
|
||||||
userIdentifier: email,
|
|
||||||
userIdentifierType: 'email',
|
|
||||||
},
|
|
||||||
origin: DomainEventService.SyncingServer,
|
|
||||||
},
|
|
||||||
payload: {
|
|
||||||
muteCloudEmailsSettingUuid,
|
|
||||||
email,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,24 +196,4 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createEmailBackupAttachmentCreatedEvent(dto: {
|
|
||||||
backupFileName: string
|
|
||||||
backupFileIndex: number
|
|
||||||
backupFilesTotal: number
|
|
||||||
email: string
|
|
||||||
}): EmailBackupAttachmentCreatedEvent {
|
|
||||||
return {
|
|
||||||
type: 'EMAIL_BACKUP_ATTACHMENT_CREATED',
|
|
||||||
createdAt: this.timer.getUTCDate(),
|
|
||||||
meta: {
|
|
||||||
correlation: {
|
|
||||||
userIdentifier: dto.email,
|
|
||||||
userIdentifierType: 'email',
|
|
||||||
},
|
|
||||||
origin: DomainEventService.SyncingServer,
|
|
||||||
},
|
|
||||||
payload: dto,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
DropboxBackupFailedEvent,
|
|
||||||
DuplicateItemSyncedEvent,
|
DuplicateItemSyncedEvent,
|
||||||
EmailArchiveExtensionSyncedEvent,
|
EmailArchiveExtensionSyncedEvent,
|
||||||
EmailBackupAttachmentCreatedEvent,
|
EmailRequestedEvent,
|
||||||
GoogleDriveBackupFailedEvent,
|
|
||||||
ItemDumpedEvent,
|
ItemDumpedEvent,
|
||||||
ItemRevisionCreationRequestedEvent,
|
ItemRevisionCreationRequestedEvent,
|
||||||
ItemsSyncedEvent,
|
ItemsSyncedEvent,
|
||||||
OneDriveBackupFailedEvent,
|
|
||||||
RevisionsCopyRequestedEvent,
|
RevisionsCopyRequestedEvent,
|
||||||
RevisionsOwnershipUpdateRequestedEvent,
|
RevisionsOwnershipUpdateRequestedEvent,
|
||||||
UserContentSizeRecalculationRequestedEvent,
|
UserContentSizeRecalculationRequestedEvent,
|
||||||
@@ -15,9 +12,20 @@ import {
|
|||||||
|
|
||||||
export interface DomainEventFactoryInterface {
|
export interface DomainEventFactoryInterface {
|
||||||
createUserContentSizeRecalculationRequestedEvent(userUuid: string): UserContentSizeRecalculationRequestedEvent
|
createUserContentSizeRecalculationRequestedEvent(userUuid: string): UserContentSizeRecalculationRequestedEvent
|
||||||
createDropboxBackupFailedEvent(muteCloudEmailsSettingUuid: string, email: string): DropboxBackupFailedEvent
|
createEmailRequestedEvent(dto: {
|
||||||
createGoogleDriveBackupFailedEvent(muteCloudEmailsSettingUuid: string, email: string): GoogleDriveBackupFailedEvent
|
userEmail: string
|
||||||
createOneDriveBackupFailedEvent(muteCloudEmailsSettingUuid: string, email: string): OneDriveBackupFailedEvent
|
messageIdentifier: string
|
||||||
|
level: string
|
||||||
|
body: string
|
||||||
|
subject: string
|
||||||
|
sender?: string
|
||||||
|
attachments?: Array<{
|
||||||
|
filePath: string
|
||||||
|
fileName: string
|
||||||
|
attachmentFileName: string
|
||||||
|
attachmentContentType: string
|
||||||
|
}>
|
||||||
|
}): EmailRequestedEvent
|
||||||
createItemsSyncedEvent(dto: {
|
createItemsSyncedEvent(dto: {
|
||||||
userUuid: string
|
userUuid: string
|
||||||
extensionUrl: string
|
extensionUrl: string
|
||||||
@@ -28,12 +36,6 @@ export interface DomainEventFactoryInterface {
|
|||||||
source: 'account-deletion' | 'realtime-extensions-sync'
|
source: 'account-deletion' | 'realtime-extensions-sync'
|
||||||
}): ItemsSyncedEvent
|
}): ItemsSyncedEvent
|
||||||
createEmailArchiveExtensionSyncedEvent(userUuid: string, extensionId: string): EmailArchiveExtensionSyncedEvent
|
createEmailArchiveExtensionSyncedEvent(userUuid: string, extensionId: string): EmailArchiveExtensionSyncedEvent
|
||||||
createEmailBackupAttachmentCreatedEvent(dto: {
|
|
||||||
backupFileName: string
|
|
||||||
backupFileIndex: number
|
|
||||||
backupFilesTotal: number
|
|
||||||
email: string
|
|
||||||
}): EmailBackupAttachmentCreatedEvent
|
|
||||||
createDuplicateItemSyncedEvent(itemUuid: string, userUuid: string): DuplicateItemSyncedEvent
|
createDuplicateItemSyncedEvent(itemUuid: string, userUuid: string): DuplicateItemSyncedEvent
|
||||||
createItemRevisionCreationRequested(itemUuid: string, userUuid: string): ItemRevisionCreationRequestedEvent
|
createItemRevisionCreationRequested(itemUuid: string, userUuid: string): ItemRevisionCreationRequestedEvent
|
||||||
createItemDumpedEvent(fileDumpPath: string, userUuid: string): ItemDumpedEvent
|
createItemDumpedEvent(fileDumpPath: string, userUuid: string): ItemDumpedEvent
|
||||||
|
|||||||
@@ -50,9 +50,7 @@ describe('ExtensionsHttpService', () => {
|
|||||||
domainEventPublisher.publish = jest.fn()
|
domainEventPublisher.publish = jest.fn()
|
||||||
|
|
||||||
domainEventFactory = {} as jest.Mocked<DomainEventFactoryInterface>
|
domainEventFactory = {} as jest.Mocked<DomainEventFactoryInterface>
|
||||||
domainEventFactory.createDropboxBackupFailedEvent = jest.fn()
|
domainEventFactory.createEmailRequestedEvent = jest.fn()
|
||||||
domainEventFactory.createGoogleDriveBackupFailedEvent = jest.fn()
|
|
||||||
domainEventFactory.createOneDriveBackupFailedEvent = jest.fn()
|
|
||||||
|
|
||||||
contentDecoder = {} as jest.Mocked<ContentDecoderInterface>
|
contentDecoder = {} as jest.Mocked<ContentDecoderInterface>
|
||||||
contentDecoder.decode = jest.fn().mockReturnValue({ name: 'Dropbox' })
|
contentDecoder.decode = jest.fn().mockReturnValue({ name: 'Dropbox' })
|
||||||
@@ -65,7 +63,6 @@ describe('ExtensionsHttpService', () => {
|
|||||||
forceMute: false,
|
forceMute: false,
|
||||||
backupFilename: 'test',
|
backupFilename: 'test',
|
||||||
authParams,
|
authParams,
|
||||||
muteEmailsSettingUuid: '3-4-5',
|
|
||||||
cloudProvider: 'DROPBOX',
|
cloudProvider: 'DROPBOX',
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -73,7 +70,6 @@ describe('ExtensionsHttpService', () => {
|
|||||||
data: {
|
data: {
|
||||||
auth_params: authParams,
|
auth_params: authParams,
|
||||||
backup_filename: 'test',
|
backup_filename: 'test',
|
||||||
settings_id: '3-4-5',
|
|
||||||
silent: false,
|
silent: false,
|
||||||
user_uuid: '1-2-3',
|
user_uuid: '1-2-3',
|
||||||
},
|
},
|
||||||
@@ -99,12 +95,11 @@ describe('ExtensionsHttpService', () => {
|
|||||||
forceMute: false,
|
forceMute: false,
|
||||||
backupFilename: 'test',
|
backupFilename: 'test',
|
||||||
authParams,
|
authParams,
|
||||||
muteEmailsSettingUuid: '3-4-5',
|
|
||||||
cloudProvider: 'DROPBOX',
|
cloudProvider: 'DROPBOX',
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||||
expect(domainEventFactory.createDropboxBackupFailedEvent).toHaveBeenCalled()
|
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should send items to extensions server', async () => {
|
it('should send items to extensions server', async () => {
|
||||||
@@ -116,7 +111,6 @@ describe('ExtensionsHttpService', () => {
|
|||||||
items: [item],
|
items: [item],
|
||||||
backupFilename: '',
|
backupFilename: '',
|
||||||
authParams,
|
authParams,
|
||||||
muteEmailsSettingUuid: '3-4-5',
|
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(httpClient.request).toHaveBeenCalledWith({
|
expect(httpClient.request).toHaveBeenCalledWith({
|
||||||
@@ -124,7 +118,6 @@ describe('ExtensionsHttpService', () => {
|
|||||||
auth_params: authParams,
|
auth_params: authParams,
|
||||||
backup_filename: '',
|
backup_filename: '',
|
||||||
items: [item],
|
items: [item],
|
||||||
settings_id: '3-4-5',
|
|
||||||
silent: false,
|
silent: false,
|
||||||
user_uuid: '1-2-3',
|
user_uuid: '1-2-3',
|
||||||
},
|
},
|
||||||
@@ -145,14 +138,12 @@ describe('ExtensionsHttpService', () => {
|
|||||||
forceMute: false,
|
forceMute: false,
|
||||||
backupFilename: 'backup-file',
|
backupFilename: 'backup-file',
|
||||||
authParams,
|
authParams,
|
||||||
muteEmailsSettingUuid: '3-4-5',
|
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(httpClient.request).toHaveBeenCalledWith({
|
expect(httpClient.request).toHaveBeenCalledWith({
|
||||||
data: {
|
data: {
|
||||||
auth_params: authParams,
|
auth_params: authParams,
|
||||||
backup_filename: 'backup-file',
|
backup_filename: 'backup-file',
|
||||||
settings_id: '3-4-5',
|
|
||||||
silent: false,
|
silent: false,
|
||||||
user_uuid: '1-2-3',
|
user_uuid: '1-2-3',
|
||||||
},
|
},
|
||||||
@@ -180,11 +171,10 @@ describe('ExtensionsHttpService', () => {
|
|||||||
items: [item],
|
items: [item],
|
||||||
backupFilename: 'backup-file',
|
backupFilename: 'backup-file',
|
||||||
authParams,
|
authParams,
|
||||||
muteEmailsSettingUuid: '3-4-5',
|
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||||
expect(domainEventFactory.createDropboxBackupFailedEvent).toHaveBeenCalled()
|
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should publish a failed Dropbox backup event if request was sent and extensions server responded not ok', async () => {
|
it('should publish a failed Dropbox backup event if request was sent and extensions server responded not ok', async () => {
|
||||||
@@ -200,11 +190,10 @@ describe('ExtensionsHttpService', () => {
|
|||||||
items: [item],
|
items: [item],
|
||||||
backupFilename: 'backup-file',
|
backupFilename: 'backup-file',
|
||||||
authParams,
|
authParams,
|
||||||
muteEmailsSettingUuid: '3-4-5',
|
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||||
expect(domainEventFactory.createDropboxBackupFailedEvent).toHaveBeenCalled()
|
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should publish a failed Google Drive backup event if request was not sent successfully', async () => {
|
it('should publish a failed Google Drive backup event if request was not sent successfully', async () => {
|
||||||
@@ -222,11 +211,10 @@ describe('ExtensionsHttpService', () => {
|
|||||||
items: [item],
|
items: [item],
|
||||||
backupFilename: 'backup-file',
|
backupFilename: 'backup-file',
|
||||||
authParams,
|
authParams,
|
||||||
muteEmailsSettingUuid: '3-4-5',
|
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||||
expect(domainEventFactory.createGoogleDriveBackupFailedEvent).toHaveBeenCalled()
|
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should publish a failed One Drive backup event if request was not sent successfully', async () => {
|
it('should publish a failed One Drive backup event if request was not sent successfully', async () => {
|
||||||
@@ -244,11 +232,10 @@ describe('ExtensionsHttpService', () => {
|
|||||||
items: [item],
|
items: [item],
|
||||||
backupFilename: 'backup-file',
|
backupFilename: 'backup-file',
|
||||||
authParams,
|
authParams,
|
||||||
muteEmailsSettingUuid: '3-4-5',
|
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||||
expect(domainEventFactory.createOneDriveBackupFailedEvent).toHaveBeenCalled()
|
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not publish a failed backup event if emailes are force muted', async () => {
|
it('should not publish a failed backup event if emailes are force muted', async () => {
|
||||||
@@ -266,7 +253,6 @@ describe('ExtensionsHttpService', () => {
|
|||||||
items: [item],
|
items: [item],
|
||||||
backupFilename: 'backup-file',
|
backupFilename: 'backup-file',
|
||||||
authParams,
|
authParams,
|
||||||
muteEmailsSettingUuid: '3-4-5',
|
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||||
@@ -289,7 +275,6 @@ describe('ExtensionsHttpService', () => {
|
|||||||
items: [item],
|
items: [item],
|
||||||
backupFilename: 'backup-file',
|
backupFilename: 'backup-file',
|
||||||
authParams,
|
authParams,
|
||||||
muteEmailsSettingUuid: '3-4-5',
|
|
||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = e
|
error = e
|
||||||
@@ -316,7 +301,6 @@ describe('ExtensionsHttpService', () => {
|
|||||||
items: [item],
|
items: [item],
|
||||||
backupFilename: 'backup-file',
|
backupFilename: 'backup-file',
|
||||||
authParams,
|
authParams,
|
||||||
muteEmailsSettingUuid: '3-4-5',
|
|
||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = e
|
error = e
|
||||||
@@ -340,11 +324,10 @@ describe('ExtensionsHttpService', () => {
|
|||||||
items: [item],
|
items: [item],
|
||||||
backupFilename: 'backup-file',
|
backupFilename: 'backup-file',
|
||||||
authParams,
|
authParams,
|
||||||
muteEmailsSettingUuid: '3-4-5',
|
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||||
expect(domainEventFactory.createDropboxBackupFailedEvent).toHaveBeenCalled()
|
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should publish a failed Google Drive backup event judging by extension url if request was not sent successfully', async () => {
|
it('should publish a failed Google Drive backup event judging by extension url if request was not sent successfully', async () => {
|
||||||
@@ -362,11 +345,10 @@ describe('ExtensionsHttpService', () => {
|
|||||||
items: [item],
|
items: [item],
|
||||||
backupFilename: 'backup-file',
|
backupFilename: 'backup-file',
|
||||||
authParams,
|
authParams,
|
||||||
muteEmailsSettingUuid: '3-4-5',
|
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||||
expect(domainEventFactory.createGoogleDriveBackupFailedEvent).toHaveBeenCalled()
|
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should publish a failed One Drive backup event judging by extension url if request was not sent successfully', async () => {
|
it('should publish a failed One Drive backup event judging by extension url if request was not sent successfully', async () => {
|
||||||
@@ -384,11 +366,10 @@ describe('ExtensionsHttpService', () => {
|
|||||||
items: [item],
|
items: [item],
|
||||||
backupFilename: 'backup-file',
|
backupFilename: 'backup-file',
|
||||||
authParams,
|
authParams,
|
||||||
muteEmailsSettingUuid: '3-4-5',
|
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||||
expect(domainEventFactory.createOneDriveBackupFailedEvent).toHaveBeenCalled()
|
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should throw an error if cannot deduce extension by judging from the url', async () => {
|
it('should throw an error if cannot deduce extension by judging from the url', async () => {
|
||||||
@@ -408,7 +389,6 @@ describe('ExtensionsHttpService', () => {
|
|||||||
items: [item],
|
items: [item],
|
||||||
backupFilename: 'backup-file',
|
backupFilename: 'backup-file',
|
||||||
authParams,
|
authParams,
|
||||||
muteEmailsSettingUuid: '3-4-5',
|
|
||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = e
|
error = e
|
||||||
@@ -434,7 +414,6 @@ describe('ExtensionsHttpService', () => {
|
|||||||
items: [item],
|
items: [item],
|
||||||
backupFilename: 'backup-file',
|
backupFilename: 'backup-file',
|
||||||
authParams,
|
authParams,
|
||||||
muteEmailsSettingUuid: '3-4-5',
|
|
||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = e
|
error = e
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { KeyParamsData } from '@standardnotes/responses'
|
import { KeyParamsData } from '@standardnotes/responses'
|
||||||
import { DomainEventInterface, DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
import { DomainEventInterface, DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
||||||
|
import { EmailLevel } from '@standardnotes/domain-core'
|
||||||
import { AxiosInstance } from 'axios'
|
import { AxiosInstance } from 'axios'
|
||||||
import { inject, injectable } from 'inversify'
|
import { inject, injectable } from 'inversify'
|
||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
@@ -10,6 +11,9 @@ import { ItemRepositoryInterface } from '../Item/ItemRepositoryInterface'
|
|||||||
import { ExtensionName } from './ExtensionName'
|
import { ExtensionName } from './ExtensionName'
|
||||||
import { ExtensionsHttpServiceInterface } from './ExtensionsHttpServiceInterface'
|
import { ExtensionsHttpServiceInterface } from './ExtensionsHttpServiceInterface'
|
||||||
import { SendItemsToExtensionsServerDTO } from './SendItemsToExtensionsServerDTO'
|
import { SendItemsToExtensionsServerDTO } from './SendItemsToExtensionsServerDTO'
|
||||||
|
import { getBody as googleDriveBody, getSubject as googleDriveSubject } from '../Email/GoogleDriveBackupFailed'
|
||||||
|
import { getBody as dropboxBody, getSubject as dropboxSubject } from '../Email/DropboxBackupFailed'
|
||||||
|
import { getBody as oneDriveBody, getSubject as oneDriveSubject } from '../Email/OneDriveBackupFailed'
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
|
export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
|
||||||
@@ -29,7 +33,6 @@ export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
|
|||||||
authParams: KeyParamsData
|
authParams: KeyParamsData
|
||||||
forceMute: boolean
|
forceMute: boolean
|
||||||
userUuid: string
|
userUuid: string
|
||||||
muteEmailsSettingUuid: string
|
|
||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
let sent = false
|
let sent = false
|
||||||
try {
|
try {
|
||||||
@@ -38,7 +41,6 @@ export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
|
|||||||
auth_params: dto.authParams,
|
auth_params: dto.authParams,
|
||||||
silent: dto.forceMute,
|
silent: dto.forceMute,
|
||||||
user_uuid: dto.userUuid,
|
user_uuid: dto.userUuid,
|
||||||
settings_id: dto.muteEmailsSettingUuid,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await this.httpClient.request({
|
const response = await this.httpClient.request({
|
||||||
@@ -58,13 +60,9 @@ export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
|
|||||||
this.logger.error(`[${dto.userUuid}] Failed to send a request to extensions server: ${(error as Error).message}`)
|
this.logger.error(`[${dto.userUuid}] Failed to send a request to extensions server: ${(error as Error).message}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sent && !dto.forceMute && dto.muteEmailsSettingUuid !== undefined) {
|
if (!sent && !dto.forceMute) {
|
||||||
await this.domainEventPublisher.publish(
|
await this.domainEventPublisher.publish(
|
||||||
this.createCloudBackupFailedEventBasedOnProvider(
|
this.createCloudBackupFailedEventBasedOnProvider(dto.cloudProvider, dto.authParams.identifier as string),
|
||||||
dto.cloudProvider,
|
|
||||||
dto.authParams.identifier as string,
|
|
||||||
dto.muteEmailsSettingUuid,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,7 +75,6 @@ export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
|
|||||||
auth_params: dto.authParams,
|
auth_params: dto.authParams,
|
||||||
silent: dto.forceMute,
|
silent: dto.forceMute,
|
||||||
user_uuid: dto.userUuid,
|
user_uuid: dto.userUuid,
|
||||||
settings_id: dto.muteEmailsSettingUuid,
|
|
||||||
}
|
}
|
||||||
if (dto.items !== undefined) {
|
if (dto.items !== undefined) {
|
||||||
payload.items = dto.items
|
payload.items = dto.items
|
||||||
@@ -100,14 +97,9 @@ export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
|
|||||||
this.logger.error(`[${dto.userUuid}] Failed to send a request to extensions server: ${(error as Error).message}`)
|
this.logger.error(`[${dto.userUuid}] Failed to send a request to extensions server: ${(error as Error).message}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sent && !dto.forceMute && dto.muteEmailsSettingUuid !== undefined) {
|
if (!sent && !dto.forceMute) {
|
||||||
await this.domainEventPublisher.publish(
|
await this.domainEventPublisher.publish(
|
||||||
await this.getBackupFailedEvent(
|
await this.getBackupFailedEvent(dto.extensionId, dto.userUuid, dto.authParams.identifier as string),
|
||||||
dto.muteEmailsSettingUuid,
|
|
||||||
dto.extensionId,
|
|
||||||
dto.userUuid,
|
|
||||||
dto.authParams.identifier as string,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -115,20 +107,36 @@ export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
|
|||||||
private createCloudBackupFailedEventBasedOnProvider(
|
private createCloudBackupFailedEventBasedOnProvider(
|
||||||
cloudProvider: 'DROPBOX' | 'GOOGLE_DRIVE' | 'ONE_DRIVE',
|
cloudProvider: 'DROPBOX' | 'GOOGLE_DRIVE' | 'ONE_DRIVE',
|
||||||
email: string,
|
email: string,
|
||||||
muteCloudEmailsSettingUuid: string,
|
|
||||||
): DomainEventInterface {
|
): DomainEventInterface {
|
||||||
switch (cloudProvider) {
|
switch (cloudProvider) {
|
||||||
case 'DROPBOX':
|
case 'DROPBOX':
|
||||||
return this.domainEventFactory.createDropboxBackupFailedEvent(muteCloudEmailsSettingUuid, email)
|
return this.domainEventFactory.createEmailRequestedEvent({
|
||||||
|
userEmail: email,
|
||||||
|
level: EmailLevel.LEVELS.FailedCloudBackup,
|
||||||
|
body: dropboxBody(),
|
||||||
|
messageIdentifier: 'FAILED_DROPBOX_BACKUP',
|
||||||
|
subject: dropboxSubject(),
|
||||||
|
})
|
||||||
case 'GOOGLE_DRIVE':
|
case 'GOOGLE_DRIVE':
|
||||||
return this.domainEventFactory.createGoogleDriveBackupFailedEvent(muteCloudEmailsSettingUuid, email)
|
return this.domainEventFactory.createEmailRequestedEvent({
|
||||||
|
userEmail: email,
|
||||||
|
level: EmailLevel.LEVELS.FailedCloudBackup,
|
||||||
|
body: googleDriveBody(),
|
||||||
|
messageIdentifier: 'FAILED_GOOGLE_DRIVE_BACKUP',
|
||||||
|
subject: googleDriveSubject(),
|
||||||
|
})
|
||||||
case 'ONE_DRIVE':
|
case 'ONE_DRIVE':
|
||||||
return this.domainEventFactory.createOneDriveBackupFailedEvent(muteCloudEmailsSettingUuid, email)
|
return this.domainEventFactory.createEmailRequestedEvent({
|
||||||
|
userEmail: email,
|
||||||
|
level: EmailLevel.LEVELS.FailedCloudBackup,
|
||||||
|
body: oneDriveBody(),
|
||||||
|
messageIdentifier: 'FAILED_ONE_DRIVE_BACKUP',
|
||||||
|
subject: oneDriveSubject(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getBackupFailedEvent(
|
private async getBackupFailedEvent(
|
||||||
muteCloudEmailsSettingUuid: string,
|
|
||||||
extensionId: string,
|
extensionId: string,
|
||||||
userUuid: string,
|
userUuid: string,
|
||||||
email: string,
|
email: string,
|
||||||
@@ -141,11 +149,11 @@ export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
|
|||||||
const content = this.contentDecoder.decode(extension.content)
|
const content = this.contentDecoder.decode(extension.content)
|
||||||
switch (this.getExtensionName(content)) {
|
switch (this.getExtensionName(content)) {
|
||||||
case ExtensionName.Dropbox:
|
case ExtensionName.Dropbox:
|
||||||
return this.createCloudBackupFailedEventBasedOnProvider('DROPBOX', muteCloudEmailsSettingUuid, email)
|
return this.createCloudBackupFailedEventBasedOnProvider('DROPBOX', email)
|
||||||
case ExtensionName.GoogleDrive:
|
case ExtensionName.GoogleDrive:
|
||||||
return this.createCloudBackupFailedEventBasedOnProvider('GOOGLE_DRIVE', muteCloudEmailsSettingUuid, email)
|
return this.createCloudBackupFailedEventBasedOnProvider('GOOGLE_DRIVE', email)
|
||||||
case ExtensionName.OneDrive:
|
case ExtensionName.OneDrive:
|
||||||
return this.createCloudBackupFailedEventBasedOnProvider('ONE_DRIVE', muteCloudEmailsSettingUuid, email)
|
return this.createCloudBackupFailedEventBasedOnProvider('ONE_DRIVE', email)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { KeyParamsData } from '@standardnotes/responses'
|
import { KeyParamsData } from '@standardnotes/responses'
|
||||||
|
|
||||||
import { Item } from '../Item/Item'
|
import { Item } from '../Item/Item'
|
||||||
|
|
||||||
export type SendItemsToExtensionsServerDTO = {
|
export type SendItemsToExtensionsServerDTO = {
|
||||||
@@ -8,6 +9,5 @@ export type SendItemsToExtensionsServerDTO = {
|
|||||||
authParams: KeyParamsData
|
authParams: KeyParamsData
|
||||||
forceMute: boolean
|
forceMute: boolean
|
||||||
userUuid: string
|
userUuid: string
|
||||||
muteEmailsSettingUuid?: string
|
|
||||||
items?: Array<Item>
|
items?: Array<Item>
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user