diff --git a/docs/src/api/irs-v1.0.yaml b/docs/src/api/irs-v1.0.yaml index 22573c9b15..92c620c173 100644 --- a/docs/src/api/irs-v1.0.yaml +++ b/docs/src/api/irs-v1.0.yaml @@ -1610,11 +1610,54 @@ components: type: string manufacturerName: type: string + Constraint: + type: object + additionalProperties: false + properties: + leftOperand: + type: string + operator: + type: string + enum: + - eq + - neq + - lt + - gt + - in + - lteq + - gteq + - isA + - hasPart + - isPartOf + - isOneOf + - isAllOf + - isNoneOf + rightOperand: + type: array + items: + type: string + Constraints: + type: object + additionalProperties: false + properties: + and: + type: array + items: + $ref: '#/components/schemas/Constraint' + or: + type: array + items: + $ref: '#/components/schemas/Constraint' CreatePolicyRequest: type: object additionalProperties: false description: Request to add a policy properties: + permissions: + type: array + description: List of permissions that will be added to the Policy on creation. + items: + $ref: '#/components/schemas/Permission' policyId: type: string description: The ID of the policy to add @@ -1623,6 +1666,7 @@ components: format: date-time description: Timestamp after which the policy will no longer be accepted in negotiations required: + - permissions - policyId - validUntil EdcNotification: @@ -2040,6 +2084,19 @@ components: required: - bpn - globalAssetId + Permission: + type: object + additionalProperties: false + properties: + action: + type: string + enum: + - ACCESS + - USE + constraints: + type: array + items: + $ref: '#/components/schemas/Constraints' Policy: type: object additionalProperties: false @@ -2047,6 +2104,10 @@ components: createdOn: type: string format: date-time + permissions: + type: array + items: + $ref: '#/components/schemas/Permission' policyId: type: string validUntil: diff --git a/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/models/Constraint.java b/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/models/Constraint.java new file mode 100644 index 0000000000..b541e612ed --- /dev/null +++ b/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/models/Constraint.java @@ -0,0 +1,44 @@ +/******************************************************************************** + * Copyright (c) 2021,2022,2023 + * 2022: ZF Friedrichshafen AG + * 2022: ISTOS GmbH + * 2022,2023: Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * 2022,2023: BOSCH AG + * Copyright (c) 2021,2022,2023 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.irs.policystore.models; + +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * A Constraint object used as an element of collection in Permission + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class Constraint { + + private String leftOperand; + private OperatorType operator; + private List rightOperand; + +} diff --git a/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/models/Constraints.java b/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/models/Constraints.java new file mode 100644 index 0000000000..efaf2722a5 --- /dev/null +++ b/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/models/Constraints.java @@ -0,0 +1,44 @@ +/******************************************************************************** + * Copyright (c) 2021,2022,2023 + * 2022: ZF Friedrichshafen AG + * 2022: ISTOS GmbH + * 2022,2023: Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * 2022,2023: BOSCH AG + * Copyright (c) 2021,2022,2023 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.irs.policystore.models; + +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * A Constraint containing two collections of Constraints + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +@SuppressWarnings("PMD.ShortVariable") +public class Constraints { + + private List and; + private List or; + +} diff --git a/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/models/CreatePolicyRequest.java b/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/models/CreatePolicyRequest.java index 50fd21bb0d..55af1f8ee8 100644 --- a/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/models/CreatePolicyRequest.java +++ b/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/models/CreatePolicyRequest.java @@ -24,6 +24,7 @@ package org.eclipse.tractusx.irs.policystore.models; import java.time.OffsetDateTime; +import java.util.List; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; @@ -37,6 +38,8 @@ @Schema(description = "Request to add a policy") public record CreatePolicyRequest(@Schema(description = "The ID of the policy to add") @NotNull String policyId, - @Schema(description = "Timestamp after which the policy will no longer be accepted in negotiations") @NotNull OffsetDateTime validUntil) { + @Schema(description = "Timestamp after which the policy will no longer be accepted in negotiations") @NotNull OffsetDateTime validUntil, + @Schema(description = "List of permissions that will be added to the Policy on creation.") @NotNull List permissions + ) { } diff --git a/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/models/OperatorType.java b/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/models/OperatorType.java new file mode 100644 index 0000000000..1389af33a5 --- /dev/null +++ b/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/models/OperatorType.java @@ -0,0 +1,78 @@ +/******************************************************************************** + * Copyright (c) 2021,2022,2023 + * 2022: ZF Friedrichshafen AG + * 2022: ISTOS GmbH + * 2022,2023: Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * 2022,2023: BOSCH AG + * Copyright (c) 2021,2022,2023 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.irs.policystore.models; + +import java.util.NoSuchElementException; +import java.util.stream.Stream; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Getter; + +/** + * List of Operator Type that can be used to build Constraints + */ +@JsonSerialize(using = ToStringSerializer.class) +@Getter +public enum OperatorType { + + EQ("eq", "Equals to"), + NEQ("neq", "Not equal to"), + LT("lt", "Less than"), + GT("gt", "Greater than"), + IN("in", "In"), + LTEQ("lteq", "Less than or equal to"), + GTEQ("gteq", "Greater than or equal to"), + ISA("isA", "Is a"), + HASPART("hasPart", "Has part"), + ISPARTOF("isPartOf", "Is part of"), + ISONEOF("isOneOf", "Is one of"), + ISALLOF("isAllOf", "Is all of"), + ISNONEOF("isNoneOf", "Is none of"); + + private final String code; + private final String label; + + OperatorType(final String code, final String label) { + this.code = code; + this.label = label; + } + + @JsonCreator + public static OperatorType fromValue(final String value) { + return Stream.of(OperatorType.values()) + .filter(operatorType -> operatorType.code.equals(value)) + .findFirst() + .orElseThrow(() -> new NoSuchElementException("Unsupported OperatorType: " + value)); + } + + /** + * @return convert OperatorType to string value + */ + @Override + public String toString() { + return code; + } +} diff --git a/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/models/Permission.java b/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/models/Permission.java new file mode 100644 index 0000000000..46e501ba5c --- /dev/null +++ b/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/models/Permission.java @@ -0,0 +1,44 @@ +/******************************************************************************** + * Copyright (c) 2021,2022,2023 + * 2022: ZF Friedrichshafen AG + * 2022: ISTOS GmbH + * 2022,2023: Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * 2022,2023: BOSCH AG + * Copyright (c) 2021,2022,2023 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.irs.policystore.models; + +import java.util.List; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * A Permission object gather PolicyType with list of Constraints and its relation + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class Permission { + + private PolicyType action; + private List constraints; + + +} diff --git a/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/models/Policy.java b/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/models/Policy.java index dac88b6c10..2a280ba360 100644 --- a/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/models/Policy.java +++ b/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/models/Policy.java @@ -24,6 +24,7 @@ package org.eclipse.tractusx.irs.policystore.models; import java.time.OffsetDateTime; +import java.util.List; import lombok.AllArgsConstructor; import lombok.Getter; @@ -40,6 +41,7 @@ public class Policy { private String policyId; private OffsetDateTime createdOn; private OffsetDateTime validUntil; + private List permissions; public Policy update(final OffsetDateTime validUntil) { this.validUntil = validUntil; diff --git a/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/models/PolicyType.java b/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/models/PolicyType.java new file mode 100644 index 0000000000..6ade98b194 --- /dev/null +++ b/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/models/PolicyType.java @@ -0,0 +1,33 @@ +/******************************************************************************** + * Copyright (c) 2021,2022,2023 + * 2022: ZF Friedrichshafen AG + * 2022: ISTOS GmbH + * 2022,2023: Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * 2022,2023: BOSCH AG + * Copyright (c) 2021,2022,2023 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.irs.policystore.models; + +/** + * A PolicyType object use in Permission + */ +public enum PolicyType { + + ACCESS, USE + +} diff --git a/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/services/PolicyStoreService.java b/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/services/PolicyStoreService.java index c8dc6dd2fd..16a1e89caf 100644 --- a/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/services/PolicyStoreService.java +++ b/irs-policy-store/src/main/java/org/eclipse/tractusx/irs/policystore/services/PolicyStoreService.java @@ -25,14 +25,20 @@ import java.time.Clock; import java.time.OffsetDateTime; +import java.util.Collections; import java.util.List; 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.policystore.exceptions.PolicyStoreException; +import org.eclipse.tractusx.irs.policystore.models.Constraint; +import org.eclipse.tractusx.irs.policystore.models.Constraints; import org.eclipse.tractusx.irs.policystore.models.CreatePolicyRequest; +import org.eclipse.tractusx.irs.policystore.models.OperatorType; +import org.eclipse.tractusx.irs.policystore.models.Permission; import org.eclipse.tractusx.irs.policystore.models.Policy; +import org.eclipse.tractusx.irs.policystore.models.PolicyType; import org.eclipse.tractusx.irs.policystore.models.UpdatePolicyRequest; import org.eclipse.tractusx.irs.policystore.persistence.PolicyPersistence; import org.springframework.beans.factory.annotation.Value; @@ -60,16 +66,23 @@ public PolicyStoreService(@Value("${apiAllowedBpn:}") final String apiAllowedBpn this.allowedPoliciesFromConfig = allowedPolicies.stream() .map(p -> new Policy(p, OffsetDateTime.now(), OffsetDateTime.now().plusYears( - DEFAULT_POLICY_LIFETIME_YEARS))) + DEFAULT_POLICY_LIFETIME_YEARS), + createPermissionFrom(p))) .toList(); this.persistence = persistence; this.clock = clock; } + private List createPermissionFrom(final String name) { + return List.of(new Permission(PolicyType.USE, + List.of(new Constraints(List.of(new Constraint("PURPOSE", OperatorType.EQ, List.of(name))), + Collections.emptyList())))); + } + public void registerPolicy(final CreatePolicyRequest request) { log.info("Registering new policy with id {}, valid until {}", request.policyId(), request.validUntil()); try { - persistence.save(apiAllowedBpn, new Policy(request.policyId(), OffsetDateTime.now(clock), request.validUntil())); + persistence.save(apiAllowedBpn, new Policy(request.policyId(), OffsetDateTime.now(clock), request.validUntil(), request.permissions())); } catch (final PolicyStoreException e) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.getMessage(), e); } diff --git a/irs-policy-store/src/test/java/org/eclipse/tractusx/irs/policystore/controllers/PolicyStoreControllerTest.java b/irs-policy-store/src/test/java/org/eclipse/tractusx/irs/policystore/controllers/PolicyStoreControllerTest.java index 575f3a1c42..ea4846b7d0 100644 --- a/irs-policy-store/src/test/java/org/eclipse/tractusx/irs/policystore/controllers/PolicyStoreControllerTest.java +++ b/irs-policy-store/src/test/java/org/eclipse/tractusx/irs/policystore/controllers/PolicyStoreControllerTest.java @@ -28,10 +28,16 @@ import static org.mockito.Mockito.when; import java.time.OffsetDateTime; +import java.util.Collections; import java.util.List; +import org.eclipse.tractusx.irs.policystore.models.Constraint; +import org.eclipse.tractusx.irs.policystore.models.Constraints; import org.eclipse.tractusx.irs.policystore.models.CreatePolicyRequest; +import org.eclipse.tractusx.irs.policystore.models.OperatorType; +import org.eclipse.tractusx.irs.policystore.models.Permission; import org.eclipse.tractusx.irs.policystore.models.Policy; +import org.eclipse.tractusx.irs.policystore.models.PolicyType; import org.eclipse.tractusx.irs.policystore.models.UpdatePolicyRequest; import org.eclipse.tractusx.irs.policystore.services.PolicyStoreService; import org.junit.jupiter.api.BeforeEach; @@ -56,7 +62,7 @@ void setUp() { @Test void registerAllowedPolicy() { // arrange - final CreatePolicyRequest request = new CreatePolicyRequest("policyId", OffsetDateTime.now()); + final CreatePolicyRequest request = new CreatePolicyRequest("policyId", OffsetDateTime.now(), createPermissions()); // act testee.registerAllowedPolicy(request); @@ -68,7 +74,7 @@ void registerAllowedPolicy() { @Test void getPolicies() { // arrange - final List policies = List.of(new Policy("testId", OffsetDateTime.now(), OffsetDateTime.now())); + final List policies = List.of(new Policy("testId", OffsetDateTime.now(), OffsetDateTime.now(), createPermissions())); when(service.getStoredPolicies()).thenReturn(policies); // act @@ -99,4 +105,21 @@ void updateAllowedPolicy() { // assert verify(service).updatePolicy(policyId, request); } + + private List createPermissions() { + return List.of( + new Permission(PolicyType.USE, List.of(createConstraints())), + new Permission(PolicyType.ACCESS, List.of(createConstraints())) + ); + } + + private Constraints createConstraints() { + return new Constraints( + Collections.emptyList(), + List.of( + new Constraint("Membership", OperatorType.EQ, List.of("active")), + new Constraint("FrameworkAgreement.traceability", OperatorType.EQ, List.of("active")), + new Constraint("PURPOSE", OperatorType.EQ, List.of("ID 3.1 Trace"))) + ); + } } \ No newline at end of file diff --git a/irs-policy-store/src/test/java/org/eclipse/tractusx/irs/policystore/models/OperatorTypeTest.java b/irs-policy-store/src/test/java/org/eclipse/tractusx/irs/policystore/models/OperatorTypeTest.java new file mode 100644 index 0000000000..0e56f79a76 --- /dev/null +++ b/irs-policy-store/src/test/java/org/eclipse/tractusx/irs/policystore/models/OperatorTypeTest.java @@ -0,0 +1,29 @@ +package org.eclipse.tractusx.irs.policystore.models; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.NoSuchElementException; + +import org.junit.jupiter.api.Test; + +class OperatorTypeTest { + + @Test + void shouldCreateOperatorTypeFromString() { + assertThat(OperatorType.fromValue("gteq")).isEqualTo(OperatorType.GTEQ); + } + + @Test + void shouldThrowExceptionForInvalidString() { + assertThatThrownBy(() -> OperatorType.fromValue("abcd")) + .isInstanceOf(NoSuchElementException.class) + .hasMessageContaining("Unsupported OperatorType: abcd"); + } + + @Test + void shouldPrintProperString() { + assertThat(OperatorType.GTEQ.toString()).isEqualTo(OperatorType.GTEQ.getCode()); + } + +} \ No newline at end of file diff --git a/irs-policy-store/src/test/java/org/eclipse/tractusx/irs/policystore/persistence/PolicyPersistenceTest.java b/irs-policy-store/src/test/java/org/eclipse/tractusx/irs/policystore/persistence/PolicyPersistenceTest.java index f8e88ee22e..5b79634e86 100644 --- a/irs-policy-store/src/test/java/org/eclipse/tractusx/irs/policystore/persistence/PolicyPersistenceTest.java +++ b/irs-policy-store/src/test/java/org/eclipse/tractusx/irs/policystore/persistence/PolicyPersistenceTest.java @@ -23,6 +23,7 @@ ********************************************************************************/ package org.eclipse.tractusx.irs.policystore.persistence; +import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -34,6 +35,8 @@ import static org.mockito.Mockito.when; import java.time.OffsetDateTime; +import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Optional; @@ -69,7 +72,7 @@ void setUp() { @Test void save() throws BlobPersistenceException { // arrange - final var policy = new Policy("test", OffsetDateTime.now(), OffsetDateTime.now()); + final var policy = new Policy("test", OffsetDateTime.now(), OffsetDateTime.now(), emptyList()); // act testee.save("testBpn", policy); @@ -81,7 +84,7 @@ void save() throws BlobPersistenceException { @Test void saveDuplicate() throws BlobPersistenceException, JsonProcessingException { // arrange - final var policy = new Policy("test", OffsetDateTime.now(), OffsetDateTime.now()); + final var policy = new Policy("test", OffsetDateTime.now(), OffsetDateTime.now(), emptyList()); final var policies = List.of(policy); when(mockPersistence.getBlob(anyString())).thenReturn(Optional.of(mapper.writeValueAsBytes(policies))); @@ -92,7 +95,7 @@ void saveDuplicate() throws BlobPersistenceException, JsonProcessingException { @Test void saveWithError() throws BlobPersistenceException { // arrange - final var policy = new Policy("test", OffsetDateTime.now(), OffsetDateTime.now()); + final var policy = new Policy("test", OffsetDateTime.now(), OffsetDateTime.now(), emptyList()); when(mockPersistence.getBlob(any())).thenThrow( new BlobPersistenceException("test", new IllegalStateException())); @@ -103,7 +106,7 @@ void saveWithError() throws BlobPersistenceException { @Test void saveWithWriteError() throws BlobPersistenceException { // arrange - final var policy = new Policy("test", OffsetDateTime.now(), OffsetDateTime.now()); + final var policy = new Policy("test", OffsetDateTime.now(), OffsetDateTime.now(), emptyList()); doThrow(new BlobPersistenceException("test", new IllegalStateException())).when(mockPersistence) .putBlob(any(), any()); @@ -115,7 +118,7 @@ void saveWithWriteError() throws BlobPersistenceException { void delete() throws BlobPersistenceException, JsonProcessingException { // arrange final String policyId = "test"; - final var policy = new Policy(policyId, OffsetDateTime.now(), OffsetDateTime.now()); + final var policy = new Policy(policyId, OffsetDateTime.now(), OffsetDateTime.now(), emptyList()); final var policies = List.of(policy); when(mockPersistence.getBlob(anyString())).thenReturn(Optional.of(mapper.writeValueAsBytes(policies))); @@ -130,7 +133,7 @@ void delete() throws BlobPersistenceException, JsonProcessingException { void update() throws BlobPersistenceException, JsonProcessingException { // arrange final String policyId = "test"; - final var policy = new Policy(policyId, OffsetDateTime.now(), OffsetDateTime.now()); + final var policy = new Policy(policyId, OffsetDateTime.now(), OffsetDateTime.now(), emptyList()); final var policies = List.of(policy); when(mockPersistence.getBlob(anyString())).thenReturn(Optional.of(mapper.writeValueAsBytes(policies))); @@ -144,7 +147,7 @@ void update() throws BlobPersistenceException, JsonProcessingException { @Test void deleteShouldThrowExceptionIfPolicyWithIdDoesntExists() throws BlobPersistenceException, JsonProcessingException { // arrange - final var policy = new Policy("policyId", OffsetDateTime.now(), OffsetDateTime.now()); + final var policy = new Policy("policyId", OffsetDateTime.now(), OffsetDateTime.now(), emptyList()); when(mockPersistence.getBlob(anyString())).thenReturn(Optional.of(mapper.writeValueAsBytes(List.of(policy)))); // act @@ -155,7 +158,7 @@ void deleteShouldThrowExceptionIfPolicyWithIdDoesntExists() throws BlobPersisten void updateShouldThrowExceptionIfPolicyWithIdDoesntExists() throws BlobPersistenceException, JsonProcessingException { // arrange final OffsetDateTime now = OffsetDateTime.now(); - final var policy = new Policy("policyId", now, now); + final var policy = new Policy("policyId", now, now, emptyList()); when(mockPersistence.getBlob(anyString())).thenReturn(Optional.of(mapper.writeValueAsBytes(List.of(policy)))); // act @@ -165,7 +168,7 @@ void updateShouldThrowExceptionIfPolicyWithIdDoesntExists() throws BlobPersisten @Test void readAll() throws BlobPersistenceException, JsonProcessingException { // arrange - final var policy = new Policy("test", OffsetDateTime.now(), OffsetDateTime.now()); + final var policy = new Policy("test", OffsetDateTime.now(), OffsetDateTime.now(), emptyList()); final var policies = List.of(policy); when(mockPersistence.getBlob(anyString())).thenReturn(Optional.of(mapper.writeValueAsBytes(policies))); @@ -179,7 +182,7 @@ void readAll() throws BlobPersistenceException, JsonProcessingException { @Test void readAllWithError() throws BlobPersistenceException, JsonProcessingException { // arrange - final var policy = new Policy("test", OffsetDateTime.now(), OffsetDateTime.now()); + final var policy = new Policy("test", OffsetDateTime.now(), OffsetDateTime.now(), emptyList()); final var policies = List.of(policy); final var mapperMock = mock(ObjectMapper.class); when(mockPersistence.getBlob(anyString())).thenReturn(Optional.of(mapper.writeValueAsBytes(policies))); diff --git a/irs-policy-store/src/test/java/org/eclipse/tractusx/irs/policystore/services/PolicyStoreServiceTest.java b/irs-policy-store/src/test/java/org/eclipse/tractusx/irs/policystore/services/PolicyStoreServiceTest.java index fd89edca93..5ea951bafe 100644 --- a/irs-policy-store/src/test/java/org/eclipse/tractusx/irs/policystore/services/PolicyStoreServiceTest.java +++ b/irs-policy-store/src/test/java/org/eclipse/tractusx/irs/policystore/services/PolicyStoreServiceTest.java @@ -23,6 +23,7 @@ ********************************************************************************/ package org.eclipse.tractusx.irs.policystore.services; +import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; @@ -33,16 +34,24 @@ import java.time.Clock; import java.time.OffsetDateTime; +import java.util.Collections; import java.util.List; import org.eclipse.tractusx.irs.policystore.exceptions.PolicyStoreException; +import org.eclipse.tractusx.irs.policystore.models.Constraint; +import org.eclipse.tractusx.irs.policystore.models.Constraints; import org.eclipse.tractusx.irs.policystore.models.CreatePolicyRequest; +import org.eclipse.tractusx.irs.policystore.models.OperatorType; +import org.eclipse.tractusx.irs.policystore.models.Permission; import org.eclipse.tractusx.irs.policystore.models.Policy; +import org.eclipse.tractusx.irs.policystore.models.PolicyType; import org.eclipse.tractusx.irs.policystore.models.UpdatePolicyRequest; import org.eclipse.tractusx.irs.policystore.persistence.PolicyPersistence; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.web.server.ResponseStatusException; @@ -51,22 +60,26 @@ class PolicyStoreServiceTest { private static final String BPN = "testBpn"; + private static final String EXAMPLE_ALLOWED_NAME = "ID 3.0 Trace"; private PolicyStoreService testee; @Mock private PolicyPersistence persistence; + @Captor + ArgumentCaptor policyCaptor; + private final Clock clock = Clock.systemUTC(); @BeforeEach void setUp() { - testee = new PolicyStoreService(BPN, List.of(), persistence, clock); + testee = new PolicyStoreService(BPN, List.of(EXAMPLE_ALLOWED_NAME), persistence, clock); } @Test void registerPolicy() { // arrange - final var req = new CreatePolicyRequest("testId", OffsetDateTime.now(clock).plusMinutes(1)); + final var req = new CreatePolicyRequest("testId", OffsetDateTime.now(clock).plusMinutes(1), emptyList()); // act testee.registerPolicy(req); @@ -75,12 +88,30 @@ void registerPolicy() { verify(persistence).save(eq(BPN), any()); } + @Test + void registerPolicyWithPermission() { + // arrange + final var req = new CreatePolicyRequest("testId", OffsetDateTime.now(clock).plusMinutes(1), createPermissions()); + + // act + testee.registerPolicy(req); + + // assert + verify(persistence).save(eq(BPN), policyCaptor.capture()); + + assertThat(policyCaptor.getValue()).isNotNull(); + List permissionList = policyCaptor.getValue().getPermissions(); + assertThat(permissionList).hasSize(2); + assertThat(permissionList.get(0)).usingRecursiveComparison().isEqualTo(createPermissions().get(0)); + assertThat(permissionList.get(1)).usingRecursiveComparison().isEqualTo(createPermissions().get(1)); + } + @Test void registerPolicyShouldThrowResponseStatusException() { // act final String policyId = "testId"; doThrow(new PolicyStoreException("")).when(persistence).save(eq(BPN), any()); - final CreatePolicyRequest request = new CreatePolicyRequest(policyId, OffsetDateTime.now()); + final CreatePolicyRequest request = new CreatePolicyRequest(policyId, OffsetDateTime.now(), emptyList()); // assert assertThrows(ResponseStatusException.class, () -> testee.registerPolicy(request)); @@ -99,10 +130,39 @@ void getStoredPolicies() { assertThat(storedPolicies).hasSize(3); } + @Test + void getStoredPoliciesWhenEmpty() { + // act + final var defaultPolicies = testee.getStoredPolicies(); + + // assert + assertThat(defaultPolicies).hasSize(1); + List permissionList = defaultPolicies.get(0).getPermissions(); + assertThat(permissionList).hasSize(1); + } + private Policy createPolicy(final String policyId) { - return new Policy(policyId, OffsetDateTime.now(clock), OffsetDateTime.now(clock).plusDays(1)); + return new Policy(policyId, OffsetDateTime.now(clock), OffsetDateTime.now(clock).plusDays(1), emptyList()); } + private List createPermissions() { + return List.of( + new Permission(PolicyType.USE, List.of(createConstraints())), + new Permission(PolicyType.ACCESS, List.of(createConstraints())) + ); + } + + private Constraints createConstraints() { + return new Constraints( + Collections.emptyList(), + List.of( + new Constraint("Membership", OperatorType.EQ, List.of("active")), + new Constraint("FrameworkAgreement.traceability", OperatorType.EQ, List.of("active")), + new Constraint("PURPOSE", OperatorType.EQ, List.of("ID 3.1 Trace"))) + ); + } + + @Test void deletePolicy() { // act