diff --git a/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpIdentityAspNetCoreModule.cs b/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpIdentityAspNetCoreModule.cs index 019ef0469e..82679b10b7 100644 --- a/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpIdentityAspNetCoreModule.cs +++ b/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpIdentityAspNetCoreModule.cs @@ -15,6 +15,7 @@ namespace Volo.Abp.Identity.AspNetCore { builder .AddDefaultTokenProviders() + .AddTokenProvider(LinkUserTokenProviderConsts.LinkUserTokenProviderName) .AddSignInManager(); }); } diff --git a/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/LinkUserTokenProvider.cs b/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/LinkUserTokenProvider.cs new file mode 100644 index 0000000000..2fadb53a83 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/LinkUserTokenProvider.cs @@ -0,0 +1,19 @@ +using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Volo.Abp.Identity.AspNetCore +{ + public class LinkUserTokenProvider : DataProtectorTokenProvider + { + public LinkUserTokenProvider( + IDataProtectionProvider dataProtectionProvider, + IOptions options, + ILogger> logger) + : base(dataProtectionProvider, options, logger) + { + + } + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/LinkUserTokenProviderConsts.cs b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/LinkUserTokenProviderConsts.cs new file mode 100644 index 0000000000..044f034e46 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/LinkUserTokenProviderConsts.cs @@ -0,0 +1,9 @@ +namespace Volo.Abp.Identity +{ + public static class LinkUserTokenProviderConsts + { + public static string LinkUserTokenProviderName { get; set; } = "AbpLinkUser"; + + public static string LinkUserTokenPurpose { get; set; } = "AbpLinkUserLogin"; + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Microsoft/Extensions/DependencyInjection/AbpIdentityServiceCollectionExtensions.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Microsoft/Extensions/DependencyInjection/AbpIdentityServiceCollectionExtensions.cs index c37889a897..5dfdf2944d 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Microsoft/Extensions/DependencyInjection/AbpIdentityServiceCollectionExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Microsoft/Extensions/DependencyInjection/AbpIdentityServiceCollectionExtensions.cs @@ -33,8 +33,7 @@ namespace Microsoft.Extensions.DependencyInjection return services .AddIdentityCore(setupAction) .AddRoles() - .AddClaimsPrincipalFactory() - .AddTokenProvider(LinkUserTokenProvider.LinkUserTokenProviderName); + .AddClaimsPrincipalFactory(); } } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityLinkUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityLinkUserRepository.cs index 2040924d10..9e86d4b34b 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityLinkUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityLinkUserRepository.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -14,6 +14,11 @@ namespace Volo.Abp.Identity CancellationToken cancellationToken = default); Task> GetListAsync( + IdentityLinkUserInfo linkUserInfo, + List excludes = null, + CancellationToken cancellationToken = default); + + Task DeleteAsync( IdentityLinkUserInfo linkUserInfo, CancellationToken cancellationToken = default); } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserLinkManager.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserLinkManager.cs index 6f8c600daa..39b41247e4 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserLinkManager.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserLinkManager.cs @@ -1,4 +1,7 @@ -using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Encodings.Web; +using System.Threading; using System.Threading.Tasks; using Volo.Abp.Domain.Services; using Volo.Abp.MultiTenancy; @@ -20,74 +23,128 @@ namespace Volo.Abp.Identity CurrentTenant = currentTenant; } - public virtual async Task LinkAsync(IdentityLinkUserInfo sourceLinkUser, IdentityLinkUserInfo targetLinkUser) + public async Task> GetListAsync(IdentityLinkUserInfo linkUserInfo, bool includeIndirect = false, CancellationToken cancellationToken = default) { - if (sourceLinkUser.UserId == targetLinkUser.UserId && sourceLinkUser.TenantId == targetLinkUser.TenantId) + using (CurrentTenant.Change(null)) { - return; - } + var users = await IdentityLinkUserRepository.GetListAsync(linkUserInfo, cancellationToken: cancellationToken); + if (includeIndirect == false) + { + return users; + } - if (await IsLinkedAsync(sourceLinkUser, targetLinkUser)) - { - return; + var userInfos = new List() + { + linkUserInfo + }; + + var allUsers = new List(); + allUsers.AddRange(users); + + do + { + var nextUsers = new List(); + foreach (var user in users) + { + if (userInfos.Any(x => x.TenantId != user.SourceTenantId || x.UserId != user.SourceUserId)) + { + nextUsers.Add(new IdentityLinkUserInfo(user.SourceUserId, user.SourceTenantId)); + } + + if (userInfos.Any(x => x.TenantId != user.TargetTenantId || x.UserId != user.TargetUserId)) + { + nextUsers.Add(new IdentityLinkUserInfo(user.TargetUserId, user.TargetTenantId)); + } + } + + users = new List(); + foreach (var next in nextUsers) + { + users.AddRange(await IdentityLinkUserRepository.GetListAsync(next, userInfos, cancellationToken)); + } + + userInfos.AddRange(nextUsers); + allUsers.AddRange(users); + } while (users.Any()); + + return allUsers; } + } + public virtual async Task LinkAsync(IdentityLinkUserInfo sourceLinkUser, IdentityLinkUserInfo targetLinkUser, CancellationToken cancellationToken = default) + { using (CurrentTenant.Change(null)) { + if (sourceLinkUser.UserId == targetLinkUser.UserId && sourceLinkUser.TenantId == targetLinkUser.TenantId) + { + return; + } + + if (await IsLinkedAsync(sourceLinkUser, targetLinkUser, cancellationToken: cancellationToken)) + { + return; + } + var userLink = new IdentityLinkUser( GuidGenerator.Create(), sourceLinkUser, targetLinkUser); - await IdentityLinkUserRepository.InsertAsync(userLink, true); + await IdentityLinkUserRepository.InsertAsync(userLink, true, cancellationToken); } } - public virtual async Task IsLinkedAsync(IdentityLinkUserInfo sourceLinkUser, IdentityLinkUserInfo targetLinkUser) + public virtual async Task IsLinkedAsync(IdentityLinkUserInfo sourceLinkUser, IdentityLinkUserInfo targetLinkUser, bool includeIndirect = false, CancellationToken cancellationToken = default) { using (CurrentTenant.Change(null)) { - return await IdentityLinkUserRepository.FindAsync(sourceLinkUser, targetLinkUser) != null; + if (includeIndirect) + { + return (await GetListAsync(sourceLinkUser, true, cancellationToken: cancellationToken)) + .Any(x => x.SourceTenantId == targetLinkUser.TenantId && x.SourceUserId == targetLinkUser.UserId || + x.TargetTenantId == targetLinkUser.TenantId && x.TargetUserId == targetLinkUser.UserId); + } + return await IdentityLinkUserRepository.FindAsync(sourceLinkUser, targetLinkUser, cancellationToken) != null; } } - public virtual async Task UnlinkAsync(IdentityLinkUserInfo sourceLinkUser, IdentityLinkUserInfo targetLinkUser) + public virtual async Task UnlinkAsync(IdentityLinkUserInfo sourceLinkUser, IdentityLinkUserInfo targetLinkUser, CancellationToken cancellationToken = default) { - if (!await IsLinkedAsync(sourceLinkUser, targetLinkUser)) - { - return; - } - using (CurrentTenant.Change(null)) { - var linkedUser = await IdentityLinkUserRepository.FindAsync(sourceLinkUser, targetLinkUser); + if (!await IsLinkedAsync(sourceLinkUser, targetLinkUser, cancellationToken: cancellationToken)) + { + return; + } + + var linkedUser = await IdentityLinkUserRepository.FindAsync(sourceLinkUser, targetLinkUser, cancellationToken); if (linkedUser != null) { - await IdentityLinkUserRepository.DeleteAsync(linkedUser); + await IdentityLinkUserRepository.DeleteAsync(linkedUser, cancellationToken: cancellationToken); } } } - public virtual async Task GenerateLinkTokenAsync(IdentityLinkUserInfo targetLinkUser) + public virtual async Task GenerateLinkTokenAsync(IdentityLinkUserInfo targetLinkUser, CancellationToken cancellationToken = default) { using (CurrentTenant.Change(targetLinkUser.TenantId)) { var user = await UserManager.GetByIdAsync(targetLinkUser.UserId); return await UserManager.GenerateUserTokenAsync( user, - LinkUserTokenProvider.LinkUserTokenProviderName, - LinkUserTokenProvider.LinkUserTokenPurpose); + LinkUserTokenProviderConsts.LinkUserTokenProviderName, + LinkUserTokenProviderConsts.LinkUserTokenPurpose); } } - public virtual async Task VerifyLinkTokenAsync(IdentityLinkUserInfo targetLinkUser, string token) + public virtual async Task VerifyLinkTokenAsync(IdentityLinkUserInfo targetLinkUser, string token, CancellationToken cancellationToken = default) { using (CurrentTenant.Change(targetLinkUser.TenantId)) { var user = await UserManager.GetByIdAsync(targetLinkUser.UserId); return await UserManager.VerifyUserTokenAsync( user, - LinkUserTokenProvider.LinkUserTokenProviderName, - LinkUserTokenProvider.LinkUserTokenPurpose, + LinkUserTokenProviderConsts.LinkUserTokenProviderName, + LinkUserTokenProviderConsts.LinkUserTokenPurpose, token); } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/LinkUserTokenProvider.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/LinkUserTokenProvider.cs deleted file mode 100644 index 706c045578..0000000000 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/LinkUserTokenProvider.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Threading.Tasks; -using Microsoft.AspNetCore.Identity; - -namespace Volo.Abp.Identity -{ - public class LinkUserTokenProvider : TotpSecurityStampBasedTokenProvider - { - public const string LinkUserTokenProviderName = "AbpLinkUser"; - - public const string LinkUserTokenPurpose = "AbpLinkUserLogin"; - - public override Task CanGenerateTwoFactorTokenAsync(UserManager manager, IdentityUser user) - { - return Task.FromResult(false); - } - } -} diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityLinkUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityLinkUserRepository.cs index c7e81f327e..ab76f0cc48 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityLinkUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityLinkUserRepository.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -28,13 +28,35 @@ namespace Volo.Abp.Identity.EntityFrameworkCore , cancellationToken: GetCancellationToken(cancellationToken)); } - public virtual async Task> GetListAsync(IdentityLinkUserInfo linkUserInfo, CancellationToken cancellationToken = default) + public virtual async Task> GetListAsync(IdentityLinkUserInfo linkUserInfo, List excludes = null, + CancellationToken cancellationToken = default) { - return await (await GetDbSetAsync()) + IQueryable query = (await GetDbSetAsync()) .Where(x => + x.SourceUserId == linkUserInfo.UserId && x.SourceTenantId == linkUserInfo.TenantId || + x.TargetUserId == linkUserInfo.UserId && x.TargetTenantId == linkUserInfo.TenantId); + + if (!excludes.IsNullOrEmpty()) + { + foreach (var userInfo in excludes) + { + query = query.Where(x => + (x.SourceTenantId != userInfo.TenantId || x.SourceUserId != userInfo.UserId) && + (x.TargetTenantId != userInfo.TenantId || x.TargetUserId != userInfo.UserId)); + } + } + + return await query.ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); + } + + public virtual async Task DeleteAsync(IdentityLinkUserInfo linkUserInfo, CancellationToken cancellationToken = default) + { + var linkUsers = await (await GetDbSetAsync()).Where(x => x.SourceUserId == linkUserInfo.UserId && x.SourceTenantId == linkUserInfo.TenantId || x.TargetUserId == linkUserInfo.UserId && x.TargetTenantId == linkUserInfo.TenantId) .ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); + + await DeleteManyAsync(linkUsers, cancellationToken: cancellationToken); } } } diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityLinkUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityLinkUserRepository.cs index e670759e5c..bb30103dfc 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityLinkUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityLinkUserRepository.cs @@ -1,7 +1,6 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; -using System.Linq.Dynamic.Core; using System.Threading; using System.Threading.Tasks; using MongoDB.Driver; @@ -28,12 +27,34 @@ namespace Volo.Abp.Identity.MongoDB , cancellationToken: GetCancellationToken(cancellationToken)); } - public virtual async Task> GetListAsync(IdentityLinkUserInfo linkUserInfo, CancellationToken cancellationToken = default) + public virtual async Task> GetListAsync(IdentityLinkUserInfo linkUserInfo, List excludes = null, + CancellationToken cancellationToken = default) { - return await (await GetMongoQueryableAsync(cancellationToken)).Where(x => + var query = (await GetMongoQueryableAsync(cancellationToken)).Where(x => + x.SourceUserId == linkUserInfo.UserId && x.SourceTenantId == linkUserInfo.TenantId || + x.TargetUserId == linkUserInfo.UserId && x.TargetTenantId == linkUserInfo.TenantId); + + if (!excludes.IsNullOrEmpty()) + { + foreach (var userInfo in excludes) + { + query = query.Where(x => + (x.SourceTenantId != userInfo.TenantId || x.SourceUserId != userInfo.UserId) && + (x.TargetTenantId != userInfo.TenantId || x.TargetUserId != userInfo.UserId)); + } + } + + return await query.ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); + } + + public virtual async Task DeleteAsync(IdentityLinkUserInfo linkUserInfo, CancellationToken cancellationToken = default) + { + var linkUsers = await (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.SourceUserId == linkUserInfo.UserId && x.SourceTenantId == linkUserInfo.TenantId || x.TargetUserId == linkUserInfo.UserId && x.TargetTenantId == linkUserInfo.TenantId) .ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); + + await DeleteManyAsync(linkUsers, cancellationToken: cancellationToken); } } } diff --git a/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/LinkUserTokenProvider_Tests.cs b/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/LinkUserTokenProvider_Tests.cs index 2791de9a4f..8e85a1125f 100644 --- a/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/LinkUserTokenProvider_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/LinkUserTokenProvider_Tests.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Identity; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Options; using Shouldly; using Xunit; @@ -7,14 +8,37 @@ namespace Volo.Abp.Identity.AspNetCore { public class LinkUserTokenProvider_Tests : AbpIdentityAspNetCoreTestBase { + protected IIdentityUserRepository UserRepository { get; } + protected IIdentityLinkUserRepository IdentityLinkUserRepository { get; } + protected IdentityLinkUserManager IdentityLinkUserManager { get; } + protected IdentityTestData TestData { get; } + + public LinkUserTokenProvider_Tests() + { + UserRepository = GetRequiredService(); + IdentityLinkUserRepository = GetRequiredService(); + IdentityLinkUserManager = GetRequiredService(); + TestData = GetRequiredService(); + } + [Fact] public void LinkUserTokenProvider_Should_Be_Register() { var identityOptions = GetRequiredService>().Value; identityOptions.Tokens.ProviderMap.ShouldContain(x => - x.Key == LinkUserTokenProvider.LinkUserTokenProviderName && + x.Key == LinkUserTokenProviderConsts.LinkUserTokenProviderName && x.Value.ProviderType == typeof(LinkUserTokenProvider)); } + + [Fact] + public virtual async Task GenerateAndVerifyLinkTokenAsync() + { + var john = await UserRepository.GetAsync(TestData.UserJohnId); + var token = await IdentityLinkUserManager.GenerateLinkTokenAsync(new IdentityLinkUserInfo(john.Id, john.TenantId)); + (await IdentityLinkUserManager.VerifyLinkTokenAsync(new IdentityLinkUserInfo(john.Id, john.TenantId), token)).ShouldBeTrue(); + + (await IdentityLinkUserManager.VerifyLinkTokenAsync(new IdentityLinkUserInfo(john.Id, john.TenantId), "123123")).ShouldBeFalse(); + } } } diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityLinkUserManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityLinkUserManager_Tests.cs index 633f419da5..953824ef5b 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityLinkUserManager_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityLinkUserManager_Tests.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using Shouldly; using Xunit; @@ -19,6 +20,122 @@ namespace Volo.Abp.Identity TestData = GetRequiredService(); } + [Fact] + public async Task GetListAsync_Test() + { + var a = Guid.NewGuid(); + var b = Guid.NewGuid(); + var c = Guid.NewGuid(); + var d = Guid.NewGuid(); + var e = Guid.NewGuid(); + var f = Guid.NewGuid(); + var g = Guid.NewGuid(); + var h = Guid.NewGuid(); + var i = Guid.NewGuid(); + + await IdentityLinkUserRepository.InsertAsync(new IdentityLinkUser( + Guid.NewGuid(), + new IdentityLinkUserInfo(a, null), + new IdentityLinkUserInfo(b, null)), true); + + await IdentityLinkUserRepository.InsertAsync(new IdentityLinkUser( + Guid.NewGuid(), + new IdentityLinkUserInfo(c, null), + new IdentityLinkUserInfo(a, null)), true); + + await IdentityLinkUserRepository.InsertAsync(new IdentityLinkUser( + Guid.NewGuid(), + new IdentityLinkUserInfo(d, null), + new IdentityLinkUserInfo(c, null)), true); + + await IdentityLinkUserRepository.InsertAsync(new IdentityLinkUser( + Guid.NewGuid(), + new IdentityLinkUserInfo(e, null), + new IdentityLinkUserInfo(c, null)), true); + + await IdentityLinkUserRepository.InsertAsync(new IdentityLinkUser( + Guid.NewGuid(), + new IdentityLinkUserInfo(f, null), + new IdentityLinkUserInfo(e, null)), true); + + await IdentityLinkUserRepository.InsertAsync(new IdentityLinkUser( + Guid.NewGuid(), + new IdentityLinkUserInfo(g, null), + new IdentityLinkUserInfo(h, null)), true); + + await IdentityLinkUserRepository.InsertAsync(new IdentityLinkUser( + Guid.NewGuid(), + new IdentityLinkUserInfo(i, null), + new IdentityLinkUserInfo(h, null)), true); + + var linkUsers = await IdentityLinkUserManager.GetListAsync(new IdentityLinkUserInfo(a, null)); + linkUsers.Count.ShouldBe(2); + + linkUsers = await IdentityLinkUserManager.GetListAsync(new IdentityLinkUserInfo(f, null)); + linkUsers.Count.ShouldBe(1); + + linkUsers = await IdentityLinkUserManager.GetListAsync(new IdentityLinkUserInfo(g, null)); + linkUsers.Count.ShouldBe(1); + } + + [Fact] + public async Task GetListAsync_Indirect_Test() + { + var a = Guid.NewGuid(); + var b = Guid.NewGuid(); + var c = Guid.NewGuid(); + var d = Guid.NewGuid(); + var e = Guid.NewGuid(); + var f = Guid.NewGuid(); + var g = Guid.NewGuid(); + var h = Guid.NewGuid(); + var i = Guid.NewGuid(); + + await IdentityLinkUserRepository.InsertAsync(new IdentityLinkUser( + Guid.NewGuid(), + new IdentityLinkUserInfo(a, null), + new IdentityLinkUserInfo(b, null)), true); + + await IdentityLinkUserRepository.InsertAsync(new IdentityLinkUser( + Guid.NewGuid(), + new IdentityLinkUserInfo(c, null), + new IdentityLinkUserInfo(a, null)), true); + + await IdentityLinkUserRepository.InsertAsync(new IdentityLinkUser( + Guid.NewGuid(), + new IdentityLinkUserInfo(d, null), + new IdentityLinkUserInfo(c, null)), true); + + await IdentityLinkUserRepository.InsertAsync(new IdentityLinkUser( + Guid.NewGuid(), + new IdentityLinkUserInfo(e, null), + new IdentityLinkUserInfo(c, null)), true); + + await IdentityLinkUserRepository.InsertAsync(new IdentityLinkUser( + Guid.NewGuid(), + new IdentityLinkUserInfo(f, null), + new IdentityLinkUserInfo(e, null)), true); + + await IdentityLinkUserRepository.InsertAsync(new IdentityLinkUser( + Guid.NewGuid(), + new IdentityLinkUserInfo(g, null), + new IdentityLinkUserInfo(h, null)), true); + + await IdentityLinkUserRepository.InsertAsync(new IdentityLinkUser( + Guid.NewGuid(), + new IdentityLinkUserInfo(i, null), + new IdentityLinkUserInfo(h, null)), true); + + var linkUsers = await IdentityLinkUserManager.GetListAsync(new IdentityLinkUserInfo(a, null), includeIndirect: true); + linkUsers.Count.ShouldBe(5); + + linkUsers = await IdentityLinkUserManager.GetListAsync(new IdentityLinkUserInfo(f, null), includeIndirect: true); + linkUsers.Count.ShouldBe(5); + + linkUsers = await IdentityLinkUserManager.GetListAsync(new IdentityLinkUserInfo(g, null), includeIndirect: true); + linkUsers.Count.ShouldBe(2); + } + [Fact] public virtual async Task LinkAsync() { @@ -71,16 +188,5 @@ namespace Volo.Abp.Identity (await IdentityLinkUserManager.IsLinkedAsync(new IdentityLinkUserInfo(john.Id, john.TenantId), new IdentityLinkUserInfo(neo.Id, neo.TenantId))).ShouldBeFalse(); } - - [Fact] - public virtual async Task GenerateAndVerifyLinkTokenAsync() - { - var john = await UserRepository.GetAsync(TestData.UserJohnId); - var token = await IdentityLinkUserManager.GenerateLinkTokenAsync(new IdentityLinkUserInfo(john.Id, john.TenantId)); - (await IdentityLinkUserManager.VerifyLinkTokenAsync(new IdentityLinkUserInfo(john.Id, john.TenantId), token)).ShouldBeTrue(); - - (await IdentityLinkUserManager.VerifyLinkTokenAsync(new IdentityLinkUserInfo(john.Id, john.TenantId), "123123")).ShouldBeFalse(); - } - } } diff --git a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityLinkUserRepository_Tests.cs b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityLinkUserRepository_Tests.cs index e5dd6dcd5f..64dd9c5d20 100644 --- a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityLinkUserRepository_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityLinkUserRepository_Tests.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using Shouldly; using Volo.Abp.Modularity; using Xunit; @@ -54,5 +55,26 @@ namespace Volo.Abp.Identity davidLinkUsers.ShouldContain(x => x.SourceUserId == john.Id && x.SourceTenantId == john.TenantId); davidLinkUsers.ShouldContain(x => x.TargetUserId == neo.Id && x.TargetTenantId == neo.TenantId); } + + [Fact] + public async Task DeleteAsync() + { + var john = await UserRepository.GetAsync(TestData.UserJohnId); + var david = await UserRepository.GetAsync(TestData.UserDavidId); + + (await IdentityLinkUserRepository.FindAsync( + new IdentityLinkUserInfo(john.Id, john.TenantId), + new IdentityLinkUserInfo(david.Id, david.TenantId))).ShouldNotBeNull(); + + await IdentityLinkUserRepository.DeleteAsync(new IdentityLinkUserInfo(david.Id, david.TenantId)); + + (await IdentityLinkUserRepository.FindAsync( + new IdentityLinkUserInfo(john.Id, john.TenantId), + new IdentityLinkUserInfo(david.Id, david.TenantId))).ShouldBeNull(); + + (await IdentityLinkUserRepository.FindAsync( + new IdentityLinkUserInfo(david.Id, david.TenantId), + new IdentityLinkUserInfo(john.Id, john.TenantId))).ShouldBeNull(); + } } }