Created
August 11, 2014 08:45
-
-
Save tjrobinson/c8758ee849fe9d258b09 to your computer and use it in GitHub Desktop.
MembershipReboot UserAccountService implementation with custom username validation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.ComponentModel.DataAnnotations; | |
using System.Linq; | |
using BrockAllen.MembershipReboot; | |
namespace Acme.Users.MembershipReboot | |
{ | |
public class AcmeUserAccountService<TAccount> : UserAccountService<TAccount> | |
where TAccount : UserAccount | |
{ | |
public AcmeUserAccountService(IUserAccountRepository<TAccount> userRepository) | |
: this(new MembershipRebootConfiguration<TAccount>(), userRepository) { } | |
public AcmeUserAccountService(MembershipRebootConfiguration<TAccount> configuration, IUserAccountRepository<TAccount> userRepository) | |
: base(configuration, userRepository) | |
{ | |
// Set here so that we can access it from CreateAccount() | |
this.userRepository = userRepository; | |
// Set up our alternative usernameValidator which will be used in CreateAccount() | |
usernameValidator = new Lazy<AggregateValidator<TAccount>>(() => | |
{ | |
var val = new AggregateValidator<TAccount> | |
{ | |
UsernameMustNotAlreadyExist, | |
UsernameCanOnlyStartOrEndWithLetterOrDigit, | |
configuration.UsernameValidator | |
}; | |
return val; | |
}); | |
} | |
/// <remarks> | |
/// We have to replicate this here as it's private in UserAccountService | |
/// </remarks> | |
private readonly IUserAccountRepository<TAccount> userRepository; | |
/// <remarks> | |
/// We have to replicate this here as it's private in UserAccountService | |
/// </remarks> | |
private readonly Lazy<AggregateValidator<TAccount>> usernameValidator; | |
/// <remarks> | |
/// Copied from MembershipReboot internal UserAccountValidation class with only a minor change to the tracing information | |
/// </remarks> | |
public static readonly IValidator<TAccount> UsernameMustNotAlreadyExist = | |
new DelegateValidator<TAccount>((service, account, value) => | |
{ | |
if (service.UsernameExists(account.Tenant, value)) | |
{ | |
Tracing.Verbose("[AcmeUserAccountService.EmailMustNotAlreadyExist] validation failed: {0}, {1}, {2}", account.Tenant, account.Username, value); | |
return new ValidationResult(service.GetValidationMessage(MembershipRebootConstants.ValidationMessages.UsernameAlreadyInUse)); | |
} | |
return null; | |
}); | |
/// <remarks> | |
/// Copied from MembershipReboot internal UserAccountValidation class with only a minor change to the tracing information | |
/// </remarks> | |
public static readonly IValidator<TAccount> UsernameCanOnlyStartOrEndWithLetterOrDigit = | |
new DelegateValidator<TAccount>((service, account, value) => | |
{ | |
if (!Char.IsLetterOrDigit(value.First()) || !Char.IsLetterOrDigit(value.Last())) | |
{ | |
Tracing.Verbose("[AcmeUserAccountService.UsernameCanOnlyStartOrEndWithLetterOrDigit] validation failed: {0}, {1}, {2}", account.Tenant, account.Username, value); | |
return new ValidationResult(service.GetValidationMessage(MembershipRebootConstants.ValidationMessages.UsernameCanOnlyStartOrEndWithLetterOrDigit)); | |
} | |
return null; | |
}); | |
/// <remarks> | |
/// Copied from MembershipReboot UserAccountService class but altered to allow us to use our own username validation rules | |
/// </remarks> | |
public override TAccount CreateAccount(string tenant, string username, string password, string email, Guid? id = null, | |
DateTime? dateCreated = null) | |
{ | |
if (Configuration.EmailIsUsername) | |
{ | |
Tracing.Verbose("[AcmeUserAccountService.CreateAccount] applying email is username"); | |
username = email; | |
} | |
if (!Configuration.MultiTenant) | |
{ | |
Tracing.Verbose("[AcmeUserAccountService.CreateAccount] applying default tenant"); | |
tenant = Configuration.DefaultTenant; | |
} | |
Tracing.Information("[AcmeUserAccountService.CreateAccount] called: {0}, {1}, {2}", tenant, username, email); | |
TAccount account = this.userRepository.Create(); | |
Init(account, tenant, username, password, email, id, dateCreated); | |
ValidateEmail(account, email); | |
ValidateUsername(account, username); | |
ValidatePassword(account, password); | |
Tracing.Verbose("[AcmeUserAccountService.CreateAccount] success"); | |
userRepository.Add(account); | |
return account; | |
} | |
/// <remarks> | |
/// Copied from MembershipReboot UserAccountService class but altered to allow us to use our own username validation rules | |
/// </remarks> | |
protected new void ValidateUsername(TAccount account, string value) | |
{ | |
ValidationResult validationResult = usernameValidator.Value.Validate(this, account, value); | |
if (validationResult == null || validationResult == ValidationResult.Success) | |
return; | |
Tracing.Error("ValidateUsername failed: " + validationResult.ErrorMessage); | |
throw new ValidationException(validationResult.ErrorMessage); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment