移除Dto(難用)

This commit is contained in:
Raymond Yang 2023-05-16 13:48:09 +08:00
parent 8999ab3272
commit bd214f0423
13 changed files with 62 additions and 152 deletions

View File

@ -31,6 +31,7 @@ dependencies {
testImplementation("io.ktor:ktor-server-tests-jvm:$ktor_version") testImplementation("io.ktor:ktor-server-tests-jvm:$ktor_version")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version") testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version")
implementation("org.litote.kmongo:kmongo:$kmongo_version") implementation("org.litote.kmongo:kmongo:$kmongo_version")
implementation("org.litote.kmongo:kmongo-id-serialization:$kmongo_version")
implementation("io.ktor:ktor-server-auth-jvm:$ktor_version") implementation("io.ktor:ktor-server-auth-jvm:$ktor_version")
implementation("io.ktor:ktor-server-auth-jwt-jvm:$ktor_version") implementation("io.ktor:ktor-server-auth-jwt-jvm:$ktor_version")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0")

View File

@ -1,8 +1,9 @@
package com.ray650128 package com.ray650128
import com.ray650128.model.dto.UserDto import com.ray650128.model.pojo.User
import com.ray650128.plugins.configureUserRouting import com.ray650128.plugins.configureUserRouting
import com.ray650128.plugins.configureArMaterialRouting import com.ray650128.plugins.configureArMaterialRouting
import com.ray650128.service.UserService
import io.ktor.serialization.kotlinx.json.* import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.application.* import io.ktor.server.application.*
import io.ktor.server.auth.* import io.ktor.server.auth.*
@ -10,20 +11,25 @@ import io.ktor.server.auth.jwt.*
import io.ktor.server.engine.* import io.ktor.server.engine.*
import io.ktor.server.netty.* import io.ktor.server.netty.*
import io.ktor.server.plugins.contentnegotiation.* import io.ktor.server.plugins.contentnegotiation.*
import kotlinx.serialization.json.Json
import org.litote.kmongo.id.serialization.IdKotlinXSerializationModule
fun main() { fun main() {
embeddedServer(Netty, port = 8080, host = "0.0.0.0") { embeddedServer(Netty, port = 8080, host = "0.0.0.0") {
install(ContentNegotiation) { install(ContentNegotiation) {
json() json(
Json { serializersModule = IdKotlinXSerializationModule }
)
} }
install(Authentication) { install(Authentication) {
jwt { jwt {
verifier(JwtConfig.verifier) verifier(JwtConfig.verifier)
realm = JwtConfig.myRealm realm = JwtConfig.myRealm
validate { validate {
val service = UserService()
val name = it.payload.getClaim("account").asString() val name = it.payload.getClaim("account").asString()
if (name != null) { if (name != null) {
UserDto(account = name, password = "") service.findByAccount(name)
} else { } else {
null null
} }

View File

@ -3,7 +3,7 @@ package com.ray650128
import com.auth0.jwt.JWT import com.auth0.jwt.JWT
import com.auth0.jwt.JWTVerifier import com.auth0.jwt.JWTVerifier
import com.auth0.jwt.algorithms.Algorithm import com.auth0.jwt.algorithms.Algorithm
import com.ray650128.model.dto.UserDto import com.ray650128.model.pojo.User
import java.util.* import java.util.*
object JwtConfig { object JwtConfig {
@ -21,7 +21,7 @@ object JwtConfig {
/** /**
* Produce a token for this combination of name and password * Produce a token for this combination of name and password
*/ */
fun generateToken(user: UserDto): String = JWT.create() fun generateToken(user: User): String = JWT.create()
.withSubject("Authentication") .withSubject("Authentication")
.withIssuer(issuer) .withIssuer(issuer)
.withClaim("account", user.account) .withClaim("account", user.account)

View File

@ -1,28 +0,0 @@
package com.ray650128.extension
import com.ray650128.model.dto.MaterialDto
import com.ray650128.model.dto.UserDto
import com.ray650128.model.pojo.Material
import com.ray650128.model.pojo.User
fun Material.toDto(): MaterialDto =
MaterialDto(
id = this.id.toString(),
ownerId = this.ownerId.toString(),
name = this.name,
path = this.path,
contentType = this.contentType,
fileTag = this.fileTag,
createAt = this.createAt,
updatedAt = this.updatedAt
)
fun MaterialDto.toMaterial(): Material =
Material(
name = this.name,
path = this.path,
contentType = this.contentType,
fileTag = this.fileTag,
createAt = this.createAt,
updatedAt = this.updatedAt
)

View File

@ -1,25 +0,0 @@
package com.ray650128.extension
import com.ray650128.model.dto.UserDto
import com.ray650128.model.pojo.User
fun User.toDto(): UserDto =
UserDto(
id = this.id.toString(),
account = this.account,
password = this.password,
name = this.name,
token = this.token,
createAt = this.createAt,
updatedAt = this.updatedAt
)
fun UserDto.toUser(): User =
User(
account = this.account,
password = this.password,
name = this.name,
token = this.token,
createAt = this.createAt,
updatedAt = this.updatedAt
)

View File

@ -1,16 +0,0 @@
package com.ray650128.model.dto
import io.ktor.server.auth.*
import kotlinx.serialization.Serializable
@Serializable
data class MaterialDto(
val id: String? = null,
var ownerId: String? = null,
var name: String,
val path: String,
val contentType: String,
var fileTag: ArrayList<String>? = null,
var createAt: Long? = null,
var updatedAt: Long? = null
): Principal

View File

@ -1,15 +0,0 @@
package com.ray650128.model.dto
import io.ktor.server.auth.*
import kotlinx.serialization.Serializable
@Serializable
data class UserDto(
val id: String? = null,
val account: String,
val password: String,
val name: String? = null,
var token: String? = null,
var createAt: Long? = null,
var updatedAt: Long? = null
): Principal

View File

@ -1,14 +1,17 @@
package com.ray650128.model.pojo package com.ray650128.model.pojo
import org.bson.codecs.pojo.annotations.BsonId import kotlinx.serialization.Contextual
import kotlinx.serialization.Serializable
import org.litote.kmongo.Id import org.litote.kmongo.Id
import org.litote.kmongo.newId
@Serializable
data class Material( data class Material(
@BsonId var id: Id<Material>? = null, @Contextual var _id: Id<Material> = newId(),
var ownerId: Id<User>? = null, @Contextual var ownerId: Id<User>? = null,
var name: String, var name: String,
var path: String, var path: String? = null,
var contentType: String, var contentType: String? = null,
var fileTag: ArrayList<String>? = null, var fileTag: ArrayList<String>? = null,
var createAt: Long? = null, var createAt: Long? = null,
var updatedAt: Long? = null var updatedAt: Long? = null

View File

@ -1,15 +1,18 @@
package com.ray650128.model.pojo package com.ray650128.model.pojo
import org.bson.codecs.pojo.annotations.BsonId import io.ktor.server.auth.*
import kotlinx.serialization.Contextual
import kotlinx.serialization.Serializable
import org.litote.kmongo.Id import org.litote.kmongo.Id
import org.litote.kmongo.newId
@Serializable
data class User( data class User(
@BsonId @Contextual val _id: Id<User>? = newId(),
val id: Id<User>? = null,
val account: String, val account: String,
val password: String, val password: String,
var name: String? = null, var name: String? = null,
var token: String? = null, var token: String? = null,
var createAt: Long? = null, var createAt: Long? = null,
var updatedAt: Long? = null var updatedAt: Long? = null
) ): Principal

View File

@ -2,10 +2,9 @@ package com.ray650128.plugins
import com.ray650128.extension.* import com.ray650128.extension.*
import com.ray650128.model.ErrorResponse import com.ray650128.model.ErrorResponse
import com.ray650128.model.dto.MaterialDto
import com.ray650128.model.dto.UserDto
import com.ray650128.model.pojo.Material import com.ray650128.model.pojo.Material
import com.ray650128.model.pojo.NewMaterial import com.ray650128.model.pojo.NewMaterial
import com.ray650128.model.pojo.User
import com.ray650128.service.MaterialService import com.ray650128.service.MaterialService
import com.ray650128.service.UserService import com.ray650128.service.UserService
import io.ktor.http.content.* import io.ktor.http.content.*
@ -45,24 +44,16 @@ fun Application.configureArMaterialRouting() {
route("/v1") { route("/v1") {
route("/materials") { route("/materials") {
get { get {
val account = call.authentication.principal<UserDto>()?.account ?: run { val user = call.authentication.principal<User>() ?: run {
call.sendUnauthorized() call.sendUnauthorized()
return@get return@get
} }
val user = userService.findByAccount(account) ?: run { val list = materialService.findByOwnerId(user._id.toString())
call.sendUnauthorized() call.sendSuccess(list)
return@get
}
val list = materialService.findByOwnerId(user.id.toString())
call.sendSuccess(list.map(Material::toDto))
} }
post("/upload") { post("/upload") {
val account = call.authentication.principal<UserDto>()?.account ?: run { val user = call.authentication.principal<User>() ?: run {
call.sendUnauthorized()
return@post
}
val user = userService.findByAccount(account) ?: run {
call.sendUnauthorized() call.sendUnauthorized()
return@post return@post
} }
@ -102,7 +93,8 @@ fun Application.configureArMaterialRouting() {
} }
} }
val tmpMaterial = MaterialDto( val tmpMaterial = Material(
ownerId = user._id!!,
name = if (params == null) { name = if (params == null) {
part.originalFileName!! part.originalFileName!!
} else { } else {
@ -111,9 +103,7 @@ fun Application.configureArMaterialRouting() {
path = "/upload/$name", path = "/upload/$name",
contentType = "${part.contentType}", contentType = "${part.contentType}",
createAt = System.currentTimeMillis() createAt = System.currentTimeMillis()
).toMaterial().apply { )
ownerId = user.id!!
}
materialId = materialService.create(tmpMaterial).toString() materialId = materialService.create(tmpMaterial).toString()
} }
@ -123,7 +113,7 @@ fun Application.configureArMaterialRouting() {
part.dispose() part.dispose()
} }
if (materialId != null) { if (materialId != null) {
val data = materialService.findById(materialId!!)?.toDto() val data = materialService.findById(materialId!!)
call.sendSuccess(data) call.sendSuccess(data)
} else { } else {
call.sendBadRequest(ErrorResponse("Add material fail.")) call.sendBadRequest(ErrorResponse("Add material fail."))
@ -131,11 +121,11 @@ fun Application.configureArMaterialRouting() {
} }
put("/{id}") { put("/{id}") {
call.authentication.principal<UserDto>()?.account ?: run { call.authentication.principal<User>() ?: run {
call.sendUnauthorized() call.sendUnauthorized()
return@put return@put
} }
val body = call.receive<MaterialDto>() val body = call.receive<Material>()
val id = call.parameters["id"].toString() val id = call.parameters["id"].toString()
val material = materialService.findById(id) ?: run { val material = materialService.findById(id) ?: run {
call.sendNotFound() call.sendNotFound()
@ -151,7 +141,7 @@ fun Application.configureArMaterialRouting() {
} }
delete("/{id}") { delete("/{id}") {
call.authentication.principal<UserDto>()?.account ?: run { call.authentication.principal<User>() ?: run {
call.sendUnauthorized() call.sendUnauthorized()
return@delete return@delete
} }

View File

@ -2,7 +2,6 @@ package com.ray650128.plugins
import com.ray650128.JwtConfig import com.ray650128.JwtConfig
import com.ray650128.extension.* import com.ray650128.extension.*
import com.ray650128.model.dto.UserDto
import com.ray650128.model.ErrorResponse import com.ray650128.model.ErrorResponse
import com.ray650128.model.pojo.LoginResult import com.ray650128.model.pojo.LoginResult
import com.ray650128.model.pojo.User import com.ray650128.model.pojo.User
@ -21,13 +20,13 @@ fun Application.configureUserRouting() {
route("/api") { route("/api") {
route("/v1") { route("/v1") {
post("/register") { post("/register") {
val request = call.receive<UserDto>() val request = call.receive<User>()
if (service.findByAccount(request.account) != null) { if (service.findByAccount(request.account) != null) {
call.sendBadRequest(ErrorResponse("User has existed.")) call.sendBadRequest(ErrorResponse("User has existed."))
return@post return@post
} }
val newToken = JwtConfig.generateToken(request) val newToken = JwtConfig.generateToken(request)
val user = request.toUser().apply { val user = request.apply {
token = newToken token = newToken
createAt = System.currentTimeMillis() createAt = System.currentTimeMillis()
} }
@ -38,7 +37,7 @@ fun Application.configureUserRouting() {
} }
post("/login") { post("/login") {
val request = call.receive<UserDto>() val request = call.receive<User>()
val user = service.findByLoginInfo(request.account, request.password) val user = service.findByLoginInfo(request.account, request.password)
if (user != null) { if (user != null) {
var token = user.token var token = user.token
@ -46,7 +45,7 @@ fun Application.configureUserRouting() {
token = JwtConfig.generateToken(request) token = JwtConfig.generateToken(request)
user.token = token user.token = token
user.updatedAt = System.currentTimeMillis() user.updatedAt = System.currentTimeMillis()
service.updateById(user.id.toString(), user) service.updateById(user._id.toString(), user)
} }
call.sendSuccess(LoginResult(request.account, token!!)) call.sendSuccess(LoginResult(request.account, token!!))
} else { } else {
@ -56,7 +55,7 @@ fun Application.configureUserRouting() {
authenticate { authenticate {
post("/logout") { post("/logout") {
val account = call.authentication.principal<UserDto>()?.account ?: run { val account = call.authentication.principal<User>()?.account ?: run {
call.sendUnauthorized() call.sendUnauthorized()
return@post return@post
} }
@ -68,35 +67,34 @@ fun Application.configureUserRouting() {
token = null token = null
updatedAt = System.currentTimeMillis() updatedAt = System.currentTimeMillis()
} }
service.updateById(user.id.toString(), user) service.updateById(user._id.toString(), user)
call.sendSuccess(null) call.sendSuccess(null)
} }
} }
} }
get { get {
val peopleList = service.findAll().map(User::toDto) val peopleList = service.findAll()
call.respond(peopleList) call.respond(peopleList)
} }
get("/{id}") { get("/{id}") {
val id = call.parameters["id"].toString() val id = call.parameters["id"].toString()
service.findById(id) service.findById(id)
?.let { foundPerson -> call.respond(foundPerson.toDto()) } ?.let { foundPerson -> call.respond(foundPerson) }
?: call.sendNotFound() ?: call.sendNotFound()
} }
get("/search") { get("/search") {
val name = call.request.queryParameters["name"].toString() val name = call.request.queryParameters["name"].toString()
val foundPeople = service.findByName(name).map(User::toDto) val foundPeople = service.findByName(name)
call.respond(foundPeople) call.respond(foundPeople)
} }
put("/{id}") { put("/{id}") {
val id = call.parameters["id"].toString() val id = call.parameters["id"].toString()
val userRequest = call.receive<UserDto>() val userRequest = call.receive<User>()
val user = userRequest.toUser() val updatedSuccessfully = service.updateById(id, userRequest)
val updatedSuccessfully = service.updateById(id, user)
if (updatedSuccessfully) { if (updatedSuccessfully) {
call.respond(HttpStatusCode.NoContent) call.respond(HttpStatusCode.NoContent)
} else { } else {

View File

@ -9,34 +9,27 @@ import org.litote.kmongo.id.toId
class MaterialService { class MaterialService {
private val client = KMongo.createClient("mongodb://www.ray650128.com:27017") private val client = KMongo.createClient("mongodb://www.ray650128.com:27017")
private val database = client.getDatabase("ar_system") private val database = client.getDatabase("ar_system")
private val userCollection = database.getCollection<Material>() private val materialCollection = database.getCollection<Material>()
fun create(user: Material): Id<Material>? { fun create(material: Material): Id<Material> {
userCollection.insertOne(user) materialCollection.insertOne(material)
return user.id return material._id
} }
fun findAll(): List<Material> = userCollection.find().toList()
fun findById(id: String): Material? { fun findById(id: String): Material? {
val bsonId: Id<Material> = ObjectId(id).toId() val bsonId: Id<Material> = ObjectId(id).toId()
return userCollection.findOne(Material::id eq bsonId) return materialCollection.findOne(Material::_id eq bsonId)
} }
fun findByOwnerId(ownerId: String): List<Material> { fun findByOwnerId(ownerId: String): List<Material> {
val bsonId: Id<User> = ObjectId(ownerId).toId() val bsonId: Id<User> = ObjectId(ownerId).toId()
return userCollection.find(Material::ownerId eq bsonId).toList() return materialCollection.find(Material::ownerId eq bsonId).toList()
}
fun findByName(name: String): List<Material> {
val caseSensitiveTypeSafeFilter = Material::name regex name
return userCollection.find(caseSensitiveTypeSafeFilter).toList()
} }
fun updateById(id: String, request: Material): Boolean = fun updateById(id: String, request: Material): Boolean =
findById(id)?.let { user -> findById(id)?.let { material ->
val updateResult = userCollection.replaceOne( val updateResult = materialCollection.replaceOne(
user.copy( material.copy(
name = request.name, name = request.name,
updatedAt = request.updatedAt updatedAt = request.updatedAt
) )
@ -45,7 +38,7 @@ class MaterialService {
} ?: false } ?: false
fun deleteById(id: String): Boolean { fun deleteById(id: String): Boolean {
val deleteResult = userCollection.deleteOneById(ObjectId(id)) val deleteResult = materialCollection.deleteOneById(ObjectId(id))
return deleteResult.deletedCount == 1L return deleteResult.deletedCount == 1L
} }
} }

View File

@ -12,14 +12,14 @@ class UserService {
fun create(user: User): Id<User>? { fun create(user: User): Id<User>? {
userCollection.insertOne(user) userCollection.insertOne(user)
return user.id return user._id
} }
fun findAll(): List<User> = userCollection.find().toList() fun findAll(): List<User> = userCollection.find().toList()
fun findById(id: String): User? { fun findById(id: String): User? {
val bsonId: Id<User> = ObjectId(id).toId() val bsonId: Id<User> = ObjectId(id).toId()
return userCollection.findOne(User::id eq bsonId) return userCollection.findOne(User::_id eq bsonId)
} }
fun findByName(name: String): List<User> { fun findByName(name: String): List<User> {