Compare commits

..

13 Commits

Author SHA1 Message Date
standardci
6b313947c3 chore(release): publish new version
- @standardnotes/revisions-server@1.11.1
2023-02-10 12:20:38 +00:00
Karol Sójko
fba8e6ce35 chore: rearrange workflow deps 2023-02-10 13:05:48 +01:00
Karol Sójko
622c024547 fix(revisions): remove missing middleware binding 2023-02-10 13:00:18 +01:00
Karol Sójko
2c51d92bab chore: reduce Docker image size 2023-02-10 12:58:20 +01:00
Karol Sójko
11ef2ef708 chore: fix publishing flow 2023-02-10 12:57:38 +01:00
standardci
df793e07fd chore(release): publish new version
- @standardnotes/revisions-server@1.11.0
2023-02-10 08:11:48 +00:00
Karol Sójko
bae6eea3aa Merge pull request #440 from standardnotes/split_containers
feat(revisions): refactor container to split worker and server containers
2023-02-10 08:20:08 +01:00
Karol Sójko
be17b67cc1 fix(revisions): remove the interval ping 2023-02-10 08:04:51 +01:00
Karol Sójko
645a24d29b fix(revisions): controller bindings 2023-02-10 07:58:26 +01:00
Karol Sójko
64962ce632 fix: yarn lock file 2023-02-10 06:59:36 +01:00
Karol Sójko
5120883691 feat(revisions): refactor container to split worker and server containers 2023-02-10 06:58:51 +01:00
standardci
0b4570ebee chore(release): publish new version
- @standardnotes/api-gateway@1.46.13
 - @standardnotes/auth-server@1.87.14
 - @standardnotes/files-server@1.9.17
 - @standardnotes/revisions-server@1.10.30
2023-02-09 11:02:48 +00:00
Karol Sójko
5bbdc7e426 fix: performance of startup sequence in supervisor controlled self-hosting setup 2023-02-09 11:23:51 +01:00
23 changed files with 506 additions and 405 deletions

View File

@@ -13,16 +13,9 @@ on:
required: true
jobs:
e2e:
name: E2E
uses: standardnotes/server/.github/workflows/common-e2e.yml@main
secrets: inherit
publish:
runs-on: ubuntu-latest
needs: e2e
steps:
- uses: actions/checkout@v3

View File

@@ -88,15 +88,23 @@ jobs:
- name: Test
run: yarn test
e2e:
needs: build
name: E2E
uses: standardnotes/server/.github/workflows/common-e2e.yml@main
secrets: inherit
publish-self-hosting:
needs: [ test, lint ]
needs: [ test, lint, e2e ]
name: Publish Self Hosting Docker Image
uses: standardnotes/server/.github/workflows/common-self-hosting.yml@main
secrets: inherit
publish-services:
needs: [ test, lint, e2e ]
runs-on: ubuntu-latest
needs: publish-self-hosting
steps:
- name: Checkout code
uses: actions/checkout@v3

100
.pnp.cjs generated
View File

@@ -4501,13 +4501,11 @@ const RAW_RUNTIME_STATE =
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
["@standardnotes/security", "workspace:packages/security"],\
["@standardnotes/time", "workspace:packages/time"],\
["@types/cors", "npm:2.8.12"],\
["@types/dotenv", "npm:8.2.0"],\
["@types/express", "npm:4.17.14"],\
["@types/inversify-express-utils", "npm:2.0.0"],\
["@types/ioredis", "npm:5.0.0"],\
["@types/jest", "npm:29.1.1"],\
["@types/newrelic", "npm:9.4.0"],\
["@typescript-eslint/eslint-plugin", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:5.48.2"],\
@@ -4516,17 +4514,15 @@ const RAW_RUNTIME_STATE =
["eslint", "npm:8.32.0"],\
["eslint-plugin-prettier", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.2.1"],\
["express", "npm:4.18.2"],\
["helmet", "npm:6.0.0"],\
["inversify", "npm:6.0.1"],\
["inversify-express-utils", "npm:6.4.3"],\
["ioredis", "npm:5.2.4"],\
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
["mysql2", "npm:3.0.1"],\
["newrelic", "npm:9.8.0"],\
["npm-check-updates", "npm:16.0.1"],\
["reflect-metadata", "npm:0.1.13"],\
["ts-jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.0.3"],\
["typeorm", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:0.3.10"],\
["typeorm", "virtual:365b8c88cdf194291829ee28b79556e2328175d26a621363e703848100bea0042e9500db2a1206c9bbc3a4a76a1d169639ef774b2ea3a1a98584a9936b58c6be#npm:0.3.10"],\
["typescript", "patch:typescript@npm%3A4.8.4#optional!builtin<compat/typescript>::version=4.8.4&hash=701156"],\
["winston", "npm:3.8.2"]\
],\
@@ -14489,6 +14485,100 @@ const RAW_RUNTIME_STATE =
],\
"linkType": "SOFT"\
}],\
["virtual:365b8c88cdf194291829ee28b79556e2328175d26a621363e703848100bea0042e9500db2a1206c9bbc3a4a76a1d169639ef774b2ea3a1a98584a9936b58c6be#npm:0.3.10", {\
"packageLocation": "./.yarn/__virtual__/typeorm-virtual-6480afe6bc/0/cache/typeorm-npm-0.3.10-4667857f33-749e1a6777.zip/node_modules/typeorm/",\
"packageDependencies": [\
["typeorm", "virtual:365b8c88cdf194291829ee28b79556e2328175d26a621363e703848100bea0042e9500db2a1206c9bbc3a4a76a1d169639ef774b2ea3a1a98584a9936b58c6be#npm:0.3.10"],\
["@google-cloud/spanner", null],\
["@sap/hana-client", null],\
["@sqltools/formatter", "npm:1.2.5"],\
["@types/better-sqlite3", null],\
["@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", null],\
["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": [\

View File

@@ -39,4 +39,8 @@ RUN yarn workspace @standardnotes/files-server bundle --no-compress --output-dir
RUN yarn workspace @standardnotes/revisions-server bundle --no-compress --output-directory /opt/bundled/revisions
RUN yarn workspace @standardnotes/api-gateway bundle --no-compress --output-directory /opt/bundled/api-gateway
WORKDIR /opt/bundled
RUN rm -rf /opt/server
ENTRYPOINT ["docker-entrypoint.sh"]

View File

@@ -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.46.13](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.46.12...@standardnotes/api-gateway@1.46.13) (2023-02-09)
### Bug Fixes
* performance of startup sequence in supervisor controlled self-hosting setup ([5bbdc7e](https://github.com/standardnotes/api-gateway/commit/5bbdc7e426c436b17dc130e3c6d9163080561c76))
## [1.46.12](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.46.11...@standardnotes/api-gateway@1.46.12) (2023-02-09)
### Bug Fixes

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/api-gateway",
"version": "1.46.12",
"version": "1.46.13",
"engines": {
"node": ">=18.0.0 <19.0.0"
},
@@ -16,13 +16,9 @@
"build": "tsc --build",
"lint": "eslint . --ext .ts",
"setup:env": "cp .env.sample .env",
"wait-for:syncing-server": "docker/wait-for.sh localhost $SYNCING_SERVER_PORT",
"wait-for:auth": "docker/wait-for.sh localhost $AUTH_SERVER_PORT",
"wait-for:files": "docker/wait-for.sh localhost $FILES_SERVER_PORT",
"wait-for:revisions": "docker/wait-for.sh localhost $REVISIONS_SERVER_PORT",
"wait-for:services": "yarn wait-for:syncing-server && yarn wait-for:auth && yarn wait-for:files && yarn wait-for:revisions",
"start": "yarn node dist/bin/server.js",
"supervisor:start": "yarn wait-for:services && yarn node dist/bin/server.js",
"supervisor:start": "yarn wait-for:revisions && yarn node dist/bin/server.js",
"upgrade:snjs": "yarn ncu -u '@standardnotes/*'"
},
"dependencies": {

View File

@@ -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.87.14](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.87.13...@standardnotes/auth-server@1.87.14) (2023-02-09)
### Bug Fixes
* performance of startup sequence in supervisor controlled self-hosting setup ([5bbdc7e](https://github.com/standardnotes/server/commit/5bbdc7e426c436b17dc130e3c6d9163080561c76))
## [1.87.13](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.87.12...@standardnotes/auth-server@1.87.13) (2023-02-09)
### Bug Fixes

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/auth-server",
"version": "1.87.13",
"version": "1.87.14",
"engines": {
"node": ">=18.0.0 <19.0.0"
},
@@ -17,12 +17,10 @@
"lint": "eslint . --ext .ts",
"pretest": "yarn lint && yarn build",
"test": "jest --coverage --config=./jest.config.js --maxWorkers=50%",
"wait-for:db": "docker/wait-for.sh $DB_HOST $DB_PORT",
"wait-for:cache": "docker/wait-for.sh $REDIS_HOST $REDIS_PORT",
"wait-for:infra": "yarn wait-for:db && yarn wait-for:cache",
"wait-for:syncing-server": "docker/wait-for.sh localhost $SYNCING_SERVER_PORT",
"wait-for:auth": "docker/wait-for.sh localhost $AUTH_SERVER_PORT",
"start": "yarn node dist/bin/server.js",
"supervisor:start": "yarn wait-for:infra && yarn node dist/bin/server.js",
"supervisor:start": "yarn wait-for:syncing-server && yarn node dist/bin/server.js",
"worker": "yarn node dist/bin/worker.js",
"supervisor:worker": "yarn wait-for:auth && yarn node dist/bin/worker.js",
"cleanup": "yarn node dist/bin/cleanup.js",

View File

@@ -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.9.17](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.9.16...@standardnotes/files-server@1.9.17) (2023-02-09)
### Bug Fixes
* performance of startup sequence in supervisor controlled self-hosting setup ([5bbdc7e](https://github.com/standardnotes/files/commit/5bbdc7e426c436b17dc130e3c6d9163080561c76))
## [1.9.16](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.9.15...@standardnotes/files-server@1.9.16) (2023-02-09)
### Bug Fixes

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/files-server",
"version": "1.9.16",
"version": "1.9.17",
"engines": {
"node": ">=18.0.0 <19.0.0"
},
@@ -20,12 +20,10 @@
"lint": "eslint . --ext .ts",
"pretest": "yarn lint && yarn build",
"test": "jest --coverage --config=./jest.config.js --maxWorkers=50%",
"wait-for:db": "docker/wait-for.sh $DB_HOST $DB_PORT",
"wait-for:cache": "docker/wait-for.sh $REDIS_HOST $REDIS_PORT",
"wait-for:infra": "yarn wait-for:db && yarn wait-for:cache",
"wait-for:auth": "docker/wait-for.sh localhost $AUTH_SERVER_PORT",
"wait-for:files": "docker/wait-for.sh localhost $FILES_SERVER_PORT",
"start": "yarn node dist/bin/server.js",
"supervisor:start": "yarn wait-for:infra && yarn node dist/bin/server.js",
"supervisor:start": "yarn wait-for:auth && yarn node dist/bin/server.js",
"worker": "yarn node dist/bin/worker.js",
"supervisor:worker": "yarn wait-for:files && yarn node dist/bin/worker.js",
"upgrade:snjs": "yarn ncu -u '@standardnotes/*'"

View File

@@ -3,6 +3,29 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.11.1](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.11.0...@standardnotes/revisions-server@1.11.1) (2023-02-10)
### Bug Fixes
* **revisions:** remove missing middleware binding ([622c024](https://github.com/standardnotes/server/commit/622c024547126a7580274d7e368f3787b809f7bc))
# [1.11.0](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.10.30...@standardnotes/revisions-server@1.11.0) (2023-02-10)
### Bug Fixes
* **revisions:** controller bindings ([645a24d](https://github.com/standardnotes/server/commit/645a24d29b2d1858251b80a8d453c98b955c79e3))
* **revisions:** remove the interval ping ([be17b67](https://github.com/standardnotes/server/commit/be17b67cc1ff27c62dfee571f7d85954c1401fda))
### Features
* **revisions:** refactor container to split worker and server containers ([5120883](https://github.com/standardnotes/server/commit/512088369152766027cb25f1566fd2295ab75ac3))
## [1.10.30](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.10.29...@standardnotes/revisions-server@1.10.30) (2023-02-09)
### Bug Fixes
* performance of startup sequence in supervisor controlled self-hosting setup ([5bbdc7e](https://github.com/standardnotes/server/commit/5bbdc7e426c436b17dc130e3c6d9163080561c76))
## [1.10.29](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.10.28...@standardnotes/revisions-server@1.10.29) (2023-02-09)
### Bug Fixes

View File

@@ -4,22 +4,21 @@ import 'newrelic'
import * as Sentry from '@sentry/node'
import '../src/Infra/InversifyExpress/InversifyExpressRevisionsController'
import '../src/Infra/InversifyExpress/InversifyExpressHealthCheckController'
import * as cors from 'cors'
import { urlencoded, json, Request, Response, NextFunction, RequestHandler, ErrorRequestHandler } from 'express'
import * as winston from 'winston'
import { InversifyExpressServer } from 'inversify-express-utils'
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
import TYPES from '../src/Bootstrap/Types'
import { Env } from '../src/Bootstrap/Env'
import { ServerContainerConfigLoader } from '../src/Bootstrap/ServerContainerConfigLoader'
const container = new ContainerConfigLoader()
import '../src/Infra/InversifyExpress/InversifyExpressRevisionsController'
import '../src/Infra/InversifyExpress/InversifyExpressHealthCheckController'
const container = new ServerContainerConfigLoader()
void container.load().then((container) => {
const env: Env = new Env()
env.load()
const env: Env = container.get(TYPES.Env)
const server = new InversifyExpressServer(container)

View File

@@ -4,12 +4,12 @@ import 'newrelic'
import { Logger } from 'winston'
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
import TYPES from '../src/Bootstrap/Types'
import { Env } from '../src/Bootstrap/Env'
import { DomainEventSubscriberFactoryInterface } from '@standardnotes/domain-events'
import { WorkerContainerConfigLoader } from '../src/Bootstrap/WorkerContainerConfigLoader'
const container = new ContainerConfigLoader()
const container = new WorkerContainerConfigLoader()
void container.load().then((container) => {
const env: Env = new Env()
env.load()
@@ -20,6 +20,4 @@ void container.load().then((container) => {
const subscriberFactory: DomainEventSubscriberFactoryInterface = container.get(TYPES.DomainEventSubscriberFactory)
subscriberFactory.create().start()
setInterval(() => logger.info('Alive and kicking!'), 20 * 60 * 1000)
})

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/revisions-server",
"version": "1.10.29",
"version": "1.11.1",
"engines": {
"node": ">=18.0.0 <19.0.0"
},
@@ -19,12 +19,10 @@
"lint:fix": "eslint . --ext .ts --fix",
"pretest": "yarn lint && yarn build",
"test": "jest --coverage --config=./jest.config.js --maxWorkers=50%",
"wait-for:db": "docker/wait-for.sh $DB_HOST $DB_PORT",
"wait-for:cache": "docker/wait-for.sh $REDIS_HOST $REDIS_PORT",
"wait-for:infra": "yarn wait-for:db && yarn wait-for:cache",
"wait-for:files": "docker/wait-for.sh localhost $FILES_SERVER_PORT",
"wait-for:revisions": "docker/wait-for.sh localhost $REVISIONS_SERVER_PORT",
"start": "yarn node dist/bin/server.js",
"supervisor:start": "yarn wait-for:infra && yarn node dist/bin/server.js",
"supervisor:start": "yarn wait-for:files && yarn node dist/bin/server.js",
"supervisor:worker": "yarn wait-for:revisions && yarn node dist/bin/worker.js",
"worker": "yarn node dist/bin/worker.js"
},
@@ -38,15 +36,12 @@
"@standardnotes/domain-core": "workspace:^",
"@standardnotes/domain-events": "workspace:*",
"@standardnotes/domain-events-infra": "workspace:*",
"@standardnotes/security": "workspace:^",
"@standardnotes/time": "workspace:^",
"cors": "2.8.5",
"dotenv": "^16.0.1",
"express": "^4.18.2",
"helmet": "^6.0.0",
"inversify": "^6.0.1",
"inversify-express-utils": "^6.4.3",
"ioredis": "^5.2.4",
"mysql2": "^3.0.1",
"newrelic": "^9.8.0",
"reflect-metadata": "0.1.13",
@@ -58,7 +53,6 @@
"@types/dotenv": "^8.2.0",
"@types/express": "^4.17.14",
"@types/inversify-express-utils": "^2.0.0",
"@types/ioredis": "^5.0.0",
"@types/jest": "^29.1.1",
"@types/newrelic": "^9.4.0",
"@typescript-eslint/eslint-plugin": "^5.48.2",

View File

@@ -0,0 +1,80 @@
import { MapperInterface } from '@standardnotes/domain-core'
import { Container, interfaces } from 'inversify'
import { Repository } from 'typeorm'
import * as winston from 'winston'
import { Revision } from '../Domain/Revision/Revision'
import { RevisionMetadata } from '../Domain/Revision/RevisionMetadata'
import { RevisionRepositoryInterface } from '../Domain/Revision/RevisionRepositoryInterface'
import { MySQLRevisionRepository } from '../Infra/MySQL/MySQLRevisionRepository'
import { TypeORMRevision } from '../Infra/TypeORM/TypeORMRevision'
import { RevisionMetadataPersistenceMapper } from '../Mapping/RevisionMetadataPersistenceMapper'
import { RevisionPersistenceMapper } from '../Mapping/RevisionPersistenceMapper'
import { AppDataSource } from './DataSource'
import { Env } from './Env'
import TYPES from './Types'
// eslint-disable-next-line @typescript-eslint/no-var-requires
const newrelicFormatter = require('@newrelic/winston-enricher')
export class CommonContainerConfigLoader {
async load(): Promise<Container> {
const env: Env = new Env()
env.load()
const container = new Container({
defaultScope: 'Singleton',
})
await AppDataSource.initialize()
container.bind<Env>(TYPES.Env).toConstantValue(env)
container.bind<winston.Logger>(TYPES.Logger).toDynamicValue((context: interfaces.Context) => {
const env: Env = context.container.get(TYPES.Env)
const newrelicWinstonFormatter = newrelicFormatter(winston)
const winstonFormatters = [winston.format.splat(), winston.format.json()]
if (env.get('NEW_RELIC_ENABLED', true) === 'true') {
winstonFormatters.push(newrelicWinstonFormatter())
}
const logger = winston.createLogger({
level: env.get('LOG_LEVEL') || 'info',
format: winston.format.combine(...winstonFormatters),
transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL') || 'info' })],
})
return logger
})
container.bind(TYPES.NEW_RELIC_ENABLED).toConstantValue(env.get('NEW_RELIC_ENABLED', true))
container.bind(TYPES.VERSION).toConstantValue(env.get('VERSION'))
// Map
container
.bind<MapperInterface<RevisionMetadata, TypeORMRevision>>(TYPES.RevisionMetadataPersistenceMapper)
.toDynamicValue(() => new RevisionMetadataPersistenceMapper())
container
.bind<MapperInterface<Revision, TypeORMRevision>>(TYPES.RevisionPersistenceMapper)
.toDynamicValue(() => new RevisionPersistenceMapper())
// ORM
container
.bind<Repository<TypeORMRevision>>(TYPES.ORMRevisionRepository)
.toDynamicValue(() => AppDataSource.getRepository(TypeORMRevision))
// Repositories
container
.bind<RevisionRepositoryInterface>(TYPES.RevisionRepository)
.toDynamicValue((context: interfaces.Context) => {
return new MySQLRevisionRepository(
context.container.get(TYPES.ORMRevisionRepository),
context.container.get(TYPES.RevisionMetadataPersistenceMapper),
context.container.get(TYPES.RevisionPersistenceMapper),
context.container.get(TYPES.Logger),
)
})
return container
}
}

View File

@@ -1,283 +0,0 @@
import * as winston from 'winston'
import Redis from 'ioredis'
import { Timer, TimerInterface } from '@standardnotes/time'
import { SQSClient, SQSClientConfig } from '@aws-sdk/client-sqs'
import { S3Client } from '@aws-sdk/client-s3'
import { Container } from 'inversify'
import { Repository } from 'typeorm'
import {
DomainEventHandlerInterface,
DomainEventMessageHandlerInterface,
DomainEventSubscriberFactoryInterface,
} from '@standardnotes/domain-events'
import { TokenDecoderInterface, CrossServiceTokenData, TokenDecoder } from '@standardnotes/security'
import {
SQSDomainEventSubscriberFactory,
SQSEventMessageHandler,
SQSNewRelicEventMessageHandler,
} from '@standardnotes/domain-events-infra'
import { MapperInterface } from '@standardnotes/domain-core'
import { Env } from './Env'
import TYPES from './Types'
import { AppDataSource } from './DataSource'
import { InversifyExpressApiGatewayAuthMiddleware } from '../Infra/InversifyExpress/InversifyExpressApiGatewayAuthMiddleware'
import { RevisionsController } from '../Controller/RevisionsController'
import { GetRevisionsMetada } from '../Domain/UseCase/GetRevisionsMetada/GetRevisionsMetada'
import { RevisionRepositoryInterface } from '../Domain/Revision/RevisionRepositoryInterface'
import { MySQLRevisionRepository } from '../Infra/MySQL/MySQLRevisionRepository'
import { RevisionMetadataPersistenceMapper } from '../Mapping/RevisionMetadataPersistenceMapper'
import { TypeORMRevision } from '../Infra/TypeORM/TypeORMRevision'
import { RevisionMetadata } from '../Domain/Revision/RevisionMetadata'
import { Revision } from '../Domain/Revision/Revision'
import { RevisionItemStringMapper } from '../Mapping/RevisionItemStringMapper'
import { RevisionPersistenceMapper } from '../Mapping/RevisionPersistenceMapper'
import { ItemDumpedEventHandler } from '../Domain/Handler/ItemDumpedEventHandler'
import { DumpRepositoryInterface } from '../Domain/Dump/DumpRepositoryInterface'
import { S3DumpRepository } from '../Infra/S3/S3ItemDumpRepository'
import { FSDumpRepository } from '../Infra/FS/FSDumpRepository'
import { GetRevision } from '../Domain/UseCase/GetRevision/GetRevision'
import { DeleteRevision } from '../Domain/UseCase/DeleteRevision/DeleteRevision'
import { AccountDeletionRequestedEventHandler } from '../Domain/Handler/AccountDeletionRequestedEventHandler'
import { RevisionsCopyRequestedEventHandler } from '../Domain/Handler/RevisionsCopyRequestedEventHandler'
import { CopyRevisions } from '../Domain/UseCase/CopyRevisions/CopyRevisions'
import { RevisionsOwnershipUpdateRequestedEventHandler } from '../Domain/Handler/RevisionsOwnershipUpdateRequestedEventHandler'
import { RevisionHttpMapper } from '../Mapping/RevisionHttpMapper'
import { RevisionMetadataHttpMapper } from '../Mapping/RevisionMetadataHttpMapper'
import { GetRequiredRoleToViewRevision } from '../Domain/UseCase/GetRequiredRoleToViewRevision/GetRequiredRoleToViewRevision'
// eslint-disable-next-line @typescript-eslint/no-var-requires
const newrelicFormatter = require('@newrelic/winston-enricher')
export class ContainerConfigLoader {
async load(): Promise<Container> {
const env: Env = new Env()
env.load()
const container = new Container()
await AppDataSource.initialize()
const redisUrl = env.get('REDIS_URL')
const isRedisInClusterMode = redisUrl.indexOf(',') > 0
let redis
if (isRedisInClusterMode) {
redis = new Redis.Cluster(redisUrl.split(','))
} else {
redis = new Redis(redisUrl)
}
container.bind(TYPES.Redis).toConstantValue(redis)
const newrelicWinstonFormatter = newrelicFormatter(winston)
const winstonFormatters = [winston.format.splat(), winston.format.json()]
if (env.get('NEW_RELIC_ENABLED', true) === 'true') {
winstonFormatters.push(newrelicWinstonFormatter())
}
const logger = winston.createLogger({
level: env.get('LOG_LEVEL') || 'info',
format: winston.format.combine(...winstonFormatters),
transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL') || 'info' })],
})
container.bind<winston.Logger>(TYPES.Logger).toConstantValue(logger)
if (env.get('SQS_QUEUE_URL', true)) {
const sqsConfig: SQSClientConfig = {
region: env.get('SQS_AWS_REGION', true),
}
if (env.get('SQS_ENDPOINT', true)) {
sqsConfig.endpoint = env.get('SQS_ENDPOINT', true)
}
if (env.get('SQS_ACCESS_KEY_ID', true) && env.get('SQS_SECRET_ACCESS_KEY', true)) {
sqsConfig.credentials = {
accessKeyId: env.get('SQS_ACCESS_KEY_ID', true),
secretAccessKey: env.get('SQS_SECRET_ACCESS_KEY', true),
}
}
container.bind<SQSClient>(TYPES.SQS).toConstantValue(new SQSClient(sqsConfig))
}
let s3Client = undefined
if (env.get('S3_AWS_REGION', true)) {
s3Client = new S3Client({
apiVersion: 'latest',
region: env.get('S3_AWS_REGION', true),
})
}
container.bind<S3Client | undefined>(TYPES.S3).toConstantValue(s3Client)
container.bind<TimerInterface>(TYPES.Timer).toConstantValue(new Timer())
container
.bind<GetRequiredRoleToViewRevision>(TYPES.GetRequiredRoleToViewRevision)
.toConstantValue(new GetRequiredRoleToViewRevision(container.get(TYPES.Timer)))
// Map
container
.bind<MapperInterface<RevisionMetadata, TypeORMRevision>>(TYPES.RevisionMetadataPersistenceMapper)
.toConstantValue(new RevisionMetadataPersistenceMapper())
container
.bind<MapperInterface<Revision, TypeORMRevision>>(TYPES.RevisionPersistenceMapper)
.toConstantValue(new RevisionPersistenceMapper())
container
.bind<MapperInterface<Revision, string>>(TYPES.RevisionItemStringMapper)
.toConstantValue(new RevisionItemStringMapper())
container
.bind<
MapperInterface<
Revision,
{
uuid: string
item_uuid: string
content: string | null
content_type: string
items_key_id: string | null
enc_item_key: string | null
auth_hash: string | null
created_at: string
updated_at: string
}
>
>(TYPES.RevisionHttpMapper)
.toConstantValue(new RevisionHttpMapper())
container
.bind<
MapperInterface<
RevisionMetadata,
{
uuid: string
content_type: string
created_at: string
updated_at: string
}
>
>(TYPES.RevisionMetadataHttpMapper)
.toConstantValue(new RevisionMetadataHttpMapper(container.get(TYPES.GetRequiredRoleToViewRevision)))
// ORM
container
.bind<Repository<TypeORMRevision>>(TYPES.ORMRevisionRepository)
.toConstantValue(AppDataSource.getRepository(TypeORMRevision))
// env vars
container.bind(TYPES.REDIS_URL).toConstantValue(env.get('REDIS_URL'))
container.bind(TYPES.SQS_QUEUE_URL).toConstantValue(env.get('SQS_QUEUE_URL'))
container.bind(TYPES.AUTH_JWT_SECRET).toConstantValue(env.get('AUTH_JWT_SECRET'))
container.bind(TYPES.S3_AWS_REGION).toConstantValue(env.get('S3_AWS_REGION', true))
container.bind(TYPES.S3_BACKUP_BUCKET_NAME).toConstantValue(env.get('S3_BACKUP_BUCKET_NAME', true))
container.bind(TYPES.NEW_RELIC_ENABLED).toConstantValue(env.get('NEW_RELIC_ENABLED', true))
container.bind(TYPES.VERSION).toConstantValue(env.get('VERSION'))
// Repositories
container
.bind<RevisionRepositoryInterface>(TYPES.RevisionRepository)
.toConstantValue(
new MySQLRevisionRepository(
container.get(TYPES.ORMRevisionRepository),
container.get(TYPES.RevisionMetadataPersistenceMapper),
container.get(TYPES.RevisionPersistenceMapper),
container.get(TYPES.Logger),
),
)
if (env.get('S3_AWS_REGION', true)) {
container
.bind<DumpRepositoryInterface>(TYPES.DumpRepository)
.toConstantValue(
new S3DumpRepository(
container.get(TYPES.S3_BACKUP_BUCKET_NAME),
container.get(TYPES.S3),
container.get(TYPES.RevisionItemStringMapper),
),
)
} else {
container
.bind<DumpRepositoryInterface>(TYPES.DumpRepository)
.toConstantValue(new FSDumpRepository(container.get(TYPES.RevisionItemStringMapper)))
}
// use cases
container
.bind<GetRevisionsMetada>(TYPES.GetRevisionsMetada)
.toConstantValue(new GetRevisionsMetada(container.get(TYPES.RevisionRepository)))
container
.bind<GetRevision>(TYPES.GetRevision)
.toConstantValue(new GetRevision(container.get(TYPES.RevisionRepository)))
container
.bind<DeleteRevision>(TYPES.DeleteRevision)
.toConstantValue(new DeleteRevision(container.get(TYPES.RevisionRepository)))
container
.bind<CopyRevisions>(TYPES.CopyRevisions)
.toConstantValue(new CopyRevisions(container.get(TYPES.RevisionRepository)))
// Controller
container
.bind<RevisionsController>(TYPES.RevisionsController)
.toConstantValue(
new RevisionsController(
container.get(TYPES.GetRevisionsMetada),
container.get(TYPES.GetRevision),
container.get(TYPES.DeleteRevision),
container.get(TYPES.RevisionHttpMapper),
container.get(TYPES.RevisionMetadataHttpMapper),
container.get(TYPES.Logger),
),
)
// Handlers
container
.bind<ItemDumpedEventHandler>(TYPES.ItemDumpedEventHandler)
.toConstantValue(
new ItemDumpedEventHandler(container.get(TYPES.DumpRepository), container.get(TYPES.RevisionRepository)),
)
container
.bind<AccountDeletionRequestedEventHandler>(TYPES.AccountDeletionRequestedEventHandler)
.toConstantValue(
new AccountDeletionRequestedEventHandler(container.get(TYPES.RevisionRepository), container.get(TYPES.Logger)),
)
container
.bind<RevisionsCopyRequestedEventHandler>(TYPES.RevisionsCopyRequestedEventHandler)
.toConstantValue(
new RevisionsCopyRequestedEventHandler(container.get(TYPES.CopyRevisions), container.get(TYPES.Logger)),
)
container
.bind<RevisionsOwnershipUpdateRequestedEventHandler>(TYPES.RevisionsOwnershipUpdateRequestedEventHandler)
.toConstantValue(new RevisionsOwnershipUpdateRequestedEventHandler(container.get(TYPES.RevisionRepository)))
// Services
container
.bind<TokenDecoderInterface<CrossServiceTokenData>>(TYPES.CrossServiceTokenDecoder)
.toConstantValue(new TokenDecoder<CrossServiceTokenData>(container.get(TYPES.AUTH_JWT_SECRET)))
// Middleware
container
.bind<InversifyExpressApiGatewayAuthMiddleware>(TYPES.ApiGatewayAuthMiddleware)
.to(InversifyExpressApiGatewayAuthMiddleware)
const eventHandlers: Map<string, DomainEventHandlerInterface> = new Map([
['ITEM_DUMPED', container.get(TYPES.ItemDumpedEventHandler)],
['ACCOUNT_DELETION_REQUESTED', container.get(TYPES.AccountDeletionRequestedEventHandler)],
['REVISIONS_COPY_REQUESTED', container.get(TYPES.RevisionsCopyRequestedEventHandler)],
['REVISIONS_OWNERSHIP_UPDATE_REQUESTED', container.get(TYPES.RevisionsOwnershipUpdateRequestedEventHandler)],
])
container
.bind<DomainEventMessageHandlerInterface>(TYPES.DomainEventMessageHandler)
.toConstantValue(
env.get('NEW_RELIC_ENABLED', true) === 'true'
? new SQSNewRelicEventMessageHandler(eventHandlers, container.get(TYPES.Logger))
: new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Logger)),
)
container
.bind<DomainEventSubscriberFactoryInterface>(TYPES.DomainEventSubscriberFactory)
.toConstantValue(
new SQSDomainEventSubscriberFactory(
container.get(TYPES.SQS),
container.get(TYPES.SQS_QUEUE_URL),
container.get(TYPES.DomainEventMessageHandler),
),
)
return container
}
}

View File

@@ -0,0 +1,89 @@
import { Timer, TimerInterface } from '@standardnotes/time'
import { Container, interfaces } from 'inversify'
import { MapperInterface } from '@standardnotes/domain-core'
import TYPES from './Types'
import { RevisionsController } from '../Controller/RevisionsController'
import { GetRevisionsMetada } from '../Domain/UseCase/GetRevisionsMetada/GetRevisionsMetada'
import { RevisionMetadata } from '../Domain/Revision/RevisionMetadata'
import { Revision } from '../Domain/Revision/Revision'
import { GetRevision } from '../Domain/UseCase/GetRevision/GetRevision'
import { DeleteRevision } from '../Domain/UseCase/DeleteRevision/DeleteRevision'
import { RevisionHttpMapper } from '../Mapping/RevisionHttpMapper'
import { RevisionMetadataHttpMapper } from '../Mapping/RevisionMetadataHttpMapper'
import { GetRequiredRoleToViewRevision } from '../Domain/UseCase/GetRequiredRoleToViewRevision/GetRequiredRoleToViewRevision'
import { CommonContainerConfigLoader } from './CommonContainerConfigLoader'
export class ServerContainerConfigLoader extends CommonContainerConfigLoader {
override async load(): Promise<Container> {
const container = await super.load()
container.bind<TimerInterface>(TYPES.Timer).toDynamicValue(() => new Timer())
container
.bind<GetRequiredRoleToViewRevision>(TYPES.GetRequiredRoleToViewRevision)
.toDynamicValue((context: interfaces.Context) => {
return new GetRequiredRoleToViewRevision(context.container.get(TYPES.Timer))
})
// Map
container
.bind<
MapperInterface<
Revision,
{
uuid: string
item_uuid: string
content: string | null
content_type: string
items_key_id: string | null
enc_item_key: string | null
auth_hash: string | null
created_at: string
updated_at: string
}
>
>(TYPES.RevisionHttpMapper)
.toDynamicValue(() => new RevisionHttpMapper())
container
.bind<
MapperInterface<
RevisionMetadata,
{
uuid: string
content_type: string
created_at: string
updated_at: string
}
>
>(TYPES.RevisionMetadataHttpMapper)
.toDynamicValue((context: interfaces.Context) => {
return new RevisionMetadataHttpMapper(context.container.get(TYPES.GetRequiredRoleToViewRevision))
})
// use cases
container.bind<GetRevisionsMetada>(TYPES.GetRevisionsMetada).toDynamicValue((context: interfaces.Context) => {
return new GetRevisionsMetada(context.container.get(TYPES.RevisionRepository))
})
container.bind<GetRevision>(TYPES.GetRevision).toDynamicValue((context: interfaces.Context) => {
return new GetRevision(context.container.get(TYPES.RevisionRepository))
})
container.bind<DeleteRevision>(TYPES.DeleteRevision).toDynamicValue((context: interfaces.Context) => {
return new DeleteRevision(context.container.get(TYPES.RevisionRepository))
})
// Controller
container.bind<RevisionsController>(TYPES.RevisionsController).toDynamicValue((context: interfaces.Context) => {
return new RevisionsController(
context.container.get(TYPES.GetRevisionsMetada),
context.container.get(TYPES.GetRevision),
context.container.get(TYPES.DeleteRevision),
context.container.get(TYPES.RevisionHttpMapper),
context.container.get(TYPES.RevisionMetadataHttpMapper),
context.container.get(TYPES.Logger),
)
})
return container
}
}

View File

@@ -1,9 +1,9 @@
const TYPES = {
DBConnection: Symbol.for('DBConnection'),
Logger: Symbol.for('Logger'),
Redis: Symbol.for('Redis'),
SQS: Symbol.for('SQS'),
S3: Symbol.for('S3'),
Env: Symbol.for('Env'),
// Map
RevisionMetadataPersistenceMapper: Symbol.for('RevisionMetadataPersistenceMapper'),
RevisionPersistenceMapper: Symbol.for('RevisionPersistenceMapper'),
@@ -16,10 +16,8 @@ const TYPES = {
RevisionRepository: Symbol.for('RevisionRepository'),
DumpRepository: Symbol.for('DumpRepository'),
// env vars
REDIS_URL: Symbol.for('REDIS_URL'),
SQS_QUEUE_URL: Symbol.for('SQS_QUEUE_URL'),
SQS_AWS_REGION: Symbol.for('SQS_AWS_REGION'),
AUTH_JWT_SECRET: Symbol.for('AUTH_JWT_SECRET'),
S3_AWS_REGION: Symbol.for('S3_AWS_REGION'),
S3_BACKUP_BUCKET_NAME: Symbol.for('S3_BACKUP_BUCKET_NAME'),
NEW_RELIC_ENABLED: Symbol.for('NEW_RELIC_ENABLED'),
@@ -42,8 +40,6 @@ const TYPES = {
DomainEventSubscriberFactory: Symbol.for('DomainEventSubscriberFactory'),
DomainEventMessageHandler: Symbol.for('DomainEventMessageHandler'),
Timer: Symbol.for('Timer'),
// Middleware
ApiGatewayAuthMiddleware: Symbol.for('ApiGatewayAuthMiddleware'),
}
export default TYPES

View File

@@ -0,0 +1,164 @@
import { SQSClient, SQSClientConfig } from '@aws-sdk/client-sqs'
import { S3Client } from '@aws-sdk/client-s3'
import { Container, interfaces } from 'inversify'
import {
DomainEventHandlerInterface,
DomainEventMessageHandlerInterface,
DomainEventSubscriberFactoryInterface,
} from '@standardnotes/domain-events'
import {
SQSDomainEventSubscriberFactory,
SQSEventMessageHandler,
SQSNewRelicEventMessageHandler,
} from '@standardnotes/domain-events-infra'
import { MapperInterface } from '@standardnotes/domain-core'
import TYPES from './Types'
import { Revision } from '../Domain/Revision/Revision'
import { RevisionItemStringMapper } from '../Mapping/RevisionItemStringMapper'
import { ItemDumpedEventHandler } from '../Domain/Handler/ItemDumpedEventHandler'
import { DumpRepositoryInterface } from '../Domain/Dump/DumpRepositoryInterface'
import { S3DumpRepository } from '../Infra/S3/S3ItemDumpRepository'
import { FSDumpRepository } from '../Infra/FS/FSDumpRepository'
import { AccountDeletionRequestedEventHandler } from '../Domain/Handler/AccountDeletionRequestedEventHandler'
import { RevisionsCopyRequestedEventHandler } from '../Domain/Handler/RevisionsCopyRequestedEventHandler'
import { CopyRevisions } from '../Domain/UseCase/CopyRevisions/CopyRevisions'
import { RevisionsOwnershipUpdateRequestedEventHandler } from '../Domain/Handler/RevisionsOwnershipUpdateRequestedEventHandler'
import { CommonContainerConfigLoader } from './CommonContainerConfigLoader'
import { Env } from './Env'
export class WorkerContainerConfigLoader extends CommonContainerConfigLoader {
override async load(): Promise<Container> {
const container = await super.load()
const env: Env = container.get(TYPES.Env)
container.bind<SQSClient>(TYPES.SQS).toDynamicValue((context: interfaces.Context) => {
const env: Env = context.container.get(TYPES.Env)
const sqsConfig: SQSClientConfig = {
region: env.get('SQS_AWS_REGION'),
}
if (env.get('SQS_ENDPOINT', true)) {
sqsConfig.endpoint = env.get('SQS_ENDPOINT', true)
}
if (env.get('SQS_ACCESS_KEY_ID', true) && env.get('SQS_SECRET_ACCESS_KEY', true)) {
sqsConfig.credentials = {
accessKeyId: env.get('SQS_ACCESS_KEY_ID', true),
secretAccessKey: env.get('SQS_SECRET_ACCESS_KEY', true),
}
}
return new SQSClient(sqsConfig)
})
container.bind<S3Client | undefined>(TYPES.S3).toDynamicValue((context: interfaces.Context) => {
const env: Env = context.container.get(TYPES.Env)
let s3Client = undefined
if (env.get('S3_AWS_REGION', true)) {
s3Client = new S3Client({
apiVersion: 'latest',
region: env.get('S3_AWS_REGION', true),
})
}
return s3Client
})
// Map
container
.bind<MapperInterface<Revision, string>>(TYPES.RevisionItemStringMapper)
.toDynamicValue(() => new RevisionItemStringMapper())
// env vars
container.bind(TYPES.SQS_QUEUE_URL).toConstantValue(env.get('SQS_QUEUE_URL'))
container.bind(TYPES.S3_AWS_REGION).toConstantValue(env.get('S3_AWS_REGION', true))
container.bind(TYPES.S3_BACKUP_BUCKET_NAME).toConstantValue(env.get('S3_BACKUP_BUCKET_NAME', true))
container.bind<DumpRepositoryInterface>(TYPES.DumpRepository).toDynamicValue((context: interfaces.Context) => {
const env: Env = context.container.get(TYPES.Env)
if (env.get('S3_AWS_REGION', true)) {
return new S3DumpRepository(
context.container.get(TYPES.S3_BACKUP_BUCKET_NAME),
context.container.get(TYPES.S3),
context.container.get(TYPES.RevisionItemStringMapper),
)
} else {
return new FSDumpRepository(context.container.get(TYPES.RevisionItemStringMapper))
}
})
// use cases
container.bind<CopyRevisions>(TYPES.CopyRevisions).toDynamicValue((context: interfaces.Context) => {
return new CopyRevisions(context.container.get(TYPES.RevisionRepository))
})
// Handlers
container
.bind<ItemDumpedEventHandler>(TYPES.ItemDumpedEventHandler)
.toDynamicValue((context: interfaces.Context) => {
return new ItemDumpedEventHandler(
context.container.get(TYPES.DumpRepository),
context.container.get(TYPES.RevisionRepository),
)
})
container
.bind<AccountDeletionRequestedEventHandler>(TYPES.AccountDeletionRequestedEventHandler)
.toDynamicValue((context: interfaces.Context) => {
return new AccountDeletionRequestedEventHandler(
context.container.get(TYPES.RevisionRepository),
context.container.get(TYPES.Logger),
)
})
container
.bind<RevisionsCopyRequestedEventHandler>(TYPES.RevisionsCopyRequestedEventHandler)
.toDynamicValue((context: interfaces.Context) => {
return new RevisionsCopyRequestedEventHandler(
context.container.get(TYPES.CopyRevisions),
context.container.get(TYPES.Logger),
)
})
container
.bind<RevisionsOwnershipUpdateRequestedEventHandler>(TYPES.RevisionsOwnershipUpdateRequestedEventHandler)
.toDynamicValue((context: interfaces.Context) => {
return new RevisionsOwnershipUpdateRequestedEventHandler(context.container.get(TYPES.RevisionRepository))
})
container
.bind<DomainEventMessageHandlerInterface>(TYPES.DomainEventMessageHandler)
.toDynamicValue((context: interfaces.Context) => {
const env: Env = context.container.get(TYPES.Env)
const eventHandlers: Map<string, DomainEventHandlerInterface> = new Map([
['ITEM_DUMPED', context.container.get(TYPES.ItemDumpedEventHandler)],
['ACCOUNT_DELETION_REQUESTED', context.container.get(TYPES.AccountDeletionRequestedEventHandler)],
['REVISIONS_COPY_REQUESTED', context.container.get(TYPES.RevisionsCopyRequestedEventHandler)],
[
'REVISIONS_OWNERSHIP_UPDATE_REQUESTED',
context.container.get(TYPES.RevisionsOwnershipUpdateRequestedEventHandler),
],
])
const handler =
env.get('NEW_RELIC_ENABLED', true) === 'true'
? new SQSNewRelicEventMessageHandler(eventHandlers, context.container.get(TYPES.Logger))
: new SQSEventMessageHandler(eventHandlers, context.container.get(TYPES.Logger))
return handler
})
container
.bind<DomainEventSubscriberFactoryInterface>(TYPES.DomainEventSubscriberFactory)
.toDynamicValue((context: interfaces.Context) => {
return new SQSDomainEventSubscriberFactory(
context.container.get(TYPES.SQS),
context.container.get(TYPES.SQS_QUEUE_URL),
context.container.get(TYPES.DomainEventMessageHandler),
)
})
return container
}
}

View File

@@ -1,60 +0,0 @@
import { CrossServiceTokenData, TokenDecoderInterface } from '@standardnotes/security'
import { NextFunction, Request, Response } from 'express'
import { inject, injectable } from 'inversify'
import { BaseMiddleware } from 'inversify-express-utils'
import { Logger } from 'winston'
import TYPES from '../../Bootstrap/Types'
@injectable()
export class InversifyExpressApiGatewayAuthMiddleware extends BaseMiddleware {
constructor(
@inject(TYPES.CrossServiceTokenDecoder) private tokenDecoder: TokenDecoderInterface<CrossServiceTokenData>,
@inject(TYPES.Logger) private logger: Logger,
) {
super()
}
async handler(request: Request, response: Response, next: NextFunction): Promise<void> {
try {
if (!request.headers['x-auth-token']) {
this.logger.debug('ApiGatewayAuthMiddleware missing x-auth-token header.')
response.status(401).send({
error: {
tag: 'invalid-auth',
message: 'Invalid login credentials.',
},
})
return
}
const token: CrossServiceTokenData | undefined = this.tokenDecoder.decodeToken(
request.headers['x-auth-token'] as string,
)
if (token === undefined) {
this.logger.debug('ApiGatewayAuthMiddleware authentication failure.')
response.status(401).send({
error: {
tag: 'invalid-auth',
message: 'Invalid login credentials.',
},
})
return
}
response.locals.user = token.user
response.locals.roles = token.roles
response.locals.session = token.session
response.locals.readOnlyAccess = token.session?.readonly_access ?? false
return next()
} catch (error) {
return next(error)
}
}
}

View File

@@ -1,7 +1,7 @@
import { controller, httpGet } from 'inversify-express-utils'
import { BaseHttpController, controller, httpGet } from 'inversify-express-utils'
@controller('/healthcheck')
export class InversifyExpressHealthCheckController {
export class InversifyExpressHealthCheckController extends BaseHttpController {
@httpGet('/')
public async get(): Promise<string> {
return 'OK'

View File

@@ -5,7 +5,7 @@ import { inject } from 'inversify'
import TYPES from '../../Bootstrap/Types'
import { RevisionsController } from '../../Controller/RevisionsController'
@controller('/items/:itemUuid/revisions', TYPES.ApiGatewayAuthMiddleware)
@controller('/items/:itemUuid/revisions')
export class InversifyExpressRevisionsController extends BaseHttpController {
constructor(@inject(TYPES.RevisionsController) private revisionsController: RevisionsController) {
super()

View File

@@ -3598,13 +3598,11 @@ __metadata:
"@standardnotes/domain-core": "workspace:^"
"@standardnotes/domain-events": "workspace:*"
"@standardnotes/domain-events-infra": "workspace:*"
"@standardnotes/security": "workspace:^"
"@standardnotes/time": "workspace:^"
"@types/cors": "npm:^2.8.9"
"@types/dotenv": "npm:^8.2.0"
"@types/express": "npm:^4.17.14"
"@types/inversify-express-utils": "npm:^2.0.0"
"@types/ioredis": "npm:^5.0.0"
"@types/jest": "npm:^29.1.1"
"@types/newrelic": "npm:^9.4.0"
"@typescript-eslint/eslint-plugin": "npm:^5.48.2"
@@ -3613,10 +3611,8 @@ __metadata:
eslint: "npm:^8.32.0"
eslint-plugin-prettier: "npm:^4.0.0"
express: "npm:^4.18.2"
helmet: "npm:^6.0.0"
inversify: "npm:^6.0.1"
inversify-express-utils: "npm:^6.4.3"
ioredis: "npm:^5.2.4"
jest: "npm:^29.1.2"
mysql2: "npm:^3.0.1"
newrelic: "npm:^9.8.0"