Skip to content
This repository has been archived by the owner on Jul 13, 2021. It is now read-only.

Upgrade ktor from 0.3.0 to 0.9.1 #36

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions .idea/runConfigurations/Backend____Jetty.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 7 additions & 9 deletions backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,19 @@ apply plugin: 'kotlin'
apply plugin: 'application'

dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"

compile "org.jetbrains.ktor:ktor-locations:$ktor_version"
compile "org.jetbrains.ktor:ktor-html-builder:$ktor_version"
compile "io.ktor:ktor-locations:$ktor_version"
compile "io.ktor:ktor-html-builder:$ktor_version"
compile "io.ktor:ktor-gson:$ktor_version"
compile "org.ehcache:ehcache:3.0.0.m4"

compile "org.jetbrains.squash:squash-h2:$squash_version"

testCompile("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version")
testCompile "org.jetbrains.ktor:ktor-test-host:$ktor_version"
testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
testCompile "io.ktor:ktor-server-test-host:$ktor_version"
testCompile "org.jsoup:jsoup:1.9.1"

compile "org.jetbrains.ktor:ktor-jetty:$ktor_version"
compile group: 'com.google.code.gson', name: 'gson', version: '2.8.0'
}

sourceSets {
Expand All @@ -41,4 +39,4 @@ kotlin {
}
}

mainClassName = 'org.jetbrains.ktor.jetty.DevelopmentHost'
mainClassName = 'io.ktor.server.jetty.DevelopmentEngine'
43 changes: 22 additions & 21 deletions backend/src/org/jetbrains/demo/thinkter/Application.kt
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
package org.jetbrains.demo.thinkter

import com.google.gson.*
import org.jetbrains.demo.thinkter.dao.*
import org.jetbrains.demo.thinkter.model.*
import org.jetbrains.ktor.application.*
import org.jetbrains.ktor.content.*
import org.jetbrains.ktor.features.*
import org.jetbrains.ktor.http.*
import org.jetbrains.ktor.locations.*
import org.jetbrains.ktor.logging.*
import org.jetbrains.ktor.routing.*
import org.jetbrains.ktor.sessions.*
import org.jetbrains.ktor.transform.*
import io.ktor.application.Application
import io.ktor.application.call
import io.ktor.application.install
import io.ktor.features.*
import io.ktor.gson.gson
import io.ktor.http.HttpStatusCode
import io.ktor.locations.Locations
import io.ktor.response.respond
import io.ktor.routing.routing
import io.ktor.sessions.SessionTransportTransformerMessageAuthentication
import io.ktor.sessions.Sessions
import io.ktor.sessions.cookie
import org.jetbrains.demo.thinkter.dao.ThinkterDatabase

data class Session(val userId: String)

Expand All @@ -21,21 +22,21 @@ fun Application.main() {
install(DefaultHeaders)
install(CallLogging)
install(ConditionalHeaders)
install(PartialContentSupport)
install(PartialContent)
install(Compression)
install(Locations)
install(StatusPages) {
exception<NotImplementedError> { call.respond(HttpStatusCode.NotImplemented) }
exception<NotImplementedError> { call.respond(HttpStatusCode.NotImplemented, "${it.message}") }
}

withSessions<Session> {
withCookieByValue {
settings = SessionCookiesSettings(transformers = listOf(SessionCookieTransformerMessageAuthentication(hashKey)))
install(ContentNegotiation) {
gson {
setPrettyPrinting()
}
}

transform.register<RpcData> {
TextContent(Gson().toJson(it), ContentType.Application.Json)
install(Sessions) {
cookie<Session>(name = "SESSION") {
transform(SessionTransportTransformerMessageAuthentication(hashKey))
}
}

routing {
Expand Down
4 changes: 2 additions & 2 deletions backend/src/org/jetbrains/demo/thinkter/ApplicationPage.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.jetbrains.demo.thinkter

import kotlinx.html.*
import org.jetbrains.ktor.html.*
import io.ktor.html.*

class ApplicationPage : Template<HTML> {
val caption = Placeholder<TITLE>()
Expand Down Expand Up @@ -45,7 +45,7 @@ class ApplicationPage : Template<HTML> {
}
}
div { id = "content" }
script(src = "frontend/frontend.bundle.js")
script(src = "frontend/frontend.bundle.js", block = {})
}
}
}
29 changes: 19 additions & 10 deletions backend/src/org/jetbrains/demo/thinkter/Delete.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ package org.jetbrains.demo.thinkter

import org.jetbrains.demo.thinkter.dao.*
import org.jetbrains.demo.thinkter.model.*
import org.jetbrains.ktor.application.*
import org.jetbrains.ktor.http.*
import org.jetbrains.ktor.locations.*
import org.jetbrains.ktor.routing.*
import org.jetbrains.ktor.sessions.*
import io.ktor.application.*
import io.ktor.http.*
import io.ktor.locations.*
import io.ktor.request.receive
import io.ktor.response.respond
import io.ktor.routing.*
import io.ktor.sessions.get
import io.ktor.sessions.sessions

fun Route.delete(dao: ThinkterStorage, hashFunction: (String) -> String) {
get<ThoughtDelete> {
val user = call.sessionOrNull<Session>()?.let { dao.user(it.userId) }
val user = call.sessions.get<Session>()?.let { dao.user(it.userId) }
val date = System.currentTimeMillis()

if (user == null) {
Expand All @@ -22,13 +25,19 @@ fun Route.delete(dao: ThinkterStorage, hashFunction: (String) -> String) {
}

post<ThoughtDelete> {
val user = call.sessionOrNull<Session>()?.let { dao.user(it.userId) }
val thought = dao.getThought(it.id)
val user = call.sessions.get<Session>()?.let { dao.user(it.userId) }

if (user == null || thought.userId != user.userId || !call.verifyCode(it.date, user, it.code, hashFunction)) {
val form = call.receive<Parameters>()
val id = form["id"]?.toInt() ?: -1
val date = form["date"]?.toLong() ?: -1
val code = form["code"] ?: ""

val thought = dao.getThought(id)

if (user == null || thought.userId != user.userId || !call.verifyCode(date, user, code, hashFunction)) {
call.respond(HttpStatusCode.Forbidden)
} else {
dao.deleteThought(it.id)
dao.deleteThought(id)
call.respond(object : RpcData {})
}
}
Expand Down
22 changes: 11 additions & 11 deletions backend/src/org/jetbrains/demo/thinkter/Index.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,30 @@ package org.jetbrains.demo.thinkter

import org.jetbrains.demo.thinkter.dao.*
import org.jetbrains.demo.thinkter.model.*
import org.jetbrains.ktor.application.*
import org.jetbrains.ktor.html.*
import org.jetbrains.ktor.http.*
import org.jetbrains.ktor.locations.*
import org.jetbrains.ktor.response.*
import org.jetbrains.ktor.routing.*
import org.jetbrains.ktor.sessions.*
import io.ktor.application.*
import io.ktor.html.*
import io.ktor.http.*
import io.ktor.locations.*
import io.ktor.response.*
import io.ktor.routing.*
import io.ktor.sessions.*
import java.time.*

fun Route.index(storage: ThinkterStorage) {
contentType(ContentType.Text.Html) {
accept(ContentType.Text.Html) {
get<Index> {
call.respondHtmlTemplate(ApplicationPage()) {
caption { +"Thinkter" }
}
}
}
contentType(ContentType.Application.Json) {
accept(ContentType.Application.Json) {
get<Index> {
val user = call.sessionOrNull<Session>()?.let { storage.user(it.userId) }
val user = call.sessions.get<Session>()?.let { storage.user(it.userId) }
val top = storage.top(10).map(storage::getThought)
val latest = storage.latest(10).map(storage::getThought)

call.response.pipeline.intercept(ApplicationResponsePipeline.After) {
call.response.pipeline.intercept(ApplicationSendPipeline.After) {
val etagString = user?.userId + "," + top.joinToString { it.id.toString() } + latest.joinToString { it.id.toString() }
call.response.etag(etagString)
}
Expand Down
22 changes: 11 additions & 11 deletions backend/src/org/jetbrains/demo/thinkter/Locations.kt
Original file line number Diff line number Diff line change
@@ -1,35 +1,35 @@
package org.jetbrains.demo.thinkter

import org.jetbrains.ktor.locations.*
import io.ktor.locations.*


@location("/")
@Location("/")
class Index()

@location("/poll")
@Location("/poll")
class Poll(val lastTime: String = "")

@location("/post-new")
@Location("/post-new")
data class PostThought(val text: String = "", val date: Long = 0L, val code: String = "", val replyTo: Int? = null)

@location("/thought/{id}/delete")
@Location("/thought/{id}/delete")
data class ThoughtDelete(val id: Int, val date: Long, val code: String)

@location("/thought/{id}")
@Location("/thought/{id}")
data class ViewThought(val id: Int)

@location("/user/{user}")
@Location("/user/{user}")
@Deprecated("")
data class UserPage(val user: String)

@location("/user/{user}/thoughts")
@Location("/user/{user}/thoughts")
data class UserThoughts(val user: String)

@location("/register")
@Location("/register")
data class Register(val userId: String = "", val displayName: String = "", val email: String = "", val password: String = "", val error: String = "")

@location("/login")
@Location("/login")
data class Login(val userId: String = "", val password: String = "", val error: String = "")

@location("/logout")
@Location("/logout")
class Logout()
30 changes: 18 additions & 12 deletions backend/src/org/jetbrains/demo/thinkter/Login.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,44 @@ package org.jetbrains.demo.thinkter

import org.jetbrains.demo.thinkter.dao.*
import org.jetbrains.demo.thinkter.model.*
import org.jetbrains.ktor.application.*
import org.jetbrains.ktor.http.*
import org.jetbrains.ktor.locations.*
import org.jetbrains.ktor.routing.*
import org.jetbrains.ktor.sessions.*
import io.ktor.application.*
import io.ktor.http.*
import io.ktor.locations.*
import io.ktor.request.receive
import io.ktor.response.respond
import io.ktor.routing.*
import io.ktor.sessions.*

fun Route.login(dao: ThinkterStorage, hash: (String) -> String) {
get<Login> {
val user = call.sessionOrNull<Session>()?.let { dao.user(it.userId) }
val user = call.sessions.get<Session>()?.let { dao.user(it.userId) }
if (user == null) {
call.respond(HttpStatusCode.Forbidden)
} else {
call.respond(LoginResponse(user))
}
}
post<Login> {
val form = call.receive<Parameters>()
val userId = form["userId"] ?: ""
val password = form["password"] ?: ""

val login = when {
it.userId.length < 4 -> null
it.password.length < 6 -> null
!userNameValid(it.userId) -> null
else -> dao.user(it.userId, hash(it.password))
userId.length < 4 -> null
password.length < 6 -> null
!userNameValid(userId) -> null
else -> dao.user(userId, hash(password))
}

if (login == null) {
call.respond(LoginResponse(error = "Invalid username or password"))
} else {
call.session(Session(login.userId))
call.sessions.set(Session(login.userId))
call.respond(LoginResponse(login))
}
}
post<Logout> {
call.clearSession()
call.sessions.clear<Session>()
call.respond(HttpStatusCode.OK)
}
}
28 changes: 19 additions & 9 deletions backend/src/org/jetbrains/demo/thinkter/PostThought.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ package org.jetbrains.demo.thinkter

import org.jetbrains.demo.thinkter.dao.*
import org.jetbrains.demo.thinkter.model.*
import org.jetbrains.ktor.application.*
import org.jetbrains.ktor.http.*
import org.jetbrains.ktor.locations.*
import org.jetbrains.ktor.routing.*
import org.jetbrains.ktor.sessions.*
import io.ktor.application.*
import io.ktor.http.*
import io.ktor.locations.*
import io.ktor.request.receive
import io.ktor.response.respond
import io.ktor.routing.*
import io.ktor.sessions.*

fun Route.postThought(dao: ThinkterStorage, hashFunction: (String) -> String) {
get<PostThought> {
val user = call.sessionOrNull<Session>()?.let { dao.user(it.userId) }
val user = call.sessions.get<Session>()?.let { dao.user(it.userId) }

if (user == null) {
call.respond(HttpStatusCode.Forbidden)
Expand All @@ -21,11 +23,19 @@ fun Route.postThought(dao: ThinkterStorage, hashFunction: (String) -> String) {
}
}
post<PostThought> {
val user = call.sessionOrNull<Session>()?.let { dao.user(it.userId) }
if (user == null || !call.verifyCode(it.date, user, it.code, hashFunction)) {
val user = call.sessions.get<Session>()?.let { dao.user(it.userId) }

val form = call.receive<Parameters>()
val date = form["date"]?.toLong() ?: -1
val code = form["code"] ?: ""

if (user == null || !call.verifyCode(date, user, code, hashFunction)) {
call.respond(HttpStatusCode.Forbidden)
} else {
val id = dao.createThought(user.userId, it.text, it.replyTo)
val text = form["text"] ?: ""
val replyTo = form["replyTo"]?.toInt()

val id = dao.createThought(user.userId, text, replyTo)
call.respond(PostThoughtResult(dao.getThought(id)))
}
}
Expand Down