Remove vavr from the bff - part 2 05/135505/2
authorFiete Ostkamp <Fiete.Ostkamp@telekom.de>
Wed, 19 Jul 2023 09:12:31 +0000 (09:12 +0000)
committerFiete Ostkamp <Fiete.Ostkamp@telekom.de>
Wed, 19 Jul 2023 09:15:09 +0000 (09:15 +0000)
Issue-ID: PORTALNG-18
Signed-off-by: Fiete Ostkamp <Fiete.Ostkamp@telekom.de>
Change-Id: I54dece01debdc487bdc6c38df1141ddae1f2e97f

build.gradle
lib/src/main/java/org/onap/portal/bff/config/IdTokenExchangeFilterFunction.java
lib/src/main/java/org/onap/portal/bff/config/clients/KeycloakConfig.java
lib/src/main/java/org/onap/portal/bff/services/KeycloakService.java

index 9ce6023..1f78aa7 100755 (executable)
@@ -11,8 +11,6 @@ buildscript {
     ext {
         springBootVersion = '2.7.3'
         springCloudVersion = '3.1.3'
-        vavrVersion = '0.10.4'
-        vavrJacksonVersion = '0.10.3'
         lombokVersion = '1.18.24'
         openapiVersion = '6.0.1'
         redocVersion = '2.0.0-rc.65'
@@ -68,8 +66,6 @@ allprojects {
     }
 
     dependencies {
-        implementation "io.vavr:vavr:$vavrVersion"
-        implementation "io.vavr:vavr-jackson:$vavrJacksonVersion"
         implementation "org.springframework.boot:spring-boot-starter-logging"
         implementation "net.logstash.logback:logstash-logback-encoder:$logstashLogbackVersion"
 
index be3493d..9cd8ac0 100644 (file)
 package org.onap.portal.bff.config;
 
 import com.nimbusds.jwt.JWTParser;
-import io.vavr.control.Option;
-import io.vavr.control.Try;
+import java.text.ParseException;
+import java.util.Collections;
 import java.util.List;
+import java.util.Optional;
 import org.springframework.util.AntPathMatcher;
 import org.springframework.web.reactive.function.client.ClientRequest;
 import org.springframework.web.reactive.function.client.ClientResponse;
@@ -33,6 +34,7 @@ import org.springframework.web.reactive.function.client.ExchangeFunction;
 import org.springframework.web.server.ServerWebExchange;
 import org.zalando.problem.Problem;
 import org.zalando.problem.Status;
+import reactor.core.Exceptions;
 import reactor.core.publisher.Mono;
 
 public class IdTokenExchangeFilterFunction implements ExchangeFilterFunction {
@@ -61,13 +63,8 @@ public class IdTokenExchangeFilterFunction implements ExchangeFilterFunction {
     }
     return extractServerWebExchange(request)
         .flatMap(IdTokenExchangeFilterFunction::extractIdentityHeader)
-        .flatMap(
-            idToken -> {
-              final ClientRequest requestWithIdToken =
-                  ClientRequest.from(request).header(X_AUTH_IDENTITY_HEADER, idToken).build();
-
-              return next.exchange(requestWithIdToken);
-            })
+        .map(idToken -> ClientRequest.from(request).header(X_AUTH_IDENTITY_HEADER, idToken).build())
+        .flatMap(requestWithIdToken -> next.exchange(requestWithIdToken))
         .switchIfEmpty(Mono.defer(() -> next.exchange(request)));
   }
 
@@ -78,11 +75,9 @@ public class IdTokenExchangeFilterFunction implements ExchangeFilterFunction {
   }
 
   private static Mono<String> extractIdentityHeader(ServerWebExchange exchange) {
-    return io.vavr.collection.List.ofAll(
-            exchange.getRequest().getHeaders().getOrEmpty(X_AUTH_IDENTITY_HEADER))
-        .headOption()
-        .map(Mono::just)
-        .getOrElse(Mono.error(Problem.valueOf(Status.FORBIDDEN, "ID token is missing")));
+    return Mono.just(exchange)
+        .map(exch -> exch.getRequest().getHeaders().getOrEmpty(X_AUTH_IDENTITY_HEADER).get(0))
+        .onErrorResume(ex -> Mono.error(Problem.valueOf(Status.FORBIDDEN, "ID token is missing")));
   }
 
   private static Mono<String> extractIdToken(ServerWebExchange exchange) {
@@ -96,30 +91,35 @@ public class IdTokenExchangeFilterFunction implements ExchangeFilterFunction {
     return extractRoles(exchange)
         .map(roles -> roles.stream().anyMatch(rolesListForMethod::contains))
         .flatMap(
-            match -> {
-              if (Boolean.TRUE.equals(match)) {
-                return Mono.empty();
-              } else {
-                return Mono.error(Problem.valueOf(Status.FORBIDDEN));
-              }
-            });
+            match ->
+                Boolean.TRUE.equals(match)
+                    ? Mono.empty()
+                    : Mono.error(Problem.valueOf(Status.FORBIDDEN)));
   }
 
   private static Mono<List<String>> extractRoles(ServerWebExchange exchange) {
     return extractIdToken(exchange)
-        .flatMap(
-            token ->
-                Try.of(() -> JWTParser.parse(token))
-                    .mapTry(jwt -> Option.of(jwt.getJWTClaimsSet()))
-                    .map(
-                        optionJwtClaimSet ->
-                            optionJwtClaimSet
-                                .flatMap(
-                                    jwtClaimSet ->
-                                        Option.of(jwtClaimSet.getClaim(CLAIM_NAME_ROLES)))
-                                .map(obj -> (List<String>) obj))
-                    .map(Mono::just)
-                    .getOrElseGet(Mono::error))
-        .map(optionRoles -> optionRoles.getOrElse(List.of()));
+        .map(
+            token -> {
+              try {
+                return JWTParser.parse(token);
+              } catch (ParseException e) {
+                throw Exceptions.propagate(e);
+              }
+            })
+        .map(
+            jwt -> {
+              try {
+                return Optional.of(jwt.getJWTClaimsSet());
+              } catch (ParseException e) {
+                throw Exceptions.propagate(e);
+              }
+            })
+        .map(
+            optionalClaimsSet ->
+                optionalClaimsSet
+                    .map(claimsSet -> claimsSet.getClaim(CLAIM_NAME_ROLES))
+                    .map(obj -> (List<String>) obj))
+        .map(roles -> roles.orElse(Collections.emptyList()));
   }
 }
index 0935a00..168c350 100644 (file)
@@ -24,7 +24,6 @@ package org.onap.portal.bff.config.clients;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import java.util.List;
 import java.util.function.Function;
-import lombok.extern.slf4j.Slf4j;
 import org.onap.portal.bff.config.BeansConfig;
 import org.onap.portal.bff.config.PortalBffConfig;
 import org.onap.portal.bff.exceptions.DownstreamApiProblemException;
@@ -32,7 +31,6 @@ import org.onap.portal.bff.openapi.client_portal_keycloak.ApiClient;
 import org.onap.portal.bff.openapi.client_portal_keycloak.api.KeycloakApi;
 import org.onap.portal.bff.openapi.client_portal_keycloak.model.ErrorResponseKeycloakDto;
 import org.onap.portal.bff.openapi.server.model.ProblemApiDto;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -41,14 +39,12 @@ import org.springframework.http.client.reactive.ClientHttpConnector;
 import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
 import org.springframework.web.reactive.function.client.WebClient;
 
-@Slf4j
 @Configuration
 public class KeycloakConfig extends AbstractClientConfig<ErrorResponseKeycloakDto> {
   private final ObjectMapper objectMapper;
   private final PortalBffConfig bffConfig;
   private final ExchangeFilterFunction oauth2ExchangeFilterFunction;
 
-  @Autowired
   public KeycloakConfig(
       @Qualifier(BeansConfig.OAUTH2_EXCHANGE_FILTER_FUNCTION)
           ExchangeFilterFunction oauth2ExchangeFilterFunction,
index 88c25c2..765efa7 100644 (file)
 
 package org.onap.portal.bff.services;
 
-import io.vavr.API;
-import io.vavr.Tuple;
-import io.vavr.Tuple2;
 import java.net.URI;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
+import java.util.Optional;
 import java.util.stream.Collectors;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -44,6 +43,7 @@ import org.springframework.stereotype.Service;
 import org.zalando.problem.Status;
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
+import reactor.util.function.Tuples;
 
 @Slf4j
 @RequiredArgsConstructor
@@ -141,6 +141,21 @@ public class KeycloakService {
     log.debug("Get users from keycloak. page=`{}`, pageSize=`{}`", page, pageSize);
     final int first = (page - 1) * pageSize;
 
+    var userIdRoleMap =
+        listRoles(xRequestId)
+            .flatMap(
+                role ->
+                    listUsersByRole(role.getName(), xRequestId)
+                        .map(userResponse -> Tuples.of(role.getName(), userResponse)))
+            .collectList()
+            .map(
+                tupleList ->
+                    tupleList.stream()
+                        .collect(
+                            Collectors.groupingBy(
+                                tuple -> tuple.getT2().getId(),
+                                Collectors.mapping(tuple -> tuple.getT1(), Collectors.toList()))));
+
     return Mono.zip(
             keycloakApi.getUsersCount(null, null, null, null, null, null, null),
             keycloakApi
@@ -148,31 +163,22 @@ public class KeycloakService {
                     null, null, null, null, null, null, null, null, first, pageSize, null, null,
                     null, null)
                 .collectList(),
-            listRoles(xRequestId)
-                .flatMap(
-                    role ->
-                        listUsersByRole(role.getName(), xRequestId)
-                            .map(user -> Tuple.of(user.getId(), role.getName())))
-                .collectList()
-                .map(io.vavr.collection.List::ofAll)
-                .map(list -> list.groupBy(t -> t._1).map((k, v) -> Tuple.of(k, v.map(Tuple2::_2)))))
+            userIdRoleMap)
         .map(
             tuple -> {
               final UserListResponseApiDto result = new UserListResponseApiDto();
+              Map<String, List<String>> userRoleMap = tuple.getT3();
               result.setTotalCount(tuple.getT1());
-              result.setItems(
-                  io.vavr.collection.List.ofAll(tuple.getT2())
+              var roleList =
+                  tuple.getT2().stream()
                       .map(
                           user ->
                               usersMapper.convert(
                                   user,
-                                  tuple.getT3().getOrElse(user.getId(), API.List()).toJavaList()))
-                      .toJavaList());
-              // result.setItems(
-              //     tuple.getT2().stream()
-              //         .map(user -> usersMapper.convert(user,tuple.getT3()))
-              //         .toList());
-
+                                  Optional.ofNullable(userRoleMap.get(user.getId()))
+                                      .orElse(Collections.emptyList())))
+                      .toList();
+              result.setItems(roleList);
               return result;
             })
         .onErrorResume(