mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Copilot
2 days ago 6a96c259696ed3934de4aa7c139a7e9e3aa839b1
opendj-server-legacy/src/main/java/org/opends/server/plugins/ReferentialIntegrityPlugin.java
@@ -14,6 +14,7 @@
 * Copyright 2008-2010 Sun Microsystems, Inc.
 * Portions Copyright 2011-2016 ForgeRock AS.
 * Portions copyright 2011 profiq s.r.o.
 * Portions copyright 2026 3A Systems, LLC.
 */
package org.opends.server.plugins;
@@ -991,10 +992,9 @@
    }
    final List<Modification> mods = modifyOperation.getModifications();
    final Entry entry = modifyOperation.getModifiedEntry();
    /* Make sure the entry belongs to one of the configured naming contexts. */
    DN entryDN = entry.getName();
    DN entryDN = modifyOperation.getEntryDN();
    DN entryBaseDN = getEntryBaseDN(entryDN);
    if (entryBaseDN == null)
    {
@@ -1009,14 +1009,35 @@
      if (modType != ModificationType.ADD
          && modType != ModificationType.REPLACE)
      {
        break;
        continue;
      }
      Attribute modifiedAttribute = entry.getAttribute(mod.getAttribute().getAttributeDescription());
      if (modifiedAttribute != null)
      Attribute modifiedAttribute = mod.getAttribute();
      if (modifiedAttribute != null && !modifiedAttribute.isEmpty())
      {
        // Only enforce referential integrity on attributes that this plugin is configured to manage.
        final AttributeType modifiedAttrType = modifiedAttribute.getAttributeDescription().getAttributeType();
        boolean isManagedAttributeType = false;
        if (modifiedAttrType != null && attributeTypes != null)
        {
          for (AttributeType configuredType : attributeTypes)
          {
            if (modifiedAttrType.equals(configuredType)
                || modifiedAttrType.isSubTypeOf(configuredType))
            {
              isManagedAttributeType = true;
              break;
            }
          }
        }
        if (!isManagedAttributeType)
        {
          // Skip integrity checks for attributes not configured for this plugin.
          continue;
        }
        PluginResult.PreOperation result =
        isIntegrityMaintained(modifiedAttribute, entryDN, entryBaseDN);
            isIntegrityMaintained(modifiedAttribute, entryDN, entryBaseDN);
        if (result.getResultCode() != ResultCode.SUCCESS)
        {
          return result;
opendj-server-legacy/src/test/java/org/opends/server/plugins/ReferentialIntegrityPluginTestCase.java
@@ -14,6 +14,7 @@
 * Copyright 2008-2010 Sun Microsystems, Inc.
 * Portions copyright 2011 profiq s.r.o.
 * Portions Copyright 2014-2016 ForgeRock AS.
 * Portions copyright 2026 3A Systems, LLC.
 */
package org.opends.server.plugins;
@@ -1829,4 +1830,60 @@
      "member", "uid=user.1,ou=people,ou=dept,o=test");
    assertEquals(modOperation.getResultCode(), ResultCode.SUCCESS);
  }
  @Test
  public void testEnforceIntegrityModifyGroupAddMissingUniqueMember() throws Exception
  {
    replaceAttrEntry(configDN, "ds-cfg-enabled", "false");
    replaceAttrEntry(configDN, dsConfigPluginType,
                               "postoperationdelete",
                               "postoperationmodifydn",
                               "subordinatemodifydn",
                               "subordinatedelete",
                               "preoperationadd",
                               "preoperationmodify");
    addAttrEntry(configDN, dsConfigBaseDN, "dc=example,dc=com");
    replaceAttrEntry(configDN, dsConfigEnforceIntegrity, "true");
    replaceAttrEntry(configDN, dsConfigAttrType, "uniquemember");
    addAttrEntry(configDN, dsConfigAttrFiltMapping,
                           "uniquemember:(objectclass=person)");
    replaceAttrEntry(configDN, "ds-cfg-enabled", "true");
    ModifyOperation modOperation = addAttrEntry(DN.valueOf(ugroup),
      "uniquemember", "uid=user.100,ou=people,ou=dept,dc=example,dc=com");
    assertEquals(modOperation.getResultCode(), ResultCode.CONSTRAINT_VIOLATION);
  }
  @Test
  public void testEnforceIntegrityModifyGroupAddMissingUniqueMemberWithPriorDelete() throws Exception
  {
    // Configure the plugin in the same way as for the single-ADD test.
    replaceAttrEntry(configDN, "ds-cfg-enabled", "false");
    replaceAttrEntry(configDN, dsConfigPluginType,
                               "postoperationdelete",
                               "postoperationmodifydn",
                               "subordinatemodifydn",
                               "subordinatedelete",
                               "preoperationadd",
                               "preoperationmodify");
    addAttrEntry(configDN, dsConfigBaseDN, "dc=example,dc=com");
    replaceAttrEntry(configDN, dsConfigEnforceIntegrity, "true");
    replaceAttrEntry(configDN, dsConfigAttrType, "uniquemember");
    addAttrEntry(configDN, dsConfigAttrFiltMapping,
                           "uniquemember:(objectclass=person)");
    replaceAttrEntry(configDN, "ds-cfg-enabled", "true");
    // Ensure 'description' exists on ugroup so the DELETE modification succeeds.
    addAttrEntry(DN.valueOf(ugroup), "description", "test description");
    // Build a modify request with a non-ADD/REPLACE modification first,
    // followed by an ADD of a uniquemember referencing a missing DN.
    final ModifyRequest modifyRequest = Requests.newModifyRequest(DN.valueOf(ugroup));
    modifyRequest.addModification(DELETE, "description");
    modifyRequest.addModification(ADD, "uniquemember",
        "uid=user.100,ou=people,ou=dept,dc=example,dc=com");
    final InternalClientConnection connection = getRootConnection();
    final ModifyOperation multiModOperation = connection.processModify(modifyRequest);
    assertEquals(multiModOperation.getResultCode(), ResultCode.CONSTRAINT_VIOLATION);
  }
}