diff --git a/src/Umbraco.Core/Models/Membership/MembershipExtensions.cs b/src/Umbraco.Core/Models/Membership/MembershipExtensions.cs
index a986869371..118ba46669 100644
--- a/src/Umbraco.Core/Models/Membership/MembershipExtensions.cs
+++ b/src/Umbraco.Core/Models/Membership/MembershipExtensions.cs
@@ -5,15 +5,15 @@ namespace Umbraco.Core.Models.Membership
{
internal static class MembershipExtensions
{
- internal static MembershipUser AsConcreteMembershipUser(this IMember member)
+ internal static UmbracoMembershipMember AsConcreteMembershipUser(this IMember member)
{
var membershipMember = new UmbracoMembershipMember(member);
return membershipMember;
}
- internal static IMember AsIMember(this MembershipUser membershipMember)
+ internal static IMember AsIMember(this UmbracoMembershipMember membershipMember)
{
- var member = membershipMember as UmbracoMembershipMember;
+ var member = membershipMember;
if (member != null)
{
return member.Member;
diff --git a/src/Umbraco.Core/Persistence/Querying/ModelToSqlExpressionHelper.cs b/src/Umbraco.Core/Persistence/Querying/ModelToSqlExpressionHelper.cs
index 611d9c63a3..4dba620ab0 100644
--- a/src/Umbraco.Core/Persistence/Querying/ModelToSqlExpressionHelper.cs
+++ b/src/Umbraco.Core/Persistence/Querying/ModelToSqlExpressionHelper.cs
@@ -232,6 +232,8 @@ namespace Umbraco.Core.Persistence.Querying
{
switch (verb)
{
+ case "SqlWildcard":
+ return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnWildcardComparison(col, EscapeAtArgument(RemoveQuote(val)), columnType);
case "Equals":
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnEqualComparison(col, EscapeAtArgument(RemoveQuote(val)), columnType);
case "StartsWith":
@@ -280,7 +282,7 @@ namespace Umbraco.Core.Persistence.Querying
return string.Format("upper({0})", r);
case "ToLower":
return string.Format("lower({0})", r);
-
+ case "SqlWildcard":
case "StartsWith":
case "EndsWith":
case "Contains":
diff --git a/src/Umbraco.Core/Persistence/Querying/SqlStringExtensions.cs b/src/Umbraco.Core/Persistence/Querying/SqlStringExtensions.cs
index 82c158a9c6..cbecc0a591 100644
--- a/src/Umbraco.Core/Persistence/Querying/SqlStringExtensions.cs
+++ b/src/Umbraco.Core/Persistence/Querying/SqlStringExtensions.cs
@@ -1,4 +1,5 @@
using System;
+using System.Text.RegularExpressions;
namespace Umbraco.Core.Persistence.Querying
{
@@ -7,6 +8,15 @@ namespace Umbraco.Core.Persistence.Querying
///
internal static class SqlStringExtensions
{
+ public static bool SqlWildcard(this string str, string txt, TextColumnType columnType)
+ {
+ var wildcardmatch = new Regex("^" + Regex.Escape(txt).
+ //deal with any wildcard chars %
+ Replace(@"\%", ".*") + "$");
+
+ return wildcardmatch.IsMatch(str);
+ }
+
public static bool SqlContains(this string str, string txt, TextColumnType columnType)
{
return str.InvariantContains(txt);
diff --git a/src/Umbraco.Core/Persistence/Querying/StringPropertyMatchType.cs b/src/Umbraco.Core/Persistence/Querying/StringPropertyMatchType.cs
index f4245b931a..f45efb412a 100644
--- a/src/Umbraco.Core/Persistence/Querying/StringPropertyMatchType.cs
+++ b/src/Umbraco.Core/Persistence/Querying/StringPropertyMatchType.cs
@@ -8,6 +8,8 @@
Exact,
Contains,
StartsWith,
- EndsWith
+ EndsWith,
+ //Deals with % as wildcard chars in a string
+ Wildcard
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/ISqlSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/ISqlSyntaxProvider.cs
index 9fbf0456b6..2b31fb2032 100644
--- a/src/Umbraco.Core/Persistence/SqlSyntax/ISqlSyntaxProvider.cs
+++ b/src/Umbraco.Core/Persistence/SqlSyntax/ISqlSyntaxProvider.cs
@@ -15,6 +15,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
string GetStringColumnStartsWithComparison(string column, string value, TextColumnType columnType);
string GetStringColumnEndsWithComparison(string column, string value, TextColumnType columnType);
string GetStringColumnContainsComparison(string column, string value, TextColumnType columnType);
+ string GetStringColumnWildcardComparison(string column, string value, TextColumnType columnType);
string GetQuotedTableName(string tableName);
string GetQuotedColumnName(string columnName);
diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs
index d908f5c9b6..d9e9599dab 100644
--- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs
+++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlCeSyntaxProvider.cs
@@ -116,6 +116,20 @@ namespace Umbraco.Core.Persistence.SqlSyntax
}
}
+ public override string GetStringColumnWildcardComparison(string column, string value, TextColumnType columnType)
+ {
+ switch (columnType)
+ {
+ case TextColumnType.NVarchar:
+ return base.GetStringColumnContainsComparison(column, value, columnType);
+ case TextColumnType.NText:
+ //MSSQL doesn't allow for upper methods with NText columns
+ return string.Format("{0} LIKE '{1}'", column, value);
+ default:
+ throw new ArgumentOutOfRangeException("columnType");
+ }
+ }
+
public override string GetQuotedTableName(string tableName)
{
return string.Format("[{0}]", tableName);
diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs
index 24177c61d5..4046a7575d 100644
--- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs
+++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs
@@ -90,6 +90,20 @@ namespace Umbraco.Core.Persistence.SqlSyntax
}
}
+ public override string GetStringColumnWildcardComparison(string column, string value, TextColumnType columnType)
+ {
+ switch (columnType)
+ {
+ case TextColumnType.NVarchar:
+ return base.GetStringColumnContainsComparison(column, value, columnType);
+ case TextColumnType.NText:
+ //MSSQL doesn't allow for upper methods with NText columns
+ return string.Format("{0} LIKE '{1}'", column, value);
+ default:
+ throw new ArgumentOutOfRangeException("columnType");
+ }
+ }
+
public override string GetQuotedTableName(string tableName)
{
return string.Format("[{0}]", tableName);
diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderBase.cs b/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderBase.cs
index 8505d1e553..8f9a84437c 100644
--- a/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderBase.cs
+++ b/src/Umbraco.Core/Persistence/SqlSyntax/SqlSyntaxProviderBase.cs
@@ -127,6 +127,12 @@ namespace Umbraco.Core.Persistence.SqlSyntax
return string.Format("upper({0}) like '%{1}%'", column, value.ToUpper());
}
+ public virtual string GetStringColumnWildcardComparison(string column, string value, TextColumnType columnType)
+ {
+ //use the 'upper' method to always ensure strings are matched without case sensitivity no matter what the db setting.
+ return string.Format("upper({0}) like '{1}'", column, value.ToUpper());
+ }
+
public virtual string GetQuotedTableName(string tableName)
{
return string.Format("\"{0}\"", tableName);
diff --git a/src/Umbraco.Core/Security/MembershipProviderBase.cs b/src/Umbraco.Core/Security/MembershipProviderBase.cs
index 10a05d042e..24a0e29409 100644
--- a/src/Umbraco.Core/Security/MembershipProviderBase.cs
+++ b/src/Umbraco.Core/Security/MembershipProviderBase.cs
@@ -7,9 +7,110 @@ using System.Text.RegularExpressions;
using System.Web.Configuration;
using System.Web.Hosting;
using System.Web.Security;
+using Umbraco.Core.Logging;
namespace Umbraco.Core.Security
{
+
+ public abstract class UmbracoMembershipProviderBase : MembershipProviderBase
+ {
+ protected UmbracoMembershipProviderBase()
+ {
+ //Set the defaults!
+ DefaultMemberTypeAlias = "Member";
+ LockPropertyTypeAlias = Constants.Conventions.Member.IsLockedOut;
+ LastLockedOutPropertyTypeAlias = Constants.Conventions.Member.LastLockoutDate;
+ FailedPasswordAttemptsPropertyTypeAlias = Constants.Conventions.Member.FailedPasswordAttempts;
+ ApprovedPropertyTypeAlias = Constants.Conventions.Member.IsApproved;
+ CommentPropertyTypeAlias = Constants.Conventions.Member.Comments;
+ LastLoginPropertyTypeAlias = Constants.Conventions.Member.LastLoginDate;
+ LastPasswordChangedPropertyTypeAlias = Constants.Conventions.Member.LastPasswordChangeDate;
+ PasswordRetrievalQuestionPropertyTypeAlias = Constants.Conventions.Member.PasswordQuestion;
+ PasswordRetrievalAnswerPropertyTypeAlias = Constants.Conventions.Member.PasswordAnswer;
+ }
+
+ public string DefaultMemberTypeAlias { get; protected set; }
+ public string LockPropertyTypeAlias { get; protected set; }
+ public string LastLockedOutPropertyTypeAlias { get; protected set; }
+ public string FailedPasswordAttemptsPropertyTypeAlias { get; protected set; }
+ public string ApprovedPropertyTypeAlias { get; protected set; }
+ public string CommentPropertyTypeAlias { get; protected set; }
+ public string LastLoginPropertyTypeAlias { get; protected set; }
+ public string LastPasswordChangedPropertyTypeAlias { get; protected set; }
+ public string PasswordRetrievalQuestionPropertyTypeAlias { get; protected set; }
+ public string PasswordRetrievalAnswerPropertyTypeAlias { get; protected set; }
+
+ public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
+ {
+ base.ChangePasswordQuestionAndAnswer(username, password, newPasswordQuestion, newPasswordAnswer);
+
+ if (string.IsNullOrEmpty(PasswordRetrievalQuestionPropertyTypeAlias) || string.IsNullOrEmpty(PasswordRetrievalAnswerPropertyTypeAlias))
+ {
+ throw new NotSupportedException("Updating the password Question and Answer is not valid if the properties aren't set in the config file");
+ }
+
+ return PerformChangePasswordQuestionAndAnswer(username, password, newPasswordQuestion, newPasswordAnswer);
+ }
+
+ ///
+ /// Adds a new membership user to the data source.
+ ///
+ /// The user name for the new user.
+ /// The password for the new user.
+ /// The e-mail address for the new user.
+ /// The password question for the new user.
+ /// The password answer for the new user
+ /// Whether or not the new user is approved to be validated.
+ /// The unique identifier from the membership data source for the user.
+ /// A enumeration value indicating whether the user was created successfully.
+ ///
+ /// A object populated with the information for the newly created user.
+ ///
+ protected sealed override MembershipUser PerformCreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
+ {
+ return PerformCreateUser(DefaultMemberTypeAlias, username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
+ }
+
+ ///
+ /// Adds a new membership user to the data source.
+ ///
+ /// The member type alias to use when creating the member
+ /// The user name for the new user.
+ /// The password for the new user.
+ /// The e-mail address for the new user.
+ /// The password question for the new user.
+ /// The password answer for the new user
+ /// Whether or not the new user is approved to be validated.
+ /// The unique identifier from the membership data source for the user.
+ /// A enumeration value indicating whether the user was created successfully.
+ ///
+ /// A object populated with the information for the newly created user.
+ ///
+ public MembershipUser CreateUser(string memberTypeAlias, string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
+ {
+ //do the base validation first
+ base.CreateUser(username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
+
+ return PerformCreateUser(memberTypeAlias, username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
+ }
+
+ ///
+ /// Adds a new membership user to the data source.
+ ///
+ /// The member type alias to use when creating the member
+ /// The user name for the new user.
+ /// The password for the new user.
+ /// The e-mail address for the new user.
+ /// The password question for the new user.
+ /// The password answer for the new user
+ /// Whether or not the new user is approved to be validated.
+ /// The unique identifier from the membership data source for the user.
+ /// A enumeration value indicating whether the user was created successfully.
+ ///
+ /// A object populated with the information for the newly created user.
+ ///
+ protected abstract MembershipUser PerformCreateUser(string memberTypeAlias, string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status);
+ }
///
/// A base membership provider class offering much of the underlying functionality for initializing and password encryption/hashing.
///
@@ -18,7 +119,7 @@ namespace Umbraco.Core.Security
///
/// Providers can override this setting, default is 7
///
- protected virtual int DefaultMinPasswordLength
+ public virtual int DefaultMinPasswordLength
{
get { return 7; }
}
@@ -26,7 +127,7 @@ namespace Umbraco.Core.Security
///
/// Providers can override this setting, default is 1
///
- protected virtual int DefaultMinNonAlphanumericChars
+ public virtual int DefaultMinNonAlphanumericChars
{
get { return 1; }
}
@@ -34,7 +135,7 @@ namespace Umbraco.Core.Security
///
/// Providers can override this setting, default is false to use better security
///
- protected virtual bool DefaultUseLegacyEncoding
+ public virtual bool DefaultUseLegacyEncoding
{
get { return false; }
}
@@ -44,7 +145,7 @@ namespace Umbraco.Core.Security
/// authenticate the username + password when ChangePassword is called. This property exists purely for
/// backwards compatibility.
///
- internal virtual bool AllowManuallyChangingPassword
+ public virtual bool AllowManuallyChangingPassword
{
get { return false; }
}
@@ -60,7 +161,8 @@ namespace Umbraco.Core.Security
private string _passwordStrengthRegularExpression;
private bool _requiresQuestionAndAnswer;
private bool _requiresUniqueEmail;
- private bool _useLegacyEncoding;
+
+ internal bool UseLegacyEncoding;
#region Properties
@@ -208,7 +310,7 @@ namespace Umbraco.Core.Security
_enablePasswordRetrieval = config.GetValue("enablePasswordRetrieval", false);
_enablePasswordReset = config.GetValue("enablePasswordReset", false);
_requiresQuestionAndAnswer = config.GetValue("requiresQuestionAndAnswer", false);
- _requiresUniqueEmail = config.GetValue("requiresUniqueEmail", false);
+ _requiresUniqueEmail = config.GetValue("requiresUniqueEmail", true);
_maxInvalidPasswordAttempts = GetIntValue(config, "maxInvalidPasswordAttempts", 5, false, 0);
_passwordAttemptWindow = GetIntValue(config, "passwordAttemptWindow", 10, false, 0);
_minRequiredPasswordLength = GetIntValue(config, "minRequiredPasswordLength", DefaultMinPasswordLength, true, 0x80);
@@ -220,10 +322,10 @@ namespace Umbraco.Core.Security
_applicationName = GetDefaultAppName();
//by default we will continue using the legacy encoding.
- _useLegacyEncoding = config.GetValue("useLegacyEncoding", DefaultUseLegacyEncoding);
+ UseLegacyEncoding = config.GetValue("useLegacyEncoding", DefaultUseLegacyEncoding);
- // make sure password format is clear by default.
- string str = config["passwordFormat"] ?? "Clear";
+ // make sure password format is Hashed by default.
+ string str = config["passwordFormat"] ?? "Hashed";
switch (str.ToLower())
{
@@ -244,7 +346,11 @@ namespace Umbraco.Core.Security
}
if ((PasswordFormat == MembershipPasswordFormat.Hashed) && EnablePasswordRetrieval)
- throw new ProviderException("Provider can not retrieve hashed password");
+ {
+ var ex = new ProviderException("Provider can not retrieve a hashed password");
+ LogHelper.Error("Cannot specify a Hashed password format with the enabledPasswordRetrieval option set to true", ex);
+ throw ex;
+ }
}
@@ -271,14 +377,19 @@ namespace Umbraco.Core.Security
AlphanumericChars,
Strength
}
-
+
///
- /// Checks to ensure the AllowManuallyChangingPassword rule is adhered to
+ /// Processes a request to update the password for a membership user.
///
- ///
- ///
- ///
- ///
+ /// The user to update the password for.
+ /// This property is ignore for this provider
+ /// The new password for the specified user.
+ ///
+ /// true if the password was updated successfully; otherwise, false.
+ ///
+ ///
+ /// Checks to ensure the AllowManuallyChangingPassword rule is adhered to
+ ///
public sealed override bool ChangePassword(string username, string oldPassword, string newPassword)
{
if (oldPassword.IsNullOrWhiteSpace() && AllowManuallyChangingPassword == false)
@@ -290,8 +401,139 @@ namespace Umbraco.Core.Security
return PerformChangePassword(username, oldPassword, newPassword);
}
+ ///
+ /// Processes a request to update the password for a membership user.
+ ///
+ /// The user to update the password for.
+ /// This property is ignore for this provider
+ /// The new password for the specified user.
+ ///
+ /// true if the password was updated successfully; otherwise, false.
+ ///
protected abstract bool PerformChangePassword(string username, string oldPassword, string newPassword);
+ ///
+ /// Processes a request to update the password question and answer for a membership user.
+ ///
+ /// The user to change the password question and answer for.
+ /// The password for the specified user.
+ /// The new password question for the specified user.
+ /// The new password answer for the specified user.
+ ///
+ /// true if the password question and answer are updated successfully; otherwise, false.
+ ///
+ ///
+ /// Performs the basic validation before passing off to PerformChangePasswordQuestionAndAnswer
+ ///
+ public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
+ {
+ if (RequiresQuestionAndAnswer == false)
+ {
+ throw new NotSupportedException("Updating the password Question and Answer is not available if requiresQuestionAndAnswer is not set in web.config");
+ }
+
+ if (ValidateUser(username, password) == false)
+ {
+ return false;
+ }
+
+ return PerformChangePasswordQuestionAndAnswer(username, password, newPasswordQuestion, newPasswordAnswer);
+ }
+
+ ///
+ /// Processes a request to update the password question and answer for a membership user.
+ ///
+ /// The user to change the password question and answer for.
+ /// The password for the specified user.
+ /// The new password question for the specified user.
+ /// The new password answer for the specified user.
+ ///
+ /// true if the password question and answer are updated successfully; otherwise, false.
+ ///
+ protected abstract bool PerformChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer);
+
+ ///
+ /// Adds a new membership user to the data source.
+ ///
+ /// The user name for the new user.
+ /// The password for the new user.
+ /// The e-mail address for the new user.
+ /// The password question for the new user.
+ /// The password answer for the new user
+ /// Whether or not the new user is approved to be validated.
+ /// The unique identifier from the membership data source for the user.
+ /// A enumeration value indicating whether the user was created successfully.
+ ///
+ /// A object populated with the information for the newly created user.
+ ///
+ ///
+ /// Ensures the ValidatingPassword event is executed before executing PerformCreateUser and performs basic membership provider validation of values.
+ ///
+ public sealed override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
+ {
+ var args = new ValidatePasswordEventArgs(username, password, true);
+ OnValidatingPassword(args);
+ if (args.Cancel)
+ {
+ status = MembershipCreateStatus.InvalidPassword;
+ return null;
+ }
+
+ // Validate password
+ var passwordValidAttempt = IsPasswordValid(password, MinRequiredNonAlphanumericCharacters, PasswordStrengthRegularExpression, MinRequiredPasswordLength);
+ if (passwordValidAttempt.Success == false)
+ {
+ status = MembershipCreateStatus.InvalidPassword;
+ return null;
+ }
+
+ // Validate email
+ if (IsEmailValid(email) == false)
+ {
+ status = MembershipCreateStatus.InvalidEmail;
+ return null;
+ }
+
+ // Make sure username isn't all whitespace
+ if (string.IsNullOrWhiteSpace(username.Trim()))
+ {
+ status = MembershipCreateStatus.InvalidUserName;
+ return null;
+ }
+
+ // Check password question
+ if (string.IsNullOrWhiteSpace(passwordQuestion) && RequiresQuestionAndAnswer)
+ {
+ status = MembershipCreateStatus.InvalidQuestion;
+ return null;
+ }
+
+ // Check password answer
+ if (string.IsNullOrWhiteSpace(passwordAnswer) && RequiresQuestionAndAnswer)
+ {
+ status = MembershipCreateStatus.InvalidAnswer;
+ return null;
+ }
+
+ return PerformCreateUser(username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
+ }
+
+ ///
+ /// Adds a new membership user to the data source.
+ ///
+ /// The user name for the new user.
+ /// The password for the new user.
+ /// The e-mail address for the new user.
+ /// The password question for the new user.
+ /// The password answer for the new user
+ /// Whether or not the new user is approved to be validated.
+ /// The unique identifier from the membership data source for the user.
+ /// A enumeration value indicating whether the user was created successfully.
+ ///
+ /// A object populated with the information for the newly created user.
+ ///
+ protected abstract MembershipUser PerformCreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status);
+
protected internal static Attempt IsPasswordValid(string password, int minRequiredNonAlphanumericChars, string strengthRegex, int minLength)
{
if (minRequiredNonAlphanumericChars > 0)
@@ -374,7 +616,7 @@ namespace Umbraco.Core.Security
protected string FormatPasswordForStorage(string pass, string salt)
{
- if (_useLegacyEncoding)
+ if (UseLegacyEncoding)
{
return pass;
}
@@ -383,11 +625,20 @@ namespace Umbraco.Core.Security
return salt + pass;
}
+ protected bool IsEmailValid(string email)
+ {
+ const string pattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|"
+ + @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?
protected string EncryptOrHashExistingPassword(string storedPassword)
{
- if (_useLegacyEncoding)
+ if (UseLegacyEncoding)
{
return EncryptOrHashPassword(storedPassword, storedPassword);
}
@@ -481,7 +732,7 @@ namespace Umbraco.Core.Security
{
//if we are doing it the old way
- if (_useLegacyEncoding)
+ if (UseLegacyEncoding)
{
return LegacyUnEncodePassword(pass);
}
@@ -533,7 +784,7 @@ namespace Umbraco.Core.Security
protected HashAlgorithm GetHashAlgorithm(string password)
{
- if (_useLegacyEncoding)
+ if (UseLegacyEncoding)
{
//before we were never checking for an algorithm type so we were always using HMACSHA1
// for any SHA specified algorithm :( so we'll need to keep doing that for backwards compat support.
@@ -601,5 +852,24 @@ namespace Umbraco.Core.Security
return password;
}
+ public override string ToString()
+ {
+ var result = base.ToString();
+ var sb = new StringBuilder(result);
+ sb.AppendLine("Name =" + Name);
+ sb.AppendLine("_applicationName =" + _applicationName);
+ sb.AppendLine("_enablePasswordReset=" + _enablePasswordReset);
+ sb.AppendLine("_enablePasswordRetrieval=" + _enablePasswordRetrieval);
+ sb.AppendLine("_maxInvalidPasswordAttempts=" + _maxInvalidPasswordAttempts);
+ sb.AppendLine("_minRequiredNonAlphanumericCharacters=" + _minRequiredNonAlphanumericCharacters);
+ sb.AppendLine("_minRequiredPasswordLength=" + _minRequiredPasswordLength);
+ sb.AppendLine("_passwordAttemptWindow=" + _passwordAttemptWindow);
+ sb.AppendLine("_passwordFormat=" + _passwordFormat);
+ sb.AppendLine("_passwordStrengthRegularExpression=" + _passwordStrengthRegularExpression);
+ sb.AppendLine("_requiresQuestionAndAnswer=" + _requiresQuestionAndAnswer);
+ sb.AppendLine("_requiresUniqueEmail=" + _requiresUniqueEmail);
+ return sb.ToString();
+ }
+
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Services/MemberService.cs b/src/Umbraco.Core/Services/MemberService.cs
index 0f4cd7c242..a84734d1f7 100644
--- a/src/Umbraco.Core/Services/MemberService.cs
+++ b/src/Umbraco.Core/Services/MemberService.cs
@@ -206,6 +206,9 @@ namespace Umbraco.Core.Services
case StringPropertyMatchType.EndsWith:
query.Where(member => member.Email.EndsWith(emailStringToMatch));
break;
+ case StringPropertyMatchType.Wildcard:
+ query.Where(member => member.Email.SqlWildcard(emailStringToMatch, TextColumnType.NVarchar));
+ break;
default:
throw new ArgumentOutOfRangeException("matchType");
}
@@ -235,6 +238,9 @@ namespace Umbraco.Core.Services
case StringPropertyMatchType.EndsWith:
query.Where(member => member.Username.EndsWith(login));
break;
+ case StringPropertyMatchType.Wildcard:
+ query.Where(member => member.Email.SqlWildcard(login, TextColumnType.NVarchar));
+ break;
default:
throw new ArgumentOutOfRangeException("matchType");
}
diff --git a/src/Umbraco.Tests/Membership/MembershipProviderBaseTests.cs b/src/Umbraco.Tests/Membership/MembershipProviderBaseTests.cs
index 500b33501c..06e44be215 100644
--- a/src/Umbraco.Tests/Membership/MembershipProviderBaseTests.cs
+++ b/src/Umbraco.Tests/Membership/MembershipProviderBaseTests.cs
@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Configuration.Provider;
using System.Diagnostics;
using System.Linq;
using System.Text;
@@ -14,6 +16,48 @@ namespace Umbraco.Tests.Membership
[TestFixture]
public class MembershipProviderBaseTests
{
+ //[Test]
+ //public void Change_Password_Base_Validation()
+
+ //[Test]
+ //public void ChangePasswordQuestionAndAnswer_Base_Validation()
+
+ //[Test]
+ //public void CreateUser_Base_Validation()
+
+ [Test]
+ public void Sets_Defaults()
+ {
+ var provider = new TestProvider();
+ provider.Initialize("test", new NameValueCollection());
+
+ Assert.AreEqual("test", provider.Name);
+ Assert.AreEqual(MembershipProviderBase.GetDefaultAppName(), provider.ApplicationName);
+ Assert.AreEqual(false, provider.EnablePasswordRetrieval);
+ Assert.AreEqual(false, provider.EnablePasswordReset);
+ Assert.AreEqual(false, provider.RequiresQuestionAndAnswer);
+ Assert.AreEqual(true, provider.RequiresUniqueEmail);
+ Assert.AreEqual(5, provider.MaxInvalidPasswordAttempts);
+ Assert.AreEqual(10, provider.PasswordAttemptWindow);
+ Assert.AreEqual(provider.DefaultMinPasswordLength, provider.MinRequiredPasswordLength);
+ Assert.AreEqual(provider.DefaultMinNonAlphanumericChars, provider.MinRequiredNonAlphanumericCharacters);
+ Assert.AreEqual(null, provider.PasswordStrengthRegularExpression);
+ Assert.AreEqual(provider.DefaultUseLegacyEncoding, provider.UseLegacyEncoding);
+ Assert.AreEqual(MembershipPasswordFormat.Hashed, provider.PasswordFormat);
+ }
+
+ [Test]
+ public void Throws_Exception_With_Hashed_Password_And_Password_Retrieval()
+ {
+ var provider = new TestProvider();
+
+ Assert.Throws(() => provider.Initialize("test", new NameValueCollection()
+ {
+ {"enablePasswordRetrieval", "true"},
+ {"passwordFormat", "Hashed"}
+ }));
+ }
+
[TestCase("hello", 0, "", 5, true)]
[TestCase("hello", 0, "", 4, true)]
[TestCase("hello", 0, "", 6, false)]
@@ -65,5 +109,88 @@ namespace Umbraco.Tests.Membership
Assert.AreEqual(salt, initSalt);
}
+ private class TestProvider : MembershipProviderBase
+ {
+ public override string GetPassword(string username, string answer)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override string ResetPassword(string username, string answer)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override void UpdateUser(MembershipUser user)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override bool ValidateUser(string username, string password)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override bool UnlockUser(string userName)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override MembershipUser GetUser(string username, bool userIsOnline)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override string GetUserNameByEmail(string email)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override bool DeleteUser(string username, bool deleteAllRelatedData)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override int GetNumberOfUsersOnline()
+ {
+ throw new NotImplementedException();
+ }
+
+ public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override bool PerformChangePassword(string username, string oldPassword, string newPassword)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override bool PerformChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override MembershipUser PerformCreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
}
}
diff --git a/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs b/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs
index f423d95fbd..23ee46fabc 100644
--- a/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs
+++ b/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs
@@ -11,6 +11,8 @@ using System.Web.Security;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
+using Umbraco.Core.Persistence.Querying;
+using Umbraco.Core.Security;
using Umbraco.Core.Services;
using Umbraco.Core.Models.Membership;
@@ -19,25 +21,8 @@ namespace Umbraco.Web.Security.Providers
///
/// Custom Membership Provider for Umbraco Members (User authentication for Frontend applications NOT umbraco CMS)
///
- internal class MembersMembershipProvider : MembershipProvider
+ internal class MembersMembershipProvider : UmbracoMembershipProviderBase
{
- #region Fields
- private string _applicationName;
- private bool _enablePasswordReset;
- private bool _enablePasswordRetrieval;
- private int _maxInvalidPasswordAttempts;
- private int _minRequiredNonAlphanumericCharacters;
- private int _minRequiredPasswordLength;
- private int _passwordAttemptWindow;
-
- private MembershipPasswordFormat _passwordFormat;
-
- private string _passwordStrengthRegularExpression;
- private bool _requiresQuestionAndAnswer;
- private bool _requiresUniqueEmail;
-
- #endregion
-
private IMembershipMemberService _memberService;
protected IMembershipMemberService MemberService
@@ -45,125 +30,8 @@ namespace Umbraco.Web.Security.Providers
get { return _memberService ?? (_memberService = ApplicationContext.Current.Services.MemberService); }
}
- ///
- /// The name of the application using the custom membership provider.
- ///
- ///
- /// The name of the application using the custom membership provider.
- public override string ApplicationName
+ public string ProviderName
{
- get { return _applicationName; }
- set { _applicationName = value; }
- }
-
- ///
- /// Indicates whether the membership provider is configured to allow users to reset their passwords.
- ///
- ///
- /// true if the membership provider supports password reset; otherwise, false. The default is true.
- public override bool EnablePasswordReset
- {
- get { return _enablePasswordReset; }
- }
-
- ///
- /// Indicates whether the membership provider is configured to allow users to retrieve their passwords.
- ///
- ///
- /// true if the membership provider is configured to support password retrieval; otherwise, false. The default is false.
- public override bool EnablePasswordRetrieval
- {
- get { return _enablePasswordRetrieval; }
- }
-
- ///
- /// Gets the number of invalid password or password-answer attempts allowed before the membership user is locked out.
- ///
- ///
- /// The number of invalid password or password-answer attempts allowed before the membership user is locked out.
- public override int MaxInvalidPasswordAttempts
- {
- get { return _maxInvalidPasswordAttempts; }
- }
-
- ///
- /// Gets the minimum number of special characters that must be present in a valid password.
- ///
- ///
- /// The minimum number of special characters that must be present in a valid password.
- public override int MinRequiredNonAlphanumericCharacters
- {
- get { return _minRequiredNonAlphanumericCharacters; }
- }
-
- ///
- /// Gets the minimum length required for a password.
- ///
- ///
- /// The minimum length required for a password.
- public override int MinRequiredPasswordLength
- {
- get { return _minRequiredPasswordLength; }
- }
-
- ///
- /// Gets the number of minutes in which a maximum number of invalid password or password-answer attempts are allowed before the membership user is locked out.
- ///
- ///
- /// The number of minutes in which a maximum number of invalid password or password-answer attempts are allowed before the membership user is locked out.
- public override int PasswordAttemptWindow
- {
- get { return _passwordAttemptWindow; }
- }
-
- ///
- /// Gets a value indicating the format for storing passwords in the membership data store.
- ///
- ///
- /// One of the values indicating the format for storing passwords in the data store.
- public override MembershipPasswordFormat PasswordFormat
- {
- get { return _passwordFormat; }
- }
-
- ///
- /// Gets the regular expression used to evaluate a password.
- ///
- ///
- /// A regular expression used to evaluate a password.
- public override string PasswordStrengthRegularExpression
- {
- get { return _passwordStrengthRegularExpression; }
- }
-
- ///
- /// Gets a value indicating whether the membership provider is configured to require the user to answer a password question for password reset and retrieval.
- ///
- ///
- /// true if a password answer is required for password reset and retrieval; otherwise, false. The default is true.
- public override bool RequiresQuestionAndAnswer
- {
- get { return _requiresQuestionAndAnswer; }
- }
-
- ///
- /// Gets a value indicating whether the membership provider is configured to require a unique e-mail address for each user name.
- ///
- ///
- /// true if the membership provider requires a unique e-mail address; otherwise, false. The default is true.
- public override bool RequiresUniqueEmail
- {
- get { return _requiresUniqueEmail; }
- }
-
- ///
- /// The default Umbraco member type alias to create when registration is performed using .net Membership
- ///
- ///
- /// Member type alias
- public string DefaultMemberTypeAlias { get; private set; }
-
- public string ProviderName {
get { return "MembersMembershipProvider"; }
}
@@ -186,80 +54,127 @@ namespace Umbraco.Web.Security.Providers
// Initialize base provider class
base.Initialize(name, config);
- _applicationName = string.IsNullOrEmpty(config["applicationName"]) ? GetDefaultAppName() : config["applicationName"];
+ //// test for membertype (if not specified, choose the first member type available)
+ //if (config["defaultMemberTypeAlias"] != null)
+ // _defaultMemberTypeAlias = config["defaultMemberTypeAlias"];
+ //else if (MemberType.GetAll.Length == 1)
+ // _defaultMemberTypeAlias = MemberType.GetAll[0].Alias;
+ //else
+ // throw new ProviderException("No default MemberType alias is specified in the web.config string. Please add a 'defaultMemberTypeAlias' to the add element in the provider declaration in web.config");
- _enablePasswordRetrieval = GetBooleanValue(config, "enablePasswordRetrieval", false);
- _enablePasswordReset = GetBooleanValue(config, "enablePasswordReset", false);
- _requiresQuestionAndAnswer = GetBooleanValue(config, "requiresQuestionAndAnswer", false);
- _requiresUniqueEmail = GetBooleanValue(config, "requiresUniqueEmail", true);
- _maxInvalidPasswordAttempts = GetIntValue(config, "maxInvalidPasswordAttempts", 5, false, 0);
- _passwordAttemptWindow = GetIntValue(config, "passwordAttemptWindow", 10, false, 0);
- _minRequiredPasswordLength = GetIntValue(config, "minRequiredPasswordLength", 7, true, 0x80);
- _minRequiredNonAlphanumericCharacters = GetIntValue(config, "minRequiredNonalphanumericCharacters", 1, true, 0x80);
- _passwordStrengthRegularExpression = config["passwordStrengthRegularExpression"];
-
- // make sure password format is Hashed by default.
- var str = config["passwordFormat"] ?? "Hashed";
-
- LogHelper.Debug("Loaded membership provider properties");
- LogHelper.Debug(ToString());
-
- switch (str.ToLower())
+ // test for approve status
+ if (config["umbracoApprovePropertyTypeAlias"] != null)
{
- case "clear":
- _passwordFormat = MembershipPasswordFormat.Clear;
- break;
- case "encrypted":
- _passwordFormat = MembershipPasswordFormat.Encrypted;
- break;
- case "hashed":
- _passwordFormat = MembershipPasswordFormat.Hashed;
- break;
- default:
- var e = new ProviderException("Provider bad password format");
- LogHelper.Error(e.Message, e);
- throw e;
+ ApprovedPropertyTypeAlias = config["umbracoApprovePropertyTypeAlias"];
}
-
- if ((PasswordFormat == MembershipPasswordFormat.Hashed) && EnablePasswordRetrieval)
+ // test for lock attempts
+ if (config["umbracoLockPropertyTypeAlias"] != null)
{
- var e = new ProviderException("Provider can not retrieve hashed password");
- LogHelper.Error(e.Message, e);
- throw e;
+ LockPropertyTypeAlias = config["umbracoLockPropertyTypeAlias"];
}
-
- // TODO: rationalise what happens when no member alias is specified....
- DefaultMemberTypeAlias = config["defaultMemberTypeAlias"];
-
- LogHelper.Debug("Finished initialising member ship provider " + GetType().FullName);
+ if (config["umbracoLastLockedPropertyTypeAlias"] != null)
+ {
+ LastLockedOutPropertyTypeAlias = config["umbracoLastLockedPropertyTypeAlias"];
+ }
+ if (config["umbracoLastPasswordChangedPropertyTypeAlias"] != null)
+ {
+ LastPasswordChangedPropertyTypeAlias = config["umbracoLastPasswordChangedPropertyTypeAlias"];
+ }
+ if (config["umbracoFailedPasswordAttemptsPropertyTypeAlias"] != null)
+ {
+ FailedPasswordAttemptsPropertyTypeAlias = config["umbracoFailedPasswordAttemptsPropertyTypeAlias"];
+ }
+ // comment property
+ if (config["umbracoCommentPropertyTypeAlias"] != null)
+ {
+ CommentPropertyTypeAlias = config["umbracoCommentPropertyTypeAlias"];
+ }
+ // last login date
+ if (config["umbracoLastLoginPropertyTypeAlias"] != null)
+ {
+ LastLoginPropertyTypeAlias = config["umbracoLastLoginPropertyTypeAlias"];
+ }
+ // password retrieval
+ if (config["umbracoPasswordRetrievalQuestionPropertyTypeAlias"] != null)
+ {
+ PasswordRetrievalQuestionPropertyTypeAlias = config["umbracoPasswordRetrievalQuestionPropertyTypeAlias"];
+ }
+ if (config["umbracoPasswordRetrievalAnswerPropertyTypeAlias"] != null)
+ {
+ PasswordRetrievalAnswerPropertyTypeAlias = config["umbracoPasswordRetrievalAnswerPropertyTypeAlias"];
+ }
}
- public override string ToString()
+ ///
+ /// Processes a request to update the password for a membership user.
+ ///
+ /// The user to update the password for.
+ /// This property is ignore for this provider
+ /// The new password for the specified user.
+ ///
+ /// true if the password was updated successfully; otherwise, false.
+ ///
+ protected override bool PerformChangePassword(string username, string oldPassword, string newPassword)
{
- var result = base.ToString();
+ //NOTE: due to backwards compatibilty reasons (and UX reasons), this provider doesn't care about the old password and
+ // allows simply setting the password manually so we don't really care about the old password.
+ // This is allowed based on the overridden AllowManuallyChangingPassword option.
- result += "_applicationName =" + _applicationName + Environment.NewLine;
- result += "_enablePasswordReset=" + _enablePasswordReset + Environment.NewLine;
- result += "_enablePasswordRetrieval=" + _enablePasswordRetrieval + Environment.NewLine;
- result += "_maxInvalidPasswordAttempts=" + _maxInvalidPasswordAttempts + Environment.NewLine;
- result += "_minRequiredNonAlphanumericCharacters=" + _minRequiredNonAlphanumericCharacters + Environment.NewLine;
- result += "_minRequiredPasswordLength=" + _minRequiredPasswordLength + Environment.NewLine;
- result += "_passwordAttemptWindow=" + _passwordAttemptWindow + Environment.NewLine;
+ // in order to support updating passwords from the umbraco core, we can't validate the old password
+ var m = _memberService.GetByUsername(username);
+ if (m == null) return false;
- result += "_passwordFormat=" + _passwordFormat + Environment.NewLine;
+ var args = new ValidatePasswordEventArgs(username, newPassword, false);
+ OnValidatingPassword(args);
- result += "_passwordStrengthRegularExpression=" + _passwordStrengthRegularExpression + Environment.NewLine;
- result += "_requiresQuestionAndAnswer=" + _requiresQuestionAndAnswer + Environment.NewLine;
- result += "_requiresUniqueEmail=" + _requiresUniqueEmail + Environment.NewLine;
- result += "DefaultMemberTypeAlias=" + DefaultMemberTypeAlias + Environment.NewLine;
+ if (args.Cancel)
+ {
+ if (args.FailureInformation != null)
+ throw args.FailureInformation;
+ throw new MembershipPasswordException("Change password canceled due to password validation failure.");
+ }
- return result;
+ string salt;
+ var encodedPassword = EncryptOrHashNewPassword(newPassword, out salt);
+
+ m.Password = FormatPasswordForStorage(encodedPassword, salt);
+ m.LastPasswordChangeDate = DateTime.Now;
+
+ _memberService.Save(m);
+
+ return true;
+ }
+
+ ///
+ /// Processes a request to update the password question and answer for a membership user.
+ ///
+ /// The user to change the password question and answer for.
+ /// The password for the specified user.
+ /// The new password question for the specified user.
+ /// The new password answer for the specified user.
+ ///
+ /// true if the password question and answer are updated successfully; otherwise, false.
+ ///
+ protected override bool PerformChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
+ {
+ var member = MemberService.GetByUsername(username);
+ if (member == null)
+ {
+ return false;
+ }
+
+ member.PasswordQuestion = newPasswordQuestion;
+ member.PasswordAnswer = newPasswordAnswer;
+
+ MemberService.Save(member);
+
+ return true;
}
///
/// Adds a new membership user to the data source with the specified member type
///
- /// A specific member type to create the member for
+ /// A specific member type to create the member for
/// The user name for the new user.
/// The password for the new user.
/// The e-mail address for the new user.
@@ -271,48 +186,11 @@ namespace Umbraco.Web.Security.Providers
///
/// A object populated with the information for the newly created user.
///
- public MembershipUser CreateUser(string memberType, string username, string password, string email, string passwordQuestion, string passwordAnswer,
- bool isApproved, object providerUserKey, out MembershipCreateStatus status)
+ protected override MembershipUser PerformCreateUser(string memberTypeAlias, string username, string password, string email, string passwordQuestion,
+ string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
{
- LogHelper.Debug("Member signup requested: username -> " + username + ". email -> " + email);
-
- // Validate password
- if (IsPasswordValid(password) == false)
- {
- status = MembershipCreateStatus.InvalidPassword;
- return null;
- }
-
- // Validate email
- if (IsEmaiValid(email) == false)
- {
- status = MembershipCreateStatus.InvalidEmail;
- return null;
- }
-
- // Make sure username isn't all whitespace
- if (string.IsNullOrWhiteSpace(username.Trim()))
- {
- status = MembershipCreateStatus.InvalidUserName;
- return null;
- }
-
- // Check password question
- if (string.IsNullOrWhiteSpace(passwordQuestion) && _requiresQuestionAndAnswer)
- {
- status = MembershipCreateStatus.InvalidQuestion;
- return null;
- }
-
- // Check password answer
- if (string.IsNullOrWhiteSpace(passwordAnswer) && _requiresQuestionAndAnswer)
- {
- status = MembershipCreateStatus.InvalidAnswer;
- return null;
- }
-
// See if the user already exists
- if (MemberService.GetByUsername(username) != null)
+ if (MemberService.Exists(username))
{
status = MembershipCreateStatus.DuplicateUserName;
LogHelper.Warn("Cannot create member as username already exists: " + username);
@@ -328,14 +206,16 @@ namespace Umbraco.Web.Security.Providers
return null;
}
- var member = MemberService.CreateMember(email, username, password, memberType);
+ string salt;
+ var encodedPassword = EncryptOrHashNewPassword(password, out salt);
- member.IsApproved = isApproved;
+ var member = MemberService.CreateMember(email, username, encodedPassword, memberTypeAlias);
+
member.PasswordQuestion = passwordQuestion;
member.PasswordAnswer = passwordAnswer;
-
- //encrypts/hashes the password depending on the settings
- member.Password = EncryptOrHashPassword(member.Password);
+ member.IsApproved = isApproved;
+ member.LastLoginDate = DateTime.Now;
+ member.LastPasswordChangeDate = DateTime.Now;
MemberService.Save(member);
@@ -344,68 +224,72 @@ namespace Umbraco.Web.Security.Providers
}
///
- /// Adds a new membership user to the data source.
+ /// Removes a user from the membership data source.
///
- /// The user name for the new user.
- /// The password for the new user.
- /// The e-mail address for the new user.
- /// The password question for the new user.
- /// The password answer for the new user
- /// Whether or not the new user is approved to be validated.
- /// The unique identifier from the membership data source for the user.
- /// A enumeration value indicating whether the user was created successfully.
+ /// The name of the user to delete.
+ ///
+ /// TODO: This setting currently has no effect
+ ///
///
- /// A object populated with the information for the newly created user.
+ /// true if the user was successfully deleted; otherwise, false.
///
- public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer,
- bool isApproved, object providerUserKey, out MembershipCreateStatus status)
+ public override bool DeleteUser(string username, bool deleteAllRelatedData)
{
- return CreateUser(DefaultMemberTypeAlias, username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
+ var member = MemberService.GetByUsername(username);
+ if (member == null) return false;
+
+ MemberService.Delete(member);
+ return true;
}
///
- /// Processes a request to update the password question and answer for a membership user.
+ /// Gets a collection of membership users where the e-mail address contains the specified e-mail address to match.
///
- /// The user to change the password question and answer for.
- /// The password for the specified user.
- /// The new password question for the specified user.
- /// The new password answer for the specified user.
+ /// The e-mail address to search for.
+ /// The index of the page of results to return. pageIndex is zero-based.
+ /// The size of the page of results to return.
+ /// The total number of matched users.
///
- /// true if the password question and answer are updated successfully; otherwise, false.
+ /// A collection that contains a page of pageSize objects beginning at the page specified by pageIndex.
///
- public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion,
- string newPasswordAnswer)
+ public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
{
- if (_requiresQuestionAndAnswer == false)
+ var byEmail = MemberService.FindMembersByEmail(emailToMatch, StringPropertyMatchType.Wildcard).ToArray();
+ totalRecords = byEmail.Length;
+ var pagedResult = new PagedResult(totalRecords, pageIndex, pageSize);
+
+ var collection = new MembershipUserCollection();
+ foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize))
{
- throw new NotSupportedException("Updating the password Question and Answer is not available if requiresQuestionAndAnswer is not set in web.config");
+ collection.Add(m.AsConcreteMembershipUser());
}
-
- if (ValidateUser(username, password) == false)
- {
- throw new MembershipPasswordException("Invalid username and password combinatio");
- }
-
- var member = MemberService.GetByUsername(username);
- var encodedPassword = EncryptOrHashPassword(password);
-
- if (member.Password == encodedPassword)
- {
- member.PasswordQuestion = newPasswordQuestion;
- member.PasswordAnswer = newPasswordAnswer;
-
- MemberService.Save(member);
-
- return true;
- }
- else
- {
- //TODO: Throw here? or just return false;
- }
-
- return false;
+ return collection;
}
+ ///
+ /// Gets a collection of membership users where the user name contains the specified user name to match.
+ ///
+ /// The user name to search for.
+ /// The index of the page of results to return. pageIndex is zero-based.
+ /// The size of the page of results to return.
+ /// The total number of matched users.
+ ///
+ /// A collection that contains a page of pageSize objects beginning at the page specified by pageIndex.
+ ///
+ public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
+ {
+ var byEmail = MemberService.FindMembersByUsername(usernameToMatch, StringPropertyMatchType.Wildcard).ToArray();
+ totalRecords = byEmail.Length;
+ var pagedResult = new PagedResult(totalRecords, pageIndex, pageSize);
+
+ var collection = new MembershipUserCollection();
+ foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize))
+ {
+ collection.Add(m.AsConcreteMembershipUser());
+ }
+ return collection;
+ }
+
///
/// Gets the password for the specified user name from the data source.
///
@@ -416,59 +300,22 @@ namespace Umbraco.Web.Security.Providers
///
public override string GetPassword(string username, string answer)
{
- if (_enablePasswordRetrieval == false)
+ if (EnablePasswordRetrieval == false)
throw new ProviderException("Password Retrieval Not Enabled.");
- if (_passwordFormat == MembershipPasswordFormat.Hashed)
+ if (PasswordFormat == MembershipPasswordFormat.Hashed)
throw new ProviderException("Cannot retrieve Hashed passwords.");
var member = MemberService.GetByUsername(username);
- if (_requiresQuestionAndAnswer && member.PasswordAnswer != answer)
+ if (RequiresQuestionAndAnswer && member.PasswordAnswer != answer)
{
throw new ProviderException("Password retrieval answer doesn't match");
}
return member.Password;
}
-
- ///
- /// Processes a request to update the password for a membership user.
- ///
- /// The user to update the password for.
- /// The current password for the specified user.
- /// The new password for the specified user.
- ///
- /// true if the password was updated successfully; otherwise, false.
- ///
- public override bool ChangePassword(string username, string oldPassword, string newPassword)
- {
- // Validate new password
- if (IsPasswordValid(newPassword) == false)
- {
- var e = new MembershipPasswordException("Change password canceled due to new password validation failure.");
- LogHelper.WarnWithException(e.Message, e);
- throw e;
- }
-
- var member = MemberService.GetByUsername(username);
- if (member == null) return false;
-
- var encodedPassword = EncryptOrHashPassword(oldPassword);
-
- if (member.Password == encodedPassword)
- {
-
- member.Password = EncryptOrHashPassword(newPassword);
- MemberService.Save(member);
-
- return true;
- }
-
- LogHelper.Warn("Can't change password as old password was incorrect");
- return false;
- }
-
+
///
/// Resets a user's password to a new, automatically generated password.
///
@@ -477,30 +324,34 @@ namespace Umbraco.Web.Security.Providers
/// The new password for the specified user.
public override string ResetPassword(string username, string answer)
{
- if (_enablePasswordReset == false)
- throw new ProviderException("Password reset is Not Enabled.");
+ //TODO: Get logic from other provider
- var member = MemberService.GetByUsername(username);
+ throw new NotImplementedException();
- if (member == null)
- throw new ProviderException("The supplied user is not found");
+ //if (EnablePasswordReset == false)
+ // throw new ProviderException("Password reset is Not Enabled.");
- if(member.IsLockedOut)
- throw new ProviderException("The member is locked out.");
+ //var member = MemberService.GetByUsername(username);
- if (_requiresQuestionAndAnswer == false || (_requiresQuestionAndAnswer && answer == member.PasswordAnswer))
- {
- member.Password =
- EncryptOrHashPassword(Membership.GeneratePassword(_minRequiredPasswordLength,
- _minRequiredNonAlphanumericCharacters));
- MemberService.Save(member);
- }
- else
- {
- throw new MembershipPasswordException("Incorrect password answer");
- }
+ //if (member == null)
+ // throw new ProviderException("The supplied user is not found");
+
+ //if(member.IsLockedOut)
+ // throw new ProviderException("The member is locked out.");
+
+ //if (RequiresQuestionAndAnswer == false || (RequiresQuestionAndAnswer && answer == member.PasswordAnswer))
+ //{
+ // member.Password =
+ // EncryptOrHashPassword(Membership.GeneratePassword(MinRequiredPasswordLength,
+ // MinRequiredNonAlphanumericCharacters));
+ // MemberService.Save(member);
+ //}
+ //else
+ //{
+ // throw new MembershipPasswordException("Incorrect password answer");
+ //}
- return null;
+ //return null;
}
///
@@ -511,8 +362,8 @@ namespace Umbraco.Web.Security.Providers
/// A object that represents the user to update and the updated information for the user.
public override void UpdateUser(MembershipUser user)
{
- var member = user.AsIMember();
- MemberService.Save(member);
+ //var member = user.AsIMember();
+ //MemberService.Save(member);
}
///
@@ -532,7 +383,8 @@ namespace Umbraco.Web.Security.Providers
if (member.IsLockedOut)
throw new ProviderException("The member is locked out.");
- var encodedPassword = EncryptOrHashPassword(password);
+ string salt;
+ var encodedPassword = EncryptOrHashNewPassword(password, out salt);
var authenticated = (encodedPassword == member.Password);
@@ -645,22 +497,7 @@ namespace Umbraco.Web.Security.Providers
return member == null ? null : member.Username;
}
- ///
- /// Removes a user from the membership data source.
- ///
- /// The name of the user to delete.
- /// true to delete data related to the user from the database; false to leave data related to the user in the database.
- ///
- /// true if the user was successfully deleted; otherwise, false.
- ///
- public override bool DeleteUser(string username, bool deleteAllRelatedData)
- {
- var member = MemberService.GetByUsername(username);
- if (member == null) return false;
-
- MemberService.Delete(member);
- return true;
- }
+
///
/// Gets a collection of all the users in the data source in pages of data.
@@ -687,182 +524,14 @@ namespace Umbraco.Web.Security.Providers
throw new System.NotImplementedException();
}
- ///
- /// Gets a collection of membership users where the user name contains the specified user name to match.
- ///
- /// The user name to search for.
- /// The index of the page of results to return. pageIndex is zero-based.
- /// The size of the page of results to return.
- /// The total number of matched users.
- ///
- /// A collection that contains a page of pageSize objects beginning at the page specified by pageIndex.
- ///
- public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
+
+ public override string ToString()
{
- throw new System.NotImplementedException();
+ var result = base.ToString();
+ var sb = new StringBuilder(result);
+ sb.AppendLine("DefaultMemberTypeAlias=" + DefaultMemberTypeAlias);
+ return sb.ToString();
}
- ///
- /// Gets a collection of membership users where the e-mail address contains the specified e-mail address to match.
- ///
- /// The e-mail address to search for.
- /// The index of the page of results to return. pageIndex is zero-based.
- /// The size of the page of results to return.
- /// The total number of matched users.
- ///
- /// A collection that contains a page of pageSize objects beginning at the page specified by pageIndex.
- ///
- public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
- {
- var byEmail = MemberService.FindMembersByEmail(emailToMatch).ToArray();
- totalRecords = byEmail.Length;
- var pagedResult = new PagedResult(totalRecords, pageIndex, pageSize);
-
- var collection = new MembershipUserCollection();
- foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize))
- {
- collection.Add(m.AsConcreteMembershipUser());
- }
- return collection;
- }
-
- #region Private methods
-
- private bool IsPasswordValid(string password)
- {
- if (_minRequiredNonAlphanumericCharacters > 0)
- {
- var nonAlphaNumeric = Regex.Replace(password, "[a-zA-Z0-9]", "", RegexOptions.Multiline | RegexOptions.IgnoreCase);
- if (nonAlphaNumeric.Length < _minRequiredNonAlphanumericCharacters)
- {
- return false;
- }
- }
-
- var valid = true;
- if(string.IsNullOrEmpty(_passwordStrengthRegularExpression) == false)
- {
- valid = Regex.IsMatch(password, _passwordStrengthRegularExpression, RegexOptions.Compiled);
- }
-
- return valid && password.Length >= _minRequiredPasswordLength;
- }
-
- private bool IsEmaiValid(string email)
- {
- const string pattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|"
- + @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?
- /// Encodes the password.
- ///
- /// The password.
- /// The encoded password.
- private string EncryptOrHashPassword(string password)
- {
- var encodedPassword = password;
- switch (PasswordFormat)
- {
- case MembershipPasswordFormat.Clear:
- break;
- case MembershipPasswordFormat.Encrypted:
- encodedPassword =
- Convert.ToBase64String(EncryptPassword(Encoding.Unicode.GetBytes(password)));
- break;
- case MembershipPasswordFormat.Hashed:
- var hash = new HMACSHA1 {Key = Encoding.Unicode.GetBytes(password)};
- encodedPassword =
- Convert.ToBase64String(hash.ComputeHash(Encoding.Unicode.GetBytes(password)));
- break;
- default:
- throw new ProviderException("Unsupported password format.");
- }
- return encodedPassword;
- }
-
- ///
- /// Gets the boolean value.
- ///
- /// The config.
- /// Name of the value.
- /// if set to true [default value].
- ///
- private bool GetBooleanValue(NameValueCollection config, string valueName, bool defaultValue)
- {
- bool flag;
- var str = config[valueName];
- if (str == null)
- return defaultValue;
-
- if (bool.TryParse(str, out flag) == false)
- {
- throw new ProviderException("Value must be boolean.");
- }
- return flag;
- }
-
- ///
- /// Gets the int value.
- ///
- /// The config.
- /// Name of the value.
- /// The default value.
- /// if set to true [zero allowed].
- /// The max value allowed.
- ///
- private int GetIntValue(NameValueCollection config, string valueName, int defaultValue, bool zeroAllowed, int maxValueAllowed)
- {
- int num;
- var s = config[valueName];
- if (s == null)
- {
- return defaultValue;
- }
- if (int.TryParse(s, out num) == false)
- {
- if (zeroAllowed)
- {
- throw new ProviderException("Value must be non negative integer");
- }
- throw new ProviderException("Value must be positive integer");
- }
- if (zeroAllowed && (num < 0))
- {
- throw new ProviderException("Value must be non negativeinteger");
- }
- if (zeroAllowed == false && (num <= 0))
- {
- throw new ProviderException("Value must be positive integer");
- }
- if ((maxValueAllowed > 0) && (num > maxValueAllowed))
- {
- throw new ProviderException("Value too big");
- }
- return num;
- }
-
-
- ///
- /// Gets the name of the default app.
- ///
- ///
- private string GetDefaultAppName()
- {
- try
- {
- var applicationVirtualPath = HostingEnvironment.ApplicationVirtualPath;
- return string.IsNullOrEmpty(applicationVirtualPath) ? "/" : applicationVirtualPath;
- }
- catch
- {
- return "/";
- }
- }
-
- #endregion
}
}
\ No newline at end of file
diff --git a/src/umbraco.providers/UsersMembershipProvider.cs b/src/umbraco.providers/UsersMembershipProvider.cs
index 278aff9871..e862bf5b19 100644
--- a/src/umbraco.providers/UsersMembershipProvider.cs
+++ b/src/umbraco.providers/UsersMembershipProvider.cs
@@ -22,7 +22,7 @@ namespace umbraco.providers
///
/// Override to maintain backwards compatibility with 0 required non-alphanumeric chars
///
- protected override int DefaultMinNonAlphanumericChars
+ public override int DefaultMinNonAlphanumericChars
{
get { return 0; }
}
@@ -30,7 +30,7 @@ namespace umbraco.providers
///
/// Override to maintain backwards compatibility with only 4 required length
///
- protected override int DefaultMinPasswordLength
+ public override int DefaultMinPasswordLength
{
get { return 4; }
}
@@ -38,7 +38,7 @@ namespace umbraco.providers
///
/// Override to maintain backwards compatibility
///
- protected override bool DefaultUseLegacyEncoding
+ public override bool DefaultUseLegacyEncoding
{
get { return true; }
}
@@ -110,7 +110,7 @@ namespace umbraco.providers
///
/// true if the password question and answer are updated successfully; otherwise, false.
///
- public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
+ protected override bool PerformChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
{
throw new Exception("The method or operation is not implemented.");
}
@@ -129,7 +129,7 @@ namespace umbraco.providers
///
/// A object populated with the information for the newly created user.
///
- public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
+ protected override MembershipUser PerformCreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
{
var args = new ValidatePasswordEventArgs(username, password, true);
OnValidatingPassword(args);
diff --git a/src/umbraco.providers/members/MembersMembershipProvider.cs b/src/umbraco.providers/members/UmbracoMembershipProvider.cs
similarity index 71%
rename from src/umbraco.providers/members/MembersMembershipProvider.cs
rename to src/umbraco.providers/members/UmbracoMembershipProvider.cs
index a14b47d84d..62562a85b0 100644
--- a/src/umbraco.providers/members/MembersMembershipProvider.cs
+++ b/src/umbraco.providers/members/UmbracoMembershipProvider.cs
@@ -1,1031 +1,958 @@
-#region namespace
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Web.Security;
-using System.Configuration;
-using Umbraco.Core;
-using Umbraco.Core.Models;
-using Umbraco.Core.Security;
-using umbraco.BusinessLogic;
-using System.Security.Cryptography;
-using System.Web.Util;
-using System.Collections.Specialized;
-using System.Configuration.Provider;
-using System.Security;
-using System.Security.Permissions;
-using System.Runtime.CompilerServices;
-using Member = umbraco.cms.businesslogic.member.Member;
-using MemberType = umbraco.cms.businesslogic.member.MemberType;
-
-#endregion
-
-namespace umbraco.providers.members
-{
- ///
- /// Custom Membership Provider for Umbraco Members (User authentication for Frontend applications NOT umbraco CMS)
- ///
-
- public class UmbracoMembershipProvider : MembershipProviderBase
- {
- #region Fields
-
- //Set the defaults!
- private string _defaultMemberTypeAlias = "Member";
- private string _lockPropertyTypeAlias = Constants.Conventions.Member.IsLockedOut;
- private string _lastLockedOutPropertyTypeAlias = Constants.Conventions.Member.LastLockoutDate;
- private string _failedPasswordAttemptsPropertyTypeAlias = Constants.Conventions.Member.FailedPasswordAttempts;
- private string _approvedPropertyTypeAlias = Constants.Conventions.Member.IsApproved;
- private string _commentPropertyTypeAlias = Constants.Conventions.Member.Comments;
- private string _lastLoginPropertyTypeAlias = Constants.Conventions.Member.LastLoginDate;
- private string _lastPasswordChangedPropertyTypeAlias = Constants.Conventions.Member.LastPasswordChangeDate;
- private string _passwordRetrievalQuestionPropertyTypeAlias = Constants.Conventions.Member.PasswordQuestion;
- private string _passwordRetrievalAnswerPropertyTypeAlias = Constants.Conventions.Member.PasswordAnswer;
-
- private string _providerName = Member.UmbracoMemberProviderName;
-
- //Need to expose these publicly so we know what field aliases to use in the editor, we only care about these 3 fields
- // because they are the only 'settable' provider properties that are not stored against the IMember directly (i.e. they are
- // property type properties).
-
- public string LockPropertyTypeAlias
- {
- get { return _lockPropertyTypeAlias; }
- }
-
- public string ApprovedPropertyTypeAlias
- {
- get { return _approvedPropertyTypeAlias; }
- }
-
- public string CommentPropertyTypeAlias
- {
- get { return _commentPropertyTypeAlias; }
- }
-
- #endregion
-
- ///
- /// Override to maintain backwards compatibility with 0 required non-alphanumeric chars
- ///
- protected override int DefaultMinNonAlphanumericChars
- {
- get { return 0; }
- }
-
- ///
- /// Override to maintain backwards compatibility with only 4 required length
- ///
- protected override int DefaultMinPasswordLength
- {
- get { return 4; }
- }
-
- ///
- /// Override to maintain backwards compatibility
- ///
- protected override bool DefaultUseLegacyEncoding
- {
- get { return true; }
- }
-
- ///
- /// For backwards compatibility, this provider supports this option
- ///
- internal override bool AllowManuallyChangingPassword
- {
- get { return true; }
- }
-
- #region Initialization Method
- ///
- /// Initializes the provider.
- ///
- /// The friendly name of the provider.
- /// A collection of the name/value pairs representing the provider-specific attributes specified in the configuration for this provider.
- /// The name of the provider is null.
- /// An attempt is made to call
- /// on a provider after the provider
- /// has already been initialized.
- /// The name of the provider has a length of zero.
- public override void Initialize(string name, NameValueCollection config)
- {
- // Intialize values from web.config
- if (config == null) throw new ArgumentNullException("config");
-
- if (string.IsNullOrEmpty(name)) name = "UmbracoMembershipProvider";
-
- base.Initialize(name, config);
-
- _providerName = name;
-
- // test for membertype (if not specified, choose the first member type available)
- if (config["defaultMemberTypeAlias"] != null)
- _defaultMemberTypeAlias = config["defaultMemberTypeAlias"];
- else if (MemberType.GetAll.Length == 1)
- _defaultMemberTypeAlias = MemberType.GetAll[0].Alias;
- else
- throw new ProviderException("No default MemberType alias is specified in the web.config string. Please add a 'defaultMemberTypeAlias' to the add element in the provider declaration in web.config");
-
- // test for approve status
- if (config["umbracoApprovePropertyTypeAlias"] != null)
- {
- _approvedPropertyTypeAlias = config["umbracoApprovePropertyTypeAlias"];
- }
- // test for lock attempts
- if (config["umbracoLockPropertyTypeAlias"] != null)
- {
- _lockPropertyTypeAlias = config["umbracoLockPropertyTypeAlias"];
- }
- if (config["umbracoLastLockedPropertyTypeAlias"] != null)
- {
- _lastLockedOutPropertyTypeAlias = config["umbracoLastLockedPropertyTypeAlias"];
- }
- if (config["umbracoLastPasswordChangedPropertyTypeAlias"] != null)
- {
- _lastPasswordChangedPropertyTypeAlias = config["umbracoLastPasswordChangedPropertyTypeAlias"];
- }
- if (config["umbracoFailedPasswordAttemptsPropertyTypeAlias"] != null)
- {
- _failedPasswordAttemptsPropertyTypeAlias = config["umbracoFailedPasswordAttemptsPropertyTypeAlias"];
- }
- // comment property
- if (config["umbracoCommentPropertyTypeAlias"] != null)
- {
- _commentPropertyTypeAlias = config["umbracoCommentPropertyTypeAlias"];
- }
- // last login date
- if (config["umbracoLastLoginPropertyTypeAlias"] != null)
- {
- _lastLoginPropertyTypeAlias = config["umbracoLastLoginPropertyTypeAlias"];
- }
- // password retrieval
- if (config["umbracoPasswordRetrievalQuestionPropertyTypeAlias"] != null)
- {
- _passwordRetrievalQuestionPropertyTypeAlias = config["umbracoPasswordRetrievalQuestionPropertyTypeAlias"];
- }
- if (config["umbracoPasswordRetrievalAnswerPropertyTypeAlias"] != null)
- {
- _passwordRetrievalAnswerPropertyTypeAlias = config["umbracoPasswordRetrievalAnswerPropertyTypeAlias"];
- }
-
- }
- #endregion
-
- #region Methods
-
- ///
- /// Processes a request to update the password for a membership user.
- ///
- /// The user to update the password for.
- /// This property is ignore for this provider
- /// The new password for the specified user.
- ///
- /// true if the password was updated successfully; otherwise, false.
- ///
- protected override bool PerformChangePassword(string username, string oldPassword, string newPassword)
- {
- //NOTE: due to backwards compatibilty reasons, this provider doesn't care about the old password and
- // allows simply setting the password manually so we don't really care about the old password.
- // This is allowed based on the overridden AllowManuallyChangingPassword option.
-
- // in order to support updating passwords from the umbraco core, we can't validate the old password
- var m = Member.GetMemberFromLoginName(username);
- if (m == null) return false;
-
- var args = new ValidatePasswordEventArgs(username, newPassword, false);
- OnValidatingPassword(args);
-
- if (args.Cancel)
- {
- if (args.FailureInformation != null)
- throw args.FailureInformation;
- throw new MembershipPasswordException("Change password canceled due to password validation failure.");
- }
-
- string salt;
- var encodedPassword = EncryptOrHashNewPassword(newPassword, out salt);
- m.ChangePassword(
- FormatPasswordForStorage(encodedPassword, salt));
-
- UpdateMemberProperty(m, _lastPasswordChangedPropertyTypeAlias, DateTime.Now);
-
- m.Save();
-
- return true;
- }
-
- ///
- /// Processes a request to update the password question and answer for a membership user.
- ///
- /// The user to change the password question and answer for.
- /// The password for the specified user.
- /// The new password question for the specified user.
- /// The new password answer for the specified user.
- ///
- /// true if the password question and answer are updated successfully; otherwise, false.
- ///
- public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
- {
- if (!String.IsNullOrEmpty(_passwordRetrievalQuestionPropertyTypeAlias) && !String.IsNullOrEmpty(_passwordRetrievalAnswerPropertyTypeAlias))
- {
- if (ValidateUser(username, password))
- {
- Member m = Member.GetMemberFromLoginName(username);
- if (m != null)
- {
- UpdateMemberProperty(m, _passwordRetrievalQuestionPropertyTypeAlias, newPasswordQuestion);
- UpdateMemberProperty(m, _passwordRetrievalAnswerPropertyTypeAlias, newPasswordAnswer);
- m.Save();
- return true;
- }
- else
- {
- throw new MembershipPasswordException("The supplied user is not found!");
- }
- }
- else {
- throw new MembershipPasswordException("Invalid user/password combo");
- }
-
- }
- else
- {
- throw new NotSupportedException("Updating the password Question and Answer is not valid if the properties aren't set in the config file");
- }
- }
-
- ///
- /// Adds a new membership user to the data source.
- ///
- ///
- /// The user name for the new user.
- /// The password for the new user.
- /// The e-mail address for the new user.
- /// The password question for the new user.
- /// The password answer for the new user
- /// Whether or not the new user is approved to be validated.
- /// The unique identifier from the membership data source for the user.
- /// A enumeration value indicating whether the user was created successfully.
- ///
- /// A object populated with the information for the newly created user.
- ///
- public MembershipUser CreateUser(string memberTypeAlias, string username, string password, string email, string passwordQuestion,
- string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
- {
-
- var args = new ValidatePasswordEventArgs(username, password, true);
- OnValidatingPassword(args);
- if (args.Cancel)
- {
- status = MembershipCreateStatus.InvalidPassword;
- return null;
- }
-
- if (Member.GetMemberFromLoginName(username) != null)
- {
- status = MembershipCreateStatus.DuplicateUserName;
- }
- else if (Member.GetMemberFromEmail(email) != null && RequiresUniqueEmail)
- {
- status = MembershipCreateStatus.DuplicateEmail;
- }
- else
- {
- var memberType = MemberType.GetByAlias(memberTypeAlias);
- if (memberType == null)
- {
- throw new InvalidOperationException("Could not find a member type with alias " + memberTypeAlias + ". Ensure your membership provider configuration is up to date and that the default member type exists.");
- }
-
- var m = Member.MakeNew(username, email, memberType, User.GetUser(0));
-
- string salt;
- var encodedPassword = EncryptOrHashNewPassword(password, out salt);
- //set the password on the member
- m.ChangePassword(
- FormatPasswordForStorage(encodedPassword, salt));
-
- // custom fields
- if (string.IsNullOrEmpty(_passwordRetrievalQuestionPropertyTypeAlias) == false)
- {
- UpdateMemberProperty(m, _passwordRetrievalQuestionPropertyTypeAlias, passwordQuestion);
- }
-
- if (string.IsNullOrEmpty(_passwordRetrievalAnswerPropertyTypeAlias) == false)
- {
- UpdateMemberProperty(m, _passwordRetrievalAnswerPropertyTypeAlias, passwordAnswer);
- }
-
- if (string.IsNullOrEmpty(ApprovedPropertyTypeAlias) == false)
- {
- UpdateMemberProperty(m, ApprovedPropertyTypeAlias, isApproved ? 1 : 0);
- }
-
- if (string.IsNullOrEmpty(_lastLoginPropertyTypeAlias) == false)
- {
- UpdateMemberProperty(m, _lastLoginPropertyTypeAlias, DateTime.Now);
- }
-
- if (string.IsNullOrEmpty(_lastPasswordChangedPropertyTypeAlias) == false)
- {
- UpdateMemberProperty(m, _lastPasswordChangedPropertyTypeAlias, DateTime.Now);
- }
-
- var mUser = ConvertToMembershipUser(m);
-
- // save
- m.Save();
-
- status = MembershipCreateStatus.Success;
-
- return mUser;
- }
- return null;
- }
-
- ///
- /// Adds a new membership user to the data source.
- ///
- /// The user name for the new user.
- /// The password for the new user.
- /// The e-mail address for the new user.
- /// The password question for the new user.
- /// The password answer for the new user
- /// Whether or not the new user is approved to be validated.
- /// The unique identifier from the membership data source for the user.
- /// A enumeration value indicating whether the user was created successfully.
- ///
- /// A object populated with the information for the newly created user.
- ///
- public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion,
- string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
- {
- return CreateUser(_defaultMemberTypeAlias, username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
- }
-
- ///
- /// Removes a user from the membership data source.
- ///
- /// The name of the user to delete.
- /// true to delete data related to the user from the database; false to leave data related to the user in the database.
- ///
- /// true if the user was successfully deleted; otherwise, false.
- ///
- public override bool DeleteUser(string username, bool deleteAllRelatedData)
- {
- var m = Member.GetMemberFromLoginName(username);
- if (m == null) return false;
- m.delete();
- return true;
- }
-
- ///
- /// Gets a collection of membership users where the e-mail address contains the specified e-mail address to match.
- ///
- /// The e-mail address to search for.
- /// The index of the page of results to return. pageIndex is zero-based.
- /// The size of the page of results to return.
- /// The total number of matched users.
- ///
- /// A collection that contains a page of pageSize objects beginning at the page specified by pageIndex.
- ///
- public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
- {
- var byEmail = ApplicationContext.Current.Services.MemberService.FindMembersByEmail(emailToMatch).ToArray();
- totalRecords = byEmail.Length;
- var pagedResult = new PagedResult(totalRecords, pageIndex, pageSize);
-
- var collection = new MembershipUserCollection();
- foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize))
- {
- collection.Add(ConvertToMembershipUser(m));
- }
- return collection;
- }
-
- ///
- /// Gets a collection of membership users where the user name contains the specified user name to match.
- ///
- /// The user name to search for.
- /// The index of the page of results to return. pageIndex is zero-based.
- /// The size of the page of results to return.
- /// The total number of matched users.
- ///
- /// A collection that contains a page of pageSize objects beginning at the page specified by pageIndex.
- ///
- public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
- {
- var counter = 0;
- var startIndex = pageSize * pageIndex;
- var endIndex = startIndex + pageSize - 1;
- var membersList = new MembershipUserCollection();
- var memberArray = Member.GetMemberByName(usernameToMatch, false);
- totalRecords = memberArray.Length;
-
- foreach (var m in memberArray)
- {
- if (counter >= startIndex)
- membersList.Add(ConvertToMembershipUser(m));
- if (counter >= endIndex) break;
- counter++;
- }
- return membersList;
- }
-
- ///
- /// Gets a collection of all the users in the data source in pages of data.
- ///
- /// The index of the page of results to return. pageIndex is zero-based.
- /// The size of the page of results to return.
- /// The total number of matched users.
- ///
- /// A collection that contains a page of pageSize objects beginning at the page specified by pageIndex.
- ///
- public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
- {
- var counter = 0;
- var startIndex = pageSize * pageIndex;
- var endIndex = startIndex + pageSize - 1;
- var membersList = new MembershipUserCollection();
- var memberArray = Member.GetAll;
- totalRecords = memberArray.Length;
-
- foreach (var m in memberArray)
- {
- if (counter >= startIndex)
- membersList.Add(ConvertToMembershipUser(m));
- if (counter >= endIndex) break;
- counter++;
- }
- return membersList;
-
- }
-
- ///
- /// Gets the number of users currently accessing the application.
- ///
- ///
- /// The number of users currently accessing the application.
- ///
- public override int GetNumberOfUsersOnline()
- {
- return Member.CachedMembers().Count;
- }
-
- ///
- /// Gets the password for the specified user name from the data source.
- ///
- /// The user to retrieve the password for.
- /// The password answer for the user.
- ///
- /// The password for the specified user name.
- ///
- public override string GetPassword(string username, string answer)
- {
- if (EnablePasswordRetrieval == false)
- throw new ProviderException("Password Retrieval Not Enabled.");
-
- if (PasswordFormat == MembershipPasswordFormat.Hashed)
- throw new ProviderException("Cannot retrieve Hashed passwords.");
-
- var m = Member.GetMemberFromLoginName(username);
- if (m != null)
- {
- if (RequiresQuestionAndAnswer)
- {
- // check if password answer property alias is set
- if (string.IsNullOrEmpty(_passwordRetrievalAnswerPropertyTypeAlias) == false)
- {
- // check if user is locked out
- if (string.IsNullOrEmpty(LockPropertyTypeAlias) == false)
- {
- var isLockedOut = false;
- bool.TryParse(GetMemberProperty(m, LockPropertyTypeAlias, true), out isLockedOut);
- if (isLockedOut)
- {
- throw new MembershipPasswordException("The supplied user is locked out");
- }
- }
-
- // match password answer
- if (GetMemberProperty(m, _passwordRetrievalAnswerPropertyTypeAlias, false) != answer)
- {
- throw new MembershipPasswordException("Incorrect password answer");
- }
- }
- else
- {
- throw new ProviderException("Password retrieval answer property alias is not set! To automatically support password question/answers you'll need to add references to the membertype properties in the 'Member' element in web.config by adding their aliases to the 'umbracoPasswordRetrievalQuestionPropertyTypeAlias' and 'umbracoPasswordRetrievalAnswerPropertyTypeAlias' attributes");
- }
- }
- }
- if (m == null)
- {
- throw new MembershipPasswordException("The supplied user is not found");
- }
- return m.GetPassword();
- }
-
- ///
- /// Gets information from the data source for a user. Provides an option to update the last-activity date/time stamp for the user.
- ///
- /// The name of the user to get information for.
- /// 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.
- ///
- /// A object populated with the specified user's information from the data source.
- ///
- public override MembershipUser GetUser(string username, bool userIsOnline)
- {
- if (String.IsNullOrEmpty(username))
- return null;
- Member m = Member.GetMemberFromLoginName(username);
- if (m == null) return null;
- else return ConvertToMembershipUser(m);
- }
-
- ///
- /// 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.
- ///
- /// The unique identifier for the membership user to get information for.
- /// 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.
- ///
- /// A object populated with the specified user's information from the data source.
- ///
- public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
- {
- var asGuid = providerUserKey.TryConvertTo();
- if (asGuid.Success)
- {
- var m = new Member(asGuid.Result);
- return ConvertToMembershipUser(m);
- }
- var asInt = providerUserKey.TryConvertTo();
- if (asInt.Success)
- {
- var m = new Member(asInt.Result);
- return ConvertToMembershipUser(m);
- }
- throw new InvalidOperationException("The " + GetType() + " provider only supports GUID or Int as a providerUserKey");
-
- }
-
-
- ///
- /// Gets the user name associated with the specified e-mail address.
- ///
- /// The e-mail address to search for.
- ///
- /// The user name associated with the specified e-mail address. If no match is found, return null.
- ///
- public override string GetUserNameByEmail(string email)
- {
- Member m = Member.GetMemberFromEmail(email);
- return m == null ? null : m.LoginName;
- }
-
- ///
- /// Resets a user's password to a new, automatically generated password.
- ///
- /// The user to reset the password for.
- /// The password answer for the specified user (not used with Umbraco).
- /// The new password for the specified user.
- public override string ResetPassword(string username, string answer)
- {
- if (EnablePasswordReset == false)
- {
- throw new NotSupportedException("Password reset is not supported");
- }
-
- //TODO: This should be here - but how do we update failure count in this provider??
- //if (answer == null && RequiresQuestionAndAnswer)
- //{
- // UpdateFailureCount(username, "passwordAnswer");
-
- // throw new ProviderException("Password answer required for password reset.");
- //}
-
- var newPassword = Membership.GeneratePassword(MinRequiredPasswordLength, MinRequiredNonAlphanumericCharacters);
-
- var args = new ValidatePasswordEventArgs(username, newPassword, true);
- OnValidatingPassword(args);
- if (args.Cancel)
- {
- if (args.FailureInformation != null)
- throw args.FailureInformation;
- throw new MembershipPasswordException("Reset password canceled due to password validation failure.");
- }
-
- var m = Member.GetMemberFromLoginName(username);
- if (m == null)
- throw new MembershipPasswordException("The supplied user is not found");
-
- if (RequiresQuestionAndAnswer)
- {
- // check if password answer property alias is set
- if (string.IsNullOrEmpty(_passwordRetrievalAnswerPropertyTypeAlias) == false)
- {
- // check if user is locked out
- if (string.IsNullOrEmpty(LockPropertyTypeAlias) == false)
- {
- var isLockedOut = false;
- bool.TryParse(GetMemberProperty(m, LockPropertyTypeAlias, true), out isLockedOut);
- if (isLockedOut)
- {
- throw new MembershipPasswordException("The supplied user is locked out");
- }
- }
-
- // match password answer
- if (GetMemberProperty(m, _passwordRetrievalAnswerPropertyTypeAlias, false) != answer)
- {
- throw new MembershipPasswordException("Incorrect password answer");
- }
- }
- else
- {
- throw new ProviderException("Password retrieval answer property alias is not set! To automatically support password question/answers you'll need to add references to the membertype properties in the 'Member' element in web.config by adding their aliases to the 'umbracoPasswordRetrievalQuestionPropertyTypeAlias' and 'umbracoPasswordRetrievalAnswerPropertyTypeAlias' attributes");
- }
- }
-
- string salt;
- var encodedPassword = EncryptOrHashNewPassword(newPassword, out salt);
- //set the password on the member
- m.ChangePassword(
- FormatPasswordForStorage(encodedPassword, salt));
-
- if (string.IsNullOrEmpty(_lastPasswordChangedPropertyTypeAlias) == false)
- {
- UpdateMemberProperty(m, _lastPasswordChangedPropertyTypeAlias, DateTime.Now);
- }
-
- m.Save();
-
- return newPassword;
- }
-
- ///
- /// Clears a lock so that the membership user can be validated.
- ///
- /// The membership user to clear the lock status for.
- ///
- /// true if the membership user was successfully unlocked; otherwise, false.
- ///
- public override bool UnlockUser(string userName)
- {
- if (string.IsNullOrEmpty(LockPropertyTypeAlias) == false)
- {
- var m = Member.GetMemberFromLoginName(userName);
- if (m != null)
- {
- UpdateMemberProperty(m, LockPropertyTypeAlias, 0);
- m.Save();
- return true;
- }
- throw new Exception(String.Format("No member with the username '{0}' found", userName));
- }
- throw new ProviderException("To enable lock/unlocking, you need to add a 'bool' property on your membertype and add the alias of the property in the 'umbracoLockPropertyTypeAlias' attribute of the membership element in the web.config.");
- }
-
- ///
- /// Updates e-mail and potentially approved status, lock status and comment on a user.
- ///
- /// A object that represents the user to update and the updated information for the user.
- public override void UpdateUser(MembershipUser user)
- {
- var m = Member.GetMemberFromLoginName(user.UserName);
- m.Email = user.Email;
-
- // if supported, update approve status
- UpdateMemberProperty(m, ApprovedPropertyTypeAlias, user.IsApproved ? 1 : 0);
-
- // if supported, update lock status
- UpdateMemberProperty(m, LockPropertyTypeAlias, user.IsLockedOut ? 1 : 0);
- if (user.IsLockedOut)
- {
- UpdateMemberProperty(m, _lastLockedOutPropertyTypeAlias, DateTime.Now);
- }
-
- // if supported, update comment
- UpdateMemberProperty(m, CommentPropertyTypeAlias, user.Comment);
-
- m.Save();
- }
-
- private static void UpdateMemberProperty(Member m, string propertyAlias, object propertyValue)
- {
- if (string.IsNullOrEmpty(propertyAlias) == false)
- {
- if (m.getProperty(propertyAlias) != null)
- {
- m.getProperty(propertyAlias).Value = propertyValue;
- }
- }
- }
-
- private static string GetMemberProperty(Member m, string propertyAlias, bool isBool)
- {
- if (string.IsNullOrEmpty(propertyAlias) == false)
- {
- if (m.getProperty(propertyAlias) != null &&
- m.getProperty(propertyAlias).Value != null)
- {
- if (isBool)
- {
- // Umbraco stored true as 1, which means it can be bool.tryParse'd
- return m.getProperty(propertyAlias).Value.ToString().Replace("1", "true").Replace("0", "false");
- }
- return m.getProperty(propertyAlias).Value.ToString();
- }
- }
-
- return null;
- }
-
- private static string GetMemberProperty(IMember m, string propertyAlias, bool isBool)
- {
- if (string.IsNullOrEmpty(propertyAlias) == false)
- {
- if (m.Properties[propertyAlias] != null &&
- m.Properties[propertyAlias].Value != null)
- {
- if (isBool)
- {
- // Umbraco stored true as 1, which means it can be bool.tryParse'd
- return m.Properties[propertyAlias].Value.ToString().Replace("1", "true").Replace("0", "false");
- }
- return m.Properties[propertyAlias].Value.ToString();
- }
- }
-
- return null;
- }
-
- ///
- /// Verifies that the specified user name and password exist in the data source.
- ///
- /// The name of the user to validate.
- /// The password for the specified user.
- ///
- /// true if the specified username and password are valid; otherwise, false.
- ///
- public override bool ValidateUser(string username, string password)
- {
- var m = Member.GetMemberFromLoginAndEncodedPassword(username, EncryptOrHashExistingPassword(password));
- if (m != null)
- {
- // check for lock status. If locked, then set the member property to null
- if (string.IsNullOrEmpty(LockPropertyTypeAlias) == false)
- {
- string lockedStatus = GetMemberProperty(m, LockPropertyTypeAlias, true);
- if (string.IsNullOrEmpty(lockedStatus) == false)
- {
- var isLocked = false;
- if (bool.TryParse(lockedStatus, out isLocked))
- {
- if (isLocked)
- {
- m = null;
- }
- }
- }
- }
-
- //check for approve status. If not approved, then set the member property to null
- if (m != null && !CheckApproveStatus(m)) {
- m = null;
- }
-
- // maybe update login date
- if (m != null && string.IsNullOrEmpty(_lastLoginPropertyTypeAlias) == false)
- {
- UpdateMemberProperty(m, _lastLoginPropertyTypeAlias, DateTime.Now);
- }
-
- // maybe reset password attempts
- if (m != null && string.IsNullOrEmpty(_failedPasswordAttemptsPropertyTypeAlias) == false)
- {
- UpdateMemberProperty(m, _failedPasswordAttemptsPropertyTypeAlias, 0);
- }
-
- // persist data
- if (m != null)
- m.Save();
- }
- else if (string.IsNullOrEmpty(LockPropertyTypeAlias) == false
- && string.IsNullOrEmpty(_failedPasswordAttemptsPropertyTypeAlias) == false)
- {
- var updateMemberDataObject = Member.GetMemberFromLoginName(username);
- // update fail rate if it's approved
- if (updateMemberDataObject != null && CheckApproveStatus(updateMemberDataObject))
- {
- int failedAttempts = 0;
- int.TryParse(GetMemberProperty(updateMemberDataObject, _failedPasswordAttemptsPropertyTypeAlias, false), out failedAttempts);
- failedAttempts = failedAttempts+1;
- UpdateMemberProperty(updateMemberDataObject, _failedPasswordAttemptsPropertyTypeAlias, failedAttempts);
-
- // lock user?
- if (failedAttempts >= MaxInvalidPasswordAttempts)
- {
- UpdateMemberProperty(updateMemberDataObject, LockPropertyTypeAlias, 1);
- UpdateMemberProperty(updateMemberDataObject, _lastLockedOutPropertyTypeAlias, DateTime.Now);
- }
- updateMemberDataObject.Save();
- }
-
- }
- return (m != null);
- }
-
- private bool CheckApproveStatus(Member m)
- {
- var isApproved = false;
- if (string.IsNullOrEmpty(ApprovedPropertyTypeAlias) == false)
- {
- if (m != null)
- {
- var approveStatus = GetMemberProperty(m, ApprovedPropertyTypeAlias, true);
- if (string.IsNullOrEmpty(approveStatus) == false)
- {
- //try parsing as bool first (just in case)
- if (bool.TryParse(approveStatus, out isApproved) == false)
- {
- int intStatus;
- //if that fails, try parsing as int (since its normally stored as 0 or 1)
- if (int.TryParse(approveStatus, out intStatus))
- {
- isApproved = intStatus != 0;
- }
- }
- }
- else
- {
- //There is no property so we shouldn't use the approve status
- isApproved = true;
- }
- }
- }
- else {
- // if we don't use approve statuses
- isApproved = true;
- }
- return isApproved;
- }
- #endregion
-
- #region Helper Methods
-
- ///
- /// Checks the password.
- ///
- /// The password.
- /// The dbPassword.
- ///
- internal bool CheckPassword(string password, string dbPassword)
- {
- string pass1 = password;
- string pass2 = dbPassword;
-
- switch (PasswordFormat)
- {
- case MembershipPasswordFormat.Encrypted:
- pass2 = DecodePassword(dbPassword);
- break;
- case MembershipPasswordFormat.Hashed:
- pass1 = EncryptOrHashExistingPassword(password);
- break;
- default:
- break;
- }
- return (pass1 == pass2) ? true : false;
- }
-
-
- ///
- /// Encodes the password.
- ///
- /// The password.
- /// The encoded password.
- [Obsolete("Do not use this, it is the legacy way to encode a password")]
- public string EncodePassword(string password)
- {
- return LegacyEncodePassword(password);
- }
-
- ///
- /// Unencode password.
- ///
- /// The encoded password.
- /// The unencoded password.
- [Obsolete("Do not use this, it is the legacy way to decode a password")]
- public string UnEncodePassword(string encodedPassword)
- {
- return LegacyUnEncodePassword(encodedPassword);
- }
-
- ///
- /// Converts to membership user.
- ///
- /// The m.
- ///
- private MembershipUser ConvertToMembershipUser(Member m)
- {
- if (m == null) return null;
-
- var lastLogin = DateTime.Now;
- var lastLocked = DateTime.MinValue;
- var isApproved = true;
- var isLocked = false;
- var comment = "";
- var passwordQuestion = "";
-
- // last login
- if (string.IsNullOrEmpty(_lastLoginPropertyTypeAlias) == false)
- {
- DateTime.TryParse(GetMemberProperty(m, _lastLoginPropertyTypeAlias, false), out lastLogin);
- }
- // approved
- if (string.IsNullOrEmpty(ApprovedPropertyTypeAlias) == false)
- {
- bool.TryParse(GetMemberProperty(m, ApprovedPropertyTypeAlias, true), out isApproved);
- }
- // locked
- if (string.IsNullOrEmpty(LockPropertyTypeAlias) == false)
- {
- bool.TryParse(GetMemberProperty(m, LockPropertyTypeAlias, true), out isLocked);
- }
- // last locked
- if (string.IsNullOrEmpty(_lastLockedOutPropertyTypeAlias) == false)
- {
- DateTime.TryParse(GetMemberProperty(m, _lastLockedOutPropertyTypeAlias, false), out lastLocked);
- }
- // comment
- if (string.IsNullOrEmpty(CommentPropertyTypeAlias) == false)
- {
- comment = GetMemberProperty(m, CommentPropertyTypeAlias, false);
- }
- // password question
- if (string.IsNullOrEmpty(_passwordRetrievalQuestionPropertyTypeAlias) == false)
- {
- passwordQuestion = GetMemberProperty(m, _passwordRetrievalQuestionPropertyTypeAlias, false);
- }
-
- return new MembershipUser(_providerName, m.LoginName, m.Id, m.Email, passwordQuestion, comment, isApproved, isLocked, m.CreateDateTime, lastLogin,
- DateTime.Now, DateTime.Now, lastLocked);
- }
-
- ///
- /// Converts to membership user.
- ///
- /// The m.
- ///
- private MembershipUser ConvertToMembershipUser(IMember m)
- {
- if (m == null) return null;
-
- var lastLogin = DateTime.Now;
- var lastLocked = DateTime.MinValue;
- var isApproved = true;
- var isLocked = false;
- var comment = "";
- var passwordQuestion = "";
-
- // last login
- if (string.IsNullOrEmpty(_lastLoginPropertyTypeAlias) == false)
- {
- DateTime.TryParse(GetMemberProperty(m, _lastLoginPropertyTypeAlias, false), out lastLogin);
- }
- // approved
- if (string.IsNullOrEmpty(ApprovedPropertyTypeAlias) == false)
- {
- bool.TryParse(GetMemberProperty(m, ApprovedPropertyTypeAlias, true), out isApproved);
- }
- // locked
- if (string.IsNullOrEmpty(LockPropertyTypeAlias) == false)
- {
- bool.TryParse(GetMemberProperty(m, LockPropertyTypeAlias, true), out isLocked);
- }
- // last locked
- if (string.IsNullOrEmpty(_lastLockedOutPropertyTypeAlias) == false)
- {
- DateTime.TryParse(GetMemberProperty(m, _lastLockedOutPropertyTypeAlias, false), out lastLocked);
- }
- // comment
- if (string.IsNullOrEmpty(CommentPropertyTypeAlias) == false)
- {
- comment = GetMemberProperty(m, CommentPropertyTypeAlias, false);
- }
- // password question
- if (string.IsNullOrEmpty(_passwordRetrievalQuestionPropertyTypeAlias) == false)
- {
- passwordQuestion = GetMemberProperty(m, _passwordRetrievalQuestionPropertyTypeAlias, false);
- }
-
- return new MembershipUser(_providerName, m.Username, m.Id, m.Email, passwordQuestion, comment, isApproved, isLocked, m.CreateDate, lastLogin,
- DateTime.Now, DateTime.Now, lastLocked);
- }
-
- #endregion
- }
-}
+#region namespace
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Web.Security;
+using System.Configuration;
+using Umbraco.Core;
+using Umbraco.Core.Logging;
+using Umbraco.Core.Models;
+using Umbraco.Core.Persistence.Querying;
+using Umbraco.Core.Security;
+using umbraco.BusinessLogic;
+using System.Security.Cryptography;
+using System.Web.Util;
+using System.Collections.Specialized;
+using System.Configuration.Provider;
+using System.Security;
+using System.Security.Permissions;
+using System.Runtime.CompilerServices;
+using Member = umbraco.cms.businesslogic.member.Member;
+using MemberType = umbraco.cms.businesslogic.member.MemberType;
+
+#endregion
+
+namespace umbraco.providers.members
+{
+ ///
+ /// Custom Membership Provider for Umbraco Members (User authentication for Frontend applications NOT umbraco CMS)
+ ///
+
+ public class UmbracoMembershipProvider : UmbracoMembershipProviderBase
+ {
+ #region Fields
+
+ private string _providerName = Member.UmbracoMemberProviderName;
+
+ #endregion
+
+ ///
+ /// Override to maintain backwards compatibility with 0 required non-alphanumeric chars
+ ///
+ public override int DefaultMinNonAlphanumericChars
+ {
+ get { return 0; }
+ }
+
+ ///
+ /// Override to maintain backwards compatibility with only 4 required length
+ ///
+ public override int DefaultMinPasswordLength
+ {
+ get { return 4; }
+ }
+
+ ///
+ /// Override to maintain backwards compatibility
+ ///
+ public override bool DefaultUseLegacyEncoding
+ {
+ get { return true; }
+ }
+
+ ///
+ /// For backwards compatibility, this provider supports this option
+ ///
+ public override bool AllowManuallyChangingPassword
+ {
+ get { return true; }
+ }
+
+ #region Initialization Method
+ ///
+ /// Initializes the provider.
+ ///
+ /// The friendly name of the provider.
+ /// A collection of the name/value pairs representing the provider-specific attributes specified in the configuration for this provider.
+ /// The name of the provider is null.
+ /// An attempt is made to call
+ /// on a provider after the provider
+ /// has already been initialized.
+ /// The name of the provider has a length of zero.
+ public override void Initialize(string name, NameValueCollection config)
+ {
+ // Intialize values from web.config
+ if (config == null) throw new ArgumentNullException("config");
+
+ if (string.IsNullOrEmpty(name)) name = "UmbracoMembershipProvider";
+
+ base.Initialize(name, config);
+
+ _providerName = name;
+
+ // test for membertype (if not specified, choose the first member type available)
+ if (config["defaultMemberTypeAlias"] != null)
+ DefaultMemberTypeAlias = config["defaultMemberTypeAlias"];
+ else if (MemberType.GetAll.Length == 1)
+ DefaultMemberTypeAlias = MemberType.GetAll[0].Alias;
+ else
+ throw new ProviderException("No default MemberType alias is specified in the web.config string. Please add a 'defaultMemberTypeAlias' to the add element in the provider declaration in web.config");
+
+ // test for approve status
+ if (config["umbracoApprovePropertyTypeAlias"] != null)
+ {
+ ApprovedPropertyTypeAlias = config["umbracoApprovePropertyTypeAlias"];
+ }
+ // test for lock attempts
+ if (config["umbracoLockPropertyTypeAlias"] != null)
+ {
+ LockPropertyTypeAlias = config["umbracoLockPropertyTypeAlias"];
+ }
+ if (config["umbracoLastLockedPropertyTypeAlias"] != null)
+ {
+ LastLockedOutPropertyTypeAlias = config["umbracoLastLockedPropertyTypeAlias"];
+ }
+ if (config["umbracoLastPasswordChangedPropertyTypeAlias"] != null)
+ {
+ LastPasswordChangedPropertyTypeAlias = config["umbracoLastPasswordChangedPropertyTypeAlias"];
+ }
+ if (config["umbracoFailedPasswordAttemptsPropertyTypeAlias"] != null)
+ {
+ FailedPasswordAttemptsPropertyTypeAlias = config["umbracoFailedPasswordAttemptsPropertyTypeAlias"];
+ }
+ // comment property
+ if (config["umbracoCommentPropertyTypeAlias"] != null)
+ {
+ CommentPropertyTypeAlias = config["umbracoCommentPropertyTypeAlias"];
+ }
+ // last login date
+ if (config["umbracoLastLoginPropertyTypeAlias"] != null)
+ {
+ LastLoginPropertyTypeAlias = config["umbracoLastLoginPropertyTypeAlias"];
+ }
+ // password retrieval
+ if (config["umbracoPasswordRetrievalQuestionPropertyTypeAlias"] != null)
+ {
+ PasswordRetrievalQuestionPropertyTypeAlias = config["umbracoPasswordRetrievalQuestionPropertyTypeAlias"];
+ }
+ if (config["umbracoPasswordRetrievalAnswerPropertyTypeAlias"] != null)
+ {
+ PasswordRetrievalAnswerPropertyTypeAlias = config["umbracoPasswordRetrievalAnswerPropertyTypeAlias"];
+ }
+
+ }
+ #endregion
+
+ #region Methods
+
+ ///
+ /// Processes a request to update the password for a membership user.
+ ///
+ /// The user to update the password for.
+ /// This property is ignore for this provider
+ /// The new password for the specified user.
+ ///
+ /// true if the password was updated successfully; otherwise, false.
+ ///
+ protected override bool PerformChangePassword(string username, string oldPassword, string newPassword)
+ {
+ //NOTE: due to backwards compatibilty reasons, this provider doesn't care about the old password and
+ // allows simply setting the password manually so we don't really care about the old password.
+ // This is allowed based on the overridden AllowManuallyChangingPassword option.
+
+ // in order to support updating passwords from the umbraco core, we can't validate the old password
+ var m = Member.GetMemberFromLoginName(username);
+ if (m == null) return false;
+
+ var args = new ValidatePasswordEventArgs(username, newPassword, false);
+ OnValidatingPassword(args);
+
+ if (args.Cancel)
+ {
+ if (args.FailureInformation != null)
+ throw args.FailureInformation;
+ throw new MembershipPasswordException("Change password canceled due to password validation failure.");
+ }
+
+ string salt;
+ var encodedPassword = EncryptOrHashNewPassword(newPassword, out salt);
+ m.ChangePassword(
+ FormatPasswordForStorage(encodedPassword, salt));
+
+ UpdateMemberProperty(m, LastPasswordChangedPropertyTypeAlias, DateTime.Now);
+
+ m.Save();
+
+ return true;
+ }
+
+ ///
+ /// Processes a request to update the password question and answer for a membership user.
+ ///
+ /// The user to change the password question and answer for.
+ /// The password for the specified user.
+ /// The new password question for the specified user.
+ /// The new password answer for the specified user.
+ ///
+ /// true if the password question and answer are updated successfully; otherwise, false.
+ ///
+ protected override bool PerformChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
+ {
+ var m = Member.GetMemberFromLoginName(username);
+ if (m == null)
+ {
+ return false;
+ }
+
+ UpdateMemberProperty(m, PasswordRetrievalQuestionPropertyTypeAlias, newPasswordQuestion);
+ UpdateMemberProperty(m, PasswordRetrievalAnswerPropertyTypeAlias, newPasswordAnswer);
+ m.Save();
+ return true;
+ }
+
+ ///
+ /// Adds a new membership user to the data source.
+ ///
+ ///
+ /// The user name for the new user.
+ /// The password for the new user.
+ /// The e-mail address for the new user.
+ /// The password question for the new user.
+ /// The password answer for the new user
+ /// Whether or not the new user is approved to be validated.
+ /// The unique identifier from the membership data source for the user.
+ /// A enumeration value indicating whether the user was created successfully.
+ ///
+ /// A object populated with the information for the newly created user.
+ ///
+ protected override MembershipUser PerformCreateUser(string memberTypeAlias, string username, string password, string email, string passwordQuestion,
+ string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
+ {
+ if (Member.GetMemberFromLoginName(username) != null)
+ {
+ status = MembershipCreateStatus.DuplicateUserName;
+ LogHelper.Warn("Cannot create member as username already exists: " + username);
+ return null;
+ }
+
+ if (Member.GetMemberFromEmail(email) != null && RequiresUniqueEmail)
+ {
+ status = MembershipCreateStatus.DuplicateEmail;
+ LogHelper.Warn(
+ "Cannot create member as a member with the same email address exists: " + email);
+ return null;
+ }
+
+ var memberType = MemberType.GetByAlias(memberTypeAlias);
+ if (memberType == null)
+ {
+ throw new InvalidOperationException("Could not find a member type with alias " + memberTypeAlias + ". Ensure your membership provider configuration is up to date and that the default member type exists.");
+ }
+
+ var m = Member.MakeNew(username, email, memberType, User.GetUser(0));
+
+ string salt;
+ var encodedPassword = EncryptOrHashNewPassword(password, out salt);
+
+ //set the password on the member
+ m.ChangePassword(FormatPasswordForStorage(encodedPassword, salt));
+
+ // custom fields
+ if (string.IsNullOrEmpty(PasswordRetrievalQuestionPropertyTypeAlias) == false)
+ {
+ UpdateMemberProperty(m, PasswordRetrievalQuestionPropertyTypeAlias, passwordQuestion);
+ }
+
+ if (string.IsNullOrEmpty(PasswordRetrievalAnswerPropertyTypeAlias) == false)
+ {
+ UpdateMemberProperty(m, PasswordRetrievalAnswerPropertyTypeAlias, passwordAnswer);
+ }
+
+ if (string.IsNullOrEmpty(ApprovedPropertyTypeAlias) == false)
+ {
+ UpdateMemberProperty(m, ApprovedPropertyTypeAlias, isApproved ? 1 : 0);
+ }
+
+ if (string.IsNullOrEmpty(LastLoginPropertyTypeAlias) == false)
+ {
+ UpdateMemberProperty(m, LastLoginPropertyTypeAlias, DateTime.Now);
+ }
+
+ if (string.IsNullOrEmpty(LastPasswordChangedPropertyTypeAlias) == false)
+ {
+ UpdateMemberProperty(m, LastPasswordChangedPropertyTypeAlias, DateTime.Now);
+ }
+
+ var mUser = ConvertToMembershipUser(m);
+
+ // save
+ m.Save();
+
+ status = MembershipCreateStatus.Success;
+
+ return mUser;
+ }
+
+
+ ///
+ /// Removes a user from the membership data source.
+ ///
+ /// The name of the user to delete.
+ ///
+ /// TODO: This setting currently has no effect
+ ///
+ ///
+ /// true if the user was successfully deleted; otherwise, false.
+ ///
+ public override bool DeleteUser(string username, bool deleteAllRelatedData)
+ {
+ var m = Member.GetMemberFromLoginName(username);
+ if (m == null) return false;
+ m.delete();
+ return true;
+ }
+
+ ///
+ /// Gets a collection of membership users where the e-mail address contains the specified e-mail address to match.
+ ///
+ /// The e-mail address to search for.
+ /// The index of the page of results to return. pageIndex is zero-based.
+ /// The size of the page of results to return.
+ /// The total number of matched users.
+ ///
+ /// A collection that contains a page of pageSize objects beginning at the page specified by pageIndex.
+ ///
+ public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
+ {
+ var byEmail = ApplicationContext.Current.Services.MemberService.FindMembersByEmail(emailToMatch, StringPropertyMatchType.Wildcard).ToArray();
+ totalRecords = byEmail.Length;
+ var pagedResult = new PagedResult(totalRecords, pageIndex, pageSize);
+
+ var collection = new MembershipUserCollection();
+ foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize))
+ {
+ collection.Add(ConvertToMembershipUser(m));
+ }
+ return collection;
+ }
+
+ ///
+ /// Gets a collection of membership users where the user name contains the specified user name to match.
+ ///
+ /// The user name to search for.
+ /// The index of the page of results to return. pageIndex is zero-based.
+ /// The size of the page of results to return.
+ /// The total number of matched users.
+ ///
+ /// A collection that contains a page of pageSize objects beginning at the page specified by pageIndex.
+ ///
+ public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
+ {
+ var byEmail = ApplicationContext.Current.Services.MemberService.FindMembersByUsername(usernameToMatch, StringPropertyMatchType.Wildcard).ToArray();
+ totalRecords = byEmail.Length;
+ var pagedResult = new PagedResult(totalRecords, pageIndex, pageSize);
+
+ var collection = new MembershipUserCollection();
+ foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize))
+ {
+ collection.Add(ConvertToMembershipUser(m));
+ }
+ return collection;
+ }
+
+ ///
+ /// Gets a collection of all the users in the data source in pages of data.
+ ///
+ /// The index of the page of results to return. pageIndex is zero-based.
+ /// The size of the page of results to return.
+ /// The total number of matched users.
+ ///
+ /// A collection that contains a page of pageSize objects beginning at the page specified by pageIndex.
+ ///
+ public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
+ {
+ var counter = 0;
+ var startIndex = pageSize * pageIndex;
+ var endIndex = startIndex + pageSize - 1;
+ var membersList = new MembershipUserCollection();
+ var memberArray = Member.GetAll;
+ totalRecords = memberArray.Length;
+
+ foreach (var m in memberArray)
+ {
+ if (counter >= startIndex)
+ membersList.Add(ConvertToMembershipUser(m));
+ if (counter >= endIndex) break;
+ counter++;
+ }
+ return membersList;
+
+ }
+
+ ///
+ /// Gets the number of users currently accessing the application.
+ ///
+ ///
+ /// The number of users currently accessing the application.
+ ///
+ public override int GetNumberOfUsersOnline()
+ {
+ return Member.CachedMembers().Count;
+ }
+
+ ///
+ /// Gets the password for the specified user name from the data source.
+ ///
+ /// The user to retrieve the password for.
+ /// The password answer for the user.
+ ///
+ /// The password for the specified user name.
+ ///
+ public override string GetPassword(string username, string answer)
+ {
+ if (EnablePasswordRetrieval == false)
+ throw new ProviderException("Password Retrieval Not Enabled.");
+
+ if (PasswordFormat == MembershipPasswordFormat.Hashed)
+ throw new ProviderException("Cannot retrieve Hashed passwords.");
+
+ var m = Member.GetMemberFromLoginName(username);
+ if (m != null)
+ {
+ if (RequiresQuestionAndAnswer)
+ {
+ // check if password answer property alias is set
+ if (string.IsNullOrEmpty(PasswordRetrievalAnswerPropertyTypeAlias) == false)
+ {
+ // check if user is locked out
+ if (string.IsNullOrEmpty(LockPropertyTypeAlias) == false)
+ {
+ var isLockedOut = false;
+ bool.TryParse(GetMemberProperty(m, LockPropertyTypeAlias, true), out isLockedOut);
+ if (isLockedOut)
+ {
+ throw new MembershipPasswordException("The supplied user is locked out");
+ }
+ }
+
+ // match password answer
+ if (GetMemberProperty(m, PasswordRetrievalAnswerPropertyTypeAlias, false) != answer)
+ {
+ throw new MembershipPasswordException("Incorrect password answer");
+ }
+ }
+ else
+ {
+ throw new ProviderException("Password retrieval answer property alias is not set! To automatically support password question/answers you'll need to add references to the membertype properties in the 'Member' element in web.config by adding their aliases to the 'umbracoPasswordRetrievalQuestionPropertyTypeAlias' and 'umbracoPasswordRetrievalAnswerPropertyTypeAlias' attributes");
+ }
+ }
+ }
+ if (m == null)
+ {
+ throw new MembershipPasswordException("The supplied user is not found");
+ }
+ return m.GetPassword();
+ }
+
+ ///
+ /// Gets information from the data source for a user. Provides an option to update the last-activity date/time stamp for the user.
+ ///
+ /// The name of the user to get information for.
+ /// 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.
+ ///
+ /// A object populated with the specified user's information from the data source.
+ ///
+ public override MembershipUser GetUser(string username, bool userIsOnline)
+ {
+ if (String.IsNullOrEmpty(username))
+ return null;
+ Member m = Member.GetMemberFromLoginName(username);
+ if (m == null) return null;
+ else return ConvertToMembershipUser(m);
+ }
+
+ ///
+ /// 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.
+ ///
+ /// The unique identifier for the membership user to get information for.
+ /// 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.
+ ///
+ /// A object populated with the specified user's information from the data source.
+ ///
+ public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
+ {
+ var asGuid = providerUserKey.TryConvertTo();
+ if (asGuid.Success)
+ {
+ var m = new Member(asGuid.Result);
+ return ConvertToMembershipUser(m);
+ }
+ var asInt = providerUserKey.TryConvertTo();
+ if (asInt.Success)
+ {
+ var m = new Member(asInt.Result);
+ return ConvertToMembershipUser(m);
+ }
+ throw new InvalidOperationException("The " + GetType() + " provider only supports GUID or Int as a providerUserKey");
+
+ }
+
+
+ ///
+ /// Gets the user name associated with the specified e-mail address.
+ ///
+ /// The e-mail address to search for.
+ ///
+ /// The user name associated with the specified e-mail address. If no match is found, return null.
+ ///
+ public override string GetUserNameByEmail(string email)
+ {
+ Member m = Member.GetMemberFromEmail(email);
+ return m == null ? null : m.LoginName;
+ }
+
+ ///
+ /// Resets a user's password to a new, automatically generated password.
+ ///
+ /// The user to reset the password for.
+ /// The password answer for the specified user (not used with Umbraco).
+ /// The new password for the specified user.
+ public override string ResetPassword(string username, string answer)
+ {
+ if (EnablePasswordReset == false)
+ {
+ throw new NotSupportedException("Password reset is not supported");
+ }
+
+ //TODO: This should be here - but how do we update failure count in this provider??
+ //if (answer == null && RequiresQuestionAndAnswer)
+ //{
+ // UpdateFailureCount(username, "passwordAnswer");
+
+ // throw new ProviderException("Password answer required for password reset.");
+ //}
+
+ var newPassword = Membership.GeneratePassword(MinRequiredPasswordLength, MinRequiredNonAlphanumericCharacters);
+
+ var args = new ValidatePasswordEventArgs(username, newPassword, true);
+ OnValidatingPassword(args);
+ if (args.Cancel)
+ {
+ if (args.FailureInformation != null)
+ throw args.FailureInformation;
+ throw new MembershipPasswordException("Reset password canceled due to password validation failure.");
+ }
+
+ var m = Member.GetMemberFromLoginName(username);
+ if (m == null)
+ throw new MembershipPasswordException("The supplied user is not found");
+
+ if (RequiresQuestionAndAnswer)
+ {
+ // check if password answer property alias is set
+ if (string.IsNullOrEmpty(PasswordRetrievalAnswerPropertyTypeAlias) == false)
+ {
+ // check if user is locked out
+ if (string.IsNullOrEmpty(LockPropertyTypeAlias) == false)
+ {
+ var isLockedOut = false;
+ bool.TryParse(GetMemberProperty(m, LockPropertyTypeAlias, true), out isLockedOut);
+ if (isLockedOut)
+ {
+ throw new MembershipPasswordException("The supplied user is locked out");
+ }
+ }
+
+ // match password answer
+ if (GetMemberProperty(m, PasswordRetrievalAnswerPropertyTypeAlias, false) != answer)
+ {
+ throw new MembershipPasswordException("Incorrect password answer");
+ }
+ }
+ else
+ {
+ throw new ProviderException("Password retrieval answer property alias is not set! To automatically support password question/answers you'll need to add references to the membertype properties in the 'Member' element in web.config by adding their aliases to the 'umbracoPasswordRetrievalQuestionPropertyTypeAlias' and 'umbracoPasswordRetrievalAnswerPropertyTypeAlias' attributes");
+ }
+ }
+
+ string salt;
+ var encodedPassword = EncryptOrHashNewPassword(newPassword, out salt);
+ //set the password on the member
+ m.ChangePassword(
+ FormatPasswordForStorage(encodedPassword, salt));
+
+ if (string.IsNullOrEmpty(LastPasswordChangedPropertyTypeAlias) == false)
+ {
+ UpdateMemberProperty(m, LastPasswordChangedPropertyTypeAlias, DateTime.Now);
+ }
+
+ m.Save();
+
+ return newPassword;
+ }
+
+ ///
+ /// Clears a lock so that the membership user can be validated.
+ ///
+ /// The membership user to clear the lock status for.
+ ///
+ /// true if the membership user was successfully unlocked; otherwise, false.
+ ///
+ public override bool UnlockUser(string userName)
+ {
+ if (string.IsNullOrEmpty(LockPropertyTypeAlias) == false)
+ {
+ var m = Member.GetMemberFromLoginName(userName);
+ if (m != null)
+ {
+ UpdateMemberProperty(m, LockPropertyTypeAlias, 0);
+ m.Save();
+ return true;
+ }
+ throw new Exception(String.Format("No member with the username '{0}' found", userName));
+ }
+ throw new ProviderException("To enable lock/unlocking, you need to add a 'bool' property on your membertype and add the alias of the property in the 'umbracoLockPropertyTypeAlias' attribute of the membership element in the web.config.");
+ }
+
+ ///
+ /// Updates e-mail and potentially approved status, lock status and comment on a user.
+ ///
+ /// A object that represents the user to update and the updated information for the user.
+ public override void UpdateUser(MembershipUser user)
+ {
+ var m = Member.GetMemberFromLoginName(user.UserName);
+ m.Email = user.Email;
+
+ // if supported, update approve status
+ UpdateMemberProperty(m, ApprovedPropertyTypeAlias, user.IsApproved ? 1 : 0);
+
+ // if supported, update lock status
+ UpdateMemberProperty(m, LockPropertyTypeAlias, user.IsLockedOut ? 1 : 0);
+ if (user.IsLockedOut)
+ {
+ UpdateMemberProperty(m, LastLockedOutPropertyTypeAlias, DateTime.Now);
+ }
+
+ // if supported, update comment
+ UpdateMemberProperty(m, CommentPropertyTypeAlias, user.Comment);
+
+ m.Save();
+ }
+
+ private static void UpdateMemberProperty(Member m, string propertyTypeAlias, object propertyValue)
+ {
+ if (string.IsNullOrEmpty(propertyTypeAlias) == false)
+ {
+ if (m.getProperty(propertyTypeAlias) != null)
+ {
+ m.getProperty(propertyTypeAlias).Value = propertyValue;
+ }
+ }
+ }
+
+ private static string GetMemberProperty(Member m, string propertyTypeAlias, bool isBool)
+ {
+ if (string.IsNullOrEmpty(propertyTypeAlias) == false)
+ {
+ if (m.getProperty(propertyTypeAlias) != null &&
+ m.getProperty(propertyTypeAlias).Value != null)
+ {
+ if (isBool)
+ {
+ // Umbraco stored true as 1, which means it can be bool.tryParse'd
+ return m.getProperty(propertyTypeAlias).Value.ToString().Replace("1", "true").Replace("0", "false");
+ }
+ return m.getProperty(propertyTypeAlias).Value.ToString();
+ }
+ }
+
+ return null;
+ }
+
+ private static string GetMemberProperty(IMember m, string propertyTypeAlias, bool isBool)
+ {
+ if (string.IsNullOrEmpty(propertyTypeAlias) == false)
+ {
+ if (m.Properties[propertyTypeAlias] != null &&
+ m.Properties[propertyTypeAlias].Value != null)
+ {
+ if (isBool)
+ {
+ // Umbraco stored true as 1, which means it can be bool.tryParse'd
+ return m.Properties[propertyTypeAlias].Value.ToString().Replace("1", "true").Replace("0", "false");
+ }
+ return m.Properties[propertyTypeAlias].Value.ToString();
+ }
+ }
+
+ return null;
+ }
+
+ ///
+ /// Verifies that the specified user name and password exist in the data source.
+ ///
+ /// The name of the user to validate.
+ /// The password for the specified user.
+ ///
+ /// true if the specified username and password are valid; otherwise, false.
+ ///
+ public override bool ValidateUser(string username, string password)
+ {
+ var m = Member.GetMemberFromLoginAndEncodedPassword(username, EncryptOrHashExistingPassword(password));
+ if (m != null)
+ {
+ // check for lock status. If locked, then set the member property to null
+ if (string.IsNullOrEmpty(LockPropertyTypeAlias) == false)
+ {
+ string lockedStatus = GetMemberProperty(m, LockPropertyTypeAlias, true);
+ if (string.IsNullOrEmpty(lockedStatus) == false)
+ {
+ var isLocked = false;
+ if (bool.TryParse(lockedStatus, out isLocked))
+ {
+ if (isLocked)
+ {
+ m = null;
+ }
+ }
+ }
+ }
+
+ //check for approve status. If not approved, then set the member property to null
+ if (m != null && !CheckApproveStatus(m)) {
+ m = null;
+ }
+
+ // maybe update login date
+ if (m != null && string.IsNullOrEmpty(LastLoginPropertyTypeAlias) == false)
+ {
+ UpdateMemberProperty(m, LastLoginPropertyTypeAlias, DateTime.Now);
+ }
+
+ // maybe reset password attempts
+ if (m != null && string.IsNullOrEmpty(FailedPasswordAttemptsPropertyTypeAlias) == false)
+ {
+ UpdateMemberProperty(m, FailedPasswordAttemptsPropertyTypeAlias, 0);
+ }
+
+ // persist data
+ if (m != null)
+ m.Save();
+ }
+ else if (string.IsNullOrEmpty(LockPropertyTypeAlias) == false
+ && string.IsNullOrEmpty(FailedPasswordAttemptsPropertyTypeAlias) == false)
+ {
+ var updateMemberDataObject = Member.GetMemberFromLoginName(username);
+ // update fail rate if it's approved
+ if (updateMemberDataObject != null && CheckApproveStatus(updateMemberDataObject))
+ {
+ int failedAttempts = 0;
+ int.TryParse(GetMemberProperty(updateMemberDataObject, FailedPasswordAttemptsPropertyTypeAlias, false), out failedAttempts);
+ failedAttempts = failedAttempts+1;
+ UpdateMemberProperty(updateMemberDataObject, FailedPasswordAttemptsPropertyTypeAlias, failedAttempts);
+
+ // lock user?
+ if (failedAttempts >= MaxInvalidPasswordAttempts)
+ {
+ UpdateMemberProperty(updateMemberDataObject, LockPropertyTypeAlias, 1);
+ UpdateMemberProperty(updateMemberDataObject, LastLockedOutPropertyTypeAlias, DateTime.Now);
+ }
+ updateMemberDataObject.Save();
+ }
+
+ }
+ return (m != null);
+ }
+
+ private bool CheckApproveStatus(Member m)
+ {
+ var isApproved = false;
+ if (string.IsNullOrEmpty(ApprovedPropertyTypeAlias) == false)
+ {
+ if (m != null)
+ {
+ var approveStatus = GetMemberProperty(m, ApprovedPropertyTypeAlias, true);
+ if (string.IsNullOrEmpty(approveStatus) == false)
+ {
+ //try parsing as bool first (just in case)
+ if (bool.TryParse(approveStatus, out isApproved) == false)
+ {
+ int intStatus;
+ //if that fails, try parsing as int (since its normally stored as 0 or 1)
+ if (int.TryParse(approveStatus, out intStatus))
+ {
+ isApproved = intStatus != 0;
+ }
+ }
+ }
+ else
+ {
+ //There is no property so we shouldn't use the approve status
+ isApproved = true;
+ }
+ }
+ }
+ else {
+ // if we don't use approve statuses
+ isApproved = true;
+ }
+ return isApproved;
+ }
+ #endregion
+
+ #region Helper Methods
+
+ ///
+ /// Checks the password.
+ ///
+ /// The password.
+ /// The dbPassword.
+ ///
+ internal bool CheckPassword(string password, string dbPassword)
+ {
+ string pass1 = password;
+ string pass2 = dbPassword;
+
+ switch (PasswordFormat)
+ {
+ case MembershipPasswordFormat.Encrypted:
+ pass2 = DecodePassword(dbPassword);
+ break;
+ case MembershipPasswordFormat.Hashed:
+ pass1 = EncryptOrHashExistingPassword(password);
+ break;
+ default:
+ break;
+ }
+ return (pass1 == pass2) ? true : false;
+ }
+
+
+ ///
+ /// Encodes the password.
+ ///
+ /// The password.
+ /// The encoded password.
+ [Obsolete("Do not use this, it is the legacy way to encode a password")]
+ public string EncodePassword(string password)
+ {
+ return LegacyEncodePassword(password);
+ }
+
+ ///
+ /// Unencode password.
+ ///
+ /// The encoded password.
+ /// The unencoded password.
+ [Obsolete("Do not use this, it is the legacy way to decode a password")]
+ public string UnEncodePassword(string encodedPassword)
+ {
+ return LegacyUnEncodePassword(encodedPassword);
+ }
+
+ ///
+ /// Converts to membership user.
+ ///
+ /// The m.
+ ///
+ private MembershipUser ConvertToMembershipUser(Member m)
+ {
+ if (m == null) return null;
+
+ var lastLogin = DateTime.Now;
+ var lastLocked = DateTime.MinValue;
+ var isApproved = true;
+ var isLocked = false;
+ var comment = "";
+ var passwordQuestion = "";
+
+ // last login
+ if (string.IsNullOrEmpty(LastLoginPropertyTypeAlias) == false)
+ {
+ DateTime.TryParse(GetMemberProperty(m, LastLoginPropertyTypeAlias, false), out lastLogin);
+ }
+ // approved
+ if (string.IsNullOrEmpty(ApprovedPropertyTypeAlias) == false)
+ {
+ bool.TryParse(GetMemberProperty(m, ApprovedPropertyTypeAlias, true), out isApproved);
+ }
+ // locked
+ if (string.IsNullOrEmpty(LockPropertyTypeAlias) == false)
+ {
+ bool.TryParse(GetMemberProperty(m, LockPropertyTypeAlias, true), out isLocked);
+ }
+ // last locked
+ if (string.IsNullOrEmpty(LastLockedOutPropertyTypeAlias) == false)
+ {
+ DateTime.TryParse(GetMemberProperty(m, LastLockedOutPropertyTypeAlias, false), out lastLocked);
+ }
+ // comment
+ if (string.IsNullOrEmpty(CommentPropertyTypeAlias) == false)
+ {
+ comment = GetMemberProperty(m, CommentPropertyTypeAlias, false);
+ }
+ // password question
+ if (string.IsNullOrEmpty(PasswordRetrievalQuestionPropertyTypeAlias) == false)
+ {
+ passwordQuestion = GetMemberProperty(m, PasswordRetrievalQuestionPropertyTypeAlias, false);
+ }
+
+ return new MembershipUser(_providerName, m.LoginName, m.Id, m.Email, passwordQuestion, comment, isApproved, isLocked, m.CreateDateTime, lastLogin,
+ DateTime.Now, DateTime.Now, lastLocked);
+ }
+
+ ///
+ /// Converts to membership user.
+ ///
+ /// The m.
+ ///
+ private MembershipUser ConvertToMembershipUser(IMember m)
+ {
+ if (m == null) return null;
+
+ var lastLogin = DateTime.Now;
+ var lastLocked = DateTime.MinValue;
+ var isApproved = true;
+ var isLocked = false;
+ var comment = "";
+ var passwordQuestion = "";
+
+ // last login
+ if (string.IsNullOrEmpty(LastLoginPropertyTypeAlias) == false)
+ {
+ DateTime.TryParse(GetMemberProperty(m, LastLoginPropertyTypeAlias, false), out lastLogin);
+ }
+ // approved
+ if (string.IsNullOrEmpty(ApprovedPropertyTypeAlias) == false)
+ {
+ bool.TryParse(GetMemberProperty(m, ApprovedPropertyTypeAlias, true), out isApproved);
+ }
+ // locked
+ if (string.IsNullOrEmpty(LockPropertyTypeAlias) == false)
+ {
+ bool.TryParse(GetMemberProperty(m, LockPropertyTypeAlias, true), out isLocked);
+ }
+ // last locked
+ if (string.IsNullOrEmpty(LastLockedOutPropertyTypeAlias) == false)
+ {
+ DateTime.TryParse(GetMemberProperty(m, LastLockedOutPropertyTypeAlias, false), out lastLocked);
+ }
+ // comment
+ if (string.IsNullOrEmpty(CommentPropertyTypeAlias) == false)
+ {
+ comment = GetMemberProperty(m, CommentPropertyTypeAlias, false);
+ }
+ // password question
+ if (string.IsNullOrEmpty(PasswordRetrievalQuestionPropertyTypeAlias) == false)
+ {
+ passwordQuestion = GetMemberProperty(m, PasswordRetrievalQuestionPropertyTypeAlias, false);
+ }
+
+ return new MembershipUser(_providerName, m.Username, m.Id, m.Email, passwordQuestion, comment, isApproved, isLocked, m.CreateDate, lastLogin,
+ DateTime.Now, DateTime.Now, lastLocked);
+ }
+
+ #endregion
+ }
+}
diff --git a/src/umbraco.providers/members/MembersProfileProvider.cs b/src/umbraco.providers/members/UmbracoProfileProvider.cs
similarity index 69%
rename from src/umbraco.providers/members/MembersProfileProvider.cs
rename to src/umbraco.providers/members/UmbracoProfileProvider.cs
index bd8f6a5ce7..4d1ac06ea3 100644
--- a/src/umbraco.providers/members/MembersProfileProvider.cs
+++ b/src/umbraco.providers/members/UmbracoProfileProvider.cs
@@ -1,159 +1,187 @@
-#region namespace
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Web.Security;
-using System.Configuration;
-using umbraco.BusinessLogic;
-using System.Security.Cryptography;
-using System.Web.Util;
-using System.Collections.Specialized;
-using System.Configuration.Provider;
-using umbraco.cms.businesslogic;
-using umbraco.cms.businesslogic.member;
-using System.Collections;
-using System.Web.Profile;
-#endregion
-
-namespace umbraco.providers.members {
- public class UmbracoProfileProvider : ProfileProvider {
-
- private string m_ApplicationName = "";
-
- public override string ApplicationName {
- get {
- return m_ApplicationName;
- }
- set {
- m_ApplicationName = value;
- }
- }
- public override string Description {
- get {
- return "Profile Provider for umbraco member profile data";
- }
- }
- public override string Name {
- get {
- return base.Name;
- }
- }
- public override void Initialize(string name, NameValueCollection config) {
-
- if (config == null)
- throw new ArgumentNullException("Null configuration parameters");
-
- if (String.IsNullOrEmpty(name))
- name = "UmbracoProfileProvider";
-
- base.Initialize(name, config);
-
- m_ApplicationName = config["applicationName"];
- if (String.IsNullOrEmpty(m_ApplicationName))
- m_ApplicationName = System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath;
- config.Remove("applicationName");
-
- // if the config element contains unused parameters we should throw an exception
- if (config.Count > 0) {
- string attrib = config.GetKey(0);
- if (!String.IsNullOrEmpty(attrib))
- throw new ProviderException(String.Format("Unrecognized attribute: {0}", attrib));
- }
-
-
- }
-
- public override int DeleteInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate) {
- throw new NotSupportedException();
- }
-
- public override int DeleteProfiles(string[] usernames) {
- throw new NotSupportedException();
- }
-
- public override int DeleteProfiles(ProfileInfoCollection profiles) {
- throw new NotSupportedException();
- }
-
- public override ProfileInfoCollection FindInactiveProfilesByUserName(ProfileAuthenticationOption authenticationOption, string usernameToMatch, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords) {
- throw new NotSupportedException();
- }
-
- public override ProfileInfoCollection FindProfilesByUserName(ProfileAuthenticationOption authenticationOption, string usernameToMatch, int pageIndex, int pageSize, out int totalRecords) {
- throw new NotSupportedException();
- }
-
- public override ProfileInfoCollection GetAllInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords) {
- throw new NotSupportedException();
- }
- public override ProfileInfoCollection GetAllProfiles(ProfileAuthenticationOption authenticationOption, int pageIndex, int pageSize, out int totalRecords) {
- throw new NotSupportedException();
- }
- public override int GetNumberOfInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate) {
- throw new NotSupportedException();
- }
- ///
- /// Returns the collection of settings property values for the current umbraco member.
- ///
- /// A describing the current application use.
- /// A containing the settings property group whose values are to be retrieved.
- ///
- /// A containing the values for the specified settings property group.
- ///
- public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection collection) {
- SettingsPropertyValueCollection settings = new SettingsPropertyValueCollection();
-
- if (collection.Count == 0)
- return settings;
-
- foreach(SettingsProperty property in collection){
- SettingsPropertyValue pv = new SettingsPropertyValue(property);
- settings.Add(pv);
- }
-
- // get the current user
- string username = (string)context["UserName"];
- Member m = Member.GetMemberFromLoginName(username);
- if (m == null)
- throw new ProviderException(String.Format("No member with username '{0}' exists", username));
-
- foreach (SettingsPropertyValue spv in settings) {
- if (m.getProperty(spv.Name) != null) {
- spv.Deserialized = true;
- spv.PropertyValue = m.getProperty(spv.Name).Value;
- }
- }
-
- return settings;
-
- }
-
- ///
- /// Sets the values of the specified group of property settings for the current umbraco member.
- ///
- /// A describing the current application usage.
- /// A representing the group of property settings to set.
- public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection collection) {
-
- string username = (string)context["UserName"];
- bool authenticated = (bool)context["IsAuthenticated"];
-
- if (String.IsNullOrEmpty(username) || collection.Count == 0)
- return;
-
- Member m = Member.GetMemberFromLoginName(username);
- if (m == null)
- throw new ProviderException(String.Format("No member with username '{0}' exists", username));
-
-
- foreach (SettingsPropertyValue spv in collection) {
- if (!authenticated && !(bool)spv.Property.Attributes["AllowAnonymous"])
- continue;
-
- if (m.getProperty(spv.Name) != null)
- m.getProperty(spv.Name).Value = spv.PropertyValue;
- }
- m.Save();
- }
- }
-}
+#region namespace
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Web.Security;
+using System.Configuration;
+using umbraco.BusinessLogic;
+using System.Security.Cryptography;
+using System.Web.Util;
+using System.Collections.Specialized;
+using System.Configuration.Provider;
+using umbraco.cms.businesslogic;
+using umbraco.cms.businesslogic.member;
+using System.Collections;
+using System.Web.Profile;
+#endregion
+
+namespace umbraco.providers.members
+{
+ public class UmbracoProfileProvider : ProfileProvider
+ {
+
+ private string _applicationName = "";
+
+ public override string ApplicationName
+ {
+ get
+ {
+ return _applicationName;
+ }
+ set
+ {
+ _applicationName = value;
+ }
+ }
+ public override string Description
+ {
+ get
+ {
+ return "Profile Provider for umbraco member profile data";
+ }
+ }
+ public override string Name
+ {
+ get
+ {
+ return base.Name;
+ }
+ }
+ public override void Initialize(string name, NameValueCollection config)
+ {
+
+ if (config == null)
+ throw new ArgumentNullException("Null configuration parameters");
+
+ if (String.IsNullOrEmpty(name))
+ name = "UmbracoProfileProvider";
+
+ base.Initialize(name, config);
+
+ _applicationName = config["applicationName"];
+ if (String.IsNullOrEmpty(_applicationName))
+ _applicationName = System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath;
+ config.Remove("applicationName");
+
+ // if the config element contains unused parameters we should throw an exception
+ if (config.Count > 0)
+ {
+ var attrib = config.GetKey(0);
+ if (string.IsNullOrEmpty(attrib) == false)
+ {
+ throw new ProviderException(String.Format("Unrecognized attribute: {0}", attrib));
+ }
+
+ }
+
+
+ }
+
+ public override int DeleteInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override int DeleteProfiles(string[] usernames)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override int DeleteProfiles(ProfileInfoCollection profiles)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override ProfileInfoCollection FindInactiveProfilesByUserName(ProfileAuthenticationOption authenticationOption, string usernameToMatch, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override ProfileInfoCollection FindProfilesByUserName(ProfileAuthenticationOption authenticationOption, string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override ProfileInfoCollection GetAllInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords)
+ {
+ throw new NotSupportedException();
+ }
+ public override ProfileInfoCollection GetAllProfiles(ProfileAuthenticationOption authenticationOption, int pageIndex, int pageSize, out int totalRecords)
+ {
+ throw new NotSupportedException();
+ }
+ public override int GetNumberOfInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate)
+ {
+ throw new NotSupportedException();
+ }
+ ///
+ /// Returns the collection of settings property values for the current umbraco member.
+ ///
+ /// A describing the current application use.
+ /// A containing the settings property group whose values are to be retrieved.
+ ///
+ /// A containing the values for the specified settings property group.
+ ///
+ public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection collection)
+ {
+ var settings = new SettingsPropertyValueCollection();
+
+ if (collection.Count == 0)
+ return settings;
+
+ foreach (SettingsProperty property in collection)
+ {
+ var pv = new SettingsPropertyValue(property);
+ settings.Add(pv);
+ }
+
+ // get the current user
+ var username = (string)context["UserName"];
+ var m = Member.GetMemberFromLoginName(username);
+ if (m == null)
+ throw new ProviderException(String.Format("No member with username '{0}' exists", username));
+
+ foreach (SettingsPropertyValue spv in settings)
+ {
+ if (m.getProperty(spv.Name) != null)
+ {
+ spv.Deserialized = true;
+ spv.PropertyValue = m.getProperty(spv.Name).Value;
+ }
+ }
+
+ return settings;
+
+ }
+
+ ///
+ /// Sets the values of the specified group of property settings for the current umbraco member.
+ ///
+ /// A describing the current application usage.
+ /// A representing the group of property settings to set.
+ public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection collection)
+ {
+
+ var username = (string)context["UserName"];
+ var authenticated = (bool)context["IsAuthenticated"];
+
+ if (string.IsNullOrEmpty(username) || collection.Count == 0)
+ return;
+
+ var m = Member.GetMemberFromLoginName(username);
+ if (m == null)
+ throw new ProviderException(String.Format("No member with username '{0}' exists", username));
+
+
+ foreach (SettingsPropertyValue spv in collection)
+ {
+ if (authenticated == false && (bool)spv.Property.Attributes["AllowAnonymous"] == false)
+ continue;
+
+ if (m.getProperty(spv.Name) != null)
+ m.getProperty(spv.Name).Value = spv.PropertyValue;
+ }
+ m.Save();
+ }
+ }
+}
diff --git a/src/umbraco.providers/members/MembersRoleProvider.cs b/src/umbraco.providers/members/UmbracoRoleProvider.cs
similarity index 97%
rename from src/umbraco.providers/members/MembersRoleProvider.cs
rename to src/umbraco.providers/members/UmbracoRoleProvider.cs
index 41a6da6568..bbae8aabfa 100644
--- a/src/umbraco.providers/members/MembersRoleProvider.cs
+++ b/src/umbraco.providers/members/UmbracoRoleProvider.cs
@@ -1,253 +1,256 @@
-#region namespace
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Web.Security;
-using System.Configuration;
-using umbraco.BusinessLogic;
-using System.Security.Cryptography;
-using System.Web.Util;
-using System.Collections.Specialized;
-using System.Configuration.Provider;
-using umbraco.cms.businesslogic;
-using umbraco.cms.businesslogic.member;
-using System.Collections;
-#endregion
-
-namespace umbraco.providers.members {
- public class UmbracoRoleProvider : RoleProvider {
- #region
- private string _ApplicationName = Member.UmbracoRoleProviderName;
- #endregion
-
- #region Properties
- ///
- /// Gets or sets the name of the application to store and retrieve role information for.
- ///
- ///
- /// The name of the application to store and retrieve role information for.
- public override string ApplicationName {
- get {
- return _ApplicationName;
- }
- set {
- if (string.IsNullOrEmpty(value))
- throw new ProviderException("ApplicationName cannot be empty.");
-
- if (value.Length > 0x100)
- throw new ProviderException("Provider application name too long.");
-
- _ApplicationName = value;
- }
- }
- #endregion
-
- #region Initialization Method
- ///
- /// Initializes the provider.
- ///
- /// The friendly name of the provider.
- /// A collection of the name/value pairs representing the provider-specific attributes specified in the configuration for this provider.
- /// The name of the provider is null.
- /// An attempt is made to call
- /// on a provider
- /// after the provider has already been initialized.
- /// The name of the provider has a length of zero.
- public override void Initialize(string name, NameValueCollection config) {
- // Initialize values from web.config
- if (config == null) throw new ArgumentNullException("config");
-
- if (name == null || name.Length == 0) name = "UmbracoMemberRoleProvider";
-
- if (String.IsNullOrEmpty(config["description"])) {
- config.Remove("description");
- config.Add("description", "Umbraco Member Role provider");
- }
-
- // Initialize the abstract base class.
- base.Initialize(name, config);
-
- this._ApplicationName = config["applicationName"];
- if (string.IsNullOrEmpty(this._ApplicationName))
- this._ApplicationName = SecUtility.GetDefaultAppName();
- }
- #endregion
-
- #region Methods
- ///
- /// Adds the specified user names to the specified roles for the configured applicationName.
- ///
- /// A string array of user names to be added to the specified roles.
- /// A string array of the role names to add the specified user names to.
- public override void AddUsersToRoles(string[] usernames, string[] roleNames) {
- ArrayList roles = new ArrayList();
- foreach (string role in roleNames)
- try {
- roles.Add(MemberGroup.GetByName(role).Id);
- } catch {
- throw new ProviderException(String.Format("No role with name '{0}' exists", role));
- }
- foreach (string username in usernames) {
- Member m = Member.GetMemberFromLoginName(username);
- foreach (int roleId in roles)
- m.AddGroup(roleId);
- }
- }
-
- ///
- /// Adds a new role to the data source for the configured applicationName.
- ///
- /// The name of the role to create.
- public override void CreateRole(string roleName) {
- MemberGroup.MakeNew(roleName, User.GetUser(0));
- }
-
- ///
- /// Removes a role from the data source for the configured applicationName.
- ///
- /// The name of the role to delete.
- /// If true, throw an exception if roleName has one or more members and do not delete roleName.
- ///
- /// true if the role was successfully deleted; otherwise, false.
- ///
- public override bool DeleteRole(string roleName, bool throwOnPopulatedRole) {
- MemberGroup group = MemberGroup.GetByName(roleName);
- if (group == null)
- throw new ProviderException(String.Format("No role with name '{0}' exists", roleName));
- else if (throwOnPopulatedRole && group.GetMembersAsIds().Length > 0)
- throw new ProviderException(String.Format("Can't delete role '{0}', there are members assigned to the role", roleName));
- else {
- foreach (Member m in group.GetMembers())
- m.RemoveGroup(group.Id);
- group.delete();
- return true;
- }
- }
-
- ///
- /// Gets an array of user names in a role where the user name contains the specified user name to match.
- ///
- /// The role to search in.
- /// The user name to search for.
- ///
- /// A string array containing the names of all the users where the user name matches usernameToMatch and the user is a member of the specified role.
- ///
- public override string[] FindUsersInRole(string roleName, string usernameToMatch) {
- ArrayList members = new ArrayList();
- MemberGroup group = MemberGroup.GetByName(roleName);
- if (group == null)
- throw new ProviderException(String.Format("No role with name '{0}' exists", roleName));
- else {
- foreach (Member m in group.GetMembers(usernameToMatch))
- members.Add(m.LoginName);
- return (string[])members.ToArray(typeof(string));
- }
- }
-
- ///
- /// Gets a list of all the roles for the configured applicationName.
- ///
- ///
- /// A string array containing the names of all the roles stored in the data source for the configured applicationName.
- ///
- public override string[] GetAllRoles() {
- ArrayList roles = new ArrayList();
- foreach (MemberGroup mg in MemberGroup.GetAll)
- roles.Add(mg.Text);
- return (string[])roles.ToArray(typeof(string));
- }
-
- ///
- /// Gets a list of the roles that a specified user is in for the configured applicationName.
- ///
- /// The user to return a list of roles for.
- ///
- /// A string array containing the names of all the roles that the specified user is in for the configured applicationName.
- ///
- public override string[] GetRolesForUser(string username) {
- ArrayList roles = new ArrayList();
- Member m = Member.GetMemberFromLoginName(username);
- if (m != null) {
- IDictionaryEnumerator ide = m.Groups.GetEnumerator();
- while (ide.MoveNext())
- roles.Add(((MemberGroup)ide.Value).Text);
- return (string[])roles.ToArray(typeof(string));
- } else
- throw new ProviderException(String.Format("No member with username '{0}' exists", username));
- }
-
- ///
- /// Gets a list of users in the specified role for the configured applicationName.
- ///
- /// The name of the role to get the list of users for.
- ///
- /// A string array containing the names of all the users who are members of the specified role for the configured applicationName.
- ///
- public override string[] GetUsersInRole(string roleName) {
- ArrayList members = new ArrayList();
- MemberGroup group = MemberGroup.GetByName(roleName);
- if (group == null)
- throw new ProviderException(String.Format("No role with name '{0}' exists", roleName));
- else {
- foreach (Member m in group.GetMembers())
- members.Add(m.LoginName);
- return (string[])members.ToArray(typeof(string));
- }
- }
-
- ///
- /// Gets a value indicating whether the specified user is in the specified role for the configured applicationName.
- ///
- /// The user name to search for.
- /// The role to search in.
- ///
- /// true if the specified user is in the specified role for the configured applicationName; otherwise, false.
- ///
- public override bool IsUserInRole(string username, string roleName) {
- Member m = Member.GetMemberFromLoginName(username);
- if (m == null)
- throw new ProviderException(String.Format("No user with name '{0}' exists", username));
- else {
- MemberGroup mg = MemberGroup.GetByName(roleName);
- if (mg == null)
- throw new ProviderException(String.Format("No Membergroup with name '{0}' exists", roleName));
- else
- return mg.HasMember(m.Id);
- }
- }
-
- ///
- /// Removes the specified user names from the specified roles for the configured applicationName.
- ///
- /// A string array of user names to be removed from the specified roles.
- /// A string array of role names to remove the specified user names from.
- public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames) {
- ArrayList roles = new ArrayList();
- foreach (string role in roleNames)
- try {
- roles.Add(MemberGroup.GetByName(role).Id);
- } catch {
- throw new ProviderException(String.Format("No role with name '{0}' exists", role));
- }
- foreach (string username in usernames) {
- Member m = Member.GetMemberFromLoginName(username);
- foreach (int roleId in roles)
- m.RemoveGroup(roleId);
- }
- }
-
- ///
- /// Gets a value indicating whether the specified role name already exists in the role data source for the configured applicationName.
- ///
- /// The name of the role to search for in the data source.
- ///
- /// true if the role name already exists in the data source for the configured applicationName; otherwise, false.
- ///
- public override bool RoleExists(string roleName) {
- MemberGroup mg = MemberGroup.GetByName(roleName);
- return mg != null;
- }
- #endregion
-
- }
-}
+#region namespace
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Web.Security;
+using System.Configuration;
+using umbraco.BusinessLogic;
+using System.Security.Cryptography;
+using System.Web.Util;
+using System.Collections.Specialized;
+using System.Configuration.Provider;
+using umbraco.cms.businesslogic;
+using umbraco.cms.businesslogic.member;
+using System.Collections;
+#endregion
+
+namespace umbraco.providers.members
+{
+ public class UmbracoRoleProvider : RoleProvider
+ {
+
+ #region
+ private string _ApplicationName = Member.UmbracoRoleProviderName;
+ #endregion
+
+ #region Properties
+ ///
+ /// Gets or sets the name of the application to store and retrieve role information for.
+ ///
+ ///
+ /// The name of the application to store and retrieve role information for.
+ public override string ApplicationName {
+ get {
+ return _ApplicationName;
+ }
+ set {
+ if (string.IsNullOrEmpty(value))
+ throw new ProviderException("ApplicationName cannot be empty.");
+
+ if (value.Length > 0x100)
+ throw new ProviderException("Provider application name too long.");
+
+ _ApplicationName = value;
+ }
+ }
+ #endregion
+
+ #region Initialization Method
+ ///
+ /// Initializes the provider.
+ ///
+ /// The friendly name of the provider.
+ /// A collection of the name/value pairs representing the provider-specific attributes specified in the configuration for this provider.
+ /// The name of the provider is null.
+ /// An attempt is made to call
+ /// on a provider
+ /// after the provider has already been initialized.
+ /// The name of the provider has a length of zero.
+ public override void Initialize(string name, NameValueCollection config) {
+ // Initialize values from web.config
+ if (config == null) throw new ArgumentNullException("config");
+
+ if (name == null || name.Length == 0) name = "UmbracoMemberRoleProvider";
+
+ if (String.IsNullOrEmpty(config["description"])) {
+ config.Remove("description");
+ config.Add("description", "Umbraco Member Role provider");
+ }
+
+ // Initialize the abstract base class.
+ base.Initialize(name, config);
+
+ this._ApplicationName = config["applicationName"];
+ if (string.IsNullOrEmpty(this._ApplicationName))
+ this._ApplicationName = SecUtility.GetDefaultAppName();
+ }
+ #endregion
+
+ #region Methods
+ ///
+ /// Adds the specified user names to the specified roles for the configured applicationName.
+ ///
+ /// A string array of user names to be added to the specified roles.
+ /// A string array of the role names to add the specified user names to.
+ public override void AddUsersToRoles(string[] usernames, string[] roleNames) {
+ ArrayList roles = new ArrayList();
+ foreach (string role in roleNames)
+ try {
+ roles.Add(MemberGroup.GetByName(role).Id);
+ } catch {
+ throw new ProviderException(String.Format("No role with name '{0}' exists", role));
+ }
+ foreach (string username in usernames) {
+ Member m = Member.GetMemberFromLoginName(username);
+ foreach (int roleId in roles)
+ m.AddGroup(roleId);
+ }
+ }
+
+ ///
+ /// Adds a new role to the data source for the configured applicationName.
+ ///
+ /// The name of the role to create.
+ public override void CreateRole(string roleName) {
+ MemberGroup.MakeNew(roleName, User.GetUser(0));
+ }
+
+ ///
+ /// Removes a role from the data source for the configured applicationName.
+ ///
+ /// The name of the role to delete.
+ /// If true, throw an exception if roleName has one or more members and do not delete roleName.
+ ///
+ /// true if the role was successfully deleted; otherwise, false.
+ ///
+ public override bool DeleteRole(string roleName, bool throwOnPopulatedRole) {
+ MemberGroup group = MemberGroup.GetByName(roleName);
+ if (group == null)
+ throw new ProviderException(String.Format("No role with name '{0}' exists", roleName));
+ else if (throwOnPopulatedRole && group.GetMembersAsIds().Length > 0)
+ throw new ProviderException(String.Format("Can't delete role '{0}', there are members assigned to the role", roleName));
+ else {
+ foreach (Member m in group.GetMembers())
+ m.RemoveGroup(group.Id);
+ group.delete();
+ return true;
+ }
+ }
+
+ ///
+ /// Gets an array of user names in a role where the user name contains the specified user name to match.
+ ///
+ /// The role to search in.
+ /// The user name to search for.
+ ///
+ /// A string array containing the names of all the users where the user name matches usernameToMatch and the user is a member of the specified role.
+ ///
+ public override string[] FindUsersInRole(string roleName, string usernameToMatch) {
+ ArrayList members = new ArrayList();
+ MemberGroup group = MemberGroup.GetByName(roleName);
+ if (group == null)
+ throw new ProviderException(String.Format("No role with name '{0}' exists", roleName));
+ else {
+ foreach (Member m in group.GetMembers(usernameToMatch))
+ members.Add(m.LoginName);
+ return (string[])members.ToArray(typeof(string));
+ }
+ }
+
+ ///
+ /// Gets a list of all the roles for the configured applicationName.
+ ///
+ ///
+ /// A string array containing the names of all the roles stored in the data source for the configured applicationName.
+ ///
+ public override string[] GetAllRoles() {
+ ArrayList roles = new ArrayList();
+ foreach (MemberGroup mg in MemberGroup.GetAll)
+ roles.Add(mg.Text);
+ return (string[])roles.ToArray(typeof(string));
+ }
+
+ ///
+ /// Gets a list of the roles that a specified user is in for the configured applicationName.
+ ///
+ /// The user to return a list of roles for.
+ ///
+ /// A string array containing the names of all the roles that the specified user is in for the configured applicationName.
+ ///
+ public override string[] GetRolesForUser(string username) {
+ ArrayList roles = new ArrayList();
+ Member m = Member.GetMemberFromLoginName(username);
+ if (m != null) {
+ IDictionaryEnumerator ide = m.Groups.GetEnumerator();
+ while (ide.MoveNext())
+ roles.Add(((MemberGroup)ide.Value).Text);
+ return (string[])roles.ToArray(typeof(string));
+ } else
+ throw new ProviderException(String.Format("No member with username '{0}' exists", username));
+ }
+
+ ///
+ /// Gets a list of users in the specified role for the configured applicationName.
+ ///
+ /// The name of the role to get the list of users for.
+ ///
+ /// A string array containing the names of all the users who are members of the specified role for the configured applicationName.
+ ///
+ public override string[] GetUsersInRole(string roleName) {
+ ArrayList members = new ArrayList();
+ MemberGroup group = MemberGroup.GetByName(roleName);
+ if (group == null)
+ throw new ProviderException(String.Format("No role with name '{0}' exists", roleName));
+ else {
+ foreach (Member m in group.GetMembers())
+ members.Add(m.LoginName);
+ return (string[])members.ToArray(typeof(string));
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether the specified user is in the specified role for the configured applicationName.
+ ///
+ /// The user name to search for.
+ /// The role to search in.
+ ///
+ /// true if the specified user is in the specified role for the configured applicationName; otherwise, false.
+ ///
+ public override bool IsUserInRole(string username, string roleName) {
+ Member m = Member.GetMemberFromLoginName(username);
+ if (m == null)
+ throw new ProviderException(String.Format("No user with name '{0}' exists", username));
+ else {
+ MemberGroup mg = MemberGroup.GetByName(roleName);
+ if (mg == null)
+ throw new ProviderException(String.Format("No Membergroup with name '{0}' exists", roleName));
+ else
+ return mg.HasMember(m.Id);
+ }
+ }
+
+ ///
+ /// Removes the specified user names from the specified roles for the configured applicationName.
+ ///
+ /// A string array of user names to be removed from the specified roles.
+ /// A string array of role names to remove the specified user names from.
+ public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames) {
+ ArrayList roles = new ArrayList();
+ foreach (string role in roleNames)
+ try {
+ roles.Add(MemberGroup.GetByName(role).Id);
+ } catch {
+ throw new ProviderException(String.Format("No role with name '{0}' exists", role));
+ }
+ foreach (string username in usernames) {
+ Member m = Member.GetMemberFromLoginName(username);
+ foreach (int roleId in roles)
+ m.RemoveGroup(roleId);
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether the specified role name already exists in the role data source for the configured applicationName.
+ ///
+ /// The name of the role to search for in the data source.
+ ///
+ /// true if the role name already exists in the data source for the configured applicationName; otherwise, false.
+ ///
+ public override bool RoleExists(string roleName) {
+ MemberGroup mg = MemberGroup.GetByName(roleName);
+ return mg != null;
+ }
+ #endregion
+
+ }
+}
diff --git a/src/umbraco.providers/umbraco.providers.csproj b/src/umbraco.providers/umbraco.providers.csproj
index de33276993..e7e5e28b12 100644
--- a/src/umbraco.providers/umbraco.providers.csproj
+++ b/src/umbraco.providers/umbraco.providers.csproj
@@ -80,9 +80,9 @@
-
-
-
+
+
+