package com.hitcommunications.servermanager.services; import com.hitcommunications.servermanager.config.security.JwtService; import com.hitcommunications.servermanager.config.security.UserPrincipal; import com.hitcommunications.servermanager.model.Users; import com.hitcommunications.servermanager.model.dtos.AuthTokens; import com.hitcommunications.servermanager.model.dtos.LoginRequest; import com.hitcommunications.servermanager.model.dtos.NewUserDTO; import com.hitcommunications.servermanager.model.dtos.UserDTO; import com.hitcommunications.servermanager.mappers.UsersMapper; import com.hitcommunications.servermanager.repositories.UsersRepository; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.stereotype.Service; import org.springframework.web.server.ResponseStatusException; import org.springframework.http.HttpStatus; import java.sql.Timestamp; import java.time.Instant; @Service @RequiredArgsConstructor public class AuthService { private final AuthenticationManager authenticationManager; private final UsersService usersService; private final UsersRepository usersRepository; private final UsersMapper usersMapper; private final JwtService jwtService; private final UserDetailsService userDetailsService; public AuthTokens login(LoginRequest request) { Authentication authentication = authenticationManager.authenticate( new UsernamePasswordAuthenticationToken(request.username(), request.password()) ); UserPrincipal principal = (UserPrincipal) authentication.getPrincipal(); Users user = usersRepository.findById(principal.getId()) .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "User not found after authentication.")); updateLastLogin(user); return issueTokens(user, principal); } public AuthTokens refresh(String refreshToken) { if (refreshToken == null || refreshToken.isBlank()) { throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Refresh token is missing."); } try { String username = jwtService.extractUsername(refreshToken); var userDetails = userDetailsService.loadUserByUsername(username); if (!jwtService.isTokenValid(refreshToken, userDetails, JwtService.TokenType.REFRESH)) { throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Invalid refresh token."); } Users user = usersRepository.findByUsername(username) .or(() -> usersRepository.findByEmail(username)) .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "User not found for refresh token.")); return issueTokens(user, UserPrincipal.fromUser(user)); } catch (ResponseStatusException ex) { throw ex; } catch (Exception ex) { throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Invalid refresh token."); } } @Transactional public UserDTO signup(NewUserDTO createDTO) throws IllegalAccessException { return usersService.create(createDTO); } private AuthTokens issueTokens(Users user, UserPrincipal principal) { String accessToken = jwtService.generateAccessToken(principal); String refreshToken = jwtService.generateRefreshToken(principal); return new AuthTokens(accessToken, refreshToken, usersMapper.toDTO(user)); } private void updateLastLogin(Users user) { user.setLastLogin(Timestamp.from(Instant.now())); usersRepository.save(user); } }