package com.astalange.web.controller; import com.astalange.core.entity.AppUser; import com.astalange.core.entity.Role; import com.astalange.core.repository.AppUserRepository; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.session.SessionRegistry; import org.springframework.security.core.userdetails.UserDetails; 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 java.time.LocalDateTime; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @Controller @RequestMapping("/admin/sessions") public class SessionController { private final SessionRegistry sessionRegistry; private final AppUserRepository userRepository; public SessionController(SessionRegistry sessionRegistry, AppUserRepository userRepository) { this.sessionRegistry = sessionRegistry; this.userRepository = userRepository; } public static class UserSessionDTO { private final Long id; private final String username; private final boolean online; private final LocalDateTime lastLoginAt; private final LocalDateTime lastLogoutAt; private final String roles; public UserSessionDTO(Long id, String username, boolean online, LocalDateTime lastLoginAt, LocalDateTime lastLogoutAt, String roles) { this.id = id; this.username = username; this.online = online; this.lastLoginAt = lastLoginAt; this.lastLogoutAt = lastLogoutAt; this.roles = roles; } public Long getId() { return id; } public String getUsername() { return username; } public boolean isOnline() { return online; } public LocalDateTime getLastLoginAt() { return lastLoginAt; } public LocalDateTime getLastLogoutAt() { return lastLogoutAt; } public String getRoles() { return roles; } } @GetMapping @PreAuthorize("hasRole('ADMIN')") public String viewSessions(Model model) { List principals = sessionRegistry.getAllPrincipals(); Set activeUsernames = principals.stream() .filter(principal -> principal instanceof UserDetails) .map(principal -> ((UserDetails) principal).getUsername()) .collect(Collectors.toSet()); List allUsers = userRepository.findAll(); List userSessions = allUsers.stream().map(user -> { boolean isOnline = activeUsernames.contains(user.getUsername()); String rolesStr = user.getRoles().stream() .map(Role::getName) .map(r -> r.replace("ROLE_", "")) .collect(Collectors.joining(", ")); return new UserSessionDTO( user.getId(), user.getUsername(), isOnline, user.getLastLoginAt(), user.getLastLogoutAt(), rolesStr ); }).collect(Collectors.toList()); long activeCount = userSessions.stream().filter(UserSessionDTO::isOnline).count(); long offlineCount = userSessions.size() - activeCount; model.addAttribute("userSessions", userSessions); model.addAttribute("activeCount", activeCount); model.addAttribute("offlineCount", offlineCount); model.addAttribute("totalCount", userSessions.size()); return "admin/sessions"; } }