mirror of
https://github.com/standardnotes/server
synced 2026-02-25 14:01:46 -05:00
Compare commits
4 Commits
@standardn
...
@standardn
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73d81df8cb | ||
|
|
484f554339 | ||
|
|
2ad864e68e | ||
|
|
723ff44151 |
98
.pnp.cjs
generated
98
.pnp.cjs
generated
@@ -4682,6 +4682,7 @@ const RAW_RUNTIME_STATE =
|
||||
["@standardnotes/security", "workspace:packages/security"],\
|
||||
["@standardnotes/settings", "workspace:packages/settings"],\
|
||||
["@standardnotes/time", "workspace:packages/time"],\
|
||||
["@types/better-sqlite3", "npm:7.6.4"],\
|
||||
["@types/cors", "npm:2.8.12"],\
|
||||
["@types/dotenv", "npm:8.2.0"],\
|
||||
["@types/express", "npm:4.17.14"],\
|
||||
@@ -4694,6 +4695,7 @@ const RAW_RUNTIME_STATE =
|
||||
["@types/uuid", "npm:8.3.4"],\
|
||||
["@typescript-eslint/eslint-plugin", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:5.48.2"],\
|
||||
["axios", "npm:1.1.3"],\
|
||||
["better-sqlite3", "npm:8.3.0"],\
|
||||
["cors", "npm:2.8.5"],\
|
||||
["dotenv", "npm:16.0.1"],\
|
||||
["eslint", "npm:8.32.0"],\
|
||||
@@ -4711,7 +4713,7 @@ const RAW_RUNTIME_STATE =
|
||||
["prettyjson", "npm:1.2.5"],\
|
||||
["reflect-metadata", "npm:0.1.13"],\
|
||||
["ts-jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.0.3"],\
|
||||
["typeorm", "virtual:365b8c88cdf194291829ee28b79556e2328175d26a621363e703848100bea0042e9500db2a1206c9bbc3a4a76a1d169639ef774b2ea3a1a98584a9936b58c6be#npm:0.3.10"],\
|
||||
["typeorm", "virtual:67ad3a1ca34e24ce4821cc48979e98af0c3e5dd7aabc7ad0b5d22d1d977d6f943f81c9f141a420105ebdc61ef777e508a96c7946081decd98f8c30543d468b33#npm:0.3.10"],\
|
||||
["typescript", "patch:typescript@npm%3A4.8.4#optional!builtin<compat/typescript>::version=4.8.4&hash=701156"],\
|
||||
["ua-parser-js", "npm:1.0.32"],\
|
||||
["uuid", "npm:9.0.0"],\
|
||||
@@ -14847,6 +14849,100 @@ const RAW_RUNTIME_STATE =
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["virtual:67ad3a1ca34e24ce4821cc48979e98af0c3e5dd7aabc7ad0b5d22d1d977d6f943f81c9f141a420105ebdc61ef777e508a96c7946081decd98f8c30543d468b33#npm:0.3.10", {\
|
||||
"packageLocation": "./.yarn/__virtual__/typeorm-virtual-f86b034570/0/cache/typeorm-npm-0.3.10-4667857f33-749e1a6777.zip/node_modules/typeorm/",\
|
||||
"packageDependencies": [\
|
||||
["typeorm", "virtual:67ad3a1ca34e24ce4821cc48979e98af0c3e5dd7aabc7ad0b5d22d1d977d6f943f81c9f141a420105ebdc61ef777e508a96c7946081decd98f8c30543d468b33#npm:0.3.10"],\
|
||||
["@google-cloud/spanner", null],\
|
||||
["@sap/hana-client", null],\
|
||||
["@sqltools/formatter", "npm:1.2.5"],\
|
||||
["@types/better-sqlite3", "npm:7.6.4"],\
|
||||
["@types/google-cloud__spanner", null],\
|
||||
["@types/hdb-pool", null],\
|
||||
["@types/ioredis", null],\
|
||||
["@types/mongodb", null],\
|
||||
["@types/mssql", null],\
|
||||
["@types/mysql2", null],\
|
||||
["@types/oracledb", null],\
|
||||
["@types/pg", null],\
|
||||
["@types/pg-native", null],\
|
||||
["@types/pg-query-stream", null],\
|
||||
["@types/redis", null],\
|
||||
["@types/sap__hana-client", null],\
|
||||
["@types/sql.js", null],\
|
||||
["@types/sqlite3", null],\
|
||||
["@types/ts-node", null],\
|
||||
["@types/typeorm-aurora-data-api-driver", null],\
|
||||
["app-root-path", "npm:3.1.0"],\
|
||||
["better-sqlite3", "npm:8.3.0"],\
|
||||
["buffer", "npm:6.0.3"],\
|
||||
["chalk", "npm:4.1.2"],\
|
||||
["cli-highlight", "npm:2.1.11"],\
|
||||
["date-fns", "npm:2.29.3"],\
|
||||
["debug", "virtual:b86a9fb34323a98c6519528ed55faa0d9b44ca8879307c0b29aa384bde47ff59a7d0c9051b31246f14521dfb71ba3c5d6d0b35c29fffc17bf875aa6ad977d9e8#npm:4.3.4"],\
|
||||
["dotenv", "npm:16.0.3"],\
|
||||
["glob", "npm:7.2.3"],\
|
||||
["hdb-pool", null],\
|
||||
["ioredis", null],\
|
||||
["js-yaml", "npm:4.1.0"],\
|
||||
["mkdirp", "npm:1.0.4"],\
|
||||
["mongodb", null],\
|
||||
["mssql", null],\
|
||||
["mysql2", "npm:3.0.1"],\
|
||||
["oracledb", null],\
|
||||
["pg", null],\
|
||||
["pg-native", null],\
|
||||
["pg-query-stream", null],\
|
||||
["redis", null],\
|
||||
["reflect-metadata", "npm:0.1.13"],\
|
||||
["sha.js", "npm:2.4.11"],\
|
||||
["sql.js", null],\
|
||||
["sqlite3", null],\
|
||||
["ts-node", null],\
|
||||
["tslib", "npm:2.4.0"],\
|
||||
["typeorm-aurora-data-api-driver", null],\
|
||||
["uuid", "npm:8.3.2"],\
|
||||
["xml2js", "npm:0.4.23"],\
|
||||
["yargs", "npm:17.5.1"]\
|
||||
],\
|
||||
"packagePeers": [\
|
||||
"@google-cloud/spanner",\
|
||||
"@sap/hana-client",\
|
||||
"@types/better-sqlite3",\
|
||||
"@types/google-cloud__spanner",\
|
||||
"@types/hdb-pool",\
|
||||
"@types/ioredis",\
|
||||
"@types/mongodb",\
|
||||
"@types/mssql",\
|
||||
"@types/mysql2",\
|
||||
"@types/oracledb",\
|
||||
"@types/pg-native",\
|
||||
"@types/pg-query-stream",\
|
||||
"@types/pg",\
|
||||
"@types/redis",\
|
||||
"@types/sap__hana-client",\
|
||||
"@types/sql.js",\
|
||||
"@types/sqlite3",\
|
||||
"@types/ts-node",\
|
||||
"@types/typeorm-aurora-data-api-driver",\
|
||||
"better-sqlite3",\
|
||||
"hdb-pool",\
|
||||
"ioredis",\
|
||||
"mongodb",\
|
||||
"mssql",\
|
||||
"mysql2",\
|
||||
"oracledb",\
|
||||
"pg-native",\
|
||||
"pg-query-stream",\
|
||||
"pg",\
|
||||
"redis",\
|
||||
"sql.js",\
|
||||
"sqlite3",\
|
||||
"ts-node",\
|
||||
"typeorm-aurora-data-api-driver"\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:0.3.10", {\
|
||||
"packageLocation": "./.yarn/__virtual__/typeorm-virtual-a38286c9d5/0/cache/typeorm-npm-0.3.10-4667857f33-749e1a6777.zip/node_modules/typeorm/",\
|
||||
"packageDependencies": [\
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.21.9](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.21.8...@standardnotes/analytics@2.21.9) (2023-04-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
## [2.21.8](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.21.7...@standardnotes/analytics@2.21.8) (2023-04-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/analytics",
|
||||
"version": "2.21.8",
|
||||
"version": "2.21.9",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.49.12](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.49.11...@standardnotes/api-gateway@1.49.12) (2023-04-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
## [1.49.11](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.49.10...@standardnotes/api-gateway@1.49.11) (2023-04-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/api-gateway",
|
||||
"version": "1.49.11",
|
||||
"version": "1.49.12",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.97.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.96.0...@standardnotes/auth-server@1.97.0) (2023-04-27)
|
||||
|
||||
### Features
|
||||
|
||||
* remove cloud backups ([#574](https://github.com/standardnotes/server/issues/574)) ([484f554](https://github.com/standardnotes/server/commit/484f55433928e5c21ee59d8fda94ab3c887cd169))
|
||||
|
||||
# [1.96.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.95.3...@standardnotes/auth-server@1.96.0) (2023-04-27)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -14,10 +14,9 @@ import { Env } from '../src/Bootstrap/Env'
|
||||
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
||||
import { DomainEventFactoryInterface } from '../src/Domain/Event/DomainEventFactoryInterface'
|
||||
import { SettingRepositoryInterface } from '../src/Domain/Setting/SettingRepositoryInterface'
|
||||
import { MuteFailedBackupsEmailsOption, MuteFailedCloudBackupsEmailsOption, SettingName } from '@standardnotes/settings'
|
||||
import { MuteFailedBackupsEmailsOption, SettingName } from '@standardnotes/settings'
|
||||
import { RoleServiceInterface } from '../src/Domain/Role/RoleServiceInterface'
|
||||
import { PermissionName } from '@standardnotes/features'
|
||||
import { SettingServiceInterface } from '../src/Domain/Setting/SettingServiceInterface'
|
||||
|
||||
const inputArgs = process.argv.slice(2)
|
||||
const backupProvider = inputArgs[0]
|
||||
@@ -26,46 +25,13 @@ const backupFrequency = inputArgs[1]
|
||||
const requestBackups = async (
|
||||
settingRepository: SettingRepositoryInterface,
|
||||
roleService: RoleServiceInterface,
|
||||
settingService: SettingServiceInterface,
|
||||
domainEventFactory: DomainEventFactoryInterface,
|
||||
domainEventPublisher: DomainEventPublisherInterface,
|
||||
): Promise<void> => {
|
||||
let settingName: SettingName,
|
||||
permissionName: PermissionName,
|
||||
muteEmailsSettingName: string,
|
||||
muteEmailsSettingValue: string,
|
||||
providerTokenSettingName: SettingName
|
||||
switch (backupProvider) {
|
||||
case 'email':
|
||||
settingName = SettingName.create(SettingName.NAMES.EmailBackupFrequency).getValue()
|
||||
permissionName = PermissionName.DailyEmailBackup
|
||||
muteEmailsSettingName = SettingName.NAMES.MuteFailedBackupsEmails
|
||||
muteEmailsSettingValue = MuteFailedBackupsEmailsOption.Muted
|
||||
break
|
||||
case 'dropbox':
|
||||
settingName = SettingName.create(SettingName.NAMES.DropboxBackupFrequency).getValue()
|
||||
permissionName = PermissionName.DailyDropboxBackup
|
||||
muteEmailsSettingName = SettingName.NAMES.MuteFailedCloudBackupsEmails
|
||||
muteEmailsSettingValue = MuteFailedCloudBackupsEmailsOption.Muted
|
||||
providerTokenSettingName = SettingName.create(SettingName.NAMES.DropboxBackupToken).getValue()
|
||||
break
|
||||
case 'one_drive':
|
||||
settingName = SettingName.create(SettingName.NAMES.OneDriveBackupFrequency).getValue()
|
||||
permissionName = PermissionName.DailyOneDriveBackup
|
||||
muteEmailsSettingName = SettingName.NAMES.MuteFailedCloudBackupsEmails
|
||||
muteEmailsSettingValue = MuteFailedCloudBackupsEmailsOption.Muted
|
||||
providerTokenSettingName = SettingName.create(SettingName.NAMES.OneDriveBackupToken).getValue()
|
||||
break
|
||||
case 'google_drive':
|
||||
settingName = SettingName.create(SettingName.NAMES.GoogleDriveBackupFrequency).getValue()
|
||||
permissionName = PermissionName.DailyGDriveBackup
|
||||
muteEmailsSettingName = SettingName.NAMES.MuteFailedCloudBackupsEmails
|
||||
muteEmailsSettingValue = MuteFailedCloudBackupsEmailsOption.Muted
|
||||
providerTokenSettingName = SettingName.create(SettingName.NAMES.GoogleDriveBackupToken).getValue()
|
||||
break
|
||||
default:
|
||||
throw new Error(`Not handled backup provider: ${backupProvider}`)
|
||||
}
|
||||
const settingName = SettingName.create(SettingName.NAMES.EmailBackupFrequency).getValue()
|
||||
const permissionName = PermissionName.DailyEmailBackup
|
||||
const muteEmailsSettingName = SettingName.NAMES.MuteFailedBackupsEmails
|
||||
const muteEmailsSettingValue = MuteFailedBackupsEmailsOption.Muted
|
||||
|
||||
const stream = await settingRepository.streamAllByNameAndValue(settingName, backupFrequency)
|
||||
|
||||
@@ -94,39 +60,14 @@ const requestBackups = async (
|
||||
userHasEmailsMuted = emailsMutedSetting.value === muteEmailsSettingValue
|
||||
}
|
||||
|
||||
if (backupProvider === 'email') {
|
||||
await domainEventPublisher.publish(
|
||||
domainEventFactory.createEmailBackupRequestedEvent(
|
||||
setting.setting_user_uuid,
|
||||
emailsMutedSetting?.uuid as string,
|
||||
userHasEmailsMuted,
|
||||
),
|
||||
)
|
||||
|
||||
callback()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const cloudBackupProviderToken = await settingService.findSettingWithDecryptedValue({
|
||||
settingName: providerTokenSettingName,
|
||||
userUuid: setting.setting_user_uuid,
|
||||
})
|
||||
if (cloudBackupProviderToken === null || cloudBackupProviderToken.value === null) {
|
||||
callback()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
await domainEventPublisher.publish(
|
||||
domainEventFactory.createCloudBackupRequestedEvent(
|
||||
backupProvider.toUpperCase() as 'DROPBOX' | 'ONE_DRIVE' | 'GOOGLE_DRIVE',
|
||||
cloudBackupProviderToken.value,
|
||||
domainEventFactory.createEmailBackupRequestedEvent(
|
||||
setting.setting_user_uuid,
|
||||
emailsMutedSetting?.uuid as string,
|
||||
userHasEmailsMuted,
|
||||
),
|
||||
)
|
||||
|
||||
callback()
|
||||
},
|
||||
}),
|
||||
@@ -149,13 +90,10 @@ void container.load().then((container) => {
|
||||
|
||||
const settingRepository: SettingRepositoryInterface = container.get(TYPES.SettingRepository)
|
||||
const roleService: RoleServiceInterface = container.get(TYPES.RoleService)
|
||||
const settingService: SettingServiceInterface = container.get(TYPES.SettingService)
|
||||
const domainEventFactory: DomainEventFactoryInterface = container.get(TYPES.DomainEventFactory)
|
||||
const domainEventPublisher: DomainEventPublisherInterface = container.get(TYPES.DomainEventPublisher)
|
||||
|
||||
Promise.resolve(
|
||||
requestBackups(settingRepository, roleService, settingService, domainEventFactory, domainEventPublisher),
|
||||
)
|
||||
Promise.resolve(requestBackups(settingRepository, roleService, domainEventFactory, domainEventPublisher))
|
||||
.then(() => {
|
||||
logger.info(`${backupFrequency} ${backupProvider} backup requesting complete`)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/auth-server",
|
||||
"version": "1.96.0",
|
||||
"version": "1.97.0",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
UserRegisteredEvent,
|
||||
UserRolesChangedEvent,
|
||||
EmailBackupRequestedEvent,
|
||||
CloudBackupRequestedEvent,
|
||||
ListedAccountRequestedEvent,
|
||||
UserDisabledSessionUserAgentLoggingEvent,
|
||||
SharedSubscriptionInvitationCreatedEvent,
|
||||
@@ -254,33 +253,6 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
|
||||
}
|
||||
}
|
||||
|
||||
createCloudBackupRequestedEvent(
|
||||
cloudProvider: 'DROPBOX' | 'ONE_DRIVE' | 'GOOGLE_DRIVE',
|
||||
cloudProviderToken: string,
|
||||
userUuid: string,
|
||||
muteEmailsSettingUuid: string,
|
||||
userHasEmailsMuted: boolean,
|
||||
): CloudBackupRequestedEvent {
|
||||
return {
|
||||
type: 'CLOUD_BACKUP_REQUESTED',
|
||||
createdAt: this.timer.getUTCDate(),
|
||||
meta: {
|
||||
correlation: {
|
||||
userIdentifier: userUuid,
|
||||
userIdentifierType: 'uuid',
|
||||
},
|
||||
origin: DomainEventService.Auth,
|
||||
},
|
||||
payload: {
|
||||
cloudProvider,
|
||||
cloudProviderToken,
|
||||
userUuid,
|
||||
userHasEmailsMuted,
|
||||
muteEmailsSettingUuid,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
createEmailBackupRequestedEvent(
|
||||
userUuid: string,
|
||||
muteEmailsSettingUuid: string,
|
||||
|
||||
@@ -2,7 +2,6 @@ import { ProtocolVersion, JSONString } from '@standardnotes/common'
|
||||
import { Predicate, PredicateVerificationResult } from '@standardnotes/predicates'
|
||||
import {
|
||||
AccountDeletionRequestedEvent,
|
||||
CloudBackupRequestedEvent,
|
||||
UserRegisteredEvent,
|
||||
UserRolesChangedEvent,
|
||||
UserEmailChangedEvent,
|
||||
@@ -42,13 +41,6 @@ export interface DomainEventFactoryInterface {
|
||||
muteEmailsSettingUuid: string,
|
||||
userHasEmailsMuted: boolean,
|
||||
): EmailBackupRequestedEvent
|
||||
createCloudBackupRequestedEvent(
|
||||
cloudProvider: 'DROPBOX' | 'ONE_DRIVE' | 'GOOGLE_DRIVE',
|
||||
cloudProviderToken: string,
|
||||
userUuid: string,
|
||||
muteEmailsSettingUuid: string,
|
||||
userHasEmailsMuted: boolean,
|
||||
): CloudBackupRequestedEvent
|
||||
createAccountDeletionRequestedEvent(dto: {
|
||||
userUuid: string
|
||||
userCreatedAtTimestamp: number
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {
|
||||
CloudBackupRequestedEvent,
|
||||
DomainEventPublisherInterface,
|
||||
EmailBackupRequestedEvent,
|
||||
MuteEmailsSettingChangedEvent,
|
||||
@@ -9,7 +8,6 @@ import {
|
||||
EmailBackupFrequency,
|
||||
LogSessionUserAgentOption,
|
||||
MuteMarketingEmailsOption,
|
||||
OneDriveBackupFrequency,
|
||||
SettingName,
|
||||
} from '@standardnotes/settings'
|
||||
import 'reflect-metadata'
|
||||
@@ -30,8 +28,7 @@ describe('SettingInterpreter', () => {
|
||||
let settingDecrypter: SettingDecrypterInterface
|
||||
let logger: Logger
|
||||
|
||||
const createInterpreter = () =>
|
||||
new SettingInterpreter(domainEventPublisher, domainEventFactory, settingRepository, settingDecrypter, logger)
|
||||
const createInterpreter = () => new SettingInterpreter(domainEventPublisher, domainEventFactory, settingRepository)
|
||||
|
||||
beforeEach(() => {
|
||||
user = {
|
||||
@@ -53,9 +50,6 @@ describe('SettingInterpreter', () => {
|
||||
domainEventFactory.createEmailBackupRequestedEvent = jest
|
||||
.fn()
|
||||
.mockReturnValue({} as jest.Mocked<EmailBackupRequestedEvent>)
|
||||
domainEventFactory.createCloudBackupRequestedEvent = jest
|
||||
.fn()
|
||||
.mockReturnValue({} as jest.Mocked<CloudBackupRequestedEvent>)
|
||||
domainEventFactory.createUserDisabledSessionUserAgentLoggingEvent = jest
|
||||
.fn()
|
||||
.mockReturnValue({} as jest.Mocked<UserDisabledSessionUserAgentLoggingEvent>)
|
||||
@@ -124,70 +118,6 @@ describe('SettingInterpreter', () => {
|
||||
expect(domainEventFactory.createEmailBackupRequestedEvent).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should trigger cloud backup if dropbox backup setting is created', async () => {
|
||||
settingRepository.findOneByNameAndUserUuid = jest.fn().mockReturnValue(null)
|
||||
|
||||
await createInterpreter().interpretSettingUpdated(SettingName.NAMES.DropboxBackupToken, user, 'test-token')
|
||||
|
||||
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||
expect(domainEventFactory.createCloudBackupRequestedEvent).toHaveBeenCalledWith(
|
||||
'DROPBOX',
|
||||
'test-token',
|
||||
'4-5-6',
|
||||
'',
|
||||
false,
|
||||
)
|
||||
})
|
||||
|
||||
it('should trigger cloud backup if dropbox backup setting is created - muted emails', async () => {
|
||||
settingRepository.findOneByNameAndUserUuid = jest.fn().mockReturnValue({
|
||||
name: SettingName.NAMES.MuteFailedCloudBackupsEmails,
|
||||
uuid: '6-7-8',
|
||||
value: 'muted',
|
||||
} as jest.Mocked<Setting>)
|
||||
|
||||
await createInterpreter().interpretSettingUpdated(SettingName.NAMES.DropboxBackupToken, user, 'test-token')
|
||||
|
||||
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||
expect(domainEventFactory.createCloudBackupRequestedEvent).toHaveBeenCalledWith(
|
||||
'DROPBOX',
|
||||
'test-token',
|
||||
'4-5-6',
|
||||
'6-7-8',
|
||||
true,
|
||||
)
|
||||
})
|
||||
|
||||
it('should trigger cloud backup if google drive backup setting is created', async () => {
|
||||
settingRepository.findOneByNameAndUserUuid = jest.fn().mockReturnValue(null)
|
||||
|
||||
await createInterpreter().interpretSettingUpdated(SettingName.NAMES.GoogleDriveBackupToken, user, 'test-token')
|
||||
|
||||
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||
expect(domainEventFactory.createCloudBackupRequestedEvent).toHaveBeenCalledWith(
|
||||
'GOOGLE_DRIVE',
|
||||
'test-token',
|
||||
'4-5-6',
|
||||
'',
|
||||
false,
|
||||
)
|
||||
})
|
||||
|
||||
it('should trigger cloud backup if one drive backup setting is created', async () => {
|
||||
settingRepository.findOneByNameAndUserUuid = jest.fn().mockReturnValue(null)
|
||||
|
||||
await createInterpreter().interpretSettingUpdated(SettingName.NAMES.OneDriveBackupToken, user, 'test-token')
|
||||
|
||||
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||
expect(domainEventFactory.createCloudBackupRequestedEvent).toHaveBeenCalledWith(
|
||||
'ONE_DRIVE',
|
||||
'test-token',
|
||||
'4-5-6',
|
||||
'',
|
||||
false,
|
||||
)
|
||||
})
|
||||
|
||||
it('should trigger mute subscription emails rejection if mute setting changed', async () => {
|
||||
settingRepository.findOneByNameAndUserUuid = jest.fn().mockReturnValue(null)
|
||||
|
||||
@@ -204,51 +134,4 @@ describe('SettingInterpreter', () => {
|
||||
username: 'test@test.te',
|
||||
})
|
||||
})
|
||||
|
||||
it('should trigger cloud backup if backup frequency setting is updated and a backup token setting is present', async () => {
|
||||
settingRepository.findLastByNameAndUserUuid = jest.fn().mockReturnValueOnce({
|
||||
name: SettingName.NAMES.OneDriveBackupToken,
|
||||
serverEncryptionVersion: 1,
|
||||
value: 'encrypted-backup-token',
|
||||
sensitive: true,
|
||||
} as jest.Mocked<Setting>)
|
||||
|
||||
await createInterpreter().interpretSettingUpdated(SettingName.NAMES.OneDriveBackupFrequency, user, 'daily')
|
||||
|
||||
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||
expect(domainEventFactory.createCloudBackupRequestedEvent).toHaveBeenCalledWith(
|
||||
'ONE_DRIVE',
|
||||
'decrypted',
|
||||
'4-5-6',
|
||||
'',
|
||||
false,
|
||||
)
|
||||
})
|
||||
|
||||
it('should not trigger cloud backup if backup frequency setting is updated as disabled', async () => {
|
||||
settingRepository.findLastByNameAndUserUuid = jest.fn().mockReturnValueOnce({
|
||||
name: SettingName.NAMES.OneDriveBackupToken,
|
||||
serverEncryptionVersion: 1,
|
||||
value: 'encrypted-backup-token',
|
||||
sensitive: true,
|
||||
} as jest.Mocked<Setting>)
|
||||
|
||||
await createInterpreter().interpretSettingUpdated(
|
||||
SettingName.NAMES.OneDriveBackupFrequency,
|
||||
user,
|
||||
OneDriveBackupFrequency.Disabled,
|
||||
)
|
||||
|
||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||
expect(domainEventFactory.createCloudBackupRequestedEvent).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should not trigger cloud backup if backup frequency setting is updated and a backup token setting is not present', async () => {
|
||||
settingRepository.findLastByNameAndUserUuid = jest.fn().mockReturnValueOnce(null)
|
||||
|
||||
await createInterpreter().interpretSettingUpdated(SettingName.NAMES.OneDriveBackupFrequency, user, 'daily')
|
||||
|
||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||
expect(domainEventFactory.createCloudBackupRequestedEvent).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,44 +1,21 @@
|
||||
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
||||
import { EmailLevel } from '@standardnotes/domain-core'
|
||||
import {
|
||||
DropboxBackupFrequency,
|
||||
EmailBackupFrequency,
|
||||
GoogleDriveBackupFrequency,
|
||||
LogSessionUserAgentOption,
|
||||
MuteFailedBackupsEmailsOption,
|
||||
MuteFailedCloudBackupsEmailsOption,
|
||||
OneDriveBackupFrequency,
|
||||
SettingName,
|
||||
} from '@standardnotes/settings'
|
||||
import { inject, injectable } from 'inversify'
|
||||
import { Logger } from 'winston'
|
||||
|
||||
import TYPES from '../../Bootstrap/Types'
|
||||
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
|
||||
import { User } from '../User/User'
|
||||
import { SettingDecrypterInterface } from './SettingDecrypterInterface'
|
||||
import { SettingInterpreterInterface } from './SettingInterpreterInterface'
|
||||
import { SettingRepositoryInterface } from './SettingRepositoryInterface'
|
||||
|
||||
@injectable()
|
||||
export class SettingInterpreter implements SettingInterpreterInterface {
|
||||
private readonly cloudBackupTokenSettings = [
|
||||
SettingName.NAMES.DropboxBackupToken,
|
||||
SettingName.NAMES.GoogleDriveBackupToken,
|
||||
SettingName.NAMES.OneDriveBackupToken,
|
||||
]
|
||||
|
||||
private readonly cloudBackupFrequencySettings = [
|
||||
SettingName.NAMES.DropboxBackupFrequency,
|
||||
SettingName.NAMES.GoogleDriveBackupFrequency,
|
||||
SettingName.NAMES.OneDriveBackupFrequency,
|
||||
]
|
||||
|
||||
private readonly cloudBackupFrequencyDisabledValues = [
|
||||
DropboxBackupFrequency.Disabled,
|
||||
GoogleDriveBackupFrequency.Disabled,
|
||||
OneDriveBackupFrequency.Disabled,
|
||||
]
|
||||
|
||||
private readonly emailSettingToSubscriptionRejectionLevelMap: Map<string, string> = new Map([
|
||||
[SettingName.NAMES.MuteFailedBackupsEmails, EmailLevel.LEVELS.FailedEmailBackup],
|
||||
[SettingName.NAMES.MuteFailedCloudBackupsEmails, EmailLevel.LEVELS.FailedCloudBackup],
|
||||
@@ -50,8 +27,6 @@ export class SettingInterpreter implements SettingInterpreterInterface {
|
||||
@inject(TYPES.DomainEventPublisher) private domainEventPublisher: DomainEventPublisherInterface,
|
||||
@inject(TYPES.DomainEventFactory) private domainEventFactory: DomainEventFactoryInterface,
|
||||
@inject(TYPES.SettingRepository) private settingRepository: SettingRepositoryInterface,
|
||||
@inject(TYPES.SettingDecrypter) private settingDecrypter: SettingDecrypterInterface,
|
||||
@inject(TYPES.Logger) private logger: Logger,
|
||||
) {}
|
||||
|
||||
async interpretSettingUpdated(
|
||||
@@ -67,10 +42,6 @@ export class SettingInterpreter implements SettingInterpreterInterface {
|
||||
await this.triggerEmailBackup(user.uuid)
|
||||
}
|
||||
|
||||
if (this.isEnablingCloudBackupSetting(updatedSettingName, unencryptedValue)) {
|
||||
await this.triggerCloudBackup(updatedSettingName, user.uuid, unencryptedValue)
|
||||
}
|
||||
|
||||
if (this.isDisablingSessionUserAgentLogging(updatedSettingName, unencryptedValue)) {
|
||||
await this.triggerSessionUserAgentCleanup(user)
|
||||
}
|
||||
@@ -109,16 +80,6 @@ export class SettingInterpreter implements SettingInterpreterInterface {
|
||||
)
|
||||
}
|
||||
|
||||
private isEnablingCloudBackupSetting(settingName: string, newValue: string | null): boolean {
|
||||
return (
|
||||
(this.cloudBackupFrequencySettings.includes(settingName) ||
|
||||
this.cloudBackupTokenSettings.includes(settingName)) &&
|
||||
!this.cloudBackupFrequencyDisabledValues.includes(
|
||||
newValue as DropboxBackupFrequency | OneDriveBackupFrequency | GoogleDriveBackupFrequency,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private isDisablingSessionUserAgentLogging(settingName: string, newValue: string | null): boolean {
|
||||
return SettingName.NAMES.LogSessionUserAgent === settingName && LogSessionUserAgentOption.Disabled === newValue
|
||||
}
|
||||
@@ -145,67 +106,4 @@ export class SettingInterpreter implements SettingInterpreterInterface {
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
private async triggerCloudBackup(
|
||||
settingName: string,
|
||||
userUuid: string,
|
||||
unencryptedValue: string | null,
|
||||
): Promise<void> {
|
||||
let cloudProvider
|
||||
let tokenSettingName
|
||||
switch (settingName) {
|
||||
case SettingName.NAMES.DropboxBackupToken:
|
||||
case SettingName.NAMES.DropboxBackupFrequency:
|
||||
cloudProvider = 'DROPBOX'
|
||||
tokenSettingName = SettingName.NAMES.DropboxBackupToken
|
||||
break
|
||||
case SettingName.NAMES.GoogleDriveBackupToken:
|
||||
case SettingName.NAMES.GoogleDriveBackupFrequency:
|
||||
cloudProvider = 'GOOGLE_DRIVE'
|
||||
tokenSettingName = SettingName.NAMES.GoogleDriveBackupToken
|
||||
break
|
||||
case SettingName.NAMES.OneDriveBackupToken:
|
||||
case SettingName.NAMES.OneDriveBackupFrequency:
|
||||
cloudProvider = 'ONE_DRIVE'
|
||||
tokenSettingName = SettingName.NAMES.OneDriveBackupToken
|
||||
break
|
||||
}
|
||||
|
||||
let backupToken = null
|
||||
if (this.cloudBackupFrequencySettings.includes(settingName)) {
|
||||
const tokenSetting = await this.settingRepository.findLastByNameAndUserUuid(tokenSettingName as string, userUuid)
|
||||
if (tokenSetting !== null) {
|
||||
backupToken = await this.settingDecrypter.decryptSettingValue(tokenSetting, userUuid)
|
||||
}
|
||||
} else {
|
||||
backupToken = unencryptedValue
|
||||
}
|
||||
|
||||
if (!backupToken) {
|
||||
this.logger.error(`Could not trigger backup. Missing backup token for user ${userUuid}`)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
let userHasEmailsMuted = false
|
||||
let muteEmailsSettingUuid = ''
|
||||
const muteFailedCloudBackupSetting = await this.settingRepository.findOneByNameAndUserUuid(
|
||||
SettingName.NAMES.MuteFailedCloudBackupsEmails,
|
||||
userUuid,
|
||||
)
|
||||
if (muteFailedCloudBackupSetting !== null) {
|
||||
userHasEmailsMuted = muteFailedCloudBackupSetting.value === MuteFailedCloudBackupsEmailsOption.Muted
|
||||
muteEmailsSettingUuid = muteFailedCloudBackupSetting.uuid
|
||||
}
|
||||
|
||||
await this.domainEventPublisher.publish(
|
||||
this.domainEventFactory.createCloudBackupRequestedEvent(
|
||||
cloudProvider as 'DROPBOX' | 'GOOGLE_DRIVE' | 'ONE_DRIVE',
|
||||
backupToken,
|
||||
userUuid,
|
||||
muteEmailsSettingUuid,
|
||||
userHasEmailsMuted,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.10.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.10.1...@standardnotes/domain-events-infra@1.10.2) (2023-04-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||
|
||||
## [1.10.1](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.10.0...@standardnotes/domain-events-infra@1.10.1) (2023-04-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/domain-events-infra",
|
||||
"version": "1.10.1",
|
||||
"version": "1.10.2",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [2.110.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.109.0...@standardnotes/domain-events@2.110.0) (2023-04-27)
|
||||
|
||||
### Features
|
||||
|
||||
* remove cloud backups ([#574](https://github.com/standardnotes/server/issues/574)) ([484f554](https://github.com/standardnotes/server/commit/484f55433928e5c21ee59d8fda94ab3c887cd169))
|
||||
|
||||
# [2.109.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.108.1...@standardnotes/domain-events@2.109.0) (2023-04-21)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/domain-events",
|
||||
"version": "2.109.0",
|
||||
"version": "2.110.0",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
import { DomainEventInterface } from './DomainEventInterface'
|
||||
import { CloudBackupRequestedEventPayload } from './CloudBackupRequestedEventPayload'
|
||||
|
||||
export interface CloudBackupRequestedEvent extends DomainEventInterface {
|
||||
type: 'CLOUD_BACKUP_REQUESTED'
|
||||
payload: CloudBackupRequestedEventPayload
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
export interface CloudBackupRequestedEventPayload {
|
||||
cloudProvider: 'DROPBOX' | 'ONE_DRIVE' | 'GOOGLE_DRIVE'
|
||||
cloudProviderToken: string
|
||||
userUuid: string
|
||||
userHasEmailsMuted: boolean
|
||||
muteEmailsSettingUuid: string
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
export * from './Event/AccountDeletionRequestedEvent'
|
||||
export * from './Event/AccountDeletionRequestedEventPayload'
|
||||
export * from './Event/CloudBackupRequestedEvent'
|
||||
export * from './Event/CloudBackupRequestedEventPayload'
|
||||
export * from './Event/DiscountApplyRequestedEvent'
|
||||
export * from './Event/DiscountApplyRequestedEventPayload'
|
||||
export * from './Event/DiscountWithdrawRequestedEvent'
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.7.10](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.7.9...@standardnotes/event-store@1.7.10) (2023-04-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/event-store
|
||||
|
||||
## [1.7.9](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.7.8...@standardnotes/event-store@1.7.9) (2023-04-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/event-store
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/event-store",
|
||||
"version": "1.7.9",
|
||||
"version": "1.7.10",
|
||||
"description": "Event Store Service",
|
||||
"private": true,
|
||||
"main": "dist/src/index.js",
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.10.13](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.10.12...@standardnotes/files-server@1.10.13) (2023-04-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files-server
|
||||
|
||||
## [1.10.12](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.10.11...@standardnotes/files-server@1.10.12) (2023-04-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/files-server",
|
||||
"version": "1.10.12",
|
||||
"version": "1.10.13",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.12.16](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.12.15...@standardnotes/revisions-server@1.12.16) (2023-04-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
## [1.12.15](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.12.14...@standardnotes/revisions-server@1.12.15) (2023-04-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/revisions-server",
|
||||
"version": "1.12.15",
|
||||
"version": "1.12.16",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.17.13](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.17.12...@standardnotes/scheduler-server@1.17.13) (2023-04-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
## [1.17.12](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.17.11...@standardnotes/scheduler-server@1.17.12) (2023-04-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/scheduler-server",
|
||||
"version": "1.17.12",
|
||||
"version": "1.17.13",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.21.0](https://github.com/standardnotes/server/compare/@standardnotes/settings@1.20.2...@standardnotes/settings@1.21.0) (2023-04-27)
|
||||
|
||||
### Features
|
||||
|
||||
* remove cloud backups ([#574](https://github.com/standardnotes/server/issues/574)) ([484f554](https://github.com/standardnotes/server/commit/484f55433928e5c21ee59d8fda94ab3c887cd169))
|
||||
|
||||
## [1.20.2](https://github.com/standardnotes/server/compare/@standardnotes/settings@1.20.1...@standardnotes/settings@1.20.2) (2023-04-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/settings
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/settings",
|
||||
"version": "1.20.2",
|
||||
"version": "1.21.0",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
export enum CloudProvider {
|
||||
Dropbox = 'Dropbox',
|
||||
Google = 'Google Drive',
|
||||
OneDrive = 'OneDrive',
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
export enum DropboxBackupFrequency {
|
||||
Disabled = 'disabled',
|
||||
Daily = 'daily',
|
||||
Weekly = 'weekly',
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
export enum GoogleDriveBackupFrequency {
|
||||
Disabled = 'disabled',
|
||||
Daily = 'daily',
|
||||
Weekly = 'weekly',
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
export enum MuteFailedCloudBackupsEmailsOption {
|
||||
Muted = 'muted',
|
||||
NotMuted = 'not_muted',
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
export enum OneDriveBackupFrequency {
|
||||
Disabled = 'disabled',
|
||||
Daily = 'daily',
|
||||
Weekly = 'weekly',
|
||||
}
|
||||
@@ -1,13 +1,8 @@
|
||||
export * from './CloudProvider/CloudProvider'
|
||||
export * from './DropboxBackupFrequency/DropboxBackupFrequency'
|
||||
export * from './EmailBackupFrequency/EmailBackupFrequency'
|
||||
export * from './GoogleDriveBackupFrequency/GoogleDriveBackupFrequency'
|
||||
export * from './ListedAuthorSecretsData/ListedAuthorSecretsData'
|
||||
export * from './LogSessionUserAgent/LogSessionUserAgentOption'
|
||||
export * from './MuteFailedBackupsEmails/MuteFailedBackupsEmailsOption'
|
||||
export * from './MuteFailedCloudBackupsEmails/MuteFailedCloudBackupsEmailsOption'
|
||||
export * from './MuteMarketingEmails/MuteMarketingEmailsOption'
|
||||
export * from './MuteSignInEmails/MuteSignInEmailsOption'
|
||||
export * from './OneDriveBackupFrequency/OneDriveBackupFrequency'
|
||||
export * from './Setting/SettingName'
|
||||
export * from './Setting/SettingNameProps'
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.34.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.33.0...@standardnotes/syncing-server@1.34.0) (2023-04-27)
|
||||
|
||||
### Features
|
||||
|
||||
* remove cloud backups ([#574](https://github.com/standardnotes/syncing-server-js/issues/574)) ([484f554](https://github.com/standardnotes/syncing-server-js/commit/484f55433928e5c21ee59d8fda94ab3c887cd169))
|
||||
|
||||
# [1.33.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.32.8...@standardnotes/syncing-server@1.33.0) (2023-04-27)
|
||||
|
||||
### Features
|
||||
|
||||
* add syncing server sqlite driver ([#573](https://github.com/standardnotes/syncing-server-js/issues/573)) ([723ff44](https://github.com/standardnotes/syncing-server-js/commit/723ff441517ec2242d828ba8136a0ad827221868))
|
||||
|
||||
## [1.32.8](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.32.7...@standardnotes/syncing-server@1.32.8) (2023-04-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class initialBoilerplate1682587956616 implements MigrationInterface {
|
||||
name = 'initialBoilerplate1682587956616'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE "items" ("uuid" varchar PRIMARY KEY NOT NULL, "duplicate_of" varchar(36), "items_key_id" varchar(255), "content" text, "content_type" varchar(255), "content_size" integer, "enc_item_key" text, "auth_hash" varchar(255), "user_uuid" varchar(36) NOT NULL, "deleted" tinyint(1) DEFAULT (0), "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, "created_at_timestamp" bigint NOT NULL, "updated_at_timestamp" bigint NOT NULL, "updated_with_session" varchar(36))',
|
||||
)
|
||||
await queryRunner.query('CREATE INDEX "index_items_on_content_type" ON "items" ("content_type") ')
|
||||
await queryRunner.query('CREATE INDEX "index_items_on_user_uuid" ON "items" ("user_uuid") ')
|
||||
await queryRunner.query('CREATE INDEX "index_items_on_deleted" ON "items" ("deleted") ')
|
||||
await queryRunner.query('CREATE INDEX "updated_at_timestamp" ON "items" ("updated_at_timestamp") ')
|
||||
await queryRunner.query('CREATE INDEX "user_uuid_and_deleted" ON "items" ("user_uuid", "deleted") ')
|
||||
await queryRunner.query(
|
||||
'CREATE INDEX "user_uuid_and_updated_at_timestamp_and_created_at_timestamp" ON "items" ("user_uuid", "updated_at_timestamp", "created_at_timestamp") ',
|
||||
)
|
||||
await queryRunner.query(
|
||||
'CREATE INDEX "index_items_on_user_uuid_and_content_type" ON "items" ("user_uuid", "content_type") ',
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP INDEX "index_items_on_user_uuid_and_content_type"')
|
||||
await queryRunner.query('DROP INDEX "user_uuid_and_updated_at_timestamp_and_created_at_timestamp"')
|
||||
await queryRunner.query('DROP INDEX "user_uuid_and_deleted"')
|
||||
await queryRunner.query('DROP INDEX "updated_at_timestamp"')
|
||||
await queryRunner.query('DROP INDEX "index_items_on_deleted"')
|
||||
await queryRunner.query('DROP INDEX "index_items_on_user_uuid"')
|
||||
await queryRunner.query('DROP INDEX "index_items_on_content_type"')
|
||||
await queryRunner.query('DROP TABLE "items"')
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/syncing-server",
|
||||
"version": "1.32.8",
|
||||
"version": "1.34.0",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
@@ -41,6 +41,7 @@
|
||||
"@standardnotes/settings": "workspace:*",
|
||||
"@standardnotes/time": "workspace:*",
|
||||
"axios": "^1.1.3",
|
||||
"better-sqlite3": "^8.3.0",
|
||||
"cors": "2.8.5",
|
||||
"dotenv": "^16.0.1",
|
||||
"express": "^4.18.2",
|
||||
@@ -59,6 +60,7 @@
|
||||
"winston": "^3.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/better-sqlite3": "^7.6.4",
|
||||
"@types/cors": "^2.8.9",
|
||||
"@types/dotenv": "^8.2.0",
|
||||
"@types/express": "^4.17.14",
|
||||
|
||||
@@ -6,7 +6,7 @@ import TYPES from './Types'
|
||||
import { AppDataSource } from './DataSource'
|
||||
import { SNSClient, SNSClientConfig } from '@aws-sdk/client-sns'
|
||||
import { ItemRepositoryInterface } from '../Domain/Item/ItemRepositoryInterface'
|
||||
import { MySQLItemRepository } from '../Infra/MySQL/MySQLItemRepository'
|
||||
import { TypeORMItemRepository } from '../Infra/TypeORM/TypeORMItemRepository'
|
||||
import { Repository } from 'typeorm'
|
||||
import { Item } from '../Domain/Item/Item'
|
||||
import { ItemProjection } from '../Projection/ItemProjection'
|
||||
@@ -74,7 +74,7 @@ export class CommonContainerConfigLoader {
|
||||
|
||||
// Repositories
|
||||
container.bind<ItemRepositoryInterface>(TYPES.ItemRepository).toDynamicValue((context: interfaces.Context) => {
|
||||
return new MySQLItemRepository(context.container.get(TYPES.ORMItemRepository))
|
||||
return new TypeORMItemRepository(context.container.get(TYPES.ORMItemRepository))
|
||||
})
|
||||
|
||||
// ORM
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import { DataSource, LoggerOptions } from 'typeorm'
|
||||
import { BetterSqlite3ConnectionOptions } from 'typeorm/driver/better-sqlite3/BetterSqlite3ConnectionOptions'
|
||||
import { MysqlConnectionOptions } from 'typeorm/driver/mysql/MysqlConnectionOptions'
|
||||
import { Item } from '../Domain/Item/Item'
|
||||
import { Env } from './Env'
|
||||
|
||||
const env: Env = new Env()
|
||||
env.load()
|
||||
|
||||
const isConfiguredForMySQL = env.get('DB_TYPE') === 'mysql'
|
||||
|
||||
const maxQueryExecutionTime = env.get('DB_MAX_QUERY_EXECUTION_TIME', true)
|
||||
? +env.get('DB_MAX_QUERY_EXECUTION_TIME', true)
|
||||
: 45_000
|
||||
@@ -32,20 +36,32 @@ const replicationConfig = {
|
||||
restoreNodeTimeout: 5,
|
||||
}
|
||||
|
||||
export const AppDataSource = new DataSource({
|
||||
const commonDataSourceOptions = {
|
||||
maxQueryExecutionTime,
|
||||
entities: [Item],
|
||||
migrations: [`dist/migrations/${isConfiguredForMySQL ? 'mysql' : 'sqlite'}/*.js`],
|
||||
migrationsRun: true,
|
||||
logging: <LoggerOptions>env.get('DB_DEBUG_LEVEL'),
|
||||
}
|
||||
|
||||
const mySQLDataSourceOptions: MysqlConnectionOptions = {
|
||||
...commonDataSourceOptions,
|
||||
type: 'mysql',
|
||||
charset: 'utf8mb4',
|
||||
supportBigNumbers: true,
|
||||
bigNumberStrings: false,
|
||||
maxQueryExecutionTime,
|
||||
replication: inReplicaMode ? replicationConfig : undefined,
|
||||
host: inReplicaMode ? undefined : env.get('DB_HOST'),
|
||||
port: inReplicaMode ? undefined : parseInt(env.get('DB_PORT')),
|
||||
username: inReplicaMode ? undefined : env.get('DB_USERNAME'),
|
||||
password: inReplicaMode ? undefined : env.get('DB_PASSWORD'),
|
||||
database: inReplicaMode ? undefined : env.get('DB_DATABASE'),
|
||||
entities: [Item],
|
||||
migrations: [env.get('DB_MIGRATIONS_PATH', true) ?? 'dist/migrations/*.js'],
|
||||
migrationsRun: true,
|
||||
logging: <LoggerOptions>env.get('DB_DEBUG_LEVEL'),
|
||||
})
|
||||
}
|
||||
|
||||
const sqliteDataSourceOptions: BetterSqlite3ConnectionOptions = {
|
||||
...commonDataSourceOptions,
|
||||
type: 'better-sqlite3',
|
||||
database: `data/${env.get('DB_DATABASE')}.sqlite`,
|
||||
}
|
||||
|
||||
export const AppDataSource = new DataSource(isConfiguredForMySQL ? mySQLDataSourceOptions : sqliteDataSourceOptions)
|
||||
|
||||
@@ -42,7 +42,6 @@ const TYPES = {
|
||||
AccountDeletionRequestedEventHandler: Symbol.for('AccountDeletionRequestedEventHandler'),
|
||||
DuplicateItemSyncedEventHandler: Symbol.for('DuplicateItemSyncedEventHandler'),
|
||||
EmailBackupRequestedEventHandler: Symbol.for('EmailBackupRequestedEventHandler'),
|
||||
CloudBackupRequestedEventHandler: Symbol.for('CloudBackupRequestedEventHandler'),
|
||||
ItemRevisionCreationRequestedEventHandler: Symbol.for('ItemRevisionCreationRequestedEventHandler'),
|
||||
// Services
|
||||
ContentDecoder: Symbol.for('ContentDecoder'),
|
||||
|
||||
@@ -27,7 +27,6 @@ import {
|
||||
SQSNewRelicEventMessageHandler,
|
||||
} from '@standardnotes/domain-events-infra'
|
||||
import { EmailBackupRequestedEventHandler } from '../Domain/Handler/EmailBackupRequestedEventHandler'
|
||||
import { CloudBackupRequestedEventHandler } from '../Domain/Handler/CloudBackupRequestedEventHandler'
|
||||
import { ItemRevisionCreationRequestedEventHandler } from '../Domain/Handler/ItemRevisionCreationRequestedEventHandler'
|
||||
import { FSItemBackupService } from '../Infra/FS/FSItemBackupService'
|
||||
import { CommonContainerConfigLoader } from './CommonContainerConfigLoader'
|
||||
@@ -122,18 +121,6 @@ export class WorkerContainerConfigLoader extends CommonContainerConfigLoader {
|
||||
context.container.get(TYPES.Logger),
|
||||
)
|
||||
})
|
||||
container
|
||||
.bind<CloudBackupRequestedEventHandler>(TYPES.CloudBackupRequestedEventHandler)
|
||||
.toDynamicValue((context: interfaces.Context) => {
|
||||
return new CloudBackupRequestedEventHandler(
|
||||
context.container.get(TYPES.ItemRepository),
|
||||
context.container.get(TYPES.AuthHttpService),
|
||||
context.container.get(TYPES.ExtensionsHttpService),
|
||||
context.container.get(TYPES.ItemBackupService),
|
||||
context.container.get(TYPES.EXTENSIONS_SERVER_URL),
|
||||
context.container.get(TYPES.Logger),
|
||||
)
|
||||
})
|
||||
container
|
||||
.bind<ItemRevisionCreationRequestedEventHandler>(TYPES.ItemRevisionCreationRequestedEventHandler)
|
||||
.toDynamicValue((context: interfaces.Context) => {
|
||||
@@ -194,7 +181,6 @@ export class WorkerContainerConfigLoader extends CommonContainerConfigLoader {
|
||||
['DUPLICATE_ITEM_SYNCED', context.container.get(TYPES.DuplicateItemSyncedEventHandler)],
|
||||
['ACCOUNT_DELETION_REQUESTED', context.container.get(TYPES.AccountDeletionRequestedEventHandler)],
|
||||
['EMAIL_BACKUP_REQUESTED', context.container.get(TYPES.EmailBackupRequestedEventHandler)],
|
||||
['CLOUD_BACKUP_REQUESTED', context.container.get(TYPES.CloudBackupRequestedEventHandler)],
|
||||
['ITEM_REVISION_CREATION_REQUESTED', context.container.get(TYPES.ItemRevisionCreationRequestedEventHandler)],
|
||||
])
|
||||
|
||||
|
||||
@@ -1,177 +0,0 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { CloudBackupRequestedEvent } from '@standardnotes/domain-events'
|
||||
import { AuthHttpServiceInterface } from '../Auth/AuthHttpServiceInterface'
|
||||
import { Item } from '../Item/Item'
|
||||
import { ItemRepositoryInterface } from '../Item/ItemRepositoryInterface'
|
||||
import { CloudBackupRequestedEventHandler } from './CloudBackupRequestedEventHandler'
|
||||
import { ItemBackupServiceInterface } from '../Item/ItemBackupServiceInterface'
|
||||
import { ExtensionsHttpServiceInterface } from '../Extension/ExtensionsHttpServiceInterface'
|
||||
import { Logger } from 'winston'
|
||||
|
||||
describe('CloudBackupRequestedEventHandler', () => {
|
||||
let itemRepository: ItemRepositoryInterface
|
||||
let authHttpService: AuthHttpServiceInterface
|
||||
let extensionsHttpService: ExtensionsHttpServiceInterface
|
||||
let itemBackupService: ItemBackupServiceInterface
|
||||
const extensionsServerUrl = 'https://extensions-server'
|
||||
let event: CloudBackupRequestedEvent
|
||||
let item: Item
|
||||
let logger: Logger
|
||||
|
||||
const createHandler = () =>
|
||||
new CloudBackupRequestedEventHandler(
|
||||
itemRepository,
|
||||
authHttpService,
|
||||
extensionsHttpService,
|
||||
itemBackupService,
|
||||
extensionsServerUrl,
|
||||
logger,
|
||||
)
|
||||
|
||||
beforeEach(() => {
|
||||
item = {} as jest.Mocked<Item>
|
||||
|
||||
itemRepository = {} as jest.Mocked<ItemRepositoryInterface>
|
||||
itemRepository.findAll = jest.fn().mockReturnValue([item])
|
||||
|
||||
authHttpService = {} as jest.Mocked<AuthHttpServiceInterface>
|
||||
authHttpService.getUserKeyParams = jest.fn().mockReturnValue({ foo: 'bar' })
|
||||
|
||||
extensionsHttpService = {} as jest.Mocked<ExtensionsHttpServiceInterface>
|
||||
extensionsHttpService.triggerCloudBackupOnExtensionsServer = jest.fn()
|
||||
|
||||
event = {} as jest.Mocked<CloudBackupRequestedEvent>
|
||||
event.createdAt = new Date(1)
|
||||
event.payload = {
|
||||
cloudProvider: 'DROPBOX',
|
||||
cloudProviderToken: 'test-token',
|
||||
userUuid: '1-2-3',
|
||||
muteEmailsSettingUuid: '2-3-4',
|
||||
userHasEmailsMuted: false,
|
||||
}
|
||||
|
||||
itemBackupService = {} as jest.Mocked<ItemBackupServiceInterface>
|
||||
itemBackupService.backup = jest.fn().mockReturnValue(['backup-file-name'])
|
||||
|
||||
logger = {} as jest.Mocked<Logger>
|
||||
logger.debug = jest.fn()
|
||||
logger.warn = jest.fn()
|
||||
})
|
||||
|
||||
it('should trigger cloud backup on extensions server - dropbox', async () => {
|
||||
await createHandler().handle(event)
|
||||
|
||||
expect(itemRepository.findAll).toHaveBeenCalledWith({
|
||||
sortBy: 'updated_at_timestamp',
|
||||
sortOrder: 'ASC',
|
||||
userUuid: '1-2-3',
|
||||
deleted: false,
|
||||
})
|
||||
|
||||
expect(extensionsHttpService.triggerCloudBackupOnExtensionsServer).toHaveBeenCalledWith({
|
||||
authParams: {
|
||||
foo: 'bar',
|
||||
},
|
||||
backupFilename: 'backup-file-name',
|
||||
cloudProvider: 'DROPBOX',
|
||||
extensionsServerUrl: 'https://extensions-server/dropbox/items/sync?type=sf&dbt=test-token',
|
||||
muteEmailsSettingUuid: '2-3-4',
|
||||
forceMute: false,
|
||||
userUuid: '1-2-3',
|
||||
})
|
||||
})
|
||||
|
||||
it('should trigger cloud backup on extensions server - google drive', async () => {
|
||||
event.payload.cloudProvider = 'GOOGLE_DRIVE'
|
||||
|
||||
await createHandler().handle(event)
|
||||
|
||||
expect(extensionsHttpService.triggerCloudBackupOnExtensionsServer).toHaveBeenCalledWith({
|
||||
authParams: {
|
||||
foo: 'bar',
|
||||
},
|
||||
backupFilename: 'backup-file-name',
|
||||
cloudProvider: 'GOOGLE_DRIVE',
|
||||
extensionsServerUrl: 'https://extensions-server/gdrive/sync?key=test-token',
|
||||
muteEmailsSettingUuid: '2-3-4',
|
||||
forceMute: false,
|
||||
userUuid: '1-2-3',
|
||||
})
|
||||
})
|
||||
|
||||
it('should trigger cloud backup on extensions server - one drive', async () => {
|
||||
event.payload.cloudProvider = 'ONE_DRIVE'
|
||||
|
||||
await createHandler().handle(event)
|
||||
|
||||
expect(extensionsHttpService.triggerCloudBackupOnExtensionsServer).toHaveBeenCalledWith({
|
||||
authParams: {
|
||||
foo: 'bar',
|
||||
},
|
||||
backupFilename: 'backup-file-name',
|
||||
cloudProvider: 'ONE_DRIVE',
|
||||
extensionsServerUrl: 'https://extensions-server/onedrive/sync?type=sf&key=test-token',
|
||||
muteEmailsSettingUuid: '2-3-4',
|
||||
forceMute: false,
|
||||
userUuid: '1-2-3',
|
||||
})
|
||||
})
|
||||
|
||||
it('should not trigger cloud backup on extensions server - unknown', async () => {
|
||||
event.payload.cloudProvider = 'test' as 'DROPBOX' | 'GOOGLE_DRIVE' | 'ONE_DRIVE'
|
||||
|
||||
let expectedError = null
|
||||
try {
|
||||
await createHandler().handle(event)
|
||||
} catch (error) {
|
||||
expectedError = error
|
||||
}
|
||||
|
||||
expect(extensionsHttpService.triggerCloudBackupOnExtensionsServer).not.toHaveBeenCalled()
|
||||
expect(expectedError).not.toBeNull()
|
||||
})
|
||||
|
||||
it('should not trigger cloud backup if backup filename is not returned', async () => {
|
||||
itemBackupService.backup = jest.fn().mockReturnValue([])
|
||||
|
||||
await createHandler().handle(event)
|
||||
|
||||
expect(extensionsHttpService.triggerCloudBackupOnExtensionsServer).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should trigger cloud backup on extensions server with muted emails', async () => {
|
||||
event.payload.userHasEmailsMuted = true
|
||||
|
||||
await createHandler().handle(event)
|
||||
|
||||
expect(itemRepository.findAll).toHaveBeenCalledWith({
|
||||
sortBy: 'updated_at_timestamp',
|
||||
sortOrder: 'ASC',
|
||||
userUuid: '1-2-3',
|
||||
deleted: false,
|
||||
})
|
||||
|
||||
expect(extensionsHttpService.triggerCloudBackupOnExtensionsServer).toHaveBeenCalledWith({
|
||||
authParams: {
|
||||
foo: 'bar',
|
||||
},
|
||||
backupFilename: 'backup-file-name',
|
||||
cloudProvider: 'DROPBOX',
|
||||
extensionsServerUrl: 'https://extensions-server/dropbox/items/sync?type=sf&dbt=test-token',
|
||||
muteEmailsSettingUuid: '2-3-4',
|
||||
forceMute: true,
|
||||
userUuid: '1-2-3',
|
||||
})
|
||||
})
|
||||
|
||||
it('should skip triggering cloud backups on extensions server if user key params cannot be obtained', async () => {
|
||||
authHttpService.getUserKeyParams = jest.fn().mockImplementation(() => {
|
||||
throw new Error('Oops!')
|
||||
})
|
||||
|
||||
await createHandler().handle(event)
|
||||
|
||||
expect(extensionsHttpService.triggerCloudBackupOnExtensionsServer).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
@@ -1,80 +0,0 @@
|
||||
import { DomainEventHandlerInterface, CloudBackupRequestedEvent } from '@standardnotes/domain-events'
|
||||
|
||||
import { ItemRepositoryInterface } from '../Item/ItemRepositoryInterface'
|
||||
import { ItemQuery } from '../Item/ItemQuery'
|
||||
import { AuthHttpServiceInterface } from '../Auth/AuthHttpServiceInterface'
|
||||
import { Item } from '../Item/Item'
|
||||
import { ExtensionsHttpServiceInterface } from '../Extension/ExtensionsHttpServiceInterface'
|
||||
import { ItemBackupServiceInterface } from '../Item/ItemBackupServiceInterface'
|
||||
import { Logger } from 'winston'
|
||||
import { KeyParamsData } from '@standardnotes/responses'
|
||||
|
||||
export class CloudBackupRequestedEventHandler implements DomainEventHandlerInterface {
|
||||
constructor(
|
||||
private itemRepository: ItemRepositoryInterface,
|
||||
private authHttpService: AuthHttpServiceInterface,
|
||||
private extensionsHttpService: ExtensionsHttpServiceInterface,
|
||||
private itemBackupService: ItemBackupServiceInterface,
|
||||
private extensionsServerUrl: string,
|
||||
private logger: Logger,
|
||||
) {}
|
||||
|
||||
async handle(event: CloudBackupRequestedEvent): Promise<void> {
|
||||
const items = await this.getItemsForPostingToExtension(event)
|
||||
|
||||
let authParams: KeyParamsData
|
||||
try {
|
||||
authParams = await this.authHttpService.getUserKeyParams({
|
||||
uuid: event.payload.userUuid,
|
||||
authenticated: false,
|
||||
})
|
||||
} catch (error) {
|
||||
this.logger.warn(`Could not get user key params from auth service: ${(error as Error).message}`)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const backupFilenames = await this.itemBackupService.backup(items, authParams)
|
||||
if (backupFilenames.length === 0) {
|
||||
this.logger.warn(`No backup files created for user ${event.payload.userUuid}`)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
this.logger.debug(`Sending ${items.length} items to extensions server for user ${event.payload.userUuid}`)
|
||||
|
||||
await this.extensionsHttpService.triggerCloudBackupOnExtensionsServer({
|
||||
cloudProvider: event.payload.cloudProvider,
|
||||
authParams,
|
||||
backupFilename: backupFilenames[0],
|
||||
forceMute: event.payload.userHasEmailsMuted,
|
||||
muteEmailsSettingUuid: event.payload.muteEmailsSettingUuid,
|
||||
extensionsServerUrl: this.getExtensionsServerUrl(event),
|
||||
userUuid: event.payload.userUuid,
|
||||
})
|
||||
}
|
||||
|
||||
private getExtensionsServerUrl(event: CloudBackupRequestedEvent): string {
|
||||
switch (event.payload.cloudProvider) {
|
||||
case 'ONE_DRIVE':
|
||||
return `${this.extensionsServerUrl}/onedrive/sync?type=sf&key=${event.payload.cloudProviderToken}`
|
||||
case 'GOOGLE_DRIVE':
|
||||
return `${this.extensionsServerUrl}/gdrive/sync?key=${event.payload.cloudProviderToken}`
|
||||
case 'DROPBOX':
|
||||
return `${this.extensionsServerUrl}/dropbox/items/sync?type=sf&dbt=${event.payload.cloudProviderToken}`
|
||||
default:
|
||||
throw new Error(`Unsupported cloud provider ${event.payload.cloudProvider}`)
|
||||
}
|
||||
}
|
||||
|
||||
private async getItemsForPostingToExtension(event: CloudBackupRequestedEvent): Promise<Item[]> {
|
||||
const itemQuery: ItemQuery = {
|
||||
userUuid: event.payload.userUuid,
|
||||
sortBy: 'updated_at_timestamp',
|
||||
sortOrder: 'ASC',
|
||||
deleted: false,
|
||||
}
|
||||
|
||||
return this.itemRepository.findAll(itemQuery)
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ export class Item {
|
||||
declare itemsKeyId: string | null
|
||||
|
||||
@Column({
|
||||
type: 'mediumtext',
|
||||
type: 'text',
|
||||
nullable: true,
|
||||
})
|
||||
declare content: string | null
|
||||
|
||||
@@ -5,7 +5,7 @@ import { ItemRepositoryInterface } from '../../Domain/Item/ItemRepositoryInterfa
|
||||
import { ReadStream } from 'fs'
|
||||
import { ExtendedIntegrityPayload } from '../../Domain/Item/ExtendedIntegrityPayload'
|
||||
|
||||
export class MySQLItemRepository implements ItemRepositoryInterface {
|
||||
export class TypeORMItemRepository implements ItemRepositoryInterface {
|
||||
constructor(private ormRepository: Repository<Item>) {}
|
||||
|
||||
async save(item: Item): Promise<Item> {
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.6.14](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.6.13...@standardnotes/websockets-server@1.6.14) (2023-04-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/websockets-server
|
||||
|
||||
## [1.6.13](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.6.12...@standardnotes/websockets-server@1.6.13) (2023-04-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/websockets-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/websockets-server",
|
||||
"version": "1.6.13",
|
||||
"version": "1.6.14",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -3774,6 +3774,7 @@ __metadata:
|
||||
"@standardnotes/security": "workspace:*"
|
||||
"@standardnotes/settings": "workspace:*"
|
||||
"@standardnotes/time": "workspace:*"
|
||||
"@types/better-sqlite3": "npm:^7.6.4"
|
||||
"@types/cors": "npm:^2.8.9"
|
||||
"@types/dotenv": "npm:^8.2.0"
|
||||
"@types/express": "npm:^4.17.14"
|
||||
@@ -3786,6 +3787,7 @@ __metadata:
|
||||
"@types/uuid": "npm:^8.3.0"
|
||||
"@typescript-eslint/eslint-plugin": "npm:^5.48.2"
|
||||
axios: "npm:^1.1.3"
|
||||
better-sqlite3: "npm:^8.3.0"
|
||||
cors: "npm:2.8.5"
|
||||
dotenv: "npm:^16.0.1"
|
||||
eslint: "npm:^8.32.0"
|
||||
|
||||
Reference in New Issue
Block a user