mirror of
https://git.imnavajas.es/jjimenez/erp-imprimelibros.git
synced 2026-02-08 11:59:13 +00:00
116 lines
4.3 KiB
Java
116 lines
4.3 KiB
Java
package com.imprimelibros.erp.users;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
import org.springframework.security.access.AccessDeniedException;
|
|
import org.springframework.security.access.prepost.PreAuthorize;
|
|
import org.springframework.security.core.Authentication;
|
|
import org.springframework.security.core.GrantedAuthority;
|
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|
import org.springframework.security.core.context.SecurityContextHolder;
|
|
import org.springframework.security.core.userdetails.UserDetails;
|
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
|
import org.springframework.stereotype.Controller;
|
|
import org.springframework.web.bind.annotation.PostMapping;
|
|
import org.springframework.web.bind.annotation.RequestParam;
|
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
|
|
|
import com.imprimelibros.erp.config.Sanitizer;
|
|
|
|
import jakarta.servlet.http.HttpServletRequest;
|
|
import jakarta.servlet.http.HttpSession;
|
|
|
|
@Controller
|
|
public class ImpersonationController {
|
|
|
|
private static final String PREVIOUS_ADMIN_ROLE = "ROLE_PREVIOUS_ADMINISTRATOR";
|
|
private static final String SESSION_ATTR = "IMPERSONATOR_AUTH";
|
|
|
|
private final UserService userService;
|
|
private final Sanitizer sanitizer;
|
|
|
|
public ImpersonationController(UserService userService, Sanitizer sanitizer) {
|
|
this.userService = userService;
|
|
this.sanitizer = sanitizer;
|
|
}
|
|
|
|
@PostMapping("/impersonate")
|
|
@PreAuthorize("hasRole('ADMIN') or hasRole('SUPERADMIN')")
|
|
public String impersonate(
|
|
@RequestParam("username") String username,
|
|
Authentication authentication,
|
|
HttpServletRequest request) {
|
|
|
|
if (authentication == null) {
|
|
return "redirect:/login";
|
|
}
|
|
|
|
if (hasRole(authentication, PREVIOUS_ADMIN_ROLE)) {
|
|
return "redirect:/";
|
|
}
|
|
|
|
String normalized = sanitizer.plain(username);
|
|
if (normalized == null || normalized.isBlank()) {
|
|
return "redirect:/users";
|
|
}
|
|
normalized = normalized.trim().toLowerCase();
|
|
|
|
if (authentication.getName() != null
|
|
&& authentication.getName().equalsIgnoreCase(normalized)) {
|
|
return "redirect:/users";
|
|
}
|
|
|
|
UserDetails target;
|
|
try {
|
|
target = userService.loadUserByUsername(normalized);
|
|
} catch (UsernameNotFoundException ex) {
|
|
throw new AccessDeniedException("No autorizado");
|
|
}
|
|
|
|
boolean currentIsSuperAdmin = hasRole(authentication, "ROLE_SUPERADMIN");
|
|
boolean targetIsSuperAdmin = target.getAuthorities().stream()
|
|
.anyMatch(a -> "ROLE_SUPERADMIN".equals(a.getAuthority()));
|
|
if (targetIsSuperAdmin && !currentIsSuperAdmin) {
|
|
throw new AccessDeniedException("No autorizado");
|
|
}
|
|
|
|
HttpSession session = request.getSession(true);
|
|
if (session.getAttribute(SESSION_ATTR) == null) {
|
|
session.setAttribute(SESSION_ATTR, authentication);
|
|
}
|
|
|
|
List<GrantedAuthority> authorities = new ArrayList<>(target.getAuthorities());
|
|
authorities.add(new SimpleGrantedAuthority(PREVIOUS_ADMIN_ROLE));
|
|
|
|
UsernamePasswordAuthenticationToken newAuth = new UsernamePasswordAuthenticationToken(
|
|
target, target.getPassword(), authorities);
|
|
newAuth.setDetails(authentication.getDetails());
|
|
|
|
SecurityContextHolder.getContext().setAuthentication(newAuth);
|
|
return "redirect:/";
|
|
}
|
|
|
|
@PostMapping("/impersonate/exit")
|
|
@PreAuthorize("hasRole('PREVIOUS_ADMINISTRATOR')")
|
|
public String exit(HttpServletRequest request) {
|
|
HttpSession session = request.getSession(false);
|
|
if (session != null) {
|
|
Object previous = session.getAttribute(SESSION_ATTR);
|
|
if (previous instanceof Authentication previousAuth) {
|
|
SecurityContextHolder.getContext().setAuthentication(previousAuth);
|
|
} else {
|
|
SecurityContextHolder.clearContext();
|
|
}
|
|
session.removeAttribute(SESSION_ATTR);
|
|
}
|
|
return "redirect:/";
|
|
}
|
|
|
|
private static boolean hasRole(Authentication auth, String role) {
|
|
return auth != null
|
|
&& auth.getAuthorities().stream()
|
|
.anyMatch(a -> role.equals(a.getAuthority()));
|
|
}
|
|
}
|