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

Valery Kharseko
yesterday ba2b247fb296f883e9efcd46308a64dfd6cca0a4
[#737] Fix cn=changelog search failing when aliases are dereferenced (#740)
2 files modified
94 ■■■■■ changed files
opendj-server-legacy/src/main/java/org/opends/server/backends/ChangelogBackend.java 14 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/test/java/org/opends/server/backends/ChangelogBackendTestCase.java 80 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/backends/ChangelogBackend.java
@@ -297,6 +297,14 @@
    return true;
  }
  /**
   * {@inheritDoc}
   * <p>
   * Only the base changelog entry can be retrieved by DN. Change records are streamed by
   * {@link #search(SearchOperation)}, which needs the search filter and the change number range to
   * position its cursors, so they cannot be looked up individually and {@code null} is returned for
   * them. None of them is ever an alias, so callers dereferencing aliases get the answer they need.
   */
  @Override
  public Entry getEntry(final DN entryDN) throws DirectoryException
  {
@@ -305,7 +313,11 @@
      throw new DirectoryException(DirectoryServer.getCoreConfigManager().getServerErrorResultCode(),
          ERR_BACKEND_GET_ENTRY_NULL.get(getBackendID()));
    }
    throw new RuntimeException("Not implemented");
    if (CHANGELOG_BASE_DN.equals(entryDN))
    {
      return buildBaseChangelogEntry();
    }
    return null;
  }
  @Override
opendj-server-legacy/src/test/java/org/opends/server/backends/ChangelogBackendTestCase.java
@@ -12,6 +12,7 @@
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2014-2016 ForgeRock AS.
 * Portions Copyright 2026 3A Systems, LLC.
 */
package org.opends.server.backends;
@@ -47,6 +48,7 @@
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.DereferenceAliasesPolicy;
import org.forgerock.opendj.ldap.RDN;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.SearchScope;
@@ -783,6 +785,84 @@
    debugInfo(testName, "Ending test successfully");
  }
  /**
   * The alias dereferencing policies which make the server look the search base entry up before
   * handing the search over to the backend.
   */
  @DataProvider
  Object[][] getBaseEntryLookupDerefPolicies()
  {
    return new Object[][] {
      { DereferenceAliasesPolicy.ALWAYS },
      { DereferenceAliasesPolicy.FINDING_BASE },
      // only looks the base entry up for subtree searches, which newSearchRequest() uses
      { DereferenceAliasesPolicy.IN_SEARCHING },
    };
  }
  /**
   * Dereferencing aliases makes the server read the base entry before searching, so the changelog
   * backend must be able to return it rather than failing the whole search.
   *
   * @see <a href="https://github.com/OpenIdentityPlatform/OpenDJ/issues/737">issue #737</a>
   */
  @Test(dataProvider = "getBaseEntryLookupDerefPolicies")
  public void searchWhenNoChangesShouldReturnRootEntryOnlyWhenDereferencingAliases(
      DereferenceAliasesPolicy derefPolicy) throws Exception
  {
    String testName = "EmptyRSDeref/" + derefPolicy;
    debugInfo(testName, "Starting test\n\n");
    SearchRequest request = newSearchRequest("(objectclass=*)").setDereferenceAliasesPolicy(derefPolicy);
    searchChangelog(request, 1, SUCCESS, testName);
    debugInfo(testName, "Ending test successfully");
  }
  /**
   * Dereferencing aliases used to fail change number searches with an unexpected error, which broke
   * every client defaulting to it, JNDI-based ones in particular.
   *
   * @see <a href="https://github.com/OpenIdentityPlatform/OpenDJ/issues/737">issue #737</a>
   */
  @Test(dataProvider = "getBaseEntryLookupDerefPolicies")
  public void searchInChangeNumberModeWhenDereferencingAliases(DereferenceAliasesPolicy derefPolicy) throws Exception
  {
    String testName = "ChangeNumberDeref/" + derefPolicy;
    debugInfo(testName, "Starting test\n\n");
    CSN[] csns = generateAndPublishUpdateMsgForEachOperationType(testName, false);
    SearchRequest request = newSearchRequest("(changenumber>=1)").setDereferenceAliasesPolicy(derefPolicy);
    InternalSearchOperation searchOp = searchChangelog(request, csns.length, SUCCESS, testName);
    assertEntriesForEachOperationType(searchOp.getSearchEntries(), 1, testName, USER1_ENTRY_UUID, csns);
    debugInfo(testName, "Ending test successfully");
  }
  /**
   * The base changelog entry is the only one the backend can return by DN: change records need the
   * search parameters to be located, so they are only reachable through a search.
   */
  @Test
  public void getEntryShouldReturnBaseEntryOnly() throws Exception
  {
    String testName = "getEntry";
    debugInfo(testName, "Starting test\n\n");
    generateAndPublishUpdateMsgForEachOperationType(testName, false);
    final LocalBackend<?> backend = TestCaseUtils.getServerContext().getBackendConfigManager()
        .getLocalBackendById(ChangelogBackend.BACKEND_ID);
    assertEquals(backend.getEntry(ChangelogBackend.CHANGELOG_BASE_DN).getName(),
        ChangelogBackend.CHANGELOG_BASE_DN);
    assertNull(backend.getEntry(DN.valueOf("changeNumber=1,cn=changelog")));
    assertNull(backend.getEntry(DN.valueOf("changeNumber=1000,cn=changelog")));
    debugInfo(testName, "Ending test successfully");
  }
  @Test
  public void operationalAndVirtualAttributesShouldNotBeVisibleOutsideRootDSE() throws Exception
  {