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>
|
<flyway_version>6.3.3</flyway_version>
|
||||||
<javajwt_version>3.10.2</javajwt_version>
|
<javajwt_version>3.10.2</javajwt_version>
|
||||||
<jbcrypt_version>0.4</jbcrypt_version>
|
<jbcrypt_version>0.4</jbcrypt_version>
|
||||||
|
<hoplite_version>1.2.2</hoplite_version>
|
||||||
|
|
||||||
<kotlin.code.style>official</kotlin.code.style>
|
<kotlin.code.style>official</kotlin.code.style>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
@ -149,6 +150,16 @@
|
|||||||
<artifactId>HikariCP</artifactId>
|
<artifactId>HikariCP</artifactId>
|
||||||
<version>3.4.2</version>
|
<version>3.4.2</version>
|
||||||
</dependency>
|
</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>
|
<dependency>
|
||||||
<groupId>com.github.javafaker</groupId>
|
<groupId>com.github.javafaker</groupId>
|
||||||
<artifactId>javafaker</artifactId>
|
<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
|
package be.vandewalleh
|
||||||
|
|
||||||
import be.vandewalleh.features.configurationFeature
|
import be.vandewalleh.features.Config
|
||||||
import be.vandewalleh.features.configurationModule
|
import be.vandewalleh.features.configurationModule
|
||||||
import be.vandewalleh.features.features
|
import be.vandewalleh.features.loadFeatures
|
||||||
import be.vandewalleh.migrations.Migration
|
import be.vandewalleh.migrations.Migration
|
||||||
import be.vandewalleh.routing.registerRoutes
|
import be.vandewalleh.routing.registerRoutes
|
||||||
import be.vandewalleh.services.serviceModule
|
import be.vandewalleh.services.serviceModule
|
||||||
import io.ktor.application.*
|
import io.ktor.application.*
|
||||||
import io.ktor.routing.*
|
import io.ktor.routing.*
|
||||||
|
import io.ktor.server.engine.*
|
||||||
|
import io.ktor.server.netty.*
|
||||||
import me.liuwj.ktorm.database.*
|
import me.liuwj.ktorm.database.*
|
||||||
import org.kodein.di.Kodein
|
import org.kodein.di.Kodein
|
||||||
import org.kodein.di.description
|
import org.kodein.di.description
|
||||||
import org.kodein.di.generic.bind
|
import org.kodein.di.generic.bind
|
||||||
import org.kodein.di.generic.instance
|
import org.kodein.di.generic.instance
|
||||||
import org.kodein.di.generic.singleton
|
import org.kodein.di.generic.singleton
|
||||||
|
import org.slf4j.Logger
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
import javax.sql.DataSource
|
import javax.sql.DataSource
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
lateinit var kodein: Kodein
|
val kodein = Kodein {
|
||||||
|
import(serviceModule)
|
||||||
@Suppress("unused") // Referenced in application.conf
|
import(configurationModule)
|
||||||
fun Application.module() {
|
bind<Logger>() with singleton { LoggerFactory.getLogger("Application") }
|
||||||
// must be first to be loaded
|
bind<Migration>() with singleton { Migration(this.kodein) }
|
||||||
configurationFeature()
|
bind<Database>() with singleton { Database.connect(this.instance<DataSource>()) }
|
||||||
|
}
|
||||||
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())
|
|
||||||
|
|
||||||
|
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>()
|
val migration by kodein.instance<Migration>()
|
||||||
migration.migrate()
|
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 {
|
routing {
|
||||||
registerRoutes(kodein)
|
registerRoutes(kodein)
|
||||||
|
|||||||
@ -1,42 +1,61 @@
|
|||||||
package be.vandewalleh.features
|
package be.vandewalleh.features
|
||||||
|
|
||||||
import be.vandewalleh.auth.SimpleJWT
|
import be.vandewalleh.auth.SimpleJWT
|
||||||
|
import com.sksamuel.hoplite.ConfigLoader
|
||||||
|
import com.sksamuel.hoplite.Masked
|
||||||
import com.zaxxer.hikari.HikariConfig
|
import com.zaxxer.hikari.HikariConfig
|
||||||
import com.zaxxer.hikari.HikariDataSource
|
import com.zaxxer.hikari.HikariDataSource
|
||||||
import io.ktor.application.*
|
|
||||||
import org.kodein.di.Kodein
|
import org.kodein.di.Kodein
|
||||||
import org.kodein.di.generic.bind
|
import org.kodein.di.generic.bind
|
||||||
import org.kodein.di.generic.instance
|
import org.kodein.di.generic.instance
|
||||||
|
import org.kodein.di.generic.singleton
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import javax.sql.DataSource
|
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() {
|
data class DatabaseConfig(val host: String, val port: Int, val name: String, val username: String, val password: Masked)
|
||||||
val dataSource: DataSource = with(environment.config) {
|
data class ServerConfig(val host: String, val port: Int)
|
||||||
val host = property("database.host").getString()
|
data class JwtConfig(val secret: Masked, val auth: JwtValidity, val refresh: JwtValidity)
|
||||||
val port = property("database.port").getString()
|
data class JwtValidity(val validity: Long, val unit: TimeUnit)
|
||||||
val name = property("database.name").getString()
|
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()
|
return HikariDataSource(hikariConfig)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -1,6 +1,5 @@
|
|||||||
package be.vandewalleh.features
|
package be.vandewalleh.features
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature
|
|
||||||
import io.ktor.application.*
|
import io.ktor.application.*
|
||||||
import io.ktor.features.*
|
import io.ktor.features.*
|
||||||
import io.ktor.jackson.*
|
import io.ktor.jackson.*
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import io.ktor.utils.io.errors.*
|
|||||||
|
|
||||||
fun Application.handleErrors() {
|
fun Application.handleErrors() {
|
||||||
install(StatusPages) {
|
install(StatusPages) {
|
||||||
exception<IOException> { _ ->
|
exception<IOException> {
|
||||||
call.respond(HttpStatusCode.BadRequest)
|
call.respond(HttpStatusCode.BadRequest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ package be.vandewalleh.features
|
|||||||
import be.vandewalleh.auth.authenticationModule
|
import be.vandewalleh.auth.authenticationModule
|
||||||
import io.ktor.application.*
|
import io.ktor.application.*
|
||||||
|
|
||||||
fun Application.features() {
|
fun Application.loadFeatures() {
|
||||||
corsFeature()
|
corsFeature()
|
||||||
contentNegotiationFeature()
|
contentNegotiationFeature()
|
||||||
authenticationModule()
|
authenticationModule()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user