Use new config library + refactor
This commit is contained in:
parent
cbe1a8a7b7
commit
fb95413856
11
api/pom.xml
11
api/pom.xml
@ -18,6 +18,7 @@
|
||||
<flyway_version>6.3.3</flyway_version>
|
||||
<javajwt_version>3.10.2</javajwt_version>
|
||||
<jbcrypt_version>0.4</jbcrypt_version>
|
||||
<hoplite_version>1.2.2</hoplite_version>
|
||||
|
||||
<kotlin.code.style>official</kotlin.code.style>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
@ -149,6 +150,16 @@
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>3.4.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sksamuel.hoplite</groupId>
|
||||
<artifactId>hoplite-core</artifactId>
|
||||
<version>${hoplite_version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sksamuel.hoplite</groupId>
|
||||
<artifactId>hoplite-yaml</artifactId>
|
||||
<version>${hoplite_version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.javafaker</groupId>
|
||||
<artifactId>javafaker</artifactId>
|
||||
|
||||
@ -1,22 +0,0 @@
|
||||
ktor {
|
||||
deployment {
|
||||
port = 8081
|
||||
port = ${?PORT}
|
||||
}
|
||||
application {
|
||||
modules = [ be.vandewalleh.NotesApplicationKt.module ]
|
||||
}
|
||||
}
|
||||
|
||||
database {
|
||||
host = "127.0.0.1"
|
||||
port = "3306"
|
||||
name = "Notes"
|
||||
user = "test"
|
||||
password = "test"
|
||||
}
|
||||
|
||||
jwt {
|
||||
secret = "thisisasecret"
|
||||
secret = ${?SECRET}
|
||||
}
|
||||
22
api/resources/application.yaml
Normal file
22
api/resources/application.yaml
Normal file
@ -0,0 +1,22 @@
|
||||
env: staging
|
||||
|
||||
database:
|
||||
host: 127.0.0.1
|
||||
port: 3306
|
||||
name: Notes
|
||||
username: test
|
||||
password: test
|
||||
|
||||
server:
|
||||
host: 0.0.0.0
|
||||
port: 8081
|
||||
|
||||
jwt:
|
||||
secret: ${random.string(25)}
|
||||
auth:
|
||||
validity: 1
|
||||
unit: HOURS
|
||||
refresh:
|
||||
validity: 15
|
||||
unit: DAYS
|
||||
|
||||
@ -1,42 +1,64 @@
|
||||
package be.vandewalleh
|
||||
|
||||
import be.vandewalleh.features.configurationFeature
|
||||
import be.vandewalleh.features.Config
|
||||
import be.vandewalleh.features.configurationModule
|
||||
import be.vandewalleh.features.features
|
||||
import be.vandewalleh.features.loadFeatures
|
||||
import be.vandewalleh.migrations.Migration
|
||||
import be.vandewalleh.routing.registerRoutes
|
||||
import be.vandewalleh.services.serviceModule
|
||||
import io.ktor.application.*
|
||||
import io.ktor.routing.*
|
||||
import io.ktor.server.engine.*
|
||||
import io.ktor.server.netty.*
|
||||
import me.liuwj.ktorm.database.*
|
||||
import org.kodein.di.Kodein
|
||||
import org.kodein.di.description
|
||||
import org.kodein.di.generic.bind
|
||||
import org.kodein.di.generic.instance
|
||||
import org.kodein.di.generic.singleton
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import javax.sql.DataSource
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
lateinit var kodein: Kodein
|
||||
|
||||
@Suppress("unused") // Referenced in application.conf
|
||||
fun Application.module() {
|
||||
// must be first to be loaded
|
||||
configurationFeature()
|
||||
|
||||
kodein = Kodein {
|
||||
import(configurationModule)
|
||||
import(serviceModule)
|
||||
|
||||
bind<Migration>() with singleton { Migration(this.kodein) }
|
||||
bind<Database>() with singleton { Database.Companion.connect(this.instance<DataSource>()) }
|
||||
}
|
||||
|
||||
features()
|
||||
|
||||
log.debug(kodein.container.tree.bindings.description())
|
||||
val kodein = Kodein {
|
||||
import(serviceModule)
|
||||
import(configurationModule)
|
||||
bind<Logger>() with singleton { LoggerFactory.getLogger("Application") }
|
||||
bind<Migration>() with singleton { Migration(this.kodein) }
|
||||
bind<Database>() with singleton { Database.connect(this.instance<DataSource>()) }
|
||||
}
|
||||
|
||||
fun main() {
|
||||
val config by kodein.instance<Config>()
|
||||
val logger by kodein.instance<Logger>()
|
||||
logger.info("Running application with configuration $config")
|
||||
val migration by kodein.instance<Migration>()
|
||||
migration.migrate()
|
||||
serve(kodein)
|
||||
}
|
||||
|
||||
fun serve(kodein: Kodein) {
|
||||
val config by kodein.instance<Config>()
|
||||
val logger by kodein.instance<Logger>()
|
||||
val env = applicationEngineEnvironment {
|
||||
module {
|
||||
module()
|
||||
}
|
||||
log = logger
|
||||
connector {
|
||||
host = config.server.host
|
||||
port = config.server.port
|
||||
}
|
||||
}
|
||||
embeddedServer(Netty, env).start(wait = true)
|
||||
}
|
||||
|
||||
|
||||
fun Application.module() {
|
||||
loadFeatures()
|
||||
|
||||
log.debug(kodein.container.tree.bindings.description())
|
||||
|
||||
routing {
|
||||
registerRoutes(kodein)
|
||||
|
||||
@ -1,42 +1,61 @@
|
||||
package be.vandewalleh.features
|
||||
|
||||
import be.vandewalleh.auth.SimpleJWT
|
||||
import com.sksamuel.hoplite.ConfigLoader
|
||||
import com.sksamuel.hoplite.Masked
|
||||
import com.zaxxer.hikari.HikariConfig
|
||||
import com.zaxxer.hikari.HikariDataSource
|
||||
import io.ktor.application.*
|
||||
import org.kodein.di.Kodein
|
||||
import org.kodein.di.generic.bind
|
||||
import org.kodein.di.generic.instance
|
||||
import org.kodein.di.generic.singleton
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.sql.DataSource
|
||||
|
||||
/**
|
||||
* [Kodein] configuration module
|
||||
* [Kodein] controller module containing the app configuration
|
||||
*/
|
||||
lateinit var configurationModule: Kodein.Module
|
||||
val configurationModule = Kodein.Module(name = "Configuration") {
|
||||
bind() from singleton { ConfigLoader().loadConfigOrThrow<Config>("/application.yaml") }
|
||||
bind<SimpleJWT>(tag = "auth") with singleton { configureAuthJwt(this.kodein) }
|
||||
bind<SimpleJWT>(tag = "refresh") with singleton { configureRefreshJwt(this.kodein) }
|
||||
bind<DataSource>() with singleton { configureDatasource(this.kodein) }
|
||||
}
|
||||
|
||||
fun Application.configurationFeature() {
|
||||
val dataSource: DataSource = with(environment.config) {
|
||||
val host = property("database.host").getString()
|
||||
val port = property("database.port").getString()
|
||||
val name = property("database.name").getString()
|
||||
data class DatabaseConfig(val host: String, val port: Int, val name: String, val username: String, val password: Masked)
|
||||
data class ServerConfig(val host: String, val port: Int)
|
||||
data class JwtConfig(val secret: Masked, val auth: JwtValidity, val refresh: JwtValidity)
|
||||
data class JwtValidity(val validity: Long, val unit: TimeUnit)
|
||||
data class Config(val database: DatabaseConfig, val server: ServerConfig, val jwt: JwtConfig)
|
||||
|
||||
val hikariConfig = HikariConfig().apply {
|
||||
jdbcUrl = "jdbc:mariadb://$host:$port/$name"
|
||||
username = this@with.property("database.user").getString()
|
||||
password = this@with.property("database.password").getString()
|
||||
}
|
||||
|
||||
HikariDataSource(hikariConfig)
|
||||
private fun configureAuthJwt(kodein: Kodein): SimpleJWT {
|
||||
val config by kodein.instance<Config>()
|
||||
val jwtSecret = config.jwt.secret
|
||||
val authConfig = config.jwt.auth
|
||||
return SimpleJWT(jwtSecret.value, authConfig.validity, authConfig.unit)
|
||||
}
|
||||
|
||||
private fun configureRefreshJwt(kodein: Kodein): SimpleJWT {
|
||||
val config by kodein.instance<Config>()
|
||||
val jwtSecret = config.jwt.secret
|
||||
val refreshConfig = config.jwt.auth
|
||||
return SimpleJWT(jwtSecret.value, refreshConfig.validity, refreshConfig.unit)
|
||||
}
|
||||
|
||||
private fun configureDatasource(kodein: Kodein): DataSource {
|
||||
val config by kodein.instance<Config>()
|
||||
val dbConfig = config.database
|
||||
|
||||
val host = dbConfig.host
|
||||
val port = dbConfig.port
|
||||
val name = dbConfig.name
|
||||
|
||||
val hikariConfig = HikariConfig().apply {
|
||||
jdbcUrl = "jdbc:mariadb://$host:$port/$name"
|
||||
username = dbConfig.username
|
||||
password = dbConfig.password.value
|
||||
}
|
||||
|
||||
val jwtSecret = environment.config.property("jwt.secret").getString()
|
||||
val authSimpleJwt = SimpleJWT(jwtSecret, 1, TimeUnit.HOURS)
|
||||
val refreshSimpleJwt = SimpleJWT(jwtSecret, 7, TimeUnit.DAYS)
|
||||
|
||||
configurationModule = Kodein.Module("Configuration") {
|
||||
bind<DataSource>() with instance(dataSource)
|
||||
bind<SimpleJWT>(tag = "auth") with instance(authSimpleJwt)
|
||||
bind<SimpleJWT>(tag = "refresh") with instance(refreshSimpleJwt)
|
||||
}
|
||||
return HikariDataSource(hikariConfig)
|
||||
}
|
||||
@ -1,6 +1,5 @@
|
||||
package be.vandewalleh.features
|
||||
|
||||
import com.fasterxml.jackson.databind.SerializationFeature
|
||||
import io.ktor.application.*
|
||||
import io.ktor.features.*
|
||||
import io.ktor.jackson.*
|
||||
|
||||
@ -8,7 +8,7 @@ import io.ktor.utils.io.errors.*
|
||||
|
||||
fun Application.handleErrors() {
|
||||
install(StatusPages) {
|
||||
exception<IOException> { _ ->
|
||||
exception<IOException> {
|
||||
call.respond(HttpStatusCode.BadRequest)
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ package be.vandewalleh.features
|
||||
import be.vandewalleh.auth.authenticationModule
|
||||
import io.ktor.application.*
|
||||
|
||||
fun Application.features() {
|
||||
fun Application.loadFeatures() {
|
||||
corsFeature()
|
||||
contentNegotiationFeature()
|
||||
authenticationModule()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user