/
Handlers.kt
87 lines (79 loc) · 4.26 KB
/
Handlers.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package reactive
import arrow.core.*
import org.springframework.http.MediaType
import org.springframework.web.reactive.function.server.ServerRequest
import org.springframework.web.reactive.function.server.ServerResponse
import org.springframework.web.reactive.function.server.ServerResponse.badRequest
import org.springframework.web.reactive.function.server.ServerResponse.ok
import org.springframework.web.reactive.function.server.body
import org.springframework.web.reactive.function.server.bodyToMono
import reactor.core.publisher.Mono
import top.User
import top.ValidationError
import top.rules.validateEmailWithRules
import top.typeclass.errorAccumulation
import top.typeclass.failFast
class Handlers(
private val userRepository: UserRepository,
private val cityRepository: CityRepository
) {
fun listApi(request: ServerRequest) =
ok().contentType(MediaType.APPLICATION_JSON).body(userRepository.findAll())
fun upsert(request: ServerRequest): Mono<ServerResponse> = // 👎🏼 This is struck with using FailFast strategy
request.bodyToMono<User>()
.flatMap { user ->
val isEmailValid: Either<ValidationError, Unit> = validateEmailFailFast(user.email)
isEmailValid.fold(
{ badRequest().bodyValue("$user email validation errors: $it") },
{
cityRepository.doesCityExistsWith(user.city)
.flatMap { cityExists ->
if (cityExists) {
userRepository.doesUserExistsWith(user.login)
.flatMap { userExists ->
if (userExists) {
userRepository.update(user)
ok().bodyValue("Updated!! $user")
} else {
userRepository.insert(user)
ok().bodyValue("Inserted!! $user")
}
}
} else {
badRequest().bodyValue("City is invalid!! : $user")
}
}
}
)
}
companion object Utils {
private fun validateEmailFailFast(email: String): Either<ValidationError, Unit> =
if (email.contains("@", false)) {
if (email.length <= 250) {
Unit.right()
} else {
ValidationError.EmailMaxLength(250).left()
}
} else {
ValidationError.DoesNotContain("@").left()
}
private fun validateEmailFailFastX(email: String): Either<NonEmptyList<ValidationError>, Tuple2<String, String>> =
failFast<ValidationError>().run {
validateEmailWithRules(email).fix()
}
private fun validateEmailErrorAccumulation(email: String): Either<MutableList<ValidationError>, Unit> {
val errorList = mutableListOf<ValidationError>()
if (!email.contains("@", false)) {
errorList.add(ValidationError.DoesNotContain("@"))
}
if (email.length > 250) {
errorList.add(ValidationError.EmailMaxLength(250))
}
return if (errorList.isNotEmpty()) errorList.left() else Unit.right()
}
private fun validateEmailErrorAccumulationX(email: String): Validated<NonEmptyList<ValidationError>, Tuple2<String, String>> =
errorAccumulation<ValidationError>().run {
validateEmailWithRules(email).fix()
}
}
}