init commit
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
package com.ray650128
|
||||
|
||||
import com.ray650128.database.DatabaseFactory
|
||||
import io.ktor.server.application.*
|
||||
import com.ray650128.plugins.*
|
||||
|
||||
fun main(args: Array<String>): Unit =
|
||||
io.ktor.server.netty.EngineMain.main(args)
|
||||
|
||||
@Suppress("unused") // application.conf references the main function. This annotation prevents the IDE from marking it as unused.
|
||||
fun Application.module() {
|
||||
DatabaseFactory.init()
|
||||
DatabaseFactory.createTable()
|
||||
configureRouting()
|
||||
configureSerialization()
|
||||
configureSecurity()
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.ray650128.database
|
||||
|
||||
import com.ray650128.entity.Users
|
||||
import com.zaxxer.hikari.HikariConfig
|
||||
import com.zaxxer.hikari.HikariDataSource
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
import org.jetbrains.exposed.sql.SchemaUtils
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
|
||||
object DatabaseFactory {
|
||||
fun init() {
|
||||
Database.connect(hikari())
|
||||
}
|
||||
|
||||
fun createTable(){
|
||||
transaction {
|
||||
SchemaUtils.create(Users)
|
||||
}
|
||||
}
|
||||
|
||||
private fun hikari(): HikariDataSource {
|
||||
val config = HikariConfig()
|
||||
config.driverClassName = "com.mysql.cj.jdbc.Driver"
|
||||
config.jdbcUrl = "jdbc:mysql://www.ray650128.com:3306/test_db"
|
||||
config.username = "root"
|
||||
config.password = "650128"
|
||||
config.validate()
|
||||
return HikariDataSource(config)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.ray650128.entity
|
||||
|
||||
import org.jetbrains.exposed.dao.id.LongIdTable
|
||||
import org.jetbrains.exposed.sql.Table.Dual.default
|
||||
import org.jetbrains.exposed.sql.Table.Dual.long
|
||||
import org.jetbrains.exposed.sql.Table.Dual.uniqueIndex
|
||||
import org.jetbrains.exposed.sql.Table.Dual.varchar
|
||||
|
||||
object Users : LongIdTable() {
|
||||
var name = varchar("name", 50)
|
||||
var account = varchar("account", 255).uniqueIndex()
|
||||
var password = varchar("password", 255)
|
||||
var token = varchar("token", 255).default("")
|
||||
var createTime = long("createTime")
|
||||
var updateTime = long("updateTime")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.ray650128.model
|
||||
|
||||
data class User(
|
||||
var id: Long,
|
||||
var name: String,
|
||||
var account: String,
|
||||
var password: String,
|
||||
var token: String,
|
||||
var createTime: Long,
|
||||
var updateTime: Long
|
||||
)
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.ray650128.plugins
|
||||
|
||||
import io.ktor.server.routing.*
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.request.*
|
||||
|
||||
fun Application.configureRouting() {
|
||||
|
||||
routing {
|
||||
get("/") {
|
||||
call.respondText("Hello World!")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.ray650128.plugins
|
||||
|
||||
import io.ktor.server.auth.*
|
||||
import io.ktor.util.*
|
||||
import io.ktor.server.auth.jwt.*
|
||||
import com.auth0.jwt.JWT
|
||||
import com.auth0.jwt.JWTVerifier
|
||||
import com.auth0.jwt.algorithms.Algorithm
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.request.*
|
||||
|
||||
fun Application.configureSecurity() {
|
||||
|
||||
authentication {
|
||||
jwt {
|
||||
val jwtAudience = this@configureSecurity.environment.config.property("jwt.audience").getString()
|
||||
realm = this@configureSecurity.environment.config.property("jwt.realm").getString()
|
||||
verifier(
|
||||
JWT
|
||||
.require(Algorithm.HMAC256("secret"))
|
||||
.withAudience(jwtAudience)
|
||||
.withIssuer(this@configureSecurity.environment.config.property("jwt.domain").getString())
|
||||
.build()
|
||||
)
|
||||
validate { credential ->
|
||||
if (credential.payload.audience.contains(jwtAudience)) JWTPrincipal(credential.payload) else null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.ray650128.plugins
|
||||
|
||||
import io.ktor.serialization.gson.*
|
||||
import io.ktor.server.plugins.contentnegotiation.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.request.*
|
||||
import io.ktor.server.routing.*
|
||||
|
||||
fun Application.configureSerialization() {
|
||||
install(ContentNegotiation) {
|
||||
gson {
|
||||
}
|
||||
}
|
||||
|
||||
routing {
|
||||
get("/json/gson") {
|
||||
call.respond(mapOf("hello" to "world"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.ray650128.repository
|
||||
|
||||
import com.ray650128.entity.Users
|
||||
import com.ray650128.model.User
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jetbrains.exposed.sql.*
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
|
||||
class UserRepository {
|
||||
suspend fun add(data: User) {
|
||||
transaction {
|
||||
Users.insert {
|
||||
it[account] = data.account
|
||||
it[password] = data.password
|
||||
it[createTime] = System.currentTimeMillis()
|
||||
it[updateTime] = System.currentTimeMillis()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun update(data: User) {
|
||||
transaction {
|
||||
Users.update {
|
||||
it[name] = data.name
|
||||
it[token] = data.token
|
||||
it[updateTime] = System.currentTimeMillis()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun get(): List<User> {
|
||||
val data = withContext(Dispatchers.IO) {
|
||||
transaction {
|
||||
Users.selectAll().orderBy(Users.id, SortOrder.DESC).mapNotNull {
|
||||
toUser(it)
|
||||
}.toList()
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
private fun toUser(row: ResultRow): User =
|
||||
User(
|
||||
id = row[Users.id].value,
|
||||
name = row[Users.name],
|
||||
account = row[Users.account],
|
||||
password = row[Users.password],
|
||||
token = row[Users.token],
|
||||
createTime = row[Users.createTime],
|
||||
updateTime = row[Users.updateTime]
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
ktor {
|
||||
deployment {
|
||||
port = 8080
|
||||
port = ${?PORT}
|
||||
}
|
||||
application {
|
||||
modules = [ com.ray650128.ApplicationKt.module ]
|
||||
}
|
||||
}
|
||||
jwt {
|
||||
domain = "https://jwt-provider-domain/"
|
||||
audience = "jwt-audience"
|
||||
realm = "ktor sample app"
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
<root level="trace">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</root>
|
||||
<logger name="org.eclipse.jetty" level="INFO"/>
|
||||
<logger name="io.netty" level="INFO"/>
|
||||
</configuration>
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.ray650128
|
||||
|
||||
import io.ktor.server.routing.*
|
||||
import io.ktor.http.*
|
||||
import io.ktor.serialization.gson.*
|
||||
import io.ktor.server.plugins.contentnegotiation.*
|
||||
import io.ktor.server.auth.*
|
||||
import io.ktor.util.*
|
||||
import io.ktor.server.auth.jwt.*
|
||||
import com.auth0.jwt.JWT
|
||||
import com.auth0.jwt.JWTVerifier
|
||||
import com.auth0.jwt.algorithms.Algorithm
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.request.*
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.client.statement.*
|
||||
import kotlin.test.*
|
||||
import io.ktor.server.testing.*
|
||||
import com.ray650128.plugins.*
|
||||
|
||||
class ApplicationTest {
|
||||
@Test
|
||||
fun testRoot() = testApplication {
|
||||
application {
|
||||
configureRouting()
|
||||
}
|
||||
client.get("/").apply {
|
||||
assertEquals(HttpStatusCode.OK, status)
|
||||
assertEquals("Hello World!", bodyAsText())
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user