Container.ts 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. import {
  2. ControllerContainer,
  3. ControllerContainerInterface,
  4. MapperInterface,
  5. ServiceIdentifier,
  6. } from '@standardnotes/domain-core'
  7. import Redis from 'ioredis'
  8. import { Container, interfaces } from 'inversify'
  9. import { MongoRepository, Repository } from 'typeorm'
  10. import * as winston from 'winston'
  11. import { SNSClient, SNSClientConfig } from '@aws-sdk/client-sns'
  12. import { Revision } from '../Domain/Revision/Revision'
  13. import { RevisionMetadata } from '../Domain/Revision/RevisionMetadata'
  14. import { RevisionRepositoryInterface } from '../Domain/Revision/RevisionRepositoryInterface'
  15. import { SQLLegacyRevisionRepository } from '../Infra/TypeORM/SQL/SQLLegacyRevisionRepository'
  16. import { SQLLegacyRevision } from '../Infra/TypeORM/SQL/SQLLegacyRevision'
  17. import { AppDataSource } from './DataSource'
  18. import { Env } from './Env'
  19. import TYPES from './Types'
  20. import { TokenDecoderInterface, CrossServiceTokenData, TokenDecoder } from '@standardnotes/security'
  21. import { TimerInterface, Timer } from '@standardnotes/time'
  22. import { ApiGatewayAuthMiddleware } from '../Infra/InversifyExpress/Middleware/ApiGatewayAuthMiddleware'
  23. import { DeleteRevision } from '../Domain/UseCase/DeleteRevision/DeleteRevision'
  24. import { GetRequiredRoleToViewRevision } from '../Domain/UseCase/GetRequiredRoleToViewRevision/GetRequiredRoleToViewRevision'
  25. import { GetRevision } from '../Domain/UseCase/GetRevision/GetRevision'
  26. import { GetRevisionsMetada } from '../Domain/UseCase/GetRevisionsMetada/GetRevisionsMetada'
  27. import { RevisionMetadataHttpMapper } from '../Mapping/Http/RevisionMetadataHttpMapper'
  28. import { S3Client } from '@aws-sdk/client-s3'
  29. import { SQSClient, SQSClientConfig } from '@aws-sdk/client-sqs'
  30. import {
  31. DomainEventMessageHandlerInterface,
  32. DomainEventHandlerInterface,
  33. DomainEventSubscriberFactoryInterface,
  34. DomainEventPublisherInterface,
  35. } from '@standardnotes/domain-events'
  36. import {
  37. SQSEventMessageHandler,
  38. SQSDomainEventSubscriberFactory,
  39. DirectCallEventMessageHandler,
  40. DirectCallDomainEventPublisher,
  41. SQSOpenTelemetryEventMessageHandler,
  42. SNSOpenTelemetryDomainEventPublisher,
  43. } from '@standardnotes/domain-events-infra'
  44. import { DumpRepositoryInterface } from '../Domain/Dump/DumpRepositoryInterface'
  45. import { AccountDeletionRequestedEventHandler } from '../Domain/Handler/AccountDeletionRequestedEventHandler'
  46. import { ItemDumpedEventHandler } from '../Domain/Handler/ItemDumpedEventHandler'
  47. import { RevisionsCopyRequestedEventHandler } from '../Domain/Handler/RevisionsCopyRequestedEventHandler'
  48. import { CopyRevisions } from '../Domain/UseCase/CopyRevisions/CopyRevisions'
  49. import { FSDumpRepository } from '../Infra/FS/FSDumpRepository'
  50. import { S3DumpRepository } from '../Infra/S3/S3ItemDumpRepository'
  51. import { RevisionItemStringMapper } from '../Mapping/Backup/RevisionItemStringMapper'
  52. import { BaseRevisionsController } from '../Infra/InversifyExpress/Base/BaseRevisionsController'
  53. import { Transform } from 'stream'
  54. import { MongoDBRevision } from '../Infra/TypeORM/MongoDB/MongoDBRevision'
  55. import { MongoDBRevisionRepository } from '../Infra/TypeORM/MongoDB/MongoDBRevisionRepository'
  56. import { SQLLegacyRevisionMetadataPersistenceMapper } from '../Mapping/Persistence/SQL/SQLLegacyRevisionMetadataPersistenceMapper'
  57. import { SQLLegacyRevisionPersistenceMapper } from '../Mapping/Persistence/SQL/SQLLegacyRevisionPersistenceMapper'
  58. import { MongoDBRevisionMetadataPersistenceMapper } from '../Mapping/Persistence/MongoDB/MongoDBRevisionMetadataPersistenceMapper'
  59. import { MongoDBRevisionPersistenceMapper } from '../Mapping/Persistence/MongoDB/MongoDBRevisionPersistenceMapper'
  60. import { RevisionHttpMapper } from '../Mapping/Http/RevisionHttpMapper'
  61. import { RevisionRepositoryResolverInterface } from '../Domain/Revision/RevisionRepositoryResolverInterface'
  62. import { TypeORMRevisionRepositoryResolver } from '../Infra/TypeORM/TypeORMRevisionRepositoryResolver'
  63. import { RevisionMetadataHttpRepresentation } from '../Mapping/Http/RevisionMetadataHttpRepresentation'
  64. import { RevisionHttpRepresentation } from '../Mapping/Http/RevisionHttpRepresentation'
  65. import { TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser } from '../Domain/UseCase/Transition/TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser/TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser'
  66. import { DomainEventFactoryInterface } from '../Domain/Event/DomainEventFactoryInterface'
  67. import { DomainEventFactory } from '../Domain/Event/DomainEventFactory'
  68. import { SQLRevision } from '../Infra/TypeORM/SQL/SQLRevision'
  69. import { SQLRevisionRepository } from '../Infra/TypeORM/SQL/SQLRevisionRepository'
  70. import { SQLRevisionMetadataPersistenceMapper } from '../Mapping/Persistence/SQL/SQLRevisionMetadataPersistenceMapper'
  71. import { SQLRevisionPersistenceMapper } from '../Mapping/Persistence/SQL/SQLRevisionPersistenceMapper'
  72. import { RemoveRevisionsFromSharedVault } from '../Domain/UseCase/RemoveRevisionsFromSharedVault/RemoveRevisionsFromSharedVault'
  73. import { ItemRemovedFromSharedVaultEventHandler } from '../Domain/Handler/ItemRemovedFromSharedVaultEventHandler'
  74. import { TransitionRequestedEventHandler } from '../Domain/Handler/TransitionRequestedEventHandler'
  75. import { SharedVaultRemovedEventHandler } from '../Domain/Handler/SharedVaultRemovedEventHandler'
  76. import { TransitionRepositoryInterface } from '../Domain/Transition/TransitionRepositoryInterface'
  77. import { RedisTransitionRepository } from '../Infra/Redis/RedisTransitionRepository'
  78. import { CreateRevisionFromDump } from '../Domain/UseCase/CreateRevisionFromDump/CreateRevisionFromDump'
  79. export class ContainerConfigLoader {
  80. constructor(private mode: 'server' | 'worker' = 'server') {}
  81. async load(configuration?: {
  82. controllerConatiner?: ControllerContainerInterface
  83. directCallDomainEventPublisher?: DirectCallDomainEventPublisher
  84. logger?: Transform
  85. environmentOverrides?: { [name: string]: string }
  86. }): Promise<Container> {
  87. const directCallDomainEventPublisher =
  88. configuration?.directCallDomainEventPublisher ?? new DirectCallDomainEventPublisher()
  89. const env: Env = new Env(configuration?.environmentOverrides)
  90. env.load()
  91. const isConfiguredForHomeServer = env.get('MODE', true) === 'home-server'
  92. const isConfiguredForSelfHosting = env.get('MODE', true) === 'self-hosted'
  93. const isConfiguredForHomeServerOrSelfHosting = isConfiguredForHomeServer || isConfiguredForSelfHosting
  94. const isSecondaryDatabaseEnabled = env.get('SECONDARY_DB_ENABLED', true) === 'true'
  95. const isConfiguredForInMemoryCache = env.get('CACHE_TYPE', true) === 'memory'
  96. const container = new Container({
  97. defaultScope: 'Singleton',
  98. })
  99. container
  100. .bind<boolean>(TYPES.Revisions_IS_CONFIGURED_FOR_HOME_SERVER_OR_SELF_HOSTING)
  101. .toConstantValue(isConfiguredForHomeServerOrSelfHosting)
  102. if (!isConfiguredForInMemoryCache) {
  103. const redisUrl = env.get('REDIS_URL')
  104. const isRedisInClusterMode = redisUrl.indexOf(',') > 0
  105. let redis
  106. if (isRedisInClusterMode) {
  107. redis = new Redis.Cluster(redisUrl.split(','))
  108. } else {
  109. redis = new Redis(redisUrl)
  110. }
  111. container.bind(TYPES.Revisions_Redis).toConstantValue(redis)
  112. container
  113. .bind<TransitionRepositoryInterface>(TYPES.Revisions_TransitionStatusRepository)
  114. .toConstantValue(new RedisTransitionRepository(container.get<Redis>(TYPES.Revisions_Redis)))
  115. }
  116. let logger: winston.Logger
  117. if (configuration?.logger) {
  118. logger = configuration.logger as winston.Logger
  119. } else {
  120. const winstonFormatters = [winston.format.splat(), winston.format.json()]
  121. logger = winston.createLogger({
  122. level: env.get('LOG_LEVEL', true) || 'info',
  123. format: winston.format.combine(...winstonFormatters),
  124. transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL', true) || 'info' })],
  125. defaultMeta: { service: 'revisions' },
  126. })
  127. }
  128. container.bind<winston.Logger>(TYPES.Revisions_Logger).toConstantValue(logger)
  129. container.bind<TimerInterface>(TYPES.Revisions_Timer).toDynamicValue(() => new Timer())
  130. const appDataSource = new AppDataSource({ env, runMigrations: this.mode === 'server' })
  131. await appDataSource.initialize()
  132. logger.debug('Database initialized')
  133. container.bind<Env>(TYPES.Revisions_Env).toConstantValue(env)
  134. container.bind(TYPES.Revisions_VERSION).toConstantValue(env.get('VERSION', true) ?? 'development')
  135. if (!isConfiguredForHomeServer) {
  136. // env vars
  137. container.bind(TYPES.Revisions_SNS_TOPIC_ARN).toConstantValue(env.get('SNS_TOPIC_ARN'))
  138. container.bind(TYPES.Revisions_SNS_AWS_REGION).toConstantValue(env.get('SNS_AWS_REGION', true))
  139. container.bind(TYPES.Revisions_SQS_QUEUE_URL).toConstantValue(env.get('SQS_QUEUE_URL'))
  140. container.bind(TYPES.Revisions_S3_AWS_REGION).toConstantValue(env.get('S3_AWS_REGION', true))
  141. container.bind(TYPES.Revisions_S3_BACKUP_BUCKET_NAME).toConstantValue(env.get('S3_BACKUP_BUCKET_NAME', true))
  142. container.bind<SNSClient>(TYPES.Revisions_SNS).toDynamicValue((context: interfaces.Context) => {
  143. const env: Env = context.container.get(TYPES.Revisions_Env)
  144. const snsConfig: SNSClientConfig = {
  145. apiVersion: 'latest',
  146. region: env.get('SNS_AWS_REGION', true),
  147. }
  148. if (env.get('SNS_ENDPOINT', true)) {
  149. snsConfig.endpoint = env.get('SNS_ENDPOINT', true)
  150. }
  151. if (env.get('SNS_ACCESS_KEY_ID', true) && env.get('SNS_SECRET_ACCESS_KEY', true)) {
  152. snsConfig.credentials = {
  153. accessKeyId: env.get('SNS_ACCESS_KEY_ID', true),
  154. secretAccessKey: env.get('SNS_SECRET_ACCESS_KEY', true),
  155. }
  156. }
  157. return new SNSClient(snsConfig)
  158. })
  159. container
  160. .bind<DomainEventPublisherInterface>(TYPES.Revisions_DomainEventPublisher)
  161. .toDynamicValue((context: interfaces.Context) => {
  162. return new SNSOpenTelemetryDomainEventPublisher(
  163. context.container.get(TYPES.Revisions_SNS),
  164. context.container.get(TYPES.Revisions_SNS_TOPIC_ARN),
  165. )
  166. })
  167. container.bind<SQSClient>(TYPES.Revisions_SQS).toDynamicValue((context: interfaces.Context) => {
  168. const env: Env = context.container.get(TYPES.Revisions_Env)
  169. const sqsConfig: SQSClientConfig = {
  170. region: env.get('SQS_AWS_REGION'),
  171. }
  172. if (env.get('SQS_ENDPOINT', true)) {
  173. sqsConfig.endpoint = env.get('SQS_ENDPOINT', true)
  174. }
  175. if (env.get('SQS_ACCESS_KEY_ID', true) && env.get('SQS_SECRET_ACCESS_KEY', true)) {
  176. sqsConfig.credentials = {
  177. accessKeyId: env.get('SQS_ACCESS_KEY_ID', true),
  178. secretAccessKey: env.get('SQS_SECRET_ACCESS_KEY', true),
  179. }
  180. }
  181. return new SQSClient(sqsConfig)
  182. })
  183. container.bind<S3Client | undefined>(TYPES.Revisions_S3).toDynamicValue((context: interfaces.Context) => {
  184. const env: Env = context.container.get(TYPES.Revisions_Env)
  185. let s3Client = undefined
  186. if (env.get('S3_AWS_REGION', true)) {
  187. s3Client = new S3Client({
  188. apiVersion: 'latest',
  189. region: env.get('S3_AWS_REGION', true),
  190. })
  191. }
  192. return s3Client
  193. })
  194. } else {
  195. container
  196. .bind<DomainEventPublisherInterface>(TYPES.Revisions_DomainEventPublisher)
  197. .toConstantValue(directCallDomainEventPublisher)
  198. }
  199. container
  200. .bind<DomainEventFactoryInterface>(TYPES.Revisions_DomainEventFactory)
  201. .toConstantValue(new DomainEventFactory(container.get(TYPES.Revisions_Timer)))
  202. // Map
  203. container
  204. .bind<MapperInterface<RevisionMetadata, SQLLegacyRevision>>(
  205. TYPES.Revisions_SQLLegacyRevisionMetadataPersistenceMapper,
  206. )
  207. .toConstantValue(new SQLLegacyRevisionMetadataPersistenceMapper())
  208. container
  209. .bind<MapperInterface<RevisionMetadata, SQLRevision>>(TYPES.Revisions_SQLRevisionMetadataPersistenceMapper)
  210. .toConstantValue(new SQLRevisionMetadataPersistenceMapper())
  211. container
  212. .bind<MapperInterface<Revision, SQLLegacyRevision>>(TYPES.Revisions_SQLLegacyRevisionPersistenceMapper)
  213. .toConstantValue(new SQLLegacyRevisionPersistenceMapper(container.get<TimerInterface>(TYPES.Revisions_Timer)))
  214. container
  215. .bind<MapperInterface<Revision, SQLRevision>>(TYPES.Revisions_SQLRevisionPersistenceMapper)
  216. .toConstantValue(new SQLRevisionPersistenceMapper(container.get<TimerInterface>(TYPES.Revisions_Timer)))
  217. container
  218. .bind<MapperInterface<RevisionMetadata, MongoDBRevision>>(
  219. TYPES.Revisions_MongoDBRevisionMetadataPersistenceMapper,
  220. )
  221. .toConstantValue(new MongoDBRevisionMetadataPersistenceMapper())
  222. container
  223. .bind<MapperInterface<Revision, MongoDBRevision>>(TYPES.Revisions_MongoDBRevisionPersistenceMapper)
  224. .toConstantValue(new MongoDBRevisionPersistenceMapper(container.get<TimerInterface>(TYPES.Revisions_Timer)))
  225. // ORM
  226. container
  227. .bind<Repository<SQLLegacyRevision>>(TYPES.Revisions_ORMLegacyRevisionRepository)
  228. .toDynamicValue(() => appDataSource.getRepository(SQLLegacyRevision))
  229. container
  230. .bind<Repository<SQLRevision>>(TYPES.Revisions_ORMRevisionRepository)
  231. .toConstantValue(appDataSource.getRepository(SQLRevision))
  232. // Repositories
  233. container
  234. .bind<RevisionRepositoryInterface>(TYPES.Revisions_SQLRevisionRepository)
  235. .toConstantValue(
  236. isConfiguredForHomeServerOrSelfHosting
  237. ? new SQLRevisionRepository(
  238. container.get<Repository<SQLRevision>>(TYPES.Revisions_ORMRevisionRepository),
  239. container.get<MapperInterface<RevisionMetadata, SQLRevision>>(
  240. TYPES.Revisions_SQLRevisionMetadataPersistenceMapper,
  241. ),
  242. container.get<MapperInterface<Revision, SQLRevision>>(TYPES.Revisions_SQLRevisionPersistenceMapper),
  243. container.get<winston.Logger>(TYPES.Revisions_Logger),
  244. )
  245. : new SQLLegacyRevisionRepository(
  246. container.get<Repository<SQLLegacyRevision>>(TYPES.Revisions_ORMLegacyRevisionRepository),
  247. container.get<MapperInterface<RevisionMetadata, SQLLegacyRevision>>(
  248. TYPES.Revisions_SQLLegacyRevisionMetadataPersistenceMapper,
  249. ),
  250. container.get<MapperInterface<Revision, SQLLegacyRevision>>(
  251. TYPES.Revisions_SQLLegacyRevisionPersistenceMapper,
  252. ),
  253. container.get<winston.Logger>(TYPES.Revisions_Logger),
  254. ),
  255. )
  256. if (isSecondaryDatabaseEnabled) {
  257. container
  258. .bind<MongoRepository<MongoDBRevision>>(TYPES.Revisions_ORMMongoRevisionRepository)
  259. .toConstantValue(appDataSource.getMongoRepository(MongoDBRevision))
  260. container
  261. .bind<RevisionRepositoryInterface>(TYPES.Revisions_MongoDBRevisionRepository)
  262. .toConstantValue(
  263. new MongoDBRevisionRepository(
  264. container.get<MongoRepository<MongoDBRevision>>(TYPES.Revisions_ORMMongoRevisionRepository),
  265. container.get<MapperInterface<RevisionMetadata, MongoDBRevision>>(
  266. TYPES.Revisions_MongoDBRevisionMetadataPersistenceMapper,
  267. ),
  268. container.get<MapperInterface<Revision, MongoDBRevision>>(TYPES.Revisions_MongoDBRevisionPersistenceMapper),
  269. container.get<winston.Logger>(TYPES.Revisions_Logger),
  270. ),
  271. )
  272. }
  273. container
  274. .bind<RevisionRepositoryResolverInterface>(TYPES.Revisions_RevisionRepositoryResolver)
  275. .toConstantValue(
  276. new TypeORMRevisionRepositoryResolver(
  277. container.get<RevisionRepositoryInterface>(TYPES.Revisions_SQLRevisionRepository),
  278. isSecondaryDatabaseEnabled
  279. ? container.get<RevisionRepositoryInterface>(TYPES.Revisions_MongoDBRevisionRepository)
  280. : null,
  281. ),
  282. )
  283. container
  284. .bind<GetRequiredRoleToViewRevision>(TYPES.Revisions_GetRequiredRoleToViewRevision)
  285. .toDynamicValue((context: interfaces.Context) => {
  286. return new GetRequiredRoleToViewRevision(context.container.get(TYPES.Revisions_Timer))
  287. })
  288. // Map
  289. container
  290. .bind<MapperInterface<Revision, RevisionHttpRepresentation>>(TYPES.Revisions_RevisionHttpMapper)
  291. .toDynamicValue(() => new RevisionHttpMapper())
  292. container
  293. .bind<MapperInterface<RevisionMetadata, RevisionMetadataHttpRepresentation>>(
  294. TYPES.Revisions_RevisionMetadataHttpMapper,
  295. )
  296. .toDynamicValue((context: interfaces.Context) => {
  297. return new RevisionMetadataHttpMapper(context.container.get(TYPES.Revisions_GetRequiredRoleToViewRevision))
  298. })
  299. container
  300. .bind<MapperInterface<Revision, string>>(TYPES.Revisions_RevisionItemStringMapper)
  301. .toDynamicValue(() => new RevisionItemStringMapper())
  302. container
  303. .bind<DumpRepositoryInterface>(TYPES.Revisions_DumpRepository)
  304. .toConstantValue(
  305. env.get('S3_AWS_REGION', true)
  306. ? new S3DumpRepository(
  307. container.get(TYPES.Revisions_S3_BACKUP_BUCKET_NAME),
  308. container.get(TYPES.Revisions_S3),
  309. container.get(TYPES.Revisions_RevisionItemStringMapper),
  310. )
  311. : new FSDumpRepository(container.get(TYPES.Revisions_RevisionItemStringMapper)),
  312. )
  313. // use cases
  314. container
  315. .bind<GetRevisionsMetada>(TYPES.Revisions_GetRevisionsMetada)
  316. .toConstantValue(
  317. new GetRevisionsMetada(
  318. container.get<RevisionRepositoryResolverInterface>(TYPES.Revisions_RevisionRepositoryResolver),
  319. ),
  320. )
  321. container
  322. .bind<GetRevision>(TYPES.Revisions_GetRevision)
  323. .toConstantValue(
  324. new GetRevision(container.get<RevisionRepositoryResolverInterface>(TYPES.Revisions_RevisionRepositoryResolver)),
  325. )
  326. container
  327. .bind<DeleteRevision>(TYPES.Revisions_DeleteRevision)
  328. .toConstantValue(
  329. new DeleteRevision(
  330. container.get<RevisionRepositoryResolverInterface>(TYPES.Revisions_RevisionRepositoryResolver),
  331. ),
  332. )
  333. container
  334. .bind<CopyRevisions>(TYPES.Revisions_CopyRevisions)
  335. .toConstantValue(
  336. new CopyRevisions(
  337. container.get<RevisionRepositoryResolverInterface>(TYPES.Revisions_RevisionRepositoryResolver),
  338. ),
  339. )
  340. container
  341. .bind<TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser>(
  342. TYPES.Revisions_TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser,
  343. )
  344. .toConstantValue(
  345. new TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser(
  346. container.get<RevisionRepositoryInterface>(TYPES.Revisions_SQLRevisionRepository),
  347. isSecondaryDatabaseEnabled
  348. ? container.get<RevisionRepositoryInterface>(TYPES.Revisions_MongoDBRevisionRepository)
  349. : null,
  350. isConfiguredForInMemoryCache
  351. ? null
  352. : container.get<TransitionRepositoryInterface>(TYPES.Revisions_TransitionStatusRepository),
  353. container.get<TimerInterface>(TYPES.Revisions_Timer),
  354. container.get<winston.Logger>(TYPES.Revisions_Logger),
  355. env.get('MIGRATION_BATCH_SIZE', true) ? +env.get('MIGRATION_BATCH_SIZE', true) : 100,
  356. container.get<DomainEventPublisherInterface>(TYPES.Revisions_DomainEventPublisher),
  357. container.get<DomainEventFactoryInterface>(TYPES.Revisions_DomainEventFactory),
  358. ),
  359. )
  360. container
  361. .bind<RemoveRevisionsFromSharedVault>(TYPES.Revisions_RemoveRevisionsFromSharedVault)
  362. .toConstantValue(
  363. new RemoveRevisionsFromSharedVault(
  364. isSecondaryDatabaseEnabled
  365. ? container.get<RevisionRepositoryInterface>(TYPES.Revisions_MongoDBRevisionRepository)
  366. : container.get<RevisionRepositoryInterface>(TYPES.Revisions_SQLRevisionRepository),
  367. ),
  368. )
  369. container
  370. .bind<CreateRevisionFromDump>(TYPES.Revisions_CreateRevisionFromDump)
  371. .toConstantValue(
  372. new CreateRevisionFromDump(
  373. container.get<DumpRepositoryInterface>(TYPES.Revisions_DumpRepository),
  374. container.get<RevisionRepositoryResolverInterface>(TYPES.Revisions_RevisionRepositoryResolver),
  375. ),
  376. )
  377. // env vars
  378. container.bind(TYPES.Revisions_AUTH_JWT_SECRET).toConstantValue(env.get('AUTH_JWT_SECRET'))
  379. // Controller
  380. container
  381. .bind<ControllerContainerInterface>(TYPES.Revisions_ControllerContainer)
  382. .toConstantValue(configuration?.controllerConatiner ?? new ControllerContainer())
  383. container
  384. .bind<TokenDecoderInterface<CrossServiceTokenData>>(TYPES.Revisions_CrossServiceTokenDecoder)
  385. .toDynamicValue((context: interfaces.Context) => {
  386. return new TokenDecoder<CrossServiceTokenData>(context.container.get(TYPES.Revisions_AUTH_JWT_SECRET))
  387. })
  388. container
  389. .bind<ApiGatewayAuthMiddleware>(TYPES.Revisions_ApiGatewayAuthMiddleware)
  390. .toDynamicValue((context: interfaces.Context) => {
  391. return new ApiGatewayAuthMiddleware(
  392. context.container.get(TYPES.Revisions_CrossServiceTokenDecoder),
  393. context.container.get(TYPES.Revisions_Logger),
  394. )
  395. })
  396. // Handlers
  397. container
  398. .bind<ItemDumpedEventHandler>(TYPES.Revisions_ItemDumpedEventHandler)
  399. .toConstantValue(
  400. new ItemDumpedEventHandler(
  401. container.get<CreateRevisionFromDump>(TYPES.Revisions_CreateRevisionFromDump),
  402. container.get<winston.Logger>(TYPES.Revisions_Logger),
  403. ),
  404. )
  405. container
  406. .bind<AccountDeletionRequestedEventHandler>(TYPES.Revisions_AccountDeletionRequestedEventHandler)
  407. .toConstantValue(
  408. new AccountDeletionRequestedEventHandler(
  409. container.get<RevisionRepositoryResolverInterface>(TYPES.Revisions_RevisionRepositoryResolver),
  410. container.get<winston.Logger>(TYPES.Revisions_Logger),
  411. ),
  412. )
  413. container
  414. .bind<RevisionsCopyRequestedEventHandler>(TYPES.Revisions_RevisionsCopyRequestedEventHandler)
  415. .toConstantValue(
  416. new RevisionsCopyRequestedEventHandler(
  417. container.get<CopyRevisions>(TYPES.Revisions_CopyRevisions),
  418. container.get<winston.Logger>(TYPES.Revisions_Logger),
  419. ),
  420. )
  421. container
  422. .bind<ItemRemovedFromSharedVaultEventHandler>(TYPES.Revisions_ItemRemovedFromSharedVaultEventHandler)
  423. .toConstantValue(
  424. new ItemRemovedFromSharedVaultEventHandler(
  425. container.get<RemoveRevisionsFromSharedVault>(TYPES.Revisions_RemoveRevisionsFromSharedVault),
  426. container.get<winston.Logger>(TYPES.Revisions_Logger),
  427. ),
  428. )
  429. container
  430. .bind<TransitionRequestedEventHandler>(TYPES.Revisions_TransitionRequestedEventHandler)
  431. .toConstantValue(
  432. new TransitionRequestedEventHandler(
  433. false,
  434. container.get<TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser>(
  435. TYPES.Revisions_TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser,
  436. ),
  437. container.get<winston.Logger>(TYPES.Revisions_Logger),
  438. ),
  439. )
  440. container
  441. .bind<SharedVaultRemovedEventHandler>(TYPES.Revisions_SharedVaultRemovedEventHandler)
  442. .toConstantValue(
  443. new SharedVaultRemovedEventHandler(
  444. container.get<RemoveRevisionsFromSharedVault>(TYPES.Revisions_RemoveRevisionsFromSharedVault),
  445. container.get<winston.Logger>(TYPES.Revisions_Logger),
  446. ),
  447. )
  448. const eventHandlers: Map<string, DomainEventHandlerInterface> = new Map([
  449. ['ITEM_DUMPED', container.get(TYPES.Revisions_ItemDumpedEventHandler)],
  450. ['ACCOUNT_DELETION_REQUESTED', container.get(TYPES.Revisions_AccountDeletionRequestedEventHandler)],
  451. ['REVISIONS_COPY_REQUESTED', container.get(TYPES.Revisions_RevisionsCopyRequestedEventHandler)],
  452. ['ITEM_REMOVED_FROM_SHARED_VAULT', container.get(TYPES.Revisions_ItemRemovedFromSharedVaultEventHandler)],
  453. ['TRANSITION_REQUESTED', container.get(TYPES.Revisions_TransitionRequestedEventHandler)],
  454. ['SHARED_VAULT_REMOVED', container.get(TYPES.Revisions_SharedVaultRemovedEventHandler)],
  455. ])
  456. if (isConfiguredForHomeServer) {
  457. const directCallEventMessageHandler = new DirectCallEventMessageHandler(
  458. eventHandlers,
  459. container.get(TYPES.Revisions_Logger),
  460. )
  461. directCallDomainEventPublisher.register(directCallEventMessageHandler)
  462. container
  463. .bind<DomainEventMessageHandlerInterface>(TYPES.Revisions_DomainEventMessageHandler)
  464. .toConstantValue(directCallEventMessageHandler)
  465. } else {
  466. container
  467. .bind<DomainEventMessageHandlerInterface>(TYPES.Revisions_DomainEventMessageHandler)
  468. .toConstantValue(
  469. isConfiguredForHomeServerOrSelfHosting
  470. ? new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Revisions_Logger))
  471. : new SQSOpenTelemetryEventMessageHandler(
  472. ServiceIdentifier.NAMES.RevisionsWorker,
  473. eventHandlers,
  474. container.get(TYPES.Revisions_Logger),
  475. ),
  476. )
  477. container
  478. .bind<DomainEventSubscriberFactoryInterface>(TYPES.Revisions_DomainEventSubscriberFactory)
  479. .toDynamicValue((context: interfaces.Context) => {
  480. return new SQSDomainEventSubscriberFactory(
  481. context.container.get(TYPES.Revisions_SQS),
  482. context.container.get(TYPES.Revisions_SQS_QUEUE_URL),
  483. context.container.get(TYPES.Revisions_DomainEventMessageHandler),
  484. )
  485. })
  486. }
  487. // Inversify Controllers
  488. if (isConfiguredForHomeServer) {
  489. container
  490. .bind<BaseRevisionsController>(TYPES.Revisions_BaseRevisionsController)
  491. .toConstantValue(
  492. new BaseRevisionsController(
  493. container.get<GetRevisionsMetada>(TYPES.Revisions_GetRevisionsMetada),
  494. container.get<GetRevision>(TYPES.Revisions_GetRevision),
  495. container.get<DeleteRevision>(TYPES.Revisions_DeleteRevision),
  496. container.get<RevisionHttpMapper>(TYPES.Revisions_RevisionHttpMapper),
  497. container.get<RevisionMetadataHttpMapper>(TYPES.Revisions_RevisionMetadataHttpMapper),
  498. container.get<ControllerContainerInterface>(TYPES.Revisions_ControllerContainer),
  499. ),
  500. )
  501. }
  502. logger.debug('Configuration complete')
  503. return container
  504. }
  505. }