Open Closed

Customize Login and Register Pages in the new Blazor web app solution #8256


User avatar
0
abhisheksreesaila created
  • ABP Framework version: v8.3.2
  • UI Type: Blazor WASM & Blazor Server (new blazor web app)
  • Database System: EF Core (PostgreSQL)
  • Tiered (for MVC) or Auth Server Separated (for Angular): Yes
  • Exception message and full stack trace:
  • Steps to reproduce the issue:
  • created a new blazor web app solution
  • Want to customize the REGISTER and LOGIN page
    • earlier, I was able to copy over CSHTML files to PAGES / Account folder and override the LoginModel.cs and RegisterModel.cs

Question : **How to do the same customization? in the BLAZOR new web app. **


18 Answer(s)
  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    earlier, I was able to copy over CSHTML files to PAGES / Account folder and override the LoginModel.cs and RegisterModel.cs Question : **How to do the same customization? in the BLAZOR new web app. **

    you can do it, copy pages to account folder of AuthServer project.

  • User Avatar
    0
    abhisheksreesaila created

    I see, makes sense. Let me try that and close this issue

  • User Avatar
    0
    abhisheksreesaila created

    I already have a solution. Can i add a "auth server" project now? or create a new solution and transfer my code?

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Can i add a "auth server" project now? or create a new solution and transfer my code?

    sorry, i didn't get it

  • User Avatar
    0
    abhisheksreesaila created

    I dont have "auth server" project now. How i can add it?

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Based on the information you provided, I thought you were using a tiered project.

    you can copy pages to account folder of Blazor project.

  • User Avatar
    0
    abhisheksreesaila created

    Apologies. I read it as Auth Server (for angular only).

    I tried adding that to the blazor project (server) but it didnt work.

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    It works for me

  • User Avatar
    0
    abhisheksreesaila created

    Thanks! I was able to get the the test page working too. it could be an issue with the script itself I wonder. atleast I can proceed at this point. Thank you for the fast response

  • User Avatar
    0
    abhisheksreesaila created

    Its working when you are adding text, however the button is not rendering. do you have any ideas? I have not added any custom code. Just copy paste the same code from the source module.

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    Add _ViewImports.cshtml

    @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
    @addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI
    @addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap
    @addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling
    
  • User Avatar
    0
    abhisheksreesaila created

    yes that worked like a charm! thanks you.

  • User Avatar
    0
    abhisheksreesaila created

    This is closely related to the https://abp.io/support/questions/8116/Change-default-admin-name-to-the-provided-USER-NAME-when-creating-a-new-tenant

    It didnt completely resolve the problem.

    Good News Code below

    • Create a new tenant with a new database (works)
    • Create a ADMIN USER with a USER NAME provided in the registration page (works)

    However, 2 problems **

    1. Duplicate Email Issue However, I see this error in the logs --> https://drive.google.com/file/d/1-fctzIxKqW5zSgSvLGbjCdaWh31mvWAV/view?usp=sharing

    2. Once we resolve #1, how do we assign custom permission to the admin user. This will be customer facing app - so i dont want the admin to meddle with CMS KIT, View Security Logs, Audit Logs etc. I just want him to look at APP pages that i created + Add new users if he wants to. Is that possible. The code below for permission is a simple prototype I was trying - but even that didnt work.

    PLEASE Help.

    *** removing import statement for brevity ******
    
    namespace Janvika.Finxplorer.Blazor.Pages.Account
    {
        public class CustomRegisterModel : RegisterModel
        {
            private readonly ITenantAppService _tenantAppService;
            private readonly IConfiguration _configuration;
            private readonly IdentityUserManager _identityUserManager;
            private readonly IUnitOfWorkManager _unitOfWorkManager;
            private readonly ILogger<CustomRegisterModel> _logger;
            private readonly IFinxplorerDbSchemaMigrator _dbSchemaMigrator;
            private readonly ICurrentTenant _currentTenant;
            private readonly IDataSeeder _dataSeeder;
            private readonly IIdentityRoleRepository _roleRepository;
            private readonly IPermissionManager _permissionManager;
    
            public CustomRegisterModel(
                IAuthenticationSchemeProvider schemeProvider,
                IOptions<AbpAccountOptions> accountOptions,
                IAccountExternalProviderAppService accountExternalProviderAppService,
                ICurrentPrincipalAccessor currentPrincipalAccessor,
                IHttpClientFactory httpClientFactory,
                ITenantAppService tenantAppService,
                IConfiguration configuration,
                IdentityUserManager identityUserManager,
                IUnitOfWorkManager unitOfWorkManager,
                ILogger<CustomRegisterModel> logger,
                IFinxplorerDbSchemaMigrator dbSchemaMigrator,
                ICurrentTenant currentTenant,
                IDataSeeder dataSeeder,
                IIdentityRoleRepository roleRepository,
                IPermissionManager permissionManager
            ) : base(schemeProvider, accountOptions, accountExternalProviderAppService, currentPrincipalAccessor, httpClientFactory)
            {
                _tenantAppService = tenantAppService;
                _configuration = configuration;
                _identityUserManager = identityUserManager;
                _unitOfWorkManager = unitOfWorkManager;
                _logger = logger;
                _dbSchemaMigrator = dbSchemaMigrator;
                _currentTenant = currentTenant;
                _dataSeeder = dataSeeder;
                _roleRepository = roleRepository;
                _permissionManager = permissionManager;
            }
    
            public override async Task<IActionResult> OnPostAsync()
            {
    
                   // Call the base OnPostAsync method to retain the base functionality
                var result = await base.OnPostAsync();
                if (!ModelState.IsValid)
                {
                    return result;
                }
    
                try
                {
                    var tenantName = $"{Input.UserName}-dedicated-tenant";
                    var defaultConnectionString = _configuration.GetConnectionString("Default");
    
                    if (string.IsNullOrEmpty(defaultConnectionString))
                    {
                        throw new Exception("Default connection string is not configured in app settings.");
                    }
    
                    // Create the database for the new tenant
                    var tenantConnectionString = CreateTenantSpecificConnectionString(defaultConnectionString, tenantName);
    
                    SaasTenantDto tenant;
                    using (var uow = _unitOfWorkManager.Begin(requiresNew: true, isTransactional: false))
                    {
                        var tenantCreateDto = new SaasTenantCreateDto
                        {
                            Name = tenantName,
                            AdminEmailAddress = Input.EmailAddress,
                            AdminPassword = Input.Password,
                            ConnectionStrings = new SaasTenantConnectionStringsDto
                            {
                                Default = tenantConnectionString
                            }
                        };
    
                        tenant = await _tenantAppService.CreateAsync(tenantCreateDto);
    
                        await MigrateAndSeedTenantDatabaseAsync(tenant.Id);
    
                        // Assign permissions to the existing admin role
                        await AssignPermissionsToAdminRoleAsync(tenant.Id);
    
                        await uow.CompleteAsync();
                    }
    
    
                        // Migrate and seed the tenant database
                  
    
                
    
                    // Redirect to the login page
                    return RedirectToPage("./Login");
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "An error occurred during registration");
                    // Redirect to the login page
                    return RedirectToPage("./Login");
                }
            }
    
            private string CreateTenantSpecificConnectionString(string defaultConnectionString, string tenantName)
            {
                var builder = new NpgsqlConnectionStringBuilder(defaultConnectionString);
                builder.Database = tenantName;
                return builder.ConnectionString;
            }
    
            private async Task MigrateAndSeedTenantDatabaseAsync(Guid tenantId)
            {
                using (_currentTenant.Change(tenantId))
                {
                  await _dbSchemaMigrator.MigrateAsync();
    
                  
                  await _dataSeeder.SeedAsync(
                        new DataSeedContext(tenantId)
                        .WithProperty(IdentityDataSeedContributor.AdminEmailPropertyName, Input.EmailAddress)
                        .WithProperty(IdentityDataSeedContributor.AdminUserNamePropertyName, Input.UserName)
                        .WithProperty(IdentityDataSeedContributor.AdminPasswordPropertyName, Input.Password)
                        
                        );
            
               
                
                }
            }
    
            private async Task AssignPermissionsToAdminRoleAsync(Guid tenantId)
            {
                using (_currentTenant.Change(tenantId))
                {
                    // Find the existing admin role
                    var adminRole = await _roleRepository.FindByNormalizedNameAsync("ADMIN");
                    if (adminRole == null)
                    {
                        throw new Exception("Admin role not found.");
                    }
    
             
                    var permissions = new[] { "My.CUSTOM" }; // permission names
                    foreach (var permission in permissions)
                    {
                        await _permissionManager.SetForRoleAsync(adminRole.Name, permission, true);
                    }
    
                    // Assign admin role to the registered user
                    var user = await _identityUserManager.FindByEmailAsync(Input.EmailAddress);
                    if (user != null)
                    {
                        await _identityUserManager.AddToRoleAsync(user, adminRole.Name);
                    }
                }
            }
        }
    }
    
    
  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Email 'abhishek101@gmail.com' is already taken.

    I think the error message is clear, there already a user with email abhishek101@gmail.com

    2.

    you can remove admin role for admin user manually, and assign a new role to this user.

    private async Task AssignPermissionsToAdminRoleAsync(Guid tenantId)
    {
        using (_currentTenant.Change(tenantId))
        {
            var user = await _identityUserManager.FindByEmailAsync(Input.EmailAddress);
            // remove admin role and assign a new role here
            ....
            
        }
    }
    
  • User Avatar
    0
    abhisheksreesaila created

    this is happening every time during the initial registration. Lets say, you have USER100, it will say USER100 is duplicate because the migration are running twice.

    DUPS EMAIL ISSUE

    I am spinning up a new database with a new user. this is the only user in the whole database. then its says duplicate email found.

    • Problem // its called the base.onpostsync() -- which adds the user.
    • Then we are creating a new tenant with an admin user with the same email and id. I think that' s the problem.
    • Do you agree?

    What code changes do you suggest? we want to make use of all the code in the base class except make sure to have a seperate db for each user.

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    this is happening every time during the initial registration. Lets say, you have USER100, it will say USER100 is duplicate because the migration are running twice.

    Okay, I got it. I think you should remove your migration code here. ABP will automatically migrate data.

    • Remove MigrateAndSeedTenantDatabaseAsync and AssignPermissionsToAdminRoleAsync
    • Add a new DataSeedContributor to assign roles&permissions for users

    https://abp.io/docs/latest/framework/infrastructure/data-seeding

  • User Avatar
    0
    abhisheksreesaila created

    thank you!

    Overall Goal :

    Enabled users to self register + Assign a **new **database for each new user.


    Problem I was calling var result = await base.OnPostAsync(); which registers a user in the host. a new tenant with a admin role with the same email address was the duplicate email.

    Solution : I override the post async and remove the RegisterLocalUserAsync which solved the duplicate email. I dont want to store this user in the host


    Current Problem: Attached the current code. https://drive.google.com/file/d/10yTLcz5QeiZ8Gy7FulbGPP5YzeOC_2UZ/view?usp=sharing Attached the current logs : https://drive.google.com/file/d/1eu1ukcUamo0Lrd-50aNEpkmWE6YdzlxK/view?usp=sharing

    this is needed for a TENANT with a new database to be created. ** await _dbSchemaMigrator.MigrateAsync();**

    This line is needed for the USERNAME to have the same name entered in the registration OR else the default admin name "admin" is used. ** await _dataSeeder.SeedAsync(new DataSeedContext(tenant.Id) .WithProperty(IdentityDataSeedContributor.AdminEmailPropertyName, Input.EmailAddress) .WithProperty(IdentityDataSeedContributor.AdminPasswordPropertyName, Input.Password) .WithProperty(IdentityDataSeedContributor.AdminUserNamePropertyName, Input.UserName)); **

    If I use both, I get a transient failure to ABP permission grants. How do i resolve the issue?

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    you can try change the time out value.

    Exception while reading from stream

Made with ❤️ on ABP v9.1.0-preview. Updated on December 26, 2024, 06:07