From 61d8e68a0aebed305f51c81125e713481e2fa7c3 Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Tue, 4 Feb 2020 12:44:27 +0300 Subject: [PATCH] Default roles on registration resolves https://github.com/abpframework/abp/issues/2721 --- .../Volo/Abp/Account/AccountAppService.cs | 17 +++++++++++-- .../Pages/Account/Register.cshtml.cs | 24 ++++++++++++++++--- .../Abp/Identity/IIdentityRoleRepository.cs | 4 ++++ .../EfCoreIdentityRoleRepository.cs | 5 ++++ .../MongoDB/MongoIdentityRoleRepository.cs | 5 ++++ .../Identity/IdentityRoleRepository_Tests.cs | 11 +++++++++ 6 files changed, 61 insertions(+), 5 deletions(-) diff --git a/modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/AccountAppService.cs b/modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/AccountAppService.cs index 9935078fe1..ab703dd223 100644 --- a/modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/AccountAppService.cs +++ b/modules/account/src/Volo.Abp.Account.Application/Volo/Abp/Account/AccountAppService.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Linq; +using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Volo.Abp.Account.Settings; using Volo.Abp.Application.Services; @@ -9,11 +10,14 @@ namespace Volo.Abp.Account { public class AccountAppService : ApplicationService, IAccountAppService { + private readonly IIdentityRoleRepository _roleRepository; protected IdentityUserManager UserManager { get; } public AccountAppService( - IdentityUserManager userManager) + IdentityUserManager userManager, + IIdentityRoleRepository roleRepository) { + _roleRepository = roleRepository; UserManager = userManager; } @@ -25,9 +29,18 @@ namespace Volo.Abp.Account (await UserManager.CreateAsync(user, input.Password).ConfigureAwait(false)).CheckErrors(); + await SetDefaultRolesAsync(user); + return ObjectMapper.Map(user); } + protected virtual async Task SetDefaultRolesAsync(IdentityUser user) + { + var defaultRoles = await _roleRepository.GetDefaultOnesAsync().ConfigureAwait(false); + + await UserManager.SetRolesAsync(user, defaultRoles.Select(r => r.Name)).ConfigureAwait(false); + } + protected virtual async Task CheckSelfRegistrationAsync() { if (!await SettingProvider.IsTrueAsync(AccountSettingNames.IsSelfRegistrationEnabled).ConfigureAwait(false)) diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs index 40b819e0e1..e521db5f9d 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Register.cshtml.cs @@ -1,8 +1,10 @@ using System.ComponentModel.DataAnnotations; +using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Volo.Abp.Account.Settings; +using Volo.Abp.Application.Dtos; using Volo.Abp.Identity; using Volo.Abp.Settings; using Volo.Abp.Uow; @@ -12,6 +14,8 @@ namespace Volo.Abp.Account.Web.Pages.Account { public class RegisterModel : AccountPageModel { + private readonly IIdentityRoleRepository _roleRepository; + [BindProperty(SupportsGet = true)] public string ReturnUrl { get; set; } @@ -21,7 +25,12 @@ namespace Volo.Abp.Account.Web.Pages.Account [BindProperty] public PostInput Input { get; set; } - public virtual async Task OnGet() + public RegisterModel(IIdentityRoleRepository roleRepository) + { + _roleRepository = roleRepository; + } + + public virtual async Task OnGetAsync() { await CheckSelfRegistrationAsync().ConfigureAwait(false); } @@ -35,15 +44,24 @@ namespace Volo.Abp.Account.Web.Pages.Account var user = new IdentityUser(GuidGenerator.Create(), Input.UserName, Input.EmailAddress, CurrentTenant.Id); - (await UserManager.CreateAsync(user, Input.Password).ConfigureAwait(false)).CheckErrors(); - + (await UserManager.CreateAsync(user, Input.Password).ConfigureAwait(false)).CheckErrors(); + await UserManager.SetEmailAsync(user, Input.EmailAddress).ConfigureAwait(false); + await SetDefaultRolesAsync(user); + await SignInManager.SignInAsync(user, isPersistent: false).ConfigureAwait(false); return Redirect(ReturnUrl ?? "/"); //TODO: How to ensure safety? IdentityServer requires it however it should be checked somehow! } + protected async Task SetDefaultRolesAsync(IdentityUser user) + { + var defaultRoles = await _roleRepository.GetDefaultOnesAsync().ConfigureAwait(false); + + await UserManager.SetRolesAsync(user, defaultRoles.Select(r => r.Name)).ConfigureAwait(false); + } + protected virtual async Task CheckSelfRegistrationAsync() { if (!await SettingProvider.IsTrueAsync(AccountSettingNames.IsSelfRegistrationEnabled).ConfigureAwait(false) || diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityRoleRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityRoleRepository.cs index 6ce3ce3c0c..ce8c07d22b 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityRoleRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityRoleRepository.cs @@ -21,5 +21,9 @@ namespace Volo.Abp.Identity bool includeDetails = false, CancellationToken cancellationToken = default ); + + Task> GetDefaultOnesAsync( + CancellationToken cancellationToken = default + ); } } \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs index 731cc6df23..d61da8d90e 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityRoleRepository.cs @@ -42,6 +42,11 @@ namespace Volo.Abp.Identity.EntityFrameworkCore .ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); } + public virtual async Task> GetDefaultOnesAsync(CancellationToken cancellationToken = default) + { + return await DbSet.Where(r => r.IsDefault).ToListAsync(cancellationToken: cancellationToken); + } + public override IQueryable WithDetails() { return GetQueryable().IncludeDetails(); diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs index 4bae372c8e..ac55012312 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityRoleRepository.cs @@ -43,5 +43,10 @@ namespace Volo.Abp.Identity.MongoDB .PageBy>(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)).ConfigureAwait(false); } + + public virtual async Task> GetDefaultOnesAsync(CancellationToken cancellationToken = default) + { + return await GetMongoQueryable().Where(r => r.IsDefault).ToListAsync(cancellationToken: cancellationToken); + } } } \ No newline at end of file diff --git a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityRoleRepository_Tests.cs b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityRoleRepository_Tests.cs index cd7ee1eb32..9f427d3f04 100644 --- a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityRoleRepository_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityRoleRepository_Tests.cs @@ -36,6 +36,17 @@ namespace Volo.Abp.Identity roles.ShouldContain(r => r.Name == "supporter"); } + [Fact] + public async Task GetDefaultOnesAsync() + { + var roles = await RoleRepository.GetDefaultOnesAsync().ConfigureAwait(false); + + foreach (var role in roles) + { + role.IsDefault.ShouldBe(true); + } + } + [Fact] public async Task GetCountAsync() {