From 059f1eb59194d5a7484b876fbbc9a938521e15a9 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Mon, 14 Aug 2006 22:34:19 +0000
Subject: [PATCH] Update the modify operation code so that it will generate account status notifications for the following events: - User password change - Administrative password reset - Administrative account disable - Administrative account enable - Administrative account unlock

---
 opends/src/server/org/opends/server/types/AttributeType.java   |    4 
 opends/src/server/org/opends/server/core/ModifyOperation.java  |  110 ++++++++++++++++++++++++---
 opends/src/server/org/opends/server/messages/CoreMessages.java |   74 ++++++++++++++++++
 3 files changed, 173 insertions(+), 15 deletions(-)

diff --git a/opends/src/server/org/opends/server/core/ModifyOperation.java b/opends/src/server/org/opends/server/core/ModifyOperation.java
index 2c8196c..5218672 100644
--- a/opends/src/server/org/opends/server/core/ModifyOperation.java
+++ b/opends/src/server/org/opends/server/core/ModifyOperation.java
@@ -56,8 +56,10 @@
 import org.opends.server.protocols.ldap.LDAPException;
 import org.opends.server.protocols.ldap.LDAPModification;
 import org.opends.server.schema.AuthPasswordSyntax;
+import org.opends.server.schema.BooleanSyntax;
 import org.opends.server.schema.UserPasswordSyntax;
 import org.opends.server.types.AcceptRejectWarn;
+import org.opends.server.types.AccountStatusNotificationType;
 import org.opends.server.types.Attribute;
 import org.opends.server.types.AttributeType;
 import org.opends.server.types.AttributeValue;
@@ -76,6 +78,7 @@
 import org.opends.server.types.SearchResultEntry;
 import org.opends.server.types.SynchronizationProviderResult;
 
+import static org.opends.server.config.ConfigConstants.*;
 import static org.opends.server.core.CoreConstants.*;
 import static org.opends.server.loggers.Access.*;
 import static org.opends.server.loggers.Debug.*;
@@ -1251,6 +1254,9 @@
         // Declare variables used for password policy state processing.
         boolean passwordChanged = false;
         boolean currentPasswordProvided = false;
+        boolean isEnabled = true;
+        boolean enabledStateChanged = false;
+        boolean wasLocked = false;
         int numPasswords;
         if (currentEntry.hasAttribute(pwPolicyState.getPasswordAttribute()))
         {
@@ -1283,6 +1289,11 @@
 
           if (passwordChanged)
           {
+            // See if the account was locked for any reason.
+            wasLocked = pwPolicyState.lockedDueToIdleInterval() ||
+                        pwPolicyState.lockedDueToMaximumResetAge() ||
+                        pwPolicyState.lockedDueToFailures();
+
             // Update the password policy state attributes in the user's entry.
             // If the modification fails, then these changes won't be applied.
             pwPolicyState.setPasswordChangedTime();
@@ -1342,8 +1353,7 @@
           // If the modification is updating the password attribute, then
           // perform any necessary password policy processing.  This processing
           // should be skipped for internal and synchronization operations.
-          boolean isPassword = a.getAttributeType().equals(
-                                    pwPolicyState.getPasswordAttribute());
+          boolean isPassword = t.equals(pwPolicyState.getPasswordAttribute());
           if (isPassword &&
               (! (isInternalOperation() || isSynchronizationOperation())))
           {
@@ -1657,6 +1667,37 @@
                 break modifyProcessing;
             }
           }
+          else
+          {
+            // See if it's an attribute used to maintain the account
+            // enabled/disabled state.
+            AttributeType disabledAttr =
+                 DirectoryServer.getAttributeType(OP_ATTR_ACCOUNT_DISABLED,
+                                                  true);
+            if (t.equals(disabledAttr))
+            {
+              enabledStateChanged = true;
+              for (AttributeValue v : a.getValues())
+              {
+                try
+                {
+                  isEnabled = (! BooleanSyntax.decodeBooleanValue(
+                                                    v.getNormalizedValue()));
+                }
+                catch (DirectoryException de)
+                {
+                  setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
+
+                  int msgID = MSGID_MODIFY_INVALID_DISABLED_VALUE;
+                  String message =
+                       getMessage(msgID, OP_ATTR_ACCOUNT_DISABLED,
+                                  String.valueOf(de.getErrorMessage()));
+                  appendErrorMessage(message);
+                  break modifyProcessing;
+                }
+              }
+            }
+          }
 
 
           switch (m.getModificationType())
@@ -2361,20 +2402,63 @@
             backend.replaceEntry(modifiedEntry, this);
 
 
-            // If the update was successful and included a self password change,
-            // then clear the "must change" flag in the client connection.
-            if ((getResultCode() == ResultCode.SUCCESS) && passwordChanged &&
-                selfChange)
+            // If the modification was successful, then see if there's any other
+            // work that we need to do here before handing off to postop
+            // plugins.
+            if (passwordChanged)
             {
-              // We really only want to do this if the authentication DN from
-              // the client connection is equal to the entry that was updated to
-              // avoid clearing the flag for the wrong user.
-              AuthenticationInfo authInfo =
-                   clientConnection.getAuthenticationInfo();
-              if (authInfo.getAuthenticationDN().equals(entryDN))
+              if (selfChange)
               {
-                clientConnection.setMustChangePassword(false);
+                AuthenticationInfo authInfo =
+                     clientConnection.getAuthenticationInfo();
+                if (authInfo.getAuthenticationDN().equals(entryDN))
+                {
+                  clientConnection.setMustChangePassword(false);
+                }
+
+                int    msgID   = MSGID_MODIFY_PASSWORD_CHANGED;
+                String message = getMessage(msgID);
+                pwPolicyState.generateAccountStatusNotification(
+                     AccountStatusNotificationType.PASSWORD_CHANGED, entryDN,
+                     msgID, message);
               }
+              else
+              {
+                int    msgID   = MSGID_MODIFY_PASSWORD_RESET;
+                String message = getMessage(msgID);
+                pwPolicyState.generateAccountStatusNotification(
+                     AccountStatusNotificationType.PASSWORD_RESET, entryDN,
+                     msgID, message);
+              }
+            }
+
+            if (enabledStateChanged)
+            {
+              if (isEnabled)
+              {
+                int    msgID   = MSGID_MODIFY_ACCOUNT_ENABLED;
+                String message = getMessage(msgID);
+                pwPolicyState.generateAccountStatusNotification(
+                     AccountStatusNotificationType.ACCOUNT_ENABLED, entryDN,
+                     msgID, message);
+              }
+              else
+              {
+                int    msgID   = MSGID_MODIFY_ACCOUNT_DISABLED;
+                String message = getMessage(msgID);
+                pwPolicyState.generateAccountStatusNotification(
+                     AccountStatusNotificationType.ACCOUNT_DISABLED, entryDN,
+                     msgID, message);
+              }
+            }
+
+            if (wasLocked)
+            {
+              int    msgID   = MSGID_MODIFY_ACCOUNT_UNLOCKED;
+              String message = getMessage(msgID);
+              pwPolicyState.generateAccountStatusNotification(
+                   AccountStatusNotificationType.ACCOUNT_UNLOCKED, entryDN,
+                   msgID, message);
             }
           }
 
diff --git a/opends/src/server/org/opends/server/messages/CoreMessages.java b/opends/src/server/org/opends/server/messages/CoreMessages.java
index 0c749c4..e102a1e 100644
--- a/opends/src/server/org/opends/server/messages/CoreMessages.java
+++ b/opends/src/server/org/opends/server/messages/CoreMessages.java
@@ -5756,6 +5756,67 @@
 
 
   /**
+   * The message ID for the message that will be used if an attempt is made to
+   * modify the account disabled attribute using an invalid value.  This takes
+   * two arguments, which are the name of the attribute and a message explaining
+   * the reason the value was invalid.
+   */
+  public static final int MSGID_MODIFY_INVALID_DISABLED_VALUE =
+       CATEGORY_MASK_CORE | SEVERITY_MASK_MILD_ERROR | 550;
+
+
+
+  /**
+   * The message ID for the message that will be used in the account status
+   * notification indicating that a user's password has been changed.  This does
+   * not take any arguments.
+   */
+  public static final int MSGID_MODIFY_PASSWORD_CHANGED =
+       CATEGORY_MASK_CORE | SEVERITY_MASK_INFORMATIONAL | 551;
+
+
+
+  /**
+   * The message ID for the message that will be used in the account status
+   * notification indicating that a user's password has been reset by an
+   * administrator.  This does not take any arguments.
+   */
+  public static final int MSGID_MODIFY_PASSWORD_RESET =
+       CATEGORY_MASK_CORE | SEVERITY_MASK_INFORMATIONAL | 552;
+
+
+
+  /**
+   * The message ID for the message that will be used in the account status
+   * notification indicating that a user's account has been enabled.  This does
+   * not take any arguments.
+   */
+  public static final int MSGID_MODIFY_ACCOUNT_ENABLED =
+       CATEGORY_MASK_CORE | SEVERITY_MASK_INFORMATIONAL | 553;
+
+
+
+  /**
+   * The message ID for the message that will be used in the account status
+   * notification indicating that a user's account has been disabled.  This does
+   * not take any arguments.
+   */
+  public static final int MSGID_MODIFY_ACCOUNT_DISABLED =
+       CATEGORY_MASK_CORE | SEVERITY_MASK_INFORMATIONAL | 554;
+
+
+
+  /**
+   * The message ID for the message that will be used in the account status
+   * notification indicating that a user's account has been unlocked.  This does
+   * not take any arguments.
+   */
+  public static final int MSGID_MODIFY_ACCOUNT_UNLOCKED =
+       CATEGORY_MASK_CORE | SEVERITY_MASK_INFORMATIONAL | 555;
+
+
+
+  /**
    * Associates a set of generic messages with the message IDs defined
    * in this class.
    */
@@ -6867,6 +6928,9 @@
     registerMessage(MSGID_MODIFY_INVALID_MOD_TYPE_FOR_PASSWORD,
                     "Invalid modification type %s attempted on password " +
                     "attribute %s.");
+    registerMessage(MSGID_MODIFY_INVALID_DISABLED_VALUE,
+                    "Invalid value provided for operational attribute %s:  " +
+                    "%s.");
     registerMessage(MSGID_MODIFY_ADD_NO_VALUES,
                     "Entry %s cannot be modified because the modification " +
                     "contained an add component for attribute %s but no " +
@@ -6940,6 +7004,16 @@
                     "The modify operation was not actually performed in the " +
                     "Directory Server backend because the LDAP no-op control " +
                     "was present in the request.");
+    registerMessage(MSGID_MODIFY_PASSWORD_CHANGED,
+                    "The user password has been changed.");
+    registerMessage(MSGID_MODIFY_PASSWORD_RESET,
+                    "The user password has been administratively reset.");
+    registerMessage(MSGID_MODIFY_ACCOUNT_ENABLED,
+                    "The user account has been administratively enabled.");
+    registerMessage(MSGID_MODIFY_ACCOUNT_DISABLED,
+                    "The user account has been administratively disabled.");
+    registerMessage(MSGID_MODIFY_ACCOUNT_UNLOCKED,
+                    "The user account has been administratively unlocked.");
     registerMessage(MSGID_MODIFY_ERROR_NOTIFYING_CHANGE_LISTENER,
                     "An unexpected error occurred while notifying a change " +
                     "notification listener of a modify operation:  %s.");
diff --git a/opends/src/server/org/opends/server/types/AttributeType.java b/opends/src/server/org/opends/server/types/AttributeType.java
index c74aa94..9cfe2c7 100644
--- a/opends/src/server/org/opends/server/types/AttributeType.java
+++ b/opends/src/server/org/opends/server/types/AttributeType.java
@@ -1182,13 +1182,13 @@
 
   /**
    * Indicates whether the provided object is equal to this attribute
-   * value.  The object will be considered equal if it is an attribute
+   * type.  The object will be considered equal if it is an attribute
    * type with the same OID as the current type.
    *
    * @param  o  The object for which to make the determination.
    *
    * @return  <CODE>true</CODE> if the provided object is equal to
-   *          this attribute, or <CODE>false</CODE> if not.
+   *          this attribute type, or <CODE>false</CODE> if not.
    */
   public boolean equals(Object o)
   {

--
Gitblit v1.10.0