89 lines
3.9 KiB
Java
89 lines
3.9 KiB
Java
|
|
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);
|
||
|
|
}
|
||
|
|
}
|