brockallen / BrockAllen.MembershipReboot

MembershipReboot is a user identity management and authentication library.
Other
742 stars 238 forks source link

Custom UserAccountService implementation #573

Closed tvdburgt closed 8 years ago

tvdburgt commented 8 years ago

I have a custom service that derives from UserAccountService. In this class I use custom validation, because the current ValidationResult/ValidationException implementation does not facilitate typed validation errors (only localized validation messages).

For this to work, I inherited the CreateAccount method and changed some things. However, this required me to modify the constructor as well (since I need to gain access to the repository, which is private). This results in the problem that the constructor needs to instantiate the internal classes EventBus and AggregateEventBus.

How would I be able to solve this?

Winters44 commented 8 years ago

+1, I think those should be public as well. However, I wonder if Brock has a reason for keeping them private. I'm curious to hear as well, since I ran into this same issue :)

Since the IEventBus interface is public, you could always create your own EventBus and AggregateEventBus classes.

brockallen commented 8 years ago

I don't think there was a real reason -- I guess I assumed there was no reason to get at them. Can you show me a snippet of code of what you're trying to do?

tvdburgt commented 8 years ago

Here's an example for custom email validation with typed exception values (this method is used by CreateAccount which requires access to UserRepository):

    protected new void ValidateEmail(SsoUserAccount account, string value)
    {
        EmailAddressAttribute validator = new EmailAddressAttribute();

        if (!validator.IsValid(value))
        {
            Tracing.Verbose("[UserAccountValidation.EmailIsValidFormat] validation failed: {0}, {1}, {2}", account.Tenant, account.Username, value);

            throw new CreateAccountValidationException(
                GetValidationMessage(MembershipRebootConstants.ValidationMessages.InvalidEmail),
                MembershipRebootConstants.ValidationMessages.InvalidEmail);
        }

        if (EmailExistsOtherThan(account, value))
        {
            Tracing.Verbose("[UserAccountValidation.EmailMustNotAlreadyExist] validation failed: {0}, {1}, {2}", account.Tenant, account.Username, value);

            throw new CreateAccountValidationException(
                GetValidationMessage(MembershipRebootConstants.ValidationMessages.EmailAlreadyInUse),
                MembershipRebootConstants.ValidationMessages.EmailAlreadyInUse);
        }
    }
tvdburgt commented 8 years ago

I solved this for now by just handling all GetValidationMessage commands and simply setting the message as resource key. Now my client application can supply their own translations at a later point.

public class GetValidationMessageCommandHandler : ICommandHandler<GetValidationMessage>
{
    public void Handle(GetValidationMessage cmd)
    {
        cmd.Message = cmd.ID;
    }
}