app/Components.scala (214 lines of code) (raw):
import com.amazonaws.auth.AWSCredentialsProvider
import software.amazon.awssdk.regions.{Region => WeirdRegion}
import com.amazonaws.services.sns.AmazonSNSClient
import software.amazon.awssdk.auth.credentials.{
AwsCredentials,
AwsCredentialsProvider,
AwsCredentialsProviderChain,
DefaultCredentialsProvider,
ProfileCredentialsProvider
}
import conf.ApplicationConfiguration
import config.{CustomGzipFilter, UpdateManager}
import controllers._
import frontsapi.model.UpdateActions
import metrics.CloudWatch
import play.api.ApplicationLoader.Context
import play.api.Mode
import play.api.db.{DBComponents, HikariCPComponents}
import play.api.db.evolutions.EvolutionsComponents
import play.api.routing.Router
import play.filters.cors.CORSConfig
import play.filters.cors.CORSConfig.Origins
import filters._
import model.editions.{EditionsAppTemplates, FeastAppTemplates}
import router.Routes
import services._
import services.editions.EditionsTemplating
import services.editions.db.EditionsDB
import services.editions.publishing.events.PublishEventsListener
import services.editions.publishing.{
EditionsAppPublicationTarget,
FeastPublicationTarget,
Publishing
}
import slices.{Containers, FixedContainers}
import software.amazon.awssdk.services.dynamodb.DynamoDbClient
import thumbnails.ContainerThumbnails
import tools.FaciaApiIO
import updates.{BreakingNewsUpdate, StructuredLogger}
import util.{Acl, TimestampGenerator}
import services.editions.publishing.PublishedIssueFormatters._
class AppComponents(context: Context, val config: ApplicationConfiguration)
extends BaseFaciaControllerComponents(context)
with EvolutionsComponents
with DBComponents
with HikariCPComponents {
applicationEvolutions
val isDev: Boolean = context.environment.mode == Mode.Dev
val isTest: Boolean = context.environment.mode == Mode.Test
val isProd: Boolean = context.environment.mode == Mode.Prod
// Services
val awsEndpoints = new AwsEndpoints(config)
val capi = new GuardianCapi(config)
val ophan = new GuardianOphan(config)
val oldAwsCredentials: AWSCredentialsProvider =
config.aws.cmsFrontsAccountCredentials
val newAwsCredentials: AwsCredentialsProvider =
config.aws.newStyleCmsFrontsAccountCredentials
// Scala 2.13 requires a version of Scanamo which requires the 'new' Amazon AWS SDK.
// This means we have two different SDKs for AWS in the build, which is unideal
// but should not lead to problems.
// TODO Upversion the rest of the AWS SDK code!
val dynamo: DynamoDbClient = DynamoDbClient
.builder()
.credentialsProvider(newAwsCredentials)
.region(WeirdRegion.of(config.aws.region))
.build()
val s3Client = S3.client(oldAwsCredentials, config.aws.region)
val snsClient = AmazonSNSClient
.builder()
.withCredentials(oldAwsCredentials)
.withRegion(config.aws.region)
.build()
val acl = new Acl(permissions)
// Editions services
val editionsDb = new EditionsDB(
config.postgres.url,
config.postgres.user,
config.postgres.password
)
val templating = new EditionsTemplating(
EditionsAppTemplates.templates ++ FeastAppTemplates.templates,
capi,
ophan
)
val publishingBucket = new EditionsAppPublicationTarget(
s3Client,
config.aws.publishedEditionsIssuesBucket
)
val previewBucket = new EditionsAppPublicationTarget(
s3Client,
config.aws.previewEditionsIssuesBucket
)
val feastPublicationTarget =
new FeastPublicationTarget(snsClient, config, TimestampGenerator())
val editionsPublishing = new Publishing(
publishingBucket,
previewBucket,
feastPublicationTarget,
editionsDb
)
PublishEventsListener.apply(config, editionsDb).start
// Controllers
val frontsApi = new FrontsApi(config, awsEndpoints)
val s3FrontsApi = new S3FrontsApi(config, isTest, awsEndpoints)
val faciaApiIO = new FaciaApiIO(frontsApi, s3FrontsApi)
val configAgent = new ConfigAgent(config, frontsApi)
val structuredLogger = new StructuredLogger(config, configAgent)
val breakingNewsUpdate =
new BreakingNewsUpdate(config, wsClient, structuredLogger)
val fixedContainers = new FixedContainers(config)
val containerThumbnails = new ContainerThumbnails(fixedContainers)
val containers = new Containers(fixedContainers)
val containerService = new ContainerService(containers)
val collectionService = new CollectionService(frontsApi, containerService)
val faciaPressTopic = new FaciaPressTopic(config)
val faciaPress = new FaciaPress(faciaPressTopic, configAgent)
val updateActions = new UpdateActions(
faciaApiIO,
frontsApi,
config,
configAgent,
structuredLogger
)
val updateManager = new UpdateManager(updateActions, configAgent, s3FrontsApi)
val cloudwatch = new CloudWatch(config, awsEndpoints)
val press = new Press(faciaPress)
val assetsManager = new AssetsManager(config, isDev)
override lazy val httpErrorHandler = new LoggingHttpErrorHandler(
environment,
configuration,
devContext.map(_.sourceMapper),
Some(router)
)
// Controllers
val editions = new EditionsController(
editionsDb,
templating,
editionsPublishing,
capi,
this
)
val collection =
new CollectionController(acl, structuredLogger, updateManager, press, this)
val defaults = new DefaultsController(acl, isDev, this)
val faciaCapiProxy = new FaciaContentApiProxy(capi, this)
val faciaTool = new FaciaToolController(
acl,
frontsApi,
collectionService,
faciaApiIO,
updateActions,
breakingNewsUpdate,
structuredLogger,
faciaPress,
faciaPressTopic,
configAgent,
s3FrontsApi,
this
)
val front =
new FrontController(acl, structuredLogger, updateManager, press, this)
val pandaAuth = new PandaAuthController(this)
val status = new StatusController(this)
val storiesVisible = new StoriesVisibleController(containerService, this)
val thumbnail = new ThumbnailController(containerThumbnails, this)
val troubleshoot = new TroubleshootController(this)
val v1Assets = new V1Assets(assets, this)
val v2Assets = new V2Assets(assets)
val vanityRedirects = new VanityRedirects(acl, this)
val views = new ViewsController(acl, assetsManager, isDev, this)
val pressController = new PressController(dynamo, this)
val v2App = new V2App(isDev, acl, dynamo, editionsDb, this)
val faciaToolV2 = new FaciaToolV2Controller(
acl,
structuredLogger,
faciaPress,
updateActions,
configAgent,
collectionService,
faciaApiIO,
this
)
val userDataController = new UserDataController(frontsApi, dynamo, this)
val gridProxy = new GridProxy(this)
val loggingFilter = new LoggingFilter
final override lazy val corsConfig: CORSConfig = CORSConfig
.fromConfiguration(context.initialConfiguration)
.copy(
allowedOrigins = Origins.Matching(Set(config.environment.applicationUrl))
)
override lazy val assets: Assets =
new controllers.Assets(httpErrorHandler, assetsMetadata, environment)
val router: Router = new Routes(
httpErrorHandler,
status,
pandaAuth,
v2Assets,
v1Assets,
views,
faciaTool,
pressController,
faciaToolV2,
defaults,
userDataController,
faciaCapiProxy,
thumbnail,
front,
collection,
storiesVisible,
vanityRedirects,
troubleshoot,
v2App,
gridProxy,
editions
)
override lazy val httpFilters = Seq(
new CustomGzipFilter()(materializer),
corsFilter,
loggingFilter
)
}