Update Ktor to 2.0.2
Signed-off-by: Billy Brawner <me@wbrawner.com>
This commit is contained in:
parent
698051fab1
commit
b170d632e4
14 changed files with 123 additions and 95 deletions
28
README.md
28
README.md
|
@ -23,20 +23,20 @@ running, you can run the app from the command line with gradle:
|
||||||
|
|
||||||
Some parameters of Twigs can be configured via environment variables:
|
Some parameters of Twigs can be configured via environment variables:
|
||||||
|
|
||||||
Environment Variable|Default Value|Note
|
| Environment Variable | Default Value | Note |
|
||||||
:---:|:---:|:---
|
|:--------------------:|:-------------:|:--------------------------------------------------------|
|
||||||
`TWIGS_PORT`|`8080`|Port for web server to listen on
|
| `TWIGS_PORT` | `8080` | Port for web server to listen on |
|
||||||
`TWIGS_DB_HOST`|`localhost`|PostgreSQL server host
|
| `TWIGS_DB_HOST` | `localhost` | PostgreSQL server host |
|
||||||
`TWIGS_DB_PORT`|`5432`|PostgreSQL server port
|
| `TWIGS_DB_PORT` | `5432` | PostgreSQL server port |
|
||||||
`TWIGS_DB_NAME`|`twigs`|PostgreSQL database name
|
| `TWIGS_DB_NAME` | `twigs` | PostgreSQL database name |
|
||||||
`TWIGS_DB_USER`|`twigs`|PostgreSQL database user
|
| `TWIGS_DB_USER` | `twigs` | PostgreSQL database user |
|
||||||
`TWIGS_DB_PASS`|`twigs`|PostgreSQL database password
|
| `TWIGS_DB_PASS` | `twigs` | PostgreSQL database password |
|
||||||
`TWIGS_PW_SALT`||Salt to use for password, generated if empty or null
|
| `TWIGS_PW_SALT` | | Salt to use for password, generated if empty or null |
|
||||||
`TWIGS_SMTP_FROM`||From email address for automated emails sent from Twigs
|
| `TWIGS_SMTP_FROM` | | From email address for automated emails sent from Twigs |
|
||||||
`TWIGS_SMTP_HOST`||SMTP server host for sending emails
|
| `TWIGS_SMTP_HOST` | | SMTP server host for sending emails |
|
||||||
`TWIGS_SMTP_PORT`||SMTP server port for sending emails
|
| `TWIGS_SMTP_PORT` | | SMTP server port for sending emails |
|
||||||
`TWIGS_SMTP_USER`||SMTP server username for sending emails
|
| `TWIGS_SMTP_USER` | | SMTP server username for sending emails |
|
||||||
`TWIGS_SMTP_PASS`||SMTP server password for sending emails
|
| `TWIGS_SMTP_PASS` | | SMTP server password for sending emails |
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
|
|
|
@ -5,10 +5,10 @@ import com.wbrawner.twigs.model.Permission
|
||||||
import com.wbrawner.twigs.model.Session
|
import com.wbrawner.twigs.model.Session
|
||||||
import com.wbrawner.twigs.storage.BudgetRepository
|
import com.wbrawner.twigs.storage.BudgetRepository
|
||||||
import com.wbrawner.twigs.storage.PermissionRepository
|
import com.wbrawner.twigs.storage.PermissionRepository
|
||||||
import io.ktor.application.*
|
|
||||||
import io.ktor.auth.*
|
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import io.ktor.response.*
|
import io.ktor.server.application.*
|
||||||
|
import io.ktor.server.auth.*
|
||||||
|
import io.ktor.server.response.*
|
||||||
import io.ktor.util.pipeline.*
|
import io.ktor.util.pipeline.*
|
||||||
|
|
||||||
suspend inline fun PipelineContext<Unit, ApplicationCall>.requireBudgetWithPermission(
|
suspend inline fun PipelineContext<Unit, ApplicationCall>.requireBudgetWithPermission(
|
||||||
|
@ -58,5 +58,5 @@ suspend inline fun PipelineContext<Unit, ApplicationCall>.errorResponse(
|
||||||
) {
|
) {
|
||||||
message?.let {
|
message?.let {
|
||||||
call.respond(httpStatusCode, ErrorResponse(message))
|
call.respond(httpStatusCode, ErrorResponse(message))
|
||||||
}?: call.respond(httpStatusCode)
|
} ?: call.respond(httpStatusCode)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,12 @@ import com.wbrawner.twigs.model.Session
|
||||||
import com.wbrawner.twigs.model.UserPermission
|
import com.wbrawner.twigs.model.UserPermission
|
||||||
import com.wbrawner.twigs.storage.BudgetRepository
|
import com.wbrawner.twigs.storage.BudgetRepository
|
||||||
import com.wbrawner.twigs.storage.PermissionRepository
|
import com.wbrawner.twigs.storage.PermissionRepository
|
||||||
import io.ktor.application.*
|
|
||||||
import io.ktor.auth.*
|
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import io.ktor.request.*
|
import io.ktor.server.application.*
|
||||||
import io.ktor.response.*
|
import io.ktor.server.auth.*
|
||||||
import io.ktor.routing.*
|
import io.ktor.server.request.*
|
||||||
|
import io.ktor.server.response.*
|
||||||
|
import io.ktor.server.routing.*
|
||||||
|
|
||||||
fun Application.budgetRoutes(
|
fun Application.budgetRoutes(
|
||||||
budgetRepository: BudgetRepository,
|
budgetRepository: BudgetRepository,
|
||||||
|
@ -34,7 +34,12 @@ fun Application.budgetRoutes(
|
||||||
}
|
}
|
||||||
|
|
||||||
get("/{id}") {
|
get("/{id}") {
|
||||||
budgetWithPermission(budgetRepository, permissionRepository, call.parameters["id"]!!, Permission.READ) { budget ->
|
budgetWithPermission(
|
||||||
|
budgetRepository,
|
||||||
|
permissionRepository,
|
||||||
|
call.parameters["id"]!!,
|
||||||
|
Permission.READ
|
||||||
|
) { budget ->
|
||||||
val users = permissionRepository.findAll(budgetIds = listOf(budget.id))
|
val users = permissionRepository.findAll(budgetIds = listOf(budget.id))
|
||||||
call.respond(BudgetResponse(budget, users))
|
call.respond(BudgetResponse(budget, users))
|
||||||
}
|
}
|
||||||
|
@ -77,7 +82,12 @@ fun Application.budgetRoutes(
|
||||||
}
|
}
|
||||||
|
|
||||||
put("/{id}") {
|
put("/{id}") {
|
||||||
budgetWithPermission(budgetRepository, permissionRepository, call.parameters["id"]!!, Permission.MANAGE) { budget ->
|
budgetWithPermission(
|
||||||
|
budgetRepository,
|
||||||
|
permissionRepository,
|
||||||
|
call.parameters["id"]!!,
|
||||||
|
Permission.MANAGE
|
||||||
|
) { budget ->
|
||||||
val request = call.receive<BudgetRequest>()
|
val request = call.receive<BudgetRequest>()
|
||||||
val name = request.name ?: budget.name
|
val name = request.name ?: budget.name
|
||||||
val description = request.description ?: budget.description
|
val description = request.description ?: budget.description
|
||||||
|
@ -99,7 +109,12 @@ fun Application.budgetRoutes(
|
||||||
}
|
}
|
||||||
|
|
||||||
delete("/{id}") {
|
delete("/{id}") {
|
||||||
budgetWithPermission(budgetRepository, permissionRepository, budgetId = call.parameters["id"]!!, Permission.OWNER) { budget ->
|
budgetWithPermission(
|
||||||
|
budgetRepository,
|
||||||
|
permissionRepository,
|
||||||
|
budgetId = call.parameters["id"]!!,
|
||||||
|
Permission.OWNER
|
||||||
|
) { budget ->
|
||||||
budgetRepository.delete(budget)
|
budgetRepository.delete(budget)
|
||||||
call.respond(HttpStatusCode.NoContent)
|
call.respond(HttpStatusCode.NoContent)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,12 @@ import com.wbrawner.twigs.model.Permission
|
||||||
import com.wbrawner.twigs.model.Session
|
import com.wbrawner.twigs.model.Session
|
||||||
import com.wbrawner.twigs.storage.CategoryRepository
|
import com.wbrawner.twigs.storage.CategoryRepository
|
||||||
import com.wbrawner.twigs.storage.PermissionRepository
|
import com.wbrawner.twigs.storage.PermissionRepository
|
||||||
import io.ktor.application.*
|
|
||||||
import io.ktor.auth.*
|
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import io.ktor.request.*
|
import io.ktor.server.application.*
|
||||||
import io.ktor.response.*
|
import io.ktor.server.auth.*
|
||||||
import io.ktor.routing.*
|
import io.ktor.server.request.*
|
||||||
|
import io.ktor.server.response.*
|
||||||
|
import io.ktor.server.routing.*
|
||||||
|
|
||||||
fun Application.categoryRoutes(
|
fun Application.categoryRoutes(
|
||||||
categoryRepository: CategoryRepository,
|
categoryRepository: CategoryRepository,
|
||||||
|
|
|
@ -5,12 +5,12 @@ import com.wbrawner.twigs.model.RecurringTransaction
|
||||||
import com.wbrawner.twigs.model.Session
|
import com.wbrawner.twigs.model.Session
|
||||||
import com.wbrawner.twigs.storage.PermissionRepository
|
import com.wbrawner.twigs.storage.PermissionRepository
|
||||||
import com.wbrawner.twigs.storage.RecurringTransactionRepository
|
import com.wbrawner.twigs.storage.RecurringTransactionRepository
|
||||||
import io.ktor.application.*
|
|
||||||
import io.ktor.auth.*
|
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import io.ktor.request.*
|
import io.ktor.server.application.*
|
||||||
import io.ktor.response.*
|
import io.ktor.server.auth.*
|
||||||
import io.ktor.routing.*
|
import io.ktor.server.request.*
|
||||||
|
import io.ktor.server.response.*
|
||||||
|
import io.ktor.server.routing.*
|
||||||
import io.ktor.util.pipeline.*
|
import io.ktor.util.pipeline.*
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,12 @@ import com.wbrawner.twigs.model.Session
|
||||||
import com.wbrawner.twigs.model.Transaction
|
import com.wbrawner.twigs.model.Transaction
|
||||||
import com.wbrawner.twigs.storage.PermissionRepository
|
import com.wbrawner.twigs.storage.PermissionRepository
|
||||||
import com.wbrawner.twigs.storage.TransactionRepository
|
import com.wbrawner.twigs.storage.TransactionRepository
|
||||||
import io.ktor.application.*
|
|
||||||
import io.ktor.auth.*
|
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import io.ktor.request.*
|
import io.ktor.server.application.*
|
||||||
import io.ktor.response.*
|
import io.ktor.server.auth.*
|
||||||
import io.ktor.routing.*
|
import io.ktor.server.request.*
|
||||||
|
import io.ktor.server.response.*
|
||||||
|
import io.ktor.server.routing.*
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
fun Application.transactionRoutes(
|
fun Application.transactionRoutes(
|
||||||
|
@ -32,7 +32,7 @@ fun Application.transactionRoutes(
|
||||||
from = call.request.queryParameters["from"]?.let { Instant.parse(it) },
|
from = call.request.queryParameters["from"]?.let { Instant.parse(it) },
|
||||||
to = call.request.queryParameters["to"]?.let { Instant.parse(it) },
|
to = call.request.queryParameters["to"]?.let { Instant.parse(it) },
|
||||||
expense = call.request.queryParameters["expense"]?.toBoolean(),
|
expense = call.request.queryParameters["expense"]?.toBoolean(),
|
||||||
).map { it.asResponse() })
|
).map { it.asResponse() })
|
||||||
}
|
}
|
||||||
|
|
||||||
get("/{id}") {
|
get("/{id}") {
|
||||||
|
|
|
@ -7,12 +7,12 @@ import com.wbrawner.twigs.storage.PasswordResetRepository
|
||||||
import com.wbrawner.twigs.storage.PermissionRepository
|
import com.wbrawner.twigs.storage.PermissionRepository
|
||||||
import com.wbrawner.twigs.storage.SessionRepository
|
import com.wbrawner.twigs.storage.SessionRepository
|
||||||
import com.wbrawner.twigs.storage.UserRepository
|
import com.wbrawner.twigs.storage.UserRepository
|
||||||
import io.ktor.application.*
|
|
||||||
import io.ktor.auth.*
|
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import io.ktor.request.*
|
import io.ktor.server.application.*
|
||||||
import io.ktor.response.*
|
import io.ktor.server.auth.*
|
||||||
import io.ktor.routing.*
|
import io.ktor.server.request.*
|
||||||
|
import io.ktor.server.response.*
|
||||||
|
import io.ktor.server.routing.*
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
fun Application.userRoutes(
|
fun Application.userRoutes(
|
||||||
|
|
|
@ -22,9 +22,7 @@ dependencies {
|
||||||
implementation(project(":db"))
|
implementation(project(":db"))
|
||||||
implementation(project(":web"))
|
implementation(project(":web"))
|
||||||
implementation(libs.kotlin.reflect)
|
implementation(libs.kotlin.reflect)
|
||||||
implementation(libs.ktor.server.core)
|
implementation(libs.bundles.ktor.server)
|
||||||
implementation(libs.ktor.server.cio)
|
|
||||||
implementation(libs.ktor.server.sessions)
|
|
||||||
implementation(libs.kotlinx.coroutines.core)
|
implementation(libs.kotlinx.coroutines.core)
|
||||||
implementation(libs.logback)
|
implementation(libs.logback)
|
||||||
implementation(libs.mail)
|
implementation(libs.mail)
|
||||||
|
|
|
@ -8,13 +8,15 @@ import com.wbrawner.twigs.storage.*
|
||||||
import com.wbrawner.twigs.web.webRoutes
|
import com.wbrawner.twigs.web.webRoutes
|
||||||
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 io.ktor.auth.*
|
|
||||||
import io.ktor.features.*
|
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import io.ktor.response.*
|
import io.ktor.serialization.kotlinx.json.*
|
||||||
import io.ktor.serialization.*
|
import io.ktor.server.application.*
|
||||||
import io.ktor.sessions.*
|
import io.ktor.server.auth.*
|
||||||
|
import io.ktor.server.plugins.callloging.*
|
||||||
|
import io.ktor.server.plugins.contentnegotiation.*
|
||||||
|
import io.ktor.server.plugins.cors.routing.*
|
||||||
|
import io.ktor.server.response.*
|
||||||
|
import io.ktor.server.sessions.*
|
||||||
import kotlinx.coroutines.currentCoroutineContext
|
import kotlinx.coroutines.currentCoroutineContext
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
|
@ -80,14 +82,14 @@ fun Application.moduleWithDependencies(
|
||||||
call.respond(HttpStatusCode.Unauthorized)
|
call.respond(HttpStatusCode.Unauthorized)
|
||||||
}
|
}
|
||||||
validate { session ->
|
validate { session ->
|
||||||
environment.log.info("Validating session")
|
application.environment.log.info("Validating session")
|
||||||
val storedSession = sessionRepository.findAll(session.token)
|
val storedSession = sessionRepository.findAll(session.token)
|
||||||
.firstOrNull()
|
.firstOrNull()
|
||||||
if (storedSession == null) {
|
if (storedSession == null) {
|
||||||
environment.log.info("Did not find session!")
|
application.environment.log.info("Did not find session!")
|
||||||
return@validate null
|
return@validate null
|
||||||
} else {
|
} else {
|
||||||
environment.log.info("Found session!")
|
application.environment.log.info("Found session!")
|
||||||
}
|
}
|
||||||
return@validate if (twoWeeksFromNow.isAfter(storedSession.expiration)) {
|
return@validate if (twoWeeksFromNow.isAfter(storedSession.expiration)) {
|
||||||
sessionRepository.save(storedSession.copy(expiration = twoWeeksFromNow))
|
sessionRepository.save(storedSession.copy(expiration = twoWeeksFromNow))
|
||||||
|
@ -101,7 +103,7 @@ fun Application.moduleWithDependencies(
|
||||||
header<Session>("Authorization") {
|
header<Session>("Authorization") {
|
||||||
serializer = object : SessionSerializer<Session> {
|
serializer = object : SessionSerializer<Session> {
|
||||||
override fun deserialize(text: String): Session {
|
override fun deserialize(text: String): Session {
|
||||||
environment.log.info("Deserializing session!")
|
this@moduleWithDependencies.environment.log.info("Deserializing session!")
|
||||||
return Session(token = text.substringAfter("Bearer "))
|
return Session(token = text.substringAfter("Bearer "))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,28 +124,28 @@ fun Application.moduleWithDependencies(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
install(CORS) {
|
install(CORS) {
|
||||||
host("twigs.wbrawner.com", listOf("http", "https")) // TODO: Make configurable
|
allowHost("twigs.wbrawner.com", listOf("http", "https")) // TODO: Make configurable
|
||||||
method(HttpMethod.Options)
|
allowMethod(HttpMethod.Options)
|
||||||
method(HttpMethod.Put)
|
allowMethod(HttpMethod.Put)
|
||||||
method(HttpMethod.Delete)
|
allowMethod(HttpMethod.Delete)
|
||||||
header(HttpHeaders.Authorization)
|
allowHeader(HttpHeaders.Authorization)
|
||||||
header(HttpHeaders.Accept)
|
allowHeader(HttpHeaders.Accept)
|
||||||
header(HttpHeaders.AcceptEncoding)
|
allowHeader(HttpHeaders.AcceptEncoding)
|
||||||
header(HttpHeaders.AcceptLanguage)
|
allowHeader(HttpHeaders.AcceptLanguage)
|
||||||
header(HttpHeaders.Connection)
|
allowHeader(HttpHeaders.Connection)
|
||||||
header(HttpHeaders.ContentType)
|
allowHeader(HttpHeaders.ContentType)
|
||||||
header(HttpHeaders.Host)
|
allowHeader(HttpHeaders.Host)
|
||||||
header(HttpHeaders.Origin)
|
allowHeader(HttpHeaders.Origin)
|
||||||
header(HttpHeaders.AccessControlRequestHeaders)
|
allowHeader(HttpHeaders.AccessControlRequestHeaders)
|
||||||
header(HttpHeaders.AccessControlRequestMethod)
|
allowHeader(HttpHeaders.AccessControlRequestMethod)
|
||||||
header("Sec-Fetch-Dest")
|
allowHeader("Sec-Fetch-Dest")
|
||||||
header("Sec-Fetch-Mode")
|
allowHeader("Sec-Fetch-Mode")
|
||||||
header("Sec-Fetch-Site")
|
allowHeader("Sec-Fetch-Site")
|
||||||
header("sec-ch-ua")
|
allowHeader("sec-ch-ua")
|
||||||
header("sec-ch-ua-mobile")
|
allowHeader("sec-ch-ua-mobile")
|
||||||
header("sec-ch-ua-platform")
|
allowHeader("sec-ch-ua-platform")
|
||||||
header(HttpHeaders.UserAgent)
|
allowHeader(HttpHeaders.UserAgent)
|
||||||
header("DNT")
|
allowHeader("DNT")
|
||||||
allowCredentials = true
|
allowCredentials = true
|
||||||
}
|
}
|
||||||
budgetRoutes(budgetRepository, permissionRepository)
|
budgetRoutes(budgetRepository, permissionRepository)
|
||||||
|
|
|
@ -5,7 +5,7 @@ plugins {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(kotlin("stdlib"))
|
implementation(kotlin("stdlib"))
|
||||||
api(libs.ktor.auth)
|
api(libs.ktor.server.auth)
|
||||||
api(libs.bcrypt)
|
api(libs.bcrypt)
|
||||||
testImplementation(libs.junit.jupiter.api)
|
testImplementation(libs.junit.jupiter.api)
|
||||||
testRuntimeOnly(libs.junit.jupiter.engine)
|
testRuntimeOnly(libs.junit.jupiter.engine)
|
||||||
|
|
|
@ -3,7 +3,7 @@ package com.wbrawner.twigs.model
|
||||||
import com.wbrawner.twigs.Identifiable
|
import com.wbrawner.twigs.Identifiable
|
||||||
import com.wbrawner.twigs.randomString
|
import com.wbrawner.twigs.randomString
|
||||||
import com.wbrawner.twigs.twoWeeksFromNow
|
import com.wbrawner.twigs.twoWeeksFromNow
|
||||||
import io.ktor.auth.*
|
import io.ktor.server.auth.*
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
data class Session(
|
data class Session(
|
||||||
|
|
|
@ -2,7 +2,7 @@ package com.wbrawner.twigs.model
|
||||||
|
|
||||||
import com.wbrawner.twigs.Identifiable
|
import com.wbrawner.twigs.Identifiable
|
||||||
import com.wbrawner.twigs.randomString
|
import com.wbrawner.twigs.randomString
|
||||||
import io.ktor.auth.*
|
import io.ktor.server.auth.*
|
||||||
|
|
||||||
data class User(
|
data class User(
|
||||||
override val id: String = randomString(),
|
override val id: String = randomString(),
|
||||||
|
|
|
@ -4,7 +4,7 @@ hikari = "5.0.1"
|
||||||
junit = "5.8.2"
|
junit = "5.8.2"
|
||||||
kotlin = "1.6.21"
|
kotlin = "1.6.21"
|
||||||
kotlinx-coroutines = "1.6.2"
|
kotlinx-coroutines = "1.6.2"
|
||||||
ktor = "1.6.6"
|
ktor = "2.0.2"
|
||||||
logback = "1.2.11"
|
logback = "1.2.11"
|
||||||
mail = "1.6.2"
|
mail = "1.6.2"
|
||||||
postgres = "42.3.4"
|
postgres = "42.3.4"
|
||||||
|
@ -15,19 +15,32 @@ bcrypt = { module = "at.favre.lib:bcrypt", version.ref = "bcrypt" }
|
||||||
hikari = { module = "com.zaxxer:HikariCP", version.ref = "hikari" }
|
hikari = { module = "com.zaxxer:HikariCP", version.ref = "hikari" }
|
||||||
junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit" }
|
junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit" }
|
||||||
junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine" }
|
junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine" }
|
||||||
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }
|
|
||||||
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" }
|
|
||||||
kotlin-gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
|
kotlin-gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
|
||||||
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
|
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
|
||||||
ktor-auth = { module = "io.ktor:ktor-auth", version.ref = "ktor" }
|
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }
|
||||||
ktor-serialization = { module = "io.ktor:ktor-serialization", version.ref = "ktor" }
|
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" }
|
||||||
|
ktor-serialization = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
|
||||||
|
ktor-server-auth = { module = "io.ktor:ktor-server-auth", version.ref = "ktor" }
|
||||||
|
ktor-server-call-logging = { module = "io.ktor:ktor-server-call-logging", version.ref = "ktor" }
|
||||||
ktor-server-cio = { module = "io.ktor:ktor-server-cio", version.ref = "ktor" }
|
ktor-server-cio = { module = "io.ktor:ktor-server-cio", version.ref = "ktor" }
|
||||||
|
ktor-server-content-negotiation = { module = "io.ktor:ktor-server-content-negotiation", version.ref = "ktor" }
|
||||||
ktor-server-core = { module = "io.ktor:ktor-server-core", version.ref = "ktor" }
|
ktor-server-core = { module = "io.ktor:ktor-server-core", version.ref = "ktor" }
|
||||||
|
ktor-server-cors = { module = "io.ktor:ktor-server-cors", version.ref = "ktor" }
|
||||||
ktor-server-sessions = { module = "io.ktor:ktor-server-sessions", version.ref = "ktor" }
|
ktor-server-sessions = { module = "io.ktor:ktor-server-sessions", version.ref = "ktor" }
|
||||||
logback = { module = "ch.qos.logback:logback-classic", version.ref = "logback" }
|
logback = { module = "ch.qos.logback:logback-classic", version.ref = "logback" }
|
||||||
mail = { module = "com.sun.mail:javax.mail", version.ref = "mail" }
|
mail = { module = "com.sun.mail:javax.mail", version.ref = "mail" }
|
||||||
postgres = { module = "org.postgresql:postgresql", version.ref = "postgres" }
|
postgres = { module = "org.postgresql:postgresql", version.ref = "postgres" }
|
||||||
|
|
||||||
|
[bundles]
|
||||||
|
ktor-server = [
|
||||||
|
"ktor-server-call-logging",
|
||||||
|
"ktor-server-cio",
|
||||||
|
"ktor-server-content-negotiation",
|
||||||
|
"ktor-server-core",
|
||||||
|
"ktor-server-cors",
|
||||||
|
"ktor-server-sessions"
|
||||||
|
]
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
||||||
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
|
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package com.wbrawner.twigs.web
|
package com.wbrawner.twigs.web
|
||||||
|
|
||||||
import io.ktor.application.*
|
import io.ktor.server.application.*
|
||||||
import io.ktor.http.content.*
|
import io.ktor.server.http.content.*
|
||||||
import io.ktor.request.*
|
import io.ktor.server.request.*
|
||||||
import io.ktor.response.*
|
import io.ktor.server.response.*
|
||||||
import io.ktor.routing.*
|
import io.ktor.server.routing.*
|
||||||
|
|
||||||
fun Application.webRoutes() {
|
fun Application.webRoutes() {
|
||||||
routing {
|
routing {
|
||||||
|
|
Loading…
Reference in a new issue