實作新增、查詢、刪除角色
This commit is contained in:
parent
d537ec1f76
commit
7e7c8b0698
@ -11,12 +11,13 @@ object JwtConfig {
|
||||
val jwtDomain = "com.ray650128"
|
||||
val jwtRealm = "pc re:dive rank table"
|
||||
val jwtSecret = "secret"
|
||||
//private val validityInMs = 36_000_00 * 24 // 1 day
|
||||
private const val validityInMs = 300000 // 5 min
|
||||
private val validityInMs = 36_000_00 * 24 // 1 day
|
||||
//private const val validityInMs = 300000 // 5 min
|
||||
private val algorithm = Algorithm.HMAC512(jwtSecret)
|
||||
|
||||
val verifier: JWTVerifier = JWT
|
||||
.require(algorithm)
|
||||
.withAudience(jwtAudience)
|
||||
.withIssuer(jwtDomain)
|
||||
.build()
|
||||
|
||||
@ -24,9 +25,10 @@ object JwtConfig {
|
||||
* Produce a token for this combination of name and password
|
||||
*/
|
||||
fun generateToken(user: User): String = JWT.create()
|
||||
.withSubject("Authentication")
|
||||
.withAudience(jwtAudience)
|
||||
.withIssuer(jwtDomain)
|
||||
.withClaim("account", user.account)
|
||||
.withClaim("password", user.password)
|
||||
.withExpiresAt(getExpiration()) // optional
|
||||
.sign(algorithm)
|
||||
|
||||
|
||||
36
src/main/kotlin/com/ray650128/model/dto/GameCharacterDto.kt
Normal file
36
src/main/kotlin/com/ray650128/model/dto/GameCharacterDto.kt
Normal file
@ -0,0 +1,36 @@
|
||||
package com.ray650128.model.dto
|
||||
|
||||
import com.ray650128.model.pojo.GameCharacter
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class CharacterDto(
|
||||
val _id: String? = null,
|
||||
val name: String,
|
||||
val imgSrc: String,
|
||||
val position: Int,
|
||||
val standIndex: Int,
|
||||
var createAt: Long? = null,
|
||||
var updatedAt: Long? = null
|
||||
)
|
||||
|
||||
fun GameCharacter.toDto(baseUrl: String? = null): CharacterDto =
|
||||
CharacterDto(
|
||||
_id = this._id.toString(),
|
||||
name = this.name,
|
||||
imgSrc = if (baseUrl.isNullOrEmpty()) this.imgSrc else "$baseUrl${this.imgSrc}",
|
||||
position = this.position,
|
||||
standIndex = this.standIndex,
|
||||
createAt = this.createAt,
|
||||
updatedAt = this.updatedAt
|
||||
)
|
||||
|
||||
fun CharacterDto.toGameCharacter(): GameCharacter =
|
||||
GameCharacter(
|
||||
name = this.name,
|
||||
imgSrc = this.imgSrc,
|
||||
position = this.position,
|
||||
standIndex = this.standIndex,
|
||||
createAt = this.createAt,
|
||||
updatedAt = this.updatedAt
|
||||
)
|
||||
17
src/main/kotlin/com/ray650128/model/pojo/GameCharacter.kt
Normal file
17
src/main/kotlin/com/ray650128/model/pojo/GameCharacter.kt
Normal file
@ -0,0 +1,17 @@
|
||||
package com.ray650128.model.pojo
|
||||
|
||||
import kotlinx.serialization.Contextual
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.litote.kmongo.Id
|
||||
import org.litote.kmongo.newId
|
||||
|
||||
@Serializable
|
||||
data class GameCharacter(
|
||||
@Contextual val _id: Id<GameCharacter>? = newId(),
|
||||
val name: String,
|
||||
val imgSrc: String,
|
||||
val position: Int,
|
||||
val standIndex: Int,
|
||||
var createAt: Long? = null,
|
||||
var updatedAt: Long? = null
|
||||
)
|
||||
10
src/main/kotlin/com/ray650128/model/pojo/NewCharacter.kt
Normal file
10
src/main/kotlin/com/ray650128/model/pojo/NewCharacter.kt
Normal file
@ -0,0 +1,10 @@
|
||||
package com.ray650128.model.pojo
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class NewCharacter(
|
||||
val name: String,
|
||||
val position: Int,
|
||||
val standIndex: Int
|
||||
)
|
||||
@ -1,28 +1,101 @@
|
||||
package com.ray650128.plugins
|
||||
|
||||
import io.ktor.serialization.gson.*
|
||||
import io.ktor.server.plugins.contentnegotiation.*
|
||||
import com.google.gson.Gson
|
||||
import com.ray650128.extensions.sendBadRequest
|
||||
import com.ray650128.extensions.sendNotFound
|
||||
import com.ray650128.extensions.sendSuccess
|
||||
import com.ray650128.extensions.sendUnauthorized
|
||||
import com.ray650128.model.ErrorResponse
|
||||
import com.ray650128.model.User
|
||||
import com.ray650128.model.dto.toDto
|
||||
import com.ray650128.model.pojo.GameCharacter
|
||||
import com.ray650128.model.pojo.NewCharacter
|
||||
import com.ray650128.service.CharacterService
|
||||
import io.ktor.http.content.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.auth.*
|
||||
import io.ktor.server.request.*
|
||||
import io.ktor.server.routing.*
|
||||
import io.ktor.server.util.*
|
||||
import java.io.File
|
||||
|
||||
fun Application.configureCharacter() {
|
||||
routing {
|
||||
route("/api") {
|
||||
route("/v1") {
|
||||
get("/characters") {
|
||||
call.respond(mapOf("hello" to "world"))
|
||||
val gameCharacterList = CharacterService.findAll().map(GameCharacter::toDto)
|
||||
call.sendSuccess(gameCharacterList)
|
||||
}
|
||||
|
||||
route("/character") {
|
||||
get("/{id}") {
|
||||
call.respond(mapOf("hello" to "world"))
|
||||
val id = call.parameters["id"].toString()
|
||||
val character = CharacterService.findById(id)?.toDto() ?: run {
|
||||
call.sendNotFound()
|
||||
return@get
|
||||
}
|
||||
call.sendSuccess(character)
|
||||
}
|
||||
|
||||
authenticate {
|
||||
post {
|
||||
call.authentication.principal<User>() ?: run {
|
||||
call.sendUnauthorized()
|
||||
return@post
|
||||
}
|
||||
var characterId: String? = null
|
||||
// retrieve all multipart data (suspending)
|
||||
val multipart = call.receiveMultipart()
|
||||
var params: NewCharacter? = null
|
||||
multipart.forEachPart { part ->
|
||||
// Check part type
|
||||
when (part) {
|
||||
is PartData.FormItem -> {
|
||||
params = Gson().fromJson(part.value, NewCharacter::class.java)
|
||||
println(part.value)
|
||||
}
|
||||
|
||||
is PartData.FileItem -> {
|
||||
val extensionName = part.contentType?.contentSubtype
|
||||
val name = "${System.currentTimeMillis()}.$extensionName"
|
||||
val directory = File("./upload/")
|
||||
if (!directory.exists()) {
|
||||
directory.mkdir()
|
||||
}
|
||||
val file = File("${directory.path}/$name")
|
||||
|
||||
// use InputStream from part to save file
|
||||
part.streamProvider().use { its ->
|
||||
// copy the stream to the file with buffering
|
||||
file.outputStream().buffered().use {
|
||||
// note that this is blocking
|
||||
its.copyTo(it)
|
||||
}
|
||||
}
|
||||
|
||||
val tmpCharacter = GameCharacter(
|
||||
name = params!!.name,
|
||||
imgSrc = "/upload/$name",
|
||||
position = params!!.position,
|
||||
standIndex = params!!.standIndex,
|
||||
createAt = System.currentTimeMillis()
|
||||
)
|
||||
characterId = CharacterService.create(tmpCharacter).toString()
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
// make sure to dispose of the part after use to prevent leaks
|
||||
part.dispose()
|
||||
}
|
||||
if (characterId != null) {
|
||||
val data = CharacterService.findById(characterId!!)?.toDto()
|
||||
call.sendSuccess(data)
|
||||
} else {
|
||||
call.sendBadRequest(ErrorResponse("Add material fail."))
|
||||
}
|
||||
}
|
||||
|
||||
put {
|
||||
@ -30,7 +103,14 @@ fun Application.configureCharacter() {
|
||||
}
|
||||
|
||||
delete("/{id}") {
|
||||
|
||||
call.authentication.principal<User>() ?: run {
|
||||
call.sendUnauthorized()
|
||||
return@delete
|
||||
}
|
||||
val id = call.parameters["id"].toString()
|
||||
CharacterService.deleteById(id)
|
||||
val gameCharacterList = CharacterService.findAll().map(GameCharacter::toDto)
|
||||
call.sendSuccess(gameCharacterList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ package com.ray650128.plugins
|
||||
import io.ktor.server.auth.*
|
||||
import io.ktor.server.auth.jwt.*
|
||||
import com.ray650128.JwtConfig
|
||||
import com.ray650128.model.User
|
||||
import io.ktor.http.*
|
||||
import io.ktor.serialization.gson.*
|
||||
import io.ktor.server.application.*
|
||||
@ -16,8 +17,10 @@ fun Application.configureModules() {
|
||||
realm = JwtConfig.jwtRealm
|
||||
verifier(JwtConfig.verifier)
|
||||
validate { credential ->
|
||||
if (credential.payload.audience.contains(JwtConfig.jwtAudience)) {
|
||||
JWTPrincipal(credential.payload)
|
||||
val account = credential.payload.getClaim("account").asString()
|
||||
val password = credential.payload.getClaim("password").asString()
|
||||
if (account != "" && password != "") {
|
||||
User(account = account, password = password)
|
||||
} else null
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,8 +43,8 @@ fun Application.configureUser() {
|
||||
val password = md5encode(request.password)
|
||||
val user = UserService.findByLoginInfo(request.account, password)
|
||||
if (user != null) {
|
||||
val token = JwtConfig.generateToken(request)
|
||||
call.sendSuccess(LoginResult(request.account, token))
|
||||
val token = JwtConfig.generateToken(user)
|
||||
call.sendSuccess(LoginResult(user.account, token))
|
||||
} else {
|
||||
call.sendUnauthorized()
|
||||
}
|
||||
|
||||
45
src/main/kotlin/com/ray650128/service/CharacterService.kt
Normal file
45
src/main/kotlin/com/ray650128/service/CharacterService.kt
Normal file
@ -0,0 +1,45 @@
|
||||
package com.ray650128.service
|
||||
|
||||
import com.ray650128.model.pojo.GameCharacter
|
||||
import org.bson.types.ObjectId
|
||||
import org.litote.kmongo.*
|
||||
import org.litote.kmongo.id.toId
|
||||
|
||||
object CharacterService {
|
||||
private val client = KMongo.createClient("mongodb://ray650128:Zx650128!@www.ray650128.com:27017")
|
||||
private val database = client.getDatabase("test_system")
|
||||
private val characterCollection = database.getCollection<GameCharacter>()
|
||||
|
||||
fun create(character: GameCharacter): Id<GameCharacter>? {
|
||||
characterCollection.insertOne(character)
|
||||
return character._id
|
||||
}
|
||||
|
||||
fun findAll(): List<GameCharacter> = characterCollection.find().toList()
|
||||
|
||||
fun findById(id: String): GameCharacter? {
|
||||
val bsonId: Id<GameCharacter> = ObjectId(id).toId()
|
||||
return characterCollection.findOne(GameCharacter::_id eq bsonId)
|
||||
}
|
||||
|
||||
fun findByName(name: String): List<GameCharacter> {
|
||||
val caseSensitiveTypeSafeFilter = GameCharacter::name regex name
|
||||
return characterCollection.find(caseSensitiveTypeSafeFilter).toList()
|
||||
}
|
||||
|
||||
fun updateById(id: String, request: GameCharacter): Boolean =
|
||||
findById(id)?.let { character ->
|
||||
val updateResult = characterCollection.replaceOne(
|
||||
character.copy(
|
||||
name = request.name,
|
||||
updatedAt = request.updatedAt
|
||||
)
|
||||
)
|
||||
updateResult.modifiedCount == 1L
|
||||
} ?: false
|
||||
|
||||
fun deleteById(id: String): Boolean {
|
||||
val deleteResult = characterCollection.deleteOneById(ObjectId(id))
|
||||
return deleteResult.deletedCount == 1L
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user