Accounts can now be deleted

This commit is contained in:
2020-08-14 15:17:58 +02:00
parent 00dafe1da9
commit 662d6c706b
16 changed files with 204 additions and 29 deletions
+8 -5
View File
@@ -6,18 +6,21 @@ import be.simplenotes.domain.security.PasswordHash
import be.simplenotes.domain.security.SimpleJwt
import be.simplenotes.domain.usecases.NoteService
import be.simplenotes.domain.usecases.UserService
import be.simplenotes.domain.usecases.login.LoginUseCase
import be.simplenotes.domain.usecases.login.LoginUseCaseImpl
import be.simplenotes.domain.usecases.markdown.MarkdownConverter
import be.simplenotes.domain.usecases.markdown.MarkdownConverterImpl
import be.simplenotes.domain.usecases.register.RegisterUseCase
import be.simplenotes.domain.usecases.register.RegisterUseCaseImpl
import be.simplenotes.domain.usecases.users.delete.DeleteUseCase
import be.simplenotes.domain.usecases.users.delete.DeleteUseCaseImpl
import be.simplenotes.domain.usecases.users.login.LoginUseCase
import be.simplenotes.domain.usecases.users.login.LoginUseCaseImpl
import be.simplenotes.domain.usecases.users.register.RegisterUseCase
import be.simplenotes.domain.usecases.users.register.RegisterUseCaseImpl
import org.koin.dsl.module
val domainModule = module {
single<LoginUseCase> { LoginUseCaseImpl(get(), get(), get()) }
single<RegisterUseCase> { RegisterUseCaseImpl(get(), get()) }
single { UserService(get(), get()) }
single<DeleteUseCase> { DeleteUseCaseImpl(get(), get()) }
single { UserService(get(), get(), get()) }
single<PasswordHash> { BcryptPasswordHash() }
single { SimpleJwt(get()) }
single { JwtPayloadExtractor(get()) }
@@ -1,9 +1,11 @@
package be.simplenotes.domain.usecases
import be.simplenotes.domain.usecases.login.LoginUseCase
import be.simplenotes.domain.usecases.register.RegisterUseCase
import be.simplenotes.domain.usecases.users.delete.DeleteUseCase
import be.simplenotes.domain.usecases.users.login.LoginUseCase
import be.simplenotes.domain.usecases.users.register.RegisterUseCase
class UserService(
loginUseCase: LoginUseCase,
registerUseCase: RegisterUseCase
) : LoginUseCase by loginUseCase, RegisterUseCase by registerUseCase
registerUseCase: RegisterUseCase,
deleteUseCase: DeleteUseCase,
) : LoginUseCase by loginUseCase, RegisterUseCase by registerUseCase, DeleteUseCase by deleteUseCase
@@ -0,0 +1,24 @@
package be.simplenotes.domain.usecases.users.delete
import arrow.core.Either
import arrow.core.extensions.fx
import arrow.core.rightIfNotNull
import be.simplenotes.domain.security.PasswordHash
import be.simplenotes.domain.usecases.repositories.UserRepository
import be.simplenotes.domain.validation.UserValidations
internal class DeleteUseCaseImpl(
private val userRepository: UserRepository,
private val passwordHash: PasswordHash,
) : DeleteUseCase {
override fun delete(form: DeleteForm) = Either.fx<DeleteError, Unit> {
val user = !UserValidations.validateDelete(form)
val persistedUser = !userRepository.find(user.username).rightIfNotNull { DeleteError.Unregistered }
!Either.cond(
passwordHash.verify(user.password, persistedUser.password),
{ Unit },
{ DeleteError.WrongPassword }
)
!Either.cond(userRepository.delete(persistedUser.id), { Unit }, { DeleteError.Unregistered })
}
}
@@ -0,0 +1,16 @@
package be.simplenotes.domain.usecases.users.delete
import arrow.core.Either
import io.konform.validation.ValidationErrors
sealed class DeleteError {
object Unregistered : DeleteError()
object WrongPassword : DeleteError()
class InvalidForm(val validationErrors: ValidationErrors) : DeleteError()
}
data class DeleteForm(val username: String?, val password: String?, val checked: Boolean)
interface DeleteUseCase {
fun delete(form: DeleteForm): Either<DeleteError, Unit>
}
@@ -1,4 +1,4 @@
package be.simplenotes.domain.usecases.login
package be.simplenotes.domain.usecases.users.login
import arrow.core.Either
import arrow.core.extensions.fx
@@ -1,4 +1,4 @@
package be.simplenotes.domain.usecases.login
package be.simplenotes.domain.usecases.users.login
import arrow.core.Either
import io.konform.validation.ValidationErrors
@@ -1,4 +1,4 @@
package be.simplenotes.domain.usecases.register
package be.simplenotes.domain.usecases.users.register
import arrow.core.Either
import arrow.core.filterOrElse
@@ -1,8 +1,8 @@
package be.simplenotes.domain.usecases.register
package be.simplenotes.domain.usecases.users.register
import arrow.core.Either
import be.simplenotes.domain.model.PersistedUser
import be.simplenotes.domain.usecases.login.LoginForm
import be.simplenotes.domain.usecases.users.login.LoginForm
import io.konform.validation.ValidationErrors
sealed class RegisterError
@@ -4,10 +4,12 @@ import arrow.core.Either
import arrow.core.left
import arrow.core.right
import be.simplenotes.domain.model.User
import be.simplenotes.domain.usecases.login.InvalidLoginForm
import be.simplenotes.domain.usecases.login.LoginForm
import be.simplenotes.domain.usecases.register.InvalidRegisterForm
import be.simplenotes.domain.usecases.register.RegisterForm
import be.simplenotes.domain.usecases.users.delete.DeleteError
import be.simplenotes.domain.usecases.users.delete.DeleteForm
import be.simplenotes.domain.usecases.users.login.InvalidLoginForm
import be.simplenotes.domain.usecases.users.login.LoginForm
import be.simplenotes.domain.usecases.users.register.InvalidRegisterForm
import be.simplenotes.domain.usecases.users.register.RegisterForm
import io.konform.validation.Validation
import io.konform.validation.jsonschema.maxLength
import io.konform.validation.jsonschema.minLength
@@ -35,4 +37,24 @@ internal object UserValidations {
return if (errors.isEmpty()) User(form.username!!, form.password!!).right()
else return InvalidRegisterForm(errors).left()
}
private val deleteValidator = Validation<DeleteForm> {
DeleteForm::username required {
minLength(3)
maxLength(50)
}
DeleteForm::password required {
minLength(8)
maxLength(72)
}
DeleteForm::checked required {
addConstraint("Should be checked") { it }
}
}
fun validateDelete(form: DeleteForm): Either<DeleteError.InvalidForm, User> {
val errors = deleteValidator.validate(form).errors
return if (errors.isEmpty()) User(form.username!!, form.password!!).right()
else return DeleteError.InvalidForm(errors).left()
}
}