Basic accounts

- add account link in welcome.html
- add AuthorizeExchangeSpec adminPaths in SecurityConfiguration
- add AccountController
- add users.html
- add getAccounts in AccountRegistryService
- add WebClient accountRegistryAccounts in webClient
This commit is contained in:
2025-01-23 14:02:59 +01:00
parent 3212226853
commit c40f1a0036
6 changed files with 90 additions and 0 deletions

View File

@@ -31,8 +31,13 @@ class SecurityConfiguration {
private fun authorizeExchange(authorizeExchange: AuthorizeExchangeSpec) = authorizeExchange
.publicPaths().permitAll()
.adminPaths().hasRole("ADMIN")
.anyExchange().authenticated()
private fun AuthorizeExchangeSpec.adminPaths(): AuthorizeExchangeSpec.Access = pathMatchers(
"/account/**"
)
private fun AuthorizeExchangeSpec.publicPaths(): AuthorizeExchangeSpec.Access = pathMatchers(
"/css/**",
"/js/**",

View File

@@ -0,0 +1,30 @@
package ltd.hlaeja.controller
import ltd.hlaeja.service.AccountRegistryService
import org.springframework.stereotype.Controller
import org.springframework.ui.Model
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import reactor.core.publisher.Mono
@Controller
@RequestMapping("/account")
class AccountController(
private val accountRegistryService: AccountRegistryService,
) {
@GetMapping
fun getAccounts(
@RequestParam(defaultValue = "1") page: Int,
@RequestParam(defaultValue = "2") size: Int,
model: Model,
): Mono<String> = accountRegistryService.getAccounts(page, size)
.collectList()
.doOnNext { items ->
model.addAttribute("items", items)
model.addAttribute("page", page)
model.addAttribute("size", size)
}
.then(Mono.just("account/users"))
}

View File

@@ -1,15 +1,20 @@
package ltd.hlaeja.service
import io.github.oshai.kotlinlogging.KotlinLogging
import ltd.hlaeja.library.accountRegistry.Account
import ltd.hlaeja.library.accountRegistry.Authentication
import ltd.hlaeja.property.AccountRegistryProperty
import ltd.hlaeja.util.accountRegistryAccounts
import ltd.hlaeja.util.accountRegistryAuthenticate
import org.springframework.http.HttpStatus.BAD_REQUEST
import org.springframework.security.authentication.AuthenticationServiceException
import org.springframework.security.core.AuthenticationException
import org.springframework.stereotype.Service
import org.springframework.web.reactive.function.client.WebClient
import org.springframework.web.reactive.function.client.WebClientRequestException
import org.springframework.web.reactive.function.client.WebClientResponseException
import org.springframework.web.server.ResponseStatusException
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
private val log = KotlinLogging.logger {}
@@ -43,4 +48,10 @@ class AccountRegistryService(
}
}
}
fun getAccounts(
page: Int,
size: Int,
): Flux<Account.Response> = webClient.accountRegistryAccounts(page, size, property)
.onErrorResume { error -> Flux.error(ResponseStatusException(BAD_REQUEST, error.message, error)) }
}

View File

@@ -1,5 +1,6 @@
package ltd.hlaeja.util
import ltd.hlaeja.library.accountRegistry.Account
import ltd.hlaeja.library.accountRegistry.Authentication
import ltd.hlaeja.property.AccountRegistryProperty
import org.springframework.http.HttpStatus.LOCKED
@@ -9,6 +10,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 reactor.core.publisher.Flux
import reactor.core.publisher.Mono
fun WebClient.accountRegistryAuthenticate(
@@ -22,3 +24,12 @@ fun WebClient.accountRegistryAuthenticate(
.onStatus(UNAUTHORIZED::equals) { throw BadCredentialsException("Invalid credentials") }
.onStatus(NOT_FOUND::equals) { throw UsernameNotFoundException("User not found") }
.bodyToMono(Authentication.Response::class.java)
fun WebClient.accountRegistryAccounts(
page: Int,
size: Int,
property: AccountRegistryProperty
): Flux<Account.Response> = get()
.uri("${property.url}/accounts?page=$page&size=$size".also(::logCall))
.retrieve()
.bodyToFlux(Account.Response::class.java)