public override async Task HandleAsync(EnqueueMailCommand command, CommandContext context, CancellationToken cancellationToken)
        {
            var mailTypeDefinition = _mailTypeCatalog.GetDefinition(command.Model.MailType);

            RequireValid(mailTypeDefinition != null, c => c.Model.MailType);

            var validationContext = new MailModelValidationContext(() => Lambda.MemberPath((EnqueueMailCommand c) => c.Model))
            {
                Model     = command.Model,
                DbContext = context.DbContext,
            };

            await mailTypeDefinition !.ValidateModelAsync(validationContext, cancellationToken).ConfigureAwait(false);

            if (validationContext.ErrorCode != null)
            {
                new ServiceErrorException(validationContext.ErrorCode.Value, validationContext.ErrorArgsFactory?.Invoke());
            }

            await _mailSenderService.EnqueueItemAsync(command.Model, context.DbContext, cancellationToken).ConfigureAwait(false);
        }
        public override async Task HandleAsync(ResetPasswordCommand command, CommandContext context, CancellationToken cancellationToken)
        {
            var userWithProfile = await
                                  (
                from u in context.DbContext.Users.FilterByName(command.UserName)
                select new { User = u, u.Profile }
                                  ).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);

            RequireExisting(userWithProfile, c => c.UserName);

            var user = userWithProfile.User;

            user.Password = null;
            user.PasswordVerificationToken = SecurityHelper.GenerateToken(_guidProvider);
            user.PasswordVerificationTokenExpirationDate = _clock.UtcNow + command.TokenExpirationTimeSpan;

            await using (var transaction = await context.DbContext.Database.TryBeginTransactionAsync(cancellationToken).ConfigureAwait(false))
            {
                await context.DbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false);

                await _mailSenderService.EnqueueItemAsync(new PasswordResetMailModel
                {
                    Culture           = context.ExecutionContext.Culture.Name,
                    UICulture         = context.ExecutionContext.UICulture.Name,
                    Name              = userWithProfile.Profile?.FirstName,
                    UserName          = user.UserName,
                    Email             = user.Email,
                    VerificationToken = user.PasswordVerificationToken,
                    VerificationTokenExpirationDate = user.PasswordVerificationTokenExpirationDate.Value,
                }, context.DbContext, cancellationToken).ConfigureAwait(false);

                if (transaction != null)
                {
                    await transaction.CommitAsync(cancellationToken).ConfigureAwait(false);
                }
            }
        }
        public override async Task HandleAsync(RegisterUserActivityCommand command, CommandContext context, CancellationToken cancellationToken)
        {
            var user = await context.DbContext.Users.GetByNameAsync(command.UserName, cancellationToken).ConfigureAwait(false);

            RequireExisting(user, c => c.UserName);

            bool lockedOut = false;

            var now = _clock.UtcNow;

            if (command.SuccessfulLogin == true)
            {
                user.PasswordFailuresSinceLastSuccess = 0;
                user.LastLoginDate = now;
            }
            else if (command.SuccessfulLogin == false)
            {
                var failures = user.PasswordFailuresSinceLastSuccess;
                if (_lockoutOptions == null || failures < _lockoutOptions.MaxFailedAccessAttempts)
                {
                    user.PasswordFailuresSinceLastSuccess += 1;
                    user.LastPasswordFailureDate           = now;
                }
                else
                {
                    user.LastPasswordFailureDate = now;
                    user.LastLockoutDate         = now;
                    user.IsLockedOut             = true;

                    lockedOut = true;
                }
            }

            if (command.UIActivity)
            {
                user.LastActivityDate = now;
            }

            if (lockedOut)
            {
                await using (var transaction = await context.DbContext.Database.TryBeginTransactionAsync(cancellationToken).ConfigureAwait(false))
                {
                    await context.DbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false);

                    await _mailSenderService.EnqueueItemAsync(new UserLockedOutMailModel
                    {
                        Culture   = context.ExecutionContext.Culture.Name,
                        UICulture = context.ExecutionContext.UICulture.Name,
                        Name      = user.Profile?.FirstName,
                        UserName  = user.UserName,
                        Email     = user.Email,
                    }, context.DbContext, cancellationToken).ConfigureAwait(false);

                    if (transaction != null)
                    {
                        await transaction.CommitAsync(cancellationToken).ConfigureAwait(false);
                    }
                }
            }
            else
            {
                await context.DbContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
            }
        }