diff --git a/CHANGELOG.md b/CHANGELOG.md index c39a0ef8..e4782a62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.4.2-RC1 +### Added +- Added API POST lookup/shellsByAssetLink to retrieve shell ids without base64 encryption. +- Added v3.1.0 postman collection for new API. +## fixed +- Fixed behaviour of access rule management in case of multiple specificAssetIds with same keys and different values. +- Update Springboot to version 3.2.4 + ## 0.4.1 ### Added - Added API POST lookup/shellsByAssetLink to retrieve shell ids without base64 encryption. diff --git a/DEPENDENCIES b/DEPENDENCIES index ec11fe8d..3e14cde6 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -22,23 +22,23 @@ maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.24.4, Apache-2.0, approved, cl maven/mavencentral/com.opencsv/opencsv/5.7.1, Apache-2.0, approved, clearlydefined maven/mavencentral/com.zaxxer/HikariCP/5.0.1, Apache-2.0, approved, clearlydefined maven/mavencentral/io.github.classgraph/classgraph/4.8.149, MIT, approved, CQ22530 -maven/mavencentral/io.micrometer/micrometer-commons/1.12.3, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #11679 -maven/mavencentral/io.micrometer/micrometer-core/1.12.3, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #11678 -maven/mavencentral/io.micrometer/micrometer-jakarta9/1.12.3, Apache-2.0, approved, #12923 -maven/mavencentral/io.micrometer/micrometer-observation/1.12.3, Apache-2.0, approved, #11680 +maven/mavencentral/io.micrometer/micrometer-commons/1.12.4, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #11679 +maven/mavencentral/io.micrometer/micrometer-core/1.12.4, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #11678 +maven/mavencentral/io.micrometer/micrometer-jakarta9/1.12.4, Apache-2.0, approved, #12923 +maven/mavencentral/io.micrometer/micrometer-observation/1.12.4, Apache-2.0, approved, #11680 maven/mavencentral/io.swagger.core.v3/swagger-annotations-jakarta/2.2.7, Apache-2.0, approved, #5947 maven/mavencentral/io.swagger.core.v3/swagger-annotations/2.0.0, Apache-2.0, approved, clearlydefined maven/mavencentral/io.swagger.core.v3/swagger-core-jakarta/2.2.7, Apache-2.0, approved, #5929 maven/mavencentral/io.swagger.core.v3/swagger-models-jakarta/2.2.7, Apache-2.0, approved, #5919 -maven/mavencentral/jakarta.activation/jakarta.activation-api/2.1.2, EPL-2.0 OR BSD-3-Clause OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jaf +maven/mavencentral/jakarta.activation/jakarta.activation-api/2.1.3, EPL-2.0 OR BSD-3-Clause OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jaf maven/mavencentral/jakarta.annotation/jakarta.annotation-api/2.1.1, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.ca -maven/mavencentral/jakarta.persistence/jakarta.persistence-api/3.1.0, EPL-2.0 OR BSD-3-Clause AND (EPL-2.0 OR BSD-3-Clause AND BSD-3-Clause), approved, #7696 +maven/mavencentral/jakarta.persistence/jakarta.persistence-api/3.1.0, EPL-2.0 OR BSD-3-Clause, approved, ee4j.jpa maven/mavencentral/jakarta.servlet/jakarta.servlet-api/6.0.0, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.servlet -maven/mavencentral/jakarta.transaction/jakarta.transaction-api/2.0.1, EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0, approved, #7697 +maven/mavencentral/jakarta.transaction/jakarta.transaction-api/2.0.1, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jta maven/mavencentral/jakarta.validation/jakarta.validation-api/3.0.2, Apache-2.0, approved, ee4j.validation maven/mavencentral/jakarta.websocket/jakarta.websocket-api/2.1.1, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.websocket maven/mavencentral/jakarta.websocket/jakarta.websocket-client-api/2.1.1, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.websocket -maven/mavencentral/jakarta.xml.bind/jakarta.xml.bind-api/4.0.1, BSD-3-Clause, approved, ee4j.jaxb +maven/mavencentral/jakarta.xml.bind/jakarta.xml.bind-api/4.0.2, BSD-3-Clause, approved, ee4j.jaxb maven/mavencentral/javax.activation/javax.activation-api/1.2.0, (CDDL-1.1 OR GPL-2.0 WITH Classpath-exception-2.0) AND Apache-2.0, approved, CQ18740 maven/mavencentral/javax.xml.bind/jaxb-api/2.3.1, CDDL-1.1 OR GPL-2.0-only WITH Classpath-exception-2.0, approved, CQ16911 maven/mavencentral/org.antlr/antlr4-runtime/4.13.0, BSD-3-Clause, approved, #10767 @@ -49,32 +49,32 @@ maven/mavencentral/org.apache.logging.log4j/log4j-api/2.21.1, Apache-2.0 AND (Ap maven/mavencentral/org.apache.logging.log4j/log4j-to-slf4j/2.21.1, Apache-2.0, approved, #11919 maven/mavencentral/org.aspectj/aspectjweaver/1.9.21, Apache-2.0 AND BSD-3-Clause AND EPL-1.0 AND BSD-3-Clause AND Apache-1.1, approved, #7695 maven/mavencentral/org.checkerframework/checker-qual/3.42.0, MIT, approved, clearlydefined -maven/mavencentral/org.eclipse.jetty.ee10.websocket/jetty-ee10-websocket-jakarta-client/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.ee10.websocket/jetty-ee10-websocket-jakarta-common/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.ee10.websocket/jetty-ee10-websocket-jakarta-server/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.ee10.websocket/jetty-ee10-websocket-jetty-server/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.ee10.websocket/jetty-ee10-websocket-servlet/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.ee10/jetty-ee10-annotations/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.ee10/jetty-ee10-plus/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.ee10/jetty-ee10-servlet/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.ee10/jetty-ee10-servlets/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.ee10/jetty-ee10-webapp/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.websocket/jetty-websocket-core-client/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.websocket/jetty-websocket-core-common/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.websocket/jetty-websocket-core-server/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.websocket/jetty-websocket-jetty-api/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty.websocket/jetty-websocket-jetty-common/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty/jetty-alpn-client/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty/jetty-client/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty/jetty-http/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty/jetty-io/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty/jetty-jndi/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty/jetty-plus/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty/jetty-security/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty/jetty-server/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty/jetty-session/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty/jetty-util/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.eclipse.jetty/jetty-xml/12.0.6, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.ee10.websocket/jetty-ee10-websocket-jakarta-client/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.ee10.websocket/jetty-ee10-websocket-jakarta-common/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.ee10.websocket/jetty-ee10-websocket-jakarta-server/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.ee10.websocket/jetty-ee10-websocket-jetty-server/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.ee10.websocket/jetty-ee10-websocket-servlet/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.ee10/jetty-ee10-annotations/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.ee10/jetty-ee10-plus/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.ee10/jetty-ee10-servlet/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.ee10/jetty-ee10-servlets/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.ee10/jetty-ee10-webapp/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.websocket/jetty-websocket-core-client/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.websocket/jetty-websocket-core-common/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.websocket/jetty-websocket-core-server/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.websocket/jetty-websocket-jetty-api/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty.websocket/jetty-websocket-jetty-common/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty/jetty-alpn-client/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty/jetty-client/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty/jetty-http/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty/jetty-io/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty/jetty-jndi/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty/jetty-plus/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty/jetty-security/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty/jetty-server/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty/jetty-session/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty/jetty-util/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty +maven/mavencentral/org.eclipse.jetty/jetty-xml/12.0.7, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.glassfish/jakarta.json/2.0.1, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jsonp maven/mavencentral/org.hibernate.orm/hibernate-core/6.4.4.Final, LGPL-2.1-or-later AND (EPL-2.0 OR BSD-3-Clause) AND MIT, approved, #12490 maven/mavencentral/org.hibernate.validator/hibernate-validator/8.0.1.Final, Apache-2.0, approved, clearlydefined @@ -93,42 +93,42 @@ maven/mavencentral/org.slf4j/slf4j-simple/2.0.7, MIT, approved, #10372 maven/mavencentral/org.springdoc/springdoc-openapi-starter-common/2.0.2, Apache-2.0, approved, #5920 maven/mavencentral/org.springdoc/springdoc-openapi-starter-webmvc-api/2.0.2, Apache-2.0, approved, #5950 maven/mavencentral/org.springdoc/springdoc-openapi-starter-webmvc-ui/2.0.2, Apache-2.0, approved, #5923 -maven/mavencentral/org.springframework.boot/spring-boot-actuator-autoconfigure/3.2.3, Apache-2.0, approved, #11921 -maven/mavencentral/org.springframework.boot/spring-boot-actuator/3.2.3, Apache-2.0, approved, #11918 -maven/mavencentral/org.springframework.boot/spring-boot-autoconfigure/3.2.3, Apache-2.0, approved, #11751 -maven/mavencentral/org.springframework.boot/spring-boot-starter-actuator/3.2.3, Apache-2.0, approved, #12918 -maven/mavencentral/org.springframework.boot/spring-boot-starter-aop/3.2.3, Apache-2.0, approved, #11928 -maven/mavencentral/org.springframework.boot/spring-boot-starter-data-jpa/3.2.3, Apache-2.0, approved, #11926 -maven/mavencentral/org.springframework.boot/spring-boot-starter-jdbc/3.2.3, Apache-2.0, approved, #11878 -maven/mavencentral/org.springframework.boot/spring-boot-starter-jetty/3.2.3, Apache-2.0, approved, #13220 -maven/mavencentral/org.springframework.boot/spring-boot-starter-json/3.2.3, Apache-2.0, approved, #11894 -maven/mavencentral/org.springframework.boot/spring-boot-starter-logging/3.2.3, Apache-2.0, approved, #11890 -maven/mavencentral/org.springframework.boot/spring-boot-starter-oauth2-resource-server/3.2.3, Apache-2.0, approved, #11931 -maven/mavencentral/org.springframework.boot/spring-boot-starter-validation/3.2.3, Apache-2.0, approved, #12921 -maven/mavencentral/org.springframework.boot/spring-boot-starter-web/3.2.3, Apache-2.0, approved, #11916 -maven/mavencentral/org.springframework.boot/spring-boot-starter/3.2.3, Apache-2.0, approved, #11935 -maven/mavencentral/org.springframework.boot/spring-boot/3.2.3, Apache-2.0, approved, #11752 -maven/mavencentral/org.springframework.data/spring-data-commons/3.2.3, Apache-2.0, approved, #11917 -maven/mavencentral/org.springframework.data/spring-data-jpa/3.2.3, Apache-2.0, approved, #11882 -maven/mavencentral/org.springframework.security/spring-security-config/6.2.2, Apache-2.0, approved, #11896 -maven/mavencentral/org.springframework.security/spring-security-core/6.2.2, Apache-2.0, approved, #11904 -maven/mavencentral/org.springframework.security/spring-security-crypto/6.2.2, Apache-2.0 AND ISC, approved, #11908 -maven/mavencentral/org.springframework.security/spring-security-oauth2-core/6.2.2, Apache-2.0, approved, #11925 -maven/mavencentral/org.springframework.security/spring-security-oauth2-jose/6.2.2, Apache-2.0, approved, #11893 -maven/mavencentral/org.springframework.security/spring-security-oauth2-resource-server/6.2.2, Apache-2.0, approved, #11920 -maven/mavencentral/org.springframework.security/spring-security-web/6.2.2, Apache-2.0, approved, #11911 -maven/mavencentral/org.springframework/spring-aop/6.1.4, Apache-2.0, approved, #11755 -maven/mavencentral/org.springframework/spring-aspects/6.1.4, Apache-2.0, approved, #11905 -maven/mavencentral/org.springframework/spring-beans/6.1.4, Apache-2.0, approved, #11754 -maven/mavencentral/org.springframework/spring-context/6.1.4, Apache-2.0, approved, #11753 -maven/mavencentral/org.springframework/spring-core/6.1.4, Apache-2.0 AND BSD-3-Clause, approved, #11750 -maven/mavencentral/org.springframework/spring-expression/6.1.4, Apache-2.0, approved, #11747 -maven/mavencentral/org.springframework/spring-jcl/6.1.4, Apache-2.0, approved, #11749 -maven/mavencentral/org.springframework/spring-jdbc/6.1.4, Apache-2.0, approved, #11897 -maven/mavencentral/org.springframework/spring-orm/6.1.4, Apache-2.0, approved, #11924 -maven/mavencentral/org.springframework/spring-tx/6.1.4, Apache-2.0, approved, #11901 -maven/mavencentral/org.springframework/spring-web/6.1.4, Apache-2.0, approved, #11748 -maven/mavencentral/org.springframework/spring-webmvc/6.1.4, Apache-2.0, approved, #11879 +maven/mavencentral/org.springframework.boot/spring-boot-actuator-autoconfigure/3.2.4, Apache-2.0, approved, #11921 +maven/mavencentral/org.springframework.boot/spring-boot-actuator/3.2.4, Apache-2.0, approved, #11918 +maven/mavencentral/org.springframework.boot/spring-boot-autoconfigure/3.2.4, Apache-2.0, approved, #11751 +maven/mavencentral/org.springframework.boot/spring-boot-starter-actuator/3.2.4, Apache-2.0, approved, #12918 +maven/mavencentral/org.springframework.boot/spring-boot-starter-aop/3.2.4, Apache-2.0, approved, #11928 +maven/mavencentral/org.springframework.boot/spring-boot-starter-data-jpa/3.2.4, Apache-2.0, approved, #11926 +maven/mavencentral/org.springframework.boot/spring-boot-starter-jdbc/3.2.4, Apache-2.0, approved, #11878 +maven/mavencentral/org.springframework.boot/spring-boot-starter-jetty/3.2.4, Apache-2.0, approved, #13220 +maven/mavencentral/org.springframework.boot/spring-boot-starter-json/3.2.4, Apache-2.0, approved, #11894 +maven/mavencentral/org.springframework.boot/spring-boot-starter-logging/3.2.4, Apache-2.0, approved, #11890 +maven/mavencentral/org.springframework.boot/spring-boot-starter-oauth2-resource-server/3.2.4, Apache-2.0, approved, #11931 +maven/mavencentral/org.springframework.boot/spring-boot-starter-validation/3.2.4, Apache-2.0, approved, #12921 +maven/mavencentral/org.springframework.boot/spring-boot-starter-web/3.2.4, Apache-2.0, approved, #11916 +maven/mavencentral/org.springframework.boot/spring-boot-starter/3.2.4, Apache-2.0, approved, #11935 +maven/mavencentral/org.springframework.boot/spring-boot/3.2.4, Apache-2.0, approved, #11752 +maven/mavencentral/org.springframework.data/spring-data-commons/3.2.4, Apache-2.0, approved, #11917 +maven/mavencentral/org.springframework.data/spring-data-jpa/3.2.4, Apache-2.0, approved, #11882 +maven/mavencentral/org.springframework.security/spring-security-config/6.2.3, Apache-2.0, approved, #11896 +maven/mavencentral/org.springframework.security/spring-security-core/6.2.3, Apache-2.0, approved, #11904 +maven/mavencentral/org.springframework.security/spring-security-crypto/6.2.3, Apache-2.0 AND ISC, approved, #11908 +maven/mavencentral/org.springframework.security/spring-security-oauth2-core/6.2.3, Apache-2.0, approved, #11925 +maven/mavencentral/org.springframework.security/spring-security-oauth2-jose/6.2.3, Apache-2.0, approved, #11893 +maven/mavencentral/org.springframework.security/spring-security-oauth2-resource-server/6.2.3, Apache-2.0, approved, #11920 +maven/mavencentral/org.springframework.security/spring-security-web/6.2.3, Apache-2.0, approved, #11911 +maven/mavencentral/org.springframework/spring-aop/6.1.5, Apache-2.0, approved, #11755 +maven/mavencentral/org.springframework/spring-aspects/6.1.5, Apache-2.0, approved, #11905 +maven/mavencentral/org.springframework/spring-beans/6.1.5, Apache-2.0, approved, #11754 +maven/mavencentral/org.springframework/spring-context/6.1.5, Apache-2.0, approved, #11753 +maven/mavencentral/org.springframework/spring-core/6.1.5, Apache-2.0 AND BSD-3-Clause, approved, #11750 +maven/mavencentral/org.springframework/spring-expression/6.1.5, Apache-2.0, approved, #11747 +maven/mavencentral/org.springframework/spring-jcl/6.1.5, Apache-2.0, approved, #11749 +maven/mavencentral/org.springframework/spring-jdbc/6.1.5, Apache-2.0, approved, #11897 +maven/mavencentral/org.springframework/spring-orm/6.1.5, Apache-2.0, approved, #11924 +maven/mavencentral/org.springframework/spring-tx/6.1.5, Apache-2.0, approved, #11901 +maven/mavencentral/org.springframework/spring-web/6.1.5, Apache-2.0, approved, #11748 +maven/mavencentral/org.springframework/spring-webmvc/6.1.5, Apache-2.0, approved, #11879 maven/mavencentral/org.webjars/swagger-ui/4.15.5, Apache-2.0 AND MIT, approved, #5921 maven/mavencentral/org.webjars/webjars-locator-core/0.55, MIT, approved, clearlydefined maven/mavencentral/org.yaml/snakeyaml/2.0, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #7275 diff --git a/access-control-service-interface/src/main/java/org/eclipse/tractusx/semantics/accesscontrol/api/model/ShellVisibilityCriteria.java b/access-control-service-interface/src/main/java/org/eclipse/tractusx/semantics/accesscontrol/api/model/ShellVisibilityCriteria.java index 9b640040..3ca0308e 100644 --- a/access-control-service-interface/src/main/java/org/eclipse/tractusx/semantics/accesscontrol/api/model/ShellVisibilityCriteria.java +++ b/access-control-service-interface/src/main/java/org/eclipse/tractusx/semantics/accesscontrol/api/model/ShellVisibilityCriteria.java @@ -20,10 +20,11 @@ package org.eclipse.tractusx.semantics.accesscontrol.api.model; +import java.util.Map; import java.util.Set; import lombok.NonNull; public record ShellVisibilityCriteria( - @NonNull String aasId, @NonNull Set visibleSpecificAssetIdNames, @NonNull Set visibleSemanticIds, boolean publicOnly) { + @NonNull String aasId, @NonNull Map> visibleSpecificAssetIdNames, @NonNull Set visibleSemanticIds, boolean publicOnly) { } diff --git a/access-control-service-interface/src/test/java/org/eclipse/tractusx/semantics/accesscontrol/api/model/ShellVisibilityCriteriaTest.java b/access-control-service-interface/src/test/java/org/eclipse/tractusx/semantics/accesscontrol/api/model/ShellVisibilityCriteriaTest.java index c36c7139..1ae76906 100644 --- a/access-control-service-interface/src/test/java/org/eclipse/tractusx/semantics/accesscontrol/api/model/ShellVisibilityCriteriaTest.java +++ b/access-control-service-interface/src/test/java/org/eclipse/tractusx/semantics/accesscontrol/api/model/ShellVisibilityCriteriaTest.java @@ -22,6 +22,7 @@ import static org.assertj.core.api.Assertions.*; +import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.stream.Stream; @@ -37,7 +38,7 @@ public static Stream nullProvider() { return Stream. builder() .add( Arguments.of( null, null, null, true ) ) .add( Arguments.of( UUID.randomUUID().toString(), null, null, true ) ) - .add( Arguments.of( null, Set.of(), null, false ) ) + .add( Arguments.of( null, Map.of(), null, false ) ) .add( Arguments.of( null, null, Set.of(), false ) ) .build(); } @@ -45,7 +46,7 @@ public static Stream nullProvider() { @ParameterizedTest @MethodSource( "nullProvider" ) void testConstructorCalledWithNullExpectException( - String aasId, Set visibleSpecificAssetIdNames, Set visibleSemanticIds, boolean publicOnly ) { + String aasId, Map> visibleSpecificAssetIdNames, Set visibleSemanticIds, boolean publicOnly ) { assertThatThrownBy( () -> new ShellVisibilityCriteria( aasId, visibleSpecificAssetIdNames, visibleSemanticIds, publicOnly ) ) .isExactlyInstanceOf( NullPointerException.class ); } @@ -53,7 +54,8 @@ void testConstructorCalledWithNullExpectException( @Test void testConstructorCalledWithValidDataExpectSuccess() { final String aasId = UUID.randomUUID().toString(); - final Set visibleSpecificAssetIdNames = Set.of( "name1" ); + + final Map> visibleSpecificAssetIdNames = Map.of( "name1", Set.of( "" ) ); final Set visibleSemanticIds = Set.of( "name2" ); final boolean publicOnly = true; diff --git a/access-control-service-sql-impl/src/main/java/org/eclipse/tractusx/semantics/accesscontrol/sql/service/SqlBackedAccessControlRuleService.java b/access-control-service-sql-impl/src/main/java/org/eclipse/tractusx/semantics/accesscontrol/sql/service/SqlBackedAccessControlRuleService.java index 51c857f2..296e9cba 100644 --- a/access-control-service-sql-impl/src/main/java/org/eclipse/tractusx/semantics/accesscontrol/sql/service/SqlBackedAccessControlRuleService.java +++ b/access-control-service-sql-impl/src/main/java/org/eclipse/tractusx/semantics/accesscontrol/sql/service/SqlBackedAccessControlRuleService.java @@ -22,6 +22,8 @@ import java.time.Instant; import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; @@ -65,9 +67,11 @@ public List filterValidSpecificAssetIdsForLookup( .filter( accessControlRule -> aShellContext.specificAssetIds().containsAll( accessControlRule.getMandatorySpecificAssetIds() ) ) .flatMap( accessControlRule -> accessControlRule.getVisibleSpecificAssetIdNames().stream() ) .collect( Collectors.toSet() ); + Map> duplicatedSpecificAssetIds = getDuplicateSpecificAssetIds( aShellContext ); return aShellContext.specificAssetIds().stream() - .filter( id -> visibleSpecificAssetIdNames.contains( id.name() ) ) - .collect( Collectors.toSet() ).containsAll( userQuery ); + .filter( id -> isSpecificAssetIdVisible( id, visibleSpecificAssetIdNames, duplicatedSpecificAssetIds ) ) + .collect( Collectors.toSet() ) + .containsAll( userQuery ); } ) .map( ShellVisibilityContext::aasId ) .toList(); @@ -76,15 +80,28 @@ public List filterValidSpecificAssetIdsForLookup( @Override public ShellVisibilityCriteria fetchVisibilityCriteriaForShell( ShellVisibilityContext shellContext, String bpn ) throws DenyAccessException { Set matchingAccessControlRules = findMatchingAccessControlRules( shellContext, bpn ); - Set visibleSpecificAssetIdNames = matchingAccessControlRules.stream() - .flatMap( accessControlRule -> accessControlRule.getVisibleSpecificAssetIdNames().stream() ) - .collect( Collectors.toSet() ); + + Map> duplicatedSpecificAssetIds = getDuplicateSpecificAssetIds( shellContext ); + + Map> visibleSpecificAssetIds = new HashMap<>(); + matchingAccessControlRules.forEach( rule -> { + rule.getMandatorySpecificAssetIds().forEach( specificAssetId -> { + if ( duplicatedSpecificAssetIds.containsKey( specificAssetId.name() ) ) { + visibleSpecificAssetIds.computeIfAbsent( specificAssetId.name(), k -> new HashSet<>() ).add( specificAssetId.value() ); + } + } ); + + rule.getVisibleSpecificAssetIdNames().forEach( specificAssetIdName -> { + visibleSpecificAssetIds.computeIfAbsent( specificAssetIdName, k -> new HashSet<>() ); + } ); + } ); + Set visibleSemanticIds = matchingAccessControlRules.stream() .map( AccessRulePolicy::getVisibleSemanticIds ) .flatMap( Collection::stream ) .collect( Collectors.toSet() ); boolean publicOnly = matchingAccessControlRules.stream().noneMatch( rule -> rule.getBpn().equals( bpn ) ); - return new ShellVisibilityCriteria( shellContext.aasId(), visibleSpecificAssetIdNames, visibleSemanticIds, publicOnly ); + return new ShellVisibilityCriteria( shellContext.aasId(), visibleSpecificAssetIds, visibleSemanticIds, publicOnly ); } @Override @@ -123,4 +140,20 @@ private Set findMatchingAccessControlRules( ShellVisibilityCon } return matching; } + + private Map> getDuplicateSpecificAssetIds( ShellVisibilityContext shellContext ) { + return shellContext.specificAssetIds().stream() + .collect( Collectors.groupingBy( SpecificAssetId::name, + Collectors.mapping( SpecificAssetId::value, Collectors.toSet() ) ) ) + .entrySet().stream() + .filter( specificAssetIds -> specificAssetIds.getValue().size() > 1 ) + .collect( Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue ) ); + } + + private boolean isSpecificAssetIdVisible( SpecificAssetId specificAssetId, Set visibleSpecificAssetIds, + Map> duplicatedSpecificAssetIds ) { + Set identifierValues = duplicatedSpecificAssetIds.getOrDefault( specificAssetId.name(), Set.of() ); + return visibleSpecificAssetIds.contains( specificAssetId.name() ) + && (identifierValues.isEmpty() || identifierValues.contains( specificAssetId.value() )); + } } diff --git a/access-control-service-sql-impl/src/test/java/org/eclipse/tractusx/semantics/accesscontrol/sql/service/SqlBackedAccessControlRuleServiceTest.java b/access-control-service-sql-impl/src/test/java/org/eclipse/tractusx/semantics/accesscontrol/sql/service/SqlBackedAccessControlRuleServiceTest.java index 1c44c853..016f2d3e 100644 --- a/access-control-service-sql-impl/src/test/java/org/eclipse/tractusx/semantics/accesscontrol/sql/service/SqlBackedAccessControlRuleServiceTest.java +++ b/access-control-service-sql-impl/src/test/java/org/eclipse/tractusx/semantics/accesscontrol/sql/service/SqlBackedAccessControlRuleServiceTest.java @@ -29,6 +29,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.UUID; @@ -89,19 +90,37 @@ public static Stream matchingSpecificAssetIdFilterProvider() { public static Stream matchingSpecificAssetIdVisibilityProvider() { return Stream. builder() .add( Arguments.of( - Set.of( MANUFACTURER_PART_ID_99991, CUSTOMER_PART_ID_ACME001, PART_INSTANCE_ID_00001, VERSION_NUMBER_01 ), + Set.of( MANUFACTURER_PART_ID_99991, CUSTOMER_PART_ID_ACME001, PART_INSTANCE_ID_00001, PART_INSTANCE_ID_00002, VERSION_NUMBER_01 ), BPNA, - Set.of( MANUFACTURER_PART_ID, CUSTOMER_PART_ID, PART_INSTANCE_ID, VERSION_NUMBER ), + Map.of( + MANUFACTURER_PART_ID_99991.name(), + Set.of(), + CUSTOMER_PART_ID_ACME001.name(), Set.of(), + PART_INSTANCE_ID_00001.name(), Set.of( PART_INSTANCE_ID_00001.value() ), + VERSION_NUMBER_01.name(), Set.of() + ), Set.of( TRACEABILITYV_1_1_0 ) ) ) .add( Arguments.of( Set.of( MANUFACTURER_PART_ID_99991, CUSTOMER_PART_ID_ACME001, PART_INSTANCE_ID_00002, REVISION_NUMBER_01 ), BPNA, - Set.of( MANUFACTURER_PART_ID, CUSTOMER_PART_ID, PART_INSTANCE_ID, REVISION_NUMBER ), + Map.of( + MANUFACTURER_PART_ID_99991.name(), Set.of(), + CUSTOMER_PART_ID_ACME001.name(), Set.of(), + PART_INSTANCE_ID_00001.name(), Set.of(), + REVISION_NUMBER_01.name(), Set.of() + ), Set.of( PRODUCT_CARBON_FOOTPRINTV_1_1_0 ) ) ) .add( Arguments.of( Set.of( MANUFACTURER_PART_ID_99991, CUSTOMER_PART_ID_ACME001, PART_INSTANCE_ID_00001, VERSION_NUMBER_01, REVISION_NUMBER_01 ), BPNA, - Set.of( MANUFACTURER_PART_ID, CUSTOMER_PART_ID, PART_INSTANCE_ID, REVISION_NUMBER, VERSION_NUMBER ), + Map.of( + MANUFACTURER_PART_ID_99991.name(), + Set.of(), + CUSTOMER_PART_ID_ACME001.name(), Set.of(), + PART_INSTANCE_ID_00001.name(), Set.of(), + VERSION_NUMBER_01.name(), Set.of(), + REVISION_NUMBER_01.name(), Set.of() + ), Set.of( PRODUCT_CARBON_FOOTPRINTV_1_1_0, TRACEABILITYV_1_1_0 ) ) ) .build(); } @@ -165,7 +184,7 @@ void testFetchVisibilityCriteriaForShellWhenNoMatchingBpnExpectException() { @MethodSource( "matchingSpecificAssetIdVisibilityProvider" ) void testFetchVisibilityCriteriaForShellWhenMatchingSpecificAssetIdsProvidedExpectFilteringList( Set specificAssetIds, String bpn, - Set expectedSpecificAssetIdNames, Set expectedSemanticIds ) throws DenyAccessException { + Map> expectedSpecificAssetIdNames, Set expectedSemanticIds ) throws DenyAccessException { ShellVisibilityContext shellContext = new ShellVisibilityContext( UUID.randomUUID().toString(), specificAssetIds ); final var actual = underTest.fetchVisibilityCriteriaForShell( shellContext, bpn ); diff --git a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/service/GranularShellAccessHandler.java b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/service/GranularShellAccessHandler.java index 3e64a88b..fe34b060 100644 --- a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/service/GranularShellAccessHandler.java +++ b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/service/GranularShellAccessHandler.java @@ -23,6 +23,7 @@ import java.time.Instant; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -151,7 +152,7 @@ private Shell filterShellContents( Shell shell, ShellVisibilityCriteria visibili Set filteredSubmodels = shell.getSubmodels().stream() .filter( submodel -> submodel.getSemanticId().getKeys().stream() .anyMatch( key -> key.getType() == ReferenceKeyType.SUBMODEL - && visibilityCriteria.visibleSemanticIds().contains( key.getValue() ) ) ) + && visibilityCriteria.visibleSemanticIds().contains( key.getValue() ) ) ) .collect( Collectors.toSet() ); final Shell filtered; if ( visibilityCriteria.publicOnly() ) { @@ -182,8 +183,7 @@ private ShellVisibilityContext toShellVisibilityContext( Shell shell ) { private Set filterSpecificAssetIdsByTenantId( Set shellIdentifiers, ShellVisibilityCriteria visibilityCriteria ) { //noinspection SimplifyStreamApiCallChains return shellIdentifiers.stream() - .filter( identifier -> identifier.getKey().equals( ShellIdentifier.GLOBAL_ASSET_ID_KEY ) - || visibilityCriteria.visibleSpecificAssetIdNames().contains( identifier.getKey() ) ) + .filter( identifier -> isSpecificAssetIdVisible( visibilityCriteria.visibleSpecificAssetIdNames(), identifier ) ) //TODO: Do we need to clear the list of external subject Ids? .map( identifier -> { Optional.ofNullable( identifier.getExternalSubjectId() ) @@ -191,6 +191,11 @@ private Set filterSpecificAssetIdsByTenantId( Set> visibleSpecificAssetIdNames, ShellIdentifier identifier ) { + Set identifierValues = visibleSpecificAssetIdNames.get( identifier.getKey() ); + return identifier.getKey().equals( ShellIdentifier.GLOBAL_ASSET_ID_KEY ) || + identifierValues != null && (identifierValues.isEmpty() || identifierValues.contains( identifier.getValue() )); } } diff --git a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiSecurityTest.java b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiSecurityTest.java index 1a2ea719..2a6100ae 100644 --- a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiSecurityTest.java +++ b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiSecurityTest.java @@ -24,6 +24,7 @@ import static org.hamcrest.Matchers.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +import java.util.ArrayList; import java.util.Base64; import java.util.List; import java.util.UUID; @@ -664,10 +665,6 @@ public void testGetAllShellsWithDefaultClosedFilteredSpecificAssetIdsByTenantId( @Test public void testGetShellWithFilteredSpecificAssetIdsByTenantId() throws Exception { - AssetAdministrationShellDescriptor shellPayload = TestUtil - .createCompleteAasDescriptor( keyPrefix + "semanticId", "http://example.com/" ); - shellPayload.setId( keyPrefix ); - shellPayload.setSpecificAssetIds( null ); SpecificAssetId asset1 = TestUtil.createSpecificAssetId( keyPrefix + "CustomerPartId", "tenantTwoAssetIdValue", List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); SpecificAssetId asset2 = TestUtil.createSpecificAssetId( keyPrefix + "CustomerPartId2", "tenantThreeAssetIdValue", @@ -680,11 +677,22 @@ public void testGetShellWithFilteredSpecificAssetIdsByTenantId() throws Exceptio SpecificAssetId asset5 = TestUtil.createSpecificAssetId( "manufacturerPartId", keyPrefix + "wildcardAllowed", List.of( getExternalSubjectIdWildcardPrefix() ) ); - shellPayload.setSpecificAssetIds( List.of( asset1, asset2, asset3, asset4, asset5 ) ); + List specificAssetIds = List.of( asset1, asset2, asset3, asset4, asset5 ); + List expectedSpecificAssetIdsTenantTwo = List.of( asset1, asset3, asset5 ); + testGetShellWithFilteredSpecificAssetIdsByTenantId( specificAssetIds, expectedSpecificAssetIdsTenantTwo ); + } + + public void testGetShellWithFilteredSpecificAssetIdsByTenantId( List specificAssetIds, List expectedSpecificAssetIds ) + throws Exception { + AssetAdministrationShellDescriptor shellPayload = TestUtil + .createCompleteAasDescriptor( keyPrefix + "semanticId", "http://example.com/" ); + shellPayload.setId( keyPrefix ); + shellPayload.setSpecificAssetIds( specificAssetIds ); performShellCreateRequest( mapper.writeValueAsString( shellPayload ) ); String shellId = shellPayload.getId(); String encodedShellId = getEncodedValue( shellId ); + // Owner of tenant has access to all specificAssetIds mvc.perform( MockMvcRequestBuilders @@ -696,11 +704,13 @@ public void testGetShellWithFilteredSpecificAssetIdsByTenantId() throws Exceptio .andDo( MockMvcResultHandlers.print() ) .andExpect( status().isOk() ) .andExpect( jsonPath( "$.id", equalTo( shellId ) ) ) - .andExpect( jsonPath( "$.specificAssetIds[*].value", - containsInAnyOrder( "tenantTwoAssetIdValue", "tenantThreeAssetIdValue", "withoutTenantAssetIdValue", "ignoreWildcard", - keyPrefix + "wildcardAllowed" ) ) ); + .andExpect( jsonPath( "$.specificAssetIds[*].name", hasItems( specificAssetIds.stream().map( SpecificAssetId::getName ).toArray() ) ) ) + .andExpect( jsonPath( "$.specificAssetIds[*].value", hasItems( specificAssetIds.stream().map( SpecificAssetId::getValue ).toArray() ) ) ); // test with tenant two + ArrayList hiddenSpecificAssetIds = new ArrayList<>( specificAssetIds ); + hiddenSpecificAssetIds.removeAll( expectedSpecificAssetIds ); + mvc.perform( MockMvcRequestBuilders .get( SINGLE_SHELL_BASE_PATH, encodedShellId ) @@ -711,10 +721,10 @@ public void testGetShellWithFilteredSpecificAssetIdsByTenantId() throws Exceptio .andDo( MockMvcResultHandlers.print() ) .andExpect( status().isOk() ) .andExpect( jsonPath( "$.id", equalTo( shellId ) ) ) - .andExpect( jsonPath( "$.specificAssetIds[*].value", - hasItems( "tenantTwoAssetIdValue", "withoutTenantAssetIdValue", keyPrefix + "wildcardAllowed" ) ) ) - .andExpect( jsonPath( "$.specificAssetIds[*].value", - not( hasItems( "tenantThreeAssetIdValue", "ignoreWildcard" ) ) ) ); + .andExpect( jsonPath( "$.specificAssetIds[*].name", hasItems( expectedSpecificAssetIds.stream().map( SpecificAssetId::getName ).toArray() ) ) ) + .andExpect( jsonPath( "$.specificAssetIds[*].value", hasItems( expectedSpecificAssetIds.stream().map( SpecificAssetId::getValue ).toArray() ) ) ) + .andExpect( + jsonPath( "$.specificAssetIds[*].value", not( hasItems( hiddenSpecificAssetIds.stream().map( SpecificAssetId::getValue ).toArray() ) ) ) ); } @Test diff --git a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/GranularAssetAdministrationShellApiSecurityTest.java b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/GranularAssetAdministrationShellApiSecurityTest.java index 809a76f9..f3405f1b 100644 --- a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/GranularAssetAdministrationShellApiSecurityTest.java +++ b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/GranularAssetAdministrationShellApiSecurityTest.java @@ -208,19 +208,158 @@ public void testGetAllShellsWithDefaultClosedFilteredSpecificAssetIdsByTenantId( } @Test + @DisplayName( "Test GetShell with filtered specificAssetId by tenantId" ) public void testGetShellWithFilteredSpecificAssetIdsByTenantId() throws Exception { + // Create and save rule accessControlRuleRepository.saveAllAndFlush( List.of( - TestUtil.createAccessRule( TestUtil.PUBLIC_READABLE, + // Rule for BPN + TestUtil.createAccessRule( + // Rule for BPN + TestUtil.PUBLIC_READABLE, + // Rule for mandatory specificAssetIds Map.of( keyPrefix + "BPID", "ignoreWildcard", "manufacturerPartId", keyPrefix + "wildcardAllowed" ), + // Rule for visible specificAssetIds Set.of( "manufacturerPartId" ), Set.of( keyPrefix + "semanticId" ) ), - TestUtil.createAccessRule( jwtTokenFactory.tenantTwo().getTenantId(), + TestUtil.createAccessRule( + // Rule for BPN + jwtTokenFactory.tenantTwo().getTenantId(), + // Rule for mandatory specificAssetIds Map.of( keyPrefix + "CustomerPartId", "tenantTwoAssetIdValue", keyPrefix + "MaterialNumber", "withoutTenantAssetIdValue" ), + // Rule for visible specificAssetIds Set.of( keyPrefix + "CustomerPartId", keyPrefix + "MaterialNumber" ), Set.of( keyPrefix + "semanticId" ) ), - TestUtil.createAccessRule( jwtTokenFactory.tenantThree().getTenantId(), + TestUtil.createAccessRule( + // Rule for BPN + jwtTokenFactory.tenantThree().getTenantId(), + // Rule for mandatory specificAssetIds Map.of( keyPrefix + "CustomerPartId2", "tenantThreeAssetIdValue" ), + // Rule for visible specificAssetIds Set.of( keyPrefix + "CustomerPartId2" ), Set.of( keyPrefix + "semanticId" ) ) ) ); - super.testGetShellWithFilteredSpecificAssetIdsByTenantId(); + + SpecificAssetId asset1 = TestUtil.createSpecificAssetId( keyPrefix + "CustomerPartId", "tenantTwoAssetIdValue", + List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); + SpecificAssetId asset2 = TestUtil.createSpecificAssetId( keyPrefix + "CustomerPartId2", "tenantThreeAssetIdValue", + List.of( jwtTokenFactory.tenantThree().getTenantId() ) ); + SpecificAssetId asset3 = TestUtil.createSpecificAssetId( keyPrefix + "MaterialNumber", "withoutTenantAssetIdValue", + List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); + // Define specificAsset with wildcard which not allowed. (Only manufacturerPartId is defined in application.yml) + SpecificAssetId asset4 = TestUtil.createSpecificAssetId( keyPrefix + "BPID", "ignoreWildcard", List.of( getExternalSubjectIdWildcardPrefix() ) ); + // Define specificAsset with wildcard which is allowed. (Only manufacturerPartId is defined in application.yml) + SpecificAssetId asset5 = TestUtil.createSpecificAssetId( "manufacturerPartId", keyPrefix + "wildcardAllowed", + List.of( getExternalSubjectIdWildcardPrefix() ) ); + + // Define all available specificAssetIds + List specificAssetIds = List.of( asset1, asset2, asset3, asset4, asset5 ); + // Define available specificAssetIds for tenantTwo + List expectedSpecificAssetIdsTenantTwo = List.of( asset1, asset3, asset5 ); + super.testGetShellWithFilteredSpecificAssetIdsByTenantId( specificAssetIds, expectedSpecificAssetIdsTenantTwo ); + } + + @Test + @DisplayName( "Test GetShell with filtered specificAssetIds with same keys where the specific mandatory Rule match over ANY rule by tenantId" ) + public void testGetShellWithFilteredSpecificAssetIdsWithSameKeysAndMandatoryRuleMatchedOverAnyByTenantId() throws Exception { + // Create and save rule + accessControlRuleRepository.saveAllAndFlush( List.of( + // Rule for BPN + TestUtil.createAccessRule( + // Rule for BPN + TestUtil.PUBLIC_READABLE, + // Rule for mandatory specificAssetIds + Map.of( keyPrefix + "BPID", "ignoreWildcard", "manufacturerPartId", keyPrefix + "wildcardAllowed" ), + // Rule for visible specificAssetIds + Set.of( "manufacturerPartId" ), Set.of( keyPrefix + "semanticId" ) ), + TestUtil.createAccessRule( + // Rule for BPN + jwtTokenFactory.tenantTwo().getTenantId(), + // Rule for mandatory specificAssetIds + Map.of( keyPrefix + "CustomerPartId", "tenantTwoAssetIdValue", keyPrefix + "MaterialNumber", "withoutTenantAssetIdValue" ), + // Rule for visible specificAssetIds + Set.of( keyPrefix + "CustomerPartId", keyPrefix + "MaterialNumber" ), Set.of( keyPrefix + "semanticId" ) ) ) ); + + SpecificAssetId asset1 = TestUtil.createSpecificAssetId( keyPrefix + "CustomerPartId", "tenantTwoAssetIdValue", + List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); + SpecificAssetId asset2 = TestUtil.createSpecificAssetId( keyPrefix + "CustomerPartId", "tenantThreeAssetIdValue", + List.of( jwtTokenFactory.tenantThree().getTenantId() ) ); + SpecificAssetId asset3 = TestUtil.createSpecificAssetId( keyPrefix + "MaterialNumber", "withoutTenantAssetIdValue", + List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); + + // Define all available specificAssetIds + List specificAssetIds = List.of( asset1, asset2, asset3 ); + // Define available specificAssetIds for tenantTwo + List expectedSpecificAssetIdsTenantTwo = List.of( asset1, asset3 ); + super.testGetShellWithFilteredSpecificAssetIdsByTenantId( specificAssetIds, expectedSpecificAssetIdsTenantTwo ); + } + + @Test + @DisplayName( "Test GetShell with filtered specificAssetIds with same keys where the ANY Rule matched by tenantId" ) + public void testGetShellWithFilteredSpecificAssetIdsWithSameKeysAndAnyRuleMatchedByTenantId() throws Exception { + // Create and save rule + accessControlRuleRepository.saveAllAndFlush( List.of( + TestUtil.createAccessRule( + // Rule for BPN + TestUtil.PUBLIC_READABLE, + // Rule for mandatory specificAssetIds + Map.of( keyPrefix + "BPID", "ignoreWildcard", "manufacturerPartId", keyPrefix + "wildcardAllowed" ), + // Rule for visible specificAssetIds + Set.of( "manufacturerPartId" ), Set.of( keyPrefix + "semanticId" ) ), + TestUtil.createAccessRule( + // Rule for BPN + jwtTokenFactory.tenantTwo().getTenantId(), + // Rule for mandatory specificAssetIds + Map.of( keyPrefix + "MaterialNumber", "withoutTenantAssetIdValue" ), + // Rule for visible specificAssetIds + Set.of( keyPrefix + "CustomerPartId", keyPrefix + "MaterialNumber" ), Set.of( keyPrefix + "semanticId" ) ) ) ); + + SpecificAssetId asset1 = TestUtil.createSpecificAssetId( keyPrefix + "CustomerPartId", "tenantTwoAssetIdValue", + List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); + SpecificAssetId asset2 = TestUtil.createSpecificAssetId( keyPrefix + "CustomerPartId", "tenantThreeAssetIdValue", + List.of( jwtTokenFactory.tenantThree().getTenantId() ) ); + SpecificAssetId asset3 = TestUtil.createSpecificAssetId( keyPrefix + "MaterialNumber", "withoutTenantAssetIdValue", + List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); + SpecificAssetId asset4 = TestUtil.createSpecificAssetId( keyPrefix + "PartInstanceId", "OwnerAssetidValue", + List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); + + // Define all available specificAssetIds + List specificAssetIds = List.of( asset1, asset2, asset3, asset4 ); + // Define available specificAssetIds for tenantTwo + List expectedSpecificAssetIdsTenantTwo = List.of( asset1, asset2, asset3 ); + super.testGetShellWithFilteredSpecificAssetIdsByTenantId( specificAssetIds, expectedSpecificAssetIdsTenantTwo ); + } + + @Test + @DisplayName( "Test GetShell with filtered specificAssetIds with same keys where mandatory rule not match and disable specificAssetId by tenantId" ) + public void testGetShellWithFilteredSpecificAssetIdsWithSameKeysAndMandatoryRuleNotMatchedTenantId() throws Exception { + // Create and save rule + accessControlRuleRepository.saveAllAndFlush( List.of( + TestUtil.createAccessRule( + // Rule for BPN + TestUtil.PUBLIC_READABLE, + // Rule for mandatory specificAssetIds + Map.of( keyPrefix + "BPID", "ignoreWildcard", "manufacturerPartId", keyPrefix + "wildcardAllowed" ), + // Rule for visible specificAssetIds + Set.of( "manufacturerPartId" ), Set.of( keyPrefix + "semanticId" ) ), + TestUtil.createAccessRule( + // Rule for BPN + jwtTokenFactory.tenantTwo().getTenantId(), + // Rule for mandatory specificAssetIds + Map.of( keyPrefix + "MaterialNumber", "withoutTenantAssetIdValue" ), + // Rule for visible specificAssetIds + Set.of( keyPrefix + "CustomerPartId", keyPrefix + "MaterialNumber" ), Set.of( keyPrefix + "semanticId" ) ) ) ); + + SpecificAssetId asset1 = TestUtil.createSpecificAssetId( keyPrefix + "CustomerPartId", "tenantTwoAssetIdValue", + List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); + SpecificAssetId asset2 = TestUtil.createSpecificAssetId( keyPrefix + "CustomerPartId", "tenantThreeAssetIdValue", + List.of( jwtTokenFactory.tenantThree().getTenantId() ) ); + SpecificAssetId asset3 = TestUtil.createSpecificAssetId( keyPrefix + "MaterialNumber", "withoutTenantAssetIdValue", + List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); + SpecificAssetId asset4 = TestUtil.createSpecificAssetId( keyPrefix + "PartInstanceId", "OwnerAssetidValue", + List.of( jwtTokenFactory.tenantTwo().getTenantId() ) ); + + // Define all available specificAssetIds + List specificAssetIds = List.of( asset1, asset2, asset3, asset4 ); + // Define available specificAssetIds for tenantTwo + List expectedSpecificAssetIdsTenantTwo = List.of( asset3 ); + super.testGetShellWithFilteredSpecificAssetIdsByTenantId( specificAssetIds, expectedSpecificAssetIdsTenantTwo ); } @Test diff --git a/docs/README.md b/docs/README.md index 3bd1335c..a3c62ddd 100644 --- a/docs/README.md +++ b/docs/README.md @@ -840,7 +840,10 @@ The process is similar to the lookup shells, the filtering and access control of 2. The list of shells fetched in the previous step is filtered by applying the access control rules to them one-by-one. 3. The process is repeated until we have the desired number of *Digital Twins* or there are no more *Digital Twins* to fetch. 4. The visible properties of the visible *Digital Twins* are returned. - + 1. If the list of *specificAssetIds* in the shell has *multiple* entries with the same name, then the following rules apply: + 1. Usecase 1: A rule includes a specificAssetId (for example customerPartId=123) as *mandatorySpecificAssetId and visibleSpecificAssetId*. The Shell has multiple entries with the same name and *one of the entry* matched the value from mandatorySpecificAssetId, then only the matched entry is visible. + 2. Usecase 2: A rule includes a specificAssetId (for example customerPartId=123) as *mandatorySpecificAssetId and visibleSpecificAssetId*. The Shell has multiple entries with the same name and *none of the entries* matched the value from mandatorySpecificAssetId, then no entries with the same name is visible. + ###### Get Shell by AAS Id - `GET {{baseUrl}}/api/v3/shell-descriptors/:aasIdentifier` To determine the visibility of a single *Digital Twin*, we can simply: diff --git a/pom.xml b/pom.xml index 2e9ac1dd..842cb456 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ org.springframework.boot spring-boot-starter-parent - 3.2.3 + 3.2.4 @@ -66,7 +66,7 @@ - 3.2.3 + 3.2.4 1.6.14 1.18.24 1.5.20