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."
+ )
+ )
+ );
+ });
+ }
+}