Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,136 +35,134 @@

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverta todas as alterações nesse arquivo AuthApplicationService

@Service
public class AuthApplicationServiceImpl implements AuthApplicationService {
private static final int PASSWORD_RECOVERY_EXPIRATION_MINUTES = 30;

private final UserService userService;
private final PasswordEncoder passwordEncoder;
private final TokenProvider tokenProvider;
private final AuthenticationConfiguration authenticationConfiguration;
private final PasswordRecoveryTokenRepository passwordRecoveryTokenRepository;
private final EmailSender emailSender;

@Value("${app.frontend.reset-password-url}")
private String resetPasswordUrl;

public AuthApplicationServiceImpl(
UserService userService,
PasswordEncoder passwordEncoder,
AuthenticationConfiguration authenticationConfiguration,
TokenProvider tokenProvider,
PasswordRecoveryTokenRepository passwordRecoveryTokenRepository,
EmailSender emailSender) {
this.userService = userService;
this.passwordEncoder = passwordEncoder;
this.authenticationConfiguration = authenticationConfiguration;
this.tokenProvider = tokenProvider;
this.passwordRecoveryTokenRepository = passwordRecoveryTokenRepository;
this.emailSender = emailSender;
}

@Override
public void signUp(SignUpDTO signUpDto) {
String passwordHashed = passwordEncoder.encode(signUpDto.password());
userService.createUser(signUpDto.email(), passwordHashed, signUpDto.cpf(), signUpDto.fullName());
}

@Override
public TokenResponseDTO signIn(SignInDTO signInDto) {
try {
User user = userService.findUserByUsername(signInDto.username());

if (!passwordEncoder.matches(signInDto.password(), user.getPassword())) {
throw new InvalidPasswordException();
}

AuthenticationManager authenticationManager = authenticationConfiguration.getAuthenticationManager();
var authenticationToken = new UsernamePasswordAuthenticationToken(
signInDto.username(), signInDto.password());
var authentication = authenticationManager.authenticate(authenticationToken);

UserDetails userDetails = (UserDetails) authentication.getPrincipal();
String token = tokenProvider.generateToken((User) userDetails);

return new TokenResponseDTO(token);
} catch (UserNotFoundException | InvalidPasswordException e) {
throw e;
} catch (Exception e) {
throw new AuthenticationException();
private static final int PASSWORD_RECOVERY_EXPIRATION_MINUTES = 30;

private final UserService userService;
private final PasswordEncoder passwordEncoder;
private final TokenProvider tokenProvider;
private final AuthenticationConfiguration authenticationConfiguration;
private final PasswordRecoveryTokenRepository passwordRecoveryTokenRepository;
private final EmailSender emailSender;

@Value("${app.frontend.reset-password-url}")
private String resetPasswordUrl;

public AuthApplicationServiceImpl(
UserService userService,
PasswordEncoder passwordEncoder,
AuthenticationConfiguration authenticationConfiguration,
TokenProvider tokenProvider,
PasswordRecoveryTokenRepository passwordRecoveryTokenRepository,
EmailSender emailSender) {
this.userService = userService;
this.passwordEncoder = passwordEncoder;
this.authenticationConfiguration = authenticationConfiguration;
this.tokenProvider = tokenProvider;
this.passwordRecoveryTokenRepository = passwordRecoveryTokenRepository;
this.emailSender = emailSender;
}
}

@Override
@Transactional
public void requestPasswordRecovery(PasswordRecoveryRequestDTO dto) {
Optional<User> optionalUser = userService.findUserByEmail(dto.email());
@Override
public void signUp(SignUpDTO signUpDto) {
String passwordHashed = passwordEncoder.encode(signUpDto.password());
userService.createUser(signUpDto.email(), passwordHashed, signUpDto.cpf(), signUpDto.fullName());
}

@Override
public TokenResponseDTO signIn(SignInDTO signInDto) {
try {
User user = userService.findUserByUsername(signInDto.username());

if (!passwordEncoder.matches(signInDto.password(), user.getPassword())) {
throw new InvalidPasswordException();
}

AuthenticationManager authenticationManager = authenticationConfiguration.getAuthenticationManager();
var authenticationToken = new UsernamePasswordAuthenticationToken(
signInDto.username(), signInDto.password());
var authentication = authenticationManager.authenticate(authenticationToken);

UserDetails userDetails = (UserDetails) authentication.getPrincipal();
String token = tokenProvider.generateToken((User) userDetails);

if (optionalUser.isEmpty()) {
return;
return new TokenResponseDTO(token);
} catch (UserNotFoundException | InvalidPasswordException e) {
throw e;
} catch (Exception e) {
}

User user = optionalUser.get();
@Override
@Transactional
public void requestPasswordRecovery(PasswordRecoveryRequestDTO dto) {
Optional<User> optionalUser = userService.findUserByEmail(dto.email());

String rawToken = UUID.randomUUID().toString() + UUID.randomUUID();
String tokenHash = hashToken(rawToken);
if (optionalUser.isEmpty()) {
return;
}

PasswordRecoveryToken passwordRecoveryToken = new PasswordRecoveryToken(
tokenHash,
user,
LocalDateTime.now().plusMinutes(PASSWORD_RECOVERY_EXPIRATION_MINUTES));
User user = optionalUser.get();

passwordRecoveryTokenRepository.save(passwordRecoveryToken);
String rawToken = UUID.randomUUID().toString() + UUID.randomUUID();
String tokenHash = hashToken(rawToken);

String recoveryLink = resetPasswordUrl + "?token=" + rawToken;
PasswordRecoveryToken passwordRecoveryToken = new PasswordRecoveryToken(
tokenHash,
user,
LocalDateTime.now().plusMinutes(PASSWORD_RECOVERY_EXPIRATION_MINUTES));

EmailMessage emailMessage = new EmailMessage(
List.of(dto.email()),
"Recuperação de senha",
"Olá,\n\n" +
"Recebemos uma solicitação para redefinição da sua senha.\n" +
"Clique no link abaixo para continuar:\n\n" +
recoveryLink +
"\n\nSe você não solicitou esta alteração, ignore este e-mail.");
passwordRecoveryTokenRepository.save(passwordRecoveryToken);

emailSender.send(emailMessage);
}
String recoveryLink = resetPasswordUrl + "?token=" + rawToken;

@Override
@Transactional
public void resetPassword(PasswordResetDTO dto) {
if (!dto.newPassword().equals(dto.confirmPassword())) {
throw new AuthenticationException("As senhas não coincidem.");
EmailMessage emailMessage = new EmailMessage(
List.of(dto.email()),
"Recuperação de senha",
"Olá,\n\n" +
"Recebemos uma solicitação para redefinição da sua senha.\n" +
"Clique no link abaixo para continuar:\n\n" +
recoveryLink +
"\n\nSe você não solicitou esta alteração, ignore este e-mail.");

emailSender.send(emailMessage);
}

String tokenHash = hashToken(dto.token());
@Override
@Transactional
public void resetPassword(PasswordResetDTO dto) {
if (!dto.newPassword().equals(dto.confirmPassword())) {
throw new AuthenticationException("As senhas não coincidem.");
}

PasswordRecoveryToken recoveryToken = passwordRecoveryTokenRepository.findByTokenHash(tokenHash)
.orElseThrow(() -> new AuthenticationException("Token inválido."));
String tokenHash = hashToken(dto.token());

if (recoveryToken.isUsed()) {
throw new AuthenticationException("Token já utilizado.");
}
PasswordRecoveryToken recoveryToken = passwordRecoveryTokenRepository.findByTokenHash(tokenHash)
.orElseThrow(() -> new AuthenticationException("Token inválido."));

if (recoveryToken.getExpiresAt().isBefore(LocalDateTime.now())) {
throw new AuthenticationException("Token expirado.");
}
if (recoveryToken.isUsed()) {
throw new AuthenticationException("Token já utilizado.");
}

User user = recoveryToken.getUser();
String encodedPassword = passwordEncoder.encode(dto.newPassword());
if (recoveryToken.getExpiresAt().isBefore(LocalDateTime.now())) {
throw new AuthenticationException("Token expirado.");
}

user.updatePassword(encodedPassword);
userService.save(user);
User user = recoveryToken.getUser();
String encodedPassword = passwordEncoder.encode(dto.newPassword());

recoveryToken.markAsUsed();
passwordRecoveryTokenRepository.save(recoveryToken);
}
user.updatePassword(encodedPassword);
userService.save(user);

recoveryToken.markAsUsed();
passwordRecoveryTokenRepository.save(recoveryToken);
}

private String hashToken(String rawToken) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hashBytes = digest.digest(rawToken.getBytes(StandardCharsets.UTF_8));
return HexFormat.of().formatHex(hashBytes);
} catch (Exception e) {
throw new AuthenticationException("Erro ao processar token de recuperação.", e);
private String hashToken(String rawToken) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hashBytes = digest.digest(rawToken.getBytes(StandardCharsets.UTF_8));
return HexFormat.of().formatHex(hashBytes);
} catch (Exception e) {
throw new AuthenticationException("Erro ao processar token de recuperação.", e);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,74 +17,74 @@

@ControllerAdvice
public class AuthExceptionHandler {
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<ErrorResponse> handleUserNotFound(UserNotFoundException ex, HttpServletRequest request) {
ErrorResponse error = new ErrorResponse(
HttpStatus.NOT_FOUND.value(),
HttpStatus.NOT_FOUND.getReasonPhrase(),
ex.getMessage(),
request.getRequestURI());
return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<ErrorResponse> handleUserNotFound(UserNotFoundException ex, HttpServletRequest request) {
ErrorResponse error = new ErrorResponse(
HttpStatus.UNAUTHORIZED.value(),
HttpStatus.UNAUTHORIZED.getReasonPhrase(),
"E-mail ou senha incorretos",
request.getRequestURI());
return new ResponseEntity<>(error, HttpStatus.UNAUTHORIZED);
}

@ExceptionHandler(UserConflictException.class)
public ResponseEntity<ErrorResponse> handleUserConflict(UserConflictException ex, HttpServletRequest request) {
ErrorResponse error = new ErrorResponse(
HttpStatus.CONFLICT.value(),
HttpStatus.CONFLICT.getReasonPhrase(),
ex.getMessage(),
request.getRequestURI());
return new ResponseEntity<>(error, HttpStatus.CONFLICT);
}
@ExceptionHandler(UserConflictException.class)
public ResponseEntity<ErrorResponse> handleUserConflict(UserConflictException ex, HttpServletRequest request) {
ErrorResponse error = new ErrorResponse(
HttpStatus.CONFLICT.value(),
HttpStatus.CONFLICT.getReasonPhrase(),
ex.getMessage(),
request.getRequestURI());
return new ResponseEntity<>(error, HttpStatus.CONFLICT);
}

@ExceptionHandler(AuthenticationException.class)
public ResponseEntity<ErrorResponse> handleAuthentication(AuthenticationException ex, HttpServletRequest request) {
ErrorResponse error = new ErrorResponse(
HttpStatus.BAD_REQUEST.value(),
HttpStatus.BAD_REQUEST.getReasonPhrase(),
ex.getMessage(),
request.getRequestURI());
return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(AuthenticationException.class)
public ResponseEntity<ErrorResponse> handleAuthentication(AuthenticationException ex, HttpServletRequest request) {
ErrorResponse error = new ErrorResponse(
HttpStatus.BAD_REQUEST.value(),
HttpStatus.BAD_REQUEST.getReasonPhrase(),
ex.getMessage(),
request.getRequestURI());
return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}

@ExceptionHandler(TokenGenerationException.class)
public ResponseEntity<ErrorResponse> handleTokenGeneration(TokenGenerationException ex, HttpServletRequest request) {
ErrorResponse error = new ErrorResponse(
HttpStatus.INTERNAL_SERVER_ERROR.value(),
HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase(),
ex.getMessage(),
request.getRequestURI());
return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
}
@ExceptionHandler(TokenGenerationException.class)
public ResponseEntity<ErrorResponse> handleTokenGeneration(TokenGenerationException ex, HttpServletRequest request) {
ErrorResponse error = new ErrorResponse(
HttpStatus.INTERNAL_SERVER_ERROR.value(),
HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase(),
ex.getMessage(),
request.getRequestURI());
return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
}

@ExceptionHandler(TokenVerificationException.class)
public ResponseEntity<ErrorResponse> handleTokenVerification(TokenVerificationException ex,
HttpServletRequest request) {
ErrorResponse error = new ErrorResponse(
HttpStatus.UNAUTHORIZED.value(),
HttpStatus.UNAUTHORIZED.getReasonPhrase(),
ex.getMessage(),
request.getRequestURI());
return new ResponseEntity<>(error, HttpStatus.UNAUTHORIZED);
}
@ExceptionHandler(TokenVerificationException.class)
public ResponseEntity<ErrorResponse> handleTokenVerification(TokenVerificationException ex,
HttpServletRequest request) {
ErrorResponse error = new ErrorResponse(
HttpStatus.UNAUTHORIZED.value(),
HttpStatus.UNAUTHORIZED.getReasonPhrase(),
ex.getMessage(),
request.getRequestURI());
return new ResponseEntity<>(error, HttpStatus.UNAUTHORIZED);
}

@ExceptionHandler(InvalidPasswordException.class)
public ResponseEntity<ErrorResponse> handleInvalidPassword(InvalidPasswordException ex, HttpServletRequest request) {
ErrorResponse error = new ErrorResponse(
HttpStatus.BAD_REQUEST.value(),
HttpStatus.BAD_REQUEST.getReasonPhrase(),
ex.getMessage(),
request.getRequestURI());
return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(InvalidPasswordException.class)
public ResponseEntity<ErrorResponse> handleInvalidPassword(InvalidPasswordException ex, HttpServletRequest request) {
ErrorResponse error = new ErrorResponse(
HttpStatus.UNAUTHORIZED.value(),
HttpStatus.UNAUTHORIZED.getReasonPhrase(),
"E-mail ou senha incorretos",
request.getRequestURI());
return new ResponseEntity<>(error, HttpStatus.UNAUTHORIZED);
}

@ExceptionHandler(EmailSendingException.class)
public ResponseEntity<ErrorResponse> handleEmailSending(EmailSendingException ex, HttpServletRequest request) {
ErrorResponse error = new ErrorResponse(
HttpStatus.INTERNAL_SERVER_ERROR.value(),
HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase(),
ex.getMessage(),
request.getRequestURI());
return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@ExceptionHandler(EmailSendingException.class)
public ResponseEntity<ErrorResponse> handleEmailSending(EmailSendingException ex, HttpServletRequest request) {
ErrorResponse error = new ErrorResponse(
HttpStatus.INTERNAL_SERVER_ERROR.value(),
HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase(),
ex.getMessage(),
request.getRequestURI());
return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ void shouldReturnUnauthorizedWhenUserDoesNotExist() throws Exception {
);

when(authService.signIn(requestDto))
.thenThrow(new UserNotFoundException());
.thenThrow(new InvalidPasswordException());

mockMvc.perform(post(BASE_URL + "/signin")
.contentType(MediaType.APPLICATION_JSON)
Expand Down