Skip to content
Merged
2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint .",
"lint": "eslint ./src",
"preview": "vite preview",
"test": "vitest"
},
Expand Down
1 change: 1 addition & 0 deletions client/src/pages/RoleForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ export const RoleForm = () => {
<InputField name={I18n.t("roles.landingPage")}
value={application ? application.landingPage : null}
isUrl={true}
required={true}
disabled={isEmpty(application) || !allowedToEditApplication}
placeholder={I18n.t("roles.landingPagePlaceHolder")}
onBlur={e => validateApplication(index, e.target.value)}
Expand Down
2 changes: 1 addition & 1 deletion client/src/tabs/Tokens.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export const Tokens = () => {
});
}
});
}, []);
}, [user.superUser]);

useEffect(() => {
if (!isGuest) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,22 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static invite.SwaggerOpenIdConfig.BASIC_AUTHENTICATION_SCHEME_NAME;

Expand All @@ -31,6 +40,8 @@
public class AttributeAggregatorController {

private static final Log LOG = LogFactory.getLog(AttributeAggregatorController.class);
private static final String AUTORISATIE = "autorisatie";
private static final String ID = "id";

private final UserRepository userRepository;
private final Manage manage;
Expand Down Expand Up @@ -72,19 +83,32 @@ public ResponseEntity<List<Map<String, String>>> getGroupMemberships(@PathVariab
userRepository.save(user);

Map<String, Object> provider = optionalProvider.get();
List<Map<String, String>> userRoles = user.getUserRoles().stream()
.filter(userRole -> userRole.getRole().applicationsUsed().stream().anyMatch(application -> application.getManageId().equals(provider.get("id"))))
List<Map<String, String>> userRoleList = user.getUserRoles().stream()
.filter(userRole -> userRole.getRole().applicationsUsed().stream()
.anyMatch(application -> application.getManageId().equals(provider.get(ID))))
.filter(userRole -> userRole.getAuthority().equals(Authority.GUEST) || userRole.isGuestRoleIncluded())
.map(this::parseUserRole)
.toList();
LOG.debug(String.format("Returning %o roles for AA request for user: %s and service %s", userRoles.size(), unspecifiedId, spEntityId));
return ResponseEntity.ok(userRoles);
.collect(Collectors.toCollection(ArrayList::new));

List<Map<String, String>> autorisatieRoles = userRoleList.stream().filter(m -> m.containsKey(AUTORISATIE)).toList();
if (!autorisatieRoles.isEmpty()) {
Role role = user.getUserRoles().stream()
.map(userRole -> userRole.getRole())
.filter(r -> StringUtils.hasText(r.getCrmRoleId()))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("Won't happen"));
userRoleList.add(Map.of(AUTORISATIE, "urn:mace:surfnet.nl:surfnet.nl:sab:organizationCode:" + role.getCrmOrganisationCode()));
userRoleList.add(Map.of(AUTORISATIE, "urn:mace:surfnet.nl:surfnet.nl:sab:organizationGUID:" + role.getCrmOrganisationId()));
}
LOG.debug(String.format("Returning %o roles for AA request for user: %s and service %s", userRoleList.size(), unspecifiedId, spEntityId));

return ResponseEntity.ok(userRoleList);
}

private Map<String, String> parseUserRole(UserRole userRole) {
Role role = userRole.getRole();
String urn = GroupURN.urnFromRole(groupUrnPrefix, role);
return Map.of("id", urn);
return Map.of(StringUtils.hasText(role.getCrmRoleId()) ? AUTORISATIE : ID, urn);
}

}
52 changes: 49 additions & 3 deletions server/src/main/java/invite/api/InvitationController.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,24 @@
import invite.exception.InvitationEmailMatchingException;
import invite.exception.InvitationExpiredException;
import invite.exception.InvitationStatusException;
import invite.exception.InvitationUniqueCrmOrganisationException;
import invite.exception.NotFoundException;
import invite.logging.AccessLogger;
import invite.logging.Event;
import invite.mail.MailBox;
import invite.manage.Manage;
import invite.model.*;
import invite.model.AcceptInvitation;
import invite.model.Authority;
import invite.model.Invitation;
import invite.model.InvitationRequest;
import invite.model.InvitationResponse;
import invite.model.InvitationRole;
import invite.model.Role;
import invite.model.Status;
import invite.model.StatusResponse;
import invite.model.User;
import invite.model.UserRole;
import invite.model.UserRoleAudit;
import invite.provision.Provisioning;
import invite.provision.ProvisioningService;
import invite.provision.graph.GraphResponse;
Expand Down Expand Up @@ -49,12 +61,26 @@
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.time.Instant;
import java.util.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import static invite.SwaggerOpenIdConfig.API_TOKENS_SCHEME_NAME;
Expand Down Expand Up @@ -280,6 +306,8 @@ public ResponseEntity<Map<String, Object>> accept(@Validated @RequestBody Accept
});

checkEmailEquality(user, invitation);
checkCrmUniqueOrganisation(user, invitation);

user.setLastActivity(Instant.now());

invitation.setStatus(Status.ACCEPTED);
Expand Down Expand Up @@ -524,5 +552,23 @@ private void checkEmailEquality(User user, Invitation invitation) {
}
}

private void checkCrmUniqueOrganisation(User user, Invitation invitation) {
if (StringUtils.hasText(invitation.getCrmContactId()) && user.getUserRoles().stream()
.map(userRole -> userRole.getRole().getCrmOrganisationId())
.anyMatch(crmOrganisationId -> StringUtils.hasText(crmOrganisationId) &&
invitation.getRoles().stream()
.map(invitationRole -> invitationRole.getRole())
.anyMatch(role -> StringUtils.hasText(role.getCrmOrganisationId()) && !role.getCrmOrganisationId().equals(crmOrganisationId)))) {
throw new InvitationUniqueCrmOrganisationException(
String.format("User %s is not allowed to accept an invitation from Organisation %s, because it already has roles for Organisation %s",
user.getEmail(),
user.getUserRoles().stream()
.map(userRole -> userRole.getRole().getCrmOrganisationId())
.toList(),
invitation.getRoles().stream()
.map(invitationRole -> invitationRole.getRole().getCrmOrganisationId())
.toList()));
}
}

}
9 changes: 5 additions & 4 deletions server/src/main/java/invite/api/InvitationOperations.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import invite.logging.AccessLogger;
import invite.logging.Event;
import invite.mail.MailBox;
import invite.manage.Manage;
import invite.model.*;
import invite.repository.InvitationRepository;
import invite.security.RemoteUser;
Expand Down Expand Up @@ -123,7 +124,7 @@ public ResponseEntity<InvitationResponse> sendInvitation(InvitationRequest invit
if (!invitationRequest.isSuppressSendingEmails()) {

invitations.forEach(invitation -> {
Optional<String> idpName = this.identityProviderName(invitation);
Optional<String> idpName = identityProviderName(this.invitationResource.getManage(), invitation);
mailBox.sendInviteMail(user == null ? remoteUser : user,
invitation, groupedProviders, invitationRequest.getLanguage(), idpName);
});
Expand Down Expand Up @@ -174,7 +175,7 @@ public ResponseEntity<Map<String, Integer>> resendInvitation(Long id,

List<GroupedProviders> groupedProviders = this.invitationResource.getManage().getGroupedProviders(requestedRoles);
Provisionable provisionable = user != null ? user : remoteUser;
Optional<String> idpName = identityProviderName(invitation);
Optional<String> idpName = identityProviderName(this.invitationResource.getManage(), invitation);

this.invitationResource.getMailBox()
.sendInviteMail(provisionable,
Expand All @@ -192,9 +193,9 @@ public ResponseEntity<Map<String, Integer>> resendInvitation(Long id,
return Results.createResult();
}

private Optional<String> identityProviderName(Invitation invitation) {
public static Optional<String> identityProviderName(Manage manage, Invitation invitation) {
return Optional.ofNullable(invitation.getOrganizationGUID())
.map(organisationGUID -> this.invitationResource.getManage().identityProvidersByInstitutionalGUID(organisationGUID))
.map(organisationGUID -> manage.identityProvidersByInstitutionalGUID(organisationGUID))
.stream()
.flatMap(Collection::stream)
.findFirst()
Expand Down
28 changes: 28 additions & 0 deletions server/src/main/java/invite/crm/CRMContact.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package invite.crm;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

import java.util.List;

@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class CRMContact {

private String uid;
private String schacHomeOrganisation;
private boolean suppressInvitation;
private String contactId;
private String firstname;
private String middlename;
private String surname;
private String email;
private CRMOrganisation organisation;
private List<CRMRole> roles;
}
Loading
Loading