diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/group/domain_service/ValidateGroupsDomainService.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/group/domain_service/ValidateGroupsDomainService.java index bec8024499f..765fa073ea3 100644 --- a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/group/domain_service/ValidateGroupsDomainService.java +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/main/java/io/gravitee/apim/core/group/domain_service/ValidateGroupsDomainService.java @@ -21,12 +21,14 @@ import io.gravitee.apim.core.DomainService; import io.gravitee.apim.core.group.model.Group; import io.gravitee.apim.core.group.query_service.GroupQueryService; +import io.gravitee.apim.core.utils.StringUtils; import io.gravitee.apim.core.validation.Validator; import io.gravitee.definition.model.DefinitionVersion; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.function.Function; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -66,12 +68,21 @@ public Result validateAndSanitize(Input input) { var errors = new ArrayList(); + var noPrimaryOwnerResultFromIds = validateAndSanitizeNoPrimaryOwners(groupsFromIds, Group::getId); + var noPrimaryOwnerResultFromNames = validateAndSanitizeNoPrimaryOwners(groupsFromNames, Group::getName); + + noPrimaryOwnerResultFromIds.errors().ifPresent(errors::addAll); + noPrimaryOwnerResultFromNames.errors().ifPresent(errors::addAll); + + var sanitizedFromIds = noPrimaryOwnerResultFromIds.value().orElse(List.of()); + var sanitizedFromNames = noPrimaryOwnerResultFromNames.value().orElse(List.of()); + if (DefinitionVersion.V2.getLabel().equals(input.definitionVersion)) { - sanitizedGroups.addAll(groupsFromIds.stream().map(Group::getName).toList()); - sanitizedGroups.addAll(groupsFromNames.stream().map(Group::getName).toList()); + sanitizedGroups.addAll(sanitizedFromIds.stream().map(Group::getName).toList()); + sanitizedGroups.addAll(sanitizedFromNames.stream().map(Group::getName).toList()); } else { - sanitizedGroups.addAll(groupsFromIds.stream().map(Group::getId).toList()); - sanitizedGroups.addAll(groupsFromNames.stream().map(Group::getId).toList()); + sanitizedGroups.addAll(sanitizedFromIds.stream().map(Group::getId).toList()); + sanitizedGroups.addAll(sanitizedFromNames.stream().map(Group::getId).toList()); } givenGroups.removeAll(groupIds); @@ -83,4 +94,25 @@ public Result validateAndSanitize(Input input) { return Result.ofBoth(input.sanitized(sanitizedGroups), errors); } + + private Result> validateAndSanitizeNoPrimaryOwners(List groups, Function idMapper) { + var sanitized = new ArrayList<>(groups); + var groupsWithPrimaryOwner = sanitized.stream().filter(group -> StringUtils.isNotEmpty(group.getApiPrimaryOwner())).toList(); + sanitized.removeAll(groupsWithPrimaryOwner); + var errors = buildPrimaryOwnerErrors(groupsWithPrimaryOwner, idMapper); + return Result.ofBoth(sanitized, errors); + } + + private List buildPrimaryOwnerErrors(List groupsWithPrimaryOwner, Function idMapper) { + return groupsWithPrimaryOwner + .stream() + .map(idMapper) + .map(id -> + Error.warning( + "Group [%s] will be discarded because it contains an API Primary Owner member, which is not supported with by the operator.", + id + ) + ) + .toList(); + } } diff --git a/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/test/java/io/gravitee/apim/core/group/domain_service/ValidateGroupsDomainServiceTest.java b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/test/java/io/gravitee/apim/core/group/domain_service/ValidateGroupsDomainServiceTest.java new file mode 100644 index 00000000000..eec3a4fb732 --- /dev/null +++ b/gravitee-apim-rest-api/gravitee-apim-rest-api-service/src/test/java/io/gravitee/apim/core/group/domain_service/ValidateGroupsDomainServiceTest.java @@ -0,0 +1,101 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.gravitee.apim.core.group.domain_service; + +import inmemory.GroupQueryServiceInMemory; +import io.gravitee.apim.core.group.model.Group; +import io.gravitee.apim.core.validation.Validator; +import io.gravitee.definition.model.DefinitionVersion; +import java.util.List; +import java.util.Set; +import org.assertj.core.api.SoftAssertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; + +/** + * @author Antoine CORDIER (antoine.cordier at graviteesource.com) + * @author GraviteeSource Team + */ +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +class ValidateGroupsDomainServiceTest { + + private static final String ENVIRONMENT = "TEST"; + + private final GroupQueryServiceInMemory groupQueryService = new GroupQueryServiceInMemory(); + + private ValidateGroupsDomainService validateGroupsDomainService; + + @BeforeEach + void setUp() { + groupQueryService.initWith( + List.of( + Group.builder().environmentId(ENVIRONMENT).id("group-with-po-id").name("group-with-po").apiPrimaryOwner("some-po").build(), + Group.builder().environmentId(ENVIRONMENT).id("group-without-po-id").name("group-without-po").build() + ) + ); + validateGroupsDomainService = new ValidateGroupsDomainService(groupQueryService); + } + + @Test + void should_return_warnings_with_group_with_primary_owner_and_sanitize_v2() { + var givenGroups = Set.of("group-with-po-id", "group-without-po"); + + var input = new ValidateGroupsDomainService.Input(ENVIRONMENT, givenGroups, DefinitionVersion.V2.getLabel()); + + var result = validateGroupsDomainService.validateAndSanitize(input); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(result.value()).isNotEmpty(); + soft.assertThat(result.value()).hasValue(input.sanitized(Set.of("group-without-po"))); + soft.assertThat(result.errors()).isNotEmpty(); + soft + .assertThat(result.errors()) + .hasValue( + List.of( + Validator.Error.warning( + "Group [group-with-po-id] will be discarded because it contains an API Primary Owner member, which is not supported with by the operator." + ) + ) + ); + }); + } + + @Test + void should_return_warnings_with_group_with_primary_owner_and_sanitize_v4() { + var givenGroups = Set.of("group-with-po", "group-without-po-id"); + + var input = new ValidateGroupsDomainService.Input(ENVIRONMENT, givenGroups, DefinitionVersion.V4.getLabel()); + + var result = validateGroupsDomainService.validateAndSanitize(input); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(result.value()).isNotEmpty(); + soft.assertThat(result.value()).hasValue(input.sanitized(Set.of("group-without-po-id"))); + soft.assertThat(result.errors()).isNotEmpty(); + soft + .assertThat(result.errors()) + .hasValue( + List.of( + Validator.Error.warning( + "Group [group-with-po] will be discarded because it contains an API Primary Owner member, which is not supported with by the operator." + ) + ) + ); + }); + } +}