Skip to content

Commit

Permalink
roleMembershipRef value metadata merging/recomputation fixes
Browse files Browse the repository at this point in the history
Now the metadata changes manifest properly when the effective assignment
paths are changed.
If the path is not changed, the value metadata for it is not changed,
that is the storage/createTimestamp stays the same (what we want).
  • Loading branch information
virgo47 committed Feb 9, 2023
1 parent 88d3c19 commit aef9b5b
Show file tree
Hide file tree
Showing 2 changed files with 216 additions and 150 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import com.evolveum.midpoint.model.impl.util.ModelImplUtils;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.delta.*;
import com.evolveum.midpoint.prism.equivalence.EquivalenceStrategy;
import com.evolveum.midpoint.prism.path.ItemName;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.path.PathKeyedMap;
Expand Down Expand Up @@ -1015,8 +1016,6 @@ <F extends ObjectType> void processMembershipAndDelegatedRefs(
setReferences(focusContext, AssignmentHolderType.F_ROLE_MEMBERSHIP_REF, shouldBeRoleRefs);
setReferences(focusContext, AssignmentHolderType.F_DELEGATED_REF, shouldBeDelegatedRefs);
setReferences(focusContext, AssignmentHolderType.F_ARCHETYPE_REF, shouldBeArchetypeRefs);

context.recompute(); // really needed?
}

private void addRoleReferences(Collection<PrismReferenceValue> shouldBeRoleRefs,
Expand All @@ -1030,6 +1029,8 @@ private void addRoleReferences(Collection<PrismReferenceValue> shouldBeRoleRefs,
}
RoleManagementConfigurationType roleManagement = sysconfig.getRoleManagement();
if (roleManagement == null || !Boolean.TRUE.equals(roleManagement.isAccessesMetadataEnabled())) {
// TODO enable by default after fixing failing model tests
// if (roleManagement != null && Boolean.FALSE.equals(roleManagement.isAccessesMetadataEnabled())) {
return; // not enabled
}

Expand Down Expand Up @@ -1100,14 +1101,15 @@ private <F extends ObjectType> void setReferences(LensFocusContext<F> focusConte
return;
}
} else {
// we don't use QNameUtil.match here, because we want to ensure we store qualified values there
List<PrismReferenceValue> existingValues = existingState.getValues();
adoptExistingStorageCreateTimestampValueMetadata(targetState, existingValues);
// We don't use QNameUtil.match here, because we want to ensure we store qualified values there
// (and newValues are all qualified)
EqualsChecker<PrismReferenceValue> comparator =
(a, b) -> Objects.equals(a.getOid(), b.getOid())
&& Objects.equals(a.getRelation(), b.getRelation()
// TODO metadata equals
);
if (MiscUtil.unorderedCollectionEquals(targetState, existingState.getValues(), comparator)) {
&& Objects.equals(a.getRelation(), b.getRelation())
&& a.getValueMetadata().equals(b.getValueMetadata(), EquivalenceStrategy.REAL_VALUE);
if (MiscUtil.unorderedCollectionEquals(targetState, existingValues, comparator)) {
return;
}
}
Expand All @@ -1120,6 +1122,52 @@ private <F extends ObjectType> void setReferences(LensFocusContext<F> focusConte
focusContext.swallowToSecondaryDelta(itemDelta);
}

/** If we find the same assignment path value metadata, we want to preserve original creation date. */
private void adoptExistingStorageCreateTimestampValueMetadata(
Collection<PrismReferenceValue> targetState, List<PrismReferenceValue> existingValues) {
for (PrismReferenceValue ref : targetState) {
PrismReferenceValue oldRefMatch = MiscUtil.find(existingValues, ref,
(a, b) -> Objects.equals(a.getOid(), b.getOid())
&& Objects.equals(a.getRelation(), b.getRelation()));
if (oldRefMatch != null) {
mergeAssignmentPathMetadata(ref, oldRefMatch);
}
}
}

private void mergeAssignmentPathMetadata(PrismReferenceValue ref, PrismReferenceValue originalRef) {
List<PrismContainerValue<Containerable>> originalMetadataValues = originalRef.getValueMetadata().getValues();
if (originalMetadataValues.isEmpty()) {
return;
}

for (PrismContainerValue<Containerable> metadataValue : ref.getValueMetadata().getValues()) {
ValueMetadataType metadata = Objects.requireNonNull(metadataValue.getRealValue());
ProvenanceMetadataType provenance = metadata.getProvenance();
if (provenance == null) {
continue; // not assignment path metadata, we leave it as is
}

PrismContainerValue<Containerable> originalMetadataValue = originalMetadataValues.stream()
.filter(m -> provenance.equals(((ValueMetadataType) m.asContainerable()).getProvenance()))
.findFirst()
.orElse(null);
if (originalMetadataValue == null) {
continue; // no action needed
}
StorageMetadataType originalStorage = Objects.requireNonNull(
(ValueMetadataType) (originalMetadataValue.getRealValue()))
.getStorage();
if (originalStorage == null || originalStorage.getCreateTimestamp() == null) {
continue; // strange, but nothing to do about it
}

// This preserves the original assignment path creation time.
// Otherwise, each recompute would bump the time which is not what we want to show.
metadata.getStorage().setCreateTimestamp(originalStorage.getCreateTimestamp());
}
}

private void addReferences(Collection<PrismReferenceValue> extractedReferences, Collection<PrismReferenceValue> references) {
for (PrismReferenceValue reference : references) {
boolean found = false;
Expand Down

0 comments on commit aef9b5b

Please sign in to comment.