Skip to content

Commit b25aa8c

Browse files
author
=
committed
feat: dtos and utils
1 parent ec13609 commit b25aa8c

File tree

7 files changed

+119
-9
lines changed

7 files changed

+119
-9
lines changed

build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,6 @@ dependencies {
4343
implementation("org.postgresql:postgresql:$postgresql_version")
4444
implementation("org.jetbrains.kotlinx:kotlinx-datetime:$kotlinx_datetime_version")
4545
implementation("org.jetbrains.exposed:exposed-java-time:$exposed_version")
46+
implementation("io.ktor:ktor-server-request-validation:$ktor_version")
47+
implementation("io.ktor:ktor-server-status-pages:$ktor_version")
4648
}

settings.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
rootProject.name = "food-api"
1+
rootProject.name = "food-delivery-backend"

src/main/kotlin/com/example/Application.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.example
22

3-
import com.example.plugins.*
3+
import com.example.plugin.*
44
import io.ktor.server.application.*
55
import io.ktor.server.engine.*
66
import io.ktor.server.netty.*
@@ -18,5 +18,6 @@ fun Application.module() {
1818
configureDatabase()
1919
configureSerialization()
2020
configureRouting()
21-
configureUserRouting()
21+
configureValidation()
22+
configureStatusPages()
2223
}

src/main/kotlin/com/example/dto/UserDto.kt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@ enum class FoodType {
99
@Serializable
1010
data class UserDto(
1111
val id: Int,
12+
val userId: String,
1213
val fullName: String,
1314
val email: String,
1415
val password: String,
15-
val phoneNumber: String,
16-
val occupation: String,
17-
val employer: String,
18-
val country: String,
19-
val latitude: Double,
20-
val longitude: Double,
16+
val phoneNumber: String? = null,
17+
val occupation: String? = null,
18+
val employer: String? = null,
19+
val country: String? = null,
20+
val latitude: Double? = null,
21+
val longitude: Double? = null
2122
)
2223

2324
@Serializable
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.example.route
2+
3+
import com.example.dto.UserLoginDto
4+
import com.example.dto.UserRegisterDto
5+
import com.example.service.impl.userService
6+
import io.ktor.http.*
7+
import io.ktor.server.application.*
8+
import io.ktor.server.request.*
9+
import io.ktor.server.response.*
10+
import io.ktor.server.routing.*
11+
import java.util.UUID
12+
13+
fun Application.userRoute() {
14+
routing {
15+
post("/register") {
16+
val userRegisterDto = call.receive<UserRegisterDto>()
17+
userService.register(userRegisterDto).fold(
18+
onSuccess = { call.respond(HttpStatusCode.Created) },
19+
onFailure = { throwable ->
20+
call.respond(
21+
status = HttpStatusCode.BadRequest,
22+
message = throwable.message ?: "Something went wrong"
23+
)
24+
}
25+
)
26+
}
27+
28+
post("/login") {
29+
val userLoginDto: UserLoginDto = call.receive()
30+
userService.login(userLoginDto).fold(
31+
onSuccess = { userId -> call.respond(message = userId) },
32+
onFailure = { throwable ->
33+
call.respond(
34+
status = HttpStatusCode.Unauthorized,
35+
message = throwable.message ?: "Something went wrong"
36+
)
37+
}
38+
)
39+
}
40+
41+
get("/profile/{userId}") {
42+
val userId = call.parameters["userId"]?.let { UUID.fromString(it) }
43+
if (userId == null) {
44+
call.respond(
45+
status = HttpStatusCode.BadRequest,
46+
message = "Invalid user id"
47+
)
48+
return@get
49+
}
50+
userService.getProfile(userId).fold(
51+
onSuccess = { userDto -> call.respond(userDto) },
52+
onFailure = { throwable ->
53+
call.respond(
54+
status = HttpStatusCode.NotFound,
55+
message = throwable.message ?: "Something went wrong"
56+
)
57+
}
58+
)
59+
}
60+
}
61+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.example.util.ext
2+
3+
4+
private const val MinPassPattern = 8
5+
private const val PassPattern = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=\\S+$).{4,}$"
6+
private const val EmailPattern = "^[A-Za-z0-9+_.-]+@(.+)\$"
7+
8+
fun String.isValidEmail(): Boolean = matches(EmailPattern.toRegex())
9+
fun String.isValidPassword(): Boolean = length >= MinPassPattern && matches(PassPattern.toRegex())
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.example.validation
2+
3+
import com.example.dto.UserLoginDto
4+
import com.example.dto.UserRegisterDto
5+
import com.example.util.ext.isValidEmail
6+
import com.example.util.ext.isValidPassword
7+
import io.ktor.server.plugins.requestvalidation.*
8+
9+
private fun validationError(message: String) = ValidationResult.Invalid(message)
10+
11+
fun RequestValidationConfig.userValidation() {
12+
validate<UserRegisterDto> { user ->
13+
with(user) {
14+
when {
15+
fullName.isBlank() -> validationError("Full name cannot be empty")
16+
email.isBlank() -> validationError("Email cannot be empty")
17+
!email.isValidEmail() -> validationError("Invalid email")
18+
password.isBlank() -> validationError("Password cannot be empty")
19+
!password.isValidPassword() -> validationError("Invalid password")
20+
else -> ValidationResult.Valid
21+
}
22+
}
23+
}
24+
25+
validate<UserLoginDto> { user ->
26+
with(user) {
27+
when {
28+
email.isBlank() -> validationError("Email cannot be empty")
29+
!email.isValidEmail() -> validationError("Invalid email")
30+
password.isBlank() -> validationError("Password cannot be empty")
31+
!password.isValidPassword() -> validationError("Invalid password")
32+
else -> ValidationResult.Valid
33+
}
34+
}
35+
}
36+
}

0 commit comments

Comments
 (0)