From f9a5b33298403db56cde19ddc1b3c0a7de7c0ad2 Mon Sep 17 00:00:00 2001 From: Aaron Schmid Date: Thu, 9 Oct 2025 10:53:00 +0200 Subject: [PATCH 1/4] fix user update --- .../keycloak/DefaultKeycloakClient.java | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/main/java/de/unistuttgart/iste/meitrex/gamification_service/keycloak/DefaultKeycloakClient.java b/src/main/java/de/unistuttgart/iste/meitrex/gamification_service/keycloak/DefaultKeycloakClient.java index 9a5b67c..e3cbd11 100644 --- a/src/main/java/de/unistuttgart/iste/meitrex/gamification_service/keycloak/DefaultKeycloakClient.java +++ b/src/main/java/de/unistuttgart/iste/meitrex/gamification_service/keycloak/DefaultKeycloakClient.java @@ -3,8 +3,11 @@ import java.util.*; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; import de.unistuttgart.iste.meitrex.gamification_service.aspects.logging.Loggable; import de.unistuttgart.iste.meitrex.gamification_service.aspects.resiliency.Retryable; +import lombok.extern.slf4j.Slf4j; import org.springframework.http.*; import org.springframework.stereotype.*; import org.springframework.web.reactive.function.*; @@ -45,17 +48,21 @@ private static Map> extractAttributeMap(JsonNode node) { private final WebClient webClient; + private final ObjectMapper objectMapper; + public DefaultKeycloakClient( @Value("${keycloak.realm}") String realm, @Value("${keycloak.clientId}") String clientId, @Value("${keycloak.clientSecret}") String clientSecret, - @Autowired @Qualifier("keycloakServiceClient") WebClient webClient + @Autowired @Qualifier("keycloakServiceClient") WebClient webClient, + @Autowired ObjectMapper objectMapper ) { this.realm = Objects.requireNonNull(realm); this.clientId = Objects.requireNonNull(clientId); this.clientSecret = Objects.requireNonNull(clientSecret); this.webClient = Objects.requireNonNull(webClient); + this.objectMapper = Objects.requireNonNull(objectMapper); } @Override @@ -110,13 +117,27 @@ private void removeValues(UUID userId, String attrName) { private void saveAttributeMap(UUID userId, Map> valueMap) { final String token = getAccessToken(); - Map payload = new HashMap<>(); - payload.put("attributes", valueMap); + JsonNode userNode = webClient.get() + .uri("/admin/realms/" + this.realm + "/users/" + userId) + .headers(headers -> headers.setBearerAuth(token)) + .retrieve() + .bodyToMono(JsonNode.class) + .block(); + + if (userNode == null || !userNode.isObject()) { + throw new IllegalStateException("User not found or invalid json for id=" + userId); + } + + + ObjectNode fullUser = (ObjectNode) userNode; + JsonNode attributesNode = objectMapper.valueToTree(valueMap); + fullUser.set("attributes", attributesNode); + webClient.put() .uri("/admin/realms/" + realm + "/users/{id}", userId) .header(HttpHeaders.AUTHORIZATION, "Bearer " + token) .contentType(MediaType.APPLICATION_JSON) - .bodyValue(payload) + .bodyValue(fullUser) .retrieve() .toBodilessEntity() .block(); From c7e175ded8a7ddabbe10353e16918aab062e6000 Mon Sep 17 00:00:00 2001 From: Aaron Schmid Date: Thu, 9 Oct 2025 11:10:27 +0200 Subject: [PATCH 2/4] add logs --- .../gamification_service/keycloak/DefaultKeycloakClient.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/de/unistuttgart/iste/meitrex/gamification_service/keycloak/DefaultKeycloakClient.java b/src/main/java/de/unistuttgart/iste/meitrex/gamification_service/keycloak/DefaultKeycloakClient.java index e3cbd11..69e568a 100644 --- a/src/main/java/de/unistuttgart/iste/meitrex/gamification_service/keycloak/DefaultKeycloakClient.java +++ b/src/main/java/de/unistuttgart/iste/meitrex/gamification_service/keycloak/DefaultKeycloakClient.java @@ -17,6 +17,7 @@ @Component +@Slf4j public class DefaultKeycloakClient implements IKeycloakClient { private static Map> extractAttributeMap(JsonNode node) { @@ -128,11 +129,14 @@ private void saveAttributeMap(UUID userId, Map> valueMap) { throw new IllegalStateException("User not found or invalid json for id=" + userId); } + log.info("Node before: {}", userNode); ObjectNode fullUser = (ObjectNode) userNode; JsonNode attributesNode = objectMapper.valueToTree(valueMap); fullUser.set("attributes", attributesNode); + log.info("Node after: {}", fullUser); + webClient.put() .uri("/admin/realms/" + realm + "/users/{id}", userId) .header(HttpHeaders.AUTHORIZATION, "Bearer " + token) From bd08f5bb6243d63326e7bbe716b9264150cd2c14 Mon Sep 17 00:00:00 2001 From: Aaron Schmid Date: Thu, 9 Oct 2025 11:32:21 +0200 Subject: [PATCH 3/4] remove logs --- .../gamification_service/keycloak/DefaultKeycloakClient.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/de/unistuttgart/iste/meitrex/gamification_service/keycloak/DefaultKeycloakClient.java b/src/main/java/de/unistuttgart/iste/meitrex/gamification_service/keycloak/DefaultKeycloakClient.java index 69e568a..30e76b1 100644 --- a/src/main/java/de/unistuttgart/iste/meitrex/gamification_service/keycloak/DefaultKeycloakClient.java +++ b/src/main/java/de/unistuttgart/iste/meitrex/gamification_service/keycloak/DefaultKeycloakClient.java @@ -129,14 +129,10 @@ private void saveAttributeMap(UUID userId, Map> valueMap) { throw new IllegalStateException("User not found or invalid json for id=" + userId); } - log.info("Node before: {}", userNode); - ObjectNode fullUser = (ObjectNode) userNode; JsonNode attributesNode = objectMapper.valueToTree(valueMap); fullUser.set("attributes", attributesNode); - log.info("Node after: {}", fullUser); - webClient.put() .uri("/admin/realms/" + realm + "/users/{id}", userId) .header(HttpHeaders.AUTHORIZATION, "Bearer " + token) From e7a4dc36494ee14f6c049d958739117bddcfdbf1 Mon Sep 17 00:00:00 2001 From: Aaron Schmid Date: Thu, 9 Oct 2025 11:51:41 +0200 Subject: [PATCH 4/4] fix topic publisher --- .../gamification_service/service/PlayerHexadScoreService.java | 2 +- src/main/resources/application.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/unistuttgart/iste/meitrex/gamification_service/service/PlayerHexadScoreService.java b/src/main/java/de/unistuttgart/iste/meitrex/gamification_service/service/PlayerHexadScoreService.java index 299da2f..249084d 100755 --- a/src/main/java/de/unistuttgart/iste/meitrex/gamification_service/service/PlayerHexadScoreService.java +++ b/src/main/java/de/unistuttgart/iste/meitrex/gamification_service/service/PlayerHexadScoreService.java @@ -8,6 +8,7 @@ import de.unistuttgart.iste.meitrex.gamification_service.persistence.entity.UserEntity; import de.unistuttgart.iste.meitrex.gamification_service.persistence.repository.IPlayerHexadScoreQuestionRepository; import de.unistuttgart.iste.meitrex.gamification_service.service.internal.IUserCreator; +import io.dapr.client.DaprClient; import org.springframework.stereotype.Service; import de.unistuttgart.iste.meitrex.gamification_service.persistence.entity.PlayerHexadScoreEntity; @@ -90,7 +91,6 @@ public PlayerHexadScore calculateDefault(UUID userId, boolean notification) { final String message = "You skipped the questionnaire so we set a default type. Tap to resume."; final String link = "/?resumeSurvey=1"; - final ServerSource source = ServerSource.GAMIFICATION; if (notification) { topicPublisher.notificationEvent( null, diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 5e5642f..a84fac8 100755 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,5 @@ # for deployment or when using docker compose = prod, for local development = dev -spring.profiles.active=dev +spring.profiles.active=prod # enable graphiql (graphiql is a web interface for exploring GraphQL) spring.graphql.graphiql.enabled=true spring.graphql.graphiql.path=/graphiql