From 85b28b3d0fc05bc49d350a98c07459f4bcb21f43 Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Mon, 05 Oct 2026 12:44:00 +0000
Subject: [PATCH] [#1173] Check the references of every managed attribute type of an add and every modification of a modify, not only the first (#1175)

---
 opendj-server-legacy/src/test/java/org/opends/server/plugins/ReferentialIntegrityPluginTestCase.java |   94 +++++++++++++++++++++++++++++++++++++++++++++++
 opendj-server-legacy/src/main/java/org/opends/server/plugins/ReferentialIntegrityPlugin.java         |    5 +-
 2 files changed, 97 insertions(+), 2 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/plugins/ReferentialIntegrityPlugin.java b/opendj-server-legacy/src/main/java/org/opends/server/plugins/ReferentialIntegrityPlugin.java
index ddf54f5..2030243 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/plugins/ReferentialIntegrityPlugin.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/plugins/ReferentialIntegrityPlugin.java
@@ -1104,7 +1104,8 @@
         }
         PluginResult.PreOperation result =
             isIntegrityMaintained(modifiedAttribute, entryDN, entryBaseDN);
-        if (result.getResultCode() != ResultCode.SUCCESS)
+        // A reference that passes yields continueOperationProcessing(), whose result code is null, not SUCCESS.
+        if (!result.continueProcessing())
         {
           return result;
         }
@@ -1138,7 +1139,7 @@
     {
       final List<Attribute> attrs = entry.getAllAttributes(attrType, false);
       PluginResult.PreOperation result = isIntegrityMaintained(attrs, entryDN, entryBaseDN);
-      if (result.getResultCode() != ResultCode.SUCCESS)
+      if (!result.continueProcessing())
       {
         return result;
       }
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/plugins/ReferentialIntegrityPluginTestCase.java b/opendj-server-legacy/src/test/java/org/opends/server/plugins/ReferentialIntegrityPluginTestCase.java
index be66040..31014df 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/plugins/ReferentialIntegrityPluginTestCase.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/plugins/ReferentialIntegrityPluginTestCase.java
@@ -2302,4 +2302,98 @@
     final ModifyOperation multiModOperation = connection.processModify(modifyRequest);
     assertEquals(multiModOperation.getResultCode(), ResultCode.CONSTRAINT_VIOLATION);
   }
+
+  /**
+   * Issue #1173: two managed attributes, the first of which holds a reference to a missing entry, with the other one
+   * holding a valid reference or none. Each attribute takes both places, so that one row puts the missing reference
+   * after the attribute type the plugin checks first, whichever that is.
+   */
+  @DataProvider
+  public Object[][] missingReferenceNextToAnother()
+  {
+    return new Object[][] {
+      { "manager", "seeAlso" },
+      { "seeAlso", "manager" },
+      { "manager", null },
+      { "seeAlso", null },
+    };
+  }
+
+  /**
+   * Issue #1173: an added entry is refused when any managed attribute type holds a reference to a missing entry, not
+   * only when the first one the plugin checks does.
+   */
+  @Test(dataProvider = "missingReferenceNextToAnother")
+  public void testEnforceIntegrityAddChecksEveryAttributeType(String missingRefAttr, String validRefAttr)
+      throws Exception
+  {
+    enableCheckReferences("manager", "seeAlso");
+
+    List<String> ldif = newArrayList(
+        "dn: uid=employee,ou=people,ou=dept,dc=example,dc=com",
+        "objectclass: top",
+        "objectclass: person",
+        "objectclass: organizationalperson",
+        "objectclass: inetorgperson",
+        "uid: employee",
+        "cn: employee",
+        "sn: employee",
+        missingRefAttr + ": uid=bad,ou=people,ou=dept,dc=example,dc=com");
+    if (validRefAttr != null)
+    {
+      ldif.add(validRefAttr + ": " + user1);
+    }
+
+    AddOperation addOperation = getRootConnection().processAdd(TestCaseUtils.makeEntry(ldif.toArray(new String[0])));
+    assertEquals(addOperation.getResultCode(), ResultCode.CONSTRAINT_VIOLATION);
+  }
+
+  /**
+   * Issue #1173: a modify request is refused when any of its modifications adds a reference to a missing entry, not
+   * only when its first modification of a managed attribute does.
+   */
+  @Test(dataProvider = "missingReferenceNextToAnother")
+  public void testEnforceIntegrityModifyChecksEveryModification(String missingRefAttr, String validRefAttr)
+      throws Exception
+  {
+    enableCheckReferences("manager", "seeAlso");
+    String employee = "uid=employee,ou=people,ou=dept,dc=example,dc=com";
+    TestCaseUtils.addEntry(
+        "dn: " + employee,
+        "objectclass: top",
+        "objectclass: person",
+        "objectclass: organizationalperson",
+        "objectclass: inetorgperson",
+        "uid: employee",
+        "cn: employee",
+        "sn: employee");
+
+    ModifyRequest modifyRequest = Requests.newModifyRequest(DN.valueOf(employee));
+    // Without a valid managed modification first, a modification of an attribute the plugin does not manage.
+    modifyRequest.addModification(REPLACE, validRefAttr != null ? validRefAttr : "description", user1);
+    modifyRequest.addModification(ADD, missingRefAttr, "uid=bad,ou=people,ou=dept,dc=example,dc=com");
+
+    ModifyOperation modOperation = getRootConnection().processModify(modifyRequest);
+    assertEquals(modOperation.getResultCode(), ResultCode.CONSTRAINT_VIOLATION);
+  }
+
+  /**
+   * Enables the plugin with {@code check-references} for the given attribute types below {@code dc=example,dc=com}.
+   */
+  private void enableCheckReferences(String... attributeTypes)
+  {
+    assertEquals(replaceAttrEntry(configDN, "ds-cfg-enabled", "false").getResultCode(), ResultCode.SUCCESS);
+    assertEquals(replaceAttrEntry(configDN, dsConfigPluginType,
+                               "postoperationdelete",
+                               "postoperationmodifydn",
+                               "subordinatemodifydn",
+                               "subordinatedelete",
+                               "preoperationadd",
+                               "preoperationmodify").getResultCode(), ResultCode.SUCCESS);
+    assertEquals(addAttrEntry(configDN, dsConfigBaseDN, "dc=example,dc=com").getResultCode(), ResultCode.SUCCESS);
+    assertEquals(replaceAttrEntry(configDN, dsConfigEnforceIntegrity, "true").getResultCode(), ResultCode.SUCCESS);
+    assertEquals(replaceAttrEntry(configDN, dsConfigAttrType, (Object[]) attributeTypes).getResultCode(),
+        ResultCode.SUCCESS);
+    assertEquals(replaceAttrEntry(configDN, "ds-cfg-enabled", "true").getResultCode(), ResultCode.SUCCESS);
+  }
 }

--
Gitblit v1.10.0