protected virtual void SaveLoginAttempt(ShaLoginResult <TTenant, TUser> loginResult, string tenancyName, string userNameOrEmailAddress)
        {
            UnitOfWorkManager.Current?.SaveChanges();

            using (var uow = UnitOfWorkManager.Begin(TransactionScopeOption.Suppress))
            {
                var tenantId = loginResult.Tenant?.Id;
                using (UnitOfWorkManager.Current.SetTenantId(tenantId))
                {
                    var loginAttempt = new ShaUserLoginAttempt
                    {
                        TenantId    = tenantId,
                        TenancyName = tenancyName,

                        UserId = loginResult.User?.Id,
                        UserNameOrEmailAddress = userNameOrEmailAddress,

                        Result = loginResult.Result,

                        BrowserInfo     = ClientInfoProvider.BrowserInfo,
                        ClientIpAddress = ClientInfoProvider.ClientIpAddress,
                        ClientName      = ClientInfoProvider.ComputerName,
                    };

                    ShaLoginAttemptRepository.Insert(loginAttempt);

                    uow.Complete();
                }
            }
        }
        public virtual async Task <ShaLoginResult <TTenant, TUser> > LoginAsync(UserLoginInfo login, string imei = null, string tenancyName = null)
        {
            ShaLoginResult <TTenant, TUser> result = null;

            using (var uow = UnitOfWorkManager.Begin(TransactionScopeOption.RequiresNew))
            {
                result = await LoginAsyncInternal(login, tenancyName);

                await uow.CompleteAsync();
            }

            await SaveLoginAttemptAsync(result, imei, tenancyName, login.ProviderKey + "@" + login.LoginProvider);

            return(result);
        }
        public virtual async Task <ShaLoginResult <TTenant, TUser> > LoginAsync(string userNameOrEmailAddress, string plainPassword, string imei = null, string tenancyName = null, bool shouldLockout = true)
        {
            ShaLoginResult <TTenant, TUser> result = null;

            using (var uow = UnitOfWorkManager.Begin(TransactionScopeOption.RequiresNew))
            {
                result = await LoginAsyncInternal(userNameOrEmailAddress, plainPassword, imei, tenancyName, shouldLockout);

                await uow.CompleteAsync();
            }

            await SaveLoginAttemptAsync(result, imei, tenancyName, userNameOrEmailAddress);

            return(result);
        }
        public virtual async Task SaveLoginAttemptAsync(ShaLoginResult <TTenant, TUser> loginResult, string imei,
                                                        string tenancyName, string userNameOrEmailAddress)
        {
            if (UnitOfWorkManager.Current != null)
            {
                await UnitOfWorkManager.Current.SaveChangesAsync();
            }

            using (var uow = UnitOfWorkManager.Begin(TransactionScopeOption.Suppress))
            {
                var tenantId = loginResult.Tenant?.Id;
                using (UnitOfWorkManager.Current.SetTenantId(tenantId))
                {
                    var loginAttempt = new ShaUserLoginAttempt
                    {
                        TenantId    = tenantId,
                        TenancyName = tenancyName,

                        UserId = loginResult.User?.Id,
                        UserNameOrEmailAddress = userNameOrEmailAddress,

                        Result = loginResult.Result,

                        BrowserInfo        = ClientInfoProvider.BrowserInfo,
                        ClientIpAddress    = ClientInfoProvider.ClientIpAddress,
                        ClientName         = ClientInfoProvider.ComputerName,
                        IMEI               = imei,
                        DeviceName         = await GetDeviceNameAsync(imei),
                        LoginAttemptNumber = loginResult.Result == ShaLoginResultType.InvalidPassword
                            ? loginResult.User?.AccessFailedCount + 1
                            : null
                    };

                    await ShaLoginAttemptRepository.InsertAsync(loginAttempt);

                    await uow.CompleteAsync();
                }
            }
        }