Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore[1194]: fixed bug #1197

Open
wants to merge 24 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -221,7 +222,6 @@ export class PolicyEditorComponent {
}
*/
updatePolicyForm(policy: Policy) {

const isFromTemplate = !policy?.permissions[0]?.constraints;
this.policyForm.patchValue({
policyName: policy?.policyName,
Expand Down Expand Up @@ -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': {
Expand All @@ -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(),
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/app/modules/page/policies/model/policy.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -127,6 +127,7 @@ export function getOperatorTypeSign(type: OperatorType): string {
}
}


export enum ConstraintLogicType {
AND = 'AND',
OR = 'OR',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -379,6 +380,13 @@ ResponseEntity<ErrorResponse> handleUnsupportedSearchCriteriaFieldException(Unsu
.body(new ErrorResponse(exception.getMessage()));
}

@ExceptionHandler(PolicyNotValidException.class)
ResponseEntity<ErrorResponse> handlePolicyNotValidException(PolicyNotValidException exception) {
log.warn("PolicyNotValidException", exception);
return ResponseEntity.status(BAD_REQUEST)
.body(new ErrorResponse(exception.getMessage()));
}

@ExceptionHandler(CreateNotificationContractException.class)
ResponseEntity<ErrorResponse> handleCreateNotificationContractException(CreateNotificationContractException exception) {
log.warn("handleCreateNotificationContractException", exception);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,16 @@
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;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import static policies.response.PolicyResponse.toDomain;

@Configuration
@ConfigurationPropertiesScan(basePackages = "org.eclipse.tractusx.traceability.*")
@EnableWebMvc
Expand Down Expand Up @@ -105,8 +108,8 @@ private List<AcceptedPolicy> createIrsAcceptedPolicies() {

// Map the IrsPolicyResponse objects to AcceptedPolicy objects
List<AcceptedPolicy> 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ private static List<EdcPolicyPermission> mapToPermissions(List<PermissionRespons
return permissions.stream().map(permission -> 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();
}
Expand All @@ -79,7 +79,7 @@ private static List<EdcPolicyPermissionConstraintExpression> mapToConstraintExpr
.leftOperand(constraint.leftOperand())
.rightOperand(constraint.rightOperand())
.operator(EdcOperator.builder()
.operatorId("odrl:" + constraint.operatorTypeResponse().getCode())
.operatorId("odrl:" + constraint.operator().operatorType().getCode())
.build())
.build())
.toList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public class PolicyController {
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class)))})
@GetMapping()
public Map<String, List<IrsPolicyResponse>> getPolicies() {
public Map<String, List<PolicyResponse>> getPolicies() {
return policyService.getIrsPolicies();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
public interface PolicyService {
List<PolicyResponse> getPolicies();

Map<String, List<IrsPolicyResponse>> getIrsPolicies();
Map<String, List<PolicyResponse>> getIrsPolicies();

PolicyResponse getPolicy(String id);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,21 @@
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;
import policies.response.CreatePolicyResponse;
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
Expand All @@ -45,33 +48,46 @@ public class PolicyServiceImpl implements PolicyService {
private final EdcNotificationContractService edcNotificationContractService;

@Override
public Map<String, List<IrsPolicyResponse>> getIrsPolicies() {
return policyRepository.getPolicies();
public Map<String, List<PolicyResponse>> getIrsPolicies() {
Map<String, List<IrsPolicyResponse>> 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<PolicyResponse> getPolicies() {
Map<String, List<IrsPolicyResponse>> 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<String, Optional<IrsPolicyResponse>> 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
Expand All @@ -82,8 +98,12 @@ public void deletePolicy(String id) {

@Override
public void updatePolicy(UpdatePolicyRequest updatePolicyRequest) {
if(updatePolicyRequest.validUntil().isAfter(Instant.now())){
policyRepository.updatePolicy(updatePolicyRequest);
ds-lcapellino marked this conversation as resolved.
Show resolved Hide resolved
edcNotificationContractService.updateNotificationContractDefinitions();
return;
}
throw new PolicyNotValidException("Policy is not valid because of a not accepted validUntil value " +updatePolicyRequest);
}


Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -86,13 +92,14 @@ public Optional<PolicyResponse> 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());
}

}
Expand Down Expand Up @@ -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);
Expand Down
Loading
Loading