feat(hmm): align backoffice identity administration (#702)

This commit is contained in:
devmrko
2026-07-22 13:49:59 +09:00
parent 64965c294b
commit 572dcd9a67
11 changed files with 226 additions and 158 deletions

View File

@@ -1,6 +1,8 @@
package com.cloudhandson.vpdbackoffice.config;
import com.cloudhandson.vpdbackoffice.service.PermissionService;
import com.cloudhandson.vpdbackoffice.service.GroupService;
import com.cloudhandson.vpdbackoffice.service.UserService;
import java.sql.Connection;
import javax.sql.DataSource;
import org.slf4j.Logger;
@@ -14,13 +16,19 @@ public class DbPoolWarmup {
private static final Logger log = LoggerFactory.getLogger(DbPoolWarmup.class);
private final DataSource dataSource;
private final UserService userService;
private final GroupService groupService;
private final PermissionService permissionService;
public DbPoolWarmup(
DataSource dataSource,
UserService userService,
GroupService groupService,
PermissionService permissionService
) {
this.dataSource = dataSource;
this.userService = userService;
this.groupService = groupService;
this.permissionService = permissionService;
}
@@ -36,10 +44,13 @@ public class DbPoolWarmup {
private void warmupBackofficeCatalog() {
long started = System.nanoTime();
// Only warm the Smilegate identity catalog. VPD catalog objects are not
// part of this PoC and may deliberately be absent from the ADB schema.
userService.findAll();
userService.findUserRoles();
groupService.findAll();
groupService.findGroupUsers();
groupService.findGroupRoles();
permissionService.findRoles();
permissionService.findPermissionViews();
log.info("Backoffice DB catalog cache warmed up in {}ms", (System.nanoTime() - started) / 1_000_000);
log.info("HMM identity catalog cache warmed up in {}ms", (System.nanoTime() - started) / 1_000_000);
}
}

View File

@@ -13,6 +13,7 @@ import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
@Configuration
public class SecurityConfig {
@@ -45,6 +46,8 @@ public class SecurityConfig {
.headers(headers -> headers.httpStrictTransportSecurity(hsts -> hsts
.includeSubDomains(true)
.maxAgeInSeconds(31_536_000)))
.exceptionHandling(exceptions -> exceptions
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login")))
.authorizeHttpRequests(auth -> auth
.requestMatchers(
"/css/**", "/js/**", "/webjars/**",
@@ -64,8 +67,6 @@ public class SecurityConfig {
.requestMatchers(HttpMethod.POST, "/**").hasRole("ADMIN")
.requestMatchers(HttpMethod.DELETE, "/**").hasRole("ADMIN")
.anyRequest().authenticated())
.httpBasic(basic -> {
})
.formLogin(login -> login
.loginPage("/login")
.permitAll())

View File

@@ -1,6 +1,7 @@
package com.cloudhandson.vpdbackoffice.web;
import com.cloudhandson.vpdbackoffice.service.BearerTokenService;
import com.cloudhandson.vpdbackoffice.service.UserService;
import java.time.Clock;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
@@ -18,10 +19,12 @@ import org.springframework.web.servlet.mvc.support.RedirectAttributes;
public class TokenController {
private final BearerTokenService tokenService;
private final UserService userService;
private final Clock clock;
public TokenController(BearerTokenService tokenService, Clock clock) {
public TokenController(BearerTokenService tokenService, UserService userService, Clock clock) {
this.tokenService = tokenService;
this.userService = userService;
this.clock = clock;
}
@@ -32,23 +35,20 @@ public class TokenController {
) {
model.addAttribute("tokens", tokenService.findAll(includeInactive));
model.addAttribute("includeInactive", includeInactive);
model.addAttribute("stakeholders", tokenService.findStakeholderTokenSubjects());
model.addAttribute("users", userService.findAll().stream().filter(user -> user.active()).toList());
model.addAttribute("defaultExpiresAt", defaultExpiresAt());
return "tokens";
}
@PostMapping("/tokens")
public String issue(
@RequestParam String stakeholderUserId,
@RequestParam long userId,
@RequestParam String expiresAt,
@RequestParam(required = false) String description,
RedirectAttributes redirectAttributes
) {
var issued = tokenService.issueStakeholderToken(
stakeholderUserId,
parseBrowserDateTime(expiresAt),
description
);
var issued = tokenService.issueToken(new com.cloudhandson.vpdbackoffice.domain.token.TokenIssueCommand(
userId, parseBrowserDateTime(expiresAt), description));
redirectAttributes.addFlashAttribute("issued", issued);
return "redirect:/tokens";
}