Skip to content

Commit

Permalink
chore: Refactor BPN evaluation function (#1074)
Browse files Browse the repository at this point in the history
* chore: BPN number policy function refactor

* Update edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerNumberPermissionFunction.java

Co-authored-by: Jim Marino <jim.marino@gmail.com>

---------

Co-authored-by: Jim Marino <jim.marino@gmail.com>
  • Loading branch information
wolf4ood and jimmarino authored Feb 20, 2024
1 parent 2c28cf5 commit c99a8eb
Show file tree
Hide file tree
Showing 13 changed files with 293 additions and 718 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,25 @@

import org.eclipse.edc.policy.engine.spi.PolicyEngine;
import org.eclipse.edc.policy.engine.spi.RuleBindingRegistry;
import org.eclipse.edc.policy.model.Duty;
import org.eclipse.edc.policy.model.Permission;
import org.eclipse.edc.policy.model.Prohibition;
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.legacy.BusinessPartnerDutyFunction;
import org.eclipse.tractusx.edc.validation.businesspartner.functions.legacy.BusinessPartnerPermissionFunction;
import org.eclipse.tractusx.edc.validation.businesspartner.functions.legacy.BusinessPartnerProhibitionFunction;
import org.eclipse.tractusx.edc.validation.businesspartner.functions.BusinessPartnerNumberPermissionFunction;

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;
import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_SCHEMA;
import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE;
import static org.eclipse.tractusx.edc.validation.businesspartner.BusinessPartnerNumberValidationExtension.NAME;

/**
* Business partner number evaluation function.
*
* @deprecated Please use {@code BusinessPartnerEvaluationExtension} instead.
*/
@Deprecated(forRemoval = true, since = "0.5.0")
public class LegacyBusinessPartnerValidationExtension implements ServiceExtension {
@Extension(NAME)
public class BusinessPartnerNumberValidationExtension implements ServiceExtension {

/**
* The key for business partner numbers constraints. Must be used as left operand when declaring constraints.
Expand All @@ -60,66 +56,37 @@ public class LegacyBusinessPartnerValidationExtension implements ServiceExtensio
* </pre>
*/
public static final String BUSINESS_PARTNER_CONSTRAINT_KEY = "BusinessPartnerNumber";

public static final String TX_BUSINESS_PARTNER_CONSTRAINT_KEY = TX_NAMESPACE + BUSINESS_PARTNER_CONSTRAINT_KEY;


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";
protected static final String NAME = "Business Partner Validation Extension";
@Inject
private RuleBindingRegistry ruleBindingRegistry;
@Inject
private PolicyEngine policyEngine;

public LegacyBusinessPartnerValidationExtension() {
}

public LegacyBusinessPartnerValidationExtension(
final RuleBindingRegistry ruleBindingRegistry, final PolicyEngine policyEngine) {
this.ruleBindingRegistry = ruleBindingRegistry;
this.policyEngine = policyEngine;
}


@Override
public String name() {
return "Business Partner Validation Extension";
return NAME;
}

@Override
public void initialize(ServiceExtensionContext context) {

var monitor = context.getMonitor();

var logAgreementEvaluation = logAgreementEvaluationSetting(context);
var permissionFunction = new BusinessPartnerNumberPermissionFunction();

var dutyFunction = new BusinessPartnerDutyFunction(monitor, logAgreementEvaluation);
var permissionFunction = new BusinessPartnerPermissionFunction(monitor, logAgreementEvaluation);
var prohibitionFunction = new BusinessPartnerProhibitionFunction(monitor, logAgreementEvaluation);
bindToScope(permissionFunction, TRANSFER_SCOPE);
bindToScope(permissionFunction, NEGOTIATION_SCOPE);
bindToScope(permissionFunction, CATALOGING_SCOPE);

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) {
private void bindToScope(BusinessPartnerNumberPermissionFunction permissionFunction, String scope) {
ruleBindingRegistry.bind("USE", scope);
ruleBindingRegistry.bind(ODRL_SCHEMA + "use", scope);
ruleBindingRegistry.bind(BUSINESS_PARTNER_CONSTRAINT_KEY, scope);
ruleBindingRegistry.bind(TX_BUSINESS_PARTNER_CONSTRAINT_KEY, scope);


policyEngine.registerFunction(scope, Duty.class, BUSINESS_PARTNER_CONSTRAINT_KEY, dutyFunction);
policyEngine.registerFunction(scope, Permission.class, BUSINESS_PARTNER_CONSTRAINT_KEY, permissionFunction);
policyEngine.registerFunction(scope, Prohibition.class, BUSINESS_PARTNER_CONSTRAINT_KEY, prohibitionFunction);

policyEngine.registerFunction(scope, Permission.class, TX_BUSINESS_PARTNER_CONSTRAINT_KEY, permissionFunction);
}

private boolean logAgreementEvaluationSetting(ServiceExtensionContext context) {
return Boolean.parseBoolean(context.getSetting(BUSINESS_PARTNER_VALIDATION_LOG_AGREEMENT_VALIDATION, DEFAULT_LOG_AGREEMENT_EVALUATION));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@
* @see BusinessPartnerStore
*/
public class BusinessPartnerGroupFunction implements AtomicConstraintFunction<Permission> {
public static final String REFERRING_CONNECTOR_CLAIM = "referringConnector";
public static final String BUSINESS_PARTNER_CONSTRAINT_KEY = TX_NAMESPACE + "BusinessPartnerGroup";
private static final List<Operator> ALLOWED_OPERATORS = List.of(EQ, NEQ, IN, IS_ALL_OF, IS_ANY_OF, IS_NONE_OF);
private static final Map<Operator, Function<BpnGroupHolder, Boolean>> OPERATOR_EVALUATOR_MAP = new HashMap<>();
Expand Down Expand Up @@ -122,7 +121,7 @@ public boolean evaluate(Operator operator, Object rightValue, Permission rule, P
}


var bpn = getBpnClaim(participantAgent);
var bpn = participantAgent.getIdentity();
var groups = store.resolveForBpn(bpn);

// BPN not found in database
Expand Down Expand Up @@ -160,22 +159,7 @@ private List<String> parseRightOperand(Object rightValue, PolicyContext context)
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(BpnGroupHolder bpnGroupHolder) {
var assigned = bpnGroupHolder.assignedGroups;
// checks whether both lists overlap
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/********************************************************************************
* Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
*
* 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
********************************************************************************/

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 java.util.Optional;

import static java.lang.String.format;

/**
* AtomicConstraintFunction to validate business partner numbers for edc permissions.
*/
public class BusinessPartnerNumberPermissionFunction implements AtomicConstraintFunction<Permission> {

public BusinessPartnerNumberPermissionFunction() {
}

@Override
public boolean evaluate(Operator operator, Object rightValue, Permission rule, PolicyContext context) {

if (operator != Operator.EQ) {
var message = format("As operator only 'EQ' is supported. Unsupported operator: '%s'", operator);
context.reportProblem(message);
return false;
}

var participantAgent = context.getContextData(ParticipantAgent.class);
if (participantAgent == null) {
context.reportProblem("Required PolicyContext data not found: " + ParticipantAgent.class.getName());
return false;
}

var identity = participantAgent.getIdentity();
if (identity == null) {
context.reportProblem("Identity of the participant agent cannot be null");
return false;
}

if ((rightValue instanceof String businessPartnerNumberStr)) {
if (businessPartnerNumberStr.equals(identity)) {
return true;
} else {
context.reportProblem("Identity of the participant not matching the expected one: " + businessPartnerNumberStr);
return false;
}
} else {
var message = format("Invalid right operand value: expected 'String' but got '%s'",
Optional.of(rightValue).map(Object::getClass).map(Class::getName).orElse(null));
context.reportProblem(message);
return false;
}

}
}
Loading

0 comments on commit c99a8eb

Please sign in to comment.