From 7662f21fd54968c89a48d894ca3a49ec01be1f8e Mon Sep 17 00:00:00 2001 From: Shiina Kin Date: Sun, 8 Dec 2024 05:30:13 +0800 Subject: [PATCH] feat: add request validation for login and signup endpoints --- .../io/sakurasou/controller/AuthController.kt | 92 ++++++++++++------- 1 file changed, 59 insertions(+), 33 deletions(-) diff --git a/app/src/main/kotlin/io/sakurasou/controller/AuthController.kt b/app/src/main/kotlin/io/sakurasou/controller/AuthController.kt index 97b0aeb0..5445d597 100644 --- a/app/src/main/kotlin/io/sakurasou/controller/AuthController.kt +++ b/app/src/main/kotlin/io/sakurasou/controller/AuthController.kt @@ -3,6 +3,7 @@ package io.sakurasou.controller import io.github.smiley4.ktorswaggerui.dsl.routing.post import io.github.smiley4.ktorswaggerui.dsl.routing.route import io.ktor.http.* +import io.ktor.server.plugins.requestvalidation.* import io.ktor.server.request.* import io.ktor.server.routing.* import io.sakurasou.controller.request.UserInsertRequest @@ -29,53 +30,78 @@ fun Route.authRoute(authService: AuthService, userService: UserService) { } private fun Route.login(authController: AuthController) { - post("login", { - request { - body { - required = true + route { + install(RequestValidation) { + validate { loginRequest -> + if (loginRequest.username.isBlank()) ValidationResult.Invalid("username is required") + else if (loginRequest.password.isBlank()) ValidationResult.Invalid("password is required") + else if (!loginRequest.password.matches(Regex("^(?=.*[A-Za-z])(?=.*\\d)(?=.*[@\$!%*#?&])[A-Za-z\\d@\$!%*#?&]{8,32}\$"))) + ValidationResult.Invalid("password is invalid") + else ValidationResult.Valid } } - response { - HttpStatusCode.OK to { - body(Schema>>().apply { - title = "CommonResponseLoginResponse" - type = "object" - addProperty("code", Schema().apply { type = "integer" }) - addProperty("message", Schema().apply { type = "string" }) - addProperty("data", Schema>().apply { + post("login", { + request { + body { + required = true + } + } + response { + HttpStatusCode.OK to { + body(Schema>>().apply { + title = "CommonResponseLoginResponse" type = "object" - additionalProperties = Schema().apply { - type = "string" - } + addProperty("code", Schema().apply { type = "integer" }) + addProperty("message", Schema().apply { type = "string" }) + addProperty("data", Schema>().apply { + type = "object" + additionalProperties = Schema().apply { + type = "string" + } + }) + addProperty("isSuccessful", Schema().apply { type = "boolean" }) }) - addProperty("isSuccessful", Schema().apply { type = "boolean" }) - }) + } } + }) { + val loginRequest = call.receive() + val token = authController.handleLogin(loginRequest) + call.success(mapOf("token" to token)) } - }) { - val loginRequest = call.receive() - val token = authController.handleLogin(loginRequest) - call.success(mapOf("token" to token)) } } private fun Route.signup(authController: AuthController) { - post("signup", { - protected = false - request { - body { - required = true + route { + install(RequestValidation) { + validate { userInsertRequest -> + if (userInsertRequest.username.isBlank()) ValidationResult.Invalid("username is required") + else if (userInsertRequest.password.isBlank()) ValidationResult.Invalid("password is required") + else if (userInsertRequest.email.isBlank()) ValidationResult.Invalid("email is required") + else if (!userInsertRequest.password.matches(Regex("^(?=.*[A-Za-z])(?=.*\\d)(?=.*[@\$!%*#?&])[A-Za-z\\d@\$!%*#?&]{8,32}\$"))) + ValidationResult.Invalid("password is invalid") + else if (!userInsertRequest.email.matches(Regex("^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+\$"))) + ValidationResult.Invalid("email is invalid") + else ValidationResult.Valid } } - response { - HttpStatusCode.OK to { - body> { } + post("signup", { + protected = false + request { + body { + required = true + } } + response { + HttpStatusCode.OK to { + body> { } + } + } + }) { + val userInsertRequest = call.receive() + authController.handleSignup(userInsertRequest) + call.success() } - }) { - val userInsertRequest = call.receive() - authController.handleSignup(userInsertRequest) - call.success() } }