From d77fbdbc376a2760ea1c4a064e1544d19798202a Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Fri, 13 Apr 2007 15:05:04 +0000
Subject: [PATCH] Add support for user-defined virtual attributes, in which the administrator may explicitly specify the values that should be used for a virtual attribute. This provides functionality similar to the Class of Service (CoS) facility in the Sun Java System Directory Server.
---
opends/resource/schema/02-config.ldif | 12
opends/src/admin/defn/org/opends/server/admin/std/UserDefinedVirtualAttributeConfiguration.xml | 38 ++
opends/src/server/org/opends/server/extensions/UserDefinedVirtualAttributeProvider.java | 195 +++++++++++
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/UserDefinedVirtualAttributeProviderTestCase.java | 743 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 985 insertions(+), 3 deletions(-)
diff --git a/opends/resource/schema/02-config.ldif b/opends/resource/schema/02-config.ldif
index 1bced74..9138149 100644
--- a/opends/resource/schema/02-config.ldif
+++ b/opends/resource/schema/02-config.ldif
@@ -1153,6 +1153,9 @@
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.343 NAME 'ds-target-group-dn'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE
X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.344
+ NAME 'ds-cfg-virtual-attribute-value' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+ X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
NAME 'ds-cfg-access-control-handler' SUP top STRUCTURAL
MUST ( cn $ ds-cfg-acl-handler-class $ ds-cfg-acl-handler-enabled )
@@ -1605,8 +1608,11 @@
MUST ( ds-task-rebuild-base-dn $ ds-task-rebuild-index )
MAY ( ds-task-rebuild-max-threads )
X-ORIGIN 'OpenDS Directory Server' )
-objectClasses: ( 1.3.6.1.4.1.26027.1.2.99
- NAME 'ds-virtual-static-group' SUP top AUXILIARY MUST ds-target-group-dn
+objectClasses: ( 1.3.6.1.4.1.26027.1.2.99 NAME 'ds-virtual-static-group'
+ SUP top AUXILIARY MUST ds-target-group-dn
X-ORIGIN 'OpenDS Directory Server' )
-
+objectClasses: ( 1.3.6.1.4.1.26027.1.2.100
+ NAME 'ds-cfg-user-defined-virtual-attribute' SUP ds-cfg-virtual-attribute
+ STRUCTURAL MUST ds-cfg-virtual-attribute-value
+ X-ORIGIN 'OpenDS Directory Server' )
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/UserDefinedVirtualAttributeConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/UserDefinedVirtualAttributeConfiguration.xml
new file mode 100644
index 0000000..91d6e32
--- /dev/null
+++ b/opends/src/admin/defn/org/opends/server/admin/std/UserDefinedVirtualAttributeConfiguration.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<adm:managed-object name="user-defined-virtual-attribute"
+plural-name="user-defined-virtual-attributes"
+package="org.opends.server.admin.std" extends="virtual-attribute"
+xmlns:adm="http://www.opends.org/admin"
+xmlns:ldap="http://www.opends.org/admin-ldap">
+ <adm:synopsis>
+ The
+ <adm:user-friendly-name />
+ is used to create virtual attributes with user-defined values in entries
+ that match the criteria set in the associated virtual attribute rule. This
+ provides functionality that is similar to Class of Service (CoS) in the Sun
+ Java System Directory Server.
+ </adm:synopsis>
+ <adm:profile name="ldap">
+ <ldap:object-class>
+ <ldap:oid>1.3.6.1.4.1.26027.1.2.100</ldap:oid>
+ <ldap:name>ds-cfg-user-defined-virtual-attribute</ldap:name>
+ <ldap:superior>ds-cfg-virtual-attribute</ldap:superior>
+ </ldap:object-class>
+ </adm:profile>
+ <adm:property name="value" mandatory="true" multi-valued="true">
+ <adm:synopsis>
+ Specifies the value (or set of values) that should be included in entries
+ matching the critieria in the associated virtual attribute rule.
+ </adm:synopsis>
+ <adm:syntax>
+ <adm:string />
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.344</ldap:oid>
+ <ldap:name>ds-cfg-virtual-attribute-value</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+</adm:managed-object>
+
diff --git a/opends/src/server/org/opends/server/extensions/UserDefinedVirtualAttributeProvider.java b/opends/src/server/org/opends/server/extensions/UserDefinedVirtualAttributeProvider.java
new file mode 100644
index 0000000..7ea6862
--- /dev/null
+++ b/opends/src/server/org/opends/server/extensions/UserDefinedVirtualAttributeProvider.java
@@ -0,0 +1,195 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.extensions;
+
+
+
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.std.server.UserDefinedVirtualAttributeCfg;
+import org.opends.server.api.VirtualAttributeProvider;
+import org.opends.server.config.ConfigException;
+import org.opends.server.core.SearchOperation;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.AttributeValue;
+import org.opends.server.types.ConfigChangeResult;
+import org.opends.server.types.Entry;
+import org.opends.server.types.InitializationException;
+import org.opends.server.types.ResultCode;
+import org.opends.server.types.VirtualAttributeRule;
+
+
+
+/**
+ * This class implements a virtual attribute provider that allows administrators
+ * to define their own values that will be inserted into any entry that matches
+ * the criteria defined in the virtual attribute rule. This can be used to
+ * provide functionality like Class of Service (CoS) in the Sun Java System
+ * Directory Server.
+ */
+public class UserDefinedVirtualAttributeProvider
+ extends VirtualAttributeProvider<UserDefinedVirtualAttributeCfg>
+ implements ConfigurationChangeListener<UserDefinedVirtualAttributeCfg>
+{
+ // The current configuration for this virtual attribute provider.
+ private UserDefinedVirtualAttributeCfg currentConfig;
+
+
+
+ /**
+ * Creates a new instance of this member virtual attribute provider.
+ */
+ public UserDefinedVirtualAttributeProvider()
+ {
+ super();
+
+ // All initialization should be performed in the
+ // initializeVirtualAttributeProvider method.
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public void initializeVirtualAttributeProvider(
+ UserDefinedVirtualAttributeCfg configuration)
+ throws ConfigException, InitializationException
+ {
+ this.currentConfig = configuration;
+ configuration.addUserDefinedChangeListener(this);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public void finalizeVirtualAttributeProvider()
+ {
+ currentConfig.removeUserDefinedChangeListener(this);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public boolean isMultiValued()
+ {
+ if (currentConfig == null)
+ {
+ return true;
+ }
+ else
+ {
+ return (currentConfig.getValue().size() > 1);
+ }
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public LinkedHashSet<AttributeValue> getValues(Entry entry,
+ VirtualAttributeRule rule)
+ {
+ AttributeType attributeType = rule.getAttributeType();
+ Set<String> userDefinedValues = currentConfig.getValue();
+
+ LinkedHashSet<AttributeValue> values =
+ new LinkedHashSet<AttributeValue>(userDefinedValues.size());
+ for (String valueString : userDefinedValues)
+ {
+ values.add(new AttributeValue(attributeType, valueString));
+ }
+
+ return values;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public boolean isSearchable(VirtualAttributeRule rule,
+ SearchOperation searchOperation)
+ {
+ // We will not allow searches based only on user-defined virtual attributes.
+ return false;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public void processSearch(VirtualAttributeRule rule,
+ SearchOperation searchOperation)
+ {
+ searchOperation.setResultCode(ResultCode.UNWILLING_TO_PERFORM);
+ return;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isConfigurationChangeAcceptable(
+ UserDefinedVirtualAttributeCfg configuration,
+ List<String> unacceptableReasons)
+ {
+ // The new configuration should always be acceptable.
+ return true;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConfigChangeResult applyConfigurationChange(
+ UserDefinedVirtualAttributeCfg configuration)
+ {
+ // Just accept the new configuration as-is.
+ currentConfig = configuration;
+
+ return new ConfigChangeResult(ResultCode.SUCCESS, false);
+ }
+}
+
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/UserDefinedVirtualAttributeProviderTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/UserDefinedVirtualAttributeProviderTestCase.java
new file mode 100644
index 0000000..8145c69
--- /dev/null
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/UserDefinedVirtualAttributeProviderTestCase.java
@@ -0,0 +1,743 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.extensions;
+
+
+
+import java.util.LinkedHashSet;
+import java.util.List;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import org.opends.server.TestCaseUtils;
+import org.opends.server.core.DeleteOperation;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.protocols.internal.InternalClientConnection;
+import org.opends.server.protocols.internal.InternalSearchOperation;
+import org.opends.server.tools.LDAPModify;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.AttributeValue;
+import org.opends.server.types.DereferencePolicy;
+import org.opends.server.types.DN;
+import org.opends.server.types.Entry;
+import org.opends.server.types.SearchFilter;
+import org.opends.server.types.SearchScope;
+import org.opends.server.types.ResultCode;
+import org.opends.server.types.VirtualAttributeRule;
+
+import static org.testng.Assert.*;
+
+
+
+/**
+ * A set of test cases for the user-defined virtual attribute provider.
+ */
+public class UserDefinedVirtualAttributeProviderTestCase
+ extends ExtensionsTestCase
+{
+ // The attribute type for the description attribute.
+ private AttributeType descriptionType;
+
+ // The attribute type for the ds-privilege-name attribute.
+ private AttributeType privNameType;
+
+ // The attribute type for the ds-pwp-password-policy-dn attribute.
+ private AttributeType pwPolicyDNType;
+
+
+
+ /**
+ * Ensures that the Directory Server is running.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @BeforeClass()
+ public void startServer()
+ throws Exception
+ {
+ TestCaseUtils.startServer();
+
+ descriptionType = DirectoryServer.getAttributeType("description", false);
+ assertNotNull(descriptionType);
+
+ pwPolicyDNType =
+ DirectoryServer.getAttributeType("ds-pwp-password-policy-dn", false);
+ assertNotNull(pwPolicyDNType);
+
+ privNameType = DirectoryServer.getAttributeType("ds-privilege-name", false);
+ assertNotNull(privNameType);
+ }
+
+
+
+ /**
+ * Tests the methods which are part of the virtual group API using a
+ * single-valued virtual attribute.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testRuleAPISingleValued()
+ throws Exception
+ {
+ String ruleDN = "cn=User-Defined Test,cn=Virtual Attributes,cn=config";
+ TestCaseUtils.addEntry(
+ "dn: " + ruleDN,
+ "objectClass: top",
+ "objectClass: ds-cfg-virtual-attribute",
+ "objectClass: ds-cfg-user-defined-virtual-attribute",
+ "cn: User-Defined Test",
+ "ds-cfg-virtual-attribute-class: org.opends.server.extensions." +
+ "UserDefinedVirtualAttributeProvider",
+ "ds-cfg-virtual-attribute-enabled: true",
+ "ds-cfg-virtual-attribute-type: description",
+ "ds-cfg-virtual-attribute-conflict-behavior: real-overrides-virtual",
+ "ds-cfg-virtual-attribute-value: single value");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ new InternalSearchOperation(conn, conn.nextOperationID(),
+ conn.nextMessageID(), null, DN.decode(ruleDN),
+ SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
+ SearchFilter.createFilterFromString("(objectClass=*)"), null,
+ null);
+
+ for (VirtualAttributeRule rule : DirectoryServer.getVirtualAttributes())
+ {
+ if (rule.getAttributeType().equals(descriptionType))
+ {
+ UserDefinedVirtualAttributeProvider provider =
+ (UserDefinedVirtualAttributeProvider) rule.getProvider();
+ assertFalse(provider.isMultiValued());
+ assertFalse(provider.isSearchable(rule, searchOperation));
+
+ provider.processSearch(rule, searchOperation);
+ assertEquals(searchOperation.getResultCode(),
+ ResultCode.UNWILLING_TO_PERFORM);
+ }
+ }
+
+ DeleteOperation deleteOperation = conn.processDelete(DN.decode(ruleDN));
+ assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
+ }
+
+
+
+ /**
+ * Tests the methods which are part of the virtual group API using a
+ * multi-valued virtual attribute.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testRuleAPIMultiValued()
+ throws Exception
+ {
+ String ruleDN = "cn=User-Defined Test,cn=Virtual Attributes,cn=config";
+ TestCaseUtils.addEntry(
+ "dn: " + ruleDN,
+ "objectClass: top",
+ "objectClass: ds-cfg-virtual-attribute",
+ "objectClass: ds-cfg-user-defined-virtual-attribute",
+ "cn: User-Defined Test",
+ "ds-cfg-virtual-attribute-class: org.opends.server.extensions." +
+ "UserDefinedVirtualAttributeProvider",
+ "ds-cfg-virtual-attribute-enabled: true",
+ "ds-cfg-virtual-attribute-type: description",
+ "ds-cfg-virtual-attribute-conflict-behavior: real-overrides-virtual",
+ "ds-cfg-virtual-attribute-value: first value",
+ "ds-cfg-virtual-attribute-value: second value");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ new InternalSearchOperation(conn, conn.nextOperationID(),
+ conn.nextMessageID(), null, DN.decode(ruleDN),
+ SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
+ SearchFilter.createFilterFromString("(objectClass=*)"), null,
+ null);
+
+ for (VirtualAttributeRule rule : DirectoryServer.getVirtualAttributes())
+ {
+ if (rule.getAttributeType().equals(descriptionType))
+ {
+ UserDefinedVirtualAttributeProvider provider =
+ (UserDefinedVirtualAttributeProvider) rule.getProvider();
+ assertTrue(provider.isMultiValued());
+ assertFalse(provider.isSearchable(rule, searchOperation));
+
+ provider.processSearch(rule, searchOperation);
+ assertEquals(searchOperation.getResultCode(),
+ ResultCode.UNWILLING_TO_PERFORM);
+ }
+ }
+
+ DeleteOperation deleteOperation = conn.processDelete(DN.decode(ruleDN));
+ assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
+ }
+
+
+
+ /**
+ * Tests the creation of a description virtual attribute when there is only a
+ * single virtual value and no real value.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testSingleDescriptionOnlyVirtual()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+
+ String ruleDN = "cn=User-Defined Test,cn=Virtual Attributes,cn=config";
+ String userDN = "uid=test.user,o=test";
+ String value = "This is the virtual value";
+
+ TestCaseUtils.addEntries(
+ "dn: " + ruleDN,
+ "objectClass: top",
+ "objectClass: ds-cfg-virtual-attribute",
+ "objectClass: ds-cfg-user-defined-virtual-attribute",
+ "cn: User-Defined Test",
+ "ds-cfg-virtual-attribute-class: org.opends.server.extensions." +
+ "UserDefinedVirtualAttributeProvider",
+ "ds-cfg-virtual-attribute-enabled: true",
+ "ds-cfg-virtual-attribute-type: description",
+ "ds-cfg-virtual-attribute-conflict-behavior: real-overrides-virtual",
+ "ds-cfg-virtual-attribute-value: " + value,
+ "",
+ "dn: " + userDN,
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: test");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ conn.processSearch(DN.decode(userDN), SearchScope.BASE_OBJECT,
+ SearchFilter.createFilterFromString("(objectClass=*)"));
+
+ List<Attribute> attrList =
+ searchOperation.getSearchEntries().get(0).getAttribute(
+ descriptionType);
+ assertNotNull(attrList);
+ assertEquals(attrList.size(), 1);
+
+ Attribute attr = attrList.get(0);
+ assertEquals(attr.getValues().size(), 1);
+ assertTrue(attr.hasValue(new AttributeValue(descriptionType, value)));
+
+ DeleteOperation deleteOperation = conn.processDelete(DN.decode(ruleDN));
+ assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
+ }
+
+
+
+ /**
+ * Tests the creation of a description virtual attribute when there are
+ * multiple virtual values and no real value.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testMultipleDescriptionsOnlyVirtual()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+
+ String ruleDN = "cn=User-Defined Test,cn=Virtual Attributes,cn=config";
+ String userDN = "uid=test.user,o=test";
+ String value1 = "This is the first virtual value";
+ String value2 = "This is the second virtual value";
+
+ TestCaseUtils.addEntries(
+ "dn: " + ruleDN,
+ "objectClass: top",
+ "objectClass: ds-cfg-virtual-attribute",
+ "objectClass: ds-cfg-user-defined-virtual-attribute",
+ "cn: User-Defined Test",
+ "ds-cfg-virtual-attribute-class: org.opends.server.extensions." +
+ "UserDefinedVirtualAttributeProvider",
+ "ds-cfg-virtual-attribute-enabled: true",
+ "ds-cfg-virtual-attribute-type: description",
+ "ds-cfg-virtual-attribute-conflict-behavior: real-overrides-virtual",
+ "ds-cfg-virtual-attribute-value: " + value1,
+ "ds-cfg-virtual-attribute-value: " + value2,
+ "",
+ "dn: " + userDN,
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: test");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ conn.processSearch(DN.decode(userDN), SearchScope.BASE_OBJECT,
+ SearchFilter.createFilterFromString("(objectClass=*)"));
+
+ List<Attribute> attrList =
+ searchOperation.getSearchEntries().get(0).getAttribute(
+ descriptionType);
+ assertNotNull(attrList);
+ assertEquals(attrList.size(), 1);
+
+ Attribute attr = attrList.get(0);
+ assertEquals(attr.getValues().size(), 2);
+ assertTrue(attr.hasValue(new AttributeValue(descriptionType, value1)));
+ assertTrue(attr.hasValue(new AttributeValue(descriptionType, value2)));
+
+ DeleteOperation deleteOperation = conn.processDelete(DN.decode(ruleDN));
+ assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
+ }
+
+
+
+ /**
+ * Tests the creation of a description virtual attribute when real values
+ * should override virtual values and the entry has a real value.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testSingleDescriptionRealOverridesVirtual()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+
+ String ruleDN = "cn=User-Defined Test,cn=Virtual Attributes,cn=config";
+ String userDN = "uid=test.user,o=test";
+ String virtualValue = "This is the virtual value";
+ String realValue = "This is the real value";
+
+ TestCaseUtils.addEntries(
+ "dn: " + ruleDN,
+ "objectClass: top",
+ "objectClass: ds-cfg-virtual-attribute",
+ "objectClass: ds-cfg-user-defined-virtual-attribute",
+ "cn: User-Defined Test",
+ "ds-cfg-virtual-attribute-class: org.opends.server.extensions." +
+ "UserDefinedVirtualAttributeProvider",
+ "ds-cfg-virtual-attribute-enabled: true",
+ "ds-cfg-virtual-attribute-type: description",
+ "ds-cfg-virtual-attribute-conflict-behavior: real-overrides-virtual",
+ "ds-cfg-virtual-attribute-value: " + virtualValue,
+ "",
+ "dn: " + userDN,
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: test",
+ "description: " + realValue);
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ conn.processSearch(DN.decode(userDN), SearchScope.BASE_OBJECT,
+ SearchFilter.createFilterFromString("(objectClass=*)"));
+
+ List<Attribute> attrList =
+ searchOperation.getSearchEntries().get(0).getAttribute(
+ descriptionType);
+ assertNotNull(attrList);
+ assertEquals(attrList.size(), 1);
+
+ Attribute attr = attrList.get(0);
+ assertEquals(attr.getValues().size(), 1);
+ assertTrue(attr.hasValue(new AttributeValue(descriptionType, realValue)));
+
+ DeleteOperation deleteOperation = conn.processDelete(DN.decode(ruleDN));
+ assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
+ }
+
+
+
+ /**
+ * Tests the creation of a description virtual attribute when virtual values
+ * should override real values and the entry has a real value.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testSingleDescriptionVirtualOverridesReal()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+
+ String ruleDN = "cn=User-Defined Test,cn=Virtual Attributes,cn=config";
+ String userDN = "uid=test.user,o=test";
+ String virtualValue = "This is the virtual value";
+ String realValue = "This is the real value";
+
+ TestCaseUtils.addEntries(
+ "dn: " + ruleDN,
+ "objectClass: top",
+ "objectClass: ds-cfg-virtual-attribute",
+ "objectClass: ds-cfg-user-defined-virtual-attribute",
+ "cn: User-Defined Test",
+ "ds-cfg-virtual-attribute-class: org.opends.server.extensions." +
+ "UserDefinedVirtualAttributeProvider",
+ "ds-cfg-virtual-attribute-enabled: true",
+ "ds-cfg-virtual-attribute-type: description",
+ "ds-cfg-virtual-attribute-conflict-behavior: virtual-overrides-real",
+ "ds-cfg-virtual-attribute-value: " + virtualValue,
+ "",
+ "dn: " + userDN,
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: test",
+ "description: " + realValue);
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ conn.processSearch(DN.decode(userDN), SearchScope.BASE_OBJECT,
+ SearchFilter.createFilterFromString("(objectClass=*)"));
+
+ List<Attribute> attrList =
+ searchOperation.getSearchEntries().get(0).getAttribute(
+ descriptionType);
+ assertNotNull(attrList);
+ assertEquals(attrList.size(), 1);
+
+ Attribute attr = attrList.get(0);
+ assertEquals(attr.getValues().size(), 1);
+ assertTrue(attr.hasValue(new AttributeValue(descriptionType,
+ virtualValue)));
+
+ DeleteOperation deleteOperation = conn.processDelete(DN.decode(ruleDN));
+ assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
+ }
+
+
+
+ /**
+ * Tests the creation of a description virtual attribute when real and virtual
+ * values should be merged and the entry has a real value.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testSingleDescriptionMergeRealAndVirtual()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+
+ String ruleDN = "cn=User-Defined Test,cn=Virtual Attributes,cn=config";
+ String userDN = "uid=test.user,o=test";
+ String virtualValue = "This is the virtual value";
+ String realValue = "This is the real value";
+
+ TestCaseUtils.addEntries(
+ "dn: " + ruleDN,
+ "objectClass: top",
+ "objectClass: ds-cfg-virtual-attribute",
+ "objectClass: ds-cfg-user-defined-virtual-attribute",
+ "cn: User-Defined Test",
+ "ds-cfg-virtual-attribute-class: org.opends.server.extensions." +
+ "UserDefinedVirtualAttributeProvider",
+ "ds-cfg-virtual-attribute-enabled: true",
+ "ds-cfg-virtual-attribute-type: description",
+ "ds-cfg-virtual-attribute-conflict-behavior: merge-real-and-virtual",
+ "ds-cfg-virtual-attribute-value: " + virtualValue,
+ "",
+ "dn: " + userDN,
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: test",
+ "description: " + realValue);
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ conn.processSearch(DN.decode(userDN), SearchScope.BASE_OBJECT,
+ SearchFilter.createFilterFromString("(objectClass=*)"));
+
+ List<Attribute> attrList =
+ searchOperation.getSearchEntries().get(0).getAttribute(
+ descriptionType);
+ assertNotNull(attrList);
+ assertEquals(attrList.size(), 2);
+
+ LinkedHashSet<AttributeValue> allValues =
+ new LinkedHashSet<AttributeValue>();
+ for (Attribute a : attrList)
+ {
+ allValues.addAll(a.getValues());
+ }
+
+ assertTrue(allValues.contains(new AttributeValue(descriptionType,
+ realValue)));
+ assertTrue(allValues.contains(new AttributeValue(descriptionType,
+ virtualValue)));
+
+ DeleteOperation deleteOperation = conn.processDelete(DN.decode(ruleDN));
+ assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
+ }
+
+
+
+ /**
+ * Tests to ensure that the user-defined virtual attribute provider can be
+ * used to grant a privilege to a user.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testVirtualPrivilege()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+
+ String policyDN = "cn=Test Policy,cn=Password Policies,cn=config";
+ String ruleDN = "cn=User-Defined Test,cn=Virtual Attributes,cn=config";
+ String userDN = "uid=test.user,o=test";
+
+ TestCaseUtils.addEntries(
+ "dn: cn=Test Policy,cn=Password Policies,cn=config",
+ "objectClass: top",
+ "objectClass: ds-cfg-password-policy",
+ "cn: Test Policy",
+ "ds-cfg-password-attribute: userPassword",
+ "ds-cfg-default-password-storage-scheme: SSHA",
+ "ds-cfg-allow-expired-password-changes: false",
+ "ds-cfg-allow-multiple-password-values: false",
+ "ds-cfg-allow-pre-encoded-passwords: false",
+ "ds-cfg-allow-user-password-changes: true",
+ "ds-cfg-expire-passwords-without-warning: false",
+ "ds-cfg-force-change-on-add: false",
+ "ds-cfg-force-change-on-reset: false",
+ "ds-cfg-grace-login-count: 0",
+ "ds-cfg-idle-lockout-interval: 0 seconds",
+ "ds-cfg-lockout-failure-count: 0",
+ "ds-cfg-lockout-duration: 0 seconds",
+ "ds-cfg-lockout-failure-expiration-interval: 0 seconds",
+ "ds-cfg-minimum-password-age: 0 seconds",
+ "ds-cfg-maximum-password-age: 0 seconds",
+ "ds-cfg-maximum-password-reset-age: 0 seconds",
+ "ds-cfg-password-expiration-warning-interval: 5 days",
+ "ds-cfg-password-change-requires-current-password: true",
+ "ds-cfg-password-validator-dn: cn=Length-Based Password Validator," +
+ "cn=Password Validators,cn=config",
+ "ds-cfg-require-secure-authentication: false",
+ "ds-cfg-require-secure-password-changes: false",
+ "ds-cfg-skip-validation-for-administrators: false",
+ "",
+ "dn: " + ruleDN,
+ "objectClass: top",
+ "objectClass: ds-cfg-virtual-attribute",
+ "objectClass: ds-cfg-user-defined-virtual-attribute",
+ "cn: User-Defined Test",
+ "ds-cfg-virtual-attribute-class: org.opends.server.extensions." +
+ "UserDefinedVirtualAttributeProvider",
+ "ds-cfg-virtual-attribute-enabled: true",
+ "ds-cfg-virtual-attribute-type: ds-pwp-password-policy-dn",
+ "ds-cfg-virtual-attribute-conflict-behavior: merge-real-and-virtual",
+ "ds-cfg-virtual-attribute-value: " + policyDN,
+ "",
+ "dn: " + userDN,
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: test");
+
+
+ String path1 = TestCaseUtils.createTempFile(
+ "dn: " + userDN,
+ "changetype: modify",
+ "replace: userPassword",
+ "userPassword: short");
+
+ String[] args1 =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "cn=Directory Manager",
+ "-w", "password",
+ "-f", path1
+ };
+
+ assertFalse(LDAPModify.mainModify(args1, false, null, null) == 0);
+
+
+ String path2 = TestCaseUtils.createTempFile(
+ "dn: " + ruleDN,
+ "changetype: modify",
+ "replace: ds-cfg-virtual-attribute-enabled",
+ "ds-cfg-virtual-attribute-enabled: false");
+
+ String[] args2 = new String[]
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "cn=Directory Manager",
+ "-w", "password",
+ "-f", path2
+ };
+
+ assertEquals(LDAPModify.mainModify(args2, false, null, null), 0);
+ assertEquals(LDAPModify.mainModify(args1, false, null, null), 0);
+
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+
+ DeleteOperation deleteOperation = conn.processDelete(DN.decode(ruleDN));
+ assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
+
+ deleteOperation = conn.processDelete(DN.decode(policyDN));
+ assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
+ }
+
+
+
+ /**
+ * Tests to ensure that the user-defined virtual attribute provider can be
+ * used to apply a custom password policy for a user. The custom password
+ * policy will reject passwords shorter than six characters, whereas the
+ * default policy will not.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testVirtualPasswordPolicyDN()
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+
+ String ruleDN = "cn=User-Defined Test,cn=Virtual Attributes,cn=config";
+ String userDN = "uid=test.user,o=test";
+
+ TestCaseUtils.addEntries(
+ "dn: " + ruleDN,
+ "objectClass: top",
+ "objectClass: ds-cfg-virtual-attribute",
+ "objectClass: ds-cfg-user-defined-virtual-attribute",
+ "cn: User-Defined Test",
+ "ds-cfg-virtual-attribute-class: org.opends.server.extensions." +
+ "UserDefinedVirtualAttributeProvider",
+ "ds-cfg-virtual-attribute-enabled: false",
+ "ds-cfg-virtual-attribute-type: ds-privilege-name",
+ "ds-cfg-virtual-attribute-conflict-behavior: merge-real-and-virtual",
+ "ds-cfg-virtual-attribute-value: bypass-acl",
+ "",
+ "dn: " + userDN,
+ "objectClass: top",
+ "objectClass: person",
+ "objectClass: organizationalPerson",
+ "objectClass: inetOrgPerson",
+ "uid: test.user",
+ "givenName: Test",
+ "sn: User",
+ "cn: Test User",
+ "userPassword: password");
+
+
+ String path1 = TestCaseUtils.createTempFile(
+ "dn: o=test",
+ "changetype: modify",
+ "replace: description",
+ "description: foo");
+
+ String[] args1 =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", userDN,
+ "-w", "password",
+ "-f", path1
+ };
+
+ assertFalse(LDAPModify.mainModify(args1, false, null, null) == 0);
+
+
+ String path2 = TestCaseUtils.createTempFile(
+ "dn: " + ruleDN,
+ "changetype: modify",
+ "replace: ds-cfg-virtual-attribute-enabled",
+ "ds-cfg-virtual-attribute-enabled: true");
+
+ String[] args2 = new String[]
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "cn=Directory Manager",
+ "-w", "password",
+ "-f", path2
+ };
+
+ assertEquals(LDAPModify.mainModify(args2, false, null, null), 0);
+ assertEquals(LDAPModify.mainModify(args1, false, null, null), 0);
+
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+
+ DeleteOperation deleteOperation = conn.processDelete(DN.decode(ruleDN));
+ assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
+ }
+}
+
--
Gitblit v1.10.0