Skip to content

Commit 8c62c18

Browse files
[SELC-7948] feat: modify getInstution to retrieve roles and actions from IAM (#558)
1 parent 90f712a commit 8c62c18

File tree

7 files changed

+393
-22
lines changed

7 files changed

+393
-22
lines changed

docs/openapi/api-iam-docs.json

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,34 @@
2828
}
2929
}
3030
},
31+
"ProductRolePermissions" : {
32+
"type" : "object",
33+
"properties" : {
34+
"productId" : {
35+
"type" : "string"
36+
},
37+
"role" : {
38+
"type" : "string"
39+
},
40+
"permissions" : {
41+
"type" : "array",
42+
"items" : {
43+
"type" : "string"
44+
}
45+
}
46+
}
47+
},
48+
"ProductRolePermissionsList" : {
49+
"type" : "object",
50+
"properties" : {
51+
"items" : {
52+
"type" : "array",
53+
"items" : {
54+
"$ref" : "#/components/schemas/ProductRolePermissions"
55+
}
56+
}
57+
}
58+
},
3159
"ProductRoles" : {
3260
"type" : "object",
3361
"properties" : {
@@ -208,6 +236,59 @@
208236
} ]
209237
}
210238
},
239+
"/iam/users/role/permissions/{uid}" : {
240+
"get" : {
241+
"summary" : "Get IAM user Product Role Permissions List",
242+
"description" : "Retrieves a list of product, role and permissions by user ID and product ID.",
243+
"operationId" : "getIAMProductRolePermissionsList",
244+
"tags" : [ "external-v2" ],
245+
"parameters" : [ {
246+
"name" : "uid",
247+
"in" : "path",
248+
"required" : true,
249+
"schema" : {
250+
"type" : "string"
251+
}
252+
}, {
253+
"name" : "productId",
254+
"in" : "query",
255+
"schema" : {
256+
"type" : "string"
257+
}
258+
} ],
259+
"responses" : {
260+
"200" : {
261+
"description" : "OK",
262+
"content" : {
263+
"application/json" : {
264+
"schema" : {
265+
"$ref" : "#/components/schemas/ProductRolePermissionsList"
266+
}
267+
}
268+
}
269+
},
270+
"500" : {
271+
"description" : "Internal Server Error",
272+
"content" : {
273+
"application/problem+json" : {
274+
"schema" : {
275+
"$ref" : "#/components/schemas/Problem"
276+
}
277+
}
278+
}
279+
},
280+
"401" : {
281+
"description" : "Not Authorized"
282+
},
283+
"403" : {
284+
"description" : "Not Allowed"
285+
}
286+
},
287+
"security" : [ {
288+
"SecurityScheme" : [ ]
289+
} ]
290+
}
291+
},
211292
"/iam/users/{uid}" : {
212293
"get" : {
213294
"summary" : "Get IAM User",

integration-test-config/db/userClaims.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,21 @@
99
]
1010
}]
1111
},
12+
{
13+
"_id": "9f2b6b54-6c2b-4b36-8d83-4cd1d6fcf3e8",
14+
"email": "EEFF4l3KRN2cJKm8PDpdMjrVeWG00GeYY6JCbxHlcAPSpQ==",
15+
"productRoles": [{
16+
"productId": "prod-interop",
17+
"roles": [
18+
"OPERATOR"
19+
]},
20+
{
21+
"productId": "ALL",
22+
"roles": [
23+
"SUPPORT"
24+
]
25+
}]
26+
},
1227
{
1328
"_id": "a0530f76-3454-418c-9d65-eb3162075495",
1429
"email": "EEFF4l3KRN6cJKm8PDpdMjrVx7KTMZG/p/OjXGPw8gHYAg==",

src/main/java/it/pagopa/selfcare/dashboard/service/InstitutionV2ServiceImpl.java

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@
33
import it.pagopa.selfcare.commons.base.security.SelfCareUser;
44
import it.pagopa.selfcare.core.generated.openapi.v1.dto.OnboardingResponse;
55
import it.pagopa.selfcare.core.generated.openapi.v1.dto.OnboardingsResponse;
6-
import it.pagopa.selfcare.dashboard.client.CoreInstitutionApiRestClient;
7-
import it.pagopa.selfcare.dashboard.client.OnboardingRestClient;
8-
import it.pagopa.selfcare.dashboard.client.TokenRestClient;
9-
import it.pagopa.selfcare.dashboard.client.UserApiRestClient;
6+
import it.pagopa.selfcare.dashboard.client.*;
107
import it.pagopa.selfcare.dashboard.exception.ResourceNotFoundException;
118
import it.pagopa.selfcare.dashboard.model.institution.Institution;
129
import it.pagopa.selfcare.dashboard.model.institution.RelationshipState;
@@ -15,6 +12,8 @@
1512
import it.pagopa.selfcare.dashboard.model.user.OnboardedProductWithActions;
1613
import it.pagopa.selfcare.dashboard.model.user.UserInfo;
1714
import it.pagopa.selfcare.dashboard.model.user.UserInstitutionWithActionsDto;
15+
import it.pagopa.selfcare.iam.generated.openapi.v1.dto.ProductRolePermissions;
16+
import it.pagopa.selfcare.iam.generated.openapi.v1.dto.ProductRolePermissionsList;
1817
import it.pagopa.selfcare.onboarding.generated.openapi.v1.dto.OnboardingGetResponse;
1918
import lombok.extern.slf4j.Slf4j;
2019
import org.owasp.encoder.Encode;
@@ -46,6 +45,7 @@ public class InstitutionV2ServiceImpl implements InstitutionV2Service {
4645
private final UserApiRestClient userApiRestClient;
4746
private final CoreInstitutionApiRestClient coreInstitutionApiRestClient;
4847
private final OnboardingRestClient onboardingRestClient;
48+
private final IamExternalRestClient iamExternalRestClient;
4949
private final TokenRestClient tokenRestClient;
5050
private final UserMapper userMapper;
5151
private final InstitutionMapper institutionMapper;
@@ -56,6 +56,7 @@ public InstitutionV2ServiceImpl(@Value("${dashboard.institution.getUsers.filter.
5656
UserApiRestClient userApiRestClient,
5757
CoreInstitutionApiRestClient coreInstitutionApiRestClient,
5858
OnboardingRestClient onboardingRestClient,
59+
IamExternalRestClient iamExternalRestClient,
5960
TokenRestClient tokenRestClient,
6061
UserMapper userMapper,
6162
InstitutionMapper institutionMapper,
@@ -64,6 +65,7 @@ public InstitutionV2ServiceImpl(@Value("${dashboard.institution.getUsers.filter.
6465
this.userApiRestClient = userApiRestClient;
6566
this.coreInstitutionApiRestClient = coreInstitutionApiRestClient;
6667
this.onboardingRestClient = onboardingRestClient;
68+
this.iamExternalRestClient = iamExternalRestClient;
6769
this.tokenRestClient = tokenRestClient;
6870
this.userMapper = userMapper;
6971
this.institutionMapper = institutionMapper;
@@ -112,14 +114,13 @@ public Institution findInstitutionById(String institutionId) {
112114
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
113115
SelfCareUser selfCareUser = (SelfCareUser) authentication.getPrincipal();
114116
String issuer = selfCareUser.getIssuer();
117+
String userId = selfCareUser.getId();
115118

116119
if (ISSUER_PAGOPA.equalsIgnoreCase(issuer)) {
117-
log.debug("Issuer is PAGOPA, skipping user-institution permission checks");
118-
return institution;
120+
log.debug("Issuer is PAGOPA, using IAM to check permissions");
121+
return getInstitutionWithActionsIam(institutionId, userId, institution);
119122
}
120123

121-
String userId = selfCareUser.getId();
122-
123124
UserInstitutionWithActionsDto userInstitutionWithActionsDto = userMapper.toUserInstitutionWithActionsDto(userApiRestClient._getUserInstitutionWithPermission(institutionId, userId, null).getBody());
124125

125126
if (Objects.isNull(userInstitutionWithActionsDto))
@@ -143,6 +144,35 @@ public Institution findInstitutionById(String institutionId) {
143144
return institution;
144145
}
145146

147+
private Institution getInstitutionWithActionsIam(String institutionId, String userId, Institution institution) {
148+
149+
List<ProductRolePermissions> productRolePermissions = Optional.ofNullable(
150+
iamExternalRestClient._getIAMProductRolePermissionsList(userId, null).getBody())
151+
.map(ProductRolePermissionsList::getItems)
152+
.filter(list -> !list.isEmpty())
153+
.orElseThrow(() -> new AccessDeniedException(
154+
String.format("User %s has not permission on institution %s", userId, institutionId)));
155+
156+
ProductRolePermissions globalPermission = productRolePermissions.stream()
157+
.filter(p -> "ALL".equals(p.getProductId()))
158+
.findFirst().orElse(null);
159+
160+
institution.getOnboarding().stream()
161+
.filter(p -> RelationshipState.ACTIVE.equals(p.getStatus()))
162+
.forEach(p -> productRolePermissions.stream()
163+
.filter(iam -> iam.getProductId().equals(p.getProductId()))
164+
.findFirst()
165+
.or(() -> Optional.ofNullable(globalPermission))
166+
.ifPresent(iam -> {
167+
p.setAuthorized(true);
168+
p.setUserRole(iam.getRole());
169+
p.setUserProductActions(iam.getPermissions());
170+
}));
171+
172+
return institution;
173+
}
174+
175+
146176
@Override
147177
public OnboardingsResponse getOnboardingsInfoResponse(String institutionId, List<String> products) {
148178
log.trace("getOnboardingsResponse start");

src/test/java/it/pagopa/selfcare/dashboard/integration_test/CucumberSuite.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
@ConfigurationParameters({
2828
@ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "pretty"),
2929
@ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "html:target/cucumber-report/cucumber.html"),
30+
@ConfigurationParameter(key = "cucumber.filter.tags", value = "not @skip")
3031
})
3132
@CucumberContextConfiguration
3233
@TestPropertySource(locations = "classpath:application-test.properties")

0 commit comments

Comments
 (0)