Skip to content

Commit f27c4e5

Browse files
committed
WIP for #381 and #506
1 parent 8be9552 commit f27c4e5

File tree

8 files changed

+72
-42
lines changed

8 files changed

+72
-42
lines changed

server/src/main/java/access/api/InvitationOperations.java

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,7 @@
2121
import java.time.Instant;
2222
import java.time.Period;
2323
import java.time.temporal.ChronoUnit;
24-
import java.util.Comparator;
25-
import java.util.List;
26-
import java.util.Map;
27-
import java.util.Optional;
24+
import java.util.*;
2825

2926
import static java.util.stream.Collectors.toSet;
3027

@@ -115,11 +112,7 @@ public ResponseEntity<InvitationResponse> sendInvitation(InvitationRequest invit
115112
if (!invitationRequest.isSuppressSendingEmails()) {
116113

117114
invitations.forEach(invitation -> {
118-
Optional<String> idpName = Optional.ofNullable(invitation.getOrganizationGUID())
119-
.map(organisationGUID -> this.invitationResource.getManage().identityProviderByInstitutionalGUID(organisationGUID))
120-
.flatMap(optional -> optional)
121-
.map(idp -> (String) idp.get("name:en"));
122-
115+
Optional<String> idpName = this.identityProviderName(invitation);
123116
mailBox.sendInviteMail(user == null ? remoteUser : user,
124117
invitation, groupedProviders, invitationRequest.getLanguage(), idpName);
125118
});
@@ -150,10 +143,7 @@ public ResponseEntity<Map<String, Integer>> resendInvitation(Long id,
150143

151144
List<GroupedProviders> groupedProviders = this.invitationResource.getManage().getGroupedProviders(requestedRoles);
152145
Provisionable provisionable = user != null ? user : remoteUser;
153-
Optional<String> idpName = Optional.ofNullable(invitation.getOrganizationGUID())
154-
.map(organisationGUID -> this.invitationResource.getManage().identityProviderByInstitutionalGUID(organisationGUID))
155-
.flatMap(optional -> optional)
156-
.map(idp -> (String) idp.get("name:en"));
146+
Optional<String> idpName = identityProviderName(invitation);
157147

158148
this.invitationResource.getMailBox()
159149
.sendInviteMail(provisionable,
@@ -171,4 +161,14 @@ public ResponseEntity<Map<String, Integer>> resendInvitation(Long id,
171161
return Results.createResult();
172162
}
173163

164+
private Optional<String> identityProviderName(Invitation invitation) {
165+
return Optional.ofNullable(invitation.getOrganizationGUID())
166+
.map(organisationGUID -> this.invitationResource.getManage().identityProvidersByInstitutionalGUID(organisationGUID))
167+
.stream()
168+
.flatMap(Collection::stream)
169+
.findFirst()
170+
.map(idp -> (String) idp.get("name:en"));
171+
172+
}
173+
174174
}

server/src/main/java/access/api/ManageController.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.springframework.http.MediaType;
2020
import org.springframework.http.ResponseEntity;
2121
import org.springframework.transaction.annotation.Transactional;
22+
import org.springframework.util.CollectionUtils;
2223
import org.springframework.web.bind.annotation.GetMapping;
2324
import org.springframework.web.bind.annotation.PathVariable;
2425
import org.springframework.web.bind.annotation.RequestMapping;
@@ -81,9 +82,11 @@ public ResponseEntity<Map<String, Object>> organizationGUIDValidation(@Parameter
8182
LOG.debug(String.format("GET /manage/organization-guid-validation guid: %s for user %s", organizationGUID, user.getEduPersonPrincipalName()));
8283

8384
UserPermissions.assertSuperUser(user);
84-
Map<String, Object> identityProvider = manage.identityProviderByInstitutionalGUID(organizationGUID)
85-
.orElseThrow(() -> new NotFoundException("No identity provider with organizationGUID: " + organizationGUID));
86-
return ResponseEntity.ok(identityProvider);
85+
List<Map<String, Object>> identityProviders = manage.identityProvidersByInstitutionalGUID(organizationGUID);
86+
if (CollectionUtils.isEmpty(identityProviders)) {
87+
new NotFoundException("No identity provider with organizationGUID: " + organizationGUID);
88+
}
89+
return ResponseEntity.ok(identityProviders.getFirst());
8790
}
8891

8992
@GetMapping("applications")

server/src/main/java/access/api/RoleController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ public ResponseEntity<Role> newRole(@Validated @RequestBody Role role,
168168

169169
@PutMapping("")
170170
@Retryable(
171-
value = { SQLTransactionRollbackException.class },
171+
retryFor = { SQLTransactionRollbackException.class },
172172
maxAttempts = 3,
173173
backoff = @Backoff(delay = 1000)
174174
)

server/src/main/java/access/manage/LocalManage.java

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -99,27 +99,40 @@ public List<Map<String, Object>> provisioning(Collection<String> applicationIden
9999
}
100100

101101
@Override
102-
public List<Map<String, Object>> providersAllowedByIdP(Map<String, Object> identityProvider) {
103-
LOG.debug("providersAllowedByIdP for : " + identityProvider.get("type"));
104-
105-
Boolean allowedAll = (Boolean) identityProvider.getOrDefault("allowedall", Boolean.FALSE);
102+
public List<Map<String, Object>> providersAllowedByIdPs(List<Map<String, Object>> identityProviders) {
103+
if (identityProviders.isEmpty()) {
104+
return emptyList();
105+
}
106106
List<Map<String, Object>> allProviders = this.providers(EntityType.SAML20_SP, EntityType.OIDC10_RP);
107-
if (allowedAll) {
107+
if (identityProviders.stream()
108+
.anyMatch(idp -> (Boolean) idp.getOrDefault("allowedall", Boolean.FALSE))) {
108109
return allProviders;
109110
}
110-
List<Map<String, String>> allowedEntities = (List<Map<String, String>>) identityProvider.getOrDefault("allowedEntities", emptyList());
111-
List<String> entityIdentifiers = allowedEntities.stream().map(m -> m.get("name")).toList();
111+
List<String> entityIdentifiers = identityProviders.stream()
112+
.map(idp -> (List<Map<String, String>>) idp.getOrDefault("allowedEntities", emptyList()))
113+
.flatMap(Collection::stream)
114+
.map(m -> m.get("name"))
115+
.distinct()
116+
.toList();
112117
return allProviders.stream().filter(provider -> entityIdentifiers.contains((String) provider.get("entityid"))).toList();
118+
119+
}
120+
121+
@Override
122+
public List<Map<String, Object>> providersAllowedByIdP(Map<String, Object> identityProvider) {
123+
LOG.debug("providersAllowedByIdP for : " + identityProvider.get("type"));
124+
125+
return this.providersAllowedByIdPs(List.of(identityProvider));
113126
}
114127

115128
@Override
116-
public Optional<Map<String, Object>> identityProviderByInstitutionalGUID(String organisationGUID) {
129+
public List<Map<String, Object>> identityProvidersByInstitutionalGUID(String organisationGUID) {
117130
LOG.debug("identityProviderByInstitutionalGUID for : " + organisationGUID);
118131

119132
List<Map<String, Object>> providers = providers(EntityType.SAML20_IDP);
120133
return providers
121134
.stream()
122135
.filter(provider -> Objects.equals(provider.get("institutionGuid"), organisationGUID))
123-
.findAny();
136+
.toList();
124137
}
125138
}

server/src/main/java/access/manage/Manage.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ public interface Manage {
2323

2424
List<Map<String, Object>> providersAllowedByIdP(Map<String, Object> identityProvider);
2525

26-
Optional<Map<String, Object>> identityProviderByInstitutionalGUID(String organisationGUID);
26+
List<Map<String, Object>> providersAllowedByIdPs(List<Map<String, Object>> identityProviders);
27+
28+
List<Map<String, Object>> identityProvidersByInstitutionalGUID(String organisationGUID);
2729

2830
default List<Map<String, Object>> transformProvider(List<Map<String, Object>> providers) {
2931
//Defensive because of Manage misbehaviour
@@ -151,9 +153,9 @@ default Map<String, Object> enrichInstitutionAdmin(String organizationGUID) {
151153
Map<String, Object> claims = new HashMap<>();
152154
claims.put(INSTITUTION_ADMIN, true);
153155
claims.put(ORGANIZATION_GUID, organizationGUID);
154-
Optional<Map<String, Object>> optionalIdentityProvider = identityProviderByInstitutionalGUID(organizationGUID);
155-
claims.put(INSTITUTION, optionalIdentityProvider.orElse(null));
156-
List<Map<String, Object>> applications = optionalIdentityProvider.map(this::providersAllowedByIdP).orElse(Collections.emptyList());
156+
List<Map<String, Object>> identityProviders = identityProvidersByInstitutionalGUID(organizationGUID);
157+
claims.put(INSTITUTION, identityProviders.size() == 0 ? null : identityProviders.getFirst());
158+
List<Map<String, Object>> applications = this.providersAllowedByIdPs(identityProviders);
157159
claims.put(APPLICATIONS, applications);
158160
return claims;
159161
}

server/src/main/java/access/manage/RemoteManage.java

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,16 +86,22 @@ public List<Map<String, Object>> provisioning(Collection<String> applicationIden
8686
}
8787

8888
@Override
89-
public List<Map<String, Object>> providersAllowedByIdP(Map<String, Object> identityProvider) {
90-
LOG.debug("providersAllowedByIdP for : " + identityProvider.get("type"));
91-
92-
Boolean allowedAll = (Boolean) identityProvider.getOrDefault("allowedall", Boolean.FALSE);
93-
if (allowedAll) {
89+
public List<Map<String, Object>> providersAllowedByIdPs(List<Map<String, Object>> identityProviders) {
90+
LOG.debug("providersAllowedByIdPs");
91+
if (identityProviders.isEmpty()) {
92+
return emptyList();
93+
}
94+
if (identityProviders.stream()
95+
.anyMatch(idp -> (Boolean) idp.getOrDefault("allowedall", Boolean.FALSE))) {
9496
return this.providers(EntityType.SAML20_SP, EntityType.OIDC10_RP);
9597
}
96-
List<Map<String, String>> allowedEntities = (List<Map<String, String>>) identityProvider.getOrDefault("allowedEntities", emptyList());
97-
String split = allowedEntities.stream().map(m -> "\"" + m.get("name") + "\"")
98+
String split = identityProviders.stream()
99+
.map(idp -> (List<Map<String, String>>) idp.getOrDefault("allowedEntities", emptyList()))
100+
.flatMap(Collection::stream)
101+
.map(m -> "\"" + m.get("name") + "\"")
102+
.distinct()
98103
.collect(Collectors.joining(","));
104+
99105
String body = String.format("{\"data.entityid\":{\"$in\":[%s]}}", split);
100106
List<Map<String, Object>> results = new ArrayList<>();
101107
List.of(EntityType.SAML20_SP, EntityType.OIDC10_RP).forEach(entityType -> {
@@ -109,7 +115,14 @@ public List<Map<String, Object>> providersAllowedByIdP(Map<String, Object> ident
109115
}
110116

111117
@Override
112-
public Optional<Map<String, Object>> identityProviderByInstitutionalGUID(String organisationGUID) {
118+
public List<Map<String, Object>> providersAllowedByIdP(Map<String, Object> identityProvider) {
119+
LOG.debug("providersAllowedByIdP for : " + identityProvider.get("type"));
120+
121+
return this.providersAllowedByIdPs(List.of(identityProvider));
122+
}
123+
124+
@Override
125+
public List<Map<String, Object>> identityProvidersByInstitutionalGUID(String organisationGUID) {
113126
LOG.debug("identityProviderByInstitutionalGUID for : " + organisationGUID);
114127

115128
Map<String, Object> baseQuery = getBaseQuery();
@@ -122,7 +135,7 @@ public Optional<Map<String, Object>> identityProviderByInstitutionalGUID(String
122135
List<Map<String, Object>> identityProviders = restTemplate.postForObject(
123136
String.format("%s/manage/api/internal/search/%s", this.url, EntityType.SAML20_IDP.collectionName()),
124137
baseQuery, List.class);
125-
return identityProviders.isEmpty() ? Optional.empty() : Optional.of(transformProvider(identityProviders.get(0)));
138+
return transformProvider(identityProviders);
126139
}
127140

128141
private List<Map<String, Object>> getRemoteMetaData(String type) {

server/src/test/java/access/AbstractTest.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import access.config.HashGenerator;
44
import access.manage.EntityType;
55
import access.manage.LocalManage;
6-
import access.manage.Manage;
76
import access.model.*;
87
import access.repository.*;
98
import com.fasterxml.jackson.core.JsonProcessingException;
@@ -354,7 +353,7 @@ protected void stubForManageProvisioning(List<String> applicationIdentifiers) th
354353

355354
protected void stubForManageProvidersAllowedByIdP(String organisationGUID) throws JsonProcessingException {
356355
String postPath = "/manage/api/internal/search/%s";
357-
Map<String, Object> identityProvider = localManage.identityProviderByInstitutionalGUID(organisationGUID).get();
356+
Map<String, Object> identityProvider = localManage.identityProvidersByInstitutionalGUID(organisationGUID).get(0);
358357
stubFor(post(urlPathMatching(String.format(postPath, EntityType.SAML20_IDP.collectionName()))).willReturn(aResponse()
359358
.withHeader("Content-Type", "application/json")
360359
.withBody(objectMapper.writeValueAsString(List.of(identityProvider)))));

server/src/test/java/access/api/ManageControllerTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ void organizationGUIDValidation() throws Exception {
146146
AccessCookieFilter accessCookieFilter = openIDConnectFlow("/api/v1/users/login", SUPER_SUB);
147147

148148
String postPath = "/manage/api/internal/search/%s";
149-
Map<String, Object> localIdentityProvider = localManage.identityProviderByInstitutionalGUID(ORGANISATION_GUID).get();
149+
Map<String, Object> localIdentityProvider = localManage.identityProvidersByInstitutionalGUID(ORGANISATION_GUID).get(0);
150150
stubFor(post(urlPathMatching(String.format(postPath, EntityType.SAML20_IDP.collectionName()))).willReturn(aResponse()
151151
.withHeader("Content-Type", "application/json")
152152
.withBody(objectMapper.writeValueAsString(List.of(localIdentityProvider)))));

0 commit comments

Comments
 (0)