fix(auth): tratar credenciais invalidas com HTTP 401 e habilitar auto-login no cadastro

This commit is contained in:
Gabriel Menezes 2026-11-05 14:58:17 -04:00
parent b1441285a1
commit c613c71f1e
5 changed files with 50 additions and 8 deletions

View file

@ -0,0 +1,23 @@
package net.beetechgroup.beetask.interfaceadapters.controllers;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;
import net.beetechgroup.beetask.usecase.auth.login.InvalidCredentialsException;
import java.util.Map;
@Provider
public class InvalidCredentialsExceptionMapper implements ExceptionMapper<InvalidCredentialsException> {
@Override
public Response toResponse(InvalidCredentialsException exception) {
return Response.status(Response.Status.UNAUTHORIZED)
.type(MediaType.APPLICATION_JSON)
.entity(Map.of(
"error", "Unauthorized",
"message", exception.getMessage() != null ? exception.getMessage() : "Credenciais inválidas"
))
.build();
}
}

View file

@ -0,0 +1,7 @@
package net.beetechgroup.beetask.usecase.auth.login;
public class InvalidCredentialsException extends RuntimeException {
public InvalidCredentialsException(String message) {
super(message);
}
}

View file

@ -31,7 +31,7 @@ public class LoginUseCase {
if (userOptional.isEmpty()) { if (userOptional.isEmpty()) {
LOGGER.warnf("Login failed because email %s was not found", input.email()); LOGGER.warnf("Login failed because email %s was not found", input.email());
throw new RuntimeException("Invalid credentials"); throw new InvalidCredentialsException("E-mail ou senha incorretos.");
} }
User user = userOptional.get(); User user = userOptional.get();
@ -56,7 +56,7 @@ public class LoginUseCase {
if (!passwordMatches) { if (!passwordMatches) {
LOGGER.warnf("Login failed because password did not match for email %s", input.email()); LOGGER.warnf("Login failed because password did not match for email %s", input.email());
throw new RuntimeException("Invalid credentials"); throw new InvalidCredentialsException("E-mail ou senha incorretos.");
} }
LOGGER.infof("Login authenticated for user %s", input.email()); LOGGER.infof("Login authenticated for user %s", input.email());

View file

@ -55,8 +55,12 @@ export async function apiFetch<T>(path: string, options: RequestOptions = {}): P
const parsed = JSON.parse(text) const parsed = JSON.parse(text)
if (parsed.message) { if (parsed.message) {
errorMessage = parsed.message errorMessage = parsed.message
} else if (parsed.error) { } else if (parsed.error && typeof parsed.error === 'string') {
errorMessage = parsed.error errorMessage = parsed.error
} else if (parsed.details) {
errorMessage = response.status >= 500
? 'Ocorreu um erro interno no servidor. Tente novamente em instantes.'
: parsed.details
} }
} catch { } catch {
// Usar texto puro // Usar texto puro

View file

@ -91,11 +91,19 @@ export const AuthPage = () => {
try { try {
await register(name, email, password) await register(name, email, password)
setSuccessMessage('Conta criada com sucesso! Faça login para acessar seu workspace.') try {
setMode('login') const response = await login(email, password)
setSearchParams({ mode: 'login' }) if (!response.organizations || response.organizations.length === 0) {
setPassword('') navigate('/organizations')
setConfirmPassword('') } else {
navigate('/dashboard')
}
return
} catch {
setSuccessMessage('Conta criada com sucesso! Faça login para acessar seu workspace.')
setMode('login')
setSearchParams({ mode: 'login' })
}
} catch (err: unknown) { } catch (err: unknown) {
const msg = err instanceof Error ? err.message : 'Erro ao criar conta. Tente novamente.' const msg = err instanceof Error ? err.message : 'Erro ao criar conta. Tente novamente.'
setErrorMessage(msg) setErrorMessage(msg)