Skip to content

Commit c3e23d8

Browse files
authored
Support for filtering authorized models based on the defined RBAC rules. (#575)
* Adds dynamic RBAC to SM/CD Rep, SM Reg, and AAS Environment Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> * Reverts GitHub CI Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> * Attempts CI fix Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> * Reverts GitHub CI Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> * Reverts GitHub CI Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> * Adds shading plugin Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> * Adds dependency to parent pom Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> * Excludes SM dependencies Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> * Fixes the TargetInfoAdapter Bean in Aas Env Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> * Adds filtering options in Authorization Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> * Fixes Keycloak issues Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> * Reverts BaSyx Realm Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> * Fixes import issues in SM Registry Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> * Fixes app.prop of aas env Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> * Fixes CI Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> * Fixes AAS and SM Reg tests Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> * Allows swagger ui api endpoint without auth Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> * Allows swagger ui api endpoint without auth Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> * Allows Swagger API without authorization Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> * Filter models as per RBAC rules Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> * Addresses review remarks Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]> --------- Signed-off-by: Mohammad Ghazanfar Ali Danish <[email protected]>
1 parent b5303b5 commit c3e23d8

File tree

12 files changed

+239
-19
lines changed

12 files changed

+239
-19
lines changed

basyx.aasregistry/basyx.aasregistry-feature-authorization/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/authorization/AuthorizedAasRegistryStorage.java

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@
2828
import java.util.ArrayList;
2929
import java.util.Arrays;
3030
import java.util.List;
31+
import java.util.Objects;
3132
import java.util.Set;
33+
import java.util.TreeMap;
34+
import java.util.stream.Collectors;
3235

3336
import org.eclipse.digitaltwin.basyx.aasregistry.feature.authorization.rbac.AasRegistryTargetPermissionVerifier;
3437
import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetAdministrationShellDescriptor;
@@ -43,9 +46,13 @@
4346
import org.eclipse.digitaltwin.basyx.aasregistry.service.storage.DescriptorFilter;
4447
import org.eclipse.digitaltwin.basyx.authorization.rbac.Action;
4548
import org.eclipse.digitaltwin.basyx.authorization.rbac.RbacPermissionResolver;
49+
import org.eclipse.digitaltwin.basyx.authorization.rbac.TargetInformation;
4650
import org.eclipse.digitaltwin.basyx.core.exceptions.InsufficientPermissionException;
4751
import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult;
4852
import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo;
53+
import org.eclipse.digitaltwin.basyx.core.pagination.PaginationSupport;
54+
import org.slf4j.Logger;
55+
import org.slf4j.LoggerFactory;
4956

5057
/**
5158
* Decorator for authorized {@link AasRegistryStorage}
@@ -54,6 +61,7 @@
5461
*/
5562
public class AuthorizedAasRegistryStorage implements AasRegistryStorage {
5663

64+
private static final Logger LOGGER = LoggerFactory.getLogger(AuthorizedAasRegistryStorage.class);
5765
private AasRegistryStorage decorated;
5866
private RbacPermissionResolver<AasRegistryTargetInformation> permissionResolver;
5967

@@ -64,8 +72,33 @@ public AuthorizedAasRegistryStorage(AasRegistryStorage decorated, RbacPermission
6472

6573
@Override
6674
public CursorResult<List<AssetAdministrationShellDescriptor>> getAllAasDescriptors(PaginationInfo pRequest, DescriptorFilter filter) {
67-
assertHasPermission(Action.READ, getIdAsList(AasRegistryTargetPermissionVerifier.ALL_ALLOWED_WILDCARD));
68-
return decorated.getAllAasDescriptors(pRequest, filter);
75+
boolean isAuthorized = permissionResolver.hasPermission(Action.READ, new AasRegistryTargetInformation(getIdAsList(AasRegistryTargetPermissionVerifier.ALL_ALLOWED_WILDCARD)));
76+
77+
if (isAuthorized)
78+
return decorated.getAllAasDescriptors(pRequest, filter);
79+
80+
List<TargetInformation> targetInformations = permissionResolver.getMatchingTargetInformationInRules(Action.READ, new AasRegistryTargetInformation(getIdAsList(AasRegistryTargetPermissionVerifier.ALL_ALLOWED_WILDCARD)));
81+
82+
List<String> allIds = targetInformations.stream().map(AasRegistryTargetInformation.class::cast)
83+
.map(AasRegistryTargetInformation::getAasIds).flatMap(List::stream).collect(Collectors.toList());
84+
85+
List<AssetAdministrationShellDescriptor> aasDescriptors = allIds.stream().map(id -> {
86+
try {
87+
return getAasDescriptor(id);
88+
} catch (AasDescriptorNotFoundException e) {
89+
LOGGER.error("AAS Descriptor: '{}' not found, Error: {}", id, e.getMessage());
90+
return null;
91+
} catch (Exception e) {
92+
LOGGER.error("Exception occurred while retrieving the AAS Descriptor: {}, Error: {}", id, e.getMessage());
93+
return null;
94+
}
95+
}).filter(Objects::nonNull).collect(Collectors.toList());
96+
97+
TreeMap<String, AssetAdministrationShellDescriptor> aasMap = aasDescriptors.stream().collect(Collectors.toMap(AssetAdministrationShellDescriptor::getId, aas -> aas, (a, b) -> a, TreeMap::new));
98+
99+
PaginationSupport<AssetAdministrationShellDescriptor> paginationSupport = new PaginationSupport<>(aasMap, AssetAdministrationShellDescriptor::getId);
100+
101+
return paginationSupport.getPaged(pRequest);
69102
}
70103

71104
@Override

basyx.aasregistry/basyx.aasregistry-feature-authorization/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/authorization/TestAuthorizedAasRegistry.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ public void getAllAasDescriptorsWithInsufficientPermissionRole() throws IOExcept
144144
String accessToken = tokenProvider.getAccessToken(dummyCredential.getUsername(), dummyCredential.getPassword());
145145

146146
CloseableHttpResponse retrievalResponse = getAllElementsWithAuthorization(aasRegistryBaseUrl, accessToken);
147-
assertEquals(HttpStatus.FORBIDDEN.value(), retrievalResponse.getCode());
147+
assertEquals(HttpStatus.OK.value(), retrievalResponse.getCode());
148148
}
149149

150150
@Test

basyx.aasregistry/basyx.aasregistry-service-basetests/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/service/tests/integration/AuthorizedAasRegistryTestSuite.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ public void getAllAasDescriptorsWithInsufficientPermissionRole() throws IOExcept
134134
String accessToken = getAccessTokenProvider().getAccessToken(dummyCredential.getUsername(), dummyCredential.getPassword());
135135

136136
CloseableHttpResponse retrievalResponse = getAllElementsWithAuthorization(aasRegistryBaseUrl, accessToken);
137-
assertEquals(HttpStatus.FORBIDDEN.value(), retrievalResponse.getCode());
137+
assertEquals(HttpStatus.OK.value(), retrievalResponse.getCode());
138138
}
139139

140140
@Test

basyx.aasrepository/basyx.aasrepository-feature-authorization/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/feature/authorization/AuthorizedAasRepository.java

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,25 @@
3030
import java.util.ArrayList;
3131
import java.util.Arrays;
3232
import java.util.List;
33+
import java.util.Objects;
34+
import java.util.TreeMap;
35+
import java.util.stream.Collectors;
3336

3437
import org.eclipse.digitaltwin.aas4j.v3.model.AssetAdministrationShell;
3538
import org.eclipse.digitaltwin.aas4j.v3.model.AssetInformation;
3639
import org.eclipse.digitaltwin.aas4j.v3.model.Reference;
3740
import org.eclipse.digitaltwin.basyx.aasrepository.AasRepository;
3841
import org.eclipse.digitaltwin.basyx.authorization.rbac.Action;
3942
import org.eclipse.digitaltwin.basyx.authorization.rbac.RbacPermissionResolver;
43+
import org.eclipse.digitaltwin.basyx.authorization.rbac.TargetInformation;
4044
import org.eclipse.digitaltwin.basyx.core.exceptions.CollidingIdentifierException;
4145
import org.eclipse.digitaltwin.basyx.core.exceptions.ElementDoesNotExistException;
4246
import org.eclipse.digitaltwin.basyx.core.exceptions.InsufficientPermissionException;
4347
import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult;
4448
import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo;
49+
import org.eclipse.digitaltwin.basyx.core.pagination.PaginationSupport;
50+
import org.slf4j.Logger;
51+
import org.slf4j.LoggerFactory;
4552

4653
/**
4754
* Decorator for authorized {@link AasRepository}
@@ -51,6 +58,7 @@
5158
*/
5259
public class AuthorizedAasRepository implements AasRepository {
5360

61+
private static final Logger LOGGER = LoggerFactory.getLogger(AuthorizedAasRepository.class);
5462
private AasRepository decorated;
5563
private RbacPermissionResolver<AasTargetInformation> permissionResolver;
5664

@@ -64,9 +72,31 @@ public AuthorizedAasRepository(AasRepository decorated, RbacPermissionResolver<A
6472
public CursorResult<List<AssetAdministrationShell>> getAllAas(PaginationInfo pInfo) {
6573
boolean isAuthorized = permissionResolver.hasPermission(Action.READ, new AasTargetInformation(getIdAsList("*")));
6674

67-
throwExceptionIfInsufficientPermission(isAuthorized);
75+
if (isAuthorized)
76+
return decorated.getAllAas(pInfo);
77+
78+
List<TargetInformation> targetInformations = permissionResolver.getMatchingTargetInformationInRules(Action.READ, new AasTargetInformation(getIdAsList("*")));
79+
80+
List<String> allIds = targetInformations.stream().map(AasTargetInformation.class::cast)
81+
.map(AasTargetInformation::getAasIds).flatMap(List::stream).collect(Collectors.toList());
6882

69-
return decorated.getAllAas(pInfo);
83+
List<AssetAdministrationShell> shells = allIds.stream().map(id -> {
84+
try {
85+
return getAas(id);
86+
} catch (ElementDoesNotExistException e) {
87+
LOGGER.error("AAS: '{}' not found, Error: {}", id, e.getMessage());
88+
return null;
89+
} catch (Exception e) {
90+
LOGGER.error("Exception occurred while retrieving the AAS: {}, Error: {}", id, e.getMessage());
91+
return null;
92+
}
93+
}).filter(Objects::nonNull).collect(Collectors.toList());
94+
95+
TreeMap<String, AssetAdministrationShell> aasMap = shells.stream().collect(Collectors.toMap(AssetAdministrationShell::getId, aas -> aas, (a, b) -> a, TreeMap::new));
96+
97+
PaginationSupport<AssetAdministrationShell> paginationSupport = new PaginationSupport<>(aasMap, AssetAdministrationShell::getId);
98+
99+
return paginationSupport.getPaged(pInfo);
70100
}
71101

72102
@Override

basyx.aasrepository/basyx.aasrepository-feature-authorization/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/feature/authorization/TestAuthorizedAasRepository.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ public void getAllAasWithInsufficientPermissionRole() throws IOException {
131131
String accessToken = tokenProvider.getAccessToken(dummyCredential.getUsername(), dummyCredential.getPassword());
132132

133133
CloseableHttpResponse retrievalResponse = getAllAasWithAuthorization(accessToken);
134-
assertEquals(HttpStatus.FORBIDDEN.value(), retrievalResponse.getCode());
134+
assertEquals(HttpStatus.OK.value(), retrievalResponse.getCode());
135135
}
136136

137137
@Test

basyx.common/basyx.authorization/src/main/java/org/eclipse/digitaltwin/basyx/authorization/rbac/RbacPermissionResolver.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525

2626
package org.eclipse.digitaltwin.basyx.authorization.rbac;
2727

28+
import java.util.List;
29+
2830
/**
2931
* An interface for resolving Rbac permissions
3032
*
@@ -34,4 +36,6 @@ public interface RbacPermissionResolver<T extends TargetInformation> {
3436

3537
public boolean hasPermission(Action action, T targetInformation);
3638

39+
public List<TargetInformation> getMatchingTargetInformationInRules(Action action, T targetInformation);
40+
3741
}

basyx.common/basyx.authorization/src/main/java/org/eclipse/digitaltwin/basyx/authorization/rbac/SimpleRbacPermissionResolver.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
package org.eclipse.digitaltwin.basyx.authorization.rbac;
2727

2828
import java.util.List;
29+
import java.util.Objects;
2930
import java.util.Optional;
3031
import java.util.stream.Collectors;
3132
import java.util.stream.Stream;
@@ -79,6 +80,16 @@ public boolean hasPermission(final Action action, final T targetInformation) {
7980

8081
return matchingRule.isPresent();
8182
}
83+
84+
public List<TargetInformation> getMatchingTargetInformationInRules(final Action action, final T targetInformation) {
85+
86+
List<String> roles = roleAuthenticator.getRoles();
87+
88+
List<RbacRule> filteredRbacRulesForTargetInfos = roles.stream().map(role -> generateKey(role, action.toString(), targetInformation.getClass().getName())).filter(Objects::nonNull).filter(this::exist).map(this::getRbacRule)
89+
.filter(Objects::nonNull).collect(Collectors.toList());
90+
91+
return filteredRbacRulesForTargetInfos.stream().map(rbacRule -> rbacRule.getTargetInformation()).collect(Collectors.toList());
92+
}
8293

8394
private Stream<RbacRule> getMatchingRules(final List<String> roles, final Action action, final T targetInformation) {
8495

@@ -92,4 +103,31 @@ private boolean checkRbacRuleMatchesTargetInfo(final RbacRule rbacRule, final T
92103
return targetPermissionVerifier.isVerified(rbacRule, targetInformation);
93104
}
94105

106+
private String generateKey(String role, String action, String targetClassName) {
107+
try {
108+
return RbacRuleKeyGenerator.generateKey(role, action, targetClassName);
109+
} catch (Exception e) {
110+
logger.error("Error generating Rbac Rule Key for role: '{}' Action: '{}' and Target Information Class: '{}'", role, action, targetClassName, e);
111+
return null;
112+
}
113+
}
114+
115+
private boolean exist(String key) {
116+
try {
117+
return rbacStorage.exist(key);
118+
} catch (Exception e) {
119+
logger.error("Error checking existence of Rbac Rule for key: {}", key, e);
120+
return false;
121+
}
122+
}
123+
124+
private RbacRule getRbacRule(String key) {
125+
try {
126+
return rbacStorage.getRbacRule(key);
127+
} catch (Exception e) {
128+
logger.error("Error retrieving the Rbac Rule for key: {}", key, e);
129+
return null;
130+
}
131+
}
132+
95133
}

basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-feature-authorization/src/main/java/org/eclipse/digitaltwin/basyx/conceptdescriptionrepository/feature/authorization/AuthorizedConceptDescriptionRepository.java

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,25 @@
2828
import java.util.ArrayList;
2929
import java.util.Arrays;
3030
import java.util.List;
31+
import java.util.Objects;
32+
import java.util.TreeMap;
33+
import java.util.stream.Collectors;
3134

3235
import org.eclipse.digitaltwin.aas4j.v3.model.ConceptDescription;
3336
import org.eclipse.digitaltwin.aas4j.v3.model.Reference;
3437
import org.eclipse.digitaltwin.basyx.authorization.rbac.Action;
3538
import org.eclipse.digitaltwin.basyx.authorization.rbac.RbacPermissionResolver;
39+
import org.eclipse.digitaltwin.basyx.authorization.rbac.TargetInformation;
3640
import org.eclipse.digitaltwin.basyx.conceptdescriptionrepository.ConceptDescriptionRepository;
3741
import org.eclipse.digitaltwin.basyx.core.exceptions.CollidingIdentifierException;
3842
import org.eclipse.digitaltwin.basyx.core.exceptions.ElementDoesNotExistException;
3943
import org.eclipse.digitaltwin.basyx.core.exceptions.InsufficientPermissionException;
4044
import org.eclipse.digitaltwin.basyx.core.exceptions.MissingIdentifierException;
4145
import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult;
4246
import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo;
47+
import org.eclipse.digitaltwin.basyx.core.pagination.PaginationSupport;
48+
import org.slf4j.Logger;
49+
import org.slf4j.LoggerFactory;
4350

4451
/**
4552
* Decorator for authorized {@link ConceptDescriptionRepository}
@@ -49,6 +56,7 @@
4956
*/
5057
public class AuthorizedConceptDescriptionRepository implements ConceptDescriptionRepository {
5158

59+
private static final Logger LOGGER = LoggerFactory.getLogger(AuthorizedConceptDescriptionRepository.class);
5260
private ConceptDescriptionRepository decorated;
5361
private RbacPermissionResolver<ConceptDescriptionTargetInformation> permissionResolver;
5462

@@ -61,9 +69,31 @@ public AuthorizedConceptDescriptionRepository(ConceptDescriptionRepository decor
6169
public CursorResult<List<ConceptDescription>> getAllConceptDescriptions(PaginationInfo pInfo) {
6270
boolean isAuthorized = permissionResolver.hasPermission(Action.READ, new ConceptDescriptionTargetInformation(getIdAsList("*")));
6371

64-
throwExceptionIfInsufficientPermission(isAuthorized);
72+
if (isAuthorized)
73+
return decorated.getAllConceptDescriptions(pInfo);
74+
75+
List<TargetInformation> targetInformations = permissionResolver.getMatchingTargetInformationInRules(Action.READ, new ConceptDescriptionTargetInformation(getIdAsList("*")));
76+
77+
List<String> allIds = targetInformations.stream().map(ConceptDescriptionTargetInformation.class::cast)
78+
.map(ConceptDescriptionTargetInformation::getConceptDescriptionIds).flatMap(List::stream).collect(Collectors.toList());
6579

66-
return decorated.getAllConceptDescriptions(pInfo);
80+
List<ConceptDescription> conceptDesc = allIds.stream().map(id -> {
81+
try {
82+
return getConceptDescription(id);
83+
} catch (ElementDoesNotExistException e) {
84+
LOGGER.error("Concept Description: '{}' not found, Error: {}", id, e.getMessage());
85+
return null;
86+
} catch (Exception e) {
87+
LOGGER.error("Exception occurred while retrieving the Concept Description: {}, Error: {}", id, e.getMessage());
88+
return null;
89+
}
90+
}).filter(Objects::nonNull).collect(Collectors.toList());
91+
92+
TreeMap<String, ConceptDescription> aasMap = conceptDesc.stream().collect(Collectors.toMap(ConceptDescription::getId, aas -> aas, (a, b) -> a, TreeMap::new));
93+
94+
PaginationSupport<ConceptDescription> paginationSupport = new PaginationSupport<>(aasMap, ConceptDescription::getId);
95+
96+
return paginationSupport.getPaged(pInfo);
6797
}
6898

6999
@Override

basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-feature-authorization/src/test/java/org/eclipse/digitaltwin/basyx/conceptdescriptionrepository/feature/authorization/TestAuthorizedCDRepository.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ public void getAllCDWithInsufficientPermissionRole() throws IOException {
113113
String accessToken = tokenProvider.getAccessToken(dummyCredential.getUsername(), dummyCredential.getPassword());
114114

115115
CloseableHttpResponse retrievalResponse = getAllCDWithAuthorization(accessToken);
116-
assertEquals(HttpStatus.FORBIDDEN.value(), retrievalResponse.getCode());
116+
assertEquals(HttpStatus.OK.value(), retrievalResponse.getCode());
117117
}
118118

119119
@Test

basyx.submodelregistry/basyx.submodelregistry-feature-authorization/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/authorization/AuthorizedSubmodelRegistryStorage.java

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,25 @@
2828
import java.util.ArrayList;
2929
import java.util.Arrays;
3030
import java.util.List;
31+
import java.util.Objects;
3132
import java.util.Set;
33+
import java.util.TreeMap;
34+
import java.util.stream.Collectors;
35+
3236
import org.eclipse.digitaltwin.basyx.authorization.rbac.Action;
3337
import org.eclipse.digitaltwin.basyx.authorization.rbac.RbacPermissionResolver;
38+
import org.eclipse.digitaltwin.basyx.authorization.rbac.TargetInformation;
3439
import org.eclipse.digitaltwin.basyx.core.exceptions.InsufficientPermissionException;
3540
import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult;
3641
import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo;
42+
import org.eclipse.digitaltwin.basyx.core.pagination.PaginationSupport;
3743
import org.eclipse.digitaltwin.basyx.submodelregistry.feature.authorization.rbac.SubmodelRegistryTargetPermissionVerifier;
3844
import org.eclipse.digitaltwin.basyx.submodelregistry.model.SubmodelDescriptor;
3945
import org.eclipse.digitaltwin.basyx.submodelregistry.service.errors.SubmodelAlreadyExistsException;
4046
import org.eclipse.digitaltwin.basyx.submodelregistry.service.errors.SubmodelNotFoundException;
4147
import org.eclipse.digitaltwin.basyx.submodelregistry.service.storage.SubmodelRegistryStorage;
48+
import org.slf4j.Logger;
49+
import org.slf4j.LoggerFactory;
4250

4351
/**
4452
* Decorator for authorized {@link SubmodelRegistryStorage}
@@ -47,6 +55,7 @@
4755
*/
4856
public class AuthorizedSubmodelRegistryStorage implements SubmodelRegistryStorage {
4957

58+
private static final Logger LOGGER = LoggerFactory.getLogger(AuthorizedSubmodelRegistryStorage.class);
5059
private SubmodelRegistryStorage decorated;
5160
private RbacPermissionResolver<SubmodelRegistryTargetInformation> permissionResolver;
5261

@@ -57,8 +66,34 @@ public AuthorizedSubmodelRegistryStorage(SubmodelRegistryStorage decorated, Rbac
5766

5867
@Override
5968
public CursorResult<List<SubmodelDescriptor>> getAllSubmodelDescriptors(PaginationInfo pRequest) {
60-
assertHasPermission(Action.READ, getIdAsList(SubmodelRegistryTargetPermissionVerifier.ALL_ALLOWED_WILDCARD));
61-
return decorated.getAllSubmodelDescriptors(pRequest);
69+
boolean isAuthorized = permissionResolver.hasPermission(Action.READ, new SubmodelRegistryTargetInformation(getIdAsList(SubmodelRegistryTargetPermissionVerifier.ALL_ALLOWED_WILDCARD)));
70+
throwExceptionIfInsufficientPermission(isAuthorized);
71+
72+
if (isAuthorized)
73+
return decorated.getAllSubmodelDescriptors(pRequest);
74+
75+
List<TargetInformation> targetInformations = permissionResolver.getMatchingTargetInformationInRules(Action.READ, new SubmodelRegistryTargetInformation(getIdAsList(SubmodelRegistryTargetPermissionVerifier.ALL_ALLOWED_WILDCARD)));
76+
77+
List<String> allIds = targetInformations.stream().map(SubmodelRegistryTargetInformation.class::cast)
78+
.map(SubmodelRegistryTargetInformation::getSubmodelIds).flatMap(List::stream).collect(Collectors.toList());
79+
80+
List<SubmodelDescriptor> aasDescriptors = allIds.stream().map(id -> {
81+
try {
82+
return getSubmodelDescriptor(id);
83+
} catch (SubmodelNotFoundException e) {
84+
LOGGER.error("Submodel Descriptor: '{}' not found, Error: {}", id, e.getMessage());
85+
return null;
86+
} catch (Exception e) {
87+
LOGGER.error("Exception occurred while retrieving the Submodel Descriptor: {}, Error: {}", id, e.getMessage());
88+
return null;
89+
}
90+
}).filter(Objects::nonNull).collect(Collectors.toList());
91+
92+
TreeMap<String, SubmodelDescriptor> aasMap = aasDescriptors.stream().collect(Collectors.toMap(SubmodelDescriptor::getId, aas -> aas, (a, b) -> a, TreeMap::new));
93+
94+
PaginationSupport<SubmodelDescriptor> paginationSupport = new PaginationSupport<>(aasMap, SubmodelDescriptor::getId);
95+
96+
return paginationSupport.getPaged(pRequest);
6297
}
6398

6499
@Override

0 commit comments

Comments
 (0)