From 67dfae84240e12a1dd44fb9b5c7eeb2aedbb4aa2 Mon Sep 17 00:00:00 2001 From: Simone Lindner Date: Tue, 26 Sep 2023 14:37:31 +0200 Subject: [PATCH 1/7] getDescription request updated to new API version 3.0.1. Also readability restricted to user with view-role --- .../AssetAdministrationShellApiDelegate.java | 7 +-- .../security/OAuthSecurityConfig.java | 3 ++ .../static/aas-registry-openapi.yaml | 37 +++++++------- ...setAdministrationShellApiSecurityTest.java | 51 +++++++++++++++++++ .../AssetAdministrationShellApiTest.java | 16 ++++++ 5 files changed, 93 insertions(+), 21 deletions(-) diff --git a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java index 19293732..b695c31c 100644 --- a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java +++ b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java @@ -21,6 +21,7 @@ import java.util.*; +import org.eclipse.tractusx.semantics.RegistryProperties; import org.eclipse.tractusx.semantics.aas.registry.api.DescriptionApiDelegate; import org.eclipse.tractusx.semantics.aas.registry.api.LookupApiDelegate; import org.eclipse.tractusx.semantics.aas.registry.api.ShellDescriptorsApiDelegate; @@ -48,7 +49,7 @@ public class AssetAdministrationShellApiDelegate implements DescriptionApiDelega public AssetAdministrationShellApiDelegate(final ShellService shellService, final ShellMapper shellMapper, - final SubmodelMapper submodelMapper) { + final SubmodelMapper submodelMapper ) { this.shellService = shellService; this.shellMapper = shellMapper; this.submodelMapper = submodelMapper; @@ -61,9 +62,9 @@ public Optional getRequest() { @Override public ResponseEntity getDescription() { + ServiceDescription serviceDescription = new ServiceDescription(); - serviceDescription.setProfiles( List.of( ServiceDescription.ProfilesEnum.ASSETADMINISTRATIONSHELLREPOSITORYSERVICESPECIFICATION_V3_0_MINIMALPROFILE, - ServiceDescription.ProfilesEnum.REGISTRYSERVICESPECIFICATION_V3_0) ); + serviceDescription.setProfiles( List.of( ServiceDescription.ProfilesEnum.ASSETADMINISTRATIONSHELLREGISTRYSERVICESPECIFICATION_SSP_001, ServiceDescription.ProfilesEnum.DISCOVERYSERVICESPECIFICATION_SSP_001) ); return new ResponseEntity<>( serviceDescription, HttpStatus.OK ); } diff --git a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/security/OAuthSecurityConfig.java b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/security/OAuthSecurityConfig.java index 95fa1e3d..d74414f4 100644 --- a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/security/OAuthSecurityConfig.java +++ b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/security/OAuthSecurityConfig.java @@ -64,6 +64,9 @@ protected SecurityFilterChain configure(HttpSecurity http) throws Exception { .requestMatchers( HttpMethod.POST, "/**/lookup/**" ).access( "@authorizationEvaluator.hasRoleAddDigitalTwin()" ) .requestMatchers( HttpMethod.PUT, "/**/lookup/**" ).access( "@authorizationEvaluator.hasRoleUpdateDigitalTwin()" ) .requestMatchers( HttpMethod.DELETE, "/**/lookup/**" ).access( "@authorizationEvaluator.hasRoleDeleteDigitalTwin()" ) + + //getDescription allowed for reader + .requestMatchers( HttpMethod.GET, "/**/description" ).access( "@authorizationEvaluator.hasRoleViewDigitalTwin()" ) ) .csrf().disable() .sessionManagement().sessionCreationPolicy( SessionCreationPolicy.STATELESS ) diff --git a/backend/src/main/resources/static/aas-registry-openapi.yaml b/backend/src/main/resources/static/aas-registry-openapi.yaml index d85642f9..83a5a96a 100644 --- a/backend/src/main/resources/static/aas-registry-openapi.yaml +++ b/backend/src/main/resources/static/aas-registry-openapi.yaml @@ -1502,29 +1502,30 @@ components: properties: profiles: minItems: 1 - maxItems: 10000 type: array items: type: string enum: - - AssetAdministrationShellServiceSpecification/V3.0 - - AssetAdministrationShellServiceSpecification/V3.0-MinimalProfile - - SubmodelServiceSpecification/V3.0 - - SubmodelServiceSpecification/V3.0-ValueProfile - - SubmodelServiceSpecification/V3.0-MinimalProfile - - AasxFileServerServiceSpecification/V3.0 - - RegistryServiceSpecification/V3.0 - - RegistryServiceSpecification/V3.0- AssetAdministrationShellRegistry - - RegistryServiceSpecification/V3.0-SubmodelRegistry - - RepositoryServiceSpecification/V3.0 - - RepositoryServiceSpecification/V3.0-MinimalProfile - - AssetAdministrationShellRepositoryServiceSpecification/V3.0 - - AssetAdministrationShellRepositoryServiceSpecification/V3.0-MinimalProfile - - SubmodelRepositoryServiceSpecification/V3.0 - - SubmodelRepositoryServiceSpecification/V3.0-MinimalProfile - - RegistryAndDiscoveryServiceSpecification/V3.0 + - https://admin-shell.io/aas/API/3/0/AssetAdministrationShellServiceSpecification/SSP-001 + - https://admin-shell.io/aas/API/3/0/AssetAdministrationShellServiceSpecification/SSP-002 + - https://admin-shell.io/aas/API/3/0/SubmodelServiceSpecification/SSP-001 + - https://admin-shell.io/aas/API/3/0/SubmodelServiceSpecification/SSP-002 + - https://admin-shell.io/aas/API/3/0/SubmodelServiceSpecification/SSP-003 + - https://admin-shell.io/aas/API/3/0/AasxFileServerServiceSpecification/SSP-001 + - https://admin-shell.io/aas/API/3/0/AssetAdministrationShellRegistryServiceSpecification/SSP-001 + - https://admin-shell.io/aas/API/3/0/AssetAdministrationShellRegistryServiceSpecification/SSP-002 + - https://admin-shell.io/aas/API/3/0/SubmodelRegistryServiceSpecification/SSP-001 + - https://admin-shell.io/aas/API/3/0/SubmodelRegistryServiceSpecification/SSP-002 + - https://admin-shell.io/aas/API/3/0/DiscoveryServiceSpecification/SSP-001 + - https://admin-shell.io/aas/API/3/0/AssetAdministrationShellRepositoryServiceSpecification/SSP-001 + - https://admin-shell.io/aas/API/3/0/AssetAdministrationShellRepositoryServiceSpecification/SSP-002 + - https://admin-shell.io/aas/API/3/0/SubmodelRepositoryServiceSpecification/SSP-001 + - https://admin-shell.io/aas/API/3/0/SubmodelRepositoryServiceSpecification/SSP-002 + - https://admin-shell.io/aas/API/3/0/SubmodelRepositoryServiceSpecification/SSP-003 + - https://admin-shell.io/aas/API/3/0/SubmodelRepositoryServiceSpecification/SSP-004 + - https://admin-shell.io/aas/API/3/0/ConceptDescriptionServiceSpecification/SSP-001 description: "The Description object enables servers to present their capabilities to the clients, in particular which profiles they implement. At least one defined profile is required. Additional, proprietary attributes might be included. Nevertheless, the server must not expect that a regular client understands them." - example: { "profiles": [ "RepositoryServiceSpecification/V3.0-MinimalProfile", "RegistryServiceSpecification/V3.0" ] } + example: { "profiles": ["https://admin-shell.io/aas/API/3/0/AssetAdministrationShellRegistryServiceSpecification/SSP-002", "https://admin-shell.io/aas/API/3/0/SubmodelRegistryServiceSpecification/SSP-002"] } PagedResult_paging_metadata: type: object properties: 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 b0c06d85..dcc48c16 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 @@ -1243,4 +1243,55 @@ public void testGetAllShellByExternalIdWithPublicAccessByTenantId() throws Excep .andExpect(jsonPath("$.specificAssetIds[*]").exists()); } } + @Nested + @DisplayName( "Description Authentication Tests" ) + class DescriptionApiTest { + + @Test + public void testGetDescriptionOnlyDeleteRoleExpectForbidden() throws Exception { + mvc.perform( + MockMvcRequestBuilders + .get( "/api/v3.0/description" ) + .accept( MediaType.APPLICATION_JSON ) + .with( jwtTokenFactory.deleteTwin() ) + ) + .andDo( MockMvcResultHandlers.print() ) + .andExpect(status().isForbidden()); + } + + @Test + public void testGetDescriptionNoRoleExpectForbidden() throws Exception { + mvc.perform( + MockMvcRequestBuilders + .get( "/api/v3.0/description" ) + .accept( MediaType.APPLICATION_JSON ) + .with( jwtTokenFactory.withoutRoles() ) + ) + .andDo( MockMvcResultHandlers.print() ) + .andExpect(status().isForbidden()); + } + + @Test + public void testGetDescriptionReadRoleExpectSuccess() throws Exception { + mvc.perform( + MockMvcRequestBuilders + .get( "/api/v3.0/description" ) + .accept( MediaType.APPLICATION_JSON ) + .with( jwtTokenFactory.readTwin() ) + ) + .andDo( MockMvcResultHandlers.print() ) + .andExpect(status().isOk()); + } + + @Test + public void testGetDescriptionReadRoleExpectUnauthorized() throws Exception { + mvc.perform( + MockMvcRequestBuilders + .get( "/api/v3.0/description" ) + .accept( MediaType.APPLICATION_JSON ) + ) + .andDo( MockMvcResultHandlers.print() ) + .andExpect(status().isUnauthorized()); + } + } } diff --git a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java index 361bb0f3..0f7cb207 100644 --- a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java +++ b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java @@ -992,4 +992,20 @@ public void testFetchShellsByMultipleIdentificationsExpectSuccessExpectSuccess() } } + @Nested + @DisplayName( "Description Tests" ) + class DescriptionApiTest { + @Test + public void testGetDescriptionExpectSuccess() throws Exception { + mvc.perform( + MockMvcRequestBuilders + .get( "/api/v3.0/description" ) + .accept( MediaType.APPLICATION_JSON ) + .with( jwtTokenFactory.allRoles() ) + ) + .andDo( MockMvcResultHandlers.print() ) + .andExpect( status().isOk() ) + .andExpect( jsonPath( "$.profiles[0]", is( "https://admin-shell.io/aas/API/3/0/AssetAdministrationShellRegistryServiceSpecification/SSP-001" ) ) ); + } + } } \ No newline at end of file From 955d37a18eede865c9150307d41dc9aa2cf5760c Mon Sep 17 00:00:00 2001 From: "Aggarwal Sahil (BCI/ESW17)" Date: Mon, 23 Oct 2023 12:07:53 +0200 Subject: [PATCH 2/7] changes done for encoding specificAssetId in getshell lookup request --- .../AssetAdministrationShellApiDelegate.java | 23 +++++++- .../static/aas-registry-openapi.yaml | 16 ++---- ...setAdministrationShellApiSecurityTest.java | 57 ++++++++++++++----- .../AssetAdministrationShellApiTest.java | 24 ++++---- .../tractusx/semantics/registry/TestUtil.java | 16 +++++- 5 files changed, 98 insertions(+), 38 deletions(-) diff --git a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java index 19293732..28c17686 100644 --- a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java +++ b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java @@ -19,7 +19,9 @@ ********************************************************************************/ package org.eclipse.tractusx.semantics.registry.controller; +import java.io.IOException; import java.util.*; +import java.util.stream.Collectors; import org.eclipse.tractusx.semantics.aas.registry.api.DescriptionApiDelegate; import org.eclipse.tractusx.semantics.aas.registry.api.LookupApiDelegate; @@ -39,6 +41,9 @@ import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.context.request.NativeWebRequest; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; + @Service public class AssetAdministrationShellApiDelegate implements DescriptionApiDelegate, ShellDescriptorsApiDelegate, LookupApiDelegate { @@ -149,13 +154,27 @@ public ResponseEntity putSubmodelDescriptorByIdThroughSuperpath( byte[] aa } @Override - public ResponseEntity getAllAssetAdministrationShellIdsByAssetLink(List assetIds, + public ResponseEntity getAllAssetAdministrationShellIdsByAssetLink(List assetIds, Integer limit, String cursor, @RequestHeader String externalSubjectId) { if (assetIds == null || assetIds.isEmpty()) { return new ResponseEntity<>(new GetAllAssetAdministrationShellIdsByAssetLink200Response(), HttpStatus.OK); } + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion( JsonInclude.Include.NON_NULL); + List listSpecificAssetId = assetIds.stream().map( value -> + { + byte[] decodedBytes = Base64.getUrlDecoder().decode( value ); + try { + SpecificAssetId specificAssetId = mapper.readValue(decodedBytes, SpecificAssetId.class ); + return specificAssetId; + } catch ( IOException e ) { + throw new IllegalArgumentException("Incorrect Base64 encoded value provided as parameter"); + } + } + ).collect( Collectors.toList()); + GetAllAssetAdministrationShellIdsByAssetLink200Response result = - shellService.findExternalShellIdsByIdentifiersByExactMatch(shellMapper.fromApiDto(assetIds), limit, cursor,getExternalSubjectIdOrEmpty(externalSubjectId)); + shellService.findExternalShellIdsByIdentifiersByExactMatch(shellMapper.fromApiDto(listSpecificAssetId), limit, cursor,getExternalSubjectIdOrEmpty(externalSubjectId)); return new ResponseEntity<>(result, HttpStatus.OK); } diff --git a/backend/src/main/resources/static/aas-registry-openapi.yaml b/backend/src/main/resources/static/aas-registry-openapi.yaml index 2ea124a2..6efc8f1c 100644 --- a/backend/src/main/resources/static/aas-registry-openapi.yaml +++ b/backend/src/main/resources/static/aas-registry-openapi.yaml @@ -700,16 +700,12 @@ paths: # the "content" is the correct way to accept json encoded query parameters # style: form # explode: true - content: - application/json: - schema: - type: array - maxItems: 10000 - items: - $ref: '#/components/schemas/SpecificAssetId' - examples: - complete: - $ref: '#/components/examples/lookup-shells-by-aas-identifier-query' + schema: + type: array + items: + type: string + format: byte + example: '?assetIds=eyAibmFtZSI6ICJzb21lLWFzc2V0LWlkIiwgInZhbHVlIjogImh0dHA6Ly9leGFtcGxlLWNvbXBhbnkuY29tL215QXNzZXQiLCAiZXh0ZXJuYWxTdWJqZWN0SWQiOiB7ICJrZXlzIjogWyB7ICJ0eXBlIjogIkdsb2JhbFJlZmVyZW5jZSIsICJ2YWx1ZSI6ICJodHRwOi8vZXhhbXBsZS1jb21wYW55LmNvbS9leGFtcGxlLWNvbXBhbnlzLWFzc2V0LWtleXMiIH0gXSwgInR5cGUiOiAiR2xvYmFsUmVmZXJlbmNlIiB9IH0&assetIds=eyAibmFtZSI6ICJzb21lLW90aGVyLWFzc2V0LWlkIiwgInZhbHVlIjogIjEyMzQ1QUJDIiwgImV4dGVybmFsU3ViamVjdElkIjogeyAia2V5cyI6IFsgeyAidHlwZSI6ICJHbG9iYWxSZWZlcmVuY2UiLCAidmFsdWUiOiAiaHR0cDovL215LW93bi1jb21wYW55LmNvbS9rZXlzIiB9IF0sICJ0eXBlIjogIkdsb2JhbFJlZmVyZW5jZSIgfSB9' - name: limit in: query description: The maximum number of elements in the response array 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 b0c06d85..d28de333 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 @@ -21,6 +21,7 @@ import static org.hamcrest.Matchers.*; +import java.util.Base64; import java.util.List; import java.util.UUID; @@ -515,11 +516,12 @@ class LookupTest { public void testRbacForLookupByAssetIds() throws Exception { SpecificAssetId specificAssetId = TestUtil.createSpecificAssetId(); + String encodedObject = Base64.getUrlEncoder().encodeToString(serialize( specificAssetId)); mvc.perform( MockMvcRequestBuilders .get(LOOKUP_SHELL_BASE_PATH) - .queryParam("assetIds", mapper.writeValueAsString(specificAssetId)) + .queryParam("assetIds", encodedObject) .accept(MediaType.APPLICATION_JSON) .with(jwtTokenFactory.addTwin()) ) @@ -528,7 +530,7 @@ public void testRbacForLookupByAssetIds() throws Exception { mvc.perform( MockMvcRequestBuilders .get(LOOKUP_SHELL_BASE_PATH) - .param("assetIds",mapper.writeValueAsString(specificAssetId)) + .param("assetIds",encodedObject) .contentType(MediaType.APPLICATION_JSON_VALUE) .queryParam("limit", "10") .accept(MediaType.APPLICATION_JSON_VALUE) @@ -809,11 +811,13 @@ public void testGetSpecificAssetIdsFilteredByTenantId() throws Exception { .andExpect(status().isCreated()) .andExpect(content().json(mapper.writeValueAsString(List.of(specificAssetId)))); - mvc.perform( + String encodedObject = Base64.getUrlEncoder().encodeToString(serialize( specificAssetId)); + + mvc.perform( MockMvcRequestBuilders .get(LOOKUP_SHELL_BASE_PATH) .header( EXTERNAL_SUBJECT_ID_HEADER, jwtTokenFactory.tenantOne().getTenantId() ) - .queryParam("assetIds", mapper.writeValueAsString(List.of(specificAssetId))) + .queryParam("assetIds", encodedObject) .accept(MediaType.APPLICATION_JSON) .with(jwtTokenFactory.allRoles()) ) @@ -827,7 +831,7 @@ public void testGetSpecificAssetIdsFilteredByTenantId() throws Exception { .get(LOOKUP_SHELL_BASE_PATH) .accept(MediaType.APPLICATION_JSON) .header( EXTERNAL_SUBJECT_ID_HEADER, jwtTokenFactory.tenantTwo().getTenantId() ) - .queryParam("assetIds", mapper.writeValueAsString(List.of(specificAssetId))) + .queryParam("assetIds", encodedObject) .with(jwtTokenFactory.tenantTwo().allRoles()) ) .andDo(MockMvcResultHandlers.print()) @@ -854,11 +858,14 @@ public void testFindExternalShellIdsBySpecificAssetIdsWithTenantBasedVisibilityE SpecificAssetId sa1 = TestUtil.createSpecificAssetId(keyPrefix + "findExternal_2_1","value_2_1",List.of(jwtTokenFactory.tenantTwo().getTenantId())); SpecificAssetId sa2 = TestUtil.createSpecificAssetId(keyPrefix + "findExternal_2_2","value_2_2",List.of(jwtTokenFactory.tenantThree().getTenantId())); + String encodedSa1 = Base64.getUrlEncoder().encodeToString(serialize( sa1)); + String encodedSa2 = Base64.getUrlEncoder().encodeToString(serialize( sa2)); mvc.perform( MockMvcRequestBuilders .get(LOOKUP_SHELL_BASE_PATH) .header( EXTERNAL_SUBJECT_ID_HEADER, jwtTokenFactory.tenantOne().getTenantId() ) - .queryParam("assetIds", mapper.writeValueAsString(List.of(sa1,sa2))) + .queryParam("assetIds", encodedSa1) + .queryParam("assetIds", encodedSa2) .accept(MediaType.APPLICATION_JSON) .with(jwtTokenFactory.allRoles()) ) @@ -871,12 +878,12 @@ public void testFindExternalShellIdsBySpecificAssetIdsWithTenantBasedVisibilityE // test with tenantTwo assetId included SpecificAssetId specificAssetIdsWithTenantTwoIncluded = TestUtil.createSpecificAssetId(keyPrefix + "findExternal_2_2","value_2_2",null); - + String encodedSaWithTenantTwoIncluded = Base64.getUrlEncoder().encodeToString(serialize( specificAssetIdsWithTenantTwoIncluded)); mvc.perform( MockMvcRequestBuilders .get(LOOKUP_SHELL_BASE_PATH) .header( EXTERNAL_SUBJECT_ID_HEADER, jwtTokenFactory.tenantTwo().getTenantId() ) - .queryParam("assetIds", mapper.writeValueAsString(specificAssetIdsWithTenantTwoIncluded)) + .queryParam("assetIds", encodedSaWithTenantTwoIncluded) .accept(MediaType.APPLICATION_JSON) .with(jwtTokenFactory.tenantTwo().allRoles()) ) @@ -890,7 +897,8 @@ public void testFindExternalShellIdsBySpecificAssetIdsWithTenantBasedVisibilityE MockMvcRequestBuilders .get(LOOKUP_SHELL_BASE_PATH) .header( EXTERNAL_SUBJECT_ID_HEADER, jwtTokenFactory.tenantOne().getTenantId() ) - .queryParam("assetIds", mapper.writeValueAsString(List.of(sa1,sa2))) + .queryParam("assetIds", encodedSa1) + .queryParam("assetIds", encodedSa2) .accept(MediaType.APPLICATION_JSON) .with(jwtTokenFactory.tenantTwo().allRoles()) ) @@ -930,12 +938,22 @@ public void testFindExternalShellIdsBySpecificAssetIdsWithTenantBasedVisibilityA SpecificAssetId sa4 = TestUtil.createSpecificAssetId(keyPrefix + "tenantTwo_tenantThree","value_3",null); SpecificAssetId sa5 = TestUtil.createSpecificAssetId(keyPrefix + "tenantTwo","value_2",null); + String encodedSa1 = Base64.getUrlEncoder().encodeToString(serialize( sa1)); + String encodedSa2 = Base64.getUrlEncoder().encodeToString(serialize( sa2)); + String encodedSa3 = Base64.getUrlEncoder().encodeToString(serialize( sa3)); + String encodedSa4 = Base64.getUrlEncoder().encodeToString(serialize( sa4)); + String encodedSa5 = Base64.getUrlEncoder().encodeToString(serialize( sa5)); + // Make request with bpn of the owner mvc.perform( MockMvcRequestBuilders .get(LOOKUP_SHELL_BASE_PATH) .header( EXTERNAL_SUBJECT_ID_HEADER, jwtTokenFactory.tenantOne().getTenantId() ) - .queryParam("assetIds", mapper.writeValueAsString(List.of(sa1,sa2,sa3,sa4,sa5))) + .queryParam("assetIds", encodedSa1) + .queryParam("assetIds", encodedSa2) + .queryParam("assetIds", encodedSa3) + .queryParam("assetIds", encodedSa4) + .queryParam("assetIds", encodedSa5) .accept(MediaType.APPLICATION_JSON) .with(jwtTokenFactory.allRoles()) ) @@ -951,7 +969,8 @@ public void testFindExternalShellIdsBySpecificAssetIdsWithTenantBasedVisibilityA MockMvcRequestBuilders .get(LOOKUP_SHELL_BASE_PATH) .header( EXTERNAL_SUBJECT_ID_HEADER, jwtTokenFactory.tenantTwo().getTenantId() ) - .queryParam("assetIds", mapper.writeValueAsString(List.of(sa2,sa5))) + .queryParam("assetIds", encodedSa2) + .queryParam("assetIds", encodedSa5) .accept(MediaType.APPLICATION_JSON) .with(jwtTokenFactory.tenantTwo().allRoles()) ) @@ -968,7 +987,9 @@ public void testFindExternalShellIdsBySpecificAssetIdsWithTenantBasedVisibilityA MockMvcRequestBuilders .get(LOOKUP_SHELL_BASE_PATH) .header( EXTERNAL_SUBJECT_ID_HEADER, jwtTokenFactory.tenantTwo().getTenantId() ) - .queryParam("assetIds", mapper.writeValueAsString(List.of(sa2,sa3,sa5))) + .queryParam("assetIds", encodedSa2) + .queryParam("assetIds", encodedSa3) + .queryParam("assetIds", encodedSa5) .accept(MediaType.APPLICATION_JSON) .with(jwtTokenFactory.tenantTwo().allRoles()) ) @@ -981,7 +1002,8 @@ public void testFindExternalShellIdsBySpecificAssetIdsWithTenantBasedVisibilityA MockMvcRequestBuilders .get(LOOKUP_SHELL_BASE_PATH) .header( EXTERNAL_SUBJECT_ID_HEADER, jwtTokenFactory.tenantThree().getTenantId() ) - .queryParam("assetIds", mapper.writeValueAsString(List.of(sa2,sa5))) + .queryParam("assetIds", encodedSa2) + .queryParam("assetIds", encodedSa5) .accept(MediaType.APPLICATION_JSON) .with(jwtTokenFactory.tenantTwo().allRoles()) ) @@ -1009,11 +1031,15 @@ public void testFindExternalShellIdsBySpecificAssetIdsWithDefaultClosedTenantBas SpecificAssetId sa1 = TestUtil.createSpecificAssetId(keyPrefix + "defaultClosed","value_1",null); SpecificAssetId sa2 = TestUtil.createSpecificAssetId(keyPrefix + "public_visible","value_2",null); + String encodedSa1 = Base64.getUrlEncoder().encodeToString(serialize( sa1)); + String encodedSa2 = Base64.getUrlEncoder().encodeToString(serialize( sa2)); + mvc.perform( MockMvcRequestBuilders .get(LOOKUP_SHELL_BASE_PATH) .header( EXTERNAL_SUBJECT_ID_HEADER, jwtTokenFactory.tenantOne().getTenantId() ) - .queryParam("assetIds", mapper.writeValueAsString(List.of(sa1,sa2))) + .queryParam("assetIds", encodedSa1) + .queryParam("assetIds", encodedSa2) .accept(MediaType.APPLICATION_JSON) .with(jwtTokenFactory.allRoles()) ) @@ -1027,7 +1053,8 @@ public void testFindExternalShellIdsBySpecificAssetIdsWithDefaultClosedTenantBas MockMvcRequestBuilders .get(LOOKUP_SHELL_BASE_PATH) .header( EXTERNAL_SUBJECT_ID_HEADER, jwtTokenFactory.tenantTwo().getTenantId() ) - .queryParam("assetIds", mapper.writeValueAsString(List.of(sa1,sa2))) + .queryParam("assetIds", encodedSa1) + .queryParam("assetIds", encodedSa2) .accept(MediaType.APPLICATION_JSON) .with(jwtTokenFactory.tenantTwo().allRoles()) ) diff --git a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java index cfce8049..17c7d14e 100644 --- a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java +++ b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java @@ -19,10 +19,11 @@ ********************************************************************************/ package org.eclipse.tractusx.semantics.registry; -import static org.eclipse.tractusx.semantics.registry.TestUtil.getEncodedValue; +import static org.eclipse.tractusx.semantics.registry.TestUtil.*; import static org.hamcrest.Matchers.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +import java.util.Base64; import java.util.List; import java.util.UUID; @@ -679,7 +680,7 @@ public void testLookUpApiWithInvalidQueryParameterExpectFailure() throws Excepti ) .andDo( MockMvcResultHandlers.print() ) .andExpect( status().isBadRequest() ) - .andExpect( jsonPath( "$.messages[0].text", is( "The provided parameters are invalid. assetIds={ invalid }" ) ) ); + .andExpect( jsonPath( "$.messages[0].text", is( "Illegal base64 character 7b" ) ) ); } @Test @@ -726,11 +727,12 @@ public void testFindExternalShellIdsBySpecificAssetIdsExpectSuccess() throws Exc performShellCreateRequest( mapper.writeValueAsString( shellPayload2 ) ); SpecificAssetId specificAssetId1 = TestUtil.createSpecificAssetId(); + String encodedSa1 = Base64.getUrlEncoder().encodeToString(serialize( specificAssetId1)); mvc.perform( MockMvcRequestBuilders .get( LOOKUP_SHELL_BASE_PATH ) - .queryParam( "assetIds", mapper.writeValueAsString( specificAssetId1 ) ) + .queryParam( "assetIds", encodedSa1 ) .queryParam( "limit", "1" ) .header( EXTERNAL_SUBJECT_ID_HEADER, jwtTokenFactory.tenantOne().getTenantId() ) .accept( MediaType.APPLICATION_JSON ) @@ -743,10 +745,11 @@ public void testFindExternalShellIdsBySpecificAssetIdsExpectSuccess() throws Exc // Test first shell match with single assetId SpecificAssetId specificAssetId2 = TestUtil.createSpecificAssetId( "identifier99KeyExample", "identifier99ValueExample", null ); + String encodedSa2 = Base64.getUrlEncoder().encodeToString(serialize( specificAssetId2)); mvc.perform( MockMvcRequestBuilders .get( LOOKUP_SHELL_BASE_PATH ) - .queryParam( "assetIds", mapper.writeValueAsString( specificAssetId2 ) ) + .queryParam( "assetIds", encodedSa2) .queryParam( "limit", "10" ) .accept( MediaType.APPLICATION_JSON ) .with( jwtTokenFactory.allRoles() ) @@ -758,11 +761,11 @@ public void testFindExternalShellIdsBySpecificAssetIdsExpectSuccess() throws Exc // // Test first and second shell match with common asssetId SpecificAssetId specificAssetId3 = TestUtil.createSpecificAssetId( "commonAssetIdKey", "commonAssetIdValue", null ); - + String encodedSa3 = Base64.getUrlEncoder().encodeToString(serialize( specificAssetId3)); mvc.perform( MockMvcRequestBuilders .get( LOOKUP_SHELL_BASE_PATH ) - .queryParam( "assetIds", mapper.writeValueAsString( specificAssetId3 ) ) + .queryParam( "assetIds", encodedSa3 ) .accept( MediaType.APPLICATION_JSON ) .with( jwtTokenFactory.allRoles() ) ) @@ -783,14 +786,15 @@ public void testFindExternalShellIdByGlobalAssetIdExpectSuccess() throws Excepti performShellCreateRequest(payload ); // for lookup global asset id is handled as specificAssetIds - ArrayNode globalAssetIdForSampleQuery = emptyArrayNode().add( - specificAssetId( "globalAssetId", globalAssetId ) - ); + SpecificAssetId SAGlobal = TestUtil.createSpecificAssetId("globalAssetId",globalAssetId,null); + String encodedSa1 = Base64.getUrlEncoder().encodeToString(serialize( SAGlobal)); + + mvc.perform( MockMvcRequestBuilders .get( LOOKUP_SHELL_BASE_PATH ) .header( EXTERNAL_SUBJECT_ID_HEADER, jwtTokenFactory.tenantOne().getTenantId() ) - .queryParam( "assetIds", toJson( globalAssetIdForSampleQuery ) ) + .queryParam( "assetIds", encodedSa1) .accept( MediaType.APPLICATION_JSON ) .with( jwtTokenFactory.allRoles() ) ) diff --git a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/TestUtil.java b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/TestUtil.java index 8045b1a2..65caf284 100644 --- a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/TestUtil.java +++ b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/TestUtil.java @@ -22,12 +22,17 @@ import org.apache.commons.lang3.RandomStringUtils; import org.eclipse.tractusx.semantics.aas.registry.model.*; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; import java.util.Base64; import java.util.List; import java.util.UUID; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; + public class TestUtil { public static AssetAdministrationShellDescriptor createCompleteAasDescriptor() { @@ -246,4 +251,13 @@ public static SpecificAssetId createSpecificAssetId(String name, String value, L public static String getEncodedValue(String shellId){ return Base64.getUrlEncoder().encodeToString(shellId.getBytes()); } + + public static byte[] serialize(Object obj) throws IOException { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + ObjectMapper mapper = new ObjectMapper(); + mapper.enable( SerializationFeature.INDENT_OUTPUT); + mapper.setSerializationInclusion( JsonInclude.Include.NON_NULL); + mapper.writeValue(os, obj); + return os.toByteArray(); + } } \ No newline at end of file From c9cf70ff0801d79e2decd7e8293e709d44610812 Mon Sep 17 00:00:00 2001 From: "Aggarwal Sahil (BCI/ESW17)" Date: Fri, 10 Nov 2023 10:45:44 +0100 Subject: [PATCH 3/7] changes done for encoding specificAssetId in get shell lookup request --- .../AssetAdministrationShellApiDelegate.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java index 28c17686..f0119af2 100644 --- a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java +++ b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java @@ -161,21 +161,24 @@ public ResponseEntity g } ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion( JsonInclude.Include.NON_NULL); - List listSpecificAssetId = assetIds.stream().map( value -> + List listSpecificAssetId = getDecodedSpecAssetIds( assetIds, mapper ); + + GetAllAssetAdministrationShellIdsByAssetLink200Response result = + shellService.findExternalShellIdsByIdentifiersByExactMatch(shellMapper.fromApiDto(listSpecificAssetId), limit, cursor,getExternalSubjectIdOrEmpty(externalSubjectId)); + return new ResponseEntity<>(result, HttpStatus.OK); + } + + private static List getDecodedSpecAssetIds( List assetIds, ObjectMapper mapper ) { + return assetIds.stream().map( value -> { byte[] decodedBytes = Base64.getUrlDecoder().decode( value ); try { - SpecificAssetId specificAssetId = mapper.readValue(decodedBytes, SpecificAssetId.class ); - return specificAssetId; + return mapper.readValue(decodedBytes, SpecificAssetId.class ); } catch ( IOException e ) { throw new IllegalArgumentException("Incorrect Base64 encoded value provided as parameter"); } } ).collect( Collectors.toList()); - - GetAllAssetAdministrationShellIdsByAssetLink200Response result = - shellService.findExternalShellIdsByIdentifiersByExactMatch(shellMapper.fromApiDto(listSpecificAssetId), limit, cursor,getExternalSubjectIdOrEmpty(externalSubjectId)); - return new ResponseEntity<>(result, HttpStatus.OK); } @Override From 7d7e6ba659bb8b7925dc396043f583207baeb60a Mon Sep 17 00:00:00 2001 From: "Aggarwal Sahil (BCI/ESW17)" Date: Fri, 10 Nov 2023 11:02:06 +0100 Subject: [PATCH 4/7] AAS 3.0.1 changes for description api --- .../controller/AssetAdministrationShellApiDelegate.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java index b695c31c..a8791f07 100644 --- a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java +++ b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java @@ -21,7 +21,6 @@ import java.util.*; -import org.eclipse.tractusx.semantics.RegistryProperties; import org.eclipse.tractusx.semantics.aas.registry.api.DescriptionApiDelegate; import org.eclipse.tractusx.semantics.aas.registry.api.LookupApiDelegate; import org.eclipse.tractusx.semantics.aas.registry.api.ShellDescriptorsApiDelegate; @@ -49,7 +48,7 @@ public class AssetAdministrationShellApiDelegate implements DescriptionApiDelega public AssetAdministrationShellApiDelegate(final ShellService shellService, final ShellMapper shellMapper, - final SubmodelMapper submodelMapper ) { + final SubmodelMapper submodelMapper) { this.shellService = shellService; this.shellMapper = shellMapper; this.submodelMapper = submodelMapper; @@ -62,7 +61,6 @@ public Optional getRequest() { @Override public ResponseEntity getDescription() { - ServiceDescription serviceDescription = new ServiceDescription(); serviceDescription.setProfiles( List.of( ServiceDescription.ProfilesEnum.ASSETADMINISTRATIONSHELLREGISTRYSERVICESPECIFICATION_SSP_001, ServiceDescription.ProfilesEnum.DISCOVERYSERVICESPECIFICATION_SSP_001) ); return new ResponseEntity<>( serviceDescription, HttpStatus.OK ); From d10a4b5996bc8bddf8a424ee46a0afaa51a685d5 Mon Sep 17 00:00:00 2001 From: "Aggarwal Sahil (BCI/ESW17)" Date: Fri, 10 Nov 2023 15:41:38 +0100 Subject: [PATCH 5/7] AAS 3.0.1 changes for encoding get shell lookup api --- .../AssetAdministrationShellApiDelegate.java | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java index 12c070b3..58f97be8 100644 --- a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java +++ b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java @@ -156,28 +156,25 @@ public ResponseEntity putSubmodelDescriptorByIdThroughSuperpath( byte[] aa public ResponseEntity getAllAssetAdministrationShellIdsByAssetLink(List assetIds, Integer limit, String cursor, @RequestHeader String externalSubjectId) { if (assetIds == null || assetIds.isEmpty()) { - return new ResponseEntity<>(new GetAllAssetAdministrationShellIdsByAssetLink200Response(), HttpStatus.OK); + return new ResponseEntity<>(new GetAllAssetAdministrationShellIdsByAssetLink200Response(), HttpStatus.BAD_REQUEST); } - ObjectMapper mapper = new ObjectMapper(); - mapper.setSerializationInclusion( JsonInclude.Include.NON_NULL); - List listSpecificAssetId = getDecodedSpecAssetIds( assetIds, mapper ); + List listSpecificAssetId = Optional.of(assetIds).orElse(Collections.emptyList()). + stream().map( this::decodeSAID).collect( Collectors.toList()); GetAllAssetAdministrationShellIdsByAssetLink200Response result = shellService.findExternalShellIdsByIdentifiersByExactMatch(shellMapper.fromApiDto(listSpecificAssetId), limit, cursor,getExternalSubjectIdOrEmpty(externalSubjectId)); return new ResponseEntity<>(result, HttpStatus.OK); } - private static List getDecodedSpecAssetIds( List assetIds, ObjectMapper mapper ) { - return assetIds.stream().map( value -> - { - byte[] decodedBytes = Base64.getUrlDecoder().decode( value ); - try { - return mapper.readValue(decodedBytes, SpecificAssetId.class ); - } catch ( IOException e ) { - throw new IllegalArgumentException("Incorrect Base64 encoded value provided as parameter"); - } + private SpecificAssetId decodeSAID(byte[] encodedId){ + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion( JsonInclude.Include.NON_NULL); + try { + byte[] decodedBytes = Base64.getUrlDecoder().decode( encodedId ); + return mapper.readValue(decodedBytes, SpecificAssetId.class ); + } catch (Exception e ) { + throw new IllegalArgumentException("Incorrect Base64 encoded value provided as parameter"); } - ).collect( Collectors.toList()); } @Override From 00ea65d862eb590b619572d964b8217c955b582c Mon Sep 17 00:00:00 2001 From: "Aggarwal Sahil (BCI/ESW17)" Date: Fri, 10 Nov 2023 15:48:20 +0100 Subject: [PATCH 6/7] AAS 3.0.1 changes for encoding get shell lookup api --- CHANGELOG.md | 7 +++++++ .../controller/AssetAdministrationShellApiDelegate.java | 2 +- .../registry/AssetAdministrationShellApiTest.java | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a6564c4..5b09868f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ 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.3.20 +### Added + +## fixed +- Fix done for encoding input parameter to get shell look up api. +- Fixed response for GetDescription api. + ## 0.3.19 ### Added diff --git a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java index 58f97be8..fbcf1094 100644 --- a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java +++ b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java @@ -156,7 +156,7 @@ public ResponseEntity putSubmodelDescriptorByIdThroughSuperpath( byte[] aa public ResponseEntity getAllAssetAdministrationShellIdsByAssetLink(List assetIds, Integer limit, String cursor, @RequestHeader String externalSubjectId) { if (assetIds == null || assetIds.isEmpty()) { - return new ResponseEntity<>(new GetAllAssetAdministrationShellIdsByAssetLink200Response(), HttpStatus.BAD_REQUEST); + return new ResponseEntity<>(new GetAllAssetAdministrationShellIdsByAssetLink200Response(), HttpStatus.OK); } List listSpecificAssetId = Optional.of(assetIds).orElse(Collections.emptyList()). diff --git a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java index 72beb863..0d5e8443 100644 --- a/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java +++ b/backend/src/test/java/org/eclipse/tractusx/semantics/registry/AssetAdministrationShellApiTest.java @@ -680,7 +680,7 @@ public void testLookUpApiWithInvalidQueryParameterExpectFailure() throws Excepti ) .andDo( MockMvcResultHandlers.print() ) .andExpect( status().isBadRequest() ) - .andExpect( jsonPath( "$.messages[0].text", is( "Illegal base64 character 7b" ) ) ); + .andExpect( jsonPath( "$.messages[0].text", is( "Incorrect Base64 encoded value provided as parameter" ) ) ); } @Test From 8a46f4bd4ed06a3383fb6acd03fad40c0dcb6367 Mon Sep 17 00:00:00 2001 From: "Aggarwal Sahil (BCI/ESW17)" Date: Mon, 20 Nov 2023 11:23:36 +0100 Subject: [PATCH 7/7] PR comments changes --- .../controller/AssetAdministrationShellApiDelegate.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java index fbcf1094..4973e82d 100644 --- a/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java +++ b/backend/src/main/java/org/eclipse/tractusx/semantics/registry/controller/AssetAdministrationShellApiDelegate.java @@ -159,8 +159,7 @@ public ResponseEntity g return new ResponseEntity<>(new GetAllAssetAdministrationShellIdsByAssetLink200Response(), HttpStatus.OK); } - List listSpecificAssetId = Optional.of(assetIds).orElse(Collections.emptyList()). - stream().map( this::decodeSAID).collect( Collectors.toList()); + List listSpecificAssetId =assetIds.stream().map( this::decodeSAID).collect( Collectors.toList()); GetAllAssetAdministrationShellIdsByAssetLink200Response result = shellService.findExternalShellIdsByIdentifiersByExactMatch(shellMapper.fromApiDto(listSpecificAssetId), limit, cursor,getExternalSubjectIdOrEmpty(externalSubjectId)); return new ResponseEntity<>(result, HttpStatus.OK);