diff --git a/src/main/kotlin/ltd/hlaeja/controller/AccountController.kt b/src/main/kotlin/ltd/hlaeja/controller/AccountController.kt index bb2d332..fb6fed4 100644 --- a/src/main/kotlin/ltd/hlaeja/controller/AccountController.kt +++ b/src/main/kotlin/ltd/hlaeja/controller/AccountController.kt @@ -1,9 +1,12 @@ package ltd.hlaeja.controller +import java.util.UUID import ltd.hlaeja.dto.Pagination +import ltd.hlaeja.exception.PasswordException import ltd.hlaeja.exception.UsernameDuplicateException import ltd.hlaeja.form.AccountForm import ltd.hlaeja.service.AccountRegistryService +import ltd.hlaeja.util.toAccountForm import ltd.hlaeja.util.toAccountRequest import org.springframework.stereotype.Controller import org.springframework.ui.Model @@ -24,11 +27,22 @@ class AccountController( const val DEFAULT_SIZE: Int = 25 } + @GetMapping("/edit-{account}") + fun getEditAccount( + @PathVariable account: UUID, + model: Model + ): Mono = accountRegistryService.getAccount(account) + .doOnNext { + model.addAttribute("account", account) + model.addAttribute("accountForm", it.toAccountForm()) + } + .then(Mono.just("account/edit")) + @GetMapping("/create") fun getCreateAccount( model: Model, ): Mono = Mono.just("account/create") - .doOnNext { model.addAttribute("accountForm", AccountForm("", "", "", "", true)) } + .doOnNext { model.addAttribute("accountForm", AccountForm("", "")) } @PostMapping("/create") fun postCreateAccount( @@ -43,6 +57,7 @@ class AccountController( .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) diff --git a/src/main/kotlin/ltd/hlaeja/exception/PasswordException.kt b/src/main/kotlin/ltd/hlaeja/exception/PasswordException.kt new file mode 100644 index 0000000..7993158 --- /dev/null +++ b/src/main/kotlin/ltd/hlaeja/exception/PasswordException.kt @@ -0,0 +1,23 @@ +package ltd.hlaeja.exception + +@Suppress("unused") +open class PasswordException : HlaejaException { + + 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/form/AccountForm.kt b/src/main/kotlin/ltd/hlaeja/form/AccountForm.kt index c8542ff..d2139d0 100644 --- a/src/main/kotlin/ltd/hlaeja/form/AccountForm.kt +++ b/src/main/kotlin/ltd/hlaeja/form/AccountForm.kt @@ -2,8 +2,8 @@ package ltd.hlaeja.form data class AccountForm( val username: String, - val password: CharSequence, - val passwordConfirm: CharSequence, val role: String, val enabled: Boolean = false, + val password: CharSequence? = null, + val passwordConfirm: CharSequence? = null, ) diff --git a/src/main/kotlin/ltd/hlaeja/service/AccountRegistryService.kt b/src/main/kotlin/ltd/hlaeja/service/AccountRegistryService.kt index 983429a..b67abdf 100644 --- a/src/main/kotlin/ltd/hlaeja/service/AccountRegistryService.kt +++ b/src/main/kotlin/ltd/hlaeja/service/AccountRegistryService.kt @@ -1,10 +1,12 @@ package ltd.hlaeja.service import io.github.oshai.kotlinlogging.KotlinLogging +import java.util.UUID import ltd.hlaeja.exception.AccountRegistryException import ltd.hlaeja.library.accountRegistry.Account import ltd.hlaeja.library.accountRegistry.Authentication import ltd.hlaeja.property.AccountRegistryProperty +import ltd.hlaeja.util.accountRegistryAccount import ltd.hlaeja.util.accountRegistryAccounts import ltd.hlaeja.util.accountRegistryAuthenticate import ltd.hlaeja.util.accountRegistryCreate @@ -66,4 +68,14 @@ class AccountRegistryService( else -> Mono.error(ResponseStatusException(BAD_REQUEST, error.message)) } } + + fun getAccount( + account: UUID, + ): Mono = webClient.accountRegistryAccount(account, property) + .onErrorResume { error -> + when (error) { + is ResponseStatusException -> 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 df6c447..4787e68 100644 --- a/src/main/kotlin/ltd/hlaeja/util/Mapping.kt +++ b/src/main/kotlin/ltd/hlaeja/util/Mapping.kt @@ -1,5 +1,6 @@ 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 @@ -12,7 +13,13 @@ fun SpringAuthentication.toAuthenticationRequest(): Authentication.Request = Aut fun AccountForm.toAccountRequest(): Account.Request = Account.Request( username = username, - password = password, + password = password ?: throw PasswordException("Password requirements failed"), enabled = enabled, roles = listOf("ROLE_${role.uppercase()}"), ) + +fun Account.Response.toAccountForm(): AccountForm = AccountForm( + username = username, + enabled = enabled, + 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 e4e7275..57679e8 100644 --- a/src/main/kotlin/ltd/hlaeja/util/WebClientCalls.kt +++ b/src/main/kotlin/ltd/hlaeja/util/WebClientCalls.kt @@ -1,5 +1,6 @@ package ltd.hlaeja.util +import java.util.UUID import ltd.hlaeja.exception.AccountRegistryException import ltd.hlaeja.exception.UsernameDuplicateException import ltd.hlaeja.library.accountRegistry.Account @@ -14,6 +15,7 @@ import org.springframework.security.authentication.BadCredentialsException import org.springframework.security.authentication.LockedException import org.springframework.security.core.userdetails.UsernameNotFoundException import org.springframework.web.reactive.function.client.WebClient +import org.springframework.web.server.ResponseStatusException import reactor.core.publisher.Flux import reactor.core.publisher.Mono @@ -48,3 +50,12 @@ fun WebClient.accountRegistryCreate( .onStatus(CONFLICT::equals) { throw UsernameDuplicateException() } .onStatus(BAD_REQUEST::equals) { throw AccountRegistryException("Remote service returned 400") } .bodyToMono(Account.Response::class.java) + +fun WebClient.accountRegistryAccount( + account: UUID, + property: AccountRegistryProperty, +): Mono = get() + .uri("${property.url}/account-$account".also(::logCall)) + .retrieve() + .onStatus(NOT_FOUND::equals) { throw ResponseStatusException(NOT_FOUND) } + .bodyToMono(Account.Response::class.java) diff --git a/src/main/resources/templates/account/edit.html b/src/main/resources/templates/account/edit.html new file mode 100644 index 0000000..ece38c4 --- /dev/null +++ b/src/main/resources/templates/account/edit.html @@ -0,0 +1,93 @@ + + + + Home Pages + + + +
+

Test edit user username

+
+
+ +
+ Error Message +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ +
+ + +
+ + +
+ + +
+ + + +
+
+ + + +
+
+ Account + Logout
+
+ + + + diff --git a/src/main/resources/templates/account/users.html b/src/main/resources/templates/account/users.html index ec112bb..dabde49 100644 --- a/src/main/resources/templates/account/users.html +++ b/src/main/resources/templates/account/users.html @@ -14,11 +14,13 @@ Id Name Description + Actions ID timestamp username + Edit