backend/app/services/Config.scala (198 lines of code) (raw):
package services
import net.ceedubs.ficus.Ficus._
import net.ceedubs.ficus.readers.ArbitraryTypeReader._
import net.ceedubs.ficus.readers.EnumerationReader._
import play.api.libs.json.Json
import scala.concurrent.duration.FiniteDuration
// NOTE!
// When modifying settings here, be aware they can also be rewritten in AwsDiscovery.scala
case class AwsConnection(
region: String,
profile: Option[String]
)
case class AppConfig(
label: Option[String],
hideDownloadButton: Boolean,
readOnly: Boolean
)
sealed trait AuthProviderConfig {
val name: String
}
case class DatabaseAuthConfig(
minPasswordLength: Int,
require2FA: Boolean,
totpIssuer: String
) extends AuthProviderConfig {
val name = DatabaseAuthConfig.name
}
object DatabaseAuthConfig {
val name = "database"
}
case class PandaAuthConfig(
bucketName: String,
publicSettingsKey: String,
cookieName: String,
require2FA: Boolean,
loginUrl: String,
aws: AwsConnection
) extends AuthProviderConfig {
val name = PandaAuthConfig.name
}
object PandaAuthConfig {
val name = "panda"
}
case class AuthTimeouts(
maxLoginAge: FiniteDuration,
maxVerificationAge: FiniteDuration,
maxDownloadAuthAge: FiniteDuration
)
case class AuthConfig(
timeouts: AuthTimeouts,
enableGenesisFlow: Boolean,
provider: AuthProviderConfig
)
object OcrEngine extends Enumeration {
val Tesseract = Value("Tesseract")
val OcrMyPdf = Value("OCRmyPDF")
}
case class TesseractOcrConfig(
pageSegmentationMode: Int,
engineMode: Int
)
case class OcrConfig(
defaultEngine: OcrEngine.Value,
dpi: Int,
tesseract: TesseractOcrConfig
)
case class TranscribeConfig(
whisperModelFilename: String,
transcriptionServiceQueueUrl: String,
transcriptionOutputQueueUrl: String,
transcriptionOutputDeadLetterQueueUrl: String
)
case class WorkerConfig(
name: Option[String],
interval: FiniteDuration,
controlInterval: FiniteDuration,
controlCooldown: FiniteDuration,
enabled: Boolean,
workspace: String,
useExternalExtractors: Boolean
)
case class Neo4jQueryLoggingConfig(
slowQueryThreshold: FiniteDuration,
logAllQueries: Boolean
)
case class Neo4jConfig(
url: String,
user: String,
password: String,
queryLogging: Neo4jQueryLoggingConfig
)
case class PostgresConfig(
host: String,
port: Int,
username: String,
password: String,
)
object PostgresConfig {
implicit val format = Json.format[PostgresConfig]
}
case class ElasticsearchConfig(
hosts: List[String],
indexName: String,
tableRowIndexName: String,
eventIndexName: String,
pageIndexNamePrefix: String,
shards: Int,
// For when are port-forwarding to a remote instance of Elasticsearch and therefore can only connect to one node,
// otherwise you will get connection errors
disableSniffing: Option[Boolean]
// TODO MRB: customisable number of shards?
)
case class IngestConfig(
chunkSize: Int,
batchSize: Int,
fingerprintFiles: Boolean,
scratchPath: String,
inMemoryThreshold: Long
)
case class PreviewConfig(
libreOfficeBinary: String,
wkhtmltopdfBinary: String,
workspace: String
)
case class S3Config(
region: String,
buckets: BucketConfig,
// These settings are used just for Minio
endpoint: Option[String],
accessKey: Option[String],
secretKey: Option[String],
// These settings are just for AWS
sseAlgorithm: Option[String]
)
case class SQSConfig(
region: String,
endpoint: Option[String]
)
case class BucketConfig(
ingestion: String,
deadLetter: String,
collections: String,
preview: String,
transcription: String
) {
val all: List[String] = List(ingestion, deadLetter, collections, preview)
}
case class AWSDiscoveryConfig(
region: String,
stack: String,
app: String,
stage: String,
runningLocally: Option[Boolean],
workerAutoScalingGroupName: Option[String]
)
case class Config(
underlying: com.typesafe.config.Config,
app: AppConfig,
auth: AuthConfig,
worker: WorkerConfig,
neo4j: Neo4jConfig,
postgres: Option[PostgresConfig],
elasticsearch: ElasticsearchConfig,
ingestion: IngestConfig,
preview: PreviewConfig,
s3: S3Config,
aws: Option[AWSDiscoveryConfig],
ocr: OcrConfig,
transcribe: TranscribeConfig,
sqs: SQSConfig
)
object Config {
def apply(raw: com.typesafe.config.Config): Config = Config(
raw,
raw.as[AppConfig]("app"),
parseAuth(raw.getConfig("auth")),
raw.as[WorkerConfig]("worker"),
raw.as[Neo4jConfig]("neo4j"),
raw.as[Option[PostgresConfig]]("postgres"),
raw.as[ElasticsearchConfig]("elasticsearch"),
raw.as[IngestConfig]("ingestion"),
raw.as[PreviewConfig]("preview"),
raw.as[S3Config]("s3"),
raw.as[Option[AWSDiscoveryConfig]]("aws"),
raw.as[OcrConfig]("ocr"),
raw.as[TranscribeConfig]("transcribe"),
raw.as[SQSConfig]("sqs")
)
private def parseAuth(rawAuthConfig: com.typesafe.config.Config): AuthConfig = {
val providerName = rawAuthConfig.as[String]("provider")
val provider = providerName match {
case DatabaseAuthConfig.name =>
rawAuthConfig.as[DatabaseAuthConfig](DatabaseAuthConfig.name)
case PandaAuthConfig.name =>
rawAuthConfig.as[PandaAuthConfig](PandaAuthConfig.name)
case _ =>
throw new IllegalArgumentException(s"Unknown auth provider $providerName")
}
AuthConfig(
rawAuthConfig.as[AuthTimeouts]("timeouts"),
rawAuthConfig.as[Boolean]("enableGenesisFlow"),
provider
)
}
}