diff --git a/src/main/kotlin/ltd/hlaeja/controller/AccountController.kt b/src/main/kotlin/ltd/hlaeja/controller/AccountController.kt index fb6fed4..6d4e20a 100644 --- a/src/main/kotlin/ltd/hlaeja/controller/AccountController.kt +++ b/src/main/kotlin/ltd/hlaeja/controller/AccountController.kt @@ -2,6 +2,8 @@ package ltd.hlaeja.controller import java.util.UUID import ltd.hlaeja.dto.Pagination +import ltd.hlaeja.exception.NoChangeException +import ltd.hlaeja.exception.NotFoundException import ltd.hlaeja.exception.PasswordException import ltd.hlaeja.exception.UsernameDuplicateException import ltd.hlaeja.form.AccountForm @@ -30,7 +32,7 @@ class AccountController( @GetMapping("/edit-{account}") fun getEditAccount( @PathVariable account: UUID, - model: Model + model: Model, ): Mono = accountRegistryService.getAccount(account) .doOnNext { model.addAttribute("account", account) @@ -38,6 +40,37 @@ class AccountController( } .then(Mono.just("account/edit")) + @PostMapping("/edit-{account}") + fun postEditAccount( + @PathVariable account: UUID, + @ModelAttribute("accountForm") accountForm: AccountForm, + model: Model, + ): Mono = Mono.just(accountForm) + .flatMap { + accountRegistryService.updateAccount( + account, + it.toAccountRequest { password -> if (password.isNullOrEmpty()) null else password }, + ) + } + .doOnNext { + model.addAttribute("successMessage", "Saved changes!!!") + model.addAttribute("account", account) + model.addAttribute("accountForm", it.toAccountForm()) + } + .then(Mono.just("account/edit")) + .onErrorResume { error -> + val errorMessage = when (error) { + is NoChangeException -> Pair("successMessage", "No change to save") + is NotFoundException -> Pair("errorMessage", "User dont exists. how did this happen?") + is UsernameDuplicateException -> Pair("errorMessage", "Username already exists. Please choose another.") + else -> Pair("errorMessage", "An unexpected error occurred. Please try again later.") + } + model.addAttribute(errorMessage.first, errorMessage.second) + model.addAttribute("accountForm", accountForm) + model.addAttribute("account", account) + Mono.just("account/edit") + } + @GetMapping("/create") fun getCreateAccount( model: Model, @@ -48,22 +81,27 @@ class AccountController( fun postCreateAccount( @ModelAttribute("accountForm") accountForm: AccountForm, model: Model, - ): Mono { - return accountRegistryService.addAccount(accountForm.toAccountRequest()) - .map { - model.addAttribute("success", true) - "redirect:/account" + ): Mono = Mono.just(accountForm) + .flatMap { + accountRegistryService.addAccount( + it.toAccountRequest { password -> + when { + password.isNullOrEmpty() -> throw PasswordException("Password requirements failed") + else -> password + } + }, + ) + } + .map { "redirect:/account" } + .onErrorResume { error -> + val errorMessage = when (error) { + is UsernameDuplicateException -> "Username already exists. Please choose another." + is PasswordException -> error.message + else -> "An unexpected error occurred. Please try again later." } - .onErrorResume { error -> - val errorMessage = when (error) { - is UsernameDuplicateException -> "Username already exists. Please choose another." - is PasswordException -> error.message - else -> "An unexpected error occurred. Please try again later." - } - model.addAttribute("errorMessage", errorMessage) - Mono.just("account/create") - } - } + model.addAttribute("errorMessage", errorMessage) + Mono.just("account/create") + } @GetMapping fun getDefaultAccounts( diff --git a/src/main/kotlin/ltd/hlaeja/exception/NoChangeException.kt b/src/main/kotlin/ltd/hlaeja/exception/NoChangeException.kt new file mode 100644 index 0000000..2029703 --- /dev/null +++ b/src/main/kotlin/ltd/hlaeja/exception/NoChangeException.kt @@ -0,0 +1,23 @@ +package ltd.hlaeja.exception + +@Suppress("unused") +open class NoChangeException : AccountRegistryException { + + constructor() : super() + + constructor(message: String) : super(message) + + constructor(cause: Throwable) : super(cause) + + constructor( + message: String, + cause: Throwable, + ) : super(message, cause) + + constructor( + message: String, + cause: Throwable, + enableSuppression: Boolean, + writableStackTrace: Boolean, + ) : super(message, cause, enableSuppression, writableStackTrace) +} diff --git a/src/main/kotlin/ltd/hlaeja/exception/NotFoundException.kt b/src/main/kotlin/ltd/hlaeja/exception/NotFoundException.kt new file mode 100644 index 0000000..079adf1 --- /dev/null +++ b/src/main/kotlin/ltd/hlaeja/exception/NotFoundException.kt @@ -0,0 +1,23 @@ +package ltd.hlaeja.exception + +@Suppress("unused") +open class NotFoundException : AccountRegistryException { + + constructor() : super() + + constructor(message: String) : super(message) + + constructor(cause: Throwable) : super(cause) + + constructor( + message: String, + cause: Throwable, + ) : super(message, cause) + + constructor( + message: String, + cause: Throwable, + enableSuppression: Boolean, + writableStackTrace: Boolean, + ) : super(message, cause, enableSuppression, writableStackTrace) +} diff --git a/src/main/kotlin/ltd/hlaeja/service/AccountRegistryService.kt b/src/main/kotlin/ltd/hlaeja/service/AccountRegistryService.kt index b67abdf..1b9721f 100644 --- a/src/main/kotlin/ltd/hlaeja/service/AccountRegistryService.kt +++ b/src/main/kotlin/ltd/hlaeja/service/AccountRegistryService.kt @@ -10,6 +10,7 @@ import ltd.hlaeja.util.accountRegistryAccount import ltd.hlaeja.util.accountRegistryAccounts import ltd.hlaeja.util.accountRegistryAuthenticate import ltd.hlaeja.util.accountRegistryCreate +import ltd.hlaeja.util.accountRegistryUpdate import org.springframework.http.HttpStatus.BAD_REQUEST import org.springframework.security.authentication.AuthenticationServiceException import org.springframework.security.core.AuthenticationException @@ -78,4 +79,15 @@ class AccountRegistryService( else -> Mono.error(ResponseStatusException(BAD_REQUEST, error.message)) } } + + fun updateAccount( + account: UUID, + request: Account.Request, + ): Mono = webClient.accountRegistryUpdate(account, request, property) + .onErrorResume { error -> + when (error) { + is AccountRegistryException -> Mono.error(error) + else -> Mono.error(ResponseStatusException(BAD_REQUEST, error.message)) + } + } } diff --git a/src/main/kotlin/ltd/hlaeja/util/Mapping.kt b/src/main/kotlin/ltd/hlaeja/util/Mapping.kt index 4787e68..44c558e 100644 --- a/src/main/kotlin/ltd/hlaeja/util/Mapping.kt +++ b/src/main/kotlin/ltd/hlaeja/util/Mapping.kt @@ -1,6 +1,5 @@ package ltd.hlaeja.util -import ltd.hlaeja.exception.PasswordException import ltd.hlaeja.form.AccountForm import ltd.hlaeja.library.accountRegistry.Account import ltd.hlaeja.library.accountRegistry.Authentication @@ -11,9 +10,9 @@ fun SpringAuthentication.toAuthenticationRequest(): Authentication.Request = Aut credentials as String, ) -fun AccountForm.toAccountRequest(): Account.Request = Account.Request( +fun AccountForm.toAccountRequest(operation: (CharSequence?) -> CharSequence?): Account.Request = Account.Request( username = username, - password = password ?: throw PasswordException("Password requirements failed"), + password = operation(password), enabled = enabled, roles = listOf("ROLE_${role.uppercase()}"), ) @@ -21,5 +20,5 @@ fun AccountForm.toAccountRequest(): Account.Request = Account.Request( fun Account.Response.toAccountForm(): AccountForm = AccountForm( username = username, enabled = enabled, - role = roles.first().removePrefix("ROLE_").lowercase() + role = roles.first().removePrefix("ROLE_").lowercase(), ) diff --git a/src/main/kotlin/ltd/hlaeja/util/WebClientCalls.kt b/src/main/kotlin/ltd/hlaeja/util/WebClientCalls.kt index 57679e8..7c4b580 100644 --- a/src/main/kotlin/ltd/hlaeja/util/WebClientCalls.kt +++ b/src/main/kotlin/ltd/hlaeja/util/WebClientCalls.kt @@ -2,10 +2,13 @@ package ltd.hlaeja.util import java.util.UUID import ltd.hlaeja.exception.AccountRegistryException +import ltd.hlaeja.exception.NoChangeException +import ltd.hlaeja.exception.NotFoundException import ltd.hlaeja.exception.UsernameDuplicateException import ltd.hlaeja.library.accountRegistry.Account import ltd.hlaeja.library.accountRegistry.Authentication import ltd.hlaeja.property.AccountRegistryProperty +import org.springframework.http.HttpStatus.ACCEPTED import org.springframework.http.HttpStatus.BAD_REQUEST import org.springframework.http.HttpStatus.CONFLICT import org.springframework.http.HttpStatus.LOCKED @@ -36,7 +39,7 @@ fun WebClient.accountRegistryAccounts( size: Int, property: AccountRegistryProperty, ): Flux = get() - .uri("${property.url}/accounts?page=$page&size=$size".also(::logCall)) + .uri("${property.url}/accounts/page-$page/show-$size".also(::logCall)) .retrieve() .bodyToFlux(Account.Response::class.java) @@ -47,7 +50,7 @@ fun WebClient.accountRegistryCreate( .uri("${property.url}/account".also(::logCall)) .bodyValue(request) .retrieve() - .onStatus(CONFLICT::equals) { throw UsernameDuplicateException() } + .onStatus(CONFLICT::equals) { throw UsernameDuplicateException("Remote service returned 409") } .onStatus(BAD_REQUEST::equals) { throw AccountRegistryException("Remote service returned 400") } .bodyToMono(Account.Response::class.java) @@ -59,3 +62,17 @@ fun WebClient.accountRegistryAccount( .retrieve() .onStatus(NOT_FOUND::equals) { throw ResponseStatusException(NOT_FOUND) } .bodyToMono(Account.Response::class.java) + +fun WebClient.accountRegistryUpdate( + account: UUID, + request: Account.Request, + property: AccountRegistryProperty, +): Mono = put() + .uri("${property.url}/account-$account".also(::logCall)) + .bodyValue(request) + .retrieve() + .onStatus(ACCEPTED::equals) { throw NoChangeException("Remote service returned 202") } + .onStatus(BAD_REQUEST::equals) { throw AccountRegistryException("Remote service returned 400") } + .onStatus(NOT_FOUND::equals) { throw NotFoundException("Remote service returned 404") } + .onStatus(CONFLICT::equals) { throw UsernameDuplicateException("Remote service returned 409") } + .bodyToMono(Account.Response::class.java) diff --git a/src/main/resources/templates/account/edit.html b/src/main/resources/templates/account/edit.html index ece38c4..fc303c2 100644 --- a/src/main/resources/templates/account/edit.html +++ b/src/main/resources/templates/account/edit.html @@ -13,6 +13,9 @@
Error Message
+
+ success Message +