From 7ae9a6e9c95abb5baaa4a6fce2bfef3989840d08 Mon Sep 17 00:00:00 2001 From: Mohammad Ghazanfar Ali Danish Date: Thu, 29 Aug 2024 23:11:56 +0200 Subject: [PATCH] Includes AAS Registry Signed-off-by: Mohammad Ghazanfar Ali Danish --- .../pom.xml | 4 + .../AuthorizedAasRegistryConfiguration.java | 8 + .../AasRegistryTargetInformationAdapter.java | 87 +++++++++++ ...sRegistryTargetInformationAdapterTest.java | 143 ++++++++++++++++++ 4 files changed, 242 insertions(+) create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-authorization/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/authorization/rbac/backend/submodel/AasRegistryTargetInformationAdapter.java create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-authorization/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/authorization/AasRegistryTargetInformationAdapterTest.java diff --git a/basyx.aasregistry/basyx.aasregistry-feature-authorization/pom.xml b/basyx.aasregistry/basyx.aasregistry-feature-authorization/pom.xml index d36eeabcd..be57092e4 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-authorization/pom.xml +++ b/basyx.aasregistry/basyx.aasregistry-feature-authorization/pom.xml @@ -61,5 +61,9 @@ org.eclipse.digitaltwin.basyx basyx.authorization.rules.rbac.backend.inmemory + + org.eclipse.digitaltwin.basyx + basyx.authorization.rules.rbac.backend.submodel + diff --git a/basyx.aasregistry/basyx.aasregistry-feature-authorization/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/authorization/AuthorizedAasRegistryConfiguration.java b/basyx.aasregistry/basyx.aasregistry-feature-authorization/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/authorization/AuthorizedAasRegistryConfiguration.java index 8c34ce5f7..b59a03471 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-authorization/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/authorization/AuthorizedAasRegistryConfiguration.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-authorization/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/authorization/AuthorizedAasRegistryConfiguration.java @@ -26,12 +26,14 @@ package org.eclipse.digitaltwin.basyx.aasregistry.feature.authorization; import org.eclipse.digitaltwin.basyx.aasregistry.feature.authorization.rbac.AasRegistryTargetPermissionVerifier; +import org.eclipse.digitaltwin.basyx.aasregistry.feature.authorization.rbac.backend.submodel.AasRegistryTargetInformationAdapter; import org.eclipse.digitaltwin.basyx.authorization.CommonAuthorizationProperties; import org.eclipse.digitaltwin.basyx.authorization.rbac.RbacPermissionResolver; import org.eclipse.digitaltwin.basyx.authorization.rbac.RbacStorage; import org.eclipse.digitaltwin.basyx.authorization.rbac.RoleProvider; import org.eclipse.digitaltwin.basyx.authorization.rbac.SimpleRbacPermissionResolver; import org.eclipse.digitaltwin.basyx.authorization.rbac.TargetPermissionVerifier; +import org.eclipse.digitaltwin.basyx.authorization.rules.rbac.backend.submodel.TargetInformationAdapter; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -54,5 +56,11 @@ public TargetPermissionVerifier getAasTargetPermis public RbacPermissionResolver getAasPermissionResolver(RbacStorage rbacStorage, RoleProvider roleProvider, TargetPermissionVerifier targetPermissionVerifier) { return new SimpleRbacPermissionResolver<>(rbacStorage, roleProvider, targetPermissionVerifier); } + + @Bean + public TargetInformationAdapter getAasRegistryTargetInformationAdapter() { + + return new AasRegistryTargetInformationAdapter(); + } } diff --git a/basyx.aasregistry/basyx.aasregistry-feature-authorization/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/authorization/rbac/backend/submodel/AasRegistryTargetInformationAdapter.java b/basyx.aasregistry/basyx.aasregistry-feature-authorization/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/authorization/rbac/backend/submodel/AasRegistryTargetInformationAdapter.java new file mode 100644 index 000000000..ee37eaadf --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-authorization/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/authorization/rbac/backend/submodel/AasRegistryTargetInformationAdapter.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.aasregistry.feature.authorization.rbac.backend.submodel; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.eclipse.digitaltwin.aas4j.v3.model.Property; +import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElement; +import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElementCollection; +import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElementList; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultProperty; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSubmodelElementCollection; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSubmodelElementList; +import org.eclipse.digitaltwin.basyx.aasregistry.feature.authorization.AasRegistryTargetInformation; +import org.eclipse.digitaltwin.basyx.authorization.rbac.TargetInformation; +import org.eclipse.digitaltwin.basyx.authorization.rules.rbac.backend.submodel.TargetInformationAdapter; +import org.eclipse.digitaltwin.basyx.core.exceptions.InvalidTargetInformationException; + +/** + * An implementation of the {@link TargetInformationAdapter} to adapt with Aas + * {@link TargetInformation} + * + * @author danish + */ +public class AasRegistryTargetInformationAdapter implements TargetInformationAdapter { + + @Override + public SubmodelElementCollection adapt(TargetInformation targetInformation) { + + SubmodelElementCollection targetInformationSMC = new DefaultSubmodelElementCollection.Builder().idShort("targetInformation").build(); + + SubmodelElementList aasId = new DefaultSubmodelElementList.Builder().idShort("aasIds").build(); + + List aasIds = ((AasRegistryTargetInformation) targetInformation).getAasIds().stream().map(this::transform).collect(Collectors.toList()); + aasId.setValue(aasIds); + + targetInformationSMC.setValue(Arrays.asList(aasId)); + + return targetInformationSMC; + } + + @Override + public TargetInformation adapt(SubmodelElementCollection targetInformation) { + + SubmodelElement aasIdSubmodelElement = targetInformation.getValue().stream().filter(sme -> sme.getIdShort().equals("aasIds")).findAny().orElseThrow( + () -> new InvalidTargetInformationException("The TargetInformation defined in the SubmodelElementCollection Rule with id: " + targetInformation.getIdShort() + " is not compatible with the " + getClass().getName())); + + if (!(aasIdSubmodelElement instanceof SubmodelElementList)) + throw new InvalidTargetInformationException("The TargetInformation defined in the SubmodelElementCollection Rule with id: " + targetInformation.getIdShort() + " is not compatible with the " + getClass().getName()); + + SubmodelElementList aasIdList = (SubmodelElementList) aasIdSubmodelElement; + + List aasIds = aasIdList.getValue().stream().map(Property.class::cast).map(Property::getValue).collect(Collectors.toList()); + + return new AasRegistryTargetInformation(aasIds); + } + + private Property transform(String aasId) { + return new DefaultProperty.Builder().value(aasId).build(); + } + +} diff --git a/basyx.aasregistry/basyx.aasregistry-feature-authorization/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/authorization/AasRegistryTargetInformationAdapterTest.java b/basyx.aasregistry/basyx.aasregistry-feature-authorization/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/authorization/AasRegistryTargetInformationAdapterTest.java new file mode 100644 index 000000000..d3bac91be --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-authorization/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/authorization/AasRegistryTargetInformationAdapterTest.java @@ -0,0 +1,143 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.aasregistry.regression.feature.authorization; + +import static org.junit.Assert.*; +import org.eclipse.digitaltwin.aas4j.v3.model.Property; +import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElement; +import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElementCollection; +import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElementList; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultProperty; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSubmodelElementCollection; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSubmodelElementList; +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import org.eclipse.digitaltwin.basyx.aasregistry.feature.authorization.AasRegistryTargetInformation; +import org.eclipse.digitaltwin.basyx.aasregistry.feature.authorization.rbac.backend.submodel.AasRegistryTargetInformationAdapter; +import org.eclipse.digitaltwin.basyx.authorization.rbac.TargetInformation; +import org.eclipse.digitaltwin.basyx.core.exceptions.InvalidTargetInformationException; + +/** + * Tests {@link AasRegistryTargetInformationAdapter} + * + * @author danish + */ +public class AasRegistryTargetInformationAdapterTest { + + private AasRegistryTargetInformationAdapter aasRegistryTargetInformationAdapter; + + @Before + public void setUp() { + aasRegistryTargetInformationAdapter = new AasRegistryTargetInformationAdapter(); + } + + @Test + public void testAdaptTargetInformationToSubmodelElementCollection() { + + List aasIds = Arrays.asList("aasId1", "aasId2"); + TargetInformation targetInformation = new AasRegistryTargetInformation(aasIds); + + SubmodelElementCollection result = aasRegistryTargetInformationAdapter.adapt(targetInformation); + + assertEquals("targetInformation", result.getIdShort()); + + List elements = result.getValue(); + assertEquals(1, elements.size()); + + SubmodelElementList aasIdList = (SubmodelElementList) elements.get(0); + assertEquals("aasIds", aasIdList.getIdShort()); + + List actualAasIds = aasIdList.getValue().stream().map(Property.class::cast).map(Property::getValue).map(String::valueOf).collect(Collectors.toList()); + assertEquals(aasIds, actualAasIds); + } + + @Test + public void testAdaptSubmodelElementCollectionToTargetInformation() { + + List expectedAasIds = Arrays.asList("aasId1", "aasId2"); + List aasIdProperties = expectedAasIds.stream().map(aasId -> new DefaultProperty.Builder().value(aasId).build()).collect(Collectors.toList()); + + SubmodelElementList aasIdList = new DefaultSubmodelElementList.Builder().idShort("aasIds").value(aasIdProperties).build(); + + SubmodelElementCollection targetInformationSMC = new DefaultSubmodelElementCollection.Builder().idShort("targetInformation").value(Collections.singletonList(aasIdList)).build(); + + TargetInformation result = aasRegistryTargetInformationAdapter.adapt(targetInformationSMC); + + assertTrue(result instanceof AasRegistryTargetInformation); + assertEquals(expectedAasIds, ((AasRegistryTargetInformation) result).getAasIds()); + } + + @Test + public void testAdaptTargetInformationWithEmptyAasIds() { + + List aasIds = Collections.emptyList(); + TargetInformation targetInformation = new AasRegistryTargetInformation(aasIds); + + SubmodelElementCollection result = aasRegistryTargetInformationAdapter.adapt(targetInformation); + + assertEquals("targetInformation", result.getIdShort()); + + List elements = result.getValue(); + assertEquals(1, elements.size()); + + SubmodelElementList aasIdList = (SubmodelElementList) elements.get(0); + assertEquals("aasIds", aasIdList.getIdShort()); + + List actualAasIds = aasIdList.getValue().stream() + .map(Property.class::cast) + .map(Property::getValue) + .map(String::valueOf) + .collect(Collectors.toList()); + assertTrue(actualAasIds.isEmpty()); + } + + @Test(expected = InvalidTargetInformationException.class) + public void testAdaptSubmodelElementCollectionWithInvalidStructure() { + + SubmodelElementCollection targetInformationSMC = new DefaultSubmodelElementCollection.Builder().idShort("targetInformation") + .value(Collections.singletonList(new DefaultProperty.Builder().idShort("invalidElement").value("value").build())) + .build(); + + aasRegistryTargetInformationAdapter.adapt(targetInformationSMC); + } + + @Test(expected = InvalidTargetInformationException.class) + public void testAdaptSubmodelElementCollectionWithoutAasIds() { + + SubmodelElementCollection targetInformationSMC = new DefaultSubmodelElementCollection.Builder().idShort("targetInformation") + .value(Collections.emptyList()) + .build(); + + aasRegistryTargetInformationAdapter.adapt(targetInformationSMC); + } + +}