From 23e84fb215a8b9b156489efc330733e65de55538 Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Thu, 17 Oct 2024 12:25:34 +0000
Subject: [PATCH] [#425] Add option -Dorg.openidentityplatform.opendj.ERR_ENTRY_SCHEMA_VIOLATES_PARENT_DSR for force control "Entry is invalid according to the server schema because there is no DIT structure rule that applies to that entry, but there is a DIT structure rule for the parent entry". Default: warning level (#435)

---
 opendj-server-legacy/src/test/java/org/opends/server/extensions/Issue425TestCase.java       |  148 +++++++++++++++++++++++++++++++++++++++++++++++++
 opendj-server-legacy/src/main/java/org/opends/server/types/Entry.java                       |   15 ++--
 opendj-server-legacy/src/test/java/org/opends/server/types/EntrySchemaCheckingTestCase.java |    3 
 3 files changed, 158 insertions(+), 8 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/Entry.java b/opendj-server-legacy/src/main/java/org/opends/server/types/Entry.java
index 621792a..c8087de 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/types/Entry.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/types/Entry.java
@@ -2220,13 +2220,14 @@
                   if (!parentDSR.isObsolete())
                   {
                     LocalizableMessage message = ERR_ENTRY_SCHEMA_VIOLATES_PARENT_DSR.get(dn, parentEntry.getName());
-                    if (structuralPolicy == AcceptRejectWarn.REJECT)
-                    {
-                      invalidReason.append(message);
-                      return false;
-                    }
-                    else if (structuralPolicy == AcceptRejectWarn.WARN)
-                    {
+                    if (System.getProperty("org.openidentityplatform.opendj.ERR_ENTRY_SCHEMA_VIOLATES_PARENT_DSR")!=null) {
+                      if (structuralPolicy == AcceptRejectWarn.REJECT) {
+                        invalidReason.append(message);
+                        return false;
+                      } else if (structuralPolicy == AcceptRejectWarn.WARN) {
+                        logger.error(message);
+                      }
+                    }else{
                       logger.error(message);
                     }
                   }
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/extensions/Issue425TestCase.java b/opendj-server-legacy/src/test/java/org/opends/server/extensions/Issue425TestCase.java
new file mode 100644
index 0000000..8b1b17e
--- /dev/null
+++ b/opendj-server-legacy/src/test/java/org/opends/server/extensions/Issue425TestCase.java
@@ -0,0 +1,148 @@
+/*
+ * The contents of this file are subject to the terms of the Common Development and
+ * Distribution License (the License). You may not use this file except in compliance with the
+ * License.
+ *
+ * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
+ * specific language governing permission and limitations under the License.
+ *
+ * When distributing Covered Software, include this CDDL Header Notice in each file and include
+ * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
+ * Header, with the fields enclosed by brackets [] replaced by your own identifying
+ * information: "Portions Copyright [year] [name of copyright owner]".
+ *
+ * Copyright 2024 3A Systems, LLC.
+ */
+package org.opends.server.extensions;
+
+import org.opends.server.TestCaseUtils;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.*;
+
+/**
+ * A set of test cases for the governing structure rule virtual attribute
+ * provider.
+ */
+public class Issue425TestCase
+       extends ExtensionsTestCase
+{
+
+  /**
+   * Ensures that the Directory Server is running.
+   *
+   * @throws  Exception  If an unexpected problem occurs.
+   */
+  @BeforeClass
+  public void startServer()
+         throws Exception
+  {
+    TestCaseUtils.startServer();
+    TestCaseUtils.initializeTestBackend(true);
+    TestCaseUtils.clearBackend("userRoot", "dc=example,dc=com");
+
+    int resultCode = TestCaseUtils.applyModifications(true,
+    "dn: cn=schema",
+    "changetype: modify",
+    "add: nameForms",
+    "nameForms: ( 1.3.6.1.1.2.1\n" +
+            "          NAME 'domainNameForm'\n" +
+            "          OC domain\n" +
+            "          MUST dc\n" +
+            "          X-ORIGIN 'RFC2377' )",
+    "nameForms: ( 1.3.6.1.4.1.56521.999.2.7.2\n" +
+            "          NAME 'ouForm'\n" +
+            "          OC organizationalUnit\n" +
+            "          MUST ou\n" +
+            "          X-ORIGIN 'fake name form' )",
+    "-",
+    "add: ditStructureRules",
+    "dITStructureRules: ( 20\n" +
+            "          NAME 'rootSuffixStructure'\n" +
+            "          FORM domainNameForm )",
+    "dITStructureRules: ( 21\n" +
+            "          NAME 'ouStructure'\n" +
+            "          FORM ouForm\n" +
+            "          SUP 20 )"
+    );
+    assertEquals(resultCode, 0);
+  }
+
+    @Test
+    public void test()
+            throws Exception {
+      TestCaseUtils.addEntry(
+              "dn: ou=Accounts,dc=example,dc=com",
+              "objectClass: organizationalunit",
+              "objectClass: top",
+              "ou: People"
+      );
+      //add OC subentry without DSR (warning level)
+      TestCaseUtils.addEntry(
+              "dn: cn=test-subentry,ou=Accounts,dc=example,dc=com",
+              "objectClass: top",
+              "objectClass: extensibleObject",
+              "objectClass: subentry",
+              "objectClass: collectiveAttributeSubentry",
+              "subtreeSpecification: {}",
+              "cn: test-subentry"
+      );
+      //add OC subentry without DSR (warning level)
+      TestCaseUtils.addEntry(
+              "dn: o=test-subentry2,ou=Accounts,dc=example,dc=com",
+              "objectClass: top",
+              "objectClass: extensibleObject",
+              "objectClass: subentry",
+              "objectClass: collectiveAttributeSubentry",
+              "subtreeSpecification: {}",
+              "cn: test-subentry2"
+      );
+
+      int resultCode = TestCaseUtils.applyModifications(true,
+              "dn: cn=schema",
+              "changetype: modify",
+              "add: nameForms",
+              "nameForms: ( 2.5.15.16\n"+
+                      "          NAME 'subentryNameForm'\n"+
+                      "          DESC 'X.501, cl. 14.2.2: the Subentry name form'\n"+
+                      "          OC subentry\n"+
+                      "          MUST cn )",
+              "-",
+              "add: ditStructureRules",
+              "dITStructureRules: ( 177\n"+
+                      "          NAME 'subentryStructure'\n"+
+                      "          FORM subentryNameForm\n"+
+                      "          SUP ( 20 21 ) )"
+      );
+      assertEquals(resultCode, 0);
+
+      //add OC subentry with DSR: RDN OC subentry MUST cn
+      TestCaseUtils.addEntry(
+              "dn: cn=test-subentry-ok,ou=Accounts,dc=example,dc=com",
+              "objectClass: top",
+              "objectClass: extensibleObject",
+              "objectClass: subentry",
+              "objectClass: collectiveAttributeSubentry",
+              "subtreeSpecification: {}",
+              "cn: test-subentry-ok"
+      );
+
+      //add OC subentry with DSR violation: RDN OC subentry MUST cn
+      assertThrows(new ThrowingRunnable() {
+                     @Override
+                     public void run() throws Throwable {
+                       TestCaseUtils.addEntry(
+                               "dn: o=test-subentry-error,ou=Accounts,dc=example,dc=com",
+                               "objectClass: top",
+                               "objectClass: extensibleObject",
+                               "objectClass: subentry",
+                               "objectClass: collectiveAttributeSubentry",
+                               "subtreeSpecification: {}",
+                               "cn: test-subentry-error"
+                       );
+                     }
+                   }
+      );
+    }
+}
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/types/EntrySchemaCheckingTestCase.java b/opendj-server-legacy/src/test/java/org/opends/server/types/EntrySchemaCheckingTestCase.java
index 6231415..10ba991 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/types/EntrySchemaCheckingTestCase.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/types/EntrySchemaCheckingTestCase.java
@@ -13,6 +13,7 @@
  *
  * Copyright 2008 Sun Microsystems, Inc.
  * Portions Copyright 2014-2016 ForgeRock AS.
+ * Portions Copyright 2024 3A Systems, LLC
  */
 package org.opends.server.types;
 
@@ -1439,7 +1440,7 @@
          "cn: not below valid parent");
     failOnlyForStrictEvaluation(e);
 
-
+    System.setProperty("org.openidentityplatform.opendj.ERR_ENTRY_SCHEMA_VIOLATES_PARENT_DSR","yes");
     e = TestCaseUtils.makeEntry(
          "dn: cn=invalid entry below parent covered by DSR,ou=parent,o=test",
          "objectClass: top",

--
Gitblit v1.10.0