Base solution for your next web application

Activities of "TimMackey"

Answer

This error keeps happening. Sometimes several times per day.

Answer

So far so good. I need a couple of weeks of dev to make sure it doesn't happen again.

Answer

before change:

  "scripts": {
    "ng": "ng",
    "publish": "gulp build && ng build --prod",
    "start": "gulp buildDev && ng serve --host 0.0.0.0 --port 4200",
    "hmr": "gulp buildDev && ng serve --host 0.0.0.0 --port 4200 --hmr",
    "test": "gulp buildDev && ng test",
    "pree2e": "webdriver-manager update --standalone false --gecko false",
    "e2e": "gulp buildDev && protractor",
    "create-dynamic-bundles": "gulp buildDev"
  },

after change:

  "scripts": {
    "ng": "ng",
    "publish": "gulp build && ng build --prod",
    "start": "ng serve --host 0.0.0.0 --port 4200",
    "hmr": "gulp buildDev && ng serve --host 0.0.0.0 --port 4200 --hmr",
    "test": "gulp buildDev && ng test",
    "pree2e": "webdriver-manager update --standalone false --gecko false",
    "e2e": "gulp buildDev && protractor",
    "create-dynamic-bundles": "gulp buildDev"
  },

Thank you for the suggestion.

Answer

Do you mean system RAM? I have 16 Gigs installed on my dev machine. Client Node.js is 1.5G at startup.
Dev Studio Diagnostic Tools reports 489M Process Memory at startup. I'll take a snapshot of these memorys next occurrence of the fault. Or should I be looking at something else?

I'll try an upgrade to ANZ 9.0 and see if that solves the problem. I'll get back to you in a couple of weeks.

Last upgrade: ANZ 8.0.0

Server: Web.Public\package.json(9): "abp-web-resources": "^3.3.0"

Client: package.json: "abp-ng2-module": "^5.0.0", "abp-web-resources": "^4.1.0",

I answer my own question.

Use AppConsts.remoteServiceBaseUrl directly in .ts code.

That solution works! Thank you!

I had to make a few minor changes to get the code to build. Here is the complete solution for anyone who might want to do something similar.

.Core/TtmUserLoginAttempts.cs (perform Add-Migration, Update-Database)

using Abp.Authorization.Users;

namespace ngTTM.Authorization.Users
{
    public class TtmUserLoginAttempt : UserLoginAttempt
    {
        public string ClientInfo { get; set; }
    }
}

.EntityFrameworkCore/EntityFrameworkCore/ntTTMDbContext.cs

        public virtual DbSet<TtmUserLoginAttempt> TtmUserLoginAttempts { get; set; }

.Web.Core/Models/TokenAuth/AuthenticateModel.cs

        public string ClientInfo { get; set; }

.Web.Core/Controllers/TokenAuthController.cs

private async Task<AbpLoginResult<Tenant, User>> GetLoginResultAsync(string usernameOrEmailAddress,
                                                                     string password,
                                                                     string tenancyName,
                                                                     string clientInfo)
{
    var loginResult = await _logInManager.LoginAsync(clientInfo,
                                                     usernameOrEmailAddress,
                                                     password,tenancyName);

    switch (loginResult.Result)
    {
        case AbpLoginResultType.Success:
            return loginResult;
        default:
            throw _abpLoginResultTypeHelper
                .CreateExceptionForFailedLoginAttempt(loginResult.Result,
                                                      usernameOrEmailAddress,
                                                      tenancyName);
    }
}

.Application/Authorization/LogInManager.cs

using Abp.Authorization;
using Abp.Authorization.Users;
using Abp.Configuration;
using Abp.Configuration.Startup;
using Abp.Dependency;
using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using Abp.Zero.Configuration;
using Microsoft.AspNetCore.Identity;
using ngTTM.Authorization.Roles;
using ngTTM.Authorization.Users;
using ngTTM.MultiTenancy;
using System.Threading.Tasks;
using System.Transactions;

namespace ngTTM.Authorization
{
    public class LogInManager : AbpLogInManager<Tenant, Role, User>
    {
        private IRepository<TtmUserLoginAttempt, long> _ttmUserLoginAttemptRepository;

        public LogInManager(
            UserManager userManager,
            IMultiTenancyConfig multiTenancyConfig,
            IRepository<Tenant> tenantRepository,
            IUnitOfWorkManager unitOfWorkManager,
            ISettingManager settingManager,
            IRepository<UserLoginAttempt, long> userLoginAttemptRepository,
            IUserManagementConfig userManagementConfig,
            IIocResolver iocResolver,
            RoleManager roleManager,
            IPasswordHasher<User> passwordHasher,
            UserClaimsPrincipalFactory claimsPrincipalFactory,
            IRepository<TtmUserLoginAttempt, long> ttmUserLoginAttemptRepository)
            : base(
                  userManager,
                  multiTenancyConfig,
                  tenantRepository,
                  unitOfWorkManager,
                  settingManager,
                  userLoginAttemptRepository,
                  userManagementConfig,
                  iocResolver,
                  passwordHasher,
                  roleManager,
                  claimsPrincipalFactory)
        {
            _ttmUserLoginAttemptRepository = ttmUserLoginAttemptRepository;
        }

        [UnitOfWork]
        public virtual async Task<AbpLoginResult<Tenant, User>> LoginAsync(string clientInfo,
                                                                               string userNameOrEmailAddress,
                                                                               string plainPassword,
                                                                               string tenancyName = null,
                                                                                 bool shouldLockout = true)
        {
            var result = await LoginAsyncInternal(userNameOrEmailAddress, plainPassword, tenancyName, shouldLockout);
            await SaveLoginAttemptAsync(clientInfo, result, tenancyName, userNameOrEmailAddress);
            return result;
        }

        protected virtual async Task SaveLoginAttemptAsync(string clientInfo,
                                         AbpLoginResult<Tenant, User> loginResult,
                                                               string tenancyName,
                                                               string userNameOrEmailAddress)
        {
            using (var uow = UnitOfWorkManager.Begin(TransactionScopeOption.Suppress))
            {
                var tenantId = loginResult.Tenant != null ? loginResult.Tenant.Id : (int?)null;

                using (UnitOfWorkManager.Current.SetTenantId(tenantId))
                {
                    var loginAttempt = new TtmUserLoginAttempt
                    {
                        TenantId = tenantId,
                        TenancyName = tenancyName,
                        UserId = loginResult.User != null ? loginResult.User.Id : (long?)null,
                        UserNameOrEmailAddress = userNameOrEmailAddress,
                        Result = loginResult.Result,
                        BrowserInfo = ClientInfoProvider.BrowserInfo,
                        ClientIpAddress = ClientInfoProvider.ClientIpAddress,
                        ClientName = ClientInfoProvider.ComputerName,
                        ClientInfo = clientInfo
                    };
                    await _ttmUserLoginAttemptRepository.InsertAsync(loginAttempt);
                    await UnitOfWorkManager.Current.SaveChangesAsync();
                    await uow.CompleteAsync();
                }
            }
        }
    }
}

/src/account/login/login.service.ts

    authenticate(finallyCallback?: () => void, redirectUrl?: string, captchaResponse?: string): void {
        finallyCallback = finallyCallback || (() => {
            this.spinnerService.hide();
        });

        // We may switch to localStorage instead of cookies
        this.authenticateModel.twoFactorRememberClientToken = this._utilsService.getCookieValue(LoginService.twoFactorRememberClientTokenName);
        this.authenticateModel.singleSignIn = UrlHelper.getSingleSignIn();
        this.authenticateModel.returnUrl = UrlHelper.getReturnUrl();
        this.authenticateModel.captchaResponse = captchaResponse;
        this.authenticateModel.clientInfo = this.getClientInfo();

        this._tokenAuthService
            .authenticate(this.authenticateModel)
            .subscribe({
                next: (result: AuthenticateResultModel) => {
                    this.processAuthenticateResult(result, redirectUrl);
                    finallyCallback();
                },
                error: (err: any) => {
                    finallyCallback();
                }
            });
    }

I was not able to find a LoginAsync method to override so used the closest match LoginAsyncInternal.

This is what I have so far:

LoginManager.cs

using Abp.Authorization;
using Abp.Authorization.Users;
using Abp.Configuration;
using Abp.Configuration.Startup;
using Abp.Dependency;
using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using Abp.Zero.Configuration;
using Microsoft.AspNetCore.Identity;
using ngTTM.Authorization.Roles;
using ngTTM.Authorization.Users;
using ngTTM.MultiTenancy;
using System.Threading.Tasks;
using System.Transactions;

namespace ngTTM.Authorization
{
    public class LogInManager : AbpLogInManager<Tenant, Role, User>
    {
        private IRepository<TtmUserLoginAttempt, long> _ttmUserLoginAttemptRepository;
        private string _clientInfo;

        public LogInManager(
            UserManager userManager,
            IMultiTenancyConfig multiTenancyConfig,
            IRepository<Tenant> tenantRepository,
            IUnitOfWorkManager unitOfWorkManager,
            ISettingManager settingManager,
            IRepository<UserLoginAttempt, long> userLoginAttemptRepository,
            IUserManagementConfig userManagementConfig,
            IIocResolver iocResolver,
            RoleManager roleManager,
            IPasswordHasher<User> passwordHasher,
            UserClaimsPrincipalFactory claimsPrincipalFactory,
            IRepository<TtmUserLoginAttempt, long> ttmUserLoginAttemptRepository)
            : base(
                  userManager,
                  multiTenancyConfig,
                  tenantRepository,
                  unitOfWorkManager,
                  settingManager,
                  userLoginAttemptRepository,
                  userManagementConfig,
                  iocResolver,
                  passwordHasher,
                  roleManager,
                  claimsPrincipalFactory)
        {
            _ttmUserLoginAttemptRepository = ttmUserLoginAttemptRepository;
        }

        protected override Task<AbpLoginResult<Tenant, User>> LoginAsyncInternal(UserLoginInfo login, string tenancyName)
        {
            TtmUserLoginInfo ttmUserLoginInfo = login as TtmUserLoginInfo;
            _clientInfo = ttmUserLoginInfo.ClientInfo;
            return base.LoginAsyncInternal(login, tenancyName);
        }

        protected override async Task SaveLoginAttemptAsync(AbpLoginResult<Tenant, User> loginResult, string tenancyName, string userNameOrEmailAddress)
        {
            using (var uow = UnitOfWorkManager.Begin(TransactionScopeOption.Suppress))
            {
                var tenantId = loginResult.Tenant != null ? loginResult.Tenant.Id : (int?)null;

                using (UnitOfWorkManager.Current.SetTenantId(tenantId))
                {
                    var loginAttempt = new TtmUserLoginAttempt
                    {
                        TenantId = tenantId,
                        TenancyName = tenancyName,
                        UserId = loginResult.User != null ? loginResult.User.Id : (long?)null,
                        UserNameOrEmailAddress = userNameOrEmailAddress,
                        Result = loginResult.Result,
                        BrowserInfo = ClientInfoProvider.BrowserInfo,
                        ClientIpAddress = ClientInfoProvider.ClientIpAddress,
                        ClientName = ClientInfoProvider.ComputerName,
                        ClientInfo = _clientInfo
                    };
                    await _ttmUserLoginAttemptRepository.InsertAsync(loginAttempt);
                    await UnitOfWorkManager.Current.SaveChangesAsync();
                    await uow.CompleteAsync();
                }
            }
        }

    }
}

TtmUserLoginInfo.cs

using Microsoft.AspNetCore.Identity;

namespace ngTTM.Authorization.Users
{
    public class TtmUserLoginInfo : UserLoginInfo
    {
        public string ClientInfo { get; set; }

        public TtmUserLoginInfo(string loginProvider, string providerKey, string displayName, string clientInfo): base(loginProvider, providerKey, displayName)
        {
            ClientInfo = clientInfo;
        }

    }
}

TokenAuthController.cs

        private async Task<AbpLoginResult<Tenant, User>> GetLoginResultAsync(string usernameOrEmailAddress, string password, string tenancyName, string clientInfo)
        {
            // the old way which works without clientInfo
            //AbpLoginResult<Tenant, User> loginResult = await _logInManager.LoginAsync(usernameOrEmailAddress, password, tenancyName);

            // the new way as recommended by @aaron
            TtmUserLoginInfo ttmUserLoginInfo = new TtmUserLoginInfo("", "", "", clientInfo);
            AbpLoginResult<Tenant, User> loginResult = await _logInManager.LoginAsync(ttmUserLoginInfo, tenancyName);

            switch (loginResult.Result)
            {
                case AbpLoginResultType.Success:
                    return loginResult;
                default:
                    throw _abpLoginResultTypeHelper.CreateExceptionForFailedLoginAttempt(loginResult.Result, usernameOrEmailAddress, tenancyName);
            }
        }

While I am able to pass clientInfo into LogInManager, the login fails (no surprise) since I don't know what values to use for loginProvider, providerKey, and displayName for UserLoginInfo.

What are the argument values to use to login to my site (and localhost)?

@ismcagdas -

Adding my ClientInfo string to the loginResult.Identity claim list is too late in the process, as LogInManager.SaveLoginAttemptAsync is called before logInManager.LoginAsync returns loginResult.

Showing 101 to 110 of 285 entries