LoginUseCase.kt
package com.example.realworldkotlinspringbootjdbc.usecase.user_and_authentication
import arrow.core.Either
import arrow.core.Either.Left
import arrow.core.Either.Right
import arrow.core.Validated.Invalid
import arrow.core.Validated.Valid
import arrow.core.left
import arrow.core.right
import arrow.core.zip
import arrow.typeclasses.Semigroup
import com.example.realworldkotlinspringbootjdbc.domain.RegisteredUser
import com.example.realworldkotlinspringbootjdbc.domain.UserRepository
import com.example.realworldkotlinspringbootjdbc.domain.user.Email
import com.example.realworldkotlinspringbootjdbc.domain.user.Password
import com.example.realworldkotlinspringbootjdbc.util.MyError
import org.springframework.stereotype.Service
interface LoginUseCase {
fun execute(email: String?, password: String?): Either<Error, RegisteredUser> = throw NotImplementedError()
sealed interface Error : MyError {
data class InvalidEmailOrPassword(override val errors: List<MyError.ValidationError>) :
Error,
MyError.ValidationErrors
data class Unauthorized(val email: Email) : Error, MyError.Basic
}
}
@Service
class LoginUseCaseImpl(
val userRepository: UserRepository
) : LoginUseCase {
override fun execute(email: String?, password: String?): Either<LoginUseCase.Error, RegisteredUser> {
val validatedInput = Email.new(email).zip(
Semigroup.nonEmptyList(),
Password.newForLogin(password)
) { a, b -> Pair(a, b) }
return when (validatedInput) {
is Invalid -> LoginUseCase.Error.InvalidEmailOrPassword(validatedInput.value).left()
/**
* Email, Password両方ともバリデーションはOK -> User 検索
*/
is Valid -> when (
val registeredUserWithPassword =
userRepository.findByEmailWithPassword(validatedInput.value.first)
) {
/**
* 何かしらのエラー
*/
is Left -> when (val error = registeredUserWithPassword.value) {
is UserRepository.FindByEmailWithPasswordError.NotFound -> LoginUseCase.Error.Unauthorized(error.email)
.left()
}
/**
* Found user by email
*/
is Right -> {
val aPassword = validatedInput.value.second
val (registeredUser, bPassword) = registeredUserWithPassword.value
/**
* 認証 成功/失敗
*/
if (aPassword == bPassword) {
registeredUser.right()
} else {
LoginUseCase.Error.Unauthorized(
validatedInput.value.first
).left()
}
}
}
}
}
}