Compare commits

..

24 Commits

Author SHA1 Message Date
standardci
9c01fffca5 chore(release): publish new version
- @standardnotes/analytics@2.12.18
 - @standardnotes/api-gateway@1.39.22
 - @standardnotes/auth-server@1.66.4
 - @standardnotes/domain-events-infra@1.9.52
 - @standardnotes/domain-events@2.103.0
 - @standardnotes/event-store@1.6.49
 - @standardnotes/files-server@1.8.48
 - @standardnotes/revisions-server@1.9.21
 - @standardnotes/scheduler-server@1.15.2
 - @standardnotes/syncing-server@1.24.1
 - @standardnotes/websockets-server@1.4.49
 - @standardnotes/workspace-server@1.18.0
2022-12-09 13:32:57 +00:00
Karol Sójko
61c1cfff4b feat(workspace): replace workspace invite created event with email requested 2022-12-09 14:30:58 +01:00
standardci
7e74261f62 chore(release): publish new version
- @standardnotes/analytics@2.12.17
 - @standardnotes/api-gateway@1.39.21
 - @standardnotes/auth-server@1.66.3
 - @standardnotes/domain-events-infra@1.9.51
 - @standardnotes/domain-events@2.102.0
 - @standardnotes/event-store@1.6.48
 - @standardnotes/files-server@1.8.47
 - @standardnotes/revisions-server@1.9.20
 - @standardnotes/scheduler-server@1.15.1
 - @standardnotes/syncing-server@1.24.0
 - @standardnotes/websockets-server@1.4.48
 - @standardnotes/workspace-server@1.17.47
2022-12-09 13:11:30 +00:00
Karol Sójko
32601f34f1 feat(syncing-server): replace email backup attachment created with email requested 2022-12-09 14:09:30 +01:00
standardci
aef69a1a96 chore(release): publish new version
- @standardnotes/analytics@2.12.16
 - @standardnotes/api-gateway@1.39.20
 - @standardnotes/auth-server@1.66.2
 - @standardnotes/domain-events-infra@1.9.50
 - @standardnotes/domain-events@2.101.0
 - @standardnotes/event-store@1.6.47
 - @standardnotes/files-server@1.8.46
 - @standardnotes/revisions-server@1.9.19
 - @standardnotes/scheduler-server@1.15.0
 - @standardnotes/syncing-server@1.23.0
 - @standardnotes/websockets-server@1.4.47
 - @standardnotes/workspace-server@1.17.46
2022-12-09 10:22:39 +00:00
Karol Sójko
130f90bdb6 feat(syncing-server): replace one drive backup failed event with email requested 2022-12-09 11:20:34 +01:00
standardci
851c7de87f chore(release): publish new version
- @standardnotes/syncing-server@1.22.0
2022-12-09 09:35:39 +00:00
Karol Sójko
118156c62d feat(syncing-serfver): remove dropbox backup failed event in favour of email requested 2022-12-09 10:33:40 +01:00
standardci
cdad3143c9 chore(release): publish new version
- @standardnotes/analytics@2.12.15
 - @standardnotes/api-gateway@1.39.19
 - @standardnotes/auth-server@1.66.1
 - @standardnotes/domain-events-infra@1.9.49
 - @standardnotes/domain-events@2.100.0
 - @standardnotes/event-store@1.6.46
 - @standardnotes/files-server@1.8.45
 - @standardnotes/revisions-server@1.9.18
 - @standardnotes/scheduler-server@1.14.10
 - @standardnotes/syncing-server@1.21.0
 - @standardnotes/websockets-server@1.4.46
 - @standardnotes/workspace-server@1.17.45
2022-12-09 09:28:27 +00:00
Karol Sójko
00fe32136e feat(syncing-server): remove google drive backup failed event in favour of email requested 2022-12-09 10:26:13 +01:00
standardci
52f56eeb68 chore(release): publish new version
- @standardnotes/auth-server@1.66.0
2022-12-09 09:17:28 +00:00
Karol Sójko
b595264e31 feat(email): replace offline subscription token created event in favour of email requested 2022-12-09 10:15:33 +01:00
standardci
bf04262170 chore(release): publish new version
- @standardnotes/analytics@2.12.14
 - @standardnotes/api-gateway@1.39.18
 - @standardnotes/auth-server@1.65.0
 - @standardnotes/domain-events-infra@1.9.48
 - @standardnotes/domain-events@2.99.0
 - @standardnotes/event-store@1.6.45
 - @standardnotes/files-server@1.8.44
 - @standardnotes/revisions-server@1.9.17
 - @standardnotes/scheduler-server@1.14.9
 - @standardnotes/syncing-server@1.20.17
 - @standardnotes/websockets-server@1.4.45
 - @standardnotes/workspace-server@1.17.44
2022-12-09 09:03:31 +00:00
Karol Sójko
fd589922bb feat(auth): remove offline subscription token created event in favour of email requested 2022-12-09 10:01:38 +01:00
standardci
fb7029f5c1 chore(release): publish new version
- @standardnotes/analytics@2.12.13
 - @standardnotes/api-gateway@1.39.17
 - @standardnotes/auth-server@1.64.7
 - @standardnotes/domain-events-infra@1.9.47
 - @standardnotes/domain-events@2.98.4
 - @standardnotes/event-store@1.6.44
 - @standardnotes/files-server@1.8.43
 - @standardnotes/revisions-server@1.9.16
 - @standardnotes/scheduler-server@1.14.8
 - @standardnotes/syncing-server@1.20.16
 - @standardnotes/websockets-server@1.4.44
 - @standardnotes/workspace-server@1.17.43
2022-12-09 07:54:49 +00:00
Karol Sójko
cc4b4f9bf8 fix(domain-events): remove unused event 2022-12-09 08:52:51 +01:00
standardci
b048d6d7e3 chore(release): publish new version
- @standardnotes/analytics@2.12.12
 - @standardnotes/api-gateway@1.39.16
 - @standardnotes/auth-server@1.64.6
 - @standardnotes/domain-events-infra@1.9.46
 - @standardnotes/domain-events@2.98.3
 - @standardnotes/event-store@1.6.43
 - @standardnotes/files-server@1.8.42
 - @standardnotes/revisions-server@1.9.15
 - @standardnotes/scheduler-server@1.14.7
 - @standardnotes/syncing-server@1.20.15
 - @standardnotes/websockets-server@1.4.43
 - @standardnotes/workspace-server@1.17.42
2022-12-08 14:03:38 +00:00
Karol Sójko
cffc1f442f fix(domain-events): remove unused event 2022-12-08 15:01:44 +01:00
standardci
91fe710741 chore(release): publish new version
- @standardnotes/analytics@2.12.11
 - @standardnotes/api-gateway@1.39.15
 - @standardnotes/auth-server@1.64.5
 - @standardnotes/domain-events-infra@1.9.45
 - @standardnotes/domain-events@2.98.2
 - @standardnotes/event-store@1.6.42
 - @standardnotes/files-server@1.8.41
 - @standardnotes/revisions-server@1.9.14
 - @standardnotes/scheduler-server@1.14.6
 - @standardnotes/syncing-server@1.20.14
 - @standardnotes/websockets-server@1.4.42
 - @standardnotes/workspace-server@1.17.41
2022-12-08 13:55:05 +00:00
Karol Sójko
5a1eb9fdac fix(domain-events): remove unused event 2022-12-08 14:53:07 +01:00
standardci
a64ef6e750 chore(release): publish new version
- @standardnotes/analytics@2.12.10
 - @standardnotes/api-gateway@1.39.14
 - @standardnotes/auth-server@1.64.4
 - @standardnotes/domain-events-infra@1.9.44
 - @standardnotes/domain-events@2.98.1
 - @standardnotes/event-store@1.6.41
 - @standardnotes/files-server@1.8.40
 - @standardnotes/revisions-server@1.9.13
 - @standardnotes/scheduler-server@1.14.5
 - @standardnotes/syncing-server@1.20.13
 - @standardnotes/websockets-server@1.4.41
 - @standardnotes/workspace-server@1.17.40
2022-12-08 13:49:54 +00:00
Karol Sójko
47d2012b3d fix(domain-events): remove unused event 2022-12-08 14:47:39 +01:00
standardci
2c99cd2e21 chore(release): publish new version
- @standardnotes/analytics@2.12.9
 - @standardnotes/api-gateway@1.39.13
 - @standardnotes/auth-server@1.64.3
 - @standardnotes/domain-events-infra@1.9.43
 - @standardnotes/domain-events@2.98.0
 - @standardnotes/event-store@1.6.40
 - @standardnotes/files-server@1.8.39
 - @standardnotes/revisions-server@1.9.12
 - @standardnotes/scheduler-server@1.14.4
 - @standardnotes/syncing-server@1.20.12
 - @standardnotes/websockets-server@1.4.40
 - @standardnotes/workspace-server@1.17.39
2022-12-08 10:01:57 +00:00
Karol Sójko
435cd2f66a feat(domain-events): remove unused events and add attachments option for sending emails 2022-12-08 11:00:02 +01:00
94 changed files with 940 additions and 577 deletions

1
.pnp.cjs generated
View File

@@ -3324,6 +3324,7 @@ const RAW_RUNTIME_STATE =
["@sentry/node", "npm:7.19.0"],\
["@standardnotes/api", "npm:1.19.0"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
["@standardnotes/models", "npm:1.28.0"],\

View File

@@ -3,6 +3,46 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.12.18](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.12.17...@standardnotes/analytics@2.12.18) (2022-12-09)
**Note:** Version bump only for package @standardnotes/analytics
## [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

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/analytics",
"version": "2.12.8",
"version": "2.12.18",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -3,6 +3,46 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.22](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.39.21...@standardnotes/api-gateway@1.39.22) (2022-12-09)
**Note:** Version bump only for package @standardnotes/api-gateway
## [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

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/api-gateway",
"version": "1.39.12",
"version": "1.39.22",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -3,6 +3,54 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.66.4](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.66.3...@standardnotes/auth-server@1.66.4) (2022-12-09)
**Note:** Version bump only for package @standardnotes/auth-server
## [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

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/auth-server",
"version": "1.64.2",
"version": "1.66.4",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -5,11 +5,5 @@ export function getSubject(email: string): string {
}
export function getBody(email: string, device: string, browser: string, date: Date): string {
const body = html
return body
.replace('%%EMAIL%%', email)
.replace('%%DEVICE%%', device)
.replace('%%BROWSER%%', browser)
.replace('%%TIME_AND_DATE%%', date.toLocaleString())
return html(email, device, browser, date.toLocaleString())
}

View File

@@ -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>`

View File

@@ -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>`

View File

@@ -1,15 +1,15 @@
export const html = `
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>We've detected a new sign-in to your account ${email}</p>
<p>
<b>Device type</b>: %%DEVICE%%
<b>Device type</b>: ${device}
</p>
<p>
<b>Browser type</b>: %%BROWSER%%
<b>Browser type</b>: ${browser}
</p>
<p>
<strong>Time and date</strong>: <span>%%TIME_AND_DATE%%</span>
<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

View File

@@ -6,7 +6,6 @@ import {
UserEmailChangedEvent,
UserRegisteredEvent,
UserRolesChangedEvent,
OfflineSubscriptionTokenCreatedEvent,
EmailBackupRequestedEvent,
CloudBackupRequestedEvent,
ListedAccountRequestedEvent,
@@ -290,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: {
userUuid: string
email: string

View File

@@ -6,7 +6,6 @@ import {
UserRegisteredEvent,
UserRolesChangedEvent,
UserEmailChangedEvent,
OfflineSubscriptionTokenCreatedEvent,
EmailBackupRequestedEvent,
ListedAccountRequestedEvent,
UserDisabledSessionUserAgentLoggingEvent,
@@ -56,7 +55,6 @@ export interface DomainEventFactoryInterface {
}): AccountDeletionRequestedEvent
createUserRolesChangedEvent(userUuid: string, email: string, currentRoles: RoleName[]): UserRolesChangedEvent
createUserEmailChangedEvent(userUuid: string, fromEmail: string, toEmail: string): UserEmailChangedEvent
createOfflineSubscriptionTokenCreatedEvent(token: string, email: string): OfflineSubscriptionTokenCreatedEvent
createUserDisabledSessionUserAgentLoggingEvent(dto: {
userUuid: Uuid
email: string

View File

@@ -5,7 +5,7 @@ import { TimerInterface } from '@standardnotes/time'
import { OfflineSubscriptionTokenRepositoryInterface } from '../../Auth/OfflineSubscriptionTokenRepositoryInterface'
import { CreateOfflineSubscriptionToken } from './CreateOfflineSubscriptionToken'
import { DomainEventPublisherInterface, OfflineSubscriptionTokenCreatedEvent } from '@standardnotes/domain-events'
import { DomainEventPublisherInterface, EmailRequestedEvent } from '@standardnotes/domain-events'
import { DomainEventFactoryInterface } from '../../Event/DomainEventFactoryInterface'
import { OfflineUserSubscriptionRepositoryInterface } from '../../Subscription/OfflineUserSubscriptionRepositoryInterface'
import { OfflineUserSubscription } from '../../Subscription/OfflineUserSubscription'
@@ -47,9 +47,9 @@ describe('CreateOfflineSubscriptionToken', () => {
domainEventPublisher.publish = jest.fn()
domainEventFactory = {} as jest.Mocked<DomainEventFactoryInterface>
domainEventFactory.createOfflineSubscriptionTokenCreatedEvent = jest
domainEventFactory.createEmailRequestedEvent = jest
.fn()
.mockReturnValue({} as jest.Mocked<OfflineSubscriptionTokenCreatedEvent>)
.mockReturnValue({} as jest.Mocked<EmailRequestedEvent>)
timer = {} as jest.Mocked<TimerInterface>
timer.convertStringDateToMicroseconds = jest.fn().mockReturnValue(1)
@@ -71,10 +71,7 @@ describe('CreateOfflineSubscriptionToken', () => {
expiresAt: 1,
})
expect(domainEventFactory.createOfflineSubscriptionTokenCreatedEvent).toHaveBeenCalledWith(
'random-string',
'test@test.com',
)
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
expect(domainEventPublisher.publish).toHaveBeenCalled()
})
@@ -91,7 +88,7 @@ describe('CreateOfflineSubscriptionToken', () => {
})
expect(offlineSubscriptionTokenRepository.save).not.toHaveBeenCalled()
expect(domainEventFactory.createOfflineSubscriptionTokenCreatedEvent).not.toHaveBeenCalled()
expect(domainEventFactory.createEmailRequestedEvent).not.toHaveBeenCalled()
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
})
@@ -110,7 +107,7 @@ describe('CreateOfflineSubscriptionToken', () => {
})
expect(offlineSubscriptionTokenRepository.save).not.toHaveBeenCalled()
expect(domainEventFactory.createOfflineSubscriptionTokenCreatedEvent).not.toHaveBeenCalled()
expect(domainEventFactory.createEmailRequestedEvent).not.toHaveBeenCalled()
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
})
@@ -129,7 +126,7 @@ describe('CreateOfflineSubscriptionToken', () => {
})
expect(offlineSubscriptionTokenRepository.save).not.toHaveBeenCalled()
expect(domainEventFactory.createOfflineSubscriptionTokenCreatedEvent).not.toHaveBeenCalled()
expect(domainEventFactory.createEmailRequestedEvent).not.toHaveBeenCalled()
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
})
})

View File

@@ -1,4 +1,5 @@
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
import { EmailLevel } from '@standardnotes/domain-core'
import { CryptoNode } from '@standardnotes/sncrypto-node'
import { TimerInterface } from '@standardnotes/time'
import { inject, injectable } from 'inversify'
@@ -6,6 +7,7 @@ import { Logger } from 'winston'
import TYPES from '../../../Bootstrap/Types'
import { OfflineSubscriptionTokenRepositoryInterface } from '../../Auth/OfflineSubscriptionTokenRepositoryInterface'
import { getBody, getSubject } from '../../Email/OfflineSubscriptionTokenCreated'
import { DomainEventFactoryInterface } from '../../Event/DomainEventFactoryInterface'
import { OfflineUserSubscriptionRepositoryInterface } from '../../Subscription/OfflineUserSubscriptionRepositoryInterface'
import { UseCaseInterface } from '../UseCaseInterface'
@@ -62,7 +64,13 @@ export class CreateOfflineSubscriptionToken implements UseCaseInterface {
await this.offlineSubscriptionTokenRepository.save(offlineSubscriptionToken)
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 {

View File

@@ -1,6 +1,10 @@
import 'reflect-metadata'
import { DomainEventPublisherInterface, SharedSubscriptionInvitationCreatedEvent } from '@standardnotes/domain-events'
import {
DomainEventPublisherInterface,
SharedSubscriptionInvitationCreatedEvent,
EmailRequestedEvent,
} from '@standardnotes/domain-events'
import { TimerInterface } from '@standardnotes/time'
import { DomainEventFactoryInterface } from '../../Event/DomainEventFactoryInterface'
import { SharedSubscriptionInvitationRepositoryInterface } from '../../SharedSubscription/SharedSubscriptionInvitationRepositoryInterface'
@@ -51,6 +55,7 @@ describe('InviteToSharedSubscription', () => {
domainEventFactory.createSharedSubscriptionInvitationCreatedEvent = jest
.fn()
.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 () => {

View File

@@ -1,9 +1,11 @@
import { RoleName } from '@standardnotes/common'
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
import { EmailLevel } from '@standardnotes/domain-core'
import { TimerInterface } from '@standardnotes/time'
import { inject, injectable } from 'inversify'
import TYPES from '../../../Bootstrap/Types'
import { getBody, getSubject } from '../../Email/SharedSubscriptionInvitationCreated'
import { DomainEventFactoryInterface } from '../../Event/DomainEventFactoryInterface'
import { InvitationStatus } from '../../SharedSubscription/InvitationStatus'
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 {
success: true,
sharedSubscriptionInvitationUuid: savedInvitation.uuid,

View File

@@ -3,6 +3,46 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.9.52](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.51...@standardnotes/domain-events-infra@1.9.52) (2022-12-09)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [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

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/domain-events-infra",
"version": "1.9.42",
"version": "1.9.52",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -3,6 +3,66 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [2.103.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.102.0...@standardnotes/domain-events@2.103.0) (2022-12-09)
### Features
* **workspace:** replace workspace invite created event with email requested ([61c1cff](https://github.com/standardnotes/server/commit/61c1cfff4bcee09e1f933cb3e085412b6f07cc42))
# [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

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/domain-events",
"version": "2.97.0",
"version": "2.103.0",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -1,7 +0,0 @@
import { DomainEventInterface } from './DomainEventInterface'
import { AccountClaimRequestedEventPayload } from './AccountClaimRequestedEventPayload'
export interface AccountClaimRequestedEvent extends DomainEventInterface {
type: 'ACCOUNT_CLAIM_REQUESTED'
payload: AccountClaimRequestedEventPayload
}

View File

@@ -1,4 +0,0 @@
export interface AccountClaimRequestedEventPayload {
email: string
token: string
}

View File

@@ -1,7 +0,0 @@
import { DomainEventInterface } from './DomainEventInterface'
import { ActivationCodeRequestedEventPayload } from './ActivationCodeRequestedEventPayload'
export interface ActivationCodeRequestedEvent extends DomainEventInterface {
type: 'ACTIVATION_CODE_REQUESTED'
payload: ActivationCodeRequestedEventPayload
}

View File

@@ -1,4 +0,0 @@
export interface ActivationCodeRequestedEventPayload {
userEmail: string
offlineFeaturesToken: string
}

View File

@@ -1,8 +0,0 @@
import { DomainEventInterface } from './DomainEventInterface'
import { DiscountAppliedEventPayload } from './DiscountAppliedEventPayload'
export interface DiscountAppliedEvent extends DomainEventInterface {
type: 'DISCOUNT_APPLIED'
payload: DiscountAppliedEventPayload
}

View File

@@ -1,4 +0,0 @@
export interface DiscountAppliedEventPayload {
userEmail: string
discountRate: number
}

View File

@@ -1,8 +0,0 @@
import { DomainEventInterface } from './DomainEventInterface'
import { DropboxBackupFailedEventPayload } from './DropboxBackupFailedEventPayload'
export interface DropboxBackupFailedEvent extends DomainEventInterface {
type: 'DROPBOX_BACKUP_FAILED'
payload: DropboxBackupFailedEventPayload
}

View File

@@ -1,5 +0,0 @@
export interface DropboxBackupFailedEventPayload {
muteCloudEmailsSettingUuid: string
extensionSettingUuid?: string
email: string
}

View File

@@ -1,7 +0,0 @@
import { DomainEventInterface } from './DomainEventInterface'
import { EmailBackupAttachmentCreatedEventPayload } from './EmailBackupAttachmentCreatedEventPayload'
export interface EmailBackupAttachmentCreatedEvent extends DomainEventInterface {
type: 'EMAIL_BACKUP_ATTACHMENT_CREATED'
payload: EmailBackupAttachmentCreatedEventPayload
}

View File

@@ -1,6 +0,0 @@
export interface EmailBackupAttachmentCreatedEventPayload {
backupFileName: string
backupFileIndex: number
backupFilesTotal: number
email: string
}

View File

@@ -4,4 +4,11 @@ export interface EmailRequestedEventPayload {
level: string
subject: string
body: string
sender?: string
attachments?: Array<{
filePath: string
fileName: string
attachmentFileName: string
attachmentContentType: string
}>
}

View File

@@ -1,8 +0,0 @@
import { DomainEventInterface } from './DomainEventInterface'
import { GoogleDriveBackupFailedEventPayload } from './GoogleDriveBackupFailedEventPayload'
export interface GoogleDriveBackupFailedEvent extends DomainEventInterface {
type: 'GOOGLE_DRIVE_BACKUP_FAILED'
payload: GoogleDriveBackupFailedEventPayload
}

View File

@@ -1,5 +0,0 @@
export interface GoogleDriveBackupFailedEventPayload {
muteCloudEmailsSettingUuid: string
extensionSettingUuid?: string
email: string
}

View File

@@ -1,8 +0,0 @@
import { DomainEventInterface } from './DomainEventInterface'
import { InvoiceGeneratedEventPayload } from './InvoiceGeneratedEventPayload'
export interface InvoiceGeneratedEvent extends DomainEventInterface {
type: 'INVOICE_GENERATED'
payload: InvoiceGeneratedEventPayload
}

View File

@@ -1,7 +0,0 @@
export interface InvoiceGeneratedEventPayload {
userEmail: string
invoiceNumber: string
paymentDateFormatted: string
s3BucketName: string
s3InvoiceObjectKey: string
}

View File

@@ -1,8 +0,0 @@
import { DomainEventInterface } from './DomainEventInterface'
import { OfflineSubscriptionTokenCreatedEventPayload } from './OfflineSubscriptionTokenCreatedEventPayload'
export interface OfflineSubscriptionTokenCreatedEvent extends DomainEventInterface {
type: 'OFFLINE_SUBSCRIPTION_TOKEN_CREATED'
payload: OfflineSubscriptionTokenCreatedEventPayload
}

View File

@@ -1,4 +0,0 @@
export interface OfflineSubscriptionTokenCreatedEventPayload {
token: string
email: string
}

View File

@@ -1,8 +0,0 @@
import { DomainEventInterface } from './DomainEventInterface'
import { OneDriveBackupFailedEventPayload } from './OneDriveBackupFailedEventPayload'
export interface OneDriveBackupFailedEvent extends DomainEventInterface {
type: 'ONE_DRIVE_BACKUP_FAILED'
payload: OneDriveBackupFailedEventPayload
}

View File

@@ -1,5 +0,0 @@
export interface OneDriveBackupFailedEventPayload {
muteCloudEmailsSettingUuid: string
extensionSettingUuid?: string
email: string
}

View File

@@ -1,8 +0,0 @@
import { DomainEventInterface } from './DomainEventInterface'
import { RefundRequestedEventPayload } from './RefundRequestedEventPayload'
export interface RefundRequestedEvent extends DomainEventInterface {
type: 'REFUND_REQUESTED'
payload: RefundRequestedEventPayload
}

View File

@@ -1,4 +0,0 @@
export interface RefundRequestedEventPayload {
userEmail: string
refundProcessingLink: string
}

View File

@@ -1,8 +0,0 @@
import { DomainEventInterface } from './DomainEventInterface'
import { StudentDiscountApprovedEventPayload } from './StudentDiscountApprovedEventPayload'
export interface StudentDiscountApprovedEvent extends DomainEventInterface {
type: 'STUDENT_DISCOUNT_APPROVED'
payload: StudentDiscountApprovedEventPayload
}

View File

@@ -1,3 +0,0 @@
export interface StudentDiscountApprovedEventPayload {
userEmail: string
}

View File

@@ -1,8 +0,0 @@
import { DomainEventInterface } from './DomainEventInterface'
import { StudentDiscountRequestedEventPayload } from './StudentDiscountRequestedEventPayload'
export interface StudentDiscountRequestedEvent extends DomainEventInterface {
type: 'STUDENT_DISCOUNT_REQUESTED'
payload: StudentDiscountRequestedEventPayload
}

View File

@@ -1,5 +0,0 @@
export interface StudentDiscountRequestedEventPayload {
studentEmail: string
userEmail: string
adminApprovalLink: string
}

View File

@@ -1,8 +0,0 @@
import { DomainEventInterface } from './DomainEventInterface'
import { SubscriptionRateAdjustedEventPayload } from './SubscriptionRateAdjustedEventPayload'
export interface SubscriptionRateAdjustedEvent extends DomainEventInterface {
type: 'SUBSCRIPTION_RATE_ADJUSTED'
payload: SubscriptionRateAdjustedEventPayload
}

View File

@@ -1,5 +0,0 @@
export interface SubscriptionRateAdjustedEventPayload {
userEmail: string
newRateFormatted: string
refundAmountInDollarsFormatted: string
}

View File

@@ -1,7 +0,0 @@
import { DomainEventInterface } from './DomainEventInterface'
import { WorkspaceInviteCreatedEventPayload } from './WorkspaceInviteCreatedEventPayload'
export interface WorkspaceInviteCreatedEvent extends DomainEventInterface {
type: 'WORKSPACE_INVITE_CREATED'
payload: WorkspaceInviteCreatedEventPayload
}

View File

@@ -1,6 +0,0 @@
export interface WorkspaceInviteCreatedEventPayload {
inviterUuid: string
inviteeEmail: string
inviteUuid: string
workspaceUuid: string
}

View File

@@ -1,29 +1,19 @@
export * from './Event/AccountClaimRequestedEvent'
export * from './Event/AccountClaimRequestedEventPayload'
export * from './Event/AccountDeletionRequestedEvent'
export * from './Event/AccountDeletionRequestedEventPayload'
export * from './Event/ActivationCodeRequestedEvent'
export * from './Event/ActivationCodeRequestedEventPayload'
export * from './Event/CloudBackupRequestedEvent'
export * from './Event/CloudBackupRequestedEventPayload'
export * from './Event/DailyAnalyticsReportGeneratedEvent'
export * from './Event/DailyAnalyticsReportGeneratedEventPayload'
export * from './Event/DiscountAppliedEvent'
export * from './Event/DiscountAppliedEventPayload'
export * from './Event/DiscountApplyRequestedEvent'
export * from './Event/DiscountApplyRequestedEventPayload'
export * from './Event/DiscountWithdrawRequestedEvent'
export * from './Event/DiscountWithdrawRequestedEventPayload'
export * from './Event/DomainEventInterface'
export * from './Event/DomainEventService'
export * from './Event/DropboxBackupFailedEvent'
export * from './Event/DropboxBackupFailedEventPayload'
export * from './Event/DuplicateItemSyncedEvent'
export * from './Event/DuplicateItemSyncedEventPayload'
export * from './Event/EmailArchiveExtensionSyncedEvent'
export * from './Event/EmailArchiveExtensionSyncedEventPayload'
export * from './Event/EmailBackupAttachmentCreatedEvent'
export * from './Event/EmailBackupAttachmentCreatedEventPayload'
export * from './Event/EmailBackupRequestedEvent'
export * from './Event/EmailBackupRequestedEventPayload'
export * from './Event/EmailRequestedEvent'
@@ -40,10 +30,6 @@ export * from './Event/FileRemovedEvent'
export * from './Event/FileRemovedEventPayload'
export * from './Event/FileUploadedEvent'
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/ItemDumpedEventPayload'
export * from './Event/ItemRevisionCreationRequestedEvent'
@@ -58,10 +44,6 @@ export * from './Event/ListedAccountRequestedEvent'
export * from './Event/ListedAccountRequestedEventPayload'
export * from './Event/MuteEmailsSettingChangedEvent'
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/PaymentFailedEventPayload'
export * from './Event/PaymentSuccessEvent'
@@ -70,8 +52,6 @@ export * from './Event/PredicateVerificationRequestedEvent'
export * from './Event/PredicateVerificationRequestedEventPayload'
export * from './Event/PredicateVerifiedEvent'
export * from './Event/PredicateVerifiedEventPayload'
export * from './Event/RefundRequestedEvent'
export * from './Event/RefundRequestedEventPayload'
export * from './Event/RefundProcessedEvent'
export * from './Event/RefundProcessedEventPayload'
export * from './Event/RevisionsCopyRequestedEvent'
@@ -82,16 +62,10 @@ export * from './Event/SharedSubscriptionInvitationCanceledEvent'
export * from './Event/SharedSubscriptionInvitationCanceledEventPayload'
export * from './Event/SharedSubscriptionInvitationCreatedEvent'
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/SubscriptionCancelledEventPayload'
export * from './Event/SubscriptionPurchasedEvent'
export * from './Event/SubscriptionPurchasedEventPayload'
export * from './Event/SubscriptionRateAdjustedEvent'
export * from './Event/SubscriptionRateAdjustedEventPayload'
export * from './Event/SubscriptionReactivatedEvent'
export * from './Event/SubscriptionReactivatedEventPayload'
export * from './Event/SubscriptionReassignedEvent'
@@ -120,8 +94,6 @@ export * from './Event/WebSocketMessageRequestedEvent'
export * from './Event/WebSocketMessageRequestedEventPayload'
export * from './Event/WorkspaceInviteAcceptedEvent'
export * from './Event/WorkspaceInviteAcceptedEventPayload'
export * from './Event/WorkspaceInviteCreatedEvent'
export * from './Event/WorkspaceInviteCreatedEventPayload'
export * from './Handler/DomainEventHandlerInterface'
export * from './Handler/DomainEventMessageHandlerInterface'

View File

@@ -3,6 +3,46 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.6.49](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.48...@standardnotes/event-store@1.6.49) (2022-12-09)
**Note:** Version bump only for package @standardnotes/event-store
## [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

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/event-store",
"version": "1.6.39",
"version": "1.6.49",
"description": "Event Store Service",
"private": true,
"main": "dist/src/index.js",

View File

@@ -3,6 +3,46 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.8.48](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.47...@standardnotes/files-server@1.8.48) (2022-12-09)
**Note:** Version bump only for package @standardnotes/files-server
## [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

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/files-server",
"version": "1.8.38",
"version": "1.8.48",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -3,6 +3,46 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.9.21](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.9.20...@standardnotes/revisions-server@1.9.21) (2022-12-09)
**Note:** Version bump only for package @standardnotes/revisions-server
## [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

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/revisions-server",
"version": "1.9.11",
"version": "1.9.21",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -3,6 +3,48 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.15.2](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.15.1...@standardnotes/scheduler-server@1.15.2) (2022-12-09)
**Note:** Version bump only for package @standardnotes/scheduler-server
## [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

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/scheduler-server",
"version": "1.14.3",
"version": "1.15.2",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -2,7 +2,7 @@ import {
DiscountApplyRequestedEvent,
DiscountWithdrawRequestedEvent,
DomainEventPublisherInterface,
EmailMessageRequestedEvent,
EmailRequestedEvent,
ExitDiscountWithdrawRequestedEvent,
} from '@standardnotes/domain-events'
import { PredicateName } from '@standardnotes/predicates'
@@ -45,9 +45,7 @@ describe('JobDoneInterpreter', () => {
predicateRepository.findByJobUuid = jest.fn().mockReturnValue([])
domainEventFactory = {} as jest.Mocked<DomainEventFactoryInterface>
domainEventFactory.createEmailRequestedEvent = jest
.fn()
.mockReturnValue({} as jest.Mocked<EmailMessageRequestedEvent>)
domainEventFactory.createEmailRequestedEvent = jest.fn().mockReturnValue({} as jest.Mocked<EmailRequestedEvent>)
domainEventFactory.createDiscountApplyRequestedEvent = jest
.fn()
.mockReturnValue({} as jest.Mocked<DiscountApplyRequestedEvent>)

View File

@@ -3,6 +3,58 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.24.1](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.24.0...@standardnotes/syncing-server@1.24.1) (2022-12-09)
**Note:** Version bump only for package @standardnotes/syncing-server
# [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

View File

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

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/syncing-server",
"version": "1.20.11",
"version": "1.24.1",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -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
}

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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>`

View File

@@ -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>
`

View File

@@ -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>`

View File

@@ -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>`

View File

@@ -1,15 +1,12 @@
/* istanbul ignore file */
import {
DomainEventService,
DropboxBackupFailedEvent,
DuplicateItemSyncedEvent,
EmailArchiveExtensionSyncedEvent,
EmailBackupAttachmentCreatedEvent,
GoogleDriveBackupFailedEvent,
EmailRequestedEvent,
ItemDumpedEvent,
ItemRevisionCreationRequestedEvent,
ItemsSyncedEvent,
OneDriveBackupFailedEvent,
RevisionsCopyRequestedEvent,
RevisionsOwnershipUpdateRequestedEvent,
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 {
type: 'DROPBOX_BACKUP_FAILED',
type: 'EMAIL_REQUESTED',
createdAt: this.timer.getUTCDate(),
meta: {
correlation: {
userIdentifier: email,
userIdentifier: dto.userEmail,
userIdentifierType: 'email',
},
origin: DomainEventService.SyncingServer,
},
payload: {
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,
},
payload: dto,
}
}
@@ -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,
}
}
}

View File

@@ -1,13 +1,10 @@
import {
DropboxBackupFailedEvent,
DuplicateItemSyncedEvent,
EmailArchiveExtensionSyncedEvent,
EmailBackupAttachmentCreatedEvent,
GoogleDriveBackupFailedEvent,
EmailRequestedEvent,
ItemDumpedEvent,
ItemRevisionCreationRequestedEvent,
ItemsSyncedEvent,
OneDriveBackupFailedEvent,
RevisionsCopyRequestedEvent,
RevisionsOwnershipUpdateRequestedEvent,
UserContentSizeRecalculationRequestedEvent,
@@ -15,9 +12,20 @@ import {
export interface DomainEventFactoryInterface {
createUserContentSizeRecalculationRequestedEvent(userUuid: string): UserContentSizeRecalculationRequestedEvent
createDropboxBackupFailedEvent(muteCloudEmailsSettingUuid: string, email: string): DropboxBackupFailedEvent
createGoogleDriveBackupFailedEvent(muteCloudEmailsSettingUuid: string, email: string): GoogleDriveBackupFailedEvent
createOneDriveBackupFailedEvent(muteCloudEmailsSettingUuid: string, email: string): OneDriveBackupFailedEvent
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
createItemsSyncedEvent(dto: {
userUuid: string
extensionUrl: string
@@ -28,12 +36,6 @@ export interface DomainEventFactoryInterface {
source: 'account-deletion' | 'realtime-extensions-sync'
}): ItemsSyncedEvent
createEmailArchiveExtensionSyncedEvent(userUuid: string, extensionId: string): EmailArchiveExtensionSyncedEvent
createEmailBackupAttachmentCreatedEvent(dto: {
backupFileName: string
backupFileIndex: number
backupFilesTotal: number
email: string
}): EmailBackupAttachmentCreatedEvent
createDuplicateItemSyncedEvent(itemUuid: string, userUuid: string): DuplicateItemSyncedEvent
createItemRevisionCreationRequested(itemUuid: string, userUuid: string): ItemRevisionCreationRequestedEvent
createItemDumpedEvent(fileDumpPath: string, userUuid: string): ItemDumpedEvent

View File

@@ -50,9 +50,7 @@ describe('ExtensionsHttpService', () => {
domainEventPublisher.publish = jest.fn()
domainEventFactory = {} as jest.Mocked<DomainEventFactoryInterface>
domainEventFactory.createDropboxBackupFailedEvent = jest.fn()
domainEventFactory.createGoogleDriveBackupFailedEvent = jest.fn()
domainEventFactory.createOneDriveBackupFailedEvent = jest.fn()
domainEventFactory.createEmailRequestedEvent = jest.fn()
contentDecoder = {} as jest.Mocked<ContentDecoderInterface>
contentDecoder.decode = jest.fn().mockReturnValue({ name: 'Dropbox' })
@@ -65,7 +63,6 @@ describe('ExtensionsHttpService', () => {
forceMute: false,
backupFilename: 'test',
authParams,
muteEmailsSettingUuid: '3-4-5',
cloudProvider: 'DROPBOX',
})
@@ -73,7 +70,6 @@ describe('ExtensionsHttpService', () => {
data: {
auth_params: authParams,
backup_filename: 'test',
settings_id: '3-4-5',
silent: false,
user_uuid: '1-2-3',
},
@@ -99,12 +95,11 @@ describe('ExtensionsHttpService', () => {
forceMute: false,
backupFilename: 'test',
authParams,
muteEmailsSettingUuid: '3-4-5',
cloudProvider: 'DROPBOX',
})
expect(domainEventPublisher.publish).toHaveBeenCalled()
expect(domainEventFactory.createDropboxBackupFailedEvent).toHaveBeenCalled()
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
})
it('should send items to extensions server', async () => {
@@ -116,7 +111,6 @@ describe('ExtensionsHttpService', () => {
items: [item],
backupFilename: '',
authParams,
muteEmailsSettingUuid: '3-4-5',
})
expect(httpClient.request).toHaveBeenCalledWith({
@@ -124,7 +118,6 @@ describe('ExtensionsHttpService', () => {
auth_params: authParams,
backup_filename: '',
items: [item],
settings_id: '3-4-5',
silent: false,
user_uuid: '1-2-3',
},
@@ -145,14 +138,12 @@ describe('ExtensionsHttpService', () => {
forceMute: false,
backupFilename: 'backup-file',
authParams,
muteEmailsSettingUuid: '3-4-5',
})
expect(httpClient.request).toHaveBeenCalledWith({
data: {
auth_params: authParams,
backup_filename: 'backup-file',
settings_id: '3-4-5',
silent: false,
user_uuid: '1-2-3',
},
@@ -180,11 +171,10 @@ describe('ExtensionsHttpService', () => {
items: [item],
backupFilename: 'backup-file',
authParams,
muteEmailsSettingUuid: '3-4-5',
})
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 () => {
@@ -200,11 +190,10 @@ describe('ExtensionsHttpService', () => {
items: [item],
backupFilename: 'backup-file',
authParams,
muteEmailsSettingUuid: '3-4-5',
})
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 () => {
@@ -222,11 +211,10 @@ describe('ExtensionsHttpService', () => {
items: [item],
backupFilename: 'backup-file',
authParams,
muteEmailsSettingUuid: '3-4-5',
})
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 () => {
@@ -244,11 +232,10 @@ describe('ExtensionsHttpService', () => {
items: [item],
backupFilename: 'backup-file',
authParams,
muteEmailsSettingUuid: '3-4-5',
})
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 () => {
@@ -266,7 +253,6 @@ describe('ExtensionsHttpService', () => {
items: [item],
backupFilename: 'backup-file',
authParams,
muteEmailsSettingUuid: '3-4-5',
})
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
@@ -289,7 +275,6 @@ describe('ExtensionsHttpService', () => {
items: [item],
backupFilename: 'backup-file',
authParams,
muteEmailsSettingUuid: '3-4-5',
})
} catch (e) {
error = e
@@ -316,7 +301,6 @@ describe('ExtensionsHttpService', () => {
items: [item],
backupFilename: 'backup-file',
authParams,
muteEmailsSettingUuid: '3-4-5',
})
} catch (e) {
error = e
@@ -340,11 +324,10 @@ describe('ExtensionsHttpService', () => {
items: [item],
backupFilename: 'backup-file',
authParams,
muteEmailsSettingUuid: '3-4-5',
})
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 () => {
@@ -362,11 +345,10 @@ describe('ExtensionsHttpService', () => {
items: [item],
backupFilename: 'backup-file',
authParams,
muteEmailsSettingUuid: '3-4-5',
})
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 () => {
@@ -384,11 +366,10 @@ describe('ExtensionsHttpService', () => {
items: [item],
backupFilename: 'backup-file',
authParams,
muteEmailsSettingUuid: '3-4-5',
})
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 () => {
@@ -408,7 +389,6 @@ describe('ExtensionsHttpService', () => {
items: [item],
backupFilename: 'backup-file',
authParams,
muteEmailsSettingUuid: '3-4-5',
})
} catch (e) {
error = e
@@ -434,7 +414,6 @@ describe('ExtensionsHttpService', () => {
items: [item],
backupFilename: 'backup-file',
authParams,
muteEmailsSettingUuid: '3-4-5',
})
} catch (e) {
error = e

View File

@@ -1,5 +1,6 @@
import { KeyParamsData } from '@standardnotes/responses'
import { DomainEventInterface, DomainEventPublisherInterface } from '@standardnotes/domain-events'
import { EmailLevel } from '@standardnotes/domain-core'
import { AxiosInstance } from 'axios'
import { inject, injectable } from 'inversify'
import { Logger } from 'winston'
@@ -10,6 +11,9 @@ import { ItemRepositoryInterface } from '../Item/ItemRepositoryInterface'
import { ExtensionName } from './ExtensionName'
import { ExtensionsHttpServiceInterface } from './ExtensionsHttpServiceInterface'
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()
export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
@@ -29,7 +33,6 @@ export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
authParams: KeyParamsData
forceMute: boolean
userUuid: string
muteEmailsSettingUuid: string
}): Promise<void> {
let sent = false
try {
@@ -38,7 +41,6 @@ export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
auth_params: dto.authParams,
silent: dto.forceMute,
user_uuid: dto.userUuid,
settings_id: dto.muteEmailsSettingUuid,
}
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}`)
}
if (!sent && !dto.forceMute && dto.muteEmailsSettingUuid !== undefined) {
if (!sent && !dto.forceMute) {
await this.domainEventPublisher.publish(
this.createCloudBackupFailedEventBasedOnProvider(
dto.cloudProvider,
dto.authParams.identifier as string,
dto.muteEmailsSettingUuid,
),
this.createCloudBackupFailedEventBasedOnProvider(dto.cloudProvider, dto.authParams.identifier as string),
)
}
}
@@ -77,7 +75,6 @@ export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
auth_params: dto.authParams,
silent: dto.forceMute,
user_uuid: dto.userUuid,
settings_id: dto.muteEmailsSettingUuid,
}
if (dto.items !== undefined) {
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}`)
}
if (!sent && !dto.forceMute && dto.muteEmailsSettingUuid !== undefined) {
if (!sent && !dto.forceMute) {
await this.domainEventPublisher.publish(
await this.getBackupFailedEvent(
dto.muteEmailsSettingUuid,
dto.extensionId,
dto.userUuid,
dto.authParams.identifier as string,
),
await this.getBackupFailedEvent(dto.extensionId, dto.userUuid, dto.authParams.identifier as string),
)
}
}
@@ -115,20 +107,36 @@ export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
private createCloudBackupFailedEventBasedOnProvider(
cloudProvider: 'DROPBOX' | 'GOOGLE_DRIVE' | 'ONE_DRIVE',
email: string,
muteCloudEmailsSettingUuid: string,
): DomainEventInterface {
switch (cloudProvider) {
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':
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':
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(
muteCloudEmailsSettingUuid: string,
extensionId: string,
userUuid: string,
email: string,
@@ -141,11 +149,11 @@ export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
const content = this.contentDecoder.decode(extension.content)
switch (this.getExtensionName(content)) {
case ExtensionName.Dropbox:
return this.createCloudBackupFailedEventBasedOnProvider('DROPBOX', muteCloudEmailsSettingUuid, email)
return this.createCloudBackupFailedEventBasedOnProvider('DROPBOX', email)
case ExtensionName.GoogleDrive:
return this.createCloudBackupFailedEventBasedOnProvider('GOOGLE_DRIVE', muteCloudEmailsSettingUuid, email)
return this.createCloudBackupFailedEventBasedOnProvider('GOOGLE_DRIVE', email)
case ExtensionName.OneDrive:
return this.createCloudBackupFailedEventBasedOnProvider('ONE_DRIVE', muteCloudEmailsSettingUuid, email)
return this.createCloudBackupFailedEventBasedOnProvider('ONE_DRIVE', email)
}
}

View File

@@ -1,4 +1,5 @@
import { KeyParamsData } from '@standardnotes/responses'
import { Item } from '../Item/Item'
export type SendItemsToExtensionsServerDTO = {
@@ -8,6 +9,5 @@ export type SendItemsToExtensionsServerDTO = {
authParams: KeyParamsData
forceMute: boolean
userUuid: string
muteEmailsSettingUuid?: string
items?: Array<Item>
}

View File

@@ -3,7 +3,7 @@ import 'reflect-metadata'
import {
DomainEventPublisherInterface,
EmailArchiveExtensionSyncedEvent,
EmailBackupAttachmentCreatedEvent,
EmailRequestedEvent,
} from '@standardnotes/domain-events'
import { Logger } from 'winston'
import { AuthHttpServiceInterface } from '../Auth/AuthHttpServiceInterface'
@@ -35,6 +35,7 @@ describe('EmailArchiveExtensionSyncedEventHandler', () => {
domainEventFactory,
emailAttachmentMaxByteSize,
itemTransferCalculator,
's3-backup-bucket-name',
logger,
)
@@ -62,9 +63,7 @@ describe('EmailArchiveExtensionSyncedEventHandler', () => {
domainEventPublisher.publish = jest.fn()
domainEventFactory = {} as jest.Mocked<DomainEventFactoryInterface>
domainEventFactory.createEmailBackupAttachmentCreatedEvent = jest
.fn()
.mockReturnValue({} as jest.Mocked<EmailBackupAttachmentCreatedEvent>)
domainEventFactory.createEmailRequestedEvent = jest.fn().mockReturnValue({} as jest.Mocked<EmailRequestedEvent>)
itemTransferCalculator = {} as jest.Mocked<ItemTransferCalculatorInterface>
itemTransferCalculator.computeItemUuidBundlesToFetch = jest.fn().mockReturnValue([['1-2-3']])
@@ -78,12 +77,7 @@ describe('EmailArchiveExtensionSyncedEventHandler', () => {
await createHandler().handle(event)
expect(domainEventPublisher.publish).toHaveBeenCalledTimes(1)
expect(domainEventFactory.createEmailBackupAttachmentCreatedEvent).toHaveBeenCalledWith({
backupFileIndex: 1,
backupFileName: 'backup-file-name',
backupFilesTotal: 1,
email: 'test@test.com',
})
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
})
it('should inform that multipart backup attachment for email was created', async () => {
@@ -96,18 +90,7 @@ describe('EmailArchiveExtensionSyncedEventHandler', () => {
await createHandler().handle(event)
expect(domainEventPublisher.publish).toHaveBeenCalledTimes(2)
expect(domainEventFactory.createEmailBackupAttachmentCreatedEvent).toHaveBeenNthCalledWith(1, {
backupFileIndex: 1,
backupFileName: 'backup-file-name-1',
backupFilesTotal: 2,
email: 'test@test.com',
})
expect(domainEventFactory.createEmailBackupAttachmentCreatedEvent).toHaveBeenNthCalledWith(2, {
backupFileIndex: 2,
backupFileName: 'backup-file-name-2',
backupFilesTotal: 2,
email: 'test@test.com',
})
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalledTimes(2)
})
it('should not inform that backup attachment for email was created if user key params cannot be obtained', async () => {
@@ -118,7 +101,7 @@ describe('EmailArchiveExtensionSyncedEventHandler', () => {
await createHandler().handle(event)
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
expect(domainEventFactory.createEmailBackupAttachmentCreatedEvent).not.toHaveBeenCalled()
expect(domainEventFactory.createEmailRequestedEvent).not.toHaveBeenCalled()
})
it('should not inform that backup attachment for email was created if backup file name is empty', async () => {
@@ -127,6 +110,6 @@ describe('EmailArchiveExtensionSyncedEventHandler', () => {
await createHandler().handle(event)
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
expect(domainEventFactory.createEmailBackupAttachmentCreatedEvent).not.toHaveBeenCalled()
expect(domainEventFactory.createEmailRequestedEvent).not.toHaveBeenCalled()
})
})

View File

@@ -4,6 +4,7 @@ import {
DomainEventPublisherInterface,
EmailArchiveExtensionSyncedEvent,
} from '@standardnotes/domain-events'
import { EmailLevel } from '@standardnotes/domain-core'
import { inject, injectable } from 'inversify'
import { Logger } from 'winston'
import TYPES from '../../Bootstrap/Types'
@@ -13,6 +14,7 @@ import { ItemBackupServiceInterface } from '../Item/ItemBackupServiceInterface'
import { ItemRepositoryInterface } from '../Item/ItemRepositoryInterface'
import { ItemQuery } from '../Item/ItemQuery'
import { ItemTransferCalculatorInterface } from '../Item/ItemTransferCalculatorInterface'
import { getBody, getSubject } from '../Email/EmailBackupAttachmentCreated'
@injectable()
export class EmailArchiveExtensionSyncedEventHandler implements DomainEventHandlerInterface {
@@ -24,6 +26,7 @@ export class EmailArchiveExtensionSyncedEventHandler implements DomainEventHandl
@inject(TYPES.DomainEventFactory) private domainEventFactory: DomainEventFactoryInterface,
@inject(TYPES.EMAIL_ATTACHMENT_MAX_BYTE_SIZE) private emailAttachmentMaxByteSize: number,
@inject(TYPES.ItemTransferCalculator) private itemTransferCalculator: ItemTransferCalculatorInterface,
@inject(TYPES.S3_BACKUP_BUCKET_NAME) private s3BackupBucketName: string,
@inject(TYPES.Logger) private logger: Logger,
) {}
@@ -64,14 +67,24 @@ export class EmailArchiveExtensionSyncedEventHandler implements DomainEventHandl
this.logger.debug(`Data backed up into: ${backupFileName}`)
if (backupFileName.length !== 0) {
this.logger.debug('Publishing EMAIL_BACKUP_ATTACHMENT_CREATED event')
const dateOnly = new Date().toISOString().substring(0, 10)
await this.domainEventPublisher.publish(
this.domainEventFactory.createEmailBackupAttachmentCreatedEvent({
backupFileName,
backupFileIndex: bundleIndex++,
backupFilesTotal: itemUuidBundles.length,
email: authParams.identifier as string,
this.domainEventFactory.createEmailRequestedEvent({
body: getBody(authParams.identifier as string),
level: EmailLevel.LEVELS.System,
messageIdentifier: 'DATA_BACKUP',
subject: getSubject(bundleIndex++, itemUuidBundles.length, dateOnly),
userEmail: authParams.identifier as string,
sender: 'backups@standardnotes.org',
attachments: [
{
fileName: backupFileName,
filePath: this.s3BackupBucketName,
attachmentFileName: `SN-Data-${dateOnly}.txt`,
attachmentContentType: 'application/json',
},
],
}),
)
}

View File

@@ -3,7 +3,7 @@ import 'reflect-metadata'
import {
DomainEventPublisherInterface,
EmailBackupRequestedEvent,
EmailBackupAttachmentCreatedEvent,
EmailRequestedEvent,
} from '@standardnotes/domain-events'
import { Logger } from 'winston'
import { AuthHttpServiceInterface } from '../Auth/AuthHttpServiceInterface'
@@ -35,6 +35,7 @@ describe('EmailBackupRequestedEventHandler', () => {
domainEventFactory,
emailAttachmentMaxByteSize,
itemTransferCalculator,
's3-backup-bucket-name',
logger,
)
@@ -62,9 +63,7 @@ describe('EmailBackupRequestedEventHandler', () => {
domainEventPublisher.publish = jest.fn()
domainEventFactory = {} as jest.Mocked<DomainEventFactoryInterface>
domainEventFactory.createEmailBackupAttachmentCreatedEvent = jest
.fn()
.mockReturnValue({} as jest.Mocked<EmailBackupAttachmentCreatedEvent>)
domainEventFactory.createEmailRequestedEvent = jest.fn().mockReturnValue({} as jest.Mocked<EmailRequestedEvent>)
itemTransferCalculator = {} as jest.Mocked<ItemTransferCalculatorInterface>
itemTransferCalculator.computeItemUuidBundlesToFetch = jest.fn().mockReturnValue([['1-2-3']])
@@ -79,12 +78,7 @@ describe('EmailBackupRequestedEventHandler', () => {
await createHandler().handle(event)
expect(domainEventPublisher.publish).toHaveBeenCalledTimes(1)
expect(domainEventFactory.createEmailBackupAttachmentCreatedEvent).toHaveBeenCalledWith({
backupFileIndex: 1,
backupFileName: 'backup-file-name',
backupFilesTotal: 1,
email: 'test@test.com',
})
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalled()
})
it('should inform that multipart backup attachment for email was created', async () => {
@@ -97,18 +91,7 @@ describe('EmailBackupRequestedEventHandler', () => {
await createHandler().handle(event)
expect(domainEventPublisher.publish).toHaveBeenCalledTimes(2)
expect(domainEventFactory.createEmailBackupAttachmentCreatedEvent).toHaveBeenNthCalledWith(1, {
backupFileIndex: 1,
backupFileName: 'backup-file-name-1',
backupFilesTotal: 2,
email: 'test@test.com',
})
expect(domainEventFactory.createEmailBackupAttachmentCreatedEvent).toHaveBeenNthCalledWith(2, {
backupFileIndex: 2,
backupFileName: 'backup-file-name-2',
backupFilesTotal: 2,
email: 'test@test.com',
})
expect(domainEventFactory.createEmailRequestedEvent).toHaveBeenCalledTimes(2)
})
it('should not inform that backup attachment for email was created if user key params cannot be obtained', async () => {
@@ -119,7 +102,7 @@ describe('EmailBackupRequestedEventHandler', () => {
await createHandler().handle(event)
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
expect(domainEventFactory.createEmailBackupAttachmentCreatedEvent).not.toHaveBeenCalled()
expect(domainEventFactory.createEmailRequestedEvent).not.toHaveBeenCalled()
})
it('should not inform that backup attachment for email was created if backup file name is empty', async () => {
@@ -128,6 +111,6 @@ describe('EmailBackupRequestedEventHandler', () => {
await createHandler().handle(event)
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
expect(domainEventFactory.createEmailBackupAttachmentCreatedEvent).not.toHaveBeenCalled()
expect(domainEventFactory.createEmailRequestedEvent).not.toHaveBeenCalled()
})
})

View File

@@ -4,6 +4,7 @@ import {
DomainEventPublisherInterface,
EmailBackupRequestedEvent,
} from '@standardnotes/domain-events'
import { EmailLevel } from '@standardnotes/domain-core'
import { inject, injectable } from 'inversify'
import { Logger } from 'winston'
import TYPES from '../../Bootstrap/Types'
@@ -13,6 +14,7 @@ import { ItemBackupServiceInterface } from '../Item/ItemBackupServiceInterface'
import { ItemRepositoryInterface } from '../Item/ItemRepositoryInterface'
import { ItemTransferCalculatorInterface } from '../Item/ItemTransferCalculatorInterface'
import { ItemQuery } from '../Item/ItemQuery'
import { getBody, getSubject } from '../Email/EmailBackupAttachmentCreated'
@injectable()
export class EmailBackupRequestedEventHandler implements DomainEventHandlerInterface {
@@ -24,6 +26,7 @@ export class EmailBackupRequestedEventHandler implements DomainEventHandlerInter
@inject(TYPES.DomainEventFactory) private domainEventFactory: DomainEventFactoryInterface,
@inject(TYPES.EMAIL_ATTACHMENT_MAX_BYTE_SIZE) private emailAttachmentMaxByteSize: number,
@inject(TYPES.ItemTransferCalculator) private itemTransferCalculator: ItemTransferCalculatorInterface,
@inject(TYPES.S3_BACKUP_BUCKET_NAME) private s3BackupBucketName: string,
@inject(TYPES.Logger) private logger: Logger,
) {}
@@ -68,15 +71,24 @@ export class EmailBackupRequestedEventHandler implements DomainEventHandlerInter
return
}
this.logger.debug('Publishing EMAIL_BACKUP_ATTACHMENT_CREATED event')
const dateOnly = new Date().toISOString().substring(0, 10)
await this.domainEventPublisher.publish(
this.domainEventFactory.createEmailBackupAttachmentCreatedEvent({
backupFileName,
backupFileIndex: bundleIndex++,
backupFilesTotal: itemUuidBundles.length,
email: authParams.identifier as string,
this.domainEventFactory.createEmailRequestedEvent({
body: getBody(authParams.identifier as string),
level: EmailLevel.LEVELS.System,
messageIdentifier: 'DATA_BACKUP',
subject: getSubject(bundleIndex++, itemUuidBundles.length, dateOnly),
userEmail: authParams.identifier as string,
sender: 'backups@standardnotes.org',
attachments: [
{
fileName: backupFileName,
filePath: this.s3BackupBucketName,
attachmentFileName: `SN-Data-${dateOnly}.txt`,
attachmentContentType: 'application/json',
},
],
}),
)
}

View File

@@ -3,6 +3,46 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.4.49](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.4.48...@standardnotes/websockets-server@1.4.49) (2022-12-09)
**Note:** Version bump only for package @standardnotes/websockets-server
## [1.4.48](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.4.47...@standardnotes/websockets-server@1.4.48) (2022-12-09)
**Note:** Version bump only for package @standardnotes/websockets-server
## [1.4.47](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.4.46...@standardnotes/websockets-server@1.4.47) (2022-12-09)
**Note:** Version bump only for package @standardnotes/websockets-server
## [1.4.46](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.4.45...@standardnotes/websockets-server@1.4.46) (2022-12-09)
**Note:** Version bump only for package @standardnotes/websockets-server
## [1.4.45](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.4.44...@standardnotes/websockets-server@1.4.45) (2022-12-09)
**Note:** Version bump only for package @standardnotes/websockets-server
## [1.4.44](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.4.43...@standardnotes/websockets-server@1.4.44) (2022-12-09)
**Note:** Version bump only for package @standardnotes/websockets-server
## [1.4.43](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.4.42...@standardnotes/websockets-server@1.4.43) (2022-12-08)
**Note:** Version bump only for package @standardnotes/websockets-server
## [1.4.42](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.4.41...@standardnotes/websockets-server@1.4.42) (2022-12-08)
**Note:** Version bump only for package @standardnotes/websockets-server
## [1.4.41](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.4.40...@standardnotes/websockets-server@1.4.41) (2022-12-08)
**Note:** Version bump only for package @standardnotes/websockets-server
## [1.4.40](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.4.39...@standardnotes/websockets-server@1.4.40) (2022-12-08)
**Note:** Version bump only for package @standardnotes/websockets-server
## [1.4.39](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.4.38...@standardnotes/websockets-server@1.4.39) (2022-12-08)
**Note:** Version bump only for package @standardnotes/websockets-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/websockets-server",
"version": "1.4.39",
"version": "1.4.49",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -3,6 +3,48 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.18.0](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.17.47...@standardnotes/workspace-server@1.18.0) (2022-12-09)
### Features
* **workspace:** replace workspace invite created event with email requested ([61c1cff](https://github.com/standardnotes/server/commit/61c1cfff4bcee09e1f933cb3e085412b6f07cc42))
## [1.17.47](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.17.46...@standardnotes/workspace-server@1.17.47) (2022-12-09)
**Note:** Version bump only for package @standardnotes/workspace-server
## [1.17.46](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.17.45...@standardnotes/workspace-server@1.17.46) (2022-12-09)
**Note:** Version bump only for package @standardnotes/workspace-server
## [1.17.45](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.17.44...@standardnotes/workspace-server@1.17.45) (2022-12-09)
**Note:** Version bump only for package @standardnotes/workspace-server
## [1.17.44](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.17.43...@standardnotes/workspace-server@1.17.44) (2022-12-09)
**Note:** Version bump only for package @standardnotes/workspace-server
## [1.17.43](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.17.42...@standardnotes/workspace-server@1.17.43) (2022-12-09)
**Note:** Version bump only for package @standardnotes/workspace-server
## [1.17.42](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.17.41...@standardnotes/workspace-server@1.17.42) (2022-12-08)
**Note:** Version bump only for package @standardnotes/workspace-server
## [1.17.41](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.17.40...@standardnotes/workspace-server@1.17.41) (2022-12-08)
**Note:** Version bump only for package @standardnotes/workspace-server
## [1.17.40](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.17.39...@standardnotes/workspace-server@1.17.40) (2022-12-08)
**Note:** Version bump only for package @standardnotes/workspace-server
## [1.17.39](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.17.38...@standardnotes/workspace-server@1.17.39) (2022-12-08)
**Note:** Version bump only for package @standardnotes/workspace-server
## [1.17.38](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.17.37...@standardnotes/workspace-server@1.17.38) (2022-12-08)
**Note:** Version bump only for package @standardnotes/workspace-server

View File

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

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/workspace-server",
"version": "1.17.38",
"version": "1.18.0",
"engines": {
"node": ">=18.0.0 <19.0.0"
},
@@ -26,6 +26,7 @@
"@sentry/node": "^7.19.0",
"@standardnotes/api": "^1.19.0",
"@standardnotes/common": "workspace:*",
"@standardnotes/domain-core": "workspace:^",
"@standardnotes/domain-events": "workspace:^",
"@standardnotes/domain-events-infra": "workspace:^",
"@standardnotes/models": "^1.26.0",

View File

@@ -0,0 +1,9 @@
import { html } from './workspace-invite-created.html'
export function getSubject(): string {
return 'You have been invited to a Standard Notes workspace'
}
export function getBody(inviteUuid: string): string {
return html(inviteUuid)
}

View File

@@ -0,0 +1,11 @@
export const html = (inviteUuid: string) => `<p>Hello,</p>
<p>We are happy to inform that you have been invited to a shared workspace in Standard Notes.</p>
<p>
Please
<a href='https://app.standardnotes.com/?accept_workspace_invite=${inviteUuid}'>accept the invitation</a>
to see the shared content.
</p>
<p>
Thanks,
<br>SN</br>
</p>`

View File

@@ -1,92 +0,0 @@
import 'reflect-metadata'
import { TimerInterface } from '@standardnotes/time'
import { DomainEventFactory } from './DomainEventFactory'
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 WEB_SOCKET_MESSAGE_REQUESTED event', () => {
expect(
createFactory().createWebSocketMessageRequestedEvent({
userUuid: '1-2-3',
message: 'foobar',
}),
).toEqual({
createdAt: expect.any(Date),
meta: {
correlation: {
userIdentifier: '1-2-3',
userIdentifierType: 'uuid',
},
origin: 'workspace',
},
payload: {
userUuid: '1-2-3',
message: 'foobar',
},
type: 'WEB_SOCKET_MESSAGE_REQUESTED',
})
})
it('should create a WORKSPACE_INVITE_ACCEPTED event', () => {
expect(
createFactory().createWorkspaceInviteAcceptedEvent({
inviterUuid: '1-2-3',
inviteeUuid: '2-3-4',
workspaceUuid: 'w-1-2-3',
}),
).toEqual({
createdAt: expect.any(Date),
meta: {
correlation: {
userIdentifier: '2-3-4',
userIdentifierType: 'uuid',
},
origin: 'workspace',
},
payload: {
inviterUuid: '1-2-3',
inviteeUuid: '2-3-4',
workspaceUuid: 'w-1-2-3',
},
type: 'WORKSPACE_INVITE_ACCEPTED',
})
})
it('should create a WORKSPACE_INVITE_CREATED event', () => {
expect(
createFactory().createWorkspaceInviteCreatedEvent({
inviterUuid: '1-2-3',
inviteeEmail: 'test@test.te',
inviteUuid: 'i-1-2-3',
workspaceUuid: 'w-1-2-3',
}),
).toEqual({
createdAt: expect.any(Date),
meta: {
correlation: {
userIdentifier: '1-2-3',
userIdentifierType: 'uuid',
},
origin: 'workspace',
},
payload: {
inviterUuid: '1-2-3',
inviteeEmail: 'test@test.te',
inviteUuid: 'i-1-2-3',
workspaceUuid: 'w-1-2-3',
},
type: 'WORKSPACE_INVITE_CREATED',
})
})
})

View File

@@ -1,8 +1,8 @@
import {
DomainEventService,
EmailRequestedEvent,
WebSocketMessageRequestedEvent,
WorkspaceInviteAcceptedEvent,
WorkspaceInviteCreatedEvent,
} from '@standardnotes/domain-events'
import { TimerInterface } from '@standardnotes/time'
import { inject, injectable } from 'inversify'
@@ -49,21 +49,22 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
}
}
createWorkspaceInviteCreatedEvent(dto: {
inviterUuid: string
inviteeEmail: string
inviteUuid: string
workspaceUuid: string
}): WorkspaceInviteCreatedEvent {
createEmailRequestedEvent(dto: {
userEmail: string
messageIdentifier: string
level: string
body: string
subject: string
}): EmailRequestedEvent {
return {
type: 'WORKSPACE_INVITE_CREATED',
type: 'EMAIL_REQUESTED',
createdAt: this.timer.getUTCDate(),
meta: {
correlation: {
userIdentifier: dto.inviterUuid,
userIdentifierType: 'uuid',
userIdentifier: dto.userEmail,
userIdentifierType: 'email',
},
origin: DomainEventService.Workspace,
origin: DomainEventService.Auth,
},
payload: dto,
}

View File

@@ -1,17 +1,18 @@
import { JSONString } from '@standardnotes/common'
import {
EmailRequestedEvent,
WebSocketMessageRequestedEvent,
WorkspaceInviteAcceptedEvent,
WorkspaceInviteCreatedEvent,
} from '@standardnotes/domain-events'
export interface DomainEventFactoryInterface {
createWorkspaceInviteCreatedEvent(dto: {
inviterUuid: string
inviteeEmail: string
inviteUuid: string
workspaceUuid: string
}): WorkspaceInviteCreatedEvent
createEmailRequestedEvent(dto: {
userEmail: string
messageIdentifier: string
level: string
body: string
subject: string
}): EmailRequestedEvent
createWorkspaceInviteAcceptedEvent(dto: {
inviterUuid: string
inviteeUuid: string

View File

@@ -1,8 +1,10 @@
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
import { TimerInterface } from '@standardnotes/time'
import { EmailLevel } from '@standardnotes/domain-core'
import { inject, injectable } from 'inversify'
import TYPES from '../../../Bootstrap/Types'
import { getBody, getSubject } from '../../Email/WorkspaceInviteCreated'
import { DomainEventFactoryInterface } from '../../Event/DomainEventFactoryInterface'
import { WorkspaceInvite } from '../../Invite/WorkspaceInvite'
import { WorkspaceInviteRepositoryInterface } from '../../Invite/WorkspaceInviteRepositoryInterface'
@@ -36,11 +38,12 @@ export class InviteToWorkspace implements UseCaseInterface {
invite = await this.workspaceInviteRepository.save(invite)
await this.domainEventPublisher.publish(
this.domainEventFactory.createWorkspaceInviteCreatedEvent({
inviterUuid: dto.inviterUuid,
inviteeEmail: dto.inviteeEmail,
workspaceUuid: dto.workspaceUuid,
inviteUuid: invite.uuid,
this.domainEventFactory.createEmailRequestedEvent({
body: getBody(invite.uuid),
subject: getSubject(),
level: EmailLevel.LEVELS.System,
messageIdentifier: 'WORKSPACE_INVITE_CREATED',
userEmail: dto.inviteeEmail,
}),
)

View File

@@ -2535,6 +2535,7 @@ __metadata:
"@sentry/node": "npm:^7.19.0"
"@standardnotes/api": "npm:^1.19.0"
"@standardnotes/common": "workspace:*"
"@standardnotes/domain-core": "workspace:^"
"@standardnotes/domain-events": "workspace:^"
"@standardnotes/domain-events-infra": "workspace:^"
"@standardnotes/models": "npm:^1.26.0"