Skip to content

Commit 962a01a

Browse files
committed
Fixes #642
1 parent 862d9ca commit 962a01a

18 files changed

+139
-59
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,4 @@ teams-api-calls.md
4848
.run/
4949
client/locale_parser.js
5050
PlayGroundTest.java
51+
spieldata

server/src/main/java/invite/api/InvitationController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ public ResponseEntity<Map<String, Object>> accept(@Validated @RequestBody Accept
356356
//Already provisioned users in the remote systems are ignored / excluded
357357
Optional<GraphResponse> optionalGraphResponse = isGuest ? provisioningService.newUserRequest(user) : Optional.empty();
358358
if (isGuest) {
359-
newUserRoles.forEach(userRole -> provisioningService.updateGroupRequest(userRole, OperationType.Add));
359+
newUserRoles.forEach(userRole -> provisioningService.updateGroupRequest(userRole, OperationType.add));
360360
}
361361
LOG.info(String.format("User %s accepted invitation with role(s) %s",
362362
user.getEduPersonPrincipalName(),

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,9 @@ public ResponseEntity<Role> newRole(@Validated @RequestBody RoleRequest roleRequ
192192
public ResponseEntity<Role> updateRole(@Validated @RequestBody Role role,
193193
@Parameter(hidden = true) User user) {
194194
LOG.debug(String.format("PUT /roles/ for user %s", user.getEduPersonPrincipalName()));
195-
UserPermissions.assertAuthority(user, Authority.MANAGER);
195+
196+
UserPermissions.assertRoleAccess(user, role, Authority.MANAGER);
197+
196198
LOG.debug(String.format("Update role '%s' by user %s", role.getName(), user.getEduPersonPrincipalName()));
197199
return saveOrUpdate(role, user);
198200
}

server/src/main/java/invite/api/UserRoleController.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ public ResponseEntity<User> userRoleProvisioning(@Validated @RequestBody UserRol
199199
AccessLogger.user(LOG, Event.Created, user);
200200

201201
provisioningService.newUserRequest(user);
202-
newUserRoles.forEach(userRole -> provisioningService.updateGroupRequest(userRole, OperationType.Add));
202+
newUserRoles.forEach(userRole -> provisioningService.updateGroupRequest(userRole, OperationType.add));
203203

204204
return ResponseEntity.status(201).body(user);
205205
}
@@ -242,7 +242,7 @@ public ResponseEntity<Void> deleteUserRole(@PathVariable("id") Long id,
242242
AccessLogger.userRole(LOG, Event.Updated, user, userRole);
243243

244244
} else {
245-
provisioningService.updateGroupRequest(userRole, OperationType.Remove);
245+
provisioningService.updateGroupRequest(userRole, OperationType.remove);
246246
provisioningService.deleteUserRoleRequest(userRole);
247247
userRoleAuditService.logAction(userRole, UserRoleAudit.ActionType.DELETE);
248248
// Deprovision the user for all provisionings which are exclusively used in this userRole

server/src/main/java/invite/config/HashGenerator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public static String generateRandomHash(int byteLength) {
2727
}
2828

2929
public static String generateToken() {
30-
return RandomStringUtils.secure().random(36, true, true);
30+
return RandomStringUtils.secure().next(36, true, true);
3131
}
3232

3333
public static String hashToken(String token) {

server/src/main/java/invite/cron/ResourceCleaner.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ private List<UserRole> cleanUserRoles() {
9696
User user = userRole.getUser();
9797
Role role = userRole.getRole();
9898
try {
99-
provisioningService.updateGroupRequest(userRole, OperationType.Remove);
99+
provisioningService.updateGroupRequest(userRole, OperationType.remove);
100100
user.removeUserRole(userRole);
101101
userRepository.save(user);
102102
LOG.info(String.format("Deleted userRole for user %s and role %s with an endDate in the past",

server/src/main/java/invite/model/RoleRequest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public class RoleRequest implements Serializable{
2525

2626
@NotNull
2727
@NotBlank
28-
@Schema(description = "Unique name of the role", example = "Guest for my application", required = true)
28+
@Schema(description = "Unique name of the role", example = "Guest for my application", requiredMode = Schema.RequiredMode.REQUIRED)
2929
private String name;
3030

3131
@Schema(description = "Brief explanation of this role's purpose", example = "Full access to all modules")

server/src/main/java/invite/provision/ProvisioningServiceDefault.java

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@
1919
import invite.provision.eva.EvaClient;
2020
import invite.provision.graph.GraphClient;
2121
import invite.provision.graph.GraphResponse;
22+
import invite.provision.scim.DisplayNameOperation;
2223
import invite.provision.scim.GroupPatchRequest;
2324
import invite.provision.scim.GroupRequest;
2425
import invite.provision.scim.GroupURN;
2526
import invite.provision.scim.Member;
26-
import invite.provision.scim.Operation;
27+
import invite.provision.scim.MembersOperation;
2728
import invite.provision.scim.OperationType;
2829
import invite.provision.scim.UserRequest;
2930
import invite.repository.RemoteProvisionedGroupRepository;
@@ -44,9 +45,7 @@
4445
import org.springframework.http.MediaType;
4546
import org.springframework.http.RequestEntity;
4647
import org.springframework.http.ResponseEntity;
47-
import org.springframework.http.client.ClientHttpRequestInterceptor;
4848
import org.springframework.http.client.JdkClientHttpRequestFactory;
49-
import org.springframework.retry.support.RetryTemplate;
5049
import org.springframework.stereotype.Service;
5150
import org.springframework.util.StringUtils;
5251
import org.springframework.web.client.RestClientException;
@@ -64,7 +63,6 @@
6463
import java.util.Set;
6564
import java.util.concurrent.atomic.AtomicReference;
6665
import java.util.stream.Collectors;
67-
import java.util.stream.Stream;
6866

6967
@Service
7068
@SuppressWarnings("unchecked")
@@ -228,7 +226,7 @@ public void deleteUserRoleRequest(UserRole userRole) {
228226
public void deleteUserRequest(User user) {
229227
//First send update role requests
230228
user.getUserRoles()
231-
.forEach(userRole -> this.updateGroupRequest(userRole, OperationType.Remove));
229+
.forEach(userRole -> this.updateGroupRequest(userRole, OperationType.remove));
232230

233231
List<Provisioning> provisionings = getProvisionings(user);
234232
//Delete the user to all provisionings in Manage where the user is known
@@ -238,7 +236,7 @@ public void deleteUserRequest(User user) {
238236
@Override
239237
public void deleteUserRequest(User user, UserRole userRole) {
240238
//First send update role request
241-
this.updateGroupRequest(userRole, OperationType.Remove);
239+
this.updateGroupRequest(userRole, OperationType.remove);
242240
/*
243241
* We first need a List all provisionings for the user#userRole, and then we need to remove the provisiongs
244242
* from that List that are in use by other user#userRoles, and those are the provisionings which we need to delete
@@ -343,9 +341,9 @@ public void updateGroupRequest(UserRole userRole, OperationType operationType) {
343341
.filter(userRoleDB -> userRoleDB.getAuthority().equals(Authority.GUEST) || userRoleDB.isGuestRoleIncluded())
344342
.collect(Collectors.toCollection(ArrayList::new));
345343
boolean userRolePresent = userRoles.stream().anyMatch(dbUserRole -> dbUserRole.getId().equals(userRole.getId()));
346-
if (operationType.equals(OperationType.Add) && !userRolePresent) {
344+
if (operationType.equals(OperationType.add) && !userRolePresent) {
347345
userRoles.add(userRole);
348-
} else if (operationType.equals(OperationType.Remove) && userRolePresent) {
346+
} else if (operationType.equals(OperationType.remove) && userRolePresent) {
349347
userRoles = userRoles.stream()
350348
.filter(dbUserRole -> !dbUserRole.getId().equals(userRole.getId()))
351349
.collect(Collectors.toCollection(ArrayList::new));
@@ -381,31 +379,30 @@ private void sendGroupPutRequest(Provisioning provisioning,
381379
.map(Optional::get)
382380
.map(RemoteProvisionedUser::getRemoteIdentifier)
383381
.toList();
384-
if (!userScimIdentifiers.isEmpty()) {
382+
if (!userScimIdentifiers.isEmpty() || operationType.equals(OperationType.replace)) {
385383
if (provisioning.isScimUpdateRolePutMethod()) {
386384
String groupRequest = constructGroupRequest(
387385
role,
388386
provisionedGroup.getRemoteIdentifier(),
389387
userScimIdentifiers);
390388
this.updateRequest(provisioning, groupRequest, APIType.GROUP_API, provisionedGroup.getRemoteIdentifier(), HttpMethod.PUT);
391389
} else {
392-
String groupRequest = patchGroupRequest(
393-
role,
394-
userScimIdentifiers,
395-
provisionedGroup.getRemoteIdentifier(),
396-
operationType);
390+
GroupPatchRequest request = operationType.equals(OperationType.replace) ?
391+
new GroupPatchRequest(new DisplayNameOperation(role.getName())):
392+
new GroupPatchRequest(new MembersOperation(operationType, userScimIdentifiers));
393+
String groupRequest = prettyJson(request);
397394
this.updateRequest(provisioning, groupRequest, APIType.GROUP_API, provisionedGroup.getRemoteIdentifier(), HttpMethod.PATCH);
398395
}
399396
}
400-
401397
}
402398

403399
@Override
404400
public void updateGroupRequest(List<String> previousManageIdentifiers, Role newRole, boolean nameChanged) {
405401
//Immutable List cannot be sorted
406402
List<String> previousManageIdentifiersSorted = previousManageIdentifiers.stream().sorted().toList();
407403
List<String> newManageIdentifiers = this.getManageIdentifiers(newRole);
408-
if (!nameChanged && previousManageIdentifiers.equals(newManageIdentifiers)) {
404+
boolean noApplicationsChanged = previousManageIdentifiers.equals(newManageIdentifiers);
405+
if (!nameChanged && noApplicationsChanged) {
409406
LOG.info(String.format("Group %s update request with no difference in manage identifiers (%s). No action required",
410407
newRole.getName(),
411408
newManageIdentifiers));
@@ -436,13 +433,14 @@ public void updateGroupRequest(List<String> previousManageIdentifiers, Role newR
436433
}
437434
provisionedGroupOptional.ifPresent(provisionedGroup -> {
438435
List<UserRole> userRoles = userRoleRepository.findByRole(newRole);
439-
this.sendGroupPutRequest(provisioning, provisionedGroup, userRoles, newRole, OperationType.Add);
436+
this.sendGroupPutRequest(provisioning, provisionedGroup, userRoles, newRole, OperationType.replace);
440437
});
441438
});
442439

443440
LOG.info(String.format("Deleting existing provisionings %s from group %s", deletedManageIdentifiers, newRole.getName()));
444441

445-
List<Provisioning> provisionings = manage.provisioning(deletedManageIdentifiers).stream().map(Provisioning::new).toList();
442+
List<Provisioning> provisionings = manage.provisioning(deletedManageIdentifiers).stream()
443+
.map(Provisioning::new).toList();
446444
deleteGroupRequest(newRole, provisionings);
447445
}
448446

@@ -488,16 +486,6 @@ private String constructGroupRequest(Role role, String remoteGroupScimIdentifier
488486
return prettyJson(new GroupRequest(externalId, remoteGroupScimIdentifier, role.getName(), members));
489487
}
490488

491-
private String patchGroupRequest(Role role,
492-
List<String> remoteScimProvisionedUsers,
493-
String remoteScimProvisionedGroup,
494-
OperationType operationType) {
495-
String externalId = GroupURN.urnFromRole(groupUrnPrefix, role);
496-
GroupPatchRequest request = new GroupPatchRequest(externalId, remoteScimProvisionedGroup,
497-
new Operation(operationType, remoteScimProvisionedUsers));
498-
return prettyJson(request);
499-
}
500-
501489
private Optional<ProvisioningResponse> newRequest(Provisioning provisioning, String request, Provisionable provisionable) {
502490
boolean isUser = provisionable instanceof User;
503491
APIType apiType = isUser ? APIType.USER_API : APIType.GROUP_API;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package invite.provision.scim;
2+
3+
import lombok.Getter;
4+
5+
import java.util.HashSet;
6+
import java.util.List;
7+
8+
@Getter
9+
public class DisplayNameOperation implements Operation {
10+
11+
private final OperationType op = OperationType.replace;
12+
private final String path = "displayName";
13+
private final String value;
14+
15+
public DisplayNameOperation(String value) {
16+
this.value = value;
17+
}
18+
19+
}

server/src/main/java/invite/provision/scim/GroupPatchRequest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public class GroupPatchRequest implements Serializable {
1414
@JsonProperty("Operations")
1515
private final List<Operation> operations;
1616

17-
public GroupPatchRequest(String externalId, String id, Operation operation) {
17+
public GroupPatchRequest(Operation operation) {
1818
this.operations = Collections.singletonList(operation);
1919
}
2020
}

0 commit comments

Comments
 (0)