From bba756728dc0a82ce1536271b5b685b14da40de0 Mon Sep 17 00:00:00 2001 From: Lobo Date: Sun, 19 Apr 2026 11:38:31 +0200 Subject: [PATCH] Add Steam API client, service, controller Introduce Steam integration: add SteamClientConfig (RestClient bean), SteamApiService (calls GetPlayerSummaries and returns a Player DTO), SteamPlayerSummaryResponse DTO, and SteamTestController (/api/steam/test/{steamId}) for quick testing. Update SecurityConfig to permit the test endpoint and adjust the SecurityFilterChain bean signature. Add Steam API settings: base-url in application.yml and a dev API key in application-dev.yml. Includes basic error logging and optional response handling when no player is found. --- .../security/SecurityConfig.java | 7 +-- .../config/SteamClientConfig.java | 16 +++++++ .../controller/SteamTestController.java | 32 +++++++++++++ .../response/SteamPlayerSummaryResponse.java | 15 +++++++ .../service/SteamApiService.java | 45 +++++++++++++++++++ src/main/resources/application-dev.yml | 7 ++- src/main/resources/application.yml | 1 + 7 files changed, 116 insertions(+), 7 deletions(-) create mode 100644 src/main/java/core_service/domain/steam_adapter/config/SteamClientConfig.java create mode 100644 src/main/java/core_service/domain/steam_adapter/controller/SteamTestController.java create mode 100644 src/main/java/core_service/domain/steam_adapter/controller/dto/response/SteamPlayerSummaryResponse.java create mode 100644 src/main/java/core_service/domain/steam_adapter/service/SteamApiService.java diff --git a/src/main/java/core_service/configuration/security/SecurityConfig.java b/src/main/java/core_service/configuration/security/SecurityConfig.java index 009ae38..a8309b6 100644 --- a/src/main/java/core_service/configuration/security/SecurityConfig.java +++ b/src/main/java/core_service/configuration/security/SecurityConfig.java @@ -27,7 +27,8 @@ public class SecurityConfig { "/internal/**", // Allow internal service communication "/actuator/health", "/actuator/prometheus", - "/error" + "/error", + "/api/steam/test/**" }; private final JwtAuthenticationFilter jwtAuthFilter; @@ -49,7 +50,7 @@ public class SecurityConfig { } @Bean - public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + public SecurityFilterChain securityFilterChain(HttpSecurity http) { http .csrf(AbstractHttpConfigurer::disable) .cors(cors -> cors.configurationSource(corsConfigurationSource())) @@ -63,4 +64,4 @@ public class SecurityConfig { return http.build(); } -} +} \ No newline at end of file diff --git a/src/main/java/core_service/domain/steam_adapter/config/SteamClientConfig.java b/src/main/java/core_service/domain/steam_adapter/config/SteamClientConfig.java new file mode 100644 index 0000000..a2a8d34 --- /dev/null +++ b/src/main/java/core_service/domain/steam_adapter/config/SteamClientConfig.java @@ -0,0 +1,16 @@ +package core_service.domain.steam_adapter.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestClient; + +@Configuration +public class SteamClientConfig { + @Bean + public RestClient steamRestClient(@Value("${app.steam.base-url}") String baseUrl) { + return RestClient.builder() + .baseUrl(baseUrl) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/core_service/domain/steam_adapter/controller/SteamTestController.java b/src/main/java/core_service/domain/steam_adapter/controller/SteamTestController.java new file mode 100644 index 0000000..8e7aa30 --- /dev/null +++ b/src/main/java/core_service/domain/steam_adapter/controller/SteamTestController.java @@ -0,0 +1,32 @@ +package core_service.domain.steam_adapter.controller; + +import core_service.domain.steam_adapter.controller.dto.response.SteamPlayerSummaryResponse; +import core_service.domain.steam_adapter.service.SteamApiService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Optional; + +@RestController +@RequestMapping("/api/steam/test") +@RequiredArgsConstructor +public class SteamTestController { + + private final SteamApiService steamApiService; + + @GetMapping("/{steamId}") + public ResponseEntity testSteamConnection(@PathVariable String steamId) { + + Optional playerOpt = steamApiService.getPlayerSummary(steamId); + + if (playerOpt.isPresent()) { + return ResponseEntity.ok(playerOpt.get()); + } else { + return ResponseEntity.notFound().build(); + } + } +} \ No newline at end of file diff --git a/src/main/java/core_service/domain/steam_adapter/controller/dto/response/SteamPlayerSummaryResponse.java b/src/main/java/core_service/domain/steam_adapter/controller/dto/response/SteamPlayerSummaryResponse.java new file mode 100644 index 0000000..dabe4dd --- /dev/null +++ b/src/main/java/core_service/domain/steam_adapter/controller/dto/response/SteamPlayerSummaryResponse.java @@ -0,0 +1,15 @@ +package core_service.domain.steam_adapter.controller.dto.response; + +import java.util.List; + +public record SteamPlayerSummaryResponse(SteamResponse response) { + + public record SteamResponse(List players) {} + + public record Player( + String steamid, + String personaname, + String profileurl, + String avatarfull + ) {} +} \ No newline at end of file diff --git a/src/main/java/core_service/domain/steam_adapter/service/SteamApiService.java b/src/main/java/core_service/domain/steam_adapter/service/SteamApiService.java new file mode 100644 index 0000000..56fb50a --- /dev/null +++ b/src/main/java/core_service/domain/steam_adapter/service/SteamApiService.java @@ -0,0 +1,45 @@ +package core_service.domain.steam_adapter.service; + +import core_service.domain.steam_adapter.controller.dto.response.SteamPlayerSummaryResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestClient; + +import java.util.Optional; + +@Slf4j +@Service +@RequiredArgsConstructor +public class SteamApiService { + + private final RestClient steamRestClient; + + @Value("${app.steam.api-key}") + private String apiKey; + + public Optional getPlayerSummary(String steamId) { + try { + log.info("Fetching Steam profile for SteamID: {}", steamId); + + SteamPlayerSummaryResponse response = steamRestClient.get() + .uri(uriBuilder -> uriBuilder + .path("/ISteamUser/GetPlayerSummaries/v0002/") + .queryParam("key", apiKey) + .queryParam("steamids", steamId) + .build()) + .retrieve() + .body(SteamPlayerSummaryResponse.class); + + if (response != null && response.response() != null && !response.response().players().isEmpty()) { + return Optional.of(response.response().players().get(0)); + } + + } catch (Exception e) { + log.error("Error communicating with Steam API for SteamID: {}", steamId, e); + } + + return Optional.empty(); + } +} \ No newline at end of file diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index bee4232..73d90bd 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -7,7 +7,8 @@ app: cors: # Local development: allow all origins to prevent CORS issues allowed-origins: "*" - + steam: + api-key: "54EF220BF9A9BF849DB4E33FC4B0FDA3" # Optional: Make SQL logs visible for debugging spring: jpa: @@ -15,6 +16,4 @@ spring: security: jwt: - secret: "NzC9tQP1eTp496SxoVYslH1bqn81Tbfz74NjkFqdcVe7wayjcRN8IeZvJWd1s6NEWgwEXe9rdccvOn2HtJ4fdq" - steam: - api-key: "54EF220BF9A9BF849DB4E33FC4B0FDA3" \ No newline at end of file + secret: "NzC9tQP1eTp496SxoVYslH1bqn81Tbfz74NjkFqdcVe7wayjcRN8IeZvJWd1s6NEWgwEXe9rdccvOn2HtJ4fdq" \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 1726e72..c49daff 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -42,6 +42,7 @@ app: allowed-origins: "https://tbp.andreas-dahm.eu" steam: api-key: ${STEAM_API_KEY} + base-url: https://api.steampowered.com playerService-url: https://api.steampowered.com/IPlayerService/GetOwnedGames/v1/ storeService-url: https://api.steampowered.com/IStoreService/GetAppList/v1/ imageService-url: https://cdn.cloudflare.steamstatic.com/steam/apps/ \ No newline at end of file