Compare commits

..

1 Commits

Author SHA1 Message Date
dependabot[bot]
0055edc3e4 chore(deps): bump actions/setup-node from 3 to 4
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3 to 4.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-06 06:55:37 +00:00
95 changed files with 430 additions and 537 deletions

2
.github/ci.env vendored
View File

@@ -26,5 +26,3 @@ MYSQL_ROOT_PASSWORD=changeme123
AUTH_JWT_SECRET=f95259c5e441f5a4646d76422cfb3df4c4488842901aa50b6c51b8be2e0040e9
AUTH_SERVER_ENCRYPTION_SERVER_KEY=1087415dfde3093797f9a7ca93a49e7d7aa1861735eb0d32aae9c303b8c3d060
VALET_TOKEN_SECRET=4b886819ebe1e908077c6cae96311b48a8416bd60cc91c03060e15bdf6b30d1f
SYNCING_SERVER_CONTENT_SIZE_TRANSFER_LIMIT=1000000

View File

@@ -42,7 +42,7 @@ jobs:
key: ${{ runner.os }}-${{ inputs.service_name }}-build-${{ github.sha }}
- name: Set up Node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
registry-url: 'https://registry.npmjs.org'
node-version-file: '.nvmrc'

View File

@@ -46,7 +46,7 @@ jobs:
- uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
registry-url: 'https://registry.npmjs.org'
node-version-file: '.nvmrc'
@@ -70,7 +70,6 @@ jobs:
echo "ACCESS_TOKEN_AGE=4" >> packages/home-server/.env
echo "REFRESH_TOKEN_AGE=10" >> packages/home-server/.env
echo "REVISIONS_FREQUENCY=2" >> packages/home-server/.env
echo "CONTENT_SIZE_TRANSFER_LIMIT=1000000" >> packages/home-server/.env
echo "DB_HOST=localhost" >> packages/home-server/.env
echo "DB_PORT=3306" >> packages/home-server/.env
echo "DB_DATABASE=standardnotes" >> packages/home-server/.env

View File

@@ -29,7 +29,7 @@ jobs:
- uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
registry-url: 'https://registry.npmjs.org'
node-version-file: '.nvmrc'

View File

@@ -20,7 +20,7 @@ jobs:
key: ${{ runner.os }}-build-${{ github.sha }}
- name: Set up Node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
registry-url: 'https://registry.npmjs.org'
node-version-file: '.nvmrc'
@@ -48,7 +48,7 @@ jobs:
key: ${{ runner.os }}-build-${{ github.sha }}
- name: Set up Node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
registry-url: 'https://registry.npmjs.org'
node-version-file: '.nvmrc'
@@ -80,7 +80,7 @@ jobs:
key: ${{ runner.os }}-build-${{ github.sha }}
- name: Set up Node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
registry-url: 'https://registry.npmjs.org'
node-version-file: '.nvmrc'

View File

@@ -20,7 +20,7 @@ jobs:
key: ${{ runner.os }}-build-${{ github.sha }}
- name: Set up Node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
registry-url: 'https://registry.npmjs.org'
node-version-file: '.nvmrc'
@@ -48,7 +48,7 @@ jobs:
key: ${{ runner.os }}-build-${{ github.sha }}
- name: Set up Node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
registry-url: 'https://registry.npmjs.org'
node-version-file: '.nvmrc'
@@ -80,7 +80,7 @@ jobs:
key: ${{ runner.os }}-build-${{ github.sha }}
- name: Set up Node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
registry-url: 'https://registry.npmjs.org'
node-version-file: '.nvmrc'
@@ -151,7 +151,7 @@ jobs:
git_commit_gpgsign: true
- name: Set up Node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
registry-url: 'https://registry.npmjs.org'
node-version-file: '.nvmrc'

View File

@@ -3,16 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.32.6](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.32.5...@standardnotes/analytics@2.32.6) (2023-11-07)
**Note:** Version bump only for package @standardnotes/analytics
## [2.32.5](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.32.4...@standardnotes/analytics@2.32.5) (2023-11-07)
### Bug Fixes
* remove open telemetry from code ([#903](https://github.com/standardnotes/server/issues/903)) ([751f3b2](https://github.com/standardnotes/server/commit/751f3b25476c5be3d663ad8540c43266acd39493))
## [2.32.4](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.32.3...@standardnotes/analytics@2.32.4) (2023-10-26)
**Note:** Version bump only for package @standardnotes/analytics

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK, OpenTelemetryTracer } from '@standardnotes/domain-events-infra'
import { EmailLevel, ServiceIdentifier } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.AnalyticsScheduledTask })
sdk.start()
import { Logger } from 'winston'
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
@@ -16,7 +22,6 @@ import { CalculateMonthlyRecurringRevenue } from '../src/Domain/UseCase/Calculat
import { getBody, getSubject } from '../src/Domain/Email/DailyAnalyticsReport'
import { TimerInterface } from '@standardnotes/time'
import { StatisticMeasureName } from '../src/Domain/Statistics/StatisticMeasureName'
import { EmailLevel } from '@standardnotes/domain-core'
const requestReport = async (
analyticsStore: AnalyticsStoreInterface,
@@ -270,6 +275,9 @@ void container.load().then((container) => {
logger.info(`Sending report to following admins: ${adminEmails}`)
const tracer = new OpenTelemetryTracer()
tracer.startSpan(ServiceIdentifier.NAMES.AnalyticsScheduledTask, 'report')
Promise.resolve(
requestReport(
analyticsStore,
@@ -285,11 +293,15 @@ void container.load().then((container) => {
.then(() => {
logger.info('Usage report generation complete')
tracer.stopSpan()
process.exit(0)
})
.catch((error) => {
logger.error(`Could not finish usage report generation: ${error.message}`)
tracer.stopSpanWithError(error)
process.exit(1)
})
})

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.AnalyticsWorker })
sdk.start()
import { Logger } from 'winston'
import { DomainEventSubscriberInterface } from '@standardnotes/domain-events'
import * as dayjs from 'dayjs'

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/analytics",
"version": "2.32.6",
"version": "2.32.4",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -7,7 +7,7 @@ import {
DomainEventPublisherInterface,
DomainEventSubscriberInterface,
} from '@standardnotes/domain-events'
import { MapperInterface } from '@standardnotes/domain-core'
import { MapperInterface, ServiceIdentifier } from '@standardnotes/domain-core'
// eslint-disable-next-line @typescript-eslint/no-var-requires
const Mixpanel = require('mixpanel')
@@ -16,9 +16,9 @@ import TYPES from './Types'
import { AppDataSource } from './DataSource'
import { DomainEventFactory } from '../Domain/Event/DomainEventFactory'
import {
SNSDomainEventPublisher,
SQSDomainEventSubscriber,
SNSOpenTelemetryDomainEventPublisher,
SQSEventMessageHandler,
SQSOpenTelemetryDomainEventSubscriber,
} from '@standardnotes/domain-events-infra'
import { Timer, TimerInterface } from '@standardnotes/time'
import { PeriodKeyGeneratorInterface } from '../Domain/Time/PeriodKeyGeneratorInterface'
@@ -139,7 +139,9 @@ export class ContainerConfigLoader {
container
.bind<DomainEventPublisherInterface>(TYPES.DomainEventPublisher)
.toConstantValue(new SNSDomainEventPublisher(container.get(TYPES.SNS), container.get(TYPES.SNS_TOPIC_ARN)))
.toConstantValue(
new SNSOpenTelemetryDomainEventPublisher(container.get(TYPES.SNS), container.get(TYPES.SNS_TOPIC_ARN)),
)
if (env.get('MIXPANEL_TOKEN', true)) {
container.bind<Mixpanel>(TYPES.MixpanelClient).toConstantValue(Mixpanel.init(env.get('MIXPANEL_TOKEN', true)))
}
@@ -240,7 +242,8 @@ export class ContainerConfigLoader {
container
.bind<DomainEventSubscriberInterface>(TYPES.DomainEventSubscriber)
.toConstantValue(
new SQSDomainEventSubscriber(
new SQSOpenTelemetryDomainEventSubscriber(
ServiceIdentifier.NAMES.AnalyticsWorker,
container.get<SQSClient>(TYPES.SQS),
container.get<string>(TYPES.SQS_QUEUE_URL),
container.get<DomainEventMessageHandlerInterface>(TYPES.DomainEventMessageHandler),

View File

@@ -3,22 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.81.11](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.81.10...@standardnotes/api-gateway@1.81.11) (2023-11-07)
### Bug Fixes
* **api-gateway:** remove calling both auth and payments on account deletion request ([6b554c2](https://github.com/standardnotes/api-gateway/commit/6b554c28b731a9080d7ad2942d3fa05c01dcabf2))
## [1.81.10](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.81.9...@standardnotes/api-gateway@1.81.10) (2023-11-07)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.81.9](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.81.8...@standardnotes/api-gateway@1.81.9) (2023-11-07)
### Bug Fixes
* remove open telemetry from code ([#903](https://github.com/standardnotes/api-gateway/issues/903)) ([751f3b2](https://github.com/standardnotes/api-gateway/commit/751f3b25476c5be3d663ad8540c43266acd39493))
## [1.81.8](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.81.7...@standardnotes/api-gateway@1.81.8) (2023-11-03)
### Bug Fixes

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.ApiGateway })
sdk.start()
import '../src/Controller/LegacyController'
import '../src/Controller/HealthCheckController'

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/api-gateway",
"version": "1.81.11",
"version": "1.81.8",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -23,6 +23,7 @@ export class UsersController extends BaseHttpController {
@inject(TYPES.ApiGateway_ServiceProxy) private httpService: ServiceProxyInterface,
@inject(TYPES.ApiGateway_EndpointResolver) private endpointResolver: EndpointResolverInterface,
@inject(TYPES.ApiGateway_Logger) private logger: Logger,
@inject(TYPES.ApiGateway_IS_CONFIGURED_FOR_HOME_SERVER) private isConfiguredForHomeServer: boolean,
) {
super()
}
@@ -237,6 +238,10 @@ export class UsersController extends BaseHttpController {
@httpDelete('/:userUuid', TYPES.ApiGateway_RequiredCrossServiceTokenMiddleware)
async deleteUser(request: Request, response: Response): Promise<void> {
if (!this.isConfiguredForHomeServer) {
await this.httpService.callPaymentsServer(request, response, 'api/account', request.body, true)
}
await this.httpService.callAuthServer(
request,
response,

View File

@@ -151,6 +151,7 @@ export class HttpServiceProxy implements ServiceProxyInterface {
response: Response,
endpointOrMethodIdentifier: string,
payload?: Record<string, unknown> | string,
returnRawResponse?: boolean,
): Promise<void | Response<unknown, Record<string, unknown>>> {
if (!this.paymentsServerUrl) {
this.logger.debug('Payments Server URL not defined. Skipped request to Payments API.')
@@ -158,13 +159,18 @@ export class HttpServiceProxy implements ServiceProxyInterface {
return
}
await this.callServerWithLegacyFormat(
const rawResponse = await this.callServerWithLegacyFormat(
this.paymentsServerUrl,
request,
response,
endpointOrMethodIdentifier,
payload,
returnRawResponse,
)
if (returnRawResponse) {
return rawResponse
}
}
async callAuthServerWithLegacyFormat(
@@ -339,6 +345,7 @@ export class HttpServiceProxy implements ServiceProxyInterface {
response: Response,
endpointOrMethodIdentifier: string,
payload?: Record<string, unknown> | string,
returnRawResponse?: boolean,
): Promise<void | Response<unknown, Record<string, unknown>>> {
const serviceResponse = await this.getServerResponse(
serverUrl,
@@ -357,10 +364,18 @@ export class HttpServiceProxy implements ServiceProxyInterface {
if (serviceResponse.request._redirectable._redirectCount > 0) {
response.status(302)
if (returnRawResponse) {
return response
}
response.redirect(serviceResponse.request.res.responseUrl)
} else {
response.status(serviceResponse.status)
if (returnRawResponse) {
return response
}
response.send(serviceResponse.data)
}
}

View File

@@ -42,6 +42,7 @@ export interface ServiceProxyInterface {
response: Response,
endpointOrMethodIdentifier: string,
payload?: Record<string, unknown> | string,
returnRawResponse?: boolean,
): Promise<void | Response<unknown, Record<string, unknown>>>
callWebSocketServer(
request: Request,

View File

@@ -3,18 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.165.4](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.165.3...@standardnotes/auth-server@1.165.4) (2023-11-07)
### Bug Fixes
* account deletion event ([#904](https://github.com/standardnotes/server/issues/904)) ([d66ae62](https://github.com/standardnotes/server/commit/d66ae62cf4f413cac5f6f4eac45dc0f1ddbc9e32))
## [1.165.3](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.165.2...@standardnotes/auth-server@1.165.3) (2023-11-07)
### Bug Fixes
* remove open telemetry from code ([#903](https://github.com/standardnotes/server/issues/903)) ([751f3b2](https://github.com/standardnotes/server/commit/751f3b25476c5be3d663ad8540c43266acd39493))
## [1.165.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.165.1...@standardnotes/auth-server@1.165.2) (2023-11-03)
### Bug Fixes

View File

@@ -1,6 +1,10 @@
import 'reflect-metadata'
import { SettingName } from '@standardnotes/domain-core'
import { OpenTelemetrySDK, OpenTelemetryTracer } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier, SettingName } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.AuthScheduledTask })
sdk.start()
import { Stream } from 'stream'
@@ -102,17 +106,24 @@ void container.load().then((container) => {
const domainEventPublisher: DomainEventPublisherInterface = container.get(TYPES.Auth_DomainEventPublisher)
const getUserKeyParamsUseCase: GetUserKeyParams = container.get(TYPES.Auth_GetUserKeyParams)
const tracer = new OpenTelemetryTracer()
tracer.startSpan(ServiceIdentifier.NAMES.AuthScheduledTask, 'backup')
Promise.resolve(
requestBackups(settingRepository, roleService, domainEventFactory, domainEventPublisher, getUserKeyParamsUseCase),
)
.then(() => {
logger.info(`${backupFrequency} ${backupProvider} backup requesting complete`)
tracer.stopSpan()
process.exit(0)
})
.catch((error) => {
logger.error(`Could not finish ${backupFrequency} ${backupProvider} backup requesting: ${error.message}`)
tracer.stopSpanWithError(error)
process.exit(1)
})
})

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK, OpenTelemetryTracer } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.AuthScheduledTask })
sdk.start()
import { Logger } from 'winston'
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
@@ -30,15 +36,22 @@ void container.load().then((container) => {
const cleanupSessionTraces: CleanupSessionTraces = container.get(TYPES.Auth_CleanupSessionTraces)
const cleanupExpiredSessions: CleanupExpiredSessions = container.get(TYPES.Auth_CleanupExpiredSessions)
const tracer = new OpenTelemetryTracer()
tracer.startSpan(ServiceIdentifier.NAMES.AuthScheduledTask, 'cleanup')
Promise.resolve(cleanup(cleanupSessionTraces, cleanupExpiredSessions))
.then(() => {
logger.info('Expired sessions and session traces cleaned.')
tracer.stopSpan()
process.exit(0)
})
.catch((error) => {
logger.error(`Could not clean sessions and session traces: ${error.message}`)
tracer.stopSpanWithError(error)
process.exit(1)
})
})

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.Auth })
sdk.start()
import '../src/Infra/InversifyExpressUtils/AnnotatedAuthController'
import '../src/Infra/InversifyExpressUtils/AnnotatedAuthenticatorsController'
import '../src/Infra/InversifyExpressUtils/AnnotatedSessionsController'

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK, OpenTelemetryTracer } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.AuthScheduledTask })
sdk.start()
import { Logger } from 'winston'
import { TimerInterface } from '@standardnotes/time'
@@ -20,6 +26,9 @@ void container.load().then((container) => {
const persistStats: PersistStatistics = container.get(TYPES.Auth_PersistStatistics)
const timer: TimerInterface = container.get(TYPES.Auth_Timer)
const tracer = new OpenTelemetryTracer()
tracer.startSpan(ServiceIdentifier.NAMES.AuthScheduledTask, 'stats')
Promise.resolve(
persistStats.execute({
sessionsInADay: timer.getUTCDateNDaysAgo(1),
@@ -28,11 +37,15 @@ void container.load().then((container) => {
.then(() => {
logger.info('Stats persisted.')
tracer.stopSpan()
process.exit(0)
})
.catch((error) => {
logger.error(`Could not persist stats: ${error.message}`)
tracer.stopSpanWithError(error)
process.exit(1)
})
})

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK, OpenTelemetryTracer } from '@standardnotes/domain-events-infra'
import { Email, ServiceIdentifier, SettingName } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.AuthScheduledTask })
sdk.start()
import { Logger } from 'winston'
import * as dayjs from 'dayjs'
import * as utc from 'dayjs/plugin/utc'
@@ -15,7 +21,6 @@ import { RoleServiceInterface } from '../src/Domain/Role/RoleServiceInterface'
import { PermissionName } from '@standardnotes/features'
import { UserRepositoryInterface } from '../src/Domain/User/UserRepositoryInterface'
import { GetUserKeyParams } from '../src/Domain/UseCase/GetUserKeyParams/GetUserKeyParams'
import { Email, SettingName } from '@standardnotes/domain-core'
const inputArgs = process.argv.slice(2)
const backupEmail = inputArgs[0]
@@ -89,6 +94,9 @@ void container.load().then((container) => {
const domainEventPublisher: DomainEventPublisherInterface = container.get(TYPES.Auth_DomainEventPublisher)
const getUserKeyParamsUseCase: GetUserKeyParams = container.get(TYPES.Auth_GetUserKeyParams)
const tracer = new OpenTelemetryTracer()
tracer.startSpan(ServiceIdentifier.NAMES.AuthScheduledTask, 'user_email_backup')
Promise.resolve(
requestBackups(
userRepository,
@@ -102,11 +110,15 @@ void container.load().then((container) => {
.then(() => {
logger.info(`Email backup requesting complete for ${backupEmail}`)
tracer.stopSpan()
process.exit(0)
})
.catch((error) => {
logger.error(`Could not finish email backup requesting for ${backupEmail}: ${error.message}`)
tracer.stopSpanWithError(error)
process.exit(1)
})
})

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.AuthWorker })
sdk.start()
import { Logger } from 'winston'
import { ContainerConfigLoader } from '../src/Bootstrap/Container'

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/auth-server",
"version": "1.165.4",
"version": "1.165.2",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -79,9 +79,9 @@ import { ExtensionKeyGrantedEventHandler } from '../Domain/Handler/ExtensionKeyG
import {
DirectCallDomainEventPublisher,
DirectCallEventMessageHandler,
SNSDomainEventPublisher,
SQSDomainEventSubscriber,
SNSOpenTelemetryDomainEventPublisher,
SQSEventMessageHandler,
SQSOpenTelemetryDomainEventSubscriber,
} from '@standardnotes/domain-events-infra'
import { GetUserSubscription } from '../Domain/UseCase/GetUserSubscription/GetUserSubscription'
import { ChangeCredentials } from '../Domain/UseCase/ChangeCredentials/ChangeCredentials'
@@ -170,6 +170,7 @@ import {
ControllerContainer,
ControllerContainerInterface,
MapperInterface,
ServiceIdentifier,
SharedVaultUser,
} from '@standardnotes/domain-core'
import { SessionTracePersistenceMapper } from '../Mapping/SessionTracePersistenceMapper'
@@ -378,7 +379,10 @@ export class ContainerConfigLoader {
.toConstantValue(
isConfiguredForHomeServer
? directCallDomainEventPublisher
: new SNSDomainEventPublisher(container.get(TYPES.Auth_SNS), container.get(TYPES.Auth_SNS_TOPIC_ARN)),
: new SNSOpenTelemetryDomainEventPublisher(
container.get(TYPES.Auth_SNS),
container.get(TYPES.Auth_SNS_TOPIC_ARN),
),
)
// Mapping
@@ -791,16 +795,7 @@ export class ContainerConfigLoader {
container
.bind<SubscriptionSettingsAssociationServiceInterface>(TYPES.Auth_SubscriptionSettingsAssociationService)
.to(SubscriptionSettingsAssociationService)
container
.bind<FeatureServiceInterface>(TYPES.Auth_FeatureService)
.toConstantValue(
new FeatureService(
container.get<RoleToSubscriptionMapInterface>(TYPES.Auth_RoleToSubscriptionMap),
container.get<OfflineUserSubscriptionRepositoryInterface>(TYPES.Auth_OfflineUserSubscriptionRepository),
container.get<TimerInterface>(TYPES.Auth_Timer),
container.get<UserSubscriptionRepositoryInterface>(TYPES.Auth_UserSubscriptionRepository),
),
)
container.bind<FeatureServiceInterface>(TYPES.Auth_FeatureService).to(FeatureService)
container
.bind<SelectorInterface<boolean>>(TYPES.Auth_BooleanSelector)
.toConstantValue(new DeterministicSelector<boolean>())
@@ -1113,7 +1108,6 @@ export class ContainerConfigLoader {
new DeleteAccount(
container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository),
container.get<GetRegularSubscriptionForUser>(TYPES.Auth_GetRegularSubscriptionForUser),
container.get<GetSharedSubscriptionForUser>(TYPES.Auth_GetSharedSubscriptionForUser),
container.get<DomainEventPublisherInterface>(TYPES.Auth_DomainEventPublisher),
container.get<DomainEventFactoryInterface>(TYPES.Auth_DomainEventFactory),
container.get<TimerInterface>(TYPES.Auth_Timer),
@@ -1520,7 +1514,8 @@ export class ContainerConfigLoader {
container
.bind<DomainEventSubscriberInterface>(TYPES.Auth_DomainEventSubscriber)
.toConstantValue(
new SQSDomainEventSubscriber(
new SQSOpenTelemetryDomainEventSubscriber(
ServiceIdentifier.NAMES.AuthWorker,
container.get<SQSClient>(TYPES.Auth_SQS),
container.get<string>(TYPES.Auth_SQS_QUEUE_URL),
container.get<DomainEventMessageHandlerInterface>(TYPES.Auth_DomainEventMessageHandler),

View File

@@ -281,16 +281,9 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
createAccountDeletionRequestedEvent(dto: {
userUuid: string
email: string
userCreatedAtTimestamp: number
regularSubscription?: {
uuid: string
ownerUuid: string
}
sharedSubscription?: {
uuid: string
ownerUuid: string
}
regularSubscriptionUuid: string | undefined
roleNames: string[]
}): AccountDeletionRequestedEvent {
return {
type: 'ACCOUNT_DELETION_REQUESTED',

View File

@@ -45,16 +45,9 @@ export interface DomainEventFactoryInterface {
): EmailBackupRequestedEvent
createAccountDeletionRequestedEvent(dto: {
userUuid: string
email: string
userCreatedAtTimestamp: number
regularSubscription?: {
uuid: string
ownerUuid: string
}
sharedSubscription?: {
uuid: string
ownerUuid: string
}
regularSubscriptionUuid: string | undefined
roleNames: string[]
}): AccountDeletionRequestedEvent
createUserRolesChangedEvent(userUuid: string, email: string, currentRoles: string[]): UserRolesChangedEvent
createUserEmailChangedEvent(userUuid: string, fromEmail: string, toEmail: string): UserEmailChangedEvent

View File

@@ -35,7 +35,6 @@ import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/Offl
import { TimerInterface } from '@standardnotes/time'
import { OfflineUserSubscription } from '../Subscription/OfflineUserSubscription'
import { UserSubscriptionType } from '../Subscription/UserSubscriptionType'
import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface'
describe('FeatureService', () => {
let roleToSubscriptionMap: RoleToSubscriptionMapInterface
@@ -53,10 +52,8 @@ describe('FeatureService', () => {
let offlineUserSubscriptionRepository: OfflineUserSubscriptionRepositoryInterface
let timer: TimerInterface
let offlineUserSubscription: OfflineUserSubscription
let userSubscriptionRepository: UserSubscriptionRepositoryInterface
const createService = () =>
new FeatureService(roleToSubscriptionMap, offlineUserSubscriptionRepository, timer, userSubscriptionRepository)
const createService = () => new FeatureService(roleToSubscriptionMap, offlineUserSubscriptionRepository, timer)
beforeEach(() => {
roleToSubscriptionMap = {} as jest.Mocked<RoleToSubscriptionMapInterface>
@@ -110,7 +107,7 @@ describe('FeatureService', () => {
renewedAt: null,
planName: SubscriptionName.PlusPlan,
endsAt: 555,
userUuid: 'user-1-1-1',
user: Promise.resolve(user),
cancelled: false,
subscriptionId: 1,
subscriptionType: UserSubscriptionType.Regular,
@@ -123,7 +120,7 @@ describe('FeatureService', () => {
renewedAt: null,
planName: SubscriptionName.ProPlan,
endsAt: 777,
userUuid: 'user-1-1-1',
user: Promise.resolve(user),
cancelled: false,
subscriptionId: 2,
subscriptionType: UserSubscriptionType.Regular,
@@ -136,7 +133,7 @@ describe('FeatureService', () => {
renewedAt: null,
planName: SubscriptionName.PlusPlan,
endsAt: 333,
userUuid: 'user-1-1-1',
user: Promise.resolve(user),
cancelled: true,
subscriptionId: 3,
subscriptionType: UserSubscriptionType.Regular,
@@ -149,7 +146,7 @@ describe('FeatureService', () => {
renewedAt: null,
planName: SubscriptionName.PlusPlan,
endsAt: 333,
userUuid: 'user-1-1-1',
user: Promise.resolve(user),
cancelled: true,
subscriptionId: 4,
subscriptionType: UserSubscriptionType.Regular,
@@ -158,11 +155,9 @@ describe('FeatureService', () => {
user = {
uuid: 'user-1-1-1',
roles: Promise.resolve([role1]),
subscriptions: Promise.resolve([subscription1]),
} as jest.Mocked<User>
userSubscriptionRepository = {} as jest.Mocked<UserSubscriptionRepositoryInterface>
userSubscriptionRepository.findByUserUuid = jest.fn().mockReturnValue([subscription1])
offlineUserSubscription = {
roles: Promise.resolve([role1]),
uuid: 'subscription-1-1-1',
@@ -252,10 +247,9 @@ describe('FeatureService', () => {
user = {
uuid: 'user-1-1-1',
roles: Promise.resolve([role1, role2, nonSubscriptionRole]),
subscriptions: Promise.resolve([subscription1, subscription2]),
} as jest.Mocked<User>
userSubscriptionRepository.findByUserUuid = jest.fn().mockReturnValue([subscription1, subscription2])
expect(await createService().userIsEntitledToFeature(user, 'files-beta')).toBe(true)
})
@@ -275,12 +269,9 @@ describe('FeatureService', () => {
user = {
uuid: 'user-1-1-1',
roles: Promise.resolve([role1]),
subscriptions: Promise.resolve([subscription3, subscription1, subscription4]),
} as jest.Mocked<User>
userSubscriptionRepository.findByUserUuid = jest
.fn()
.mockReturnValue([subscription3, subscription1, subscription4])
const features = await createService().getFeaturesForUser(user)
expect(features).toEqual(
expect.arrayContaining([
@@ -293,13 +284,14 @@ describe('FeatureService', () => {
})
it('should not return user features if a subscription could not be found', async () => {
const subscriptions: Array<UserSubscription> = []
user = {
uuid: 'user-1-1-1',
roles: Promise.resolve([role1]),
subscriptions: Promise.resolve(subscriptions),
} as jest.Mocked<User>
userSubscriptionRepository.findByUserUuid = jest.fn().mockReturnValue([])
expect(await createService().getFeaturesForUser(user)).toEqual([])
})
@@ -315,12 +307,9 @@ describe('FeatureService', () => {
user = {
uuid: 'user-1-1-1',
roles: Promise.resolve([role1]),
subscriptions: Promise.resolve([subscription3, subscription1, subscription4]),
} as jest.Mocked<User>
userSubscriptionRepository.findByUserUuid = jest
.fn()
.mockReturnValue([subscription3, subscription1, subscription4])
expect(await createService().getFeaturesForUser(user)).toEqual([])
})
@@ -332,7 +321,7 @@ describe('FeatureService', () => {
renewedAt: null,
planName: 'non existing plan name' as SubscriptionName,
endsAt: 555,
userUuid: 'user-1-1-1',
user: Promise.resolve(user),
cancelled: false,
subscriptionId: 1,
subscriptionType: UserSubscriptionType.Regular,
@@ -341,10 +330,9 @@ describe('FeatureService', () => {
user = {
uuid: 'user-1-1-1',
roles: Promise.resolve([role1]),
subscriptions: Promise.resolve([subscription1]),
} as jest.Mocked<User>
userSubscriptionRepository.findByUserUuid = jest.fn().mockReturnValue([subscription1])
expect(await createService().getFeaturesForUser(user)).toEqual([])
})
@@ -363,10 +351,9 @@ describe('FeatureService', () => {
user = {
uuid: 'user-1-1-1',
roles: Promise.resolve([role1, role2]),
subscriptions: Promise.resolve([subscription1, subscription2]),
} as jest.Mocked<User>
userSubscriptionRepository.findByUserUuid = jest.fn().mockReturnValue([subscription1, subscription2])
const features = await createService().getFeaturesForUser(user)
expect(features).toEqual(
expect.arrayContaining([
@@ -422,10 +409,9 @@ describe('FeatureService', () => {
user = {
uuid: 'user-1-1-1',
roles: Promise.resolve([role1, role2, nonSubscriptionRole]),
subscriptions: Promise.resolve([subscription1, subscription2]),
} as jest.Mocked<User>
userSubscriptionRepository.findByUserUuid = jest.fn().mockReturnValue([subscription1, subscription2])
const features = await createService().getFeaturesForUser(user)
expect(features).toEqual(
expect.arrayContaining([
@@ -459,10 +445,9 @@ describe('FeatureService', () => {
user = {
uuid: 'user-1-1-1',
roles: Promise.resolve([role1, role2]),
subscriptions: Promise.resolve([subscription1, subscription2]),
} as jest.Mocked<User>
userSubscriptionRepository.findByUserUuid = jest.fn().mockReturnValue([subscription1, subscription2])
const longestExpireAt = 777
const features = await createService().getFeaturesForUser(user)
@@ -497,10 +482,9 @@ describe('FeatureService', () => {
user = {
uuid: 'user-1-1-1',
roles: Promise.resolve([role1, role2]),
subscriptions: Promise.resolve([subscription1, subscription2]),
} as jest.Mocked<User>
userSubscriptionRepository.findByUserUuid = jest.fn().mockReturnValue([subscription1, subscription2])
const features = await createService().getFeaturesForUser(user)
expect(features).toEqual(
expect.arrayContaining([

View File

@@ -1,22 +1,24 @@
import { SubscriptionName } from '@standardnotes/common'
import { FeatureDescription, GetFeatures } from '@standardnotes/features'
import { TimerInterface } from '@standardnotes/time'
import { inject, injectable } from 'inversify'
import TYPES from '../../Bootstrap/Types'
import { RoleToSubscriptionMapInterface } from '../Role/RoleToSubscriptionMapInterface'
import { User } from '../User/User'
import { UserSubscription } from '../Subscription/UserSubscription'
import { FeatureServiceInterface } from './FeatureServiceInterface'
import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/OfflineUserSubscriptionRepositoryInterface'
import { Role } from '../Role/Role'
import { OfflineUserSubscription } from '../Subscription/OfflineUserSubscription'
import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface'
import { TimerInterface } from '@standardnotes/time'
@injectable()
export class FeatureService implements FeatureServiceInterface {
constructor(
private roleToSubscriptionMap: RoleToSubscriptionMapInterface,
@inject(TYPES.Auth_RoleToSubscriptionMap) private roleToSubscriptionMap: RoleToSubscriptionMapInterface,
@inject(TYPES.Auth_OfflineUserSubscriptionRepository)
private offlineUserSubscriptionRepository: OfflineUserSubscriptionRepositoryInterface,
private timer: TimerInterface,
private userSubscriptionRepository: UserSubscriptionRepositoryInterface,
@inject(TYPES.Auth_Timer) private timer: TimerInterface,
) {}
async userIsEntitledToFeature(user: User, featureIdentifier: string): Promise<boolean> {
@@ -59,7 +61,7 @@ export class FeatureService implements FeatureServiceInterface {
}
async getFeaturesForUser(user: User): Promise<Array<FeatureDescription>> {
const userSubscriptions = await this.userSubscriptionRepository.findByUserUuid(user.uuid)
const userSubscriptions = await user.subscriptions
return this.getFeaturesForSubscriptions(userSubscriptions, await user.roles)
}

View File

@@ -7,7 +7,7 @@ import { RoleServiceInterface } from '../Role/RoleServiceInterface'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface'
import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/OfflineUserSubscriptionRepositoryInterface'
import { Username, Uuid } from '@standardnotes/domain-core'
import { Username } from '@standardnotes/domain-core'
@injectable()
export class SubscriptionExpiredEventHandler implements DomainEventHandlerInterface {
@@ -48,22 +48,7 @@ export class SubscriptionExpiredEventHandler implements DomainEventHandlerInterf
private async removeRoleFromSubscriptionUsers(subscriptionId: number, subscriptionName: string): Promise<void> {
const userSubscriptions = await this.userSubscriptionRepository.findBySubscriptionId(subscriptionId)
for (const userSubscription of userSubscriptions) {
const userUuidOrError = Uuid.create(userSubscription.userUuid)
if (userUuidOrError.isFailed()) {
this.logger.warn(`Could not remove role from user with uuid: ${userUuidOrError.getError()}`)
continue
}
const userUuid = userUuidOrError.getValue()
const user = await this.userRepository.findOneByUuid(userUuid)
if (user === null) {
this.logger.warn(`Could not find user with uuid: ${userUuid.value}`)
continue
}
await this.roleService.removeUserRoleBasedOnSubscription(user, subscriptionName)
await this.roleService.removeUserRoleBasedOnSubscription(await userSubscription.user, subscriptionName)
}
}

View File

@@ -84,7 +84,7 @@ export class SubscriptionPurchasedEventHandler implements DomainEventHandlerInte
): Promise<UserSubscription> {
const subscription = new UserSubscription()
subscription.planName = subscriptionName
subscription.userUuid = user.uuid
subscription.user = Promise.resolve(user)
subscription.createdAt = timestamp
subscription.updatedAt = timestamp
subscription.endsAt = subscriptionExpiresAt

View File

@@ -80,7 +80,7 @@ export class SubscriptionReassignedEventHandler implements DomainEventHandlerInt
): Promise<UserSubscription> {
const subscription = new UserSubscription()
subscription.planName = subscriptionName
subscription.userUuid = user.uuid
subscription.user = Promise.resolve(user)
subscription.createdAt = timestamp
subscription.updatedAt = timestamp
subscription.endsAt = subscriptionExpiresAt

View File

@@ -7,7 +7,7 @@ import { RoleServiceInterface } from '../Role/RoleServiceInterface'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface'
import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/OfflineUserSubscriptionRepositoryInterface'
import { Username, Uuid } from '@standardnotes/domain-core'
import { Username } from '@standardnotes/domain-core'
@injectable()
export class SubscriptionRefundedEventHandler implements DomainEventHandlerInterface {
@@ -48,22 +48,7 @@ export class SubscriptionRefundedEventHandler implements DomainEventHandlerInter
private async removeRoleFromSubscriptionUsers(subscriptionId: number, subscriptionName: string): Promise<void> {
const userSubscriptions = await this.userSubscriptionRepository.findBySubscriptionId(subscriptionId)
for (const userSubscription of userSubscriptions) {
const userUuidOrError = Uuid.create(userSubscription.userUuid)
if (userUuidOrError.isFailed()) {
this.logger.warn(`Could not remove role from user with uuid: ${userUuidOrError.getError()}`)
continue
}
const userUuid = userUuidOrError.getValue()
const user = await this.userRepository.findOneByUuid(userUuid)
if (user === null) {
this.logger.warn(`Could not find user with uuid: ${userUuid.value}`)
continue
}
await this.roleService.removeUserRoleBasedOnSubscription(user, subscriptionName)
await this.roleService.removeUserRoleBasedOnSubscription(await userSubscription.user, subscriptionName)
}
}

View File

@@ -8,7 +8,7 @@ import { RoleServiceInterface } from '../Role/RoleServiceInterface'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { Logger } from 'winston'
import { OfflineUserSubscription } from '../Subscription/OfflineUserSubscription'
import { Username, Uuid } from '@standardnotes/domain-core'
import { Username } from '@standardnotes/domain-core'
@injectable()
export class SubscriptionRenewedEventHandler implements DomainEventHandlerInterface {
@@ -71,20 +71,7 @@ export class SubscriptionRenewedEventHandler implements DomainEventHandlerInterf
private async addRoleToSubscriptionUsers(subscriptionId: number, subscriptionName: string): Promise<void> {
const userSubscriptions = await this.userSubscriptionRepository.findBySubscriptionId(subscriptionId)
for (const userSubscription of userSubscriptions) {
const userUuidOrError = Uuid.create(userSubscription.userUuid)
if (userUuidOrError.isFailed()) {
this.logger.warn(`Could not add role to user with uuid: ${userUuidOrError.getError()}`)
continue
}
const userUuid = userUuidOrError.getValue()
const user = await this.userRepository.findOneByUuid(userUuid)
if (user === null) {
this.logger.warn(`Could not find user with uuid: ${userUuid.value}`)
continue
}
const user = await userSubscription.user
await this.roleService.addUserRoleBasedOnSubscription(user, subscriptionName)
}

View File

@@ -128,7 +128,7 @@ export class SubscriptionSyncRequestedEventHandler implements DomainEventHandler
}
subscription.planName = subscriptionName
subscription.userUuid = user.uuid
subscription.user = Promise.resolve(user)
subscription.createdAt = timestamp
subscription.updatedAt = timestamp
subscription.endsAt = subscriptionExpiresAt

View File

@@ -1,4 +1,5 @@
import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm'
import { Column, Entity, Index, JoinColumn, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'
import { User } from '../User/User'
import { UserSubscriptionType } from './UserSubscriptionType'
@Entity({ name: 'user_subscriptions' })
@@ -62,9 +63,14 @@ export class UserSubscription {
})
declare subscriptionType: UserSubscriptionType
@Column({
name: 'user_uuid',
length: 36,
})
declare userUuid: string
@ManyToOne(
/* istanbul ignore next */
() => User,
/* istanbul ignore next */
(user) => user.subscriptions,
/* istanbul ignore next */
{ onDelete: 'CASCADE', nullable: false, lazy: true, eager: false },
)
@JoinColumn({ name: 'user_uuid', referencedColumnName: 'uuid' })
declare user: Promise<User>
}

View File

@@ -107,7 +107,7 @@ describe('AcceptSharedSubscriptionInvitation', () => {
subscriptionId: 3,
subscriptionType: 'shared',
updatedAt: 1,
userUuid: '123',
user: Promise.resolve(invitee),
})
expect(roleService.addUserRoleBasedOnSubscription).toHaveBeenCalledWith(invitee, 'PLUS_PLAN')
expect(applyDefaultSubscriptionSettings.execute).toHaveBeenCalled()
@@ -145,7 +145,7 @@ describe('AcceptSharedSubscriptionInvitation', () => {
subscriptionId: 3,
subscriptionType: 'shared',
updatedAt: 3,
userUuid: '123',
user: Promise.resolve(invitee),
})
expect(roleService.addUserRoleBasedOnSubscription).toHaveBeenCalledWith(invitee, 'PLUS_PLAN')
expect(applyDefaultSubscriptionSettings.execute).toHaveBeenCalled()

View File

@@ -115,7 +115,7 @@ export class AcceptSharedSubscriptionInvitation implements UseCaseInterface {
): Promise<UserSubscription> {
const subscription = new UserSubscription()
subscription.planName = subscriptionName
subscription.userUuid = user.uuid
subscription.user = Promise.resolve(user)
const timestamp = this.timer.getTimestampInMicroseconds()
subscription.createdAt = timestamp
subscription.updatedAt = timestamp

View File

@@ -53,7 +53,7 @@ export class ActivatePremiumFeatures implements UseCaseInterface<string> {
const subscription = new UserSubscription()
subscription.planName = subscriptionPlanName.value
subscription.userUuid = user.uuid
subscription.user = Promise.resolve(user)
subscription.createdAt = timestamp
subscription.updatedAt = timestamp
subscription.endsAt = this.timer.convertDateToMicroseconds(endsAt)

View File

@@ -80,7 +80,7 @@ describe('CancelSharedSubscriptionInvitation', () => {
userSubscriptionRepository.findBySubscriptionIdAndType = jest.fn().mockReturnValue([inviterSubscription])
userSubscriptionRepository.findOneByUserUuidAndSubscriptionId = jest
.fn()
.mockReturnValue({ userUuid: '123' } as jest.Mocked<UserSubscription>)
.mockReturnValue({ user: Promise.resolve(invitee) } as jest.Mocked<UserSubscription>)
userSubscriptionRepository.save = jest.fn()
roleService = {} as jest.Mocked<RoleServiceInterface>
@@ -120,7 +120,7 @@ describe('CancelSharedSubscriptionInvitation', () => {
})
expect(userSubscriptionRepository.save).toHaveBeenCalledWith({
endsAt: 1,
userUuid: '123',
user: Promise.resolve(invitee),
})
expect(roleService.removeUserRoleBasedOnSubscription).toHaveBeenCalledWith(invitee, 'PLUS_PLAN')
expect(domainEventPublisher.publish).toHaveBeenCalled()

View File

@@ -5,6 +5,7 @@ import { TokenEncoderInterface, ValetTokenData, ValetTokenOperation } from '@sta
import { CreateValetToken } from './CreateValetToken'
import { UserSubscription } from '../../Subscription/UserSubscription'
import { User } from '../../User/User'
import { UserSubscriptionType } from '../../Subscription/UserSubscriptionType'
import { SubscriptionSettingsAssociationServiceInterface } from '../../Setting/SubscriptionSettingsAssociationServiceInterface'
import { GetRegularSubscriptionForUser } from '../GetRegularSubscriptionForUser/GetRegularSubscriptionForUser'
@@ -24,6 +25,7 @@ describe('CreateValetToken', () => {
const valetTokenTTL = 123
let regularSubscription: UserSubscription
let sharedSubscription: UserSubscription
let user: User
const createUseCase = () =>
new CreateValetToken(
@@ -57,16 +59,20 @@ describe('CreateValetToken', () => {
subscriptionSettingsAssociationService = {} as jest.Mocked<SubscriptionSettingsAssociationServiceInterface>
subscriptionSettingsAssociationService.getFileUploadLimit = jest.fn().mockReturnValue(5_368_709_120)
user = {
uuid: '123',
} as jest.Mocked<User>
regularSubscription = {
uuid: '1-2-3',
subscriptionType: UserSubscriptionType.Regular,
userUuid: '123',
user: Promise.resolve(user),
} as jest.Mocked<UserSubscription>
sharedSubscription = {
uuid: '2-3-4',
subscriptionType: UserSubscriptionType.Shared,
userUuid: '123',
user: Promise.resolve(user),
} as jest.Mocked<UserSubscription>
getRegularSubscription = {} as jest.Mocked<GetRegularSubscriptionForUser>

View File

@@ -11,46 +11,29 @@ import { TimerInterface } from '@standardnotes/time'
import { Result, RoleName } from '@standardnotes/domain-core'
import { Role } from '../../Role/Role'
import { GetRegularSubscriptionForUser } from '../GetRegularSubscriptionForUser/GetRegularSubscriptionForUser'
import { GetSharedSubscriptionForUser } from '../GetSharedSubscriptionForUser/GetSharedSubscriptionForUser'
describe('DeleteAccount', () => {
let userRepository: UserRepositoryInterface
let domainEventPublisher: DomainEventPublisherInterface
let domainEventFactory: DomainEventFactoryInterface
let getRegularSubscription: GetRegularSubscriptionForUser
let getSharedSubscription: GetSharedSubscriptionForUser
let user: User
let regularSubscription: UserSubscription
let sharedSubscription: UserSubscription
let timer: TimerInterface
const createUseCase = () =>
new DeleteAccount(
userRepository,
getRegularSubscription,
getSharedSubscription,
domainEventPublisher,
domainEventFactory,
timer,
)
new DeleteAccount(userRepository, getRegularSubscription, domainEventPublisher, domainEventFactory, timer)
beforeEach(() => {
user = {
uuid: '1-2-3',
email: 'test@test.te',
} as jest.Mocked<User>
user.roles = Promise.resolve([{ name: RoleName.NAMES.CoreUser } as jest.Mocked<Role>])
regularSubscription = {
uuid: '1-2-3',
subscriptionType: UserSubscriptionType.Regular,
userUuid: 'u-1-2-3',
} as jest.Mocked<UserSubscription>
sharedSubscription = {
uuid: '1-2-3',
subscriptionType: UserSubscriptionType.Shared,
userUuid: 'u-1-2-3',
user: Promise.resolve(user),
} as jest.Mocked<UserSubscription>
userRepository = {} as jest.Mocked<UserRepositoryInterface>
@@ -60,9 +43,6 @@ describe('DeleteAccount', () => {
getRegularSubscription = {} as jest.Mocked<GetRegularSubscriptionForUser>
getRegularSubscription.execute = jest.fn().mockReturnValue(Result.ok(regularSubscription))
getSharedSubscription = {} as jest.Mocked<GetSharedSubscriptionForUser>
getSharedSubscription.execute = jest.fn().mockReturnValue(Result.ok(sharedSubscription))
domainEventPublisher = {} as jest.Mocked<DomainEventPublisherInterface>
domainEventPublisher.publish = jest.fn()
@@ -78,7 +58,6 @@ describe('DeleteAccount', () => {
describe('when user uuid is provided', () => {
it('should trigger account deletion - no subscription', async () => {
getRegularSubscription.execute = jest.fn().mockReturnValue(Result.fail('not found'))
getSharedSubscription.execute = jest.fn().mockReturnValue(Result.fail('not found'))
const result = await createUseCase().execute({ userUuid: '00000000-0000-0000-0000-000000000000' })
@@ -87,11 +66,12 @@ describe('DeleteAccount', () => {
expect(domainEventFactory.createAccountDeletionRequestedEvent).toHaveBeenLastCalledWith({
userUuid: '1-2-3',
userCreatedAtTimestamp: 1,
email: 'test@test.te',
regularSubscriptionUuid: undefined,
roleNames: ['CORE_USER'],
})
})
it('should trigger account deletion - shared subscription present', async () => {
it('should trigger account deletion - subscription present', async () => {
const result = await createUseCase().execute({ userUuid: '00000000-0000-0000-0000-000000000000' })
expect(result.isFailed()).toBeFalsy()
@@ -99,35 +79,9 @@ describe('DeleteAccount', () => {
expect(domainEventPublisher.publish).toHaveBeenCalledTimes(1)
expect(domainEventFactory.createAccountDeletionRequestedEvent).toHaveBeenLastCalledWith({
userUuid: '1-2-3',
email: 'test@test.te',
userCreatedAtTimestamp: 1,
regularSubscription: {
ownerUuid: 'u-1-2-3',
uuid: '1-2-3',
},
sharedSubscription: {
ownerUuid: 'u-1-2-3',
uuid: '1-2-3',
},
})
})
it('should trigger account deletion - regular subscription present', async () => {
getSharedSubscription.execute = jest.fn().mockReturnValue(Result.fail('not found'))
const result = await createUseCase().execute({ userUuid: '00000000-0000-0000-0000-000000000000' })
expect(result.isFailed()).toBeFalsy()
expect(domainEventPublisher.publish).toHaveBeenCalledTimes(1)
expect(domainEventFactory.createAccountDeletionRequestedEvent).toHaveBeenLastCalledWith({
userUuid: '1-2-3',
email: 'test@test.te',
userCreatedAtTimestamp: 1,
regularSubscription: {
ownerUuid: 'u-1-2-3',
uuid: '1-2-3',
},
regularSubscriptionUuid: '1-2-3',
roleNames: ['CORE_USER'],
})
})
@@ -155,7 +109,6 @@ describe('DeleteAccount', () => {
describe('when username is provided', () => {
it('should trigger account deletion - no subscription', async () => {
getRegularSubscription.execute = jest.fn().mockReturnValue(Result.fail('not found'))
getSharedSubscription.execute = jest.fn().mockReturnValue(Result.fail('not found'))
const result = await createUseCase().execute({ username: 'test@test.te' })
@@ -163,12 +116,13 @@ describe('DeleteAccount', () => {
expect(domainEventPublisher.publish).toHaveBeenCalledTimes(1)
expect(domainEventFactory.createAccountDeletionRequestedEvent).toHaveBeenLastCalledWith({
userUuid: '1-2-3',
email: 'test@test.te',
userCreatedAtTimestamp: 1,
regularSubscriptionUuid: undefined,
roleNames: ['CORE_USER'],
})
})
it('should trigger account deletion - shared subscription present', async () => {
it('should trigger account deletion - subscription present', async () => {
const result = await createUseCase().execute({ username: 'test@test.te' })
expect(result.isFailed()).toBeFalsy()
@@ -176,35 +130,9 @@ describe('DeleteAccount', () => {
expect(domainEventPublisher.publish).toHaveBeenCalledTimes(1)
expect(domainEventFactory.createAccountDeletionRequestedEvent).toHaveBeenLastCalledWith({
userUuid: '1-2-3',
email: 'test@test.te',
userCreatedAtTimestamp: 1,
regularSubscription: {
ownerUuid: 'u-1-2-3',
uuid: '1-2-3',
},
sharedSubscription: {
ownerUuid: 'u-1-2-3',
uuid: '1-2-3',
},
})
})
it('should trigger account deletion - regular subscription present', async () => {
getSharedSubscription.execute = jest.fn().mockReturnValue(Result.fail('not found'))
const result = await createUseCase().execute({ username: 'test@test.te' })
expect(result.isFailed()).toBeFalsy()
expect(domainEventPublisher.publish).toHaveBeenCalledTimes(1)
expect(domainEventFactory.createAccountDeletionRequestedEvent).toHaveBeenLastCalledWith({
userUuid: '1-2-3',
email: 'test@test.te',
userCreatedAtTimestamp: 1,
regularSubscription: {
ownerUuid: 'u-1-2-3',
uuid: '1-2-3',
},
regularSubscriptionUuid: '1-2-3',
roleNames: ['CORE_USER'],
})
})

View File

@@ -8,14 +8,11 @@ import { UserRepositoryInterface } from '../../User/UserRepositoryInterface'
import { DeleteAccountDTO } from './DeleteAccountDTO'
import { User } from '../../User/User'
import { GetRegularSubscriptionForUser } from '../GetRegularSubscriptionForUser/GetRegularSubscriptionForUser'
import { UserSubscription } from '../../Subscription/UserSubscription'
import { GetSharedSubscriptionForUser } from '../GetSharedSubscriptionForUser/GetSharedSubscriptionForUser'
export class DeleteAccount implements UseCaseInterface<string> {
constructor(
private userRepository: UserRepositoryInterface,
private getRegularSubscription: GetRegularSubscriptionForUser,
private getSharedSubscription: GetSharedSubscriptionForUser,
private domainEventPublisher: DomainEventPublisherInterface,
private domainEventFactory: DomainEventFactoryInterface,
private timer: TimerInterface,
@@ -47,39 +44,23 @@ export class DeleteAccount implements UseCaseInterface<string> {
return Result.ok('User already deleted.')
}
let sharedSubscription: UserSubscription | undefined
const sharedSubscriptionOrError = await this.getSharedSubscription.execute({
userUuid: user.uuid,
})
if (!sharedSubscriptionOrError.isFailed()) {
sharedSubscription = sharedSubscriptionOrError.getValue()
}
const roles = await user.roles
let regularSubscription: UserSubscription | undefined
const regularSubscriptionOrError = await this.getRegularSubscription.execute({
let regularSubscriptionUuid: string | undefined
const result = await this.getRegularSubscription.execute({
userUuid: user.uuid,
})
if (!regularSubscriptionOrError.isFailed()) {
regularSubscription = regularSubscriptionOrError.getValue()
if (!result.isFailed()) {
const regularSubscription = result.getValue()
regularSubscriptionUuid = regularSubscription.uuid
}
await this.domainEventPublisher.publish(
this.domainEventFactory.createAccountDeletionRequestedEvent({
userUuid: user.uuid,
email: user.email,
userCreatedAtTimestamp: this.timer.convertDateToMicroseconds(user.createdAt),
regularSubscription: regularSubscription
? {
ownerUuid: regularSubscription.userUuid,
uuid: regularSubscription.uuid,
}
: undefined,
sharedSubscription: sharedSubscription
? {
ownerUuid: sharedSubscription.userUuid,
uuid: sharedSubscription.uuid,
}
: undefined,
regularSubscriptionUuid,
roleNames: roles.map((role) => role.name),
}),
)

View File

@@ -45,13 +45,13 @@ describe('UpdateStorageQuotaUsedForUser', () => {
regularSubscription = {
uuid: '00000000-0000-0000-0000-000000000000',
subscriptionType: UserSubscriptionType.Regular,
userUuid: '123',
user: Promise.resolve(user),
} as jest.Mocked<UserSubscription>
sharedSubscription = {
uuid: '2-3-4',
subscriptionType: UserSubscriptionType.Shared,
userUuid: '123',
user: Promise.resolve(user),
} as jest.Mocked<UserSubscription>
getSharedSubscription = {} as jest.Mocked<GetSharedSubscriptionForUser>

View File

@@ -56,6 +56,7 @@ export class UpdateStorageQuotaUsedForUser implements UseCaseInterface<void> {
private async updateUploadBytesUsedSetting(subscription: UserSubscription, bytesUsed: number): Promise<void> {
let bytesAlreadyUsed = '0'
const subscriptionUser = await subscription.user
const bytesUsedSettingExists = await this.getSubscriptionSetting.execute({
userSubscriptionUuid: subscription.uuid,
@@ -76,7 +77,7 @@ export class UpdateStorageQuotaUsedForUser implements UseCaseInterface<void> {
/* istanbul ignore next */
if (result.isFailed()) {
this.logger.error(`Could not set file upload bytes used for subscription ${subscription.uuid}`)
this.logger.error(`Could not set file upload bytes used for user ${subscriptionUser.uuid}`)
}
}
}

View File

@@ -1,6 +1,7 @@
import { Column, Entity, Index, JoinTable, ManyToMany, OneToMany, PrimaryGeneratedColumn } from 'typeorm'
import { RevokedSession } from '../Session/RevokedSession'
import { Role } from '../Role/Role'
import { UserSubscription } from '../Subscription/UserSubscription'
import { ProtocolVersion } from '@standardnotes/common'
import { TypeORMEmergencyAccessInvitation } from '../../Infra/TypeORM/TypeORMEmergencyAccessInvitation'
@@ -160,6 +161,16 @@ export class User {
})
declare roles: Promise<Array<Role>>
@OneToMany(
/* istanbul ignore next */
() => UserSubscription,
/* istanbul ignore next */
(subscription) => subscription.user,
/* istanbul ignore next */
{ lazy: true, eager: false },
)
declare subscriptions: Promise<UserSubscription[]>
@OneToMany(
/* istanbul ignore next */
() => TypeORMEmergencyAccessInvitation,

View File

@@ -3,16 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.20.4](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.20.3...@standardnotes/domain-events-infra@1.20.4) (2023-11-07)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.20.3](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.20.2...@standardnotes/domain-events-infra@1.20.3) (2023-11-07)
### Bug Fixes
* remove open telemetry from code ([#903](https://github.com/standardnotes/server/issues/903)) ([751f3b2](https://github.com/standardnotes/server/commit/751f3b25476c5be3d663ad8540c43266acd39493))
## [1.20.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.20.1...@standardnotes/domain-events-infra@1.20.2) (2023-10-19)
**Note:** Version bump only for package @standardnotes/domain-events-infra

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/domain-events-infra",
"version": "1.20.4",
"version": "1.20.2",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -1,36 +0,0 @@
import { Consumer } from 'sqs-consumer'
import { Message, SQSClient } from '@aws-sdk/client-sqs'
import { DomainEventSubscriberInterface, DomainEventMessageHandlerInterface } from '@standardnotes/domain-events'
import { Logger } from 'winston'
export class SQSDomainEventSubscriber implements DomainEventSubscriberInterface {
constructor(
private sqs: SQSClient,
private queueUrl: string,
private domainEventMessageHandler: DomainEventMessageHandlerInterface,
private logger: Logger,
) {}
start(): void {
const sqsConsumer = Consumer.create({
attributeNames: ['All'],
messageAttributeNames: ['All'],
queueUrl: this.queueUrl,
sqs: this.sqs,
handleMessage: this.handleMessage.bind(this),
})
sqsConsumer.on('error', this.handleError.bind(this))
sqsConsumer.on('processing_error', this.handleError.bind(this))
sqsConsumer.start()
}
async handleMessage(message: Message): Promise<void> {
await this.domainEventMessageHandler.handleMessage(<string>message.Body)
}
handleError(error: Error): void {
this.logger.error('Error occured while handling SQS message: %O', error)
}
}

View File

@@ -15,7 +15,6 @@ export * from './SNS/SNSDomainEventPublisher'
export * from './SNS/SNSOpenTelemetryDomainEventPublisher'
export * from './SQS/SQSBounceNotificiationHandler'
export * from './SQS/SQSDomainEventSubscriber'
export * from './SQS/SQSDomainEventSubscriberFactory'
export * from './SQS/SQSEventMessageHandler'
export * from './SQS/SQSOpenTelemetryDomainEventSubscriber'

View File

@@ -3,12 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.133.1](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.133.0...@standardnotes/domain-events@2.133.1) (2023-11-07)
### Bug Fixes
* account deletion event ([#904](https://github.com/standardnotes/server/issues/904)) ([d66ae62](https://github.com/standardnotes/server/commit/d66ae62cf4f413cac5f6f4eac45dc0f1ddbc9e32))
# [2.133.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.132.3...@standardnotes/domain-events@2.133.0) (2023-10-19)
### Features

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/domain-events",
"version": "2.133.1",
"version": "2.133.0",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -1,13 +1,5 @@
export interface AccountDeletionRequestedEventPayload {
userUuid: string
email: string
userCreatedAtTimestamp: number
regularSubscription?: {
uuid: string
ownerUuid: string
}
sharedSubscription?: {
uuid: string
ownerUuid: string
}
regularSubscriptionUuid: string | undefined
}

View File

@@ -1,5 +1,6 @@
export interface FileRemovedEventPayload {
userUuid: string
regularSubscriptionUuid: string
fileByteSize: number
filePath: string
fileName: string

View File

@@ -3,14 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.13.19](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.13.18...@standardnotes/event-store@1.13.19) (2023-11-07)
**Note:** Version bump only for package @standardnotes/event-store
## [1.13.18](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.13.17...@standardnotes/event-store@1.13.18) (2023-11-07)
**Note:** Version bump only for package @standardnotes/event-store
## [1.13.17](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.13.16...@standardnotes/event-store@1.13.17) (2023-10-26)
**Note:** Version bump only for package @standardnotes/event-store

View File

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

View File

@@ -3,18 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.32.5](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.32.4...@standardnotes/files-server@1.32.5) (2023-11-07)
### Bug Fixes
* account deletion event ([#904](https://github.com/standardnotes/files/issues/904)) ([d66ae62](https://github.com/standardnotes/files/commit/d66ae62cf4f413cac5f6f4eac45dc0f1ddbc9e32))
## [1.32.4](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.32.3...@standardnotes/files-server@1.32.4) (2023-11-07)
### Bug Fixes
* remove open telemetry from code ([#903](https://github.com/standardnotes/files/issues/903)) ([751f3b2](https://github.com/standardnotes/files/commit/751f3b25476c5be3d663ad8540c43266acd39493))
## [1.32.3](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.32.2...@standardnotes/files-server@1.32.3) (2023-10-31)
### Bug Fixes

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.Files })
sdk.start()
import * as busboy from 'connect-busboy'
import '../src/Infra/InversifyExpress/AnnotatedFallbackController'

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.FilesWorker })
sdk.start()
import { Logger } from 'winston'
import { ContainerConfigLoader } from '../src/Bootstrap/Container'

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/files-server",
"version": "1.32.5",
"version": "1.32.3",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -16,9 +16,9 @@ import { DomainEventFactory } from '../Domain/Event/DomainEventFactory'
import {
DirectCallDomainEventPublisher,
DirectCallEventMessageHandler,
SNSDomainEventPublisher,
SQSDomainEventSubscriber,
SNSOpenTelemetryDomainEventPublisher,
SQSEventMessageHandler,
SQSOpenTelemetryDomainEventSubscriber,
} from '@standardnotes/domain-events-infra'
import { StreamDownloadFile } from '../Domain/UseCase/StreamDownloadFile/StreamDownloadFile'
import { FileDownloaderInterface } from '../Domain/Services/FileDownloaderInterface'
@@ -52,6 +52,7 @@ import { S3FileMover } from '../Infra/S3/S3FileMover'
import { FSFileMover } from '../Infra/FS/FSFileMover'
import { MoveFile } from '../Domain/UseCase/MoveFile/MoveFile'
import { SharedVaultValetTokenAuthMiddleware } from '../Infra/InversifyExpress/Middleware/SharedVaultValetTokenAuthMiddleware'
import { ServiceIdentifier } from '@standardnotes/domain-core'
export class ContainerConfigLoader {
async load(configuration?: {
@@ -174,7 +175,10 @@ export class ContainerConfigLoader {
container
.bind<DomainEventPublisherInterface>(TYPES.Files_DomainEventPublisher)
.toConstantValue(
new SNSDomainEventPublisher(container.get(TYPES.Files_SNS), container.get(TYPES.Files_SNS_TOPIC_ARN)),
new SNSOpenTelemetryDomainEventPublisher(
container.get(TYPES.Files_SNS),
container.get(TYPES.Files_SNS_TOPIC_ARN),
),
)
}
@@ -297,7 +301,8 @@ export class ContainerConfigLoader {
container
.bind<DomainEventSubscriberInterface>(TYPES.Files_DomainEventSubscriber)
.toConstantValue(
new SQSDomainEventSubscriber(
new SQSOpenTelemetryDomainEventSubscriber(
ServiceIdentifier.NAMES.FilesWorker,
container.get<SQSClient>(TYPES.Files_SQS),
container.get<string>(TYPES.Files_SQS_QUEUE_URL),
container.get<DomainEventMessageHandlerInterface>(TYPES.Files_DomainEventMessageHandler),

View File

@@ -18,6 +18,7 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
filePath: string
fileName: string
fileByteSize: number
regularSubscriptionUuid: string
}): FileRemovedEvent {
return {
type: 'FILE_REMOVED',

View File

@@ -18,6 +18,7 @@ export interface DomainEventFactoryInterface {
filePath: string
fileName: string
fileByteSize: number
regularSubscriptionUuid: string
}): FileRemovedEvent
createSharedVaultFileMovedEvent(payload: {
fileByteSize: number

View File

@@ -17,7 +17,7 @@ export class AccountDeletionRequestedEventHandler implements DomainEventHandlerI
) {}
async handle(event: AccountDeletionRequestedEvent): Promise<void> {
if (event.payload.regularSubscription === undefined) {
if (event.payload.regularSubscriptionUuid === undefined) {
return
}
@@ -38,6 +38,7 @@ export class AccountDeletionRequestedEventHandler implements DomainEventHandlerI
for (const fileRemoved of filesRemoved) {
await this.domainEventPublisher.publish(
this.domainEventFactory.createFileRemovedEvent({
regularSubscriptionUuid: event.payload.regularSubscriptionUuid,
userUuid: fileRemoved.userOrSharedVaultUuid,
filePath: fileRemoved.filePath,
fileName: fileRemoved.fileName,

View File

@@ -40,6 +40,7 @@ export class SharedSubscriptionInvitationCanceledEventHandler implements DomainE
for (const fileRemoved of filesRemoved) {
await this.domainEventPublisher.publish(
this.domainEventFactory.createFileRemovedEvent({
regularSubscriptionUuid: event.payload.inviterSubscriptionUuid,
userUuid: fileRemoved.userOrSharedVaultUuid,
filePath: fileRemoved.filePath,
fileName: fileRemoved.fileName,

View File

@@ -36,6 +36,7 @@ export class RemoveFile implements UseCaseInterface<boolean> {
filePath: `${dto.userInput.userUuid}/${dto.userInput.resourceRemoteIdentifier}`,
fileName: dto.userInput.resourceRemoteIdentifier,
fileByteSize: removedFileSize,
regularSubscriptionUuid: dto.userInput.regularSubscriptionUuid,
}),
)
} else if (dto.vaultInput !== undefined) {

View File

@@ -3,22 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.18.24](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.18.23...@standardnotes/home-server@1.18.24) (2023-11-07)
**Note:** Version bump only for package @standardnotes/home-server
## [1.18.23](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.18.22...@standardnotes/home-server@1.18.23) (2023-11-07)
**Note:** Version bump only for package @standardnotes/home-server
## [1.18.22](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.18.21...@standardnotes/home-server@1.18.22) (2023-11-07)
**Note:** Version bump only for package @standardnotes/home-server
## [1.18.21](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.18.20...@standardnotes/home-server@1.18.21) (2023-11-06)
**Note:** Version bump only for package @standardnotes/home-server
## [1.18.20](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.18.19...@standardnotes/home-server@1.18.20) (2023-11-03)
**Note:** Version bump only for package @standardnotes/home-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/home-server",
"version": "1.18.24",
"version": "1.18.20",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -3,18 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.47.5](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.47.4...@standardnotes/revisions-server@1.47.5) (2023-11-07)
### Bug Fixes
* account deletion event ([#904](https://github.com/standardnotes/server/issues/904)) ([d66ae62](https://github.com/standardnotes/server/commit/d66ae62cf4f413cac5f6f4eac45dc0f1ddbc9e32))
## [1.47.4](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.47.3...@standardnotes/revisions-server@1.47.4) (2023-11-07)
### Bug Fixes
* remove open telemetry from code ([#903](https://github.com/standardnotes/server/issues/903)) ([751f3b2](https://github.com/standardnotes/server/commit/751f3b25476c5be3d663ad8540c43266acd39493))
## [1.47.3](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.47.2...@standardnotes/revisions-server@1.47.3) (2023-10-26)
**Note:** Version bump only for package @standardnotes/revisions-server

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.Revisions })
sdk.start()
import * as cors from 'cors'
import { urlencoded, json, Request, Response, NextFunction } from 'express'
import * as winston from 'winston'

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.RevisionsWorker })
sdk.start()
import { Logger } from 'winston'
import TYPES from '../src/Bootstrap/Types'

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/revisions-server",
"version": "1.47.5",
"version": "1.47.3",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -1,4 +1,9 @@
import { ControllerContainer, ControllerContainerInterface, MapperInterface } from '@standardnotes/domain-core'
import {
ControllerContainer,
ControllerContainerInterface,
MapperInterface,
ServiceIdentifier,
} from '@standardnotes/domain-core'
import { Container, interfaces } from 'inversify'
import { Repository } from 'typeorm'
import * as winston from 'winston'
@@ -29,7 +34,7 @@ import {
SQSEventMessageHandler,
DirectCallEventMessageHandler,
DirectCallDomainEventPublisher,
SQSDomainEventSubscriber,
SQSOpenTelemetryDomainEventSubscriber,
} from '@standardnotes/domain-events-infra'
import { DumpRepositoryInterface } from '../Domain/Dump/DumpRepositoryInterface'
import { AccountDeletionRequestedEventHandler } from '../Domain/Handler/AccountDeletionRequestedEventHandler'
@@ -337,7 +342,8 @@ export class ContainerConfigLoader {
container
.bind<DomainEventSubscriberInterface>(TYPES.Revisions_DomainEventSubscriber)
.toConstantValue(
new SQSDomainEventSubscriber(
new SQSOpenTelemetryDomainEventSubscriber(
ServiceIdentifier.NAMES.RevisionsWorker,
container.get<SQSClient>(TYPES.Revisions_SQS),
container.get<string>(TYPES.Revisions_SQS_QUEUE_URL),
container.get<DomainEventMessageHandlerInterface>(TYPES.Revisions_DomainEventMessageHandler),

View File

@@ -0,0 +1,46 @@
import 'reflect-metadata'
import { AccountDeletionRequestedEvent } from '@standardnotes/domain-events'
import { Logger } from 'winston'
import { AccountDeletionRequestedEventHandler } from './AccountDeletionRequestedEventHandler'
import { RevisionRepositoryInterface } from '../Revision/RevisionRepositoryInterface'
describe('AccountDeletionRequestedEventHandler', () => {
let revisionRepository: RevisionRepositoryInterface
let logger: Logger
let event: AccountDeletionRequestedEvent
const createHandler = () => new AccountDeletionRequestedEventHandler(revisionRepository, logger)
beforeEach(() => {
revisionRepository = {} as jest.Mocked<RevisionRepositoryInterface>
revisionRepository.removeByUserUuid = jest.fn()
logger = {} as jest.Mocked<Logger>
logger.info = jest.fn()
logger.warn = jest.fn()
logger.error = jest.fn()
event = {} as jest.Mocked<AccountDeletionRequestedEvent>
event.createdAt = new Date(1)
event.payload = {
userUuid: '2-3-4',
userCreatedAtTimestamp: 1,
regularSubscriptionUuid: '1-2-3',
}
})
it('should remove all revisions for a user', async () => {
event.payload.userUuid = '84c0f8e8-544a-4c7e-9adf-26209303bc1d'
await createHandler().handle(event)
expect(revisionRepository.removeByUserUuid).toHaveBeenCalled()
})
it('should not remove all revisions for an invalid user uuid', async () => {
await createHandler().handle(event)
expect(revisionRepository.removeByUserUuid).not.toHaveBeenCalled()
})
})

View File

@@ -3,16 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.26.6](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.26.5...@standardnotes/scheduler-server@1.26.6) (2023-11-07)
**Note:** Version bump only for package @standardnotes/scheduler-server
## [1.26.5](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.26.4...@standardnotes/scheduler-server@1.26.5) (2023-11-07)
### Bug Fixes
* remove open telemetry from code ([#903](https://github.com/standardnotes/server/issues/903)) ([751f3b2](https://github.com/standardnotes/server/commit/751f3b25476c5be3d663ad8540c43266acd39493))
## [1.26.4](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.26.3...@standardnotes/scheduler-server@1.26.4) (2023-10-26)
**Note:** Version bump only for package @standardnotes/scheduler-server

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK, OpenTelemetryTracer } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.SchedulerScheduledTask })
sdk.start()
import { Logger } from 'winston'
import * as dayjs from 'dayjs'
import * as utc from 'dayjs/plugin/utc'
@@ -29,15 +35,22 @@ void container.load().then((container) => {
const verifyPredicates: VerifyPredicates = container.get(TYPES.VerifyPredicates)
const tracer = new OpenTelemetryTracer()
tracer.startSpan(ServiceIdentifier.NAMES.SchedulerScheduledTask, 'verify')
Promise.resolve(verifyJobs(now, verifyPredicates))
.then(() => {
logger.info('Verification of overdue jobs complete.')
tracer.stopSpan()
process.exit(0)
})
.catch((error) => {
logger.error(`Could not finish verification of overdue jobs: ${error.message}`)
tracer.stopSpanWithError(error)
process.exit(1)
})
})

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.SchedulerWorker })
sdk.start()
import { Logger } from 'winston'
import { DomainEventSubscriberInterface } from '@standardnotes/domain-events'
import * as dayjs from 'dayjs'

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/scheduler-server",
"version": "1.26.6",
"version": "1.26.4",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -15,9 +15,9 @@ import TYPES from './Types'
import { AppDataSource } from './DataSource'
import { DomainEventFactory } from '../Domain/Event/DomainEventFactory'
import {
SNSDomainEventPublisher,
SQSDomainEventSubscriber,
SNSOpenTelemetryDomainEventPublisher,
SQSEventMessageHandler,
SQSOpenTelemetryDomainEventSubscriber,
} from '@standardnotes/domain-events-infra'
import { Timer, TimerInterface } from '@standardnotes/time'
import { PredicateRepositoryInterface } from '../Domain/Predicate/PredicateRepositoryInterface'
@@ -35,6 +35,7 @@ import { VerifyPredicates } from '../Domain/UseCase/VerifyPredicates/VerifyPredi
import { UserRegisteredEventHandler } from '../Domain/Handler/UserRegisteredEventHandler'
import { SubscriptionCancelledEventHandler } from '../Domain/Handler/SubscriptionCancelledEventHandler'
import { ExitDiscountAppliedEventHandler } from '../Domain/Handler/ExitDiscountAppliedEventHandler'
import { ServiceIdentifier } from '@standardnotes/domain-core'
export class ContainerConfigLoader {
async load(): Promise<Container> {
@@ -135,7 +136,9 @@ export class ContainerConfigLoader {
container
.bind<DomainEventPublisherInterface>(TYPES.DomainEventPublisher)
.toConstantValue(new SNSDomainEventPublisher(container.get(TYPES.SNS), container.get(TYPES.SNS_TOPIC_ARN)))
.toConstantValue(
new SNSOpenTelemetryDomainEventPublisher(container.get(TYPES.SNS), container.get(TYPES.SNS_TOPIC_ARN)),
)
const eventHandlers: Map<string, DomainEventHandlerInterface> = new Map([
['PREDICATE_VERIFIED', container.get(TYPES.PredicateVerifiedEventHandler)],
@@ -150,7 +153,8 @@ export class ContainerConfigLoader {
container
.bind<DomainEventSubscriberInterface>(TYPES.DomainEventSubscriber)
.toConstantValue(
new SQSDomainEventSubscriber(
new SQSOpenTelemetryDomainEventSubscriber(
ServiceIdentifier.NAMES.SchedulerWorker,
container.get<SQSClient>(TYPES.SQS),
container.get<string>(TYPES.SQS_QUEUE_URL),
container.get<DomainEventMessageHandlerInterface>(TYPES.DomainEventMessageHandler),

View File

@@ -3,22 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.120.3](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.120.2...@standardnotes/syncing-server@1.120.3) (2023-11-07)
**Note:** Version bump only for package @standardnotes/syncing-server
## [1.120.2](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.120.1...@standardnotes/syncing-server@1.120.2) (2023-11-07)
### Bug Fixes
* remove open telemetry from code ([#903](https://github.com/standardnotes/syncing-server-js/issues/903)) ([751f3b2](https://github.com/standardnotes/syncing-server-js/commit/751f3b25476c5be3d663ad8540c43266acd39493))
## [1.120.1](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.120.0...@standardnotes/syncing-server@1.120.1) (2023-11-06)
### Bug Fixes
* **syncing-server:** return cursor token upon transfer limit breached ([#902](https://github.com/standardnotes/syncing-server-js/issues/902)) ([71689c1](https://github.com/standardnotes/syncing-server-js/commit/71689c1497728569fc6a07e21fa7bdba68c1bac0))
# [1.120.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.119.4...@standardnotes/syncing-server@1.120.0) (2023-11-02)
### Features

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.SyncingServer })
sdk.start()
import '../src/Infra/InversifyExpressUtils/AnnotatedFallbackController'
import '../src/Infra/InversifyExpressUtils/AnnotatedHealthCheckController'
import '../src/Infra/InversifyExpressUtils/AnnotatedItemsController'

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.SyncingServerWorker })
sdk.start()
import { Logger } from 'winston'
import TYPES from '../src/Bootstrap/Types'

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/syncing-server",
"version": "1.120.3",
"version": "1.120.0",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -11,9 +11,9 @@ import { Item } from '../Domain/Item/Item'
import {
DirectCallDomainEventPublisher,
DirectCallEventMessageHandler,
SNSDomainEventPublisher,
SQSDomainEventSubscriber,
SNSOpenTelemetryDomainEventPublisher,
SQSEventMessageHandler,
SQSOpenTelemetryDomainEventSubscriber,
} from '@standardnotes/domain-events-infra'
import { DomainEventFactoryInterface } from '../Domain/Event/DomainEventFactoryInterface'
import { DomainEventFactory } from '../Domain/Event/DomainEventFactory'
@@ -58,6 +58,7 @@ import {
ControllerContainer,
ControllerContainerInterface,
MapperInterface,
ServiceIdentifier,
SharedVaultUser,
} from '@standardnotes/domain-core'
import { BaseItemsController } from '../Infra/InversifyExpressUtils/Base/BaseItemsController'
@@ -251,7 +252,7 @@ export class ContainerConfigLoader {
container
.bind<DomainEventPublisherInterface>(TYPES.Sync_DomainEventPublisher)
.toDynamicValue((context: interfaces.Context) => {
return new SNSDomainEventPublisher(
return new SNSOpenTelemetryDomainEventPublisher(
context.container.get(TYPES.Sync_SNS),
context.container.get(TYPES.Sync_SNS_TOPIC_ARN),
)
@@ -1021,7 +1022,8 @@ export class ContainerConfigLoader {
container
.bind<DomainEventSubscriberInterface>(TYPES.Sync_DomainEventSubscriber)
.toConstantValue(
new SQSDomainEventSubscriber(
new SQSOpenTelemetryDomainEventSubscriber(
ServiceIdentifier.NAMES.SyncingServerWorker,
container.get<SQSClient>(TYPES.Sync_SQS),
container.get<string>(TYPES.Sync_SQS_QUEUE_URL),
container.get<DomainEventMessageHandlerInterface>(TYPES.Sync_DomainEventMessageHandler),

View File

@@ -25,14 +25,11 @@ describe('ItemTransferCalculator', () => {
const result = await createCalculator().computeItemUuidsToFetch(itemContentSizeDescriptors, 50)
expect(result).toEqual({
uuids: [
'00000000-0000-0000-0000-000000000000',
'00000000-0000-0000-0000-000000000001',
'00000000-0000-0000-0000-000000000002',
],
transferLimitBreachedBeforeEndOfItems: false,
})
expect(result).toEqual([
'00000000-0000-0000-0000-000000000000',
'00000000-0000-0000-0000-000000000001',
'00000000-0000-0000-0000-000000000002',
])
})
it('should compute uuids to fetch based on transfer limit - exact limit fit', async () => {
@@ -44,10 +41,7 @@ describe('ItemTransferCalculator', () => {
const result = await createCalculator().computeItemUuidsToFetch(itemContentSizeDescriptors, 40)
expect(result).toEqual({
uuids: ['00000000-0000-0000-0000-000000000000', '00000000-0000-0000-0000-000000000001'],
transferLimitBreachedBeforeEndOfItems: true,
})
expect(result).toEqual(['00000000-0000-0000-0000-000000000000', '00000000-0000-0000-0000-000000000001'])
})
it('should compute uuids to fetch based on transfer limit - content size not defined on an item', async () => {
@@ -59,14 +53,11 @@ describe('ItemTransferCalculator', () => {
const result = await createCalculator().computeItemUuidsToFetch(itemContentSizeDescriptors, 50)
expect(result).toEqual({
uuids: [
'00000000-0000-0000-0000-000000000000',
'00000000-0000-0000-0000-000000000001',
'00000000-0000-0000-0000-000000000002',
],
transferLimitBreachedBeforeEndOfItems: false,
})
expect(result).toEqual([
'00000000-0000-0000-0000-000000000000',
'00000000-0000-0000-0000-000000000001',
'00000000-0000-0000-0000-000000000002',
])
})
it('should compute uuids to fetch based on transfer limit - first item over the limit', async () => {
@@ -78,10 +69,7 @@ describe('ItemTransferCalculator', () => {
const result = await createCalculator().computeItemUuidsToFetch(itemContentSizeDescriptors, 40)
expect(result).toEqual({
uuids: ['00000000-0000-0000-0000-000000000000', '00000000-0000-0000-0000-000000000001'],
transferLimitBreachedBeforeEndOfItems: true,
})
expect(result).toEqual(['00000000-0000-0000-0000-000000000000', '00000000-0000-0000-0000-000000000001'])
})
})

View File

@@ -9,17 +9,16 @@ export class ItemTransferCalculator implements ItemTransferCalculatorInterface {
async computeItemUuidsToFetch(
itemContentSizeDescriptors: ItemContentSizeDescriptor[],
bytesTransferLimit: number,
): Promise<{ uuids: Array<string>; transferLimitBreachedBeforeEndOfItems: boolean }> {
): Promise<Array<string>> {
const itemUuidsToFetch = []
let totalContentSizeInBytes = 0
let transferLimitBreached = false
for (const itemContentSize of itemContentSizeDescriptors) {
const contentSize = itemContentSize.props.contentSize ?? 0
itemUuidsToFetch.push(itemContentSize.props.uuid.value)
totalContentSizeInBytes += contentSize
transferLimitBreached = this.isTransferLimitBreached({
const transferLimitBreached = this.isTransferLimitBreached({
totalContentSizeInBytes,
bytesTransferLimit,
itemUuidsToFetch,
@@ -31,11 +30,7 @@ export class ItemTransferCalculator implements ItemTransferCalculatorInterface {
}
}
return {
uuids: itemUuidsToFetch,
transferLimitBreachedBeforeEndOfItems:
transferLimitBreached && itemUuidsToFetch.length < itemContentSizeDescriptors.length,
}
return itemUuidsToFetch
}
async computeItemUuidBundlesToFetch(

View File

@@ -4,7 +4,7 @@ export interface ItemTransferCalculatorInterface {
computeItemUuidsToFetch(
itemContentSizeDescriptors: ItemContentSizeDescriptor[],
bytesTransferLimit: number,
): Promise<{ uuids: Array<string>; transferLimitBreachedBeforeEndOfItems: boolean }>
): Promise<Array<string>>
computeItemUuidBundlesToFetch(
itemContentSizeDescriptors: ItemContentSizeDescriptor[],
bytesTransferLimit: number,

View File

@@ -49,9 +49,7 @@ describe('GetItems', () => {
.mockResolvedValue([ItemContentSizeDescriptor.create('00000000-0000-0000-0000-000000000000', 20).getValue()])
itemTransferCalculator = {} as jest.Mocked<ItemTransferCalculatorInterface>
itemTransferCalculator.computeItemUuidsToFetch = jest
.fn()
.mockResolvedValue({ uuids: ['item-uuid'], transferLimitBreachedBeforeEndOfItems: false })
itemTransferCalculator.computeItemUuidsToFetch = jest.fn().mockResolvedValue(['item-uuid'])
timer = {} as jest.Mocked<TimerInterface>
timer.getTimestampInMicroseconds = jest.fn().mockReturnValue(123)

View File

@@ -60,22 +60,22 @@ export class GetItems implements UseCaseInterface<GetItemsResult> {
}
const itemContentSizeDescriptors = await this.itemRepository.findContentSizeForComputingTransferLimit(itemQuery)
const { uuids, transferLimitBreachedBeforeEndOfItems } = await this.itemTransferCalculator.computeItemUuidsToFetch(
const itemUuidsToFetch = await this.itemTransferCalculator.computeItemUuidsToFetch(
itemContentSizeDescriptors,
this.contentSizeTransferLimit,
)
let items: Array<Item> = []
if (uuids.length > 0) {
if (itemUuidsToFetch.length > 0) {
items = await this.itemRepository.findAll({
uuids,
uuids: itemUuidsToFetch,
sortBy: 'updated_at_timestamp',
sortOrder: 'ASC',
})
}
const totalItemsCount = await this.itemRepository.countAll(itemQuery)
let cursorToken = undefined
const thereAreStillMoreItemsToFetch = await this.stillMoreItemsToFetch(itemQuery, upperBoundLimit)
if (transferLimitBreachedBeforeEndOfItems || thereAreStillMoreItemsToFetch) {
if (totalItemsCount > upperBoundLimit) {
const lastSyncTime = items[items.length - 1].props.timestamps.updatedAt / Time.MicrosecondsInASecond
cursorToken = Buffer.from(`${this.SYNC_TOKEN_VERSION}:${lastSyncTime}`, 'utf-8').toString('base64')
}
@@ -87,12 +87,6 @@ export class GetItems implements UseCaseInterface<GetItemsResult> {
})
}
private async stillMoreItemsToFetch(itemQuery: ItemQuery, upperBoundLimit: number): Promise<boolean> {
const totalItemsCount = await this.itemRepository.countAll(itemQuery)
return totalItemsCount > upperBoundLimit
}
private getLastSyncTime(dto: GetItemsDTO): Result<number | null> {
let token = dto.syncToken
if (dto.cursorToken !== undefined && dto.cursorToken !== null) {

View File

@@ -3,16 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.17.6](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.17.5...@standardnotes/websockets-server@1.17.6) (2023-11-07)
**Note:** Version bump only for package @standardnotes/websockets-server
## [1.17.5](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.17.4...@standardnotes/websockets-server@1.17.5) (2023-11-07)
### Bug Fixes
* remove open telemetry from code ([#903](https://github.com/standardnotes/server/issues/903)) ([751f3b2](https://github.com/standardnotes/server/commit/751f3b25476c5be3d663ad8540c43266acd39493))
## [1.17.4](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.17.3...@standardnotes/websockets-server@1.17.4) (2023-10-26)
**Note:** Version bump only for package @standardnotes/websockets-server

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.Websockets })
sdk.start()
import '../src/Infra/InversifyExpressUtils/AnnotatedHealthCheckController'
import '../src/Infra/InversifyExpressUtils/AnnotatedWebSocketsController'

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK({ serviceName: ServiceIdentifier.NAMES.WebsocketsWorker })
sdk.start()
import { Logger } from 'winston'
import { ContainerConfigLoader } from '../src/Bootstrap/Container'

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/websockets-server",
"version": "1.17.6",
"version": "1.17.4",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -18,7 +18,7 @@ import { RedisWebSocketsConnectionRepository } from '../Infra/Redis/RedisWebSock
import { AddWebSocketsConnection } from '../Domain/UseCase/AddWebSocketsConnection/AddWebSocketsConnection'
import { RemoveWebSocketsConnection } from '../Domain/UseCase/RemoveWebSocketsConnection/RemoveWebSocketsConnection'
import { WebSocketsClientMessenger } from '../Infra/WebSockets/WebSocketsClientMessenger'
import { SQSDomainEventSubscriber, SQSEventMessageHandler } from '@standardnotes/domain-events-infra'
import { SQSEventMessageHandler, SQSOpenTelemetryDomainEventSubscriber } from '@standardnotes/domain-events-infra'
import { ApiGatewayAuthMiddleware } from '../Controller/ApiGatewayAuthMiddleware'
import {
@@ -34,6 +34,7 @@ import { WebSocketsController } from '../Controller/WebSocketsController'
import { WebSocketServerInterface } from '@standardnotes/api'
import { ClientMessengerInterface } from '../Client/ClientMessengerInterface'
import { WebSocketMessageRequestedEventHandler } from '../Domain/Handler/WebSocketMessageRequestedEventHandler'
import { ServiceIdentifier } from '@standardnotes/domain-core'
export class ContainerConfigLoader {
async load(): Promise<Container> {
@@ -144,7 +145,8 @@ export class ContainerConfigLoader {
container
.bind<DomainEventSubscriberInterface>(TYPES.DomainEventSubscriber)
.toConstantValue(
new SQSDomainEventSubscriber(
new SQSOpenTelemetryDomainEventSubscriber(
ServiceIdentifier.NAMES.WebsocketsWorker,
container.get<SQSClient>(TYPES.SQS),
container.get<string>(TYPES.SQS_QUEUE_URL),
container.get<DomainEventMessageHandlerInterface>(TYPES.DomainEventMessageHandler),