From f5946fd4d06791e0c9bb8423acfec3b20be746b8 Mon Sep 17 00:00:00 2001 From: meguito Date: Mon, 7 Sep 2026 15:15:32 -0300 Subject: [PATCH] feat: add dev login endpoint proxying to api-auth --- .../controller/DevAuthController.java | 30 +++++++++++++ .../dto/auth/AuthLoginResponseDTO.java | 21 +++++++++ .../persistence/dto/auth/LoginRequestDTO.java | 19 ++++++++ .../integration/auth/AuthClient.java | 34 +++++++++++++++ .../integration/auth/AuthClientConfig.java | 28 ++++++++++++ .../auth/AuthClientProperties.java | 43 +++++++++++++++++++ .../auth/AuthIntegrationException.java | 8 ++++ .../persistence/security/SecurityConfig.java | 3 ++ src/main/resources/application.properties | 3 ++ 9 files changed, 189 insertions(+) create mode 100644 src/main/java/com/solaria/persistence/controller/DevAuthController.java create mode 100644 src/main/java/com/solaria/persistence/dto/auth/AuthLoginResponseDTO.java create mode 100644 src/main/java/com/solaria/persistence/dto/auth/LoginRequestDTO.java create mode 100644 src/main/java/com/solaria/persistence/integration/auth/AuthClient.java create mode 100644 src/main/java/com/solaria/persistence/integration/auth/AuthClientConfig.java create mode 100644 src/main/java/com/solaria/persistence/integration/auth/AuthClientProperties.java create mode 100644 src/main/java/com/solaria/persistence/integration/auth/AuthIntegrationException.java diff --git a/src/main/java/com/solaria/persistence/controller/DevAuthController.java b/src/main/java/com/solaria/persistence/controller/DevAuthController.java new file mode 100644 index 0000000..f94763d --- /dev/null +++ b/src/main/java/com/solaria/persistence/controller/DevAuthController.java @@ -0,0 +1,30 @@ +package com.solaria.persistence.controller; + +import com.solaria.persistence.dto.auth.AuthLoginResponseDTO; +import com.solaria.persistence.dto.auth.LoginRequestDTO; +import com.solaria.persistence.integration.auth.AuthClient; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +// Proxy de conveniência para autenticar direto pelo Swagger deste serviço, +// sem precisar acessar o Swagger de api-auth. Chama api-auth por baixo. +@RestController +@Tag(name = "Dev") +public class DevAuthController { + + private final AuthClient authClient; + + public DevAuthController(AuthClient authClient) { + this.authClient = authClient; + } + + @Operation(summary = "Autentica em api-auth e devolve o JWT, para colar no botão Authorize deste Swagger") + @PostMapping("/dev/login") + public AuthLoginResponseDTO login(@Valid @RequestBody LoginRequestDTO request) { + return authClient.login(request.getEmail(), request.getPassword()); + } +} diff --git a/src/main/java/com/solaria/persistence/dto/auth/AuthLoginResponseDTO.java b/src/main/java/com/solaria/persistence/dto/auth/AuthLoginResponseDTO.java new file mode 100644 index 0000000..cd5aa8f --- /dev/null +++ b/src/main/java/com/solaria/persistence/dto/auth/AuthLoginResponseDTO.java @@ -0,0 +1,21 @@ +package com.solaria.persistence.dto.auth; + +import lombok.Getter; +import lombok.Setter; + +// Espelha o AuthResponse de api-auth (POST /auth/login) +@Setter +@Getter +public class AuthLoginResponseDTO { + + private String accessToken; + + private String refreshToken; + + private String accessTokenExpiresAt; + + private String userId; + + private String email; + +} diff --git a/src/main/java/com/solaria/persistence/dto/auth/LoginRequestDTO.java b/src/main/java/com/solaria/persistence/dto/auth/LoginRequestDTO.java new file mode 100644 index 0000000..00d6055 --- /dev/null +++ b/src/main/java/com/solaria/persistence/dto/auth/LoginRequestDTO.java @@ -0,0 +1,19 @@ +package com.solaria.persistence.dto.auth; + +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class LoginRequestDTO { + + @Email + @NotBlank + private String email; + + @NotBlank + private String password; + +} diff --git a/src/main/java/com/solaria/persistence/integration/auth/AuthClient.java b/src/main/java/com/solaria/persistence/integration/auth/AuthClient.java new file mode 100644 index 0000000..cab4e7a --- /dev/null +++ b/src/main/java/com/solaria/persistence/integration/auth/AuthClient.java @@ -0,0 +1,34 @@ +package com.solaria.persistence.integration.auth; + +import com.solaria.persistence.dto.auth.AuthLoginResponseDTO; +import com.solaria.persistence.dto.auth.LoginRequestDTO; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestClient; +import org.springframework.web.client.RestClientResponseException; + +// Cliente do endpoint POST /auth/login em api-auth +@Component +public class AuthClient { + + private final RestClient restClient; + + public AuthClient(RestClient authRestClient) { + this.restClient = authRestClient; + } + + public AuthLoginResponseDTO login(String email, String password) { + LoginRequestDTO request = new LoginRequestDTO(); + request.setEmail(email); + request.setPassword(password); + try { + return restClient.post() + .uri("/auth/login") + .body(request) + .retrieve() + .body(AuthLoginResponseDTO.class); + } catch (RestClientResponseException e) { + throw new AuthIntegrationException( + "Falha ao autenticar em api-auth: HTTP " + e.getStatusCode().value(), e); + } + } +} diff --git a/src/main/java/com/solaria/persistence/integration/auth/AuthClientConfig.java b/src/main/java/com/solaria/persistence/integration/auth/AuthClientConfig.java new file mode 100644 index 0000000..55559a1 --- /dev/null +++ b/src/main/java/com/solaria/persistence/integration/auth/AuthClientConfig.java @@ -0,0 +1,28 @@ +package com.solaria.persistence.integration.auth; + +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.JdkClientHttpRequestFactory; +import org.springframework.web.client.RestClient; + +import java.net.http.HttpClient; + +// factory responsável por criar as chamadas http a api-auth +@Configuration +@EnableConfigurationProperties(AuthClientProperties.class) +public class AuthClientConfig { + + @Bean + public RestClient authRestClient(AuthClientProperties properties) { + HttpClient httpClient = HttpClient.newBuilder() + .connectTimeout(properties.getConnectTimeout()) + .build(); + JdkClientHttpRequestFactory requestFactory = new JdkClientHttpRequestFactory(httpClient); + requestFactory.setReadTimeout(properties.getReadTimeout()); + return RestClient.builder() + .baseUrl(properties.getBaseUrl()) + .requestFactory(requestFactory) + .build(); + } +} diff --git a/src/main/java/com/solaria/persistence/integration/auth/AuthClientProperties.java b/src/main/java/com/solaria/persistence/integration/auth/AuthClientProperties.java new file mode 100644 index 0000000..cf3eb3a --- /dev/null +++ b/src/main/java/com/solaria/persistence/integration/auth/AuthClientProperties.java @@ -0,0 +1,43 @@ +package com.solaria.persistence.integration.auth; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.time.Duration; + +// Liga esta classe ao prefixo "app.integration.auth" do application.properties +@ConfigurationProperties(prefix = "app.integration.auth") +public class AuthClientProperties { + + // URL de api-auth + private String baseUrl; + + // timeout de conexão da chamada HTTP a api-auth + private Duration connectTimeout = Duration.ofSeconds(5); + + // timeout de leitura da chamada HTTP a api-auth + private Duration readTimeout = Duration.ofSeconds(5); + + public String getBaseUrl() { + return baseUrl; + } + + public void setBaseUrl(String baseUrl) { + this.baseUrl = baseUrl; + } + + public Duration getConnectTimeout() { + return connectTimeout; + } + + public void setConnectTimeout(Duration connectTimeout) { + this.connectTimeout = connectTimeout; + } + + public Duration getReadTimeout() { + return readTimeout; + } + + public void setReadTimeout(Duration readTimeout) { + this.readTimeout = readTimeout; + } +} diff --git a/src/main/java/com/solaria/persistence/integration/auth/AuthIntegrationException.java b/src/main/java/com/solaria/persistence/integration/auth/AuthIntegrationException.java new file mode 100644 index 0000000..c391d91 --- /dev/null +++ b/src/main/java/com/solaria/persistence/integration/auth/AuthIntegrationException.java @@ -0,0 +1,8 @@ +package com.solaria.persistence.integration.auth; + +// Lançada quando a chamada a POST /auth/login em api-auth falha +public class AuthIntegrationException extends RuntimeException { + public AuthIntegrationException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/com/solaria/persistence/security/SecurityConfig.java b/src/main/java/com/solaria/persistence/security/SecurityConfig.java index 1442c29..5800c08 100644 --- a/src/main/java/com/solaria/persistence/security/SecurityConfig.java +++ b/src/main/java/com/solaria/persistence/security/SecurityConfig.java @@ -143,6 +143,9 @@ public SecurityFilterChain resourceServerSecurityFilterChain(HttpSecurity http) .requestMatchers("/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html") .permitAll() + // Endpoint de conveniência para autenticar direto pelo Swagger + .requestMatchers(HttpMethod.POST, "/dev/login") + .permitAll() // todos os outros endpoints exigem um jwt de usuário válido, // decodificado por userJwtDecoder() .anyRequest().authenticated()) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index da9b05a..7d36120 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -47,3 +47,6 @@ app.jwt.service.access-ttl-ms=${SERVICE_JWT_ACCESS_TTL_MS:600000} # TTL do token de refresh app.jwt.service.refresh-ttl-ms=${SERVICE_JWT_REFRESH_TTL_MS:3600000} +# URL de api-auth, usada pelo endpoint de conveniência POST /dev/login +app.integration.auth.base-url=${AUTH_SERVICE_URL} +