diff --git a/CHANGELOG.md b/CHANGELOG.md index 66bc2cc337..b75b768874 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ _**For better traceability add the corresponding GitHub issue number in each cha - #908 Renamed header in notification detail for parts from Supplier Parts to Affected parts - #1151 Display of null values within contracts in datepicker to be empty if null - #1318 fix testdata v14 where parts had the wrong bpn +- #1194 fixed bug with misleading timezone conversion during policy creation ### Removed - #1227 Removed scrollbar on approval dialog diff --git a/frontend/src/app/modules/page/admin/presentation/policy-management/policies/policies.assembler.spec.ts b/frontend/src/app/modules/page/admin/presentation/policy-management/policies/policies.assembler.spec.ts index 0e59f02eec..d4fb6215f6 100644 --- a/frontend/src/app/modules/page/admin/presentation/policy-management/policies/policies.assembler.spec.ts +++ b/frontend/src/app/modules/page/admin/presentation/policy-management/policies/policies.assembler.spec.ts @@ -81,7 +81,7 @@ describe('PoliciesAssembler', () => { const assembledPolicy = PoliciesAssembler.assemblePolicy(mockPolicy2); expect(assembledPolicy.policyName).toBe(mockPolicy2.policyId); expect(assembledPolicy.createdOn).toBe('2024-01-01T00:00'); - expect(assembledPolicy.validUntil).toBe('2024-12-31T23:59'); + expect(assembledPolicy.validUntil).toBe('2025-01-01T00:59:59'); expect(assembledPolicy.accessType).toBe('USE'); expect(assembledPolicy.constraints).toEqual('left1=right1left2!=right2'); diff --git a/frontend/src/app/modules/page/admin/presentation/policy-management/policies/policy.assembler.ts b/frontend/src/app/modules/page/admin/presentation/policy-management/policies/policy.assembler.ts index aad14a0865..c63dadafcc 100644 --- a/frontend/src/app/modules/page/admin/presentation/policy-management/policies/policy.assembler.ts +++ b/frontend/src/app/modules/page/admin/presentation/policy-management/policies/policy.assembler.ts @@ -17,12 +17,25 @@ export class PoliciesAssembler { ...policy, policyName: policy.policyId, createdOn: isNumber(policy.createdOn) ? new Date(policy.createdOn as number * 1000).toISOString().slice(0, 19) + 'Z' : (formattedCreatedOn.isInitial() ? null : formattedCreatedOn.valueOf().toISOString().slice(0, 16)), - validUntil: isNumber(policy.validUntil) ? new Date(policy.validUntil as number * 1000).toISOString().slice(0, 19) + 'Z' : (formattedValidUntil.isInitial() ? null : formattedValidUntil.valueOf().toISOString().slice(0, 16)), + validUntil: isNumber(policy.validUntil) ? new Date(policy.validUntil as number * 1000).toISOString().slice(0, 19) + 'Z' : (formattedValidUntil.isInitial() ? null : this.mapUtcToLocalTime(policy.validUntil)), accessType: policy.permissions[0].action.toUpperCase() as PolicyAction, constraints: policy.constraints ?? this.mapDisplayPropsToPolicyRootLevelFromPolicy(policy), }; } + public static mapUtcToLocalTime(validUntil: string): string { + const date = new Date(validUntil); + + const localYear = date.getFullYear(); + const localMonth = String(date.getMonth() + 1).padStart(2, '0'); + const localDate = String(date.getDate()).padStart(2, '0'); + const localHours = String(date.getHours()).padStart(2, '0'); + const localMinutes = String(date.getMinutes()).padStart(2, '0'); + const localSeconds = String(date.getSeconds()).padStart(2, '0'); + + return `${ localYear }-${ localMonth }-${ localDate }T${ localHours }:${ localMinutes }:${ localSeconds }`; + + } public static mapToPolicyEntryList(policyResponse: PolicyResponseMap): PolicyEntry[] { const list: PolicyEntry[] = []; for (const [ key, value ] of Object.entries(policyResponse)) { diff --git a/frontend/src/app/modules/page/admin/presentation/policy-management/policy-editor/policy-editor.component.ts b/frontend/src/app/modules/page/admin/presentation/policy-management/policy-editor/policy-editor.component.ts index faac5cc379..00334aa725 100644 --- a/frontend/src/app/modules/page/admin/presentation/policy-management/policy-editor/policy-editor.component.ts +++ b/frontend/src/app/modules/page/admin/presentation/policy-management/policy-editor/policy-editor.component.ts @@ -31,6 +31,7 @@ import { ToastService } from '@shared/components/toasts/toast.service'; import { ViewMode } from '@shared/model/view.model'; import { Subscription } from 'rxjs'; + @Component({ selector: 'app-policy-editor', templateUrl: './policy-editor.component.html', @@ -221,7 +222,6 @@ export class PolicyEditorComponent { } */ updatePolicyForm(policy: Policy) { - const isFromTemplate = !policy?.permissions[0]?.constraints; this.policyForm.patchValue({ policyName: policy?.policyName, @@ -278,8 +278,11 @@ export class PolicyEditorComponent { }; }); + const validUntilDate = new Date(this.policyForm.get('validUntil').getRawValue()); + const validUntilISO = validUntilDate.toISOString(); + policyEntry = { - validUntil: this.policyForm.get('validUntil').getRawValue() + ':00.000000000Z', + validUntil: validUntilISO, businessPartnerNumber: this.viewMode === ViewMode.CREATE ? this.policyForm.get('bpns').getRawValue() : this.policyForm.get('bpns').getRawValue()?.trim()?.split(','), payload: { '@context': { @@ -289,7 +292,7 @@ export class PolicyEditorComponent { policy: { policyId: this.policyForm.get('policyName').getRawValue(), createdOn: new Date(Date.now()).toISOString().replace('Z', '000000Z'), - validUntil: this.policyForm.get('validUntil').getRawValue() + ':00.000000000Z', + validUntil: validUntilISO, permissions: [ { action: this.policyForm.get('accessType').getRawValue().toLowerCase(), diff --git a/frontend/src/app/modules/page/policies/model/policy.model.ts b/frontend/src/app/modules/page/policies/model/policy.model.ts index a55199f8fd..7758c731d9 100644 --- a/frontend/src/app/modules/page/policies/model/policy.model.ts +++ b/frontend/src/app/modules/page/policies/model/policy.model.ts @@ -44,7 +44,7 @@ export interface Policy { // props in response policyId: string; createdOn: CalendarDateModel | string | number; - validUntil: CalendarDateModel | string | number; + validUntil: string | number; permissions: PolicyPermission[]; // additional props @@ -127,6 +127,7 @@ export function getOperatorTypeSign(type: OperatorType): string { } } + export enum ConstraintLogicType { AND = 'AND', OR = 'OR', diff --git a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/common/config/ErrorHandlingConfig.java b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/common/config/ErrorHandlingConfig.java index 620b384a08..5c1e39e02f 100644 --- a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/common/config/ErrorHandlingConfig.java +++ b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/common/config/ErrorHandlingConfig.java @@ -58,6 +58,7 @@ import org.eclipse.tractusx.traceability.notification.domain.notification.exception.NotificationNotSupportedException; import org.eclipse.tractusx.traceability.notification.domain.notification.exception.NotificationSenderAndReceiverBPNEqualException; import org.eclipse.tractusx.traceability.notification.domain.notification.exception.NotificationStatusTransitionNotAllowed; +import org.eclipse.tractusx.traceability.policies.domain.exception.PolicyNotValidException; import org.eclipse.tractusx.traceability.submodel.domain.model.SubmodelNotFoundException; import org.jetbrains.annotations.Nullable; import org.springframework.context.support.DefaultMessageSourceResolvable; @@ -379,6 +380,13 @@ ResponseEntity handleUnsupportedSearchCriteriaFieldException(Unsu .body(new ErrorResponse(exception.getMessage())); } + @ExceptionHandler(PolicyNotValidException.class) + ResponseEntity handlePolicyNotValidException(PolicyNotValidException exception) { + log.warn("PolicyNotValidException", exception); + return ResponseEntity.status(BAD_REQUEST) + .body(new ErrorResponse(exception.getMessage())); + } + @ExceptionHandler(CreateNotificationContractException.class) ResponseEntity handleCreateNotificationContractException(CreateNotificationContractException exception) { log.warn("handleCreateNotificationContractException", exception); diff --git a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/common/config/PolicyStartUpConfig.java b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/common/config/PolicyStartUpConfig.java index 819bb5267a..92295ba313 100644 --- a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/common/config/PolicyStartUpConfig.java +++ b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/common/config/PolicyStartUpConfig.java @@ -46,6 +46,7 @@ import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import policies.response.IrsPolicyResponse; +import policies.response.PolicyResponse; import java.time.OffsetDateTime; import java.util.ArrayList; @@ -53,6 +54,8 @@ import java.util.Map; import java.util.UUID; +import static policies.response.PolicyResponse.toDomain; + @Configuration @ConfigurationPropertiesScan(basePackages = "org.eclipse.tractusx.traceability.*") @EnableWebMvc @@ -105,8 +108,8 @@ private List createIrsAcceptedPolicies() { // Map the IrsPolicyResponse objects to AcceptedPolicy objects List irsPolicies = irsPolicyResponses.stream().map(response -> { - Policy policy = new Policy(response.payload().policyId(), response.payload().policy().getCreatedOn(), response.validUntil(), response.payload().policy().getPermissions()); - return new AcceptedPolicy(policy, response.validUntil()); + PolicyResponse policy = new PolicyResponse(response.payload().policyId(), response.payload().policy().createdOn(), response.validUntil(), response.payload().policy().permissions(), null); + return new AcceptedPolicy(toDomain(policy), response.validUntil()); }).toList(); // Return the list of AcceptedPolicy objects diff --git a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/application/mapper/PolicyMapper.java b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/application/mapper/PolicyMapper.java index 4c5f99344d..742cc853be 100644 --- a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/application/mapper/PolicyMapper.java +++ b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/application/mapper/PolicyMapper.java @@ -60,7 +60,7 @@ private static List mapToPermissions(List EdcPolicyPermission.builder() // https://github.com/eclipse-tractusx/traceability-foss/issues/978 here we need to make sure that the USE is lowercase in the object. .action(permission.action().name().toLowerCase()) - .edcPolicyPermissionConstraints(mapToConstraint(permission.constraints())) + .edcPolicyPermissionConstraints(mapToConstraint(permission.constraint())) .build() ).toList(); } @@ -79,7 +79,7 @@ private static List mapToConstraintExpr .leftOperand(constraint.leftOperand()) .rightOperand(constraint.rightOperand()) .operator(EdcOperator.builder() - .operatorId("odrl:" + constraint.operatorTypeResponse().getCode()) + .operatorId("odrl:" + constraint.operator().operatorType().getCode()) .build()) .build()) .toList(); diff --git a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/application/rest/PolicyController.java b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/application/rest/PolicyController.java index cc4596d026..c08243ed5f 100644 --- a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/application/rest/PolicyController.java +++ b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/application/rest/PolicyController.java @@ -112,7 +112,7 @@ public class PolicyController { mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class)))}) @GetMapping() - public Map> getPolicies() { + public Map> getPolicies() { return policyService.getIrsPolicies(); } diff --git a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/application/service/PolicyService.java b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/application/service/PolicyService.java index f75d5272fd..8e51666d4f 100644 --- a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/application/service/PolicyService.java +++ b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/application/service/PolicyService.java @@ -30,7 +30,7 @@ public interface PolicyService { List getPolicies(); - Map> getIrsPolicies(); + Map> getIrsPolicies(); PolicyResponse getPolicy(String id); diff --git a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/domain/PolicyServiceImpl.java b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/domain/PolicyServiceImpl.java index e05b23e7fa..f2b75c9e3d 100644 --- a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/domain/PolicyServiceImpl.java +++ b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/domain/PolicyServiceImpl.java @@ -23,6 +23,7 @@ import org.eclipse.tractusx.traceability.assets.domain.importpoc.exception.PolicyNotFoundException; import org.eclipse.tractusx.traceability.notification.domain.contract.EdcNotificationContractService; import org.eclipse.tractusx.traceability.policies.application.service.PolicyService; +import org.eclipse.tractusx.traceability.policies.domain.exception.PolicyNotValidException; import org.springframework.stereotype.Service; import policies.request.RegisterPolicyRequest; import policies.request.UpdatePolicyRequest; @@ -30,11 +31,13 @@ import policies.response.IrsPolicyResponse; import policies.response.PolicyResponse; +import java.time.Instant; import java.util.List; import java.util.Map; import java.util.Optional; -import static policies.response.IrsPolicyResponse.toResponse; +import java.util.stream.Collectors; + @Slf4j @RequiredArgsConstructor @@ -45,33 +48,46 @@ public class PolicyServiceImpl implements PolicyService { private final EdcNotificationContractService edcNotificationContractService; @Override - public Map> getIrsPolicies() { - return policyRepository.getPolicies(); + public Map> getIrsPolicies() { + Map> policies = policyRepository.getPolicies(); + return policies.entrySet().stream() + .collect(Collectors.toMap( + Map.Entry::getKey, + entry -> entry.getValue().stream() + .map(irsPolicyResponse -> irsPolicyResponse.payload().policy()) + .collect(Collectors.toList()) + )); } @Override public List getPolicies() { Map> policies = policyRepository.getPolicies(); - return toResponse(policies); + return policies.values().stream() + .flatMap(List::stream) + .map(irsPolicyResponse -> irsPolicyResponse.payload().policy()) + .collect(Collectors.toList()); } @Override public PolicyResponse getPolicy(String id) { Map> policies = policyRepository.getPolicy(id); - // Find the first entry with a present policy - return policies.entrySet().stream() - .filter(entry -> entry.getValue().isPresent()) + return policies.values().stream() + .filter(Optional::isPresent) + .map(Optional::get) + .map(irsPolicyResponse -> irsPolicyResponse.payload().policy()) .findFirst() - .map(entry -> toResponse(entry.getValue().get(), entry.getKey())) .orElseThrow(() -> new PolicyNotFoundException("Policy with id: %s not found.".formatted(id))); } @Override public CreatePolicyResponse createPolicy(RegisterPolicyRequest registerPolicyRequest) { - CreatePolicyResponse policy = policyRepository.createPolicy(registerPolicyRequest); - edcNotificationContractService.updateNotificationContractDefinitions(); - return policy; + if(registerPolicyRequest.validUntil().isAfter(Instant.now())){ + CreatePolicyResponse policy = policyRepository.createPolicy(registerPolicyRequest); + edcNotificationContractService.updateNotificationContractDefinitions(); + return policy; + } + throw new PolicyNotValidException("Policy is not valid because of a not accepted validUntil value " +registerPolicyRequest); } @Override @@ -82,8 +98,12 @@ public void deletePolicy(String id) { @Override public void updatePolicy(UpdatePolicyRequest updatePolicyRequest) { + if(updatePolicyRequest.validUntil().isAfter(Instant.now())){ policyRepository.updatePolicy(updatePolicyRequest); edcNotificationContractService.updateNotificationContractDefinitions(); + return; + } + throw new PolicyNotValidException("Policy is not valid because of a not accepted validUntil value " +updatePolicyRequest); } diff --git a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/domain/exception/PolicyNotValidException.java b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/domain/exception/PolicyNotValidException.java new file mode 100644 index 0000000000..a1b127c9de --- /dev/null +++ b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/domain/exception/PolicyNotValidException.java @@ -0,0 +1,25 @@ +/******************************************************************************** + * Copyright (c) 2024 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 + ********************************************************************************/ +package org.eclipse.tractusx.traceability.policies.domain.exception; + +public class PolicyNotValidException extends RuntimeException{ + public PolicyNotValidException(String message) { + super(message); + } +} diff --git a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/infrastructure/PolicyClient.java b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/infrastructure/PolicyClient.java index 4b4e5f816a..9edb9b8b0d 100644 --- a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/infrastructure/PolicyClient.java +++ b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/infrastructure/PolicyClient.java @@ -40,9 +40,15 @@ import policies.request.Payload; import policies.request.RegisterPolicyRequest; import policies.request.UpdatePolicyRequest; +import policies.response.ConstraintResponse; +import policies.response.ConstraintsResponse; import policies.response.CreatePolicyResponse; import policies.response.IrsPolicyResponse; +import policies.response.OperatorResponse; +import policies.response.OperatorTypeResponse; +import policies.response.PermissionResponse; import policies.response.PolicyResponse; +import policies.response.PolicyTypeResponse; import java.time.Instant; import java.time.OffsetDateTime; @@ -86,13 +92,14 @@ public Optional getNewestPolicyByOwnBpn() { CollectionUtils.emptyIfNull(policies.get(DEFAULT_POLICY_EMPTY_PLACEHOLDER)).stream()); return defaultPolicies - .max(Comparator.comparing(p -> p.payload().policy().getCreatedOn())) - .map(irsPolicyResponse -> IrsPolicyResponse.toResponse(irsPolicyResponse, traceabilityProperties.getBpn().value())); + .max(Comparator.comparing(p -> p.payload().policy().createdOn())) + .map(irsPolicyResponse -> irsPolicyResponse.payload().policy()); + } else { return policies.get(traceabilityProperties.getBpn().value()) .stream() - .max(Comparator.comparing(p -> p.payload().policy().getCreatedOn())) - .map(irsPolicyResponse -> IrsPolicyResponse.toResponse(irsPolicyResponse, traceabilityProperties.getBpn().value())); + .max(Comparator.comparing(p -> p.payload().policy().createdOn())) + .map(irsPolicyResponse -> irsPolicyResponse.payload().policy()); } } @@ -131,19 +138,19 @@ public void createPolicyFromAppConfig() { Context context = Context.getDefault(); String policyId = UUID.randomUUID().toString(); - Constraint constraint = new Constraint(traceabilityProperties.getLeftOperand(), new Operator(OperatorType.EQ), traceabilityProperties.getRightOperand()); - Constraint constraintSecond = new Constraint(traceabilityProperties.getLeftOperandSecond(), new Operator(OperatorType.EQ), traceabilityProperties.getRightOperandSecond()); + ConstraintResponse constraint = new ConstraintResponse(traceabilityProperties.getLeftOperand(), new OperatorResponse(OperatorTypeResponse.EQ), traceabilityProperties.getRightOperand()); + ConstraintResponse constraintSecond = new ConstraintResponse(traceabilityProperties.getLeftOperandSecond(),new OperatorResponse(OperatorTypeResponse.EQ), traceabilityProperties.getRightOperandSecond()); - Constraints constraints = Constraints.builder() + ConstraintsResponse constraints = ConstraintsResponse.builder() .and(List.of(constraint, constraintSecond)) .build(); - Permission permission = Permission.builder() - .action(PolicyType.USE) + PermissionResponse permission = PermissionResponse.builder() + .action(PolicyTypeResponse.USE) .constraint(constraints) .build(); - Policy policy = new Policy(policyId, Instant.now().atOffset(ZoneOffset.UTC), validUntil, List.of(permission)); + PolicyResponse policy = new PolicyResponse(policyId, Instant.now().atOffset(ZoneOffset.UTC), validUntil, List.of(permission),null); Payload payload = new Payload(context, policyId, policy); RegisterPolicyRequest registerPolicyRequest = new RegisterPolicyRequest(validUntil.toInstant(), traceabilityProperties.getBpn().value(), payload); diff --git a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/infrastructure/PolicyRepositoryImpl.java b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/infrastructure/PolicyRepositoryImpl.java index 03f930b57f..b22f23b56e 100644 --- a/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/infrastructure/PolicyRepositoryImpl.java +++ b/tx-backend/src/main/java/org/eclipse/tractusx/traceability/policies/infrastructure/PolicyRepositoryImpl.java @@ -22,17 +22,16 @@ import lombok.extern.slf4j.Slf4j; import org.eclipse.tractusx.irs.edc.client.policy.AcceptedPoliciesProvider; import org.eclipse.tractusx.irs.edc.client.policy.AcceptedPolicy; -import org.eclipse.tractusx.irs.edc.client.policy.Constraint; -import org.eclipse.tractusx.irs.edc.client.policy.Constraints; -import org.eclipse.tractusx.irs.edc.client.policy.Permission; -import org.eclipse.tractusx.irs.edc.client.policy.Policy; import org.eclipse.tractusx.traceability.common.properties.TraceabilityProperties; import org.eclipse.tractusx.traceability.policies.domain.PolicyRepository; import org.springframework.stereotype.Service; import policies.request.RegisterPolicyRequest; import policies.request.UpdatePolicyRequest; +import policies.response.ConstraintResponse; +import policies.response.ConstraintsResponse; import policies.response.CreatePolicyResponse; import policies.response.IrsPolicyResponse; +import policies.response.PermissionResponse; import policies.response.PolicyResponse; import java.util.HashMap; @@ -42,6 +41,7 @@ import java.util.stream.Stream; import static org.apache.commons.collections4.ListUtils.emptyIfNull; +import static policies.response.PolicyResponse.toDomain; @Slf4j @Service @@ -138,19 +138,19 @@ private boolean checkConstraints(IrsPolicyResponse irsPolicy) { } private boolean checkConstraint(IrsPolicyResponse irsPolicy, String rightOperand) { - return emptyIfNull(irsPolicy.payload().policy().getPermissions()).stream() + return emptyIfNull(irsPolicy.payload().policy().permissions()).stream() .flatMap(this::getConstraintsStream) - .anyMatch(constraint -> constraint.getRightOperand().equals(rightOperand)); + .anyMatch(constraint -> constraint.rightOperand().equals(rightOperand)); } - private Stream getConstraintsStream(Permission permission) { - Constraints constraint = permission.getConstraint(); + private Stream getConstraintsStream(PermissionResponse permission) { + ConstraintsResponse constraint = permission.constraint(); if (constraint == null) { return Stream.empty(); } return Stream.concat( - emptyIfNull(constraint.getAnd()).stream(), - emptyIfNull(constraint.getOr()).stream() + emptyIfNull(constraint.and()).stream(), + emptyIfNull(constraint.or()).stream() ); } @@ -181,8 +181,8 @@ private void updateAcceptedPoliciesProvider() { // Map the IrsPolicyResponse objects to AcceptedPolicy objects List irsPolicies = irsPolicyResponses.stream().map(response -> { - Policy policy = new Policy(response.payload().policyId(), response.payload().policy().getCreatedOn(), response.validUntil(), response.payload().policy().getPermissions()); - return new AcceptedPolicy(policy, response.validUntil()); + PolicyResponse policy = new PolicyResponse(response.payload().policyId(), response.payload().policy().createdOn(), response.validUntil(), response.payload().policy().permissions(), null); + return new AcceptedPolicy(toDomain(policy), response.validUntil()); }).toList(); defaultAcceptedPoliciesProvider.addAcceptedPolicies(irsPolicies); } diff --git a/tx-backend/src/test/java/org/eclipse/tractusx/traceability/assets/infrastructure/base/irs/PolicyRepositoryImplTest.java b/tx-backend/src/test/java/org/eclipse/tractusx/traceability/assets/infrastructure/base/irs/PolicyRepositoryImplTest.java index db33453efb..03fd4a2129 100644 --- a/tx-backend/src/test/java/org/eclipse/tractusx/traceability/assets/infrastructure/base/irs/PolicyRepositoryImplTest.java +++ b/tx-backend/src/test/java/org/eclipse/tractusx/traceability/assets/infrastructure/base/irs/PolicyRepositoryImplTest.java @@ -27,6 +27,8 @@ import org.eclipse.tractusx.irs.edc.client.policy.Permission; import org.eclipse.tractusx.irs.edc.client.policy.Policy; import org.eclipse.tractusx.irs.edc.client.policy.PolicyType; +import policies.response.ConstraintResponse; +import policies.response.ConstraintsResponse; import policies.response.IrsPolicyResponse; import policies.request.Payload; import org.eclipse.tractusx.traceability.common.properties.TraceabilityProperties; @@ -37,6 +39,11 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import policies.response.OperatorResponse; +import policies.response.OperatorTypeResponse; +import policies.response.PermissionResponse; +import policies.response.PolicyResponse; +import policies.response.PolicyTypeResponse; import java.time.OffsetDateTime; import java.util.Collections; @@ -86,9 +93,9 @@ void givenPolicyExist_whenCreateIrsPolicyIfMissing_thenDoNotCreateApplicationCon // given OffsetDateTime validUntil = OffsetDateTime.parse("2023-07-03T16:01:05.309Z"); OffsetDateTime createdOn = OffsetDateTime.now(); - Constraint constraint = new Constraint("leftOperand1", new Operator(OperatorType.EQ), "test"); - Constraint constraintSecond = new Constraint("leftOperand2", new Operator(OperatorType.EQ), "test2"); - Policy policy = new Policy("1", createdOn, validUntil, List.of(new Permission(PolicyType.USE, new Constraints(List.of(constraint, constraintSecond), List.of())))); + ConstraintResponse constraint = new ConstraintResponse("leftOperand1", new OperatorResponse(OperatorTypeResponse.EQ), "test"); + ConstraintResponse constraintSecond = new ConstraintResponse("leftOperand2", new OperatorResponse(OperatorTypeResponse.EQ), "test2"); + PolicyResponse policy = new PolicyResponse("1", createdOn, validUntil, List.of(new PermissionResponse(PolicyTypeResponse.USE, new ConstraintsResponse(List.of(constraint, constraintSecond), List.of()))),null); Payload payload = new Payload(null, "1", policy); final IrsPolicyResponse existingPolicy = new IrsPolicyResponse(validUntil, payload); Map> existingPolicies = Map.of("key", List.of(existingPolicy)); @@ -111,9 +118,9 @@ void givenOutdatedPolicyExist_whenCreatePolicyBasedOnAppConfig_thenUpdateIt() { // given OffsetDateTime validUntil = OffsetDateTime.parse("2023-07-03T16:01:05.309Z"); OffsetDateTime createdOn = OffsetDateTime.now(); - Constraint constraint = new Constraint("leftOperand1", new Operator(OperatorType.EQ), "test"); - Constraint constraintSecond = new Constraint("leftOperand2", new Operator(OperatorType.EQ), "test2"); - Policy policy = new Policy("test", createdOn, validUntil, List.of(new Permission(PolicyType.USE, new Constraints(List.of(constraint, constraintSecond), List.of())))); + ConstraintResponse constraint = new ConstraintResponse("leftOperand1", new OperatorResponse(OperatorTypeResponse.EQ), "test"); + ConstraintResponse constraintSecond = new ConstraintResponse("leftOperand2", new OperatorResponse(OperatorTypeResponse.EQ), "test2"); + PolicyResponse policy = new PolicyResponse("test", createdOn, validUntil, List.of(new PermissionResponse(PolicyTypeResponse.USE, new ConstraintsResponse(List.of(constraint, constraintSecond), List.of()))),null); Payload payload = new Payload(null, "test", policy); final IrsPolicyResponse existingPolicy = new IrsPolicyResponse(validUntil, payload); @@ -138,11 +145,11 @@ void test_getPolicyConstraints() { // GIVEN OffsetDateTime validUntil = OffsetDateTime.now(); OffsetDateTime createdOn = OffsetDateTime.now(); - List andConstraints = List.of(new Constraint("leftOperand", new Operator(OperatorType.EQ), "rightOperand")); - List orConstraints = List.of(new Constraint("leftOperand", new Operator(OperatorType.EQ), "rightOperand")); - Constraints constraints = new Constraints(andConstraints, orConstraints); + List andConstraints = List.of(new ConstraintResponse("leftOperand", new OperatorResponse(OperatorTypeResponse.EQ), "rightOperand")); + List orConstraints = List.of(new ConstraintResponse("leftOperand", new OperatorResponse(OperatorTypeResponse.EQ), "rightOperand")); + ConstraintsResponse constraints = new ConstraintsResponse(andConstraints, orConstraints); - Policy policy = new Policy("test", createdOn, validUntil, List.of(new Permission(PolicyType.USE, constraints))); + PolicyResponse policy = new PolicyResponse("test", createdOn, validUntil, List.of(new PermissionResponse(PolicyTypeResponse.USE, constraints)), null); Payload payload = new Payload(null, "test", policy); final IrsPolicyResponse existingPolicy = new IrsPolicyResponse(validUntil, payload); diff --git a/tx-backend/src/test/java/org/eclipse/tractusx/traceability/infrastructure/edc/notificationcontract/service/EdcNotificationContractServiceTest.java b/tx-backend/src/test/java/org/eclipse/tractusx/traceability/infrastructure/edc/notificationcontract/service/EdcNotificationContractServiceTest.java index 89fb93808a..8a3cbffd58 100644 --- a/tx-backend/src/test/java/org/eclipse/tractusx/traceability/infrastructure/edc/notificationcontract/service/EdcNotificationContractServiceTest.java +++ b/tx-backend/src/test/java/org/eclipse/tractusx/traceability/infrastructure/edc/notificationcontract/service/EdcNotificationContractServiceTest.java @@ -50,6 +50,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.tractusx.traceability.testdata.PolicyTestDataFactory.createIrsPolicyResponse; @@ -94,7 +95,7 @@ void testHandle() throws CreateEdcAssetException, CreateEdcPolicyDefinitionExcep IrsPolicyResponse irsPolicyResponse = createIrsPolicyResponse("test", OffsetDateTime.now(), "orLeft", "andLeft", "or", "and"); Map> policyMap = Map.of("testKey", List.of(irsPolicyResponse)); - List policyResponses = IrsPolicyResponse.toResponse(policyMap); + List policyResponses = policyMap.values().stream().flatMap(List::stream).map(entry -> entry.payload().policy()).toList(); when(policyRepository.getNewestPolicyByOwnBpn()).thenReturn(Optional.of(policyResponses.get(0))); CreateNotificationContractRequest request = new CreateNotificationContractRequest(notificationType, notificationMethod); @@ -142,7 +143,7 @@ void givenService_whenPolicyDefinitionServiceThrowsException_thenThrowException( IrsPolicyResponse irsPolicyResponse = createIrsPolicyResponse("test", OffsetDateTime.now(), "orLeft", "andLeft", "or", "and"); Map> policyMap = Map.of("testKey", List.of(irsPolicyResponse)); - List policyResponses = IrsPolicyResponse.toResponse(policyMap); + List policyResponses = policyMap.values().stream().flatMap(List::stream).map(entry -> entry.payload().policy()).toList(); when(policyRepository.getNewestPolicyByOwnBpn()).thenReturn(Optional.of(policyResponses.get(0))); CreateNotificationContractRequest request = new CreateNotificationContractRequest(notificationType, notificationMethod); @@ -168,7 +169,7 @@ void givenService_whenContractDefinitionServiceThrowsException_thenThrowExceptio IrsPolicyResponse irsPolicyResponse = createIrsPolicyResponse("test", OffsetDateTime.now(), "orLeft", "andLeft", "or", "and"); Map> policyMap = Map.of("testKey", List.of(irsPolicyResponse)); - List policyResponses = IrsPolicyResponse.toResponse(policyMap); + List policyResponses = policyMap.values().stream().flatMap(List::stream).map(entry -> entry.payload().policy()).toList(); when(policyRepository.getNewestPolicyByOwnBpn()).thenReturn(Optional.of(policyResponses.get(0))); CreateNotificationContractRequest request = new CreateNotificationContractRequest(notificationType, notificationMethod); diff --git a/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/policy/PolicyControllerIT.java b/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/policy/PolicyControllerIT.java index 09f6f76a29..2a5b2bb9bc 100644 --- a/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/policy/PolicyControllerIT.java +++ b/tx-backend/src/test/java/org/eclipse/tractusx/traceability/integration/policy/PolicyControllerIT.java @@ -19,6 +19,7 @@ package org.eclipse.tractusx.traceability.integration.policy; import io.restassured.http.ContentType; +import io.restassured.response.ValidatableResponse; import org.eclipse.tractusx.traceability.integration.IntegrationTestSpecification; import org.eclipse.tractusx.traceability.integration.common.support.EdcSupport; import org.eclipse.tractusx.traceability.integration.common.support.IrsApiSupport; @@ -28,14 +29,17 @@ import policies.request.Payload; import policies.request.RegisterPolicyRequest; import policies.request.UpdatePolicyRequest; +import policies.response.CreatePolicyResponse; import java.time.Instant; import java.util.Arrays; import java.util.List; import static io.restassured.RestAssured.given; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.eclipse.tractusx.traceability.common.security.JwtRole.ADMIN; import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; class PolicyControllerIT extends IntegrationTestSpecification { @@ -126,18 +130,18 @@ void shouldCreatePolicy() throws JoseException { @Test - void shouldThorwBadRequestCreatePolicy() throws JoseException { - // GIVEN + void shouldThrowBadRequestCreatePolicy() throws JoseException { + //given irsApiSupport.irsApiCreatesPolicyBadRequest(); - // Sample data + // sample data List businessPartnerNumbers = Arrays.asList("BPN-123", "BPN-456"); List policyIds = Arrays.asList("POLICY-789", "POLICY-101"); Instant validUntil = Instant.parse("2025-12-31T23:59:59.00Z"); - // WRONG REQUEST OBJECT + UpdatePolicyRequest request = new UpdatePolicyRequest(businessPartnerNumbers, policyIds, validUntil); - // when/then + //when/then given() .header(oAuth2Support.jwtAuthorization(ADMIN)) .contentType(ContentType.JSON) @@ -150,6 +154,29 @@ void shouldThorwBadRequestCreatePolicy() throws JoseException { .log().all(); } + @Test + void shouldThrowPolicyNotValidCreatePolicy() throws JoseException { + + // GIVEN + List businessPartnerNumbers = List.of("BPN-46t6"); + List policyIds = List.of("POLICY-790"); + Instant validUntil = Instant.parse("2021-12-31T23:59:59.00Z"); + + // WRONG REQUEST OBJECT + UpdatePolicyRequest request = new UpdatePolicyRequest(businessPartnerNumbers, policyIds, validUntil); + // when/then + given() + .header(oAuth2Support.jwtAuthorization(ADMIN)) + .contentType(ContentType.JSON) + .body(request) + .when() + .post("/api/policies") + .then() + .statusCode(400) + .body("message", equalTo("Policy is not valid because of a not accepted validUntil value RegisterPolicyRequest[validUntil=2021-12-31T23:59:59Z, businessPartnerNumber=null, payload=null]")); + + } + @Test void shouldUpdatePolicy() throws JoseException { // GIVEN diff --git a/tx-backend/src/test/java/org/eclipse/tractusx/traceability/testdata/PolicyTestDataFactory.java b/tx-backend/src/test/java/org/eclipse/tractusx/traceability/testdata/PolicyTestDataFactory.java index 3cfbedb068..d5e5e1a18c 100644 --- a/tx-backend/src/test/java/org/eclipse/tractusx/traceability/testdata/PolicyTestDataFactory.java +++ b/tx-backend/src/test/java/org/eclipse/tractusx/traceability/testdata/PolicyTestDataFactory.java @@ -25,9 +25,16 @@ import org.eclipse.tractusx.irs.edc.client.policy.Permission; import org.eclipse.tractusx.irs.edc.client.policy.Policy; import org.eclipse.tractusx.irs.edc.client.policy.PolicyType; +import policies.response.ConstraintResponse; +import policies.response.ConstraintsResponse; import policies.response.IrsPolicyResponse; import policies.request.Payload; import org.jetbrains.annotations.NotNull; +import policies.response.OperatorResponse; +import policies.response.OperatorTypeResponse; +import policies.response.PermissionResponse; +import policies.response.PolicyResponse; +import policies.response.PolicyTypeResponse; import java.time.OffsetDateTime; import java.util.List; @@ -43,15 +50,15 @@ public static IrsPolicyResponse createIrsPolicyResponse(String policyId, OffsetD Payload.builder() .policyId(policyId) .policy( - Policy.builder() + PolicyResponse.builder() .policyId(policyId) .createdOn(createdOn) .permissions(List.of( - Permission.builder() - .action(PolicyType.USE) - .constraint(Constraints.builder() - .and(List.of(new Constraint(andLeftOperand, new Operator(OperatorType.EQ), andRightOperand))) - .or(List.of(new Constraint(orLeftOperand, new Operator(OperatorType.EQ), orRightOperand))) + PermissionResponse.builder() + .action(PolicyTypeResponse.USE) + .constraint(ConstraintsResponse.builder() + .and(List.of(new ConstraintResponse(andLeftOperand, new OperatorResponse(OperatorTypeResponse.EQ), andRightOperand))) + .or(List.of(new ConstraintResponse(orLeftOperand, new OperatorResponse(OperatorTypeResponse.EQ), orRightOperand))) .build()) .build())) .build()) diff --git a/tx-backend/src/test/resources/stubs/irs/policies/request_create_policy.json b/tx-backend/src/test/resources/stubs/irs/policies/request_create_policy.json index 8d187dd153..f3a7490d66 100644 --- a/tx-backend/src/test/resources/stubs/irs/policies/request_create_policy.json +++ b/tx-backend/src/test/resources/stubs/irs/policies/request_create_policy.json @@ -1,5 +1,5 @@ { - "validUntil": "2024-07-04T00:00:00.000000000Z", + "validUntil": "2029-07-04T00:00:00.000000000Z", "businessPartnerNumber": "BPNL00000003CNKC", "payload": { "@context": { @@ -9,7 +9,7 @@ "policy": { "policyId": "invalid-policy-5", "createdOn": "2024-07-03T09:01:40.109000000Z", - "validUntil": "2024-07-04T00:00:00.000000000Z", + "validUntil": "2029-07-04T00:00:00.000000000Z", "permissions": [ { "action": "use", diff --git a/tx-models/src/main/java/policies/request/Payload.java b/tx-models/src/main/java/policies/request/Payload.java index ab55f0b055..6af4383f14 100644 --- a/tx-models/src/main/java/policies/request/Payload.java +++ b/tx-models/src/main/java/policies/request/Payload.java @@ -21,7 +21,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Builder; -import org.eclipse.tractusx.irs.edc.client.policy.Policy; +import policies.response.PolicyResponse; /** * Payload representation for get all policies response @@ -30,7 +30,7 @@ public record Payload( @JsonProperty("@context") Context context, @JsonProperty("@id") String policyId, - Policy policy + PolicyResponse policy ) { } diff --git a/tx-models/src/main/java/policies/response/ConstraintResponse.java b/tx-models/src/main/java/policies/response/ConstraintResponse.java index 6abb2a361e..3ff1805a97 100644 --- a/tx-models/src/main/java/policies/response/ConstraintResponse.java +++ b/tx-models/src/main/java/policies/response/ConstraintResponse.java @@ -18,16 +18,59 @@ ********************************************************************************/ package policies.response; +import com.fasterxml.jackson.annotation.JsonAlias; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; +import org.eclipse.tractusx.irs.edc.client.policy.Constraint; +import org.eclipse.tractusx.irs.edc.client.policy.Operator; +import org.eclipse.tractusx.irs.edc.client.policy.OperatorType; +import org.eclipse.tractusx.irs.edc.client.policy.Permission; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; @Builder public record ConstraintResponse( - @Schema(example = "PURPOSE") + @Schema( + implementation = String.class, + example = "string" + ) + @JsonAlias({"odrl:leftOperand"}) String leftOperand, + @Schema - OperatorTypeResponse operatorTypeResponse, - @Schema(example = "ID Trace 3.1") + @JsonAlias({"odrl:operator"}) + OperatorResponse operator, + @Schema( + implementation = String.class, + example = "string" + ) + @JsonAlias({"odrl:rightOperand"}) String rightOperand) { + + + + public static List toDomain(List constraintResponse) { + if (constraintResponse == null) { + return null; + } + return constraintResponse.stream() + .map(ConstraintResponse::toDomain) + .collect(Collectors.toList()); + } + public static Constraint toDomain(ConstraintResponse constraintResponse){ + if (constraintResponse == null) { + return null; + } + Operator operator = new Operator(OperatorResponse.toDomain(constraintResponse.operator.operatorType())); + + return new Constraint( + constraintResponse.leftOperand(), + operator, + constraintResponse.rightOperand() + ); + } } diff --git a/tx-models/src/main/java/policies/response/ConstraintsResponse.java b/tx-models/src/main/java/policies/response/ConstraintsResponse.java index 1c1b685ace..f4f5835ac9 100644 --- a/tx-models/src/main/java/policies/response/ConstraintsResponse.java +++ b/tx-models/src/main/java/policies/response/ConstraintsResponse.java @@ -18,13 +18,29 @@ ********************************************************************************/ package policies.response; +import com.fasterxml.jackson.annotation.JsonAlias; +import io.swagger.v3.oas.annotations.media.ArraySchema; import lombok.Builder; +import org.eclipse.tractusx.irs.edc.client.policy.Constraints; import java.util.List; @Builder public record ConstraintsResponse( + @ArraySchema + @JsonAlias({"odrl:and"}) List and, + @ArraySchema + @JsonAlias({"odrl:or"}) List or ) { + public static Constraints toDomain(ConstraintsResponse constraintsResponse){ + if (constraintsResponse == null) { + return null; + } + return Constraints.builder() + .and(ConstraintResponse.toDomain(constraintsResponse.and)) + .or(ConstraintResponse.toDomain(constraintsResponse.or)) + .build(); + } } diff --git a/tx-models/src/main/java/policies/response/IrsPolicyResponse.java b/tx-models/src/main/java/policies/response/IrsPolicyResponse.java index f8d2837ae6..09908acb57 100644 --- a/tx-models/src/main/java/policies/response/IrsPolicyResponse.java +++ b/tx-models/src/main/java/policies/response/IrsPolicyResponse.java @@ -31,6 +31,7 @@ import java.time.OffsetDateTime; import java.util.List; import java.util.Map; +import java.util.Optional; import static org.apache.commons.collections4.ListUtils.emptyIfNull; @@ -86,46 +87,4 @@ public record IrsPolicyResponse(@JsonFormat(shape = JsonFormat.Shape.STRING) Off } ] """; - - public static List toResponse(Map> allPolicies) { - return allPolicies.entrySet().stream() - .flatMap(entry -> entry.getValue().stream() - .map(policy -> toResponse(policy, entry.getKey()))) - .toList(); - } - - public static PolicyResponse toResponse(IrsPolicyResponse policy, String bpn) { - return PolicyResponse.builder() - .policyId(policy.payload().policyId()) - .validUntil(policy.payload().policy().getValidUntil()) - .createdOn(policy.payload().policy().getCreatedOn()) - .permissions(map(policy.payload().policy())) - .businessPartnerNumber(bpn) - .build(); - } - - private static List map(Policy policy) { - - return policy.getPermissions().stream().map(permission -> - new PermissionResponse(PolicyTypeResponse.valueOf(permission.getAction().name()), map(permission))) - .toList(); - } - - private static ConstraintsResponse map(Permission permission) { - return ConstraintsResponse.builder() - .and(mapConstraints(emptyIfNull(permission.getConstraint().getAnd()))) - .or(mapConstraints(emptyIfNull(permission.getConstraint().getOr()))) - .build(); - - } - - private static List mapConstraints(List constraints) { - return constraints.stream().map(constraint -> ConstraintResponse.builder() - .leftOperand(constraint.getLeftOperand()) - .operatorTypeResponse(OperatorTypeResponse.valueOf(StringUtils.upperCase(constraint.getOperator().getOperatorType().getCode()))) - .rightOperand(constraint.getRightOperand()) - .build()) - .toList(); - } - } diff --git a/tx-models/src/main/java/policies/response/OperatorResponse.java b/tx-models/src/main/java/policies/response/OperatorResponse.java new file mode 100644 index 0000000000..08459f9b8c --- /dev/null +++ b/tx-models/src/main/java/policies/response/OperatorResponse.java @@ -0,0 +1,49 @@ +/******************************************************************************** + * Copyright (c) 2024 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 + ********************************************************************************/ +package policies.response; + +import com.fasterxml.jackson.annotation.JsonAlias; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import org.eclipse.tractusx.irs.edc.client.policy.OperatorType; +import policies.response.OperatorTypeResponse; + +import java.util.Arrays; +@Builder +@Schema +public record OperatorResponse( + @JsonProperty("@id") + @Schema( + implementation = OperatorType.class, + example = "odrl:eq" + ) + OperatorTypeResponse operatorType +) { + public static OperatorType toDomain(OperatorTypeResponse operatorTypeResponse) { + if (operatorTypeResponse == null) { + return null; + } + + return Arrays.stream(OperatorType.values()) + .filter(type -> type.getCode().equals(operatorTypeResponse.code)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("Unknown code: " + operatorTypeResponse.code)); + } +} diff --git a/tx-models/src/main/java/policies/response/OperatorTypeResponse.java b/tx-models/src/main/java/policies/response/OperatorTypeResponse.java index 316a075248..16c9427def 100644 --- a/tx-models/src/main/java/policies/response/OperatorTypeResponse.java +++ b/tx-models/src/main/java/policies/response/OperatorTypeResponse.java @@ -19,9 +19,14 @@ package policies.response; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import lombok.Getter; +import org.eclipse.tractusx.irs.edc.client.policy.OperatorType; + +import java.util.NoSuchElementException; +import java.util.stream.Stream; @JsonSerialize( @@ -64,4 +69,20 @@ public enum OperatorTypeResponse { this.label = label; } + @JsonCreator + public static OperatorTypeResponse fromValue(String value) { + String operator; + if (value.startsWith("odrl:")) { + operator = value.substring(5); + } else { + operator = value; + } + + return (OperatorTypeResponse) Stream.of(values()).filter((operatorType) -> { + return operatorType.code.equals(operator); + }).findFirst().orElseThrow(() -> { + return new NoSuchElementException("Unsupported OperatorType: " + operator); + }); + } + } diff --git a/tx-models/src/main/java/policies/response/PermissionResponse.java b/tx-models/src/main/java/policies/response/PermissionResponse.java index 3555053b9c..83df338b5c 100644 --- a/tx-models/src/main/java/policies/response/PermissionResponse.java +++ b/tx-models/src/main/java/policies/response/PermissionResponse.java @@ -18,11 +18,51 @@ ********************************************************************************/ package policies.response; +import com.fasterxml.jackson.annotation.JsonAlias; import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import org.eclipse.tractusx.irs.edc.client.policy.Permission; +import org.eclipse.tractusx.irs.edc.client.policy.Policy; +import org.eclipse.tractusx.irs.edc.client.policy.PolicyType; +import java.util.List; +import java.util.stream.Collectors; + +@Builder public record PermissionResponse( - @Schema(example = "USE") + @Schema( + implementation = PolicyType.class, + example = "use" + ) + @JsonAlias({"odrl:action"}) PolicyTypeResponse action, - ConstraintsResponse constraints + + @Schema + @JsonAlias({"odrl:constraint"}) + ConstraintsResponse constraint ) { + + public static PolicyType toDomain(PolicyTypeResponse response){ + return switch (response) { + case ACCESS -> PolicyType.ACCESS; + case USE -> PolicyType.USE; + }; + } + public static List toDomain(List permissionResponses) { + if (permissionResponses == null) { + return null; + } + return permissionResponses.stream() + .map(PermissionResponse::toDomain) + .collect(Collectors.toList()); + } + public static Permission toDomain(PermissionResponse permissionResponse) { + if (permissionResponse == null) { + return null; + } + return Permission.builder() + .action(toDomain(permissionResponse.action)) + .constraint(ConstraintsResponse.toDomain(permissionResponse.constraint)) + .build(); + } } diff --git a/tx-models/src/main/java/policies/response/PolicyResponse.java b/tx-models/src/main/java/policies/response/PolicyResponse.java index 88e98eb0ce..a531532d60 100644 --- a/tx-models/src/main/java/policies/response/PolicyResponse.java +++ b/tx-models/src/main/java/policies/response/PolicyResponse.java @@ -19,10 +19,12 @@ package policies.response; +import com.fasterxml.jackson.annotation.JsonAlias; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import common.CustomOffsetDateTimeSerializer; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; +import org.eclipse.tractusx.irs.edc.client.policy.Policy; import java.time.OffsetDateTime; import java.util.List; @@ -36,6 +38,22 @@ public record PolicyResponse( OffsetDateTime createdOn, @JsonSerialize(using = CustomOffsetDateTimeSerializer.class) OffsetDateTime validUntil, + + @JsonAlias({"odrl:permission"}) List permissions, String businessPartnerNumber) { + + public static Policy toDomain(PolicyResponse policyResponse){ + if (policyResponse == null) { + return null; + } + + return Policy.builder() + .policyId(policyResponse.policyId) + .createdOn(policyResponse.createdOn) + .validUntil(policyResponse.validUntil) + .permissions(PermissionResponse.toDomain(policyResponse.permissions)) + .build(); + } + } diff --git a/tx-models/src/main/java/policies/response/PolicyTypeResponse.java b/tx-models/src/main/java/policies/response/PolicyTypeResponse.java index 91ea12c0e6..33dccc0168 100644 --- a/tx-models/src/main/java/policies/response/PolicyTypeResponse.java +++ b/tx-models/src/main/java/policies/response/PolicyTypeResponse.java @@ -18,8 +18,23 @@ ********************************************************************************/ package policies.response; +import com.fasterxml.jackson.annotation.JsonValue; +import lombok.Generated; + public enum PolicyTypeResponse { - ACCESS, - USE + ACCESS("access"), + USE("use"); + @JsonValue + private final String value; + + @Generated + public String getValue() { + return this.value; + } + + @Generated + PolicyTypeResponse(String value) { + this.value = value; + } }