From 605054835d5cc5a8ab80d8d1995b7088d6959a34 Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 2 Nov 2023 16:13:58 +0800 Subject: [PATCH] Remove all user related thing when deleting a user. --- .../Volo/Abp/Identity/IdentityLinkUserInfo.cs | 2 +- .../Volo/Abp/Identity/IdentityUserManager.cs | 21 ++++- .../Abp/Identity/IdentityUserManager_Tests.cs | 79 ++++++++++++++++--- 3 files changed, 86 insertions(+), 16 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityLinkUserInfo.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityLinkUserInfo.cs index 250f6f88d6..d2f5bdbff3 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityLinkUserInfo.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityLinkUserInfo.cs @@ -8,7 +8,7 @@ public class IdentityLinkUserInfo public virtual Guid? TenantId { get; set; } - public IdentityLinkUserInfo(Guid userId, Guid? tenantId) + public IdentityLinkUserInfo(Guid userId, Guid? tenantId = null) { UserId = userId; TenantId = tenantId; diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs index 5ce3663e14..57b97bfcd7 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs @@ -11,10 +11,10 @@ using Volo.Abp.Domain.Entities; using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Services; using Volo.Abp.EventBus.Distributed; +using Volo.Abp.EventBus.Local; using Volo.Abp.Identity.Settings; using Volo.Abp.Settings; using Volo.Abp.Threading; -using Volo.Abp.Timing; using Volo.Abp.Uow; namespace Volo.Abp.Identity; @@ -27,7 +27,7 @@ public class IdentityUserManager : UserManager, IDomainService protected ISettingProvider SettingProvider { get; } protected ICancellationTokenProvider CancellationTokenProvider { get; } protected IDistributedEventBus DistributedEventBus { get; } - + protected IIdentityLinkUserRepository IdentityLinkUserRepository { get; } protected override CancellationToken CancellationToken => CancellationTokenProvider.Token; public IdentityUserManager( @@ -45,7 +45,8 @@ public class IdentityUserManager : UserManager, IDomainService ICancellationTokenProvider cancellationTokenProvider, IOrganizationUnitRepository organizationUnitRepository, ISettingProvider settingProvider, - IDistributedEventBus distributedEventBus) + IDistributedEventBus distributedEventBus, + IIdentityLinkUserRepository identityLinkUserRepository) : base( store, optionsAccessor, @@ -62,6 +63,7 @@ public class IdentityUserManager : UserManager, IDomainService DistributedEventBus = distributedEventBus; RoleRepository = roleRepository; UserRepository = userRepository; + IdentityLinkUserRepository = identityLinkUserRepository; CancellationTokenProvider = cancellationTokenProvider; } @@ -76,6 +78,19 @@ public class IdentityUserManager : UserManager, IDomainService return await CreateAsync(user); } + public async override Task DeleteAsync(IdentityUser user) + { + user.Claims.Clear(); + user.Roles.Clear(); + user.Tokens.Clear(); + user.Logins.Clear(); + user.OrganizationUnits.Clear(); + await IdentityLinkUserRepository.DeleteAsync(new IdentityLinkUserInfo(user.Id, user.TenantId), CancellationToken); + await UpdateAsync(user); + + return await base.DeleteAsync(user); + } + public virtual async Task GetByIdAsync(Guid id) { var user = await Store.FindByIdAsync(id.ToString(), CancellationToken); diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs index 191972d13b..ec29d3d29a 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.DependencyInjection; @@ -26,8 +27,10 @@ public class IdentityUserManager_Tests : AbpIdentityDomainTestBase private readonly IUnitOfWorkManager _unitOfWorkManager; private readonly IdentityTestData _testData; private readonly ICurrentTenant _currentTenant; - protected IOptions _identityOptions { get; } - protected IDistributedEventBus DistributedEventBus { get; set; } + private readonly IOptions _identityOptions; + private readonly IdentityLinkUserManager _identityLinkUserManager; + + private IDistributedEventBus _distributedEventBus { get; set; } public IdentityUserManager_Tests() { @@ -40,12 +43,13 @@ public class IdentityUserManager_Tests : AbpIdentityDomainTestBase _unitOfWorkManager = GetRequiredService(); _currentTenant = GetRequiredService(); _identityOptions = GetRequiredService>(); + _identityLinkUserManager = GetRequiredService(); } protected override void AfterAddApplication(IServiceCollection services) { - DistributedEventBus = Substitute.For(); - services.Replace(ServiceDescriptor.Singleton(DistributedEventBus)); + _distributedEventBus = Substitute.For(); + services.Replace(ServiceDescriptor.Singleton(_distributedEventBus)); } [Fact] @@ -270,7 +274,7 @@ public class IdentityUserManager_Tests : AbpIdentityDomainTestBase (await _identityUserManager.CreateAsync(user)).CheckErrors(); - await DistributedEventBus.DidNotReceive() + await _distributedEventBus.DidNotReceive() .PublishAsync(Arg.Any(), Arg.Any(), Arg.Any()); var newUser = await _identityUserManager.FindByIdAsync(user.Id.ToString()); @@ -280,16 +284,16 @@ public class IdentityUserManager_Tests : AbpIdentityDomainTestBase { var oldUsername = newUser.UserName; await _identityUserManager.SetUserNameAsync(newUser, "newUserName"); - await DistributedEventBus.Received() + await _distributedEventBus.Received() .PublishAsync( Arg.Is(x => x.Id == newUser.Id && x.TenantId == newUser.TenantId && x.OldUserName == oldUsername && x.UserName == "newUserName"), Arg.Any(), Arg.Any()); } - DistributedEventBus.ClearReceivedCalls(); + _distributedEventBus.ClearReceivedCalls(); await _identityUserManager.SetUserNameAsync(newUser, newUser.UserName); - await DistributedEventBus.DidNotReceive() + await _distributedEventBus.DidNotReceive() .PublishAsync(Arg.Any(), Arg.Any(), Arg.Any()); } @@ -300,7 +304,7 @@ public class IdentityUserManager_Tests : AbpIdentityDomainTestBase (await _identityUserManager.CreateAsync(user)).CheckErrors(); - await DistributedEventBus.DidNotReceive() + await _distributedEventBus.DidNotReceive() .PublishAsync(Arg.Any(), Arg.Any(), Arg.Any()); var newUser = await _identityUserManager.FindByIdAsync(user.Id.ToString()); @@ -310,19 +314,70 @@ public class IdentityUserManager_Tests : AbpIdentityDomainTestBase { var oldEmail = newUser.Email; await _identityUserManager.SetEmailAsync(newUser, "newEmail@abp.io"); - await DistributedEventBus.Received() + await _distributedEventBus.Received() .PublishAsync( Arg.Is(x => x.Id == newUser.Id && x.TenantId == newUser.TenantId && x.OldEmail == oldEmail && x.Email == "newEmail@abp.io"), Arg.Any(), Arg.Any()); } - DistributedEventBus.ClearReceivedCalls(); + _distributedEventBus.ClearReceivedCalls(); await _identityUserManager.SetEmailAsync(newUser, newUser.Email); - await DistributedEventBus.DidNotReceive() + await _distributedEventBus.DidNotReceive() .PublishAsync(Arg.Any(), Arg.Any(), Arg.Any()); } + [Fact] + public async Task DeleteAsync() + { + await CreateRandomDefaultRoleAsync(); + var user = CreateRandomUser(); + (await _identityUserManager.CreateAsync(user)).CheckErrors(); + + var user2 = CreateRandomUser(); + (await _identityUserManager.CreateAsync(user2)).CheckErrors(); + + using (var uow = _unitOfWorkManager.Begin()) + { + user = await _identityUserManager.FindByIdAsync(user.Id.ToString()); + user.ShouldNotBeNull(); + + await _identityUserManager.AddClaimAsync(user, new Claim("test", "test")); + await _identityUserManager.AddLoginAsync(user, new UserLoginInfo("test", "test", "test")); + await _identityUserManager.AddDefaultRolesAsync(user); + user.SetToken("test", "test", "test"); + var ou = await _organizationUnitRepository.GetAsync(_lookupNormalizer.NormalizeName("OU11")); + await _identityUserManager.AddToOrganizationUnitAsync(user, ou); + await _identityLinkUserManager.LinkAsync(new IdentityLinkUserInfo(user.Id), new IdentityLinkUserInfo(user2.Id)); + + await uow.CompleteAsync(); + } + + using (var uow = _unitOfWorkManager.Begin()) + { + user = await _identityUserManager.FindByIdAsync(user.Id.ToString()); + user.ShouldNotBeNull(); + + user.Claims.Count.ShouldBeGreaterThan(0); + user.Logins.Count.ShouldBeGreaterThan(0); + user.Roles.Count.ShouldBeGreaterThan(0); + user.Tokens.Count.ShouldBeGreaterThan(0); + user.OrganizationUnits.Count.ShouldBeGreaterThan(0); + (await _identityLinkUserManager.IsLinkedAsync(new IdentityLinkUserInfo(user.Id), new IdentityLinkUserInfo(user2.Id))).ShouldBeTrue(); + + await _identityUserManager.DeleteAsync(user); + + user.Claims.Count.ShouldBe(0); + user.Logins.Count.ShouldBe(0); + user.Roles.Count.ShouldBe(0); + user.Tokens.Count.ShouldBe(0); + user.OrganizationUnits.Count.ShouldBe(0); + (await _identityLinkUserManager.IsLinkedAsync(new IdentityLinkUserInfo(user.Id), new IdentityLinkUserInfo(user2.Id))).ShouldBeFalse(); + + await uow.CompleteAsync(); + } + } + private async Task CreateRandomDefaultRoleAsync() { await _identityRoleRepository.InsertAsync(