Skip to content

Commit

Permalink
[SCIM-34] better attribute delta management (#104)
Browse files Browse the repository at this point in the history
  • Loading branch information
andrea-patricelli authored Jan 9, 2025
1 parent 85f5723 commit fbc65fd
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,8 @@ protected abstract void fillGroupPatches(

protected abstract P buildGroupPatch(Set<AttributeDelta> modifications);

protected abstract PO buildPatchOperation(AttributeDelta currentDelta, SCIMBaseAttribute<?> attributeDefinition);
protected abstract List<PO> buildPatchOperations(
AttributeDelta currentDelta, SCIMBaseAttribute<?> attributeDefinition);

protected abstract List<PO> buildGroupPatchOperations(Set<AttributeDelta> modifications);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,10 @@ protected SCIMv11BasePatch buildGroupPatch(final Set<AttributeDelta> modificatio
}

@Override
protected SCIMPatchOperation buildPatchOperation(final AttributeDelta currentDelta,
protected List<SCIMPatchOperation> buildPatchOperations(
final AttributeDelta currentDelta,
final SCIMBaseAttribute<?> attributeDefinition) {

throw new ConnectorException("Update delta is not supported in version 1.1");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,15 +187,18 @@ protected SCIMv2Patch buildUserPatch(
} else if (!attrDelta.getName().contains(SCIMAttributeUtils.SCIM_USER_ADDRESSES)
&& !attrDelta.is(SCIMAttributeUtils.SCIM_USER_GROUPS)) {

patch.addOperation(buildPatchOperation(attrDelta, null));
patch.addOperations(buildPatchOperations(attrDelta, null));
}
}
// manage addresses patches
buildAddressesPatchOperations(modifications, currentUser).forEach(patch::addOperation);

// custom attributes
if (StringUtil.isNotBlank(configuration.getCustomAttributesJSON())) {
buildCustomAttributesPatchOperations(modifications).forEach(patch::addOperation);
buildCustomAttributesPatchOperations(
modifications,
configuration.getUseColonOnExtensionAttributes()).
forEach(patch::addOperation);
}
// manage groups
if (manageGroups) {
Expand All @@ -220,7 +223,7 @@ protected SCIMv2Patch buildGroupPatch(final Set<AttributeDelta> modifications) {
.value(attrDelta.getValuesToReplace().get(0))
.build());
} else if (!attrDelta.getName().contains(SCIMAttributeUtils.SCIM_GROUP_MEMBERS)) {
patch.addOperation(buildPatchOperation(attrDelta, null));
patch.addOperations(buildPatchOperations(attrDelta, null));
}
}

Expand Down Expand Up @@ -280,51 +283,64 @@ protected SCIMv2Patch buildGroupPatch(final Set<AttributeDelta> modifications) {
return patch;
}

protected List<SCIMv2PatchOperation> buildCustomAttributesPatchOperations(final Set<AttributeDelta> modifications) {
protected List<SCIMv2PatchOperation> buildCustomAttributesPatchOperations(
final Set<AttributeDelta> modifications,
final boolean useColon) {

List<SCIMv2PatchOperation> operations = new ArrayList<>();
SCIMUtils.extractSCIMSchemas(configuration.getCustomAttributesJSON(), SCIMv2Attribute.class).ifPresent(
scimSchema -> {
for (SCIMv2Attribute customAttribute : scimSchema.getAttributes()) {
String extAttrName = SCIMv2Attribute.class.cast(customAttribute).getExtensionSchema().
concat(".").concat(customAttribute.getName());
concat(useColon ? ":" : ".").concat(customAttribute.getName());
// only single valued attributes are supported
modifications.stream().filter(mod -> mod.getName().equals(extAttrName))
.findFirst().ifPresent(ad -> buildPatchOperation(ad, customAttribute));
modifications.stream().filter(mod -> mod.getName().equals(extAttrName)).findFirst()
.ifPresent(ad -> operations.addAll(buildPatchOperations(ad, customAttribute)));
}
});
return operations;
}

@Override
protected SCIMv2PatchOperation buildPatchOperation(
protected List<SCIMv2PatchOperation> buildPatchOperations(
final AttributeDelta currentDelta,
final SCIMBaseAttribute<?> attributeDefinition) {

SCIMv2PatchOperation patchOperation = new SCIMv2PatchOperation();
patchOperation.setPath(SCIMAttributeUtils.getBaseAttributeName(currentDelta.getName()));
List<SCIMv2PatchOperation> operations = new ArrayList<>();

if (CollectionUtil.isEmpty(currentDelta.getValuesToReplace())) {
if (!CollectionUtil.isEmpty(currentDelta.getValuesToAdd())) {
patchOperation.setOp(SCIMAttributeUtils.SCIM_ADD);
patchOperation.setValue(
SCIMv2PatchOperation addPatchOperation = new SCIMv2PatchOperation();
addPatchOperation.setPath(SCIMAttributeUtils.getBaseAttributeName(currentDelta.getName()));
addPatchOperation.setOp(SCIMAttributeUtils.SCIM_ADD);
addPatchOperation.setValue(
buildPatchValue(currentDelta.getName(), currentDelta.getValuesToAdd(), attributeDefinition));
operations.add(addPatchOperation);
}
if (CollectionUtil.isEmpty(currentDelta.getValuesToAdd())
&& !CollectionUtil.isEmpty(currentDelta.getValuesToRemove())) {
patchOperation.setOp(SCIMAttributeUtils.SCIM_REMOVE);
// also add values to remove in a new operation, if any
if (!CollectionUtil.isEmpty(currentDelta.getValuesToRemove())) {
SCIMv2PatchOperation removePatchOperation = new SCIMv2PatchOperation();
removePatchOperation.setOp(SCIMAttributeUtils.SCIM_REMOVE);
// while removing specific attribute values we must use a filter like emails[value eq \"user
// [email protected]\"], if multiple values are present must filter in OR like
// emails[value eq \"[email protected]\" or value eq \"[email protected]\"]
patchOperation.setPath(
buildFilteredPath(currentDelta.getName(), currentDelta.getValuesToRemove(), "or", "eq"));
patchOperation.setValue(
removePatchOperation.setPath(
buildFilteredPath(SCIMAttributeUtils.getBaseAttributeName(currentDelta.getName()),
currentDelta.getValuesToRemove(), "or", "eq"));
removePatchOperation.setValue(
buildPatchValue(currentDelta.getName(), currentDelta.getValuesToRemove(), attributeDefinition));
operations.add(removePatchOperation);
}
} else {
patchOperation.setOperation(SCIMAttributeUtils.SCIM_REPLACE);
patchOperation.setValue(
SCIMv2PatchOperation replacePatchOperation = new SCIMv2PatchOperation();
replacePatchOperation.setPath(SCIMAttributeUtils.getBaseAttributeName(currentDelta.getName()));
replacePatchOperation.setOperation(SCIMAttributeUtils.SCIM_REPLACE);
replacePatchOperation.setValue(
buildPatchValue(currentDelta.getName(), currentDelta.getValuesToReplace(), attributeDefinition));
operations.add(replacePatchOperation);
}
return patchOperation;

return operations;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package net.tirasa.connid.bundles.scim.v2.dto;

import java.util.List;
import java.util.Set;
import net.tirasa.connid.bundles.scim.common.dto.SCIMBasePatch;

Expand All @@ -23,5 +24,7 @@ public interface SCIMv2Patch extends SCIMBasePatch {
Set<SCIMv2PatchOperation> getOperations();

void addOperation(SCIMv2PatchOperation operation);

void addOperations(List<SCIMv2PatchOperation> operations);

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

Expand Down Expand Up @@ -70,6 +71,11 @@ public void addOperation(final SCIMv2PatchOperation operation) {
this.operations.add(operation);
}

@Override
public void addOperations(final List<SCIMv2PatchOperation> operations) {
this.operations.addAll(operations);
}

@Override
public String toString() {
return "SCIMv2Patch{"
Expand Down

0 comments on commit fbc65fd

Please sign in to comment.