in core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java [270:470]
public PropagationByResource<String> update(final Group toBeUpdated, final GroupUR groupUR) {
// Re-merge any pending change from workflow tasks
Group group = groupDAO.save(toBeUpdated);
GroupTO anyTO = AnyOperations.patch(getGroupTO(group, true), groupUR);
// Save projection on Resources (before update)
Map<String, ConnObject> beforeOnResources =
onResources(group, groupDAO.findAllResourceKeys(group.getKey()), null, Set.of());
SyncopeClientCompositeException scce = SyncopeClientException.buildComposite();
// realm
setRealm(group, groupUR);
// name
if (groupUR.getName() != null && StringUtils.isNotBlank(groupUR.getName().getValue())) {
group.setName(groupUR.getName().getValue());
}
// owner
PropagationByResource<String> ownerPropByRes = new PropagationByResource<>();
if (groupUR.getUserOwner() != null) {
if (groupUR.getUserOwner().getValue() == null) {
if (group.getUserOwner() != null) {
group.setUserOwner(null);
ownerPropByRes.addAll(ResourceOperation.UPDATE, groupDAO.findAllResourceKeys(group.getKey()));
}
} else {
User userOwner = userDAO.findById(groupUR.getUserOwner().getValue()).orElse(null);
if (userOwner == null) {
LOG.debug("Unable to find user owner for group {} by key {}",
group.getKey(), groupUR.getUserOwner().getValue());
group.setUserOwner(null);
} else {
group.setUserOwner(userOwner);
ownerPropByRes.addAll(ResourceOperation.UPDATE, groupDAO.findAllResourceKeys(group.getKey()));
}
}
}
if (groupUR.getGroupOwner() != null) {
if (groupUR.getGroupOwner().getValue() == null) {
if (group.getGroupOwner() != null) {
group.setGroupOwner(null);
ownerPropByRes.addAll(ResourceOperation.UPDATE, groupDAO.findAllResourceKeys(group.getKey()));
}
} else {
Group groupOwner = groupDAO.findById(groupUR.getGroupOwner().getValue()).orElse(null);
if (groupOwner == null) {
LOG.debug("Unable to find group owner for group {} by key {}",
group.getKey(), groupUR.getGroupOwner().getValue());
group.setGroupOwner(null);
} else {
group.setGroupOwner(groupOwner);
ownerPropByRes.addAll(ResourceOperation.UPDATE, groupDAO.findAllResourceKeys(group.getKey()));
}
}
}
// attributes and resources
fill(anyTO, group, groupUR, anyUtilsFactory.getInstance(AnyTypeKind.GROUP), scce);
group = groupDAO.save(group);
// dynamic membership
if (groupUR.getUDynMembershipCond() == null) {
if (group.getUDynMembership() != null) {
group.getUDynMembership().setGroup(null);
group.setUDynMembership(null);
groupDAO.clearUDynMembers(group);
}
} else {
setDynMembership(group, anyTypeDAO.getUser(), groupUR.getUDynMembershipCond());
}
for (Iterator<? extends ADynGroupMembership> itor = group.getADynMemberships().iterator(); itor.hasNext();) {
ADynGroupMembership memb = itor.next();
memb.setGroup(null);
itor.remove();
}
groupDAO.clearADynMembers(group);
for (Map.Entry<String, String> entry : groupUR.getADynMembershipConds().entrySet()) {
AnyType anyType = anyTypeDAO.findById(entry.getKey()).orElse(null);
if (anyType == null) {
LOG.warn("Ignoring invalid {}: {}", AnyType.class.getSimpleName(), entry.getKey());
} else {
setDynMembership(group, anyType, entry.getValue());
}
}
group = groupDAO.saveAndRefreshDynMemberships(group);
// type extensions
for (TypeExtensionTO typeExtTO : groupUR.getTypeExtensions()) {
AnyType anyType = anyTypeDAO.findById(typeExtTO.getAnyType()).orElse(null);
if (anyType == null) {
LOG.warn("Ignoring invalid {}: {}", AnyType.class.getSimpleName(), typeExtTO.getAnyType());
} else {
TypeExtension typeExt = group.getTypeExtension(anyType).orElse(null);
if (typeExt == null) {
typeExt = entityFactory.newEntity(TypeExtension.class);
typeExt.setAnyType(anyType);
typeExt.setGroup(group);
group.add(typeExt);
}
// add all classes contained in the TO
for (String key : typeExtTO.getAuxClasses()) {
AnyTypeClass anyTypeClass = anyTypeClassDAO.findById(key).orElse(null);
if (anyTypeClass == null) {
LOG.warn("Ignoring invalid {}: {}", AnyTypeClass.class.getSimpleName(), key);
} else {
typeExt.add(anyTypeClass);
}
}
// remove all classes not contained in the TO
typeExt.getAuxClasses().
removeIf(anyTypeClass -> !typeExtTO.getAuxClasses().contains(anyTypeClass.getKey()));
// only consider non-empty type extensions
if (typeExt.getAuxClasses().isEmpty()) {
group.getTypeExtensions().remove(typeExt);
typeExt.setGroup(null);
}
}
}
// remove all type extensions not contained in the TO
group.getTypeExtensions().
removeIf(typeExt -> groupUR.getTypeExtension(typeExt.getAnyType().getKey()).isEmpty());
// relationships
Set<Pair<String, String>> relationships = new HashSet<>();
for (RelationshipUR patch : groupUR.getRelationships().stream().
filter(patch -> patch.getRelationshipTO() != null).toList()) {
RelationshipType relationshipType = relationshipTypeDAO.findById(patch.getRelationshipTO().getType()).
orElse(null);
if (relationshipType == null) {
LOG.debug("Ignoring invalid relationship type {}", patch.getRelationshipTO().getType());
} else {
GRelationship relationship = group.getRelationship(
relationshipType, patch.getRelationshipTO().getOtherEndKey()).orElse(null);
if (relationship != null) {
group.getRelationships().remove(relationship);
relationship.setLeftEnd(null);
}
if (patch.getOperation() == PatchOperation.ADD_REPLACE) {
AnyObject otherEnd = anyObjectDAO.findById(patch.getRelationshipTO().getOtherEndKey()).orElse(null);
if (otherEnd == null) {
LOG.debug("Ignoring invalid any object {}", patch.getRelationshipTO().getOtherEndKey());
} else if (relationships.contains(
Pair.of(otherEnd.getKey(), patch.getRelationshipTO().getType()))) {
SyncopeClientException assigned =
SyncopeClientException.build(ClientExceptionType.InvalidRelationship);
assigned.getElements().add("Group was already in relationship "
+ patch.getRelationshipTO().getType() + " with "
+ otherEnd.getType().getKey() + " " + otherEnd.getName());
scce.addException(assigned);
} else if (patch.getRelationshipTO().getEnd() == RelationshipTO.End.RIGHT) {
SyncopeClientException noRight =
SyncopeClientException.build(ClientExceptionType.InvalidRelationship);
noRight.getElements().add(
"Relationships shall be created or updated only from their left end");
scce.addException(noRight);
} else if (group.getRealm().getFullPath().startsWith(otherEnd.getRealm().getFullPath())) {
relationships.add(Pair.of(otherEnd.getKey(), patch.getRelationshipTO().getType()));
GRelationship newRelationship = entityFactory.newEntity(GRelationship.class);
newRelationship.setType(relationshipType);
newRelationship.setRightEnd(otherEnd);
newRelationship.setLeftEnd(group);
group.add(newRelationship);
} else {
LOG.error("{} cannot be related to {}", otherEnd, group);
SyncopeClientException unrelatable =
SyncopeClientException.build(ClientExceptionType.InvalidRelationship);
unrelatable.getElements().add(otherEnd.getType().getKey() + " " + otherEnd.getName()
+ " cannot be related");
scce.addException(unrelatable);
}
}
}
}
// Throw composite exception if there is at least one element set in the composing exceptions
if (scce.hasExceptions()) {
throw scce;
}
// Re-merge any pending change from above
group = groupDAO.save(group);
// Build final information for next stage (propagation)
PropagationByResource<String> propByRes = propByRes(
beforeOnResources, onResources(group, groupDAO.findAllResourceKeys(group.getKey()), null, Set.of()));
propByRes.merge(ownerPropByRes);
return propByRes;
}