From e25b6f3da3aa4b1931098c672b1e8275e461521f Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger Date: Wed, 2 Aug 2023 16:21:19 +0200 Subject: [PATCH 01/12] feat: improve BPN validation --- build.gradle.kts | 3 + .../BusinessPartnerValidationExtension.java | 6 +- .../build.gradle.kts | 31 ++++ .../BusinessPartnerEvaluationExtension.java | 91 ++++++++++ .../BusinessPartnerGroupFunction.java | 160 +++++++++++++++++ .../spi/BusinessPartnerGroup.java | 20 +++ .../spi/BusinessPartnerGroupStore.java | 21 +++ ...rg.eclipse.edc.spi.system.ServiceExtension | 20 +++ .../BusinessPartnerGroupFunctionTest.java | 169 ++++++++++++++++++ gradle.properties | 2 +- settings.gradle.kts | 1 + 11 files changed, 519 insertions(+), 5 deletions(-) create mode 100644 edc-extensions/business-partner-validation2/build.gradle.kts create mode 100644 edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerEvaluationExtension.java create mode 100644 edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java create mode 100644 edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroup.java create mode 100644 edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroupStore.java create mode 100644 edc-extensions/business-partner-validation2/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension create mode 100644 edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java diff --git a/build.gradle.kts b/build.gradle.kts index 515e21bad..b8d38befa 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -77,10 +77,13 @@ allprojects { } } + val downloadDir = rootProject.layout.projectDirectory.dir("build/downloads") // configure which version of the annotation processor to use. defaults to the same version as the plugin configure { processorVersion.set(annotationProcessorVersion) outputDirectory.set(project.buildDir) + additionalInputDirectory.set(downloadDir.asFile) + downloadDirectory.set(downloadDir.asFile) } configure { diff --git a/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerValidationExtension.java b/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerValidationExtension.java index a2344180f..dcb59f789 100644 --- a/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerValidationExtension.java +++ b/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerValidationExtension.java @@ -90,10 +90,8 @@ public void initialize(ServiceExtensionContext context) { var logAgreementEvaluation = logAgreementEvaluationSetting(context); final BusinessPartnerDutyFunction dutyFunction = new BusinessPartnerDutyFunction(monitor, logAgreementEvaluation); - final BusinessPartnerPermissionFunction permissionFunction = - new BusinessPartnerPermissionFunction(monitor, logAgreementEvaluation); - final BusinessPartnerProhibitionFunction prohibitionFunction = - new BusinessPartnerProhibitionFunction(monitor, logAgreementEvaluation); + final BusinessPartnerPermissionFunction permissionFunction = new BusinessPartnerPermissionFunction(monitor, logAgreementEvaluation); + final BusinessPartnerProhibitionFunction prohibitionFunction = new BusinessPartnerProhibitionFunction(monitor, logAgreementEvaluation); bindToScope(dutyFunction, permissionFunction, prohibitionFunction, TRANSFER_SCOPE); bindToScope(dutyFunction, permissionFunction, prohibitionFunction, NEGOTIATION_SCOPE); diff --git a/edc-extensions/business-partner-validation2/build.gradle.kts b/edc-extensions/business-partner-validation2/build.gradle.kts new file mode 100644 index 000000000..6d5b6059a --- /dev/null +++ b/edc-extensions/business-partner-validation2/build.gradle.kts @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021,2022 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +plugins { + `java-library` + `maven-publish` +} + +dependencies { + implementation(project(":spi:core-spi")) + api(libs.edc.spi.core) + implementation(libs.edc.spi.policy) + implementation(libs.edc.spi.contract) + implementation(libs.edc.spi.policyengine) +} diff --git a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerEvaluationExtension.java b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerEvaluationExtension.java new file mode 100644 index 000000000..3035e99e7 --- /dev/null +++ b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerEvaluationExtension.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.tractusx.edc.validation.businesspartner; + +import org.eclipse.edc.policy.engine.spi.PolicyEngine; +import org.eclipse.edc.policy.engine.spi.RuleBindingRegistry; +import org.eclipse.edc.policy.model.Permission; +import org.eclipse.edc.runtime.metamodel.annotation.Extension; +import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.runtime.metamodel.annotation.Setting; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.tractusx.edc.validation.businesspartner.functions.BusinessPartnerGroupFunction; +import org.eclipse.tractusx.edc.validation.businesspartner.spi.BusinessPartnerGroupStore; + +import static org.eclipse.edc.connector.contract.spi.offer.ContractDefinitionResolver.CATALOGING_SCOPE; +import static org.eclipse.edc.connector.contract.spi.validation.ContractValidationService.NEGOTIATION_SCOPE; +import static org.eclipse.edc.connector.contract.spi.validation.ContractValidationService.TRANSFER_SCOPE; + +/** + * Registers a {@link org.eclipse.tractusx.edc.validation.businesspartner.functions.BusinessPartnerGroupFunction} for the following scopes: + *
    + *
  • {@link org.eclipse.edc.connector.contract.spi.offer.ContractDefinitionResolver#CATALOGING_SCOPE}
  • + *
  • {@link org.eclipse.edc.connector.contract.spi.validation.ContractValidationService#NEGOTIATION_SCOPE}
  • + *
  • {@link org.eclipse.edc.connector.contract.spi.validation.ContractValidationService#TRANSFER_SCOPE}
  • + *
+ * The rule to which the function is bound is {@link BusinessPartnerEvaluationExtension#BUSINESS_PARTNER_CONSTRAINT_KEY}. That means, that policies that are bound to these scopes look + * like this: + *
+ * {
+ *     "constraint": {
+ *         "leftOperand": "BusinessPartnerGroup",
+ *         "operator": "{ eq | neq | in | isAllOf | isAnyOf | isNoneOf }",
+ *         "rightOperand": ["GROUP_ID1", ... "GROUP_IDN"]
+ *     }
+ * }
+ * 
+ *

+ * Note that the {@link BusinessPartnerGroupFunction} is an {@link org.eclipse.edc.policy.engine.spi.AtomicConstraintFunction}, thus it is registered with the {@link PolicyEngine} + * for the {@link Permission} class. + */ +@Extension(value = "Registers a function to evaluate whether a BPN number is covered by a certain policy or not", categories = {"policy", "contract"}) +public class BusinessPartnerEvaluationExtension implements ServiceExtension { + + public static final String BUSINESS_PARTNER_CONSTRAINT_KEY = "BusinessPartnerGroup"; + public static final String DEFAULT_LOG_AGREEMENT_EVALUATION = "true"; + @Setting(value = "Enable logging when evaluating the business partner constraints in the agreement validation", type = "boolean", defaultValue = DEFAULT_LOG_AGREEMENT_EVALUATION) + public static final String BUSINESS_PARTNER_VALIDATION_LOG_AGREEMENT_VALIDATION = "tractusx.businesspartnervalidation.log.agreement.validation"; + private static final String USE = "USE"; + @Inject + private RuleBindingRegistry ruleBindingRegistry; + @Inject + private PolicyEngine policyEngine; + @Inject + private BusinessPartnerGroupStore store; + + @Override + public void initialize(ServiceExtensionContext context) { + var monitor = context.getMonitor(); + var logAgreementEvaluation = logAgreementEvaluationSetting(context); + var function = new BusinessPartnerGroupFunction(store); + + bindToScope(function, TRANSFER_SCOPE); + bindToScope(function, NEGOTIATION_SCOPE); + bindToScope(function, CATALOGING_SCOPE); + } + + private void bindToScope(BusinessPartnerGroupFunction function, String scope) { + ruleBindingRegistry.bind(USE, scope); + ruleBindingRegistry.bind(BUSINESS_PARTNER_CONSTRAINT_KEY, scope); + + policyEngine.registerFunction(scope, Permission.class, BUSINESS_PARTNER_CONSTRAINT_KEY, function); + } + + private boolean logAgreementEvaluationSetting(ServiceExtensionContext context) { + return Boolean.parseBoolean(context.getSetting(BUSINESS_PARTNER_VALIDATION_LOG_AGREEMENT_VALIDATION, DEFAULT_LOG_AGREEMENT_EVALUATION)); + } + +} diff --git a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java new file mode 100644 index 000000000..dfcd7b084 --- /dev/null +++ b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.tractusx.edc.validation.businesspartner.functions; + +import org.eclipse.edc.policy.engine.spi.AtomicConstraintFunction; +import org.eclipse.edc.policy.engine.spi.PolicyContext; +import org.eclipse.edc.policy.model.Operator; +import org.eclipse.edc.policy.model.Permission; +import org.eclipse.edc.spi.agent.ParticipantAgent; +import org.eclipse.tractusx.edc.validation.businesspartner.spi.BusinessPartnerGroupStore; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static java.lang.String.format; +import static org.eclipse.edc.policy.model.Operator.EQ; +import static org.eclipse.edc.policy.model.Operator.IN; +import static org.eclipse.edc.policy.model.Operator.IS_ALL_OF; +import static org.eclipse.edc.policy.model.Operator.IS_ANY_OF; +import static org.eclipse.edc.policy.model.Operator.IS_NONE_OF; +import static org.eclipse.edc.policy.model.Operator.NEQ; + +/** + * This function evaluates, that a particular {@link ParticipantAgent} is a member of a particular group. + * The {@link ParticipantAgent} is represented by its BPN, the {@link org.eclipse.edc.policy.model.Operator} and the {@code rightValue} determine the group(s) and + * whether the BPN must part of it, or not be part of it. + *

+ * For example, a {@link org.eclipse.edc.policy.model.Policy} that mandates the BPN be part of a group {@code "gold_customers"} or {@code "platin_partner} could look like this: + * + *

+ * {
+ *     "constraint": {
+ *         "leftOperand": "BusinessPartnerGroup",
+ *         "operator": "isAnyOf",
+ *         "rightOperand": ["gold_customer","platin_partner"]
+ *     }
+ * }
+ * 
+ *

+ * Upon evaluation, the {@link BusinessPartnerGroupFunction} will take the {@link ParticipantAgent}s BPN, use it to resolve the groups that the BPN is part of, and check, whether `"gold_partner"` and + * `"platin_partner"` are amongst those groups. + *

+ * The following operators are supported: + *

    + *
  • {@link Operator#EQ}: must be exactly in - and only in - that particular group
  • + *
  • {@link Operator#NEQ}: must not be in a particular group
  • + *
  • {@link Operator#IN}: must be in any of the specified groups
  • + *
  • {@link Operator#IS_ALL_OF}: must be in all of the specified groups
  • + *
  • {@link Operator#IS_ANY_OF}: must be in any of the specified groups
  • + *
  • {@link Operator#IS_NONE_OF}: must not be in any of the specified groups
  • + *
+ * + * @see BusinessPartnerGroupStore + */ + +public class BusinessPartnerGroupFunction implements AtomicConstraintFunction { + public static final String REFERRING_CONNECTOR_CLAIM = "referringConnector"; + private static final List ALLOWED_OPERATORS = List.of(EQ, NEQ, IN, IS_ALL_OF, IS_ANY_OF, IS_NONE_OF); + private static final Map> OPERATOR_EVALUATOR_MAP = new HashMap<>(); + private final BusinessPartnerGroupStore store; + + public BusinessPartnerGroupFunction(BusinessPartnerGroupStore store) { + this.store = store; + OPERATOR_EVALUATOR_MAP.put(EQ, this::evaluateEquals); + OPERATOR_EVALUATOR_MAP.put(NEQ, this::evaluateNotEquals); + OPERATOR_EVALUATOR_MAP.put(IN, this::evaluateIn); + OPERATOR_EVALUATOR_MAP.put(IS_ALL_OF, this::evaluateEquals); + OPERATOR_EVALUATOR_MAP.put(IS_ANY_OF, this::evaluateIn); + OPERATOR_EVALUATOR_MAP.put(IS_NONE_OF, this::evaluateNotEquals); + } + + + @Override + public boolean evaluate(Operator operator, Object rightValue, Permission rule, PolicyContext policyContext) { + final ParticipantAgent participantAgent = policyContext.getContextData(ParticipantAgent.class); + + if (participantAgent == null) { + policyContext.reportProblem("ParticipantAgent not found on PolicyContext"); + return false; + } + if (!ALLOWED_OPERATORS.contains(operator)) { + var ops = ALLOWED_OPERATORS.stream().map(Enum::name).collect(Collectors.joining(", ")); + policyContext.reportProblem(format("Operator must be one of [%s] but was [%s]", ops, operator.name())); + return false; + } + + var bpn = getBpnClaim(participantAgent); + var groups = store.resolveForBpn(bpn); + + var rightOperand = parseRightOperand(rightValue, policyContext); + if (rightOperand == null) { + return false; + } + + return OPERATOR_EVALUATOR_MAP.get(operator).apply(new BpnGroupTuple(groups, rightOperand)); + } + + private List parseRightOperand(Object rightValue, PolicyContext context) { + if (rightValue instanceof String) { + return List.of(rightValue.toString()); + } + if (rightValue instanceof Collection) { + return ((Collection) rightValue).stream().map(Object::toString).toList(); + } + + context.reportProblem(format("Right operand expected to be either String or a Collection, but was " + rightValue.getClass())); + return null; + } + + private String getBpnClaim(ParticipantAgent participantAgent) { + String bpnClaim = null; + var claims = participantAgent.getClaims(); + + var bpnClaimObject = claims.get(REFERRING_CONNECTOR_CLAIM); + + if (bpnClaimObject instanceof String) { + bpnClaim = (String) bpnClaimObject; + } + if (bpnClaim == null) { + bpnClaim = participantAgent.getIdentity(); + } + return bpnClaim; + } + + private Boolean evaluateIn(BpnGroupTuple bpnGroupTuple) { + var assigned = bpnGroupTuple.assignedGroups; + // checks whether both lists overlap + return bpnGroupTuple.allowedGroups + .stream() + .distinct() + .anyMatch(assigned::contains); + } + + private Boolean evaluateNotEquals(BpnGroupTuple bpnGroupTuple) { + return !evaluateIn(bpnGroupTuple); + } + + private Boolean evaluateEquals(BpnGroupTuple bpnGroupTuple) { + return bpnGroupTuple.allowedGroups.equals(bpnGroupTuple.assignedGroups); + } + + private record BpnGroupTuple(List assignedGroups, List allowedGroups) { + } +} diff --git a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroup.java b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroup.java new file mode 100644 index 000000000..9177b8495 --- /dev/null +++ b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroup.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.tractusx.edc.validation.businesspartner.spi; + +import java.util.List; + +public record BusinessPartnerGroup(String groupId, String groupName, List bpns) { +} diff --git a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroupStore.java b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroupStore.java new file mode 100644 index 000000000..df21d0d22 --- /dev/null +++ b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroupStore.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.tractusx.edc.validation.businesspartner.spi; + +import java.util.List; + +public interface BusinessPartnerGroupStore { + List resolveForBpn(String businessPartnerNumber); +} diff --git a/edc-extensions/business-partner-validation2/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/business-partner-validation2/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension new file mode 100644 index 000000000..538328bf8 --- /dev/null +++ b/edc-extensions/business-partner-validation2/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -0,0 +1,20 @@ +# +# Copyright (c) 2022 Mercedes-Benz Tech Innovation GmbH +# Copyright (c) 2021,2022 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://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. +# +# SPDX-License-Identifier: Apache-2.0 +# +org.eclipse.tractusx.edc.validation.businesspartner.BusinessPartnerEvaluationExtension diff --git a/edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java b/edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java new file mode 100644 index 000000000..6518f7e29 --- /dev/null +++ b/edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.tractusx.edc.validation.businesspartner.functions; + +import org.eclipse.edc.policy.engine.spi.PolicyContext; +import org.eclipse.edc.policy.model.AtomicConstraint; +import org.eclipse.edc.policy.model.LiteralExpression; +import org.eclipse.edc.policy.model.Operator; +import org.eclipse.edc.policy.model.Permission; +import org.eclipse.edc.spi.agent.ParticipantAgent; +import org.eclipse.tractusx.edc.validation.businesspartner.spi.BusinessPartnerGroupStore; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ArgumentsProvider; +import org.junit.jupiter.params.provider.ArgumentsSource; + +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.edc.policy.model.Operator.EQ; +import static org.eclipse.edc.policy.model.Operator.GEQ; +import static org.eclipse.edc.policy.model.Operator.GT; +import static org.eclipse.edc.policy.model.Operator.HAS_PART; +import static org.eclipse.edc.policy.model.Operator.IN; +import static org.eclipse.edc.policy.model.Operator.IS_A; +import static org.eclipse.edc.policy.model.Operator.IS_ALL_OF; +import static org.eclipse.edc.policy.model.Operator.IS_ANY_OF; +import static org.eclipse.edc.policy.model.Operator.LEQ; +import static org.eclipse.edc.policy.model.Operator.LT; +import static org.eclipse.edc.policy.model.Operator.NEQ; +import static org.eclipse.tractusx.edc.validation.businesspartner.BusinessPartnerEvaluationExtension.BUSINESS_PARTNER_CONSTRAINT_KEY; +import static org.eclipse.tractusx.edc.validation.businesspartner.functions.BusinessPartnerGroupFunction.REFERRING_CONNECTOR_CLAIM; +import static org.mockito.ArgumentMatchers.endsWith; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +class BusinessPartnerGroupFunctionTest { + + public static final String TEST_GROUP_1 = "test-group-1"; + public static final String TEST_GROUP_2 = "test-group-2"; + private static final String TEST_BPN = "BPN000TEST"; + private final PolicyContext context = mock(); + private BusinessPartnerGroupFunction function; + private BusinessPartnerGroupStore store; + + @BeforeEach + void setUp() { + store = mock(); + function = new BusinessPartnerGroupFunction(store); + } + + @Test + @DisplayName("PolicyContext does not carry ParticipantAgent") + void evaluate_noParticipantAgentOnContext() { + reset(context); + assertThat(function.evaluate(EQ, "test-group", createPermission(EQ, List.of()), context)).isFalse(); + verify(context).reportProblem(eq("ParticipantAgent not found on PolicyContext")); + } + + @ParameterizedTest(name = "Invalid operator {0}") + @ArgumentsSource(InvalidOperatorProvider.class) + @DisplayName("Invalid operators, expect report in policy context") + void evaluate_invalidOperator(Operator invalidOperator) { + when(context.getContextData(eq(ParticipantAgent.class))).thenReturn(new ParticipantAgent(Map.of(), Map.of())); + assertThat(function.evaluate(invalidOperator, "test-group", createPermission(invalidOperator, List.of()), context)).isFalse(); + verify(context).reportProblem(endsWith("but was [" + invalidOperator.name() + "]")); + } + + @Test + @DisplayName("Right-hand operand is not String or Collection") + void evaluate_rightOperandNotStringOrCollection() { + when(context.getContextData(eq(ParticipantAgent.class))).thenReturn(new ParticipantAgent(Map.of(REFERRING_CONNECTOR_CLAIM, TEST_BPN), Map.of())); + when(store.resolveForBpn(TEST_BPN)).thenReturn(List.of("test-group")); + + assertThat(function.evaluate(EQ, 42, createPermission(EQ, List.of("test-group")), context)).isFalse(); + assertThat(function.evaluate(EQ, 42L, createPermission(EQ, List.of("test-group")), context)).isFalse(); + assertThat(function.evaluate(EQ, true, createPermission(EQ, List.of("test-group")), context)).isFalse(); + assertThat(function.evaluate(EQ, new Object(), createPermission(EQ, List.of("test-group")), context)).isFalse(); + + verify(context).reportProblem("Right operand expected to be either String or a Collection, but was " + Integer.class); + verify(context).reportProblem("Right operand expected to be either String or a Collection, but was " + Long.class); + verify(context).reportProblem("Right operand expected to be either String or a Collection, but was " + Boolean.class); + verify(context).reportProblem("Right operand expected to be either String or a Collection, but was " + Object.class); + } + + @ParameterizedTest(name = "{1} :: {0}") + @ArgumentsSource(ValidOperatorProvider.class) + @DisplayName("Valid operators, evaluating different circumstances") + void evaluate_validOperator(String ignored, Operator operator, List assignedBpn, boolean expectedOutcome) { + + var allowedGroups = List.of(TEST_GROUP_1, TEST_GROUP_2); + when(context.getContextData(eq(ParticipantAgent.class))).thenReturn(new ParticipantAgent(Map.of(REFERRING_CONNECTOR_CLAIM, TEST_BPN), Map.of())); + when(store.resolveForBpn(TEST_BPN)).thenReturn(assignedBpn); + assertThat(function.evaluate(operator, allowedGroups, createPermission(operator, allowedGroups), context)).isEqualTo(expectedOutcome); + } + + private Permission createPermission(Operator op, List rightOperand) { + return Permission.Builder.newInstance() + .constraint(AtomicConstraint.Builder.newInstance() + .leftExpression(new LiteralExpression(BUSINESS_PARTNER_CONSTRAINT_KEY)) + .operator(op) + .rightExpression(new LiteralExpression(rightOperand)).build()) + .build(); + } + + private static class InvalidOperatorProvider implements ArgumentsProvider { + @Override + public Stream provideArguments(ExtensionContext extensionContext) throws Exception { + return Stream.of( + Arguments.of(GEQ), + Arguments.of(GT), + Arguments.of(HAS_PART), + Arguments.of(LT), + Arguments.of(LEQ), + Arguments.of(IS_A) + ); + } + } + + private static class ValidOperatorProvider implements ArgumentsProvider { + @Override + public Stream provideArguments(ExtensionContext extensionContext) { + return Stream.of( + Arguments.of("Matching groups", EQ, List.of(TEST_GROUP_1, TEST_GROUP_2), true), + Arguments.of("Disjoint groups", EQ, List.of("test-group", "different-group"), false), + Arguments.of("Overlapping groups", EQ, List.of("different-group"), false), + + Arguments.of("Disjoint groups", NEQ, List.of("different-group", "another-different-group"), true), + Arguments.of("Overlapping groups", NEQ, List.of(TEST_GROUP_1, "different-group"), false), + Arguments.of("Matching groups", NEQ, List.of(TEST_GROUP_1, TEST_GROUP_2), false), + + Arguments.of("Matching groups", IN, List.of(TEST_GROUP_1, TEST_GROUP_2), true), + Arguments.of("Overlapping groups", IN, List.of(TEST_GROUP_1, "different-group"), true), + Arguments.of("Disjoint groups", IN, List.of("different-group", "another-different-group"), false), + + Arguments.of("Disjoint groups", IS_ALL_OF, List.of("different-group", "another-different-group"), false), + Arguments.of("Matching groups", IS_ALL_OF, List.of(TEST_GROUP_1, TEST_GROUP_2), true), + Arguments.of("Overlapping groups", IS_ALL_OF, List.of(TEST_GROUP_1, TEST_GROUP_2, "different-group", "another-different-group"), false), + + + Arguments.of("Disjoint groups", IS_ANY_OF, List.of("different-group", "another-different-group"), false), + Arguments.of("Matching groups", IS_ANY_OF, List.of(TEST_GROUP_1, TEST_GROUP_2), true), + Arguments.of("Overlapping groups (1 overlap)", IS_ANY_OF, List.of(TEST_GROUP_1, "different-group", "another-different-group"), true), + Arguments.of("Overlapping groups (2 overlap)", IS_ANY_OF, List.of(TEST_GROUP_1, TEST_GROUP_2, "different-group", "another-different-group"), true) + ); + } + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index b5c9b7061..e4a9c0b39 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ group=org.eclipse.tractusx.edc version=0.5.1-SNAPSHOT # configure the build: annotationProcessorVersion=0.2.0 -edcGradlePluginsVersion=0.2.0 +edcGradlePluginsVersion=0.2.1 metaModelVersion=0.2.0 txScmConnection=scm:git:git@github.com:eclipse-tractusx/tractusx-edc.git txWebsiteUrl=https://github.com/eclipse-tractusx/tractusx-edc.git diff --git a/settings.gradle.kts b/settings.gradle.kts index 7182b2cc9..2d651e780 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -33,6 +33,7 @@ include(":core:json-ld-core") include(":edc-extensions:business-partner-validation") +include(":edc-extensions:business-partner-validation2") include(":edc-extensions:cx-oauth2") include(":edc-extensions:data-encryption") include(":edc-extensions:dataplane-selector-configuration") From 71ef47446aae9052875968fa2a32da02cbb948f3 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger Date: Wed, 2 Aug 2023 18:15:29 +0200 Subject: [PATCH 02/12] add SQL persistence --- .../build.gradle.kts | 37 ++++++ .../docs/schema.sql | 23 ++++ ...SqlBusinessPartnerGroupStoreExtension.java | 58 +++++++++ .../sql/BusinessPartnerGroupStatements.java | 40 ++++++ ...ostgresBusinessPartnerGroupStatements.java | 52 ++++++++ .../sql/SqlBusinessPartnerGroupStore.java | 122 ++++++++++++++++++ ...rg.eclipse.edc.spi.system.ServiceExtension | 20 +++ .../sql/SqlBusinessPartnerGroupStoreTest.java | 105 +++++++++++++++ .../DefaultStoreProviderExtension.java | 29 +++++ .../InMemoryBusinessPartnerGroupStore.java | 61 +++++++++ .../BusinessPartnerGroupFunction.java | 6 +- .../spi/BusinessPartnerGroupStore.java | 10 +- ...rg.eclipse.edc.spi.system.ServiceExtension | 1 + settings.gradle.kts | 1 + 14 files changed, 563 insertions(+), 2 deletions(-) create mode 100644 edc-extensions/business-partner-store-sql/build.gradle.kts create mode 100644 edc-extensions/business-partner-store-sql/docs/schema.sql create mode 100644 edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/SqlBusinessPartnerGroupStoreExtension.java create mode 100644 edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/BusinessPartnerGroupStatements.java create mode 100644 edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/PostgresBusinessPartnerGroupStatements.java create mode 100644 edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/SqlBusinessPartnerGroupStore.java create mode 100644 edc-extensions/business-partner-store-sql/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension create mode 100644 edc-extensions/business-partner-store-sql/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/SqlBusinessPartnerGroupStoreTest.java create mode 100644 edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/DefaultStoreProviderExtension.java create mode 100644 edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/InMemoryBusinessPartnerGroupStore.java diff --git a/edc-extensions/business-partner-store-sql/build.gradle.kts b/edc-extensions/business-partner-store-sql/build.gradle.kts new file mode 100644 index 000000000..ed51e05dd --- /dev/null +++ b/edc-extensions/business-partner-store-sql/build.gradle.kts @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021,2022 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +plugins { + `java-library` + `maven-publish` +} + +dependencies { + implementation(project(":edc-extensions:business-partner-validation2")) + + implementation(libs.edc.spi.core) + implementation(libs.edc.spi.transaction.datasource) + implementation(libs.edc.spi.transactionspi) + implementation(libs.edc.core.sql) + + + testImplementation(libs.edc.transaction.local) + testImplementation(testFixtures(libs.edc.core.sql)) + testImplementation(testFixtures(libs.edc.junit)) +} diff --git a/edc-extensions/business-partner-store-sql/docs/schema.sql b/edc-extensions/business-partner-store-sql/docs/schema.sql new file mode 100644 index 000000000..77be07c48 --- /dev/null +++ b/edc-extensions/business-partner-store-sql/docs/schema.sql @@ -0,0 +1,23 @@ +-- +-- Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +-- +-- This program and the accompanying materials are made available under the +-- terms of the Apache License, Version 2.0 which is available at +-- https://www.apache.org/licenses/LICENSE-2.0 +-- +-- SPDX-License-Identifier: Apache-2.0 +-- +-- Contributors: +-- Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation +-- + + +CREATE TABLE public.edc_business_partner_group +( + bpn VARCHAR NOT NULL + CONSTRAINT edc_business_partner_group_pk + PRIMARY KEY, + groups JSON DEFAULT '[]'::JSON NOT NULL +); + + diff --git a/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/SqlBusinessPartnerGroupStoreExtension.java b/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/SqlBusinessPartnerGroupStoreExtension.java new file mode 100644 index 000000000..578e1a408 --- /dev/null +++ b/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/SqlBusinessPartnerGroupStoreExtension.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.tractusx.edc.validation.businesspartner.store; + +import org.eclipse.edc.runtime.metamodel.annotation.Extension; +import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.runtime.metamodel.annotation.Provider; +import org.eclipse.edc.runtime.metamodel.annotation.Setting; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.spi.types.TypeManager; +import org.eclipse.edc.sql.QueryExecutor; +import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; +import org.eclipse.edc.transaction.spi.TransactionContext; +import org.eclipse.tractusx.edc.validation.businesspartner.spi.BusinessPartnerGroupStore; +import org.eclipse.tractusx.edc.validation.businesspartner.store.sql.BusinessPartnerGroupStatements; +import org.eclipse.tractusx.edc.validation.businesspartner.store.sql.PostgresBusinessPartnerGroupStatements; +import org.eclipse.tractusx.edc.validation.businesspartner.store.sql.SqlBusinessPartnerGroupStore; + +@Extension("Registers an SQL implementation for the BusinessPartnerGroupStore") +public class SqlBusinessPartnerGroupStoreExtension implements ServiceExtension { + + private static final String DEFAULT_DATASOURCE_NAME = "bpn"; + @Setting(value = "Datasource name for the SQL BusinessPartnerGroup store", defaultValue = DEFAULT_DATASOURCE_NAME) + private static final String DATASOURCE_SETTING_NAME = "edc.datasource.bpn.name"; + @Inject + private DataSourceRegistry dataSourceRegistry; + @Inject + private TransactionContext transactionContext; + @Inject + private TypeManager typeManager; + @Inject + private QueryExecutor queryExecutor; + @Inject(required = false) + private BusinessPartnerGroupStatements statements; + + @Provider + public BusinessPartnerGroupStore sqlStore(ServiceExtensionContext context) { + var dataSourceName = context.getConfig().getString(DATASOURCE_SETTING_NAME, DEFAULT_DATASOURCE_NAME); + return new SqlBusinessPartnerGroupStore(dataSourceRegistry, dataSourceName, transactionContext, typeManager.getMapper(), queryExecutor, getStatements()); + } + + private BusinessPartnerGroupStatements getStatements() { + return statements == null ? new PostgresBusinessPartnerGroupStatements() : statements; + } +} diff --git a/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/BusinessPartnerGroupStatements.java b/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/BusinessPartnerGroupStatements.java new file mode 100644 index 000000000..83eecad3a --- /dev/null +++ b/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/BusinessPartnerGroupStatements.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.tractusx.edc.validation.businesspartner.store.sql; + +public interface BusinessPartnerGroupStatements { + + default String getBpnColumn() { + return "bpn"; + } + + default String getGroupsColumn() { + return "groups"; + } + + default String getTable() { + return "edc_business_partner_group"; + } + + String findByBpnTemplate(); + + String insertTemplate(); + + String deleteTemplate(); + + String countQuery(); + + String updateTemplate(); +} diff --git a/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/PostgresBusinessPartnerGroupStatements.java b/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/PostgresBusinessPartnerGroupStatements.java new file mode 100644 index 000000000..4d8961de4 --- /dev/null +++ b/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/PostgresBusinessPartnerGroupStatements.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.tractusx.edc.validation.businesspartner.store.sql; + +import org.eclipse.edc.sql.dialect.PostgresDialect; +import org.jetbrains.annotations.NotNull; + +import static java.lang.String.format; + +public class PostgresBusinessPartnerGroupStatements implements BusinessPartnerGroupStatements { + @Override + public String findByBpnTemplate() { + return format("SELECT %s from %s WHERE %s = ?", getGroupsColumn(), getTable(), getBpnColumn()); + } + + @Override + public String insertTemplate() { + return format("INSERT INTO %s (%s, %s) VALUES (?, ?%s)", getTable(), getBpnColumn(), getGroupsColumn(), getFormatJsonOperator()); + } + + @Override + public String deleteTemplate() { + return format("DELETE FROM %s WHERE %s = ?", getTable(), getBpnColumn()); + } + + @Override + public String countQuery() { + return format("SELECT COUNT (*) FROM %s WHERE %s = ?", getTable(), getBpnColumn()); + } + + @Override + public String updateTemplate() { + return format("UPDATE %s SET %s=?%s WHERE %s=?", getTable(), getGroupsColumn(), getFormatJsonOperator(), getBpnColumn()); + } + + @NotNull + private String getFormatJsonOperator() { + return PostgresDialect.getJsonCastOperator(); + } +} diff --git a/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/SqlBusinessPartnerGroupStore.java b/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/SqlBusinessPartnerGroupStore.java new file mode 100644 index 000000000..04b29171d --- /dev/null +++ b/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/SqlBusinessPartnerGroupStore.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.tractusx.edc.validation.businesspartner.store.sql; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.eclipse.edc.spi.persistence.EdcPersistenceException; +import org.eclipse.edc.spi.result.StoreResult; +import org.eclipse.edc.sql.QueryExecutor; +import org.eclipse.edc.sql.store.AbstractSqlStore; +import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; +import org.eclipse.edc.transaction.spi.TransactionContext; +import org.eclipse.tractusx.edc.validation.businesspartner.spi.BusinessPartnerGroupStore; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.util.Objects; + +public class SqlBusinessPartnerGroupStore extends AbstractSqlStore implements BusinessPartnerGroupStore { + private static final TypeReference> LIST_OF_STRING = new TypeReference<>() { + }; + private final BusinessPartnerGroupStatements statements; + + public SqlBusinessPartnerGroupStore(DataSourceRegistry dataSourceRegistry, String dataSourceName, TransactionContext transactionContext, + ObjectMapper objectMapper, QueryExecutor queryExecutor, BusinessPartnerGroupStatements statements) { + super(dataSourceRegistry, dataSourceName, transactionContext, objectMapper, queryExecutor); + this.statements = statements; + } + + @Override + public StoreResult> resolveForBpn(String businessPartnerNumber) { + Objects.requireNonNull(businessPartnerNumber); + return transactionContext.execute(() -> { + try (var connection = getConnection()) { + var sql = statements.findByBpnTemplate(); + var list = queryExecutor.single(connection, true, this::mapJson, sql, businessPartnerNumber); + return list == null ? + StoreResult.notFound("BPN " + businessPartnerNumber + " was not found") : + StoreResult.success(list); + } catch (SQLException e) { + throw new EdcPersistenceException(e); + } + }); + } + + @Override + public StoreResult save(String businessPartnerNumber, List groups) { + Objects.requireNonNull(businessPartnerNumber); + return transactionContext.execute(() -> { + try (var connection = getConnection()) { + if (exists(businessPartnerNumber, connection)) { + return StoreResult.alreadyExists("BPN " + businessPartnerNumber + " already exists in database"); + } + var sql = statements.insertTemplate(); + queryExecutor.execute(connection, sql, businessPartnerNumber, toJson(groups)); + return StoreResult.success(); + } catch (SQLException e) { + throw new EdcPersistenceException(e); + } + }); + } + + + @Override + public StoreResult delete(String businessPartnerNumber) { + Objects.requireNonNull(businessPartnerNumber); + return transactionContext.execute(() -> { + try (var connection = getConnection()) { + if (!exists(businessPartnerNumber, connection)) { + return StoreResult.notFound("BPN " + businessPartnerNumber + " was not found"); + } + var sql = statements.deleteTemplate(); + queryExecutor.execute(connection, sql, businessPartnerNumber); + return StoreResult.success(); + } catch (SQLException e) { + throw new EdcPersistenceException(e); + } + }); + } + + @Override + public StoreResult update(String businessPartnerNumber, List groups) { + Objects.requireNonNull(businessPartnerNumber); + return transactionContext.execute(() -> { + try (var connection = getConnection()) { + if (!exists(businessPartnerNumber, connection)) { + return StoreResult.notFound("BPN " + businessPartnerNumber + " was not found"); + } + var sql = statements.updateTemplate(); + queryExecutor.execute(connection, sql, toJson(groups), businessPartnerNumber); + return StoreResult.success(); + } catch (SQLException e) { + throw new EdcPersistenceException(e); + } + }); + } + + private List mapJson(ResultSet resultSet) throws SQLException { + return fromJson(resultSet.getString(statements.getGroupsColumn()), LIST_OF_STRING); + } + + private boolean exists(String businessPartnerNumber, Connection connection) { + var countQuery = statements.countQuery(); + try (var stream = queryExecutor.query(connection, false, r -> r.getInt("COUNT"), countQuery, businessPartnerNumber)) { + return stream.findFirst().orElse(0) > 0; + } + } +} diff --git a/edc-extensions/business-partner-store-sql/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/business-partner-store-sql/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension new file mode 100644 index 000000000..eae3fe7cb --- /dev/null +++ b/edc-extensions/business-partner-store-sql/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -0,0 +1,20 @@ +# +# Copyright (c) 2022 Mercedes-Benz Tech Innovation GmbH +# Copyright (c) 2021,2022 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://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. +# +# SPDX-License-Identifier: Apache-2.0 +# +org.eclipse.tractusx.edc.validation.businesspartner.store.SqlBusinessPartnerGroupStoreExtension diff --git a/edc-extensions/business-partner-store-sql/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/SqlBusinessPartnerGroupStoreTest.java b/edc-extensions/business-partner-store-sql/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/SqlBusinessPartnerGroupStoreTest.java new file mode 100644 index 000000000..e57cc17cd --- /dev/null +++ b/edc-extensions/business-partner-store-sql/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/SqlBusinessPartnerGroupStoreTest.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.tractusx.edc.validation.businesspartner.store.sql; + +import org.eclipse.edc.spi.types.TypeManager; +import org.eclipse.edc.sql.QueryExecutor; +import org.eclipse.edc.sql.testfixtures.PostgresqlStoreSetupExtension; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(PostgresqlStoreSetupExtension.class) +class SqlBusinessPartnerGroupStoreTest { + private final TypeManager typeManager = new TypeManager(); + private final BusinessPartnerGroupStatements statements = new PostgresBusinessPartnerGroupStatements(); + private SqlBusinessPartnerGroupStore store; + + @BeforeEach + void setUp(PostgresqlStoreSetupExtension extension, QueryExecutor queryExecutor) throws IOException { + store = new SqlBusinessPartnerGroupStore(extension.getDataSourceRegistry(), extension.getDatasourceName(), extension.getTransactionContext(), typeManager.getMapper(), queryExecutor, statements); + var schema = Files.readString(Paths.get("./docs/schema.sql")); + extension.runQuery(schema); + } + + @Test + void resolveForBpn() { + store.save("test-bpn", List.of("group1", "group2", "group3")); + assertThat(store.resolveForBpn("test-bpn").getContent()).containsExactly("group1", "group2", "group3"); + } + + @Test + void resolveForBpn_notExists() { + assertThat(store.resolveForBpn("test-bpn").succeeded()).isFalse(); + } + + @Test + void resolveForBpn_existsNoGroups() { + store.save("test-bpn", List.of()); + assertThat(store.resolveForBpn("test-bpn").getContent()).isNotNull().isEmpty(); + } + + @Test + void save() { + store.save("test-bpn", List.of("group1", "group2", "group3")); + assertThat(store.resolveForBpn("test-bpn").getContent()).containsExactly("group1", "group2", "group3"); + } + + @Test + void save_exists() { + store.save("test-bpn", List.of("group1", "group2", "group3")); + assertThat(store.save("test-bpn", List.of("group4")).succeeded()).isFalse(); + } + + @Test + void delete() { + var businessPartnerNumber = "test-bpn"; + store.save(businessPartnerNumber, List.of("group1", "group2", "group3")); + var delete = store.delete(businessPartnerNumber); + assertThat(delete.succeeded()).withFailMessage(delete::getFailureDetail).isTrue(); + } + + @Test + void delete_notExist() { + var businessPartnerNumber = "test-bpn"; + store.delete(businessPartnerNumber); + assertThat(store.resolveForBpn(businessPartnerNumber).succeeded()).isFalse(); + } + + @Test + void update() { + var businessPartnerNumber = "test-bpn"; + store.save(businessPartnerNumber, List.of("group1", "group2", "group3")); + assertThat(store.update(businessPartnerNumber, List.of("group4", "group5")).succeeded()).isTrue(); + } + + @Test + void update_notExists() { + assertThat(store.update("test-bpn", List.of("foo", "bar")).succeeded()).isFalse(); + } + + @AfterEach + void tearDown(PostgresqlStoreSetupExtension extension) { + extension.runQuery("DROP TABLE " + statements.getTable() + " CASCADE"); + } +} \ No newline at end of file diff --git a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/DefaultStoreProviderExtension.java b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/DefaultStoreProviderExtension.java new file mode 100644 index 000000000..317703691 --- /dev/null +++ b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/DefaultStoreProviderExtension.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.tractusx.edc.validation.businesspartner; + +import org.eclipse.edc.runtime.metamodel.annotation.Extension; +import org.eclipse.edc.runtime.metamodel.annotation.Provider; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.tractusx.edc.validation.businesspartner.spi.BusinessPartnerGroupStore; + +@Extension("Provides a default BusinessPartnerGroupStore") +public class DefaultStoreProviderExtension implements ServiceExtension { + + @Provider(isDefault = true) + public BusinessPartnerGroupStore createInMemStore() { + return new InMemoryBusinessPartnerGroupStore(); + } +} diff --git a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/InMemoryBusinessPartnerGroupStore.java b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/InMemoryBusinessPartnerGroupStore.java new file mode 100644 index 000000000..a4ced979d --- /dev/null +++ b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/InMemoryBusinessPartnerGroupStore.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.tractusx.edc.validation.businesspartner; + +import org.eclipse.edc.spi.result.StoreResult; +import org.eclipse.tractusx.edc.validation.businesspartner.spi.BusinessPartnerGroupStore; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +class InMemoryBusinessPartnerGroupStore implements BusinessPartnerGroupStore { + private final Map> cache = new HashMap<>(); + + @Override + public StoreResult> resolveForBpn(String businessPartnerNumber) { + var entry = cache.get(businessPartnerNumber); + return entry == null ? + StoreResult.notFound("BPN " + businessPartnerNumber + " was not found in database") : + StoreResult.success(entry); + } + + @Override + public StoreResult save(String businessPartnerNumber, List groups) { + //to maintain behavioural consistency with the SQL store + if (cache.containsKey(businessPartnerNumber)) { + return StoreResult.alreadyExists("BPN " + businessPartnerNumber + " already exists in database"); + } + cache.put(businessPartnerNumber, groups); + return StoreResult.success(); + } + + @Override + public StoreResult delete(String businessPartnerNumber) { + + return cache.remove(businessPartnerNumber) == null ? + StoreResult.notFound("BPN " + businessPartnerNumber + " was not found in database") : + StoreResult.success(); + } + + @Override + public StoreResult update(String businessPartnerNumber, List groups) { + if (cache.containsKey(businessPartnerNumber)) { + cache.put(businessPartnerNumber, groups); + return StoreResult.success(); + } + return StoreResult.notFound("BPN " + businessPartnerNumber + " was not found in database"); + } +} diff --git a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java index dfcd7b084..44188305a 100644 --- a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java +++ b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java @@ -102,13 +102,17 @@ public boolean evaluate(Operator operator, Object rightValue, Permission rule, P var bpn = getBpnClaim(participantAgent); var groups = store.resolveForBpn(bpn); + if (groups.failed()) { + policyContext.reportProblem(groups.getFailureDetail()); + return false; + } var rightOperand = parseRightOperand(rightValue, policyContext); if (rightOperand == null) { return false; } - return OPERATOR_EVALUATOR_MAP.get(operator).apply(new BpnGroupTuple(groups, rightOperand)); + return OPERATOR_EVALUATOR_MAP.get(operator).apply(new BpnGroupTuple(groups.getContent(), rightOperand)); } private List parseRightOperand(Object rightValue, PolicyContext context) { diff --git a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroupStore.java b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroupStore.java index df21d0d22..de9338b7f 100644 --- a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroupStore.java +++ b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroupStore.java @@ -14,8 +14,16 @@ package org.eclipse.tractusx.edc.validation.businesspartner.spi; +import org.eclipse.edc.spi.result.StoreResult; + import java.util.List; public interface BusinessPartnerGroupStore { - List resolveForBpn(String businessPartnerNumber); + StoreResult> resolveForBpn(String businessPartnerNumber); + + StoreResult save(String businessPartnerNumber, List groups); + + StoreResult delete(String businessPartnerNumber); + + StoreResult update(String businessPartnerNumber, List groups); } diff --git a/edc-extensions/business-partner-validation2/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/business-partner-validation2/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension index 538328bf8..6b704afe6 100644 --- a/edc-extensions/business-partner-validation2/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ b/edc-extensions/business-partner-validation2/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -18,3 +18,4 @@ # SPDX-License-Identifier: Apache-2.0 # org.eclipse.tractusx.edc.validation.businesspartner.BusinessPartnerEvaluationExtension +org.eclipse.tractusx.edc.validation.businesspartner.DefaultStoreProviderExtension diff --git a/settings.gradle.kts b/settings.gradle.kts index 2d651e780..01e22260b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -34,6 +34,7 @@ include(":core:json-ld-core") include(":edc-extensions:business-partner-validation") include(":edc-extensions:business-partner-validation2") +include(":edc-extensions:business-partner-store-sql") include(":edc-extensions:cx-oauth2") include(":edc-extensions:data-encryption") include(":edc-extensions:dataplane-selector-configuration") From c9daec870d2f03250525dfdb1d6f9b0c9cdf141f Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger Date: Wed, 2 Aug 2023 18:24:51 +0200 Subject: [PATCH 03/12] add base test class, inmem tests --- .../build.gradle.kts | 1 + .../sql/SqlBusinessPartnerGroupStoreTest.java | 67 ++------------- .../build.gradle.kts | 5 ++ ...InMemoryBusinessPartnerGroupStoreTest.java | 29 +++++++ .../BusinessPartnerGroupFunctionTest.java | 5 +- .../BusinessPartnerGroupStoreTestBase.java | 83 +++++++++++++++++++ 6 files changed, 128 insertions(+), 62 deletions(-) create mode 100644 edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/InMemoryBusinessPartnerGroupStoreTest.java create mode 100644 edc-extensions/business-partner-validation2/src/testFixtures/java/org/eclipse/tractusx/edc/validation/businesspartner/store/BusinessPartnerGroupStoreTestBase.java diff --git a/edc-extensions/business-partner-store-sql/build.gradle.kts b/edc-extensions/business-partner-store-sql/build.gradle.kts index ed51e05dd..a3e570458 100644 --- a/edc-extensions/business-partner-store-sql/build.gradle.kts +++ b/edc-extensions/business-partner-store-sql/build.gradle.kts @@ -34,4 +34,5 @@ dependencies { testImplementation(libs.edc.transaction.local) testImplementation(testFixtures(libs.edc.core.sql)) testImplementation(testFixtures(libs.edc.junit)) + testImplementation(testFixtures(project(":edc-extensions:business-partner-validation2"))) } diff --git a/edc-extensions/business-partner-store-sql/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/SqlBusinessPartnerGroupStoreTest.java b/edc-extensions/business-partner-store-sql/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/SqlBusinessPartnerGroupStoreTest.java index e57cc17cd..647bd3b6e 100644 --- a/edc-extensions/business-partner-store-sql/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/SqlBusinessPartnerGroupStoreTest.java +++ b/edc-extensions/business-partner-store-sql/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/SqlBusinessPartnerGroupStoreTest.java @@ -17,20 +17,18 @@ import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.sql.QueryExecutor; import org.eclipse.edc.sql.testfixtures.PostgresqlStoreSetupExtension; +import org.eclipse.tractusx.edc.validation.businesspartner.spi.BusinessPartnerGroupStore; +import org.eclipse.tractusx.edc.validation.businesspartner.store.BusinessPartnerGroupStoreTestBase; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; @ExtendWith(PostgresqlStoreSetupExtension.class) -class SqlBusinessPartnerGroupStoreTest { +class SqlBusinessPartnerGroupStoreTest extends BusinessPartnerGroupStoreTestBase { private final TypeManager typeManager = new TypeManager(); private final BusinessPartnerGroupStatements statements = new PostgresBusinessPartnerGroupStatements(); private SqlBusinessPartnerGroupStore store; @@ -42,64 +40,13 @@ void setUp(PostgresqlStoreSetupExtension extension, QueryExecutor queryExecutor) extension.runQuery(schema); } - @Test - void resolveForBpn() { - store.save("test-bpn", List.of("group1", "group2", "group3")); - assertThat(store.resolveForBpn("test-bpn").getContent()).containsExactly("group1", "group2", "group3"); - } - - @Test - void resolveForBpn_notExists() { - assertThat(store.resolveForBpn("test-bpn").succeeded()).isFalse(); - } - - @Test - void resolveForBpn_existsNoGroups() { - store.save("test-bpn", List.of()); - assertThat(store.resolveForBpn("test-bpn").getContent()).isNotNull().isEmpty(); - } - - @Test - void save() { - store.save("test-bpn", List.of("group1", "group2", "group3")); - assertThat(store.resolveForBpn("test-bpn").getContent()).containsExactly("group1", "group2", "group3"); - } - - @Test - void save_exists() { - store.save("test-bpn", List.of("group1", "group2", "group3")); - assertThat(store.save("test-bpn", List.of("group4")).succeeded()).isFalse(); - } - - @Test - void delete() { - var businessPartnerNumber = "test-bpn"; - store.save(businessPartnerNumber, List.of("group1", "group2", "group3")); - var delete = store.delete(businessPartnerNumber); - assertThat(delete.succeeded()).withFailMessage(delete::getFailureDetail).isTrue(); - } - - @Test - void delete_notExist() { - var businessPartnerNumber = "test-bpn"; - store.delete(businessPartnerNumber); - assertThat(store.resolveForBpn(businessPartnerNumber).succeeded()).isFalse(); - } - - @Test - void update() { - var businessPartnerNumber = "test-bpn"; - store.save(businessPartnerNumber, List.of("group1", "group2", "group3")); - assertThat(store.update(businessPartnerNumber, List.of("group4", "group5")).succeeded()).isTrue(); - } - - @Test - void update_notExists() { - assertThat(store.update("test-bpn", List.of("foo", "bar")).succeeded()).isFalse(); - } @AfterEach void tearDown(PostgresqlStoreSetupExtension extension) { extension.runQuery("DROP TABLE " + statements.getTable() + " CASCADE"); } + + protected BusinessPartnerGroupStore getStore() { + return store; + } } \ No newline at end of file diff --git a/edc-extensions/business-partner-validation2/build.gradle.kts b/edc-extensions/business-partner-validation2/build.gradle.kts index 6d5b6059a..988b109f1 100644 --- a/edc-extensions/business-partner-validation2/build.gradle.kts +++ b/edc-extensions/business-partner-validation2/build.gradle.kts @@ -20,6 +20,7 @@ plugins { `java-library` `maven-publish` + `java-test-fixtures` } dependencies { @@ -28,4 +29,8 @@ dependencies { implementation(libs.edc.spi.policy) implementation(libs.edc.spi.contract) implementation(libs.edc.spi.policyengine) + + testFixturesImplementation(libs.edc.junit) + testFixturesImplementation(libs.junit.jupiter.api) + testFixturesImplementation(libs.assertj) } diff --git a/edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/InMemoryBusinessPartnerGroupStoreTest.java b/edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/InMemoryBusinessPartnerGroupStoreTest.java new file mode 100644 index 000000000..45cd7d83a --- /dev/null +++ b/edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/InMemoryBusinessPartnerGroupStoreTest.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.tractusx.edc.validation.businesspartner; + +import org.eclipse.tractusx.edc.validation.businesspartner.spi.BusinessPartnerGroupStore; +import org.eclipse.tractusx.edc.validation.businesspartner.store.BusinessPartnerGroupStoreTestBase; + +class InMemoryBusinessPartnerGroupStoreTest extends BusinessPartnerGroupStoreTestBase { + + + private final InMemoryBusinessPartnerGroupStore store = new InMemoryBusinessPartnerGroupStore(); + + @Override + protected BusinessPartnerGroupStore getStore() { + return store; + } +} \ No newline at end of file diff --git a/edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java b/edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java index 6518f7e29..25ae41d14 100644 --- a/edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java +++ b/edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java @@ -20,6 +20,7 @@ import org.eclipse.edc.policy.model.Operator; import org.eclipse.edc.policy.model.Permission; import org.eclipse.edc.spi.agent.ParticipantAgent; +import org.eclipse.edc.spi.result.StoreResult; import org.eclipse.tractusx.edc.validation.businesspartner.spi.BusinessPartnerGroupStore; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -91,7 +92,7 @@ void evaluate_invalidOperator(Operator invalidOperator) { @DisplayName("Right-hand operand is not String or Collection") void evaluate_rightOperandNotStringOrCollection() { when(context.getContextData(eq(ParticipantAgent.class))).thenReturn(new ParticipantAgent(Map.of(REFERRING_CONNECTOR_CLAIM, TEST_BPN), Map.of())); - when(store.resolveForBpn(TEST_BPN)).thenReturn(List.of("test-group")); + when(store.resolveForBpn(TEST_BPN)).thenReturn(StoreResult.success(List.of("test-group"))); assertThat(function.evaluate(EQ, 42, createPermission(EQ, List.of("test-group")), context)).isFalse(); assertThat(function.evaluate(EQ, 42L, createPermission(EQ, List.of("test-group")), context)).isFalse(); @@ -111,7 +112,7 @@ void evaluate_validOperator(String ignored, Operator operator, List assi var allowedGroups = List.of(TEST_GROUP_1, TEST_GROUP_2); when(context.getContextData(eq(ParticipantAgent.class))).thenReturn(new ParticipantAgent(Map.of(REFERRING_CONNECTOR_CLAIM, TEST_BPN), Map.of())); - when(store.resolveForBpn(TEST_BPN)).thenReturn(assignedBpn); + when(store.resolveForBpn(TEST_BPN)).thenReturn(StoreResult.success(assignedBpn)); assertThat(function.evaluate(operator, allowedGroups, createPermission(operator, allowedGroups), context)).isEqualTo(expectedOutcome); } diff --git a/edc-extensions/business-partner-validation2/src/testFixtures/java/org/eclipse/tractusx/edc/validation/businesspartner/store/BusinessPartnerGroupStoreTestBase.java b/edc-extensions/business-partner-validation2/src/testFixtures/java/org/eclipse/tractusx/edc/validation/businesspartner/store/BusinessPartnerGroupStoreTestBase.java new file mode 100644 index 000000000..edf186397 --- /dev/null +++ b/edc-extensions/business-partner-validation2/src/testFixtures/java/org/eclipse/tractusx/edc/validation/businesspartner/store/BusinessPartnerGroupStoreTestBase.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.tractusx.edc.validation.businesspartner.store; + +import org.eclipse.tractusx.edc.validation.businesspartner.spi.BusinessPartnerGroupStore; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public abstract class BusinessPartnerGroupStoreTestBase { + + @Test + void resolveForBpn() { + getStore().save("test-bpn", List.of("group1", "group2", "group3")); + assertThat(getStore().resolveForBpn("test-bpn").getContent()).containsExactly("group1", "group2", "group3"); + } + + @Test + void resolveForBpn_notExists() { + assertThat(getStore().resolveForBpn("test-bpn").succeeded()).isFalse(); + } + + @Test + void resolveForBpn_existsNoGroups() { + getStore().save("test-bpn", List.of()); + assertThat(getStore().resolveForBpn("test-bpn").getContent()).isNotNull().isEmpty(); + } + + @Test + void save() { + getStore().save("test-bpn", List.of("group1", "group2", "group3")); + assertThat(getStore().resolveForBpn("test-bpn").getContent()).containsExactly("group1", "group2", "group3"); + } + + @Test + void save_exists() { + getStore().save("test-bpn", List.of("group1", "group2", "group3")); + assertThat(getStore().save("test-bpn", List.of("group4")).succeeded()).isFalse(); + } + + @Test + void delete() { + var businessPartnerNumber = "test-bpn"; + getStore().save(businessPartnerNumber, List.of("group1", "group2", "group3")); + var delete = getStore().delete(businessPartnerNumber); + assertThat(delete.succeeded()).withFailMessage(delete::getFailureDetail).isTrue(); + } + + @Test + void delete_notExist() { + var businessPartnerNumber = "test-bpn"; + getStore().delete(businessPartnerNumber); + assertThat(getStore().resolveForBpn(businessPartnerNumber).succeeded()).isFalse(); + } + + @Test + void update() { + var businessPartnerNumber = "test-bpn"; + getStore().save(businessPartnerNumber, List.of("group1", "group2", "group3")); + assertThat(getStore().update(businessPartnerNumber, List.of("group4", "group5")).succeeded()).isTrue(); + } + + @Test + void update_notExists() { + assertThat(getStore().update("test-bpn", List.of("foo", "bar")).succeeded()).isFalse(); + } + + protected abstract BusinessPartnerGroupStore getStore(); +} From 3fc11526bb791d8cc288155dc40b0d682db38f85 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger Date: Wed, 2 Aug 2023 19:48:18 +0200 Subject: [PATCH 04/12] revert build --- build.gradle.kts | 7 ++++--- gradle.properties | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index b8d38befa..d0909ae35 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -77,13 +77,14 @@ allprojects { } } - val downloadDir = rootProject.layout.projectDirectory.dir("build/downloads") // configure which version of the annotation processor to use. defaults to the same version as the plugin configure { processorVersion.set(annotationProcessorVersion) outputDirectory.set(project.buildDir) - additionalInputDirectory.set(downloadDir.asFile) - downloadDirectory.set(downloadDir.asFile) + // uncomment the following lines to enable the Autodoc-2-Markdown converter + // only available with EDC 0.2.1 SNAPSHOT + // additionalInputDirectory.set(downloadDir.asFile) + // downloadDirectory.set(downloadDir.asFile) } configure { diff --git a/gradle.properties b/gradle.properties index e4a9c0b39..b5c9b7061 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ group=org.eclipse.tractusx.edc version=0.5.1-SNAPSHOT # configure the build: annotationProcessorVersion=0.2.0 -edcGradlePluginsVersion=0.2.1 +edcGradlePluginsVersion=0.2.0 metaModelVersion=0.2.0 txScmConnection=scm:git:git@github.com:eclipse-tractusx/tractusx-edc.git txWebsiteUrl=https://github.com/eclipse-tractusx/tractusx-edc.git From 5c5ebfe5804a448eac38f5d63bbdd7542dba1c82 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger Date: Wed, 2 Aug 2023 19:52:00 +0200 Subject: [PATCH 05/12] deprecation --- .../businesspartner/BusinessPartnerValidationExtension.java | 3 +++ .../functions/AbstractBusinessPartnerValidation.java | 3 +++ .../businesspartner/functions/BusinessPartnerDutyFunction.java | 1 + .../functions/BusinessPartnerPermissionFunction.java | 1 + .../functions/BusinessPartnerProhibitionFunction.java | 1 + 5 files changed, 9 insertions(+) diff --git a/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerValidationExtension.java b/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerValidationExtension.java index dcb59f789..3eea01011 100644 --- a/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerValidationExtension.java +++ b/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerValidationExtension.java @@ -38,6 +38,7 @@ import static org.eclipse.edc.connector.contract.spi.validation.ContractValidationService.NEGOTIATION_SCOPE; import static org.eclipse.edc.connector.contract.spi.validation.ContractValidationService.TRANSFER_SCOPE; +@Deprecated(forRemoval = true, since = "0.5.0") public class BusinessPartnerValidationExtension implements ServiceExtension { /** @@ -96,6 +97,8 @@ public void initialize(ServiceExtensionContext context) { bindToScope(dutyFunction, permissionFunction, prohibitionFunction, TRANSFER_SCOPE); bindToScope(dutyFunction, permissionFunction, prohibitionFunction, NEGOTIATION_SCOPE); bindToScope(dutyFunction, permissionFunction, prohibitionFunction, CATALOGING_SCOPE); + + monitor.warning("This extension was deprecated and is scheduled for removal in version 0.6.0 of Tractus-X EDC"); } private void bindToScope(BusinessPartnerDutyFunction dutyFunction, BusinessPartnerPermissionFunction permissionFunction, BusinessPartnerProhibitionFunction prohibitionFunction, String scope) { diff --git a/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/AbstractBusinessPartnerValidation.java b/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/AbstractBusinessPartnerValidation.java index c1720edbe..3d97d7eee 100644 --- a/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/AbstractBusinessPartnerValidation.java +++ b/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/AbstractBusinessPartnerValidation.java @@ -35,6 +35,7 @@ * Abstract class for BusinessPartnerNumber validation. This class may be inherited from the EDC * policy enforcing functions for duties, permissions and prohibitions. */ +@Deprecated(forRemoval = true, since = "0.5.0") public abstract class AbstractBusinessPartnerValidation { // Developer Note: @@ -93,6 +94,8 @@ public boolean isLogAgreementEvaluation() { protected boolean evaluate( final Operator operator, final Object rightValue, final PolicyContext policyContext) { + monitor.warning("This policy evaluation function was deprecated and is scheduled for removal in version 0.6.0 of Tractus-X EDC"); + if (policyContext.hasProblems() && !policyContext.getProblems().isEmpty()) { String problems = String.join(", ", policyContext.getProblems()); String message = diff --git a/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerDutyFunction.java b/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerDutyFunction.java index 061d7fd7d..c9219bc09 100644 --- a/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerDutyFunction.java +++ b/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerDutyFunction.java @@ -29,6 +29,7 @@ /** * AtomicConstraintFunction to validate business partner numbers for edc duties. */ +@Deprecated(forRemoval = true, since = "0.5.0") public class BusinessPartnerDutyFunction extends AbstractBusinessPartnerValidation implements AtomicConstraintFunction { diff --git a/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerPermissionFunction.java b/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerPermissionFunction.java index b6713c477..c0c538441 100644 --- a/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerPermissionFunction.java +++ b/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerPermissionFunction.java @@ -29,6 +29,7 @@ /** * AtomicConstraintFunction to validate business partner numbers for edc permissions. */ +@Deprecated(forRemoval = true, since = "0.5.0") public class BusinessPartnerPermissionFunction extends AbstractBusinessPartnerValidation implements AtomicConstraintFunction { diff --git a/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerProhibitionFunction.java b/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerProhibitionFunction.java index 79e318741..4d1382eeb 100644 --- a/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerProhibitionFunction.java +++ b/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerProhibitionFunction.java @@ -29,6 +29,7 @@ /** * AtomicConstraintFunction to validate business partner numbers for edc prohibitions. */ +@Deprecated(forRemoval = true, since = "0.5.0") public class BusinessPartnerProhibitionFunction extends AbstractBusinessPartnerValidation implements AtomicConstraintFunction { From ba838dfc86a48dc29e640f83c7d44db7c49449de Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger Date: Wed, 2 Aug 2023 20:15:54 +0200 Subject: [PATCH 06/12] documentation, cleanup --- .../BusinessPartnerValidationExtension.java | 11 ++-- .../AbstractBusinessPartnerValidation.java | 2 + .../BusinessPartnerDutyFunction.java | 2 + .../BusinessPartnerPermissionFunction.java | 2 + .../BusinessPartnerProhibitionFunction.java | 2 + .../BusinessPartnerEvaluationExtension.java | 18 ++----- .../DefaultStoreProviderExtension.java | 4 +- .../InMemoryBusinessPartnerGroupStore.java | 4 +- .../BusinessPartnerGroupFunction.java | 54 ++++++++++++++----- ...rg.eclipse.edc.spi.system.ServiceExtension | 2 +- ...InMemoryBusinessPartnerGroupStoreTest.java | 1 + .../BusinessPartnerGroupFunctionTest.java | 21 ++++++++ 12 files changed, 86 insertions(+), 37 deletions(-) rename edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/{ => defaults}/DefaultStoreProviderExtension.java (93%) rename edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/{ => defaults}/InMemoryBusinessPartnerGroupStore.java (93%) diff --git a/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerValidationExtension.java b/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerValidationExtension.java index 3eea01011..b9dcf4672 100644 --- a/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerValidationExtension.java +++ b/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerValidationExtension.java @@ -38,14 +38,17 @@ import static org.eclipse.edc.connector.contract.spi.validation.ContractValidationService.NEGOTIATION_SCOPE; import static org.eclipse.edc.connector.contract.spi.validation.ContractValidationService.TRANSFER_SCOPE; +/** + * Business partner number evaluation function. + * + * @deprecated Please use {@code BusinessPartnerEvaluationExtension} instead. + */ @Deprecated(forRemoval = true, since = "0.5.0") public class BusinessPartnerValidationExtension implements ServiceExtension { /** - * The key for business partner numbers constraints. Must be used as left operand when declaring - * constraints. - * - *

Example: + * The key for business partner numbers constraints. Must be used as left operand when declaring constraints. + *

Example: * *

      * {
diff --git a/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/AbstractBusinessPartnerValidation.java b/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/AbstractBusinessPartnerValidation.java
index 3d97d7eee..88609af8f 100644
--- a/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/AbstractBusinessPartnerValidation.java
+++ b/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/AbstractBusinessPartnerValidation.java
@@ -34,6 +34,8 @@
 /**
  * Abstract class for BusinessPartnerNumber validation. This class may be inherited from the EDC
  * policy enforcing functions for duties, permissions and prohibitions.
+ *
+ * @deprecated Please use {@code BusinessPartnerGroupFunction} instead
  */
 @Deprecated(forRemoval = true, since = "0.5.0")
 public abstract class AbstractBusinessPartnerValidation {
diff --git a/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerDutyFunction.java b/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerDutyFunction.java
index c9219bc09..0a4cf74bd 100644
--- a/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerDutyFunction.java
+++ b/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerDutyFunction.java
@@ -28,6 +28,8 @@
 
 /**
  * AtomicConstraintFunction to validate business partner numbers for edc duties.
+ *
+ * @deprecated Please use {@code BusinessPartnerGroupFunction} instead
  */
 @Deprecated(forRemoval = true, since = "0.5.0")
 public class BusinessPartnerDutyFunction extends AbstractBusinessPartnerValidation
diff --git a/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerPermissionFunction.java b/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerPermissionFunction.java
index c0c538441..e2ab43b3a 100644
--- a/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerPermissionFunction.java
+++ b/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerPermissionFunction.java
@@ -28,6 +28,8 @@
 
 /**
  * AtomicConstraintFunction to validate business partner numbers for edc permissions.
+ *
+ * @deprecated Please use {@code BusinessPartnerGroupFunction} instead
  */
 @Deprecated(forRemoval = true, since = "0.5.0")
 public class BusinessPartnerPermissionFunction extends AbstractBusinessPartnerValidation
diff --git a/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerProhibitionFunction.java b/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerProhibitionFunction.java
index 4d1382eeb..d21b44920 100644
--- a/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerProhibitionFunction.java
+++ b/edc-extensions/business-partner-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerProhibitionFunction.java
@@ -28,6 +28,8 @@
 
 /**
  * AtomicConstraintFunction to validate business partner numbers for edc prohibitions.
+ *
+ * @deprecated Please use {@code BusinessPartnerGroupFunction} instead
  */
 @Deprecated(forRemoval = true, since = "0.5.0")
 public class BusinessPartnerProhibitionFunction extends AbstractBusinessPartnerValidation
diff --git a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerEvaluationExtension.java b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerEvaluationExtension.java
index 3035e99e7..316175066 100644
--- a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerEvaluationExtension.java
+++ b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerEvaluationExtension.java
@@ -19,7 +19,6 @@
 import org.eclipse.edc.policy.model.Permission;
 import org.eclipse.edc.runtime.metamodel.annotation.Extension;
 import org.eclipse.edc.runtime.metamodel.annotation.Inject;
-import org.eclipse.edc.runtime.metamodel.annotation.Setting;
 import org.eclipse.edc.spi.system.ServiceExtension;
 import org.eclipse.edc.spi.system.ServiceExtensionContext;
 import org.eclipse.tractusx.edc.validation.businesspartner.functions.BusinessPartnerGroupFunction;
@@ -42,22 +41,18 @@
  * {
  *     "constraint": {
  *         "leftOperand": "BusinessPartnerGroup",
- *         "operator": "{ eq | neq | in | isAllOf | isAnyOf | isNoneOf }",
- *         "rightOperand": ["GROUP_ID1", ... "GROUP_IDN"]
+ *         "operator": "isAnyOf",
+ *         "rightOperand": ["gold_customer","platin_partner"]
  *     }
  * }
  * 
*

- * Note that the {@link BusinessPartnerGroupFunction} is an {@link org.eclipse.edc.policy.engine.spi.AtomicConstraintFunction}, thus it is registered with the {@link PolicyEngine} - * for the {@link Permission} class. + * Note that the {@link BusinessPartnerGroupFunction} is an {@link org.eclipse.edc.policy.engine.spi.AtomicConstraintFunction}, thus it is registered with the {@link PolicyEngine} for the {@link Permission} class. */ @Extension(value = "Registers a function to evaluate whether a BPN number is covered by a certain policy or not", categories = {"policy", "contract"}) public class BusinessPartnerEvaluationExtension implements ServiceExtension { public static final String BUSINESS_PARTNER_CONSTRAINT_KEY = "BusinessPartnerGroup"; - public static final String DEFAULT_LOG_AGREEMENT_EVALUATION = "true"; - @Setting(value = "Enable logging when evaluating the business partner constraints in the agreement validation", type = "boolean", defaultValue = DEFAULT_LOG_AGREEMENT_EVALUATION) - public static final String BUSINESS_PARTNER_VALIDATION_LOG_AGREEMENT_VALIDATION = "tractusx.businesspartnervalidation.log.agreement.validation"; private static final String USE = "USE"; @Inject private RuleBindingRegistry ruleBindingRegistry; @@ -68,8 +63,6 @@ public class BusinessPartnerEvaluationExtension implements ServiceExtension { @Override public void initialize(ServiceExtensionContext context) { - var monitor = context.getMonitor(); - var logAgreementEvaluation = logAgreementEvaluationSetting(context); var function = new BusinessPartnerGroupFunction(store); bindToScope(function, TRANSFER_SCOPE); @@ -83,9 +76,4 @@ private void bindToScope(BusinessPartnerGroupFunction function, String scope) { policyEngine.registerFunction(scope, Permission.class, BUSINESS_PARTNER_CONSTRAINT_KEY, function); } - - private boolean logAgreementEvaluationSetting(ServiceExtensionContext context) { - return Boolean.parseBoolean(context.getSetting(BUSINESS_PARTNER_VALIDATION_LOG_AGREEMENT_VALIDATION, DEFAULT_LOG_AGREEMENT_EVALUATION)); - } - } diff --git a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/DefaultStoreProviderExtension.java b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/defaults/DefaultStoreProviderExtension.java similarity index 93% rename from edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/DefaultStoreProviderExtension.java rename to edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/defaults/DefaultStoreProviderExtension.java index 317703691..91861ad3d 100644 --- a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/DefaultStoreProviderExtension.java +++ b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/defaults/DefaultStoreProviderExtension.java @@ -12,7 +12,7 @@ * */ -package org.eclipse.tractusx.edc.validation.businesspartner; +package org.eclipse.tractusx.edc.validation.businesspartner.defaults; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Provider; @@ -21,7 +21,7 @@ @Extension("Provides a default BusinessPartnerGroupStore") public class DefaultStoreProviderExtension implements ServiceExtension { - + @Provider(isDefault = true) public BusinessPartnerGroupStore createInMemStore() { return new InMemoryBusinessPartnerGroupStore(); diff --git a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/InMemoryBusinessPartnerGroupStore.java b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/defaults/InMemoryBusinessPartnerGroupStore.java similarity index 93% rename from edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/InMemoryBusinessPartnerGroupStore.java rename to edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/defaults/InMemoryBusinessPartnerGroupStore.java index a4ced979d..d6fb4e754 100644 --- a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/InMemoryBusinessPartnerGroupStore.java +++ b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/defaults/InMemoryBusinessPartnerGroupStore.java @@ -12,7 +12,7 @@ * */ -package org.eclipse.tractusx.edc.validation.businesspartner; +package org.eclipse.tractusx.edc.validation.businesspartner.defaults; import org.eclipse.edc.spi.result.StoreResult; import org.eclipse.tractusx.edc.validation.businesspartner.spi.BusinessPartnerGroupStore; @@ -21,7 +21,7 @@ import java.util.List; import java.util.Map; -class InMemoryBusinessPartnerGroupStore implements BusinessPartnerGroupStore { +public class InMemoryBusinessPartnerGroupStore implements BusinessPartnerGroupStore { private final Map> cache = new HashMap<>(); @Override diff --git a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java index 44188305a..5bed93886 100644 --- a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java +++ b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java @@ -58,8 +58,8 @@ *

* The following operators are supported: *

    - *
  • {@link Operator#EQ}: must be exactly in - and only in - that particular group
  • - *
  • {@link Operator#NEQ}: must not be in a particular group
  • + *
  • {@link Operator#EQ}: must be exactly in - and only in - that particular group or set of groups
  • + *
  • {@link Operator#NEQ}: must not be in a particular group or set of groups
  • *
  • {@link Operator#IN}: must be in any of the specified groups
  • *
  • {@link Operator#IS_ALL_OF}: must be in all of the specified groups
  • *
  • {@link Operator#IS_ANY_OF}: must be in any of the specified groups
  • @@ -68,11 +68,10 @@ * * @see BusinessPartnerGroupStore */ - public class BusinessPartnerGroupFunction implements AtomicConstraintFunction { public static final String REFERRING_CONNECTOR_CLAIM = "referringConnector"; private static final List ALLOWED_OPERATORS = List.of(EQ, NEQ, IN, IS_ALL_OF, IS_ANY_OF, IS_NONE_OF); - private static final Map> OPERATOR_EVALUATOR_MAP = new HashMap<>(); + private static final Map> OPERATOR_EVALUATOR_MAP = new HashMap<>(); private final BusinessPartnerGroupStore store; public BusinessPartnerGroupFunction(BusinessPartnerGroupStore store) { @@ -86,33 +85,59 @@ public BusinessPartnerGroupFunction(BusinessPartnerGroupStore store) { } + /** + * Policy evaluation function that checks whether a given BusinessPartnerNumber is covered by a given policy. + * The evaluation is prematurely aborted (returns {@code false}) if: + *
      + *
    • No {@link ParticipantAgent} was found on the {@link PolicyContext}
    • + *
    • The operator is invalid. Check {@link BusinessPartnerGroupFunction#ALLOWED_OPERATORS} for valid operators.
    • + *
    • No database entry was found for the BPN (taken from the {@link ParticipantAgent})
    • + *
    • A database entry was found, but no group-IDs were assigned
    • + *
    • The right value is anything other than {@link String} or {@link Collection}
    • + *
    + */ @Override public boolean evaluate(Operator operator, Object rightValue, Permission rule, PolicyContext policyContext) { final ParticipantAgent participantAgent = policyContext.getContextData(ParticipantAgent.class); + // No participant agent found in context if (participantAgent == null) { policyContext.reportProblem("ParticipantAgent not found on PolicyContext"); return false; } + + // invalid operator if (!ALLOWED_OPERATORS.contains(operator)) { var ops = ALLOWED_OPERATORS.stream().map(Enum::name).collect(Collectors.joining(", ")); policyContext.reportProblem(format("Operator must be one of [%s] but was [%s]", ops, operator.name())); return false; } + var bpn = getBpnClaim(participantAgent); var groups = store.resolveForBpn(bpn); + + // BPN not found in database if (groups.failed()) { policyContext.reportProblem(groups.getFailureDetail()); return false; } + var assignedGroups = groups.getContent(); + + // BPN was found, but it does not have groups assigned. + if (assignedGroups.isEmpty()) { + policyContext.reportProblem("No groups were assigned to BPN " + bpn); + return false; + } + // right-operand is anything other than String or Collection var rightOperand = parseRightOperand(rightValue, policyContext); if (rightOperand == null) { return false; } - return OPERATOR_EVALUATOR_MAP.get(operator).apply(new BpnGroupTuple(groups.getContent(), rightOperand)); + //call evaluator function + return OPERATOR_EVALUATOR_MAP.get(operator).apply(new BpnGroupHolder(assignedGroups, rightOperand)); } private List parseRightOperand(Object rightValue, PolicyContext context) { @@ -142,23 +167,26 @@ private String getBpnClaim(ParticipantAgent participantAgent) { return bpnClaim; } - private Boolean evaluateIn(BpnGroupTuple bpnGroupTuple) { - var assigned = bpnGroupTuple.assignedGroups; + private Boolean evaluateIn(BpnGroupHolder bpnGroupHolder) { + var assigned = bpnGroupHolder.assignedGroups; // checks whether both lists overlap - return bpnGroupTuple.allowedGroups + return bpnGroupHolder.allowedGroups .stream() .distinct() .anyMatch(assigned::contains); } - private Boolean evaluateNotEquals(BpnGroupTuple bpnGroupTuple) { - return !evaluateIn(bpnGroupTuple); + private Boolean evaluateNotEquals(BpnGroupHolder bpnGroupHolder) { + return !evaluateIn(bpnGroupHolder); } - private Boolean evaluateEquals(BpnGroupTuple bpnGroupTuple) { - return bpnGroupTuple.allowedGroups.equals(bpnGroupTuple.assignedGroups); + private Boolean evaluateEquals(BpnGroupHolder bpnGroupHolder) { + return bpnGroupHolder.allowedGroups.equals(bpnGroupHolder.assignedGroups); } - private record BpnGroupTuple(List assignedGroups, List allowedGroups) { + /** + * Internal utility class to hold the list of assigned groups for a BPN, and the list of groups specified in the policy ("allowed groups"). + */ + private record BpnGroupHolder(List assignedGroups, List allowedGroups) { } } diff --git a/edc-extensions/business-partner-validation2/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/business-partner-validation2/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension index 6b704afe6..d16eb96eb 100644 --- a/edc-extensions/business-partner-validation2/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ b/edc-extensions/business-partner-validation2/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -18,4 +18,4 @@ # SPDX-License-Identifier: Apache-2.0 # org.eclipse.tractusx.edc.validation.businesspartner.BusinessPartnerEvaluationExtension -org.eclipse.tractusx.edc.validation.businesspartner.DefaultStoreProviderExtension +org.eclipse.tractusx.edc.validation.businesspartner.defaults.DefaultStoreProviderExtension diff --git a/edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/InMemoryBusinessPartnerGroupStoreTest.java b/edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/InMemoryBusinessPartnerGroupStoreTest.java index 45cd7d83a..508172285 100644 --- a/edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/InMemoryBusinessPartnerGroupStoreTest.java +++ b/edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/InMemoryBusinessPartnerGroupStoreTest.java @@ -14,6 +14,7 @@ package org.eclipse.tractusx.edc.validation.businesspartner; +import org.eclipse.tractusx.edc.validation.businesspartner.defaults.InMemoryBusinessPartnerGroupStore; import org.eclipse.tractusx.edc.validation.businesspartner.spi.BusinessPartnerGroupStore; import org.eclipse.tractusx.edc.validation.businesspartner.store.BusinessPartnerGroupStoreTestBase; diff --git a/edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java b/edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java index 25ae41d14..99e221eed 100644 --- a/edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java +++ b/edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java @@ -31,6 +31,7 @@ import org.junit.jupiter.params.provider.ArgumentsProvider; import org.junit.jupiter.params.provider.ArgumentsSource; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.stream.Stream; @@ -116,6 +117,26 @@ void evaluate_validOperator(String ignored, Operator operator, List assi assertThat(function.evaluate(operator, allowedGroups, createPermission(operator, allowedGroups), context)).isEqualTo(expectedOutcome); } + @Test + void evaluate_noEntryForBpn() { + var operator = NEQ; + var allowedGroups = List.of(TEST_GROUP_1, TEST_GROUP_2); + when(context.getContextData(eq(ParticipantAgent.class))).thenReturn(new ParticipantAgent(Map.of(REFERRING_CONNECTOR_CLAIM, TEST_BPN), Map.of())); + when(store.resolveForBpn(TEST_BPN)).thenReturn(StoreResult.notFound("foobar")); + + assertThat(function.evaluate(operator, allowedGroups, createPermission(operator, allowedGroups), context)).isFalse(); + } + + @Test + void evaluate_noGroupsAssignedToBpn() { + var operator = NEQ; + var allowedGroups = List.of(TEST_GROUP_1, TEST_GROUP_2); + when(context.getContextData(eq(ParticipantAgent.class))).thenReturn(new ParticipantAgent(Map.of(REFERRING_CONNECTOR_CLAIM, TEST_BPN), Map.of())); + when(store.resolveForBpn(TEST_BPN)).thenReturn(StoreResult.success(Collections.emptyList())); + + assertThat(function.evaluate(operator, allowedGroups, createPermission(operator, allowedGroups), context)).isFalse(); + } + private Permission createPermission(Operator op, List rightOperand) { return Permission.Builder.newInstance() .constraint(AtomicConstraint.Builder.newInstance() From 4fbc2156b474e9f00911f87f639be5b141e430e0 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger Date: Thu, 3 Aug 2023 07:39:35 +0200 Subject: [PATCH 07/12] cleanup --- .../docs/schema.sql | 2 +- .../sql/SqlBusinessPartnerGroupStore.java | 8 ++++---- .../InMemoryBusinessPartnerGroupStore.java | 8 ++++---- .../spi/BusinessPartnerGroup.java | 20 ------------------- .../spi/BusinessPartnerGroupStore.java | 3 +++ 5 files changed, 12 insertions(+), 29 deletions(-) delete mode 100644 edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroup.java diff --git a/edc-extensions/business-partner-store-sql/docs/schema.sql b/edc-extensions/business-partner-store-sql/docs/schema.sql index 77be07c48..29cf1e232 100644 --- a/edc-extensions/business-partner-store-sql/docs/schema.sql +++ b/edc-extensions/business-partner-store-sql/docs/schema.sql @@ -12,7 +12,7 @@ -- -CREATE TABLE public.edc_business_partner_group +CREATE TABLE edc_business_partner_group ( bpn VARCHAR NOT NULL CONSTRAINT edc_business_partner_group_pk diff --git a/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/SqlBusinessPartnerGroupStore.java b/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/SqlBusinessPartnerGroupStore.java index 04b29171d..0a9a5e235 100644 --- a/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/SqlBusinessPartnerGroupStore.java +++ b/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/SqlBusinessPartnerGroupStore.java @@ -49,7 +49,7 @@ public StoreResult> resolveForBpn(String businessPartnerNumber) { var sql = statements.findByBpnTemplate(); var list = queryExecutor.single(connection, true, this::mapJson, sql, businessPartnerNumber); return list == null ? - StoreResult.notFound("BPN " + businessPartnerNumber + " was not found") : + StoreResult.notFound(NOT_FOUND_TEMPLATE.formatted(businessPartnerNumber)) : StoreResult.success(list); } catch (SQLException e) { throw new EdcPersistenceException(e); @@ -63,7 +63,7 @@ public StoreResult save(String businessPartnerNumber, List groups) return transactionContext.execute(() -> { try (var connection = getConnection()) { if (exists(businessPartnerNumber, connection)) { - return StoreResult.alreadyExists("BPN " + businessPartnerNumber + " already exists in database"); + return StoreResult.alreadyExists(ALREADY_EXISTS_TEMPLATE.formatted(businessPartnerNumber)); } var sql = statements.insertTemplate(); queryExecutor.execute(connection, sql, businessPartnerNumber, toJson(groups)); @@ -81,7 +81,7 @@ public StoreResult delete(String businessPartnerNumber) { return transactionContext.execute(() -> { try (var connection = getConnection()) { if (!exists(businessPartnerNumber, connection)) { - return StoreResult.notFound("BPN " + businessPartnerNumber + " was not found"); + return StoreResult.notFound(NOT_FOUND_TEMPLATE.formatted(businessPartnerNumber)); } var sql = statements.deleteTemplate(); queryExecutor.execute(connection, sql, businessPartnerNumber); @@ -98,7 +98,7 @@ public StoreResult update(String businessPartnerNumber, List group return transactionContext.execute(() -> { try (var connection = getConnection()) { if (!exists(businessPartnerNumber, connection)) { - return StoreResult.notFound("BPN " + businessPartnerNumber + " was not found"); + return StoreResult.notFound(NOT_FOUND_TEMPLATE.formatted(businessPartnerNumber)); } var sql = statements.updateTemplate(); queryExecutor.execute(connection, sql, toJson(groups), businessPartnerNumber); diff --git a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/defaults/InMemoryBusinessPartnerGroupStore.java b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/defaults/InMemoryBusinessPartnerGroupStore.java index d6fb4e754..556bff402 100644 --- a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/defaults/InMemoryBusinessPartnerGroupStore.java +++ b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/defaults/InMemoryBusinessPartnerGroupStore.java @@ -28,7 +28,7 @@ public class InMemoryBusinessPartnerGroupStore implements BusinessPartnerGroupSt public StoreResult> resolveForBpn(String businessPartnerNumber) { var entry = cache.get(businessPartnerNumber); return entry == null ? - StoreResult.notFound("BPN " + businessPartnerNumber + " was not found in database") : + StoreResult.notFound(NOT_FOUND_TEMPLATE.formatted(businessPartnerNumber)) : StoreResult.success(entry); } @@ -36,7 +36,7 @@ public StoreResult> resolveForBpn(String businessPartnerNumber) { public StoreResult save(String businessPartnerNumber, List groups) { //to maintain behavioural consistency with the SQL store if (cache.containsKey(businessPartnerNumber)) { - return StoreResult.alreadyExists("BPN " + businessPartnerNumber + " already exists in database"); + return StoreResult.alreadyExists(ALREADY_EXISTS_TEMPLATE.formatted(businessPartnerNumber)); } cache.put(businessPartnerNumber, groups); return StoreResult.success(); @@ -46,7 +46,7 @@ public StoreResult save(String businessPartnerNumber, List groups) public StoreResult delete(String businessPartnerNumber) { return cache.remove(businessPartnerNumber) == null ? - StoreResult.notFound("BPN " + businessPartnerNumber + " was not found in database") : + StoreResult.notFound(NOT_FOUND_TEMPLATE.formatted(businessPartnerNumber)) : StoreResult.success(); } @@ -56,6 +56,6 @@ public StoreResult update(String businessPartnerNumber, List group cache.put(businessPartnerNumber, groups); return StoreResult.success(); } - return StoreResult.notFound("BPN " + businessPartnerNumber + " was not found in database"); + return StoreResult.notFound(NOT_FOUND_TEMPLATE.formatted(businessPartnerNumber)); } } diff --git a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroup.java b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroup.java deleted file mode 100644 index 9177b8495..000000000 --- a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroup.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - * - * Contributors: - * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation - * - */ - -package org.eclipse.tractusx.edc.validation.businesspartner.spi; - -import java.util.List; - -public record BusinessPartnerGroup(String groupId, String groupName, List bpns) { -} diff --git a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroupStore.java b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroupStore.java index de9338b7f..c95dee513 100644 --- a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroupStore.java +++ b/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroupStore.java @@ -19,6 +19,9 @@ import java.util.List; public interface BusinessPartnerGroupStore { + String NOT_FOUND_TEMPLATE = "BPN %s was not found"; + String ALREADY_EXISTS_TEMPLATE = "BPN %s already exists in database"; + StoreResult> resolveForBpn(String businessPartnerNumber); StoreResult save(String businessPartnerNumber, List groups); From f797b28dc6ac7b98f9da996322cb0892cdbcadb0 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger Date: Thu, 3 Aug 2023 07:44:54 +0200 Subject: [PATCH 08/12] added migration --- .../docs/schema.sql | 2 -- ...sinessGroupPostgresMigrationExtension.java | 32 +++++++++++++++++++ ...rg.eclipse.edc.spi.system.ServiceExtension | 1 + .../V0_0_1__Init_BusinessGroup_Schema.sql | 21 ++++++++++++ 4 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/BusinessGroupPostgresMigrationExtension.java create mode 100644 edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/businessgroup/V0_0_1__Init_BusinessGroup_Schema.sql diff --git a/edc-extensions/business-partner-store-sql/docs/schema.sql b/edc-extensions/business-partner-store-sql/docs/schema.sql index 29cf1e232..aa7b7a08f 100644 --- a/edc-extensions/business-partner-store-sql/docs/schema.sql +++ b/edc-extensions/business-partner-store-sql/docs/schema.sql @@ -19,5 +19,3 @@ CREATE TABLE edc_business_partner_group PRIMARY KEY, groups JSON DEFAULT '[]'::JSON NOT NULL ); - - diff --git a/edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/BusinessGroupPostgresMigrationExtension.java b/edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/BusinessGroupPostgresMigrationExtension.java new file mode 100644 index 000000000..91125a930 --- /dev/null +++ b/edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/BusinessGroupPostgresMigrationExtension.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.tractusx.edc.postgresql.migration; + +import org.eclipse.edc.connector.store.sql.assetindex.ConfigurationKeys; + +public class BusinessGroupPostgresMigrationExtension extends AbstractPostgresqlMigrationExtension { + private static final String NAME = "businessgroup"; + + + @Override + protected String getDataSourceNameConfigurationKey() { + return ConfigurationKeys.DATASOURCE_SETTING_NAME; + } + + @Override + protected String getSubsystemName() { + return NAME; + } +} diff --git a/edc-extensions/postgresql-migration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/postgresql-migration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension index a641ec766..9acab3b4d 100644 --- a/edc-extensions/postgresql-migration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ b/edc-extensions/postgresql-migration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -23,3 +23,4 @@ org.eclipse.tractusx.edc.postgresql.migration.ContractNegotiationPostgresqlMigra org.eclipse.tractusx.edc.postgresql.migration.PolicyPostgresqlMigrationExtension org.eclipse.tractusx.edc.postgresql.migration.TransferProcessPostgresqlMigrationExtension org.eclipse.tractusx.edc.postgresql.migration.EdrPostgresqlMigrationExtension +org.eclipse.tractusx.edc.postgresql.migration.BusinessGroupPostgresMigrationExtension diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/businessgroup/V0_0_1__Init_BusinessGroup_Schema.sql b/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/businessgroup/V0_0_1__Init_BusinessGroup_Schema.sql new file mode 100644 index 000000000..aa7b7a08f --- /dev/null +++ b/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/businessgroup/V0_0_1__Init_BusinessGroup_Schema.sql @@ -0,0 +1,21 @@ +-- +-- Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +-- +-- This program and the accompanying materials are made available under the +-- terms of the Apache License, Version 2.0 which is available at +-- https://www.apache.org/licenses/LICENSE-2.0 +-- +-- SPDX-License-Identifier: Apache-2.0 +-- +-- Contributors: +-- Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation +-- + + +CREATE TABLE edc_business_partner_group +( + bpn VARCHAR NOT NULL + CONSTRAINT edc_business_partner_group_pk + PRIMARY KEY, + groups JSON DEFAULT '[]'::JSON NOT NULL +); From b8af25509c79878415193ea9d5881b309066bcf0 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger Date: Thu, 3 Aug 2023 09:06:40 +0200 Subject: [PATCH 09/12] renamed extension --- .../build.gradle.kts | 0 .../businesspartner/BusinessPartnerEvaluationExtension.java | 0 .../defaults/DefaultStoreProviderExtension.java | 0 .../defaults/InMemoryBusinessPartnerGroupStore.java | 0 .../functions/BusinessPartnerGroupFunction.java | 0 .../businesspartner/spi/BusinessPartnerGroupStore.java | 0 .../services/org.eclipse.edc.spi.system.ServiceExtension | 0 .../InMemoryBusinessPartnerGroupStoreTest.java | 0 .../functions/BusinessPartnerGroupFunctionTest.java | 0 .../store/BusinessPartnerGroupStoreTestBase.java | 0 edc-extensions/business-partner-store-sql/build.gradle.kts | 4 ++-- settings.gradle.kts | 2 +- 12 files changed, 3 insertions(+), 3 deletions(-) rename edc-extensions/{business-partner-validation2 => bpn-validation}/build.gradle.kts (100%) rename edc-extensions/{business-partner-validation2 => bpn-validation}/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerEvaluationExtension.java (100%) rename edc-extensions/{business-partner-validation2 => bpn-validation}/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/defaults/DefaultStoreProviderExtension.java (100%) rename edc-extensions/{business-partner-validation2 => bpn-validation}/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/defaults/InMemoryBusinessPartnerGroupStore.java (100%) rename edc-extensions/{business-partner-validation2 => bpn-validation}/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java (100%) rename edc-extensions/{business-partner-validation2 => bpn-validation}/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroupStore.java (100%) rename edc-extensions/{business-partner-validation2 => bpn-validation}/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension (100%) rename edc-extensions/{business-partner-validation2 => bpn-validation}/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/InMemoryBusinessPartnerGroupStoreTest.java (100%) rename edc-extensions/{business-partner-validation2 => bpn-validation}/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java (100%) rename edc-extensions/{business-partner-validation2 => bpn-validation}/src/testFixtures/java/org/eclipse/tractusx/edc/validation/businesspartner/store/BusinessPartnerGroupStoreTestBase.java (100%) diff --git a/edc-extensions/business-partner-validation2/build.gradle.kts b/edc-extensions/bpn-validation/build.gradle.kts similarity index 100% rename from edc-extensions/business-partner-validation2/build.gradle.kts rename to edc-extensions/bpn-validation/build.gradle.kts diff --git a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerEvaluationExtension.java b/edc-extensions/bpn-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerEvaluationExtension.java similarity index 100% rename from edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerEvaluationExtension.java rename to edc-extensions/bpn-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerEvaluationExtension.java diff --git a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/defaults/DefaultStoreProviderExtension.java b/edc-extensions/bpn-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/defaults/DefaultStoreProviderExtension.java similarity index 100% rename from edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/defaults/DefaultStoreProviderExtension.java rename to edc-extensions/bpn-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/defaults/DefaultStoreProviderExtension.java diff --git a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/defaults/InMemoryBusinessPartnerGroupStore.java b/edc-extensions/bpn-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/defaults/InMemoryBusinessPartnerGroupStore.java similarity index 100% rename from edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/defaults/InMemoryBusinessPartnerGroupStore.java rename to edc-extensions/bpn-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/defaults/InMemoryBusinessPartnerGroupStore.java diff --git a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java b/edc-extensions/bpn-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java similarity index 100% rename from edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java rename to edc-extensions/bpn-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java diff --git a/edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroupStore.java b/edc-extensions/bpn-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroupStore.java similarity index 100% rename from edc-extensions/business-partner-validation2/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroupStore.java rename to edc-extensions/bpn-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/spi/BusinessPartnerGroupStore.java diff --git a/edc-extensions/business-partner-validation2/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/bpn-validation/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension similarity index 100% rename from edc-extensions/business-partner-validation2/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension rename to edc-extensions/bpn-validation/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension diff --git a/edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/InMemoryBusinessPartnerGroupStoreTest.java b/edc-extensions/bpn-validation/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/InMemoryBusinessPartnerGroupStoreTest.java similarity index 100% rename from edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/InMemoryBusinessPartnerGroupStoreTest.java rename to edc-extensions/bpn-validation/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/InMemoryBusinessPartnerGroupStoreTest.java diff --git a/edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java b/edc-extensions/bpn-validation/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java similarity index 100% rename from edc-extensions/business-partner-validation2/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java rename to edc-extensions/bpn-validation/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java diff --git a/edc-extensions/business-partner-validation2/src/testFixtures/java/org/eclipse/tractusx/edc/validation/businesspartner/store/BusinessPartnerGroupStoreTestBase.java b/edc-extensions/bpn-validation/src/testFixtures/java/org/eclipse/tractusx/edc/validation/businesspartner/store/BusinessPartnerGroupStoreTestBase.java similarity index 100% rename from edc-extensions/business-partner-validation2/src/testFixtures/java/org/eclipse/tractusx/edc/validation/businesspartner/store/BusinessPartnerGroupStoreTestBase.java rename to edc-extensions/bpn-validation/src/testFixtures/java/org/eclipse/tractusx/edc/validation/businesspartner/store/BusinessPartnerGroupStoreTestBase.java diff --git a/edc-extensions/business-partner-store-sql/build.gradle.kts b/edc-extensions/business-partner-store-sql/build.gradle.kts index a3e570458..ffa1bd242 100644 --- a/edc-extensions/business-partner-store-sql/build.gradle.kts +++ b/edc-extensions/business-partner-store-sql/build.gradle.kts @@ -23,7 +23,7 @@ plugins { } dependencies { - implementation(project(":edc-extensions:business-partner-validation2")) + implementation(project(":edc-extensions:bpn-validation")) implementation(libs.edc.spi.core) implementation(libs.edc.spi.transaction.datasource) @@ -34,5 +34,5 @@ dependencies { testImplementation(libs.edc.transaction.local) testImplementation(testFixtures(libs.edc.core.sql)) testImplementation(testFixtures(libs.edc.junit)) - testImplementation(testFixtures(project(":edc-extensions:business-partner-validation2"))) + testImplementation(testFixtures(project(":edc-extensions:bpn-validation"))) } diff --git a/settings.gradle.kts b/settings.gradle.kts index 01e22260b..92dffb46c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -33,7 +33,7 @@ include(":core:json-ld-core") include(":edc-extensions:business-partner-validation") -include(":edc-extensions:business-partner-validation2") +include(":edc-extensions:bpn-validation") include(":edc-extensions:business-partner-store-sql") include(":edc-extensions:cx-oauth2") include(":edc-extensions:data-encryption") From 6d8a223b196ce300b16e83c35226614213d45e5d Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger Date: Thu, 3 Aug 2023 09:14:59 +0200 Subject: [PATCH 10/12] pr remarks --- .../BusinessPartnerEvaluationExtension.java | 9 ++++----- .../functions/BusinessPartnerGroupFunction.java | 4 +++- .../functions/BusinessPartnerGroupFunctionTest.java | 2 +- .../store/sql/BusinessPartnerGroupStatements.java | 3 +++ .../sql/PostgresBusinessPartnerGroupStatements.java | 5 ++++- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/edc-extensions/bpn-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerEvaluationExtension.java b/edc-extensions/bpn-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerEvaluationExtension.java index 316175066..e60d5e04f 100644 --- a/edc-extensions/bpn-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerEvaluationExtension.java +++ b/edc-extensions/bpn-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerEvaluationExtension.java @@ -35,12 +35,12 @@ *
  • {@link org.eclipse.edc.connector.contract.spi.validation.ContractValidationService#NEGOTIATION_SCOPE}
  • *
  • {@link org.eclipse.edc.connector.contract.spi.validation.ContractValidationService#TRANSFER_SCOPE}
  • *
- * The rule to which the function is bound is {@link BusinessPartnerEvaluationExtension#BUSINESS_PARTNER_CONSTRAINT_KEY}. That means, that policies that are bound to these scopes look + * The rule to which the function is bound is {@link BusinessPartnerGroupFunction#BUSINESS_PARTNER_CONSTRAINT_KEY}. That means, that policies that are bound to these scopes look * like this: *
  * {
  *     "constraint": {
- *         "leftOperand": "BusinessPartnerGroup",
+ *         "leftOperand": "https://w3id.org/tractusx/v0.0.1/ns/BusinessPartnerGroup",
  *         "operator": "isAnyOf",
  *         "rightOperand": ["gold_customer","platin_partner"]
  *     }
@@ -52,7 +52,6 @@
 @Extension(value = "Registers a function to evaluate whether a BPN number is covered by a certain policy or not", categories = {"policy", "contract"})
 public class BusinessPartnerEvaluationExtension implements ServiceExtension {
 
-    public static final String BUSINESS_PARTNER_CONSTRAINT_KEY = "BusinessPartnerGroup";
     private static final String USE = "USE";
     @Inject
     private RuleBindingRegistry ruleBindingRegistry;
@@ -72,8 +71,8 @@ public void initialize(ServiceExtensionContext context) {
 
     private void bindToScope(BusinessPartnerGroupFunction function, String scope) {
         ruleBindingRegistry.bind(USE, scope);
-        ruleBindingRegistry.bind(BUSINESS_PARTNER_CONSTRAINT_KEY, scope);
+        ruleBindingRegistry.bind(BusinessPartnerGroupFunction.BUSINESS_PARTNER_CONSTRAINT_KEY, scope);
 
-        policyEngine.registerFunction(scope, Permission.class, BUSINESS_PARTNER_CONSTRAINT_KEY, function);
+        policyEngine.registerFunction(scope, Permission.class, BusinessPartnerGroupFunction.BUSINESS_PARTNER_CONSTRAINT_KEY, function);
     }
 }
diff --git a/edc-extensions/bpn-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java b/edc-extensions/bpn-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java
index 5bed93886..012ec1371 100644
--- a/edc-extensions/bpn-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java
+++ b/edc-extensions/bpn-validation/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java
@@ -35,6 +35,7 @@
 import static org.eclipse.edc.policy.model.Operator.IS_ANY_OF;
 import static org.eclipse.edc.policy.model.Operator.IS_NONE_OF;
 import static org.eclipse.edc.policy.model.Operator.NEQ;
+import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE;
 
 /**
  * This function evaluates, that a particular {@link ParticipantAgent} is a member of a particular group.
@@ -46,7 +47,7 @@
  * 
  * {
  *     "constraint": {
- *         "leftOperand": "BusinessPartnerGroup",
+ *         "leftOperand": "https://w3id.org/tractusx/v0.0.1/ns/BusinessPartnerGroup",
  *         "operator": "isAnyOf",
  *         "rightOperand": ["gold_customer","platin_partner"]
  *     }
@@ -70,6 +71,7 @@
  */
 public class BusinessPartnerGroupFunction implements AtomicConstraintFunction {
     public static final String REFERRING_CONNECTOR_CLAIM = "referringConnector";
+    public static final String BUSINESS_PARTNER_CONSTRAINT_KEY = TX_NAMESPACE + "BusinessPartnerGroup";
     private static final List ALLOWED_OPERATORS = List.of(EQ, NEQ, IN, IS_ALL_OF, IS_ANY_OF, IS_NONE_OF);
     private static final Map> OPERATOR_EVALUATOR_MAP = new HashMap<>();
     private final BusinessPartnerGroupStore store;
diff --git a/edc-extensions/bpn-validation/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java b/edc-extensions/bpn-validation/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java
index 99e221eed..e317ec1b2 100644
--- a/edc-extensions/bpn-validation/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java
+++ b/edc-extensions/bpn-validation/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java
@@ -48,7 +48,7 @@
 import static org.eclipse.edc.policy.model.Operator.LEQ;
 import static org.eclipse.edc.policy.model.Operator.LT;
 import static org.eclipse.edc.policy.model.Operator.NEQ;
-import static org.eclipse.tractusx.edc.validation.businesspartner.BusinessPartnerEvaluationExtension.BUSINESS_PARTNER_CONSTRAINT_KEY;
+import static org.eclipse.tractusx.edc.validation.businesspartner.functions.BusinessPartnerGroupFunction.BUSINESS_PARTNER_CONSTRAINT_KEY;
 import static org.eclipse.tractusx.edc.validation.businesspartner.functions.BusinessPartnerGroupFunction.REFERRING_CONNECTOR_CLAIM;
 import static org.mockito.ArgumentMatchers.endsWith;
 import static org.mockito.ArgumentMatchers.eq;
diff --git a/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/BusinessPartnerGroupStatements.java b/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/BusinessPartnerGroupStatements.java
index 83eecad3a..08171a887 100644
--- a/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/BusinessPartnerGroupStatements.java
+++ b/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/BusinessPartnerGroupStatements.java
@@ -14,6 +14,9 @@
 
 package org.eclipse.tractusx.edc.validation.businesspartner.store.sql;
 
+/**
+ * Statement templates and SQL table+column names required for the {@link SqlBusinessPartnerGroupStore}
+ */
 public interface BusinessPartnerGroupStatements {
 
     default String getBpnColumn() {
diff --git a/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/PostgresBusinessPartnerGroupStatements.java b/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/PostgresBusinessPartnerGroupStatements.java
index 4d8961de4..37ba72377 100644
--- a/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/PostgresBusinessPartnerGroupStatements.java
+++ b/edc-extensions/business-partner-store-sql/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/PostgresBusinessPartnerGroupStatements.java
@@ -19,6 +19,9 @@
 
 import static java.lang.String.format;
 
+/**
+ * Postgres-specific statement templates for the {@link SqlBusinessPartnerGroupStore}
+ */
 public class PostgresBusinessPartnerGroupStatements implements BusinessPartnerGroupStatements {
     @Override
     public String findByBpnTemplate() {
@@ -44,7 +47,7 @@ public String countQuery() {
     public String updateTemplate() {
         return format("UPDATE %s SET %s=?%s WHERE %s=?", getTable(), getGroupsColumn(), getFormatJsonOperator(), getBpnColumn());
     }
-    
+
     @NotNull
     private String getFormatJsonOperator() {
         return PostgresDialect.getJsonCastOperator();

From bcfd0b770756266ffb518df3bd7a7eae1e33f3c0 Mon Sep 17 00:00:00 2001
From: Paul Latzelsperger 
Date: Thu, 3 Aug 2023 09:58:54 +0200
Subject: [PATCH 11/12] add D-R

---
 .../README.md                                 | 42 +++++++++++++++++++
 1 file changed, 42 insertions(+)
 create mode 100644 docs/development/decision-records/2023-08-03_improve_bpn_validation/README.md

diff --git a/docs/development/decision-records/2023-08-03_improve_bpn_validation/README.md b/docs/development/decision-records/2023-08-03_improve_bpn_validation/README.md
new file mode 100644
index 000000000..4f8f35423
--- /dev/null
+++ b/docs/development/decision-records/2023-08-03_improve_bpn_validation/README.md
@@ -0,0 +1,42 @@
+# Removal of manually curated CHANGELOG.md
+
+## Decision
+
+The BPN validation extension will be improved in the following aspects:
+
+1. Instead of hard-coding them on policies, BPNs are stored in a database (in-mem + Postgres)
+2. BPNs are grouped to enable stable policies
+3. More `Operator`s are supported
+4. Database entries can be manipulated using a REST API
+
+## Rationale
+
+Hard-coding BPNs on policies is quite inflexible and does not scale, because when a new business partner joins or leaves
+the network, all participants would have to update all their policies, which is a significant migration effort. Instead,
+a structure has to be defined where that situation can be handled in a less intrusive and involved way. This effectively
+will remove the need to update/migrate policies.
+
+## Approach
+
+Every BPN is associated with one or more groups, for example `BPN0000001` -> `["gold_member"]`. It is important to note,
+that these groups are _internal_ tags that every participant maintains on their own, they are not claims in
+VerifiableCredentials (the BPN would be a claim, however). A new policy constraint is introduced, that looks like this:
+
+```json
+{
+  "constraint": {
+    "leftOperand": "https://w3id.org/tractusx/v0.0.1/ns/BusinessPartnerGroup",
+    "operator": "isAnyOf",
+    "rightOperand": [
+      "gold_customer",
+      "platin_partner"
+    ]
+  }
+}
+```
+
+NB: the `leftOperand` must be an IRI as mandated by ODRL, thus it must either be prefixed with the namespace (as shown
+in the example), or using a vocabulary entry in the JSON-LD context, i.e. `tx:BusinessPartnerGroup`. Supported operators
+will be: `eq, neq, in, isAllOf, isAnyOf, isNoneOf`.
+
+Manipulating the BPN -> group associations can be done through a REST API.
\ No newline at end of file

From 79e82a894644811766b271ed98ac42522b175e5e Mon Sep 17 00:00:00 2001
From: Paul Latzelsperger 
Date: Thu, 3 Aug 2023 10:04:56 +0200
Subject: [PATCH 12/12] md lint

---
 .../2023-08-03_improve_bpn_validation/README.md                 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/development/decision-records/2023-08-03_improve_bpn_validation/README.md b/docs/development/decision-records/2023-08-03_improve_bpn_validation/README.md
index 4f8f35423..930789f27 100644
--- a/docs/development/decision-records/2023-08-03_improve_bpn_validation/README.md
+++ b/docs/development/decision-records/2023-08-03_improve_bpn_validation/README.md
@@ -39,4 +39,4 @@ NB: the `leftOperand` must be an IRI as mandated by ODRL, thus it must either be
 in the example), or using a vocabulary entry in the JSON-LD context, i.e. `tx:BusinessPartnerGroup`. Supported operators
 will be: `eq, neq, in, isAllOf, isAnyOf, isNoneOf`.
 
-Manipulating the BPN -> group associations can be done through a REST API.
\ No newline at end of file
+Manipulating the BPN -> group associations can be done through a REST API.