/// <summary>
        /// Updates information about a user in the data source.
        /// </summary>
        /// <param name="user">A <see cref="T:System.Web.Security.MembershipUser"></see> object that represents the user to update and the updated information for the user.</param>
        public override void UpdateUser(MembershipUser user)
        {
            lock (SyncRoot)
            {
                XmlUser suser = this.Store.GetUserByKey((Guid)user.ProviderUserKey);
                if (suser != null)
                {
                    if (!ValidateUserName(suser.UserName, suser.UserKey))
                    {
                        throw new ArgumentException("UserName is not unique!");
                    }
                    if (this.RequiresUniqueEmail && !ValidateEmail(suser.Email, suser.UserKey))
                    {
                        throw new ArgumentException("Email is not unique!");
                    }

                    try
                    {
                        suser.Email            = user.Email;
                        suser.LastActivityDate = user.LastActivityDate;
                        suser.LastLoginDate    = user.LastLoginDate;
                        suser.Comment          = user.Comment;
                        suser.IsApproved       = user.IsApproved;
                        this.Store.Save();
                    }
                    catch { throw; }
                }
                else
                {
                    throw new ProviderException("User does not exist!");
                }
            }
        }
        /// <summary>
        /// Verifies that the specified user name and password exist in the data source.
        /// </summary>
        /// <param name="username">The name of the user to validate.</param>
        /// <param name="password">The password for the specified user.</param>
        /// <returns>
        /// true if the specified username and password are valid; otherwise, false.
        /// </returns>
        public override bool ValidateUser(string username, string password)
        {
            try
            {
                lock (SyncRoot)
                {
                    XmlUser user = this.Store.GetUserByName(username);

                    if (user == null)
                    {
                        return(false);
                    }

                    if (ValidateUserInternal(user, password))
                    {
                        user.LastLoginDate    = DateTime.Now;
                        user.LastActivityDate = DateTime.Now;
                        this.Store.Save();
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }
            }
            catch { throw; }
        }
        /// <summary>
        /// Resets a user's password to a new, automatically generated password.
        /// </summary>
        /// <param name="username">The user to reset the password for.</param>
        /// <param name="answer">The password answer for the specified user.</param>
        /// <returns>The new password for the specified user.</returns>
        public override string ResetPassword(string username, string answer)
        {
            lock (SyncRoot)
            {
                XmlUser user = this.Store.GetUserByName(username);
                if (user != null)
                {
                    if (answer != null && !user.PasswordAnswer.Equals(answer, StringComparison.OrdinalIgnoreCase))
                    {
                        throw new Exception("Invalid answer entered!");
                    }
                    else if (answer == null && Membership.RequiresQuestionAndAnswer)
                    {
                        throw new Exception("Invalid question and answer entered!");
                    }

                    try
                    {
                        byte[] NewPassword        = new byte[16];
                        RandomNumberGenerator rng = RandomNumberGenerator.Create();
                        rng.GetBytes(NewPassword);

                        string NewPasswordString = Convert.ToBase64String(NewPassword);
                        user.PasswordSalt = string.Empty;
                        user.Password     = TransformPassword(NewPasswordString, ref user.PasswordSalt);
                        this.Store.Save();

                        return(NewPasswordString);
                    }
                    catch { throw; }
                }
            }
            return(null);
        }
        /// <summary>
        /// Creates the membership from internal user.
        /// </summary>
        /// <param name="user">The user.</param>
        /// <returns></returns>
        private MembershipUser CreateMembershipFromInternalUser(XmlUser user)
        {
            MembershipUser muser = new MembershipUser(base.Name,
                                                      user.UserName, user.UserKey, user.Email, user.PasswordQuestion,
                                                      user.Comment, user.IsApproved, user.IsLockedOut, user.CreationDate, user.LastLoginDate,
                                                      user.LastActivityDate, user.LastPasswordChangeDate, user.LastLockoutDate);

            return(muser);
        }
 /// <summary>
 /// Validates the user internal.
 /// </summary>
 /// <param name="user">The user.</param>
 /// <param name="password">The password.</param>
 /// <returns></returns>
 private bool ValidateUserInternal(XmlUser user, string password)
 {
     if (user != null)
     {
         string passwordValidate = TransformPassword(password, ref user.PasswordSalt);
         if (string.Compare(passwordValidate, user.Password) == 0)
         {
             return(true);
         }
     }
     return(false);
 }
 /// <summary>
 /// Gets the user name associated with the specified e-mail address.
 /// </summary>
 /// <param name="email">The e-mail address to search for.</param>
 /// <returns>
 /// The user name associated with the specified e-mail address. If no match is found, return null.
 /// </returns>
 public override string GetUserNameByEmail(string email)
 {
     try
     {
         lock (SyncRoot)
         {
             XmlUser user = this.Store.GetUserByEmail(email);
             return((user != null) ? user.UserName : null);
         }
     }
     catch { throw; }
 }
        /// <summary>
        /// Adds a new membership user to the data source.
        /// </summary>
        /// <param name="username">The user name for the new user.</param>
        /// <param name="password">The password for the new user.</param>
        /// <param name="email">The e-mail address for the new user.</param>
        /// <param name="passwordQuestion">The password question for the new user.</param>
        /// <param name="passwordAnswer">The password answer for the new user</param>
        /// <param name="isApproved">Whether or not the new user is approved to be validated.</param>
        /// <param name="providerUserKey">The unique identifier from the membership data source for the user.</param>
        /// <param name="status">A <see cref="T:System.Web.Security.MembershipCreateStatus"></see> enumeration value indicating whether the user was created successfully.</param>
        /// <returns>
        /// A <see cref="T:System.Web.Security.MembershipUser"></see> object populated with the information for the newly created user.
        /// </returns>
        public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
        {
            status = MembershipCreateStatus.Success;

            try
            {
                // Validate the username and email
                if (!ValidateUserName(username, Guid.Empty))
                {
                    status = MembershipCreateStatus.DuplicateUserName;
                    return(null);
                }
                if (this.RequiresUniqueEmail && !ValidateEmail(password, Guid.Empty))
                {
                    status = MembershipCreateStatus.DuplicateEmail;
                    return(null);
                }

                // Validate the password
                ValidatePasswordEventArgs e = new ValidatePasswordEventArgs(username, password, true);
                // Raise the event before validating the password
                base.OnValidatingPassword(e);
                if (e.Cancel || !ValidatePassword(password))
                {
                    status = MembershipCreateStatus.InvalidPassword;
                    return(null);
                }

                // Everything is valid, create the user
                lock (SyncRoot)
                {
                    XmlUser user = new XmlUser();
                    user.UserKey                = Guid.NewGuid();
                    user.UserName               = username;
                    user.PasswordSalt           = string.Empty;
                    user.Password               = this.TransformPassword(password, ref user.PasswordSalt);
                    user.Email                  = email;
                    user.PasswordQuestion       = passwordQuestion;
                    user.PasswordAnswer         = passwordAnswer;
                    user.IsApproved             = isApproved;
                    user.CreationDate           = DateTime.Now;
                    user.LastActivityDate       = DateTime.Now;
                    user.LastPasswordChangeDate = DateTime.Now;

                    // Add the user to the store
                    this.Store.Users.Add(user);
                    this.Store.Save();

                    return(CreateMembershipFromInternalUser(user));
                }
            }
            catch { throw; }
        }
        /// <summary>
        /// Processes a request to update the password for a membership user.
        /// </summary>
        /// <param name="username">The user to update the password for.</param>
        /// <param name="oldPassword">The current password for the specified user.</param>
        /// <param name="newPassword">The new password for the specified user.</param>
        /// <returns>
        /// true if the password was updated successfully; otherwise, false.
        /// </returns>
        public override bool ChangePassword(string username, string oldPassword, string newPassword)
        {
            lock (SyncRoot)
            {
                XmlUser user = this.Store.GetUserByName(username);
                if (user == null)
                {
                    throw new Exception("User does not exist!");
                }

                if (ValidateUserInternal(user, oldPassword))
                {
                    ValidatePasswordEventArgs args = new ValidatePasswordEventArgs(username, newPassword, false);
                    base.OnValidatingPassword(args);
                    if (args.Cancel)
                    {
                        if (args.FailureInformation != null)
                        {
                            throw args.FailureInformation;
                        }
                        else
                        {
                            throw new MembershipPasswordException("Change password canceled due to new password validation failure.");
                        }
                    }
                    if (!ValidatePassword(newPassword))
                    {
                        throw new ArgumentException("Password doesn't meet password strength requirements!");
                    }
                    ///
                    user.PasswordSalt           = string.Empty;
                    user.Password               = TransformPassword(newPassword, ref user.PasswordSalt);
                    user.LastPasswordChangeDate = DateTime.Now;
                    this.Store.Save();
                    ///
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
        }
 /// <summary>
 /// Removes a user from the membership data source.
 /// </summary>
 /// <param name="username">The name of the user to delete.</param>
 /// <param name="deleteAllRelatedData">true to delete data related to the user from the database; false to leave data related to the user in the database.</param>
 /// <returns>
 /// true if the user was successfully deleted; otherwise, false.
 /// </returns>
 public override bool DeleteUser(string username, bool deleteAllRelatedData)
 {
     try
     {
         lock (SyncRoot)
         {
             XmlUser user = this.Store.GetUserByName(username);
             if (user != null)
             {
                 this.Store.Users.Remove(user);
                 // FIX: http://www.codeplex.com/aspnetxmlproviders/WorkItem/View.aspx?WorkItemId=7186
                 this.Store.Save();
                 return(true);
             }
         }
     }
     catch { throw; }
     //
     return(false);
 }
 /// <summary>
 /// Processes a request to update the password question and answer for a membership user.
 /// </summary>
 /// <param name="username">The user to change the password question and answer for.</param>
 /// <param name="password">The password for the specified user.</param>
 /// <param name="newPasswordQuestion">The new password question for the specified user.</param>
 /// <param name="newPasswordAnswer">The new password answer for the specified user.</param>
 /// <returns>
 /// true if the password question and answer are updated successfully; otherwise, false.
 /// </returns>
 public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
 {
     try
     {
         lock (SyncRoot)
         {
             XmlUser user = this.Store.GetUserByName(username);
             if (user != null && ValidateUserInternal(user, password))
             {
                 user.PasswordQuestion = newPasswordQuestion;
                 user.PasswordAnswer   = newPasswordAnswer;
                 this.Store.Save();
                 return(true);
             }
         }
     }
     catch { throw; }
     //
     return(false);
 }
 /// <summary>
 /// Gets information from the data source for a user based on the unique identifier for the membership user. Provides an option to update the last-activity date/time stamp for the user.
 /// </summary>
 /// <param name="providerUserKey">The unique identifier for the membership user to get information for.</param>
 /// <param name="userIsOnline">true to update the last-activity date/time stamp for the user; false to return user information without updating the last-activity date/time stamp for the user.</param>
 /// <returns>
 /// A <see cref="T:System.Web.Security.MembershipUser"></see> object populated with the specified user's information from the data source.
 /// </returns>
 public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
 {
     try
     {
         lock (SyncRoot)
         {
             XmlUser user = this.Store.GetUserByKey((Guid)providerUserKey);
             if (user != null)
             {
                 if (userIsOnline)
                 {
                     user.LastActivityDate = DateTime.Now;
                     this.Store.Save();
                 }
                 return(CreateMembershipFromInternalUser(user));
             }
             else
             {
                 return(null);
             }
         }
     }
     catch { throw; }
 }
 /// <summary>
 /// Gets information from the data source for a user. Provides an option to update the last-activity date/time stamp for the user.
 /// </summary>
 /// <param name="username">The name of the user to get information for.</param>
 /// <param name="userIsOnline">true to update the last-activity date/time stamp for the user; false to return user information without updating the last-activity date/time stamp for the user.</param>
 /// <returns>
 /// A <see cref="T:System.Web.Security.MembershipUser"></see> object populated with the specified user's information from the data source.
 /// </returns>
 public override MembershipUser GetUser(string username, bool userIsOnline)
 {
     try
     {
         lock (SyncRoot)
         {
             XmlUser user = this.Store.GetUserByName(username);
             if (user != null)
             {
                 if (userIsOnline)
                 {
                     user.LastActivityDate = DateTime.Now;
                     this.Store.Save();
                 }
                 return(CreateMembershipFromInternalUser(user));
             }
             else
             {
                 return(null);
             }
         }
     }
     catch { throw; }
 }
 /// <summary>
 /// Gets the password for the specified user name from the data source.
 /// </summary>
 /// <param name="username">The user to retrieve the password for.</param>
 /// <param name="answer">The password answer for the user.</param>
 /// <returns>
 /// The password for the specified user name.
 /// </returns>
 public override string GetPassword(string username, string answer)
 {
     try
     {
         if (EnablePasswordRetrieval)
         {
             lock (SyncRoot)
             {
                 XmlUser user = this.Store.GetUserByName(username);
                 if (user != null)
                 {
                     // >> FIX http://www.codeplex.com/aspnetxmlproviders/WorkItem/View.aspx?WorkItemId=9701
                     if (RequiresQuestionAndAnswer && answer.Equals(user.PasswordAnswer, StringComparison.OrdinalIgnoreCase))
                     {
                         return(UnEncodePassword(user.Password));
                     }
                     else if (!RequiresQuestionAndAnswer)
                     {
                         return(UnEncodePassword(user.Password));
                     }
                     else
                     {
                         throw new System.Web.Security.MembershipPasswordException();
                     }
                     // << FIX
                 }
             }
             return(null);
         }
         else
         {
             throw new Exception("Password retrieval is not enabled!");
         }
     }
     catch { throw; }
 }