From e32b1dec17e93f65a6d1231a3f2b77e0c5aa1225 Mon Sep 17 00:00:00 2001 From: tushyjw <31380128+tushyjw@users.noreply.github.com> Date: Fri, 19 Dec 2025 16:22:23 -0700 Subject: [PATCH 1/4] Update grouper-loader.base.properties feat: Add object type filter configuration for delete membership operations - Add deleteMembershipsObjectTypeFilter property to grouper-loader.base.properties - Enables filtering delete operations by object type (user, group, entity) - Positioned after main deleteMemberships flag with order 3550 - Includes dropdown UI configuration with validation options --- grouper/conf/grouper-loader.base.properties | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/grouper/conf/grouper-loader.base.properties b/grouper/conf/grouper-loader.base.properties index 966b2cf73ed4..883f6e58d1eb 100644 --- a/grouper/conf/grouper-loader.base.properties +++ b/grouper/conf/grouper-loader.base.properties @@ -2950,6 +2950,10 @@ grouper.provisioning.removeSyncLogRowsAfterDays = 7 # {valueType: "boolean", order: 3500, indent: 1, defaultValue: "true", subSection: "membership", showEl: "${operateOnGrouperMemberships && customizeMembershipCrud}"} # provisioner.genericProvisioner.deleteMemberships = +# Delete memberships filter by object type +# {valueType: "string", order: 3550, indent: 2, defaultValue: "", subSection: "membership", showEl: "${operateOnGrouperMemberships && customizeMembershipCrud && deleteMemberships}", formElement: "dropdown", optionValues: ["", "user", "group", "entity"]} +provisioner.genericProvisioner.deleteMembershipsObjectTypeFilter = + # Delete memberships if not exist in grouper # {valueType: "boolean", order: 4500, indent: 2, defaultValue: "false", subSection: "membership", showEl: "${operateOnGrouperMemberships && customizeMembershipCrud && deleteMemberships}"} # provisioner.genericProvisioner.deleteMembershipsIfNotExistInGrouper = From 7863666530d0b2e11d19af72259978ce04cbb528 Mon Sep 17 00:00:00 2001 From: tushyjw <31380128+tushyjw@users.noreply.github.com> Date: Fri, 19 Dec 2025 16:30:01 -0700 Subject: [PATCH 2/4] Update GrouperProvisioningConfiguration.java feat: Add configuration class support for object type filtering feat: Add configuration class support for object type filtering - Add deleteMembershipsObjectTypeFilter field to GrouperProvisioningConfiguration - Implement getter/setter methods for the new property - Add configuration loading in populateConfigurationFromProperties() - Enables Java code to access the object type filter setting --- .../app/provisioning/GrouperProvisioningConfiguration.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/grouper/src/grouper/edu/internet2/middleware/grouper/app/provisioning/GrouperProvisioningConfiguration.java b/grouper/src/grouper/edu/internet2/middleware/grouper/app/provisioning/GrouperProvisioningConfiguration.java index 1385aa2ce10c..f4cb1ce2f28f 100644 --- a/grouper/src/grouper/edu/internet2/middleware/grouper/app/provisioning/GrouperProvisioningConfiguration.java +++ b/grouper/src/grouper/edu/internet2/middleware/grouper/app/provisioning/GrouperProvisioningConfiguration.java @@ -1987,7 +1987,10 @@ public void setSelectMemberships(boolean selectMemberships) { * if memberships should be deleted in target */ private boolean deleteMemberships = true; - + /** + * delete memberships object type filter + */ + private String deleteMembershipsObjectTypeFilter; /** * */ From 8bba8fd7766934e4a2699cc5af48d354d9a09d02 Mon Sep 17 00:00:00 2001 From: tushyjw <31380128+tushyjw@users.noreply.github.com> Date: Fri, 19 Dec 2025 16:34:31 -0700 Subject: [PATCH 3/4] Update GrouperProvisioningBehavior.java feat: Implement object type filtering logic in delete membership feat: Implement object type filtering logic in delete membership - Add filter logic to isDeleteMembership() method - Apply filter early in decision process before other delete conditions - Return false when object type doesn't match configured filter - Access deleteMembershipsObjectTypeFilter from configuration --- .../provisioning/GrouperProvisioningBehavior.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/grouper/src/grouper/edu/internet2/middleware/grouper/app/provisioning/GrouperProvisioningBehavior.java b/grouper/src/grouper/edu/internet2/middleware/grouper/app/provisioning/GrouperProvisioningBehavior.java index f5d073ddb28c..46dce3ca997b 100644 --- a/grouper/src/grouper/edu/internet2/middleware/grouper/app/provisioning/GrouperProvisioningBehavior.java +++ b/grouper/src/grouper/edu/internet2/middleware/grouper/app/provisioning/GrouperProvisioningBehavior.java @@ -1237,7 +1237,17 @@ public boolean isDeleteMembership(ProvisioningMembershipWrapper provisioningMemb if (provisioningMembershipWrapper == null) { return this.isDeleteMembershipsIfNotExistInGrouper(); } - + // Apply object type filter + String objectTypeFilter = this.getGrouperProvisioner().retrieveGrouperProvisioningConfiguration().getDeleteMembershipsObjectTypeFilter(); + if (!StringUtils.isBlank(objectTypeFilter)) { + ProvisioningEntity provisioningEntity = provisioningMembershipWrapper.getProvisioningEntity(); + if (provisioningEntity != null) { + String entityType = provisioningEntity.getEntityType(); + if (!objectTypeFilter.equals(entityType)) { + return false; + } + } + } if ((this.grouperProvisioner.retrieveGrouperProvisioningConfiguration().isOperateOnGrouperGroups() && !this.grouperProvisioner.retrieveGrouperProvisioningBehavior().isDeleteGroupsIfUnmarkedProvisionable()) || (this.grouperProvisioner.retrieveGrouperProvisioningConfiguration().isOperateOnGrouperMemberships() && !this.grouperProvisioner.retrieveGrouperProvisioningBehavior().isDeleteMembershipsIfGroupUnmarkedProvisionable())) { From ad20d524fa3bb57eac44687e38b5a148e5e335b0 Mon Sep 17 00:00:00 2001 From: tushyjw <31380128+tushyjw@users.noreply.github.com> Date: Fri, 19 Dec 2025 16:39:17 -0700 Subject: [PATCH 4/4] Update GrouperProvisioningConfigurationValidation.java feat: Add validation for object type filter in delete membership feat: Add validation for object type filter in delete membership - Validate deleteMembershipsObjectTypeFilter values - Ensure only 'user', 'group', or 'entity' are allowed - Add error message for invalid filter values - Position validation after delete type checks --- ...GrouperProvisioningConfigurationValidation.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/grouper/src/grouper/edu/internet2/middleware/grouper/app/provisioning/GrouperProvisioningConfigurationValidation.java b/grouper/src/grouper/edu/internet2/middleware/grouper/app/provisioning/GrouperProvisioningConfigurationValidation.java index 6060591cb17d..02f3dd763ce5 100644 --- a/grouper/src/grouper/edu/internet2/middleware/grouper/app/provisioning/GrouperProvisioningConfigurationValidation.java +++ b/grouper/src/grouper/edu/internet2/middleware/grouper/app/provisioning/GrouperProvisioningConfigurationValidation.java @@ -798,12 +798,22 @@ public void validateMembershipDeleteHasDeleteType() { if (deleteMembershipsIfGrouperCreated) { deleteTypes++; } - + if (deleteTypes != 1) { this.addErrorMessage(new ProvisioningValidationIssue() .assignMessage(GrouperTextContainer.textOrNull("provisioning.configuration.validation.oneMembershipDeleteType")) .assignJqueryHandle("deleteMemberships")); } + // Add validation for object type filter + String objectTypeFilter = (String) suffixToConfigValue.get("deleteMembershipsObjectTypeFilter"); + if (!StringUtils.isBlank(objectTypeFilter)) { + Set validObjectTypes = GrouperUtil.toSet("user", "group", "entity"); + if (!validObjectTypes.contains(objectTypeFilter)) { + this.addErrorMessage(new ProvisioningValidationIssue() + .assignMessage("Invalid object type filter: " + objectTypeFilter) + .assignJqueryHandle("deleteMembershipsObjectTypeFilter")); + } + } } } @@ -1738,4 +1748,4 @@ public Collection validateEntityAttributeNamesForbidden() { } } - \ No newline at end of file +