All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.xlrit.gears.plugin.scim.GroupHandler Maven / Gradle / Ivy
package com.xlrit.gears.plugin.scim;
import java.time.OffsetDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import com.google.common.collect.Sets;
import com.xlrit.gears.base.model.Role;
import com.xlrit.gears.base.model.User;
import com.xlrit.gears.base.repository.RoleRepository;
import com.xlrit.gears.base.repository.UserRepository;
import com.xlrit.gears.engine.util.EngineUtils;
import de.captaingoldfish.scim.sdk.common.constants.enums.SortOrder;
import de.captaingoldfish.scim.sdk.common.exceptions.BadRequestException;
import de.captaingoldfish.scim.sdk.common.exceptions.ResourceNotFoundException;
import de.captaingoldfish.scim.sdk.common.resources.Group;
import de.captaingoldfish.scim.sdk.common.resources.complex.Meta;
import de.captaingoldfish.scim.sdk.common.resources.multicomplex.Member;
import de.captaingoldfish.scim.sdk.common.schemas.SchemaAttribute;
import de.captaingoldfish.scim.sdk.server.endpoints.Context;
import de.captaingoldfish.scim.sdk.server.endpoints.ResourceHandler;
import de.captaingoldfish.scim.sdk.server.filter.FilterNode;
import de.captaingoldfish.scim.sdk.server.response.PartialListResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static com.xlrit.gears.plugin.scim.Helper.createResponse;
import static com.xlrit.gears.plugin.scim.Helper.toLocalDateTime;
public class GroupHandler extends ResourceHandler {
private static final Logger LOG = LoggerFactory.getLogger(GroupHandler.class);
private final RoleRepository roles;
private final UserRepository users;
private final Map roleMapping;
public GroupHandler(RoleRepository roles, UserRepository users, Map roleMapping) {
this.roles = roles;
this.users = users;
this.roleMapping = roleMapping;
LOG.info("SCIM role mapping: {}", roleMapping);
}
@Override
public Group createResource(Group provGroup, Context context) {
LOG.info("createResource: group={}", provGroup);
String id = provGroup.getExternalId().map(EngineUtils::uuidToUlid).orElseThrow();
LOG.debug("createResource: externalId '{}' converted to id '{}'", provGroup.getExternalId().get(), id);
Role nativeRole = roles.create(id);
OffsetDateTime now = OffsetDateTime.now();
nativeRole.setCreatedAt(now);
nativeRole.setModifiedAt(now);
copy(provGroup, nativeRole);
LOG.info("result: {}", nativeRole);
return convert(nativeRole);
}
@Override
public Group getResource(String id, List attributes, List excludedAttributes, Context context) {
LOG.info("getResource: id={}, attributes={}, excludedAttributes={}", id, attributes, excludedAttributes);
Role nativeRole = getRoleById(id);
return convert(nativeRole);
}
@Override
public PartialListResponse listResources(long startIndex, int count, FilterNode filter, SchemaAttribute sortBy, SortOrder sortOrder, List attrs, List excludedAttrs, Context context) {
LOG.info("listResources: start={}, count={}, filter={}, sort={} {}, attrs={}", startIndex, count, filter, sortBy, sortOrder, attrs);
List nativeRoles = this.roles.findAll();
List provGroups = nativeRoles.stream()
.filter(Role::getActive)
.map(this::convert)
.collect(Collectors.toList());
return createResponse(provGroups);
}
@Override
public Group updateResource(Group provGroup, Context context) {
LOG.info("updateResource: group={}", provGroup);
String groupId = provGroup.getId().orElseThrow(() -> new BadRequestException("Group id is required"));
Role nativeRole = getRoleById(groupId);
copy(provGroup, nativeRole);
LOG.info("result: {}", nativeRole);
return convert(nativeRole);
}
@Override
public void deleteResource(String id, Context context) {
LOG.info("deleteResource: id={}", id);
Role nativeRole = getRoleById(id);
nativeRole.setActive(false);
}
private Role getRoleById(String roleId) {
Role nativeRole = roles.findById(roleId);
if (nativeRole == null) throw new ResourceNotFoundException("Group with id '" + roleId + "' not found");
return nativeRole;
}
private void copy(Group provGroup, Role nativeRole) {
nativeRole.setActive(true);
provGroup.getExternalId().ifPresent(nativeRole::setExternalId);
provGroup.getDisplayName().ifPresent(externalName -> {
nativeRole.setExternalName(externalName);
nativeRole.setName(externalNameToName(externalName));
nativeRole.setType("WORKFLOW");
});
provGroup.getMeta().ifPresent(meta -> {
meta.getCreated().ifPresent(created -> nativeRole.setCreatedAt(toLocalDateTime(created)));
meta.getLastModified().ifPresent(modified -> nativeRole.setModifiedAt(toLocalDateTime(modified)));
});
syncMembers(provGroup, nativeRole);
}
private String externalNameToName(String externalName) {
return roleMapping.getOrDefault(externalName, externalName);
}
private void syncMembers(Group provGroup, Role nativeRole) {
Set targetUserIds = provGroup.getMembers().stream()
.map(Member::getValue)
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toSet());
Set actualUserIds = nativeRole.getUsers().stream()
.map(User::getId)
.collect(Collectors.toSet());
Collection addUsers = resolveUsers(List.copyOf(Sets.difference(targetUserIds, actualUserIds)));
Collection remUsers = nativeRole.getUsers().stream()
.filter(user -> !targetUserIds.contains(user.getId()))
.collect(Collectors.toList());
nativeRole.addUsersBidi(addUsers);
nativeRole.removeUsersBidi(remUsers);
}
private List resolveUsers(List userIds) {
List nativeUsers = this.users.findByIds(userIds);
List missingUserIds = IntStream.range(0, nativeUsers.size())
.filter(index -> nativeUsers.get(index) == null)
.mapToObj(userIds::get)
.collect(Collectors.toList());
if (!missingUserIds.isEmpty()) {
throw new ResourceNotFoundException("Users with the following ids were not found: " + missingUserIds);
}
return nativeUsers;
}
private Group convert(Role nativeRole) {
String displayName = Objects.requireNonNullElseGet(nativeRole.getExternalName(), nativeRole::getName);
List members = nativeRole.getUsers().stream()
.map(this::toMember)
.collect(Collectors.toList());
return Group.builder()
.id(nativeRole.getId())
.externalId(nativeRole.getExternalId())
.displayName(displayName)
.meta(Meta.builder()
.resourceType("Group")
.created(nativeRole.getCreatedAt())
.lastModified(nativeRole.getModifiedAt())
.build()
)
.members(members)
.build();
}
private Member toMember(User user) {
return Member.builder().value(user.getId()).build();
}
}