diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs index 9b7b86f8d4..cc88d3d792 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs @@ -197,6 +197,12 @@ public interface IIdentityUserRepository : IBasicRepository CancellationToken cancellationToken = default ); + Task> GetUsersByPasskeyIdAsync( + [NotNull] byte[] credentialId, + bool includeDetails = false, + CancellationToken cancellationToken = default + ); + Task FindByNormalizedUserNameAsync( Guid? tenantId, [NotNull] string normalizedUserName, 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 a893bcf530..3fad7f2916 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 @@ -687,4 +687,35 @@ public class IdentityUserManager : UserManager, IDomainService } } } + + public virtual async Task FindByPasskeyIdInHostAsync(byte[] credentialId) + { + if (MultiTenancyOptions.Value.UserSharingStrategy == TenantUserSharingStrategy.Isolated) + { + return await base.FindByPasskeyIdAsync(credentialId); + } + + using (CurrentTenant.Change(null)) + { + using (DataFilter.Disable()) + { + var hostusers = await UserRepository.GetUsersByPasskeyIdAsync(credentialId, cancellationToken: CancellationToken); + //host user first + var hostUser = hostusers.FirstOrDefault(x => x.TenantId == null) ?? hostusers.FirstOrDefault(); + if (hostUser == null) + { + return null; + } + + using (DataFilter.Enable()) + { + using (CurrentTenant.Change(hostUser.TenantId)) + { + return await base.FindByPasskeyIdAsync(credentialId); + } + } + } + } + } + } diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs index e472448fc9..cd6fa072a1 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs @@ -502,6 +502,15 @@ public class EfCoreIdentityUserRepository : EfCoreRepository> GetUsersByPasskeyIdAsync(byte[] credentialId, bool includeDetails = false, CancellationToken cancellationToken = default) + { + return await (await GetDbSetAsync()) + .IncludeDetails(includeDetails) + .Where(u => u.Passkeys.Any(x => x.CredentialId.SequenceEqual(credentialId))) + .OrderBy(x => x.Id) + .ToListAsync(GetCancellationToken(cancellationToken)); + } + public virtual async Task FindByNormalizedUserNameAsync(Guid? tenantId, string normalizedUserName, bool includeDetails = true, CancellationToken cancellationToken = default) { return await (await GetDbSetAsync()) diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs index c2c23344eb..9209946d7f 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs @@ -493,6 +493,14 @@ public class MongoIdentityUserRepository : MongoDbRepository> GetUsersByPasskeyIdAsync(byte[] credentialId, bool includeDetails = false, CancellationToken cancellationToken = default) + { + return await (await GetQueryableAsync(cancellationToken)) + .OrderBy(x => x.Id) + .Where(u => u.Passkeys.Any(x => x.CredentialId == credentialId)) + .ToListAsync(cancellationToken: cancellationToken); + } + public virtual async Task FindByNormalizedUserNameAsync(Guid? tenantId, string normalizedUserName, bool includeDetails = true, CancellationToken cancellationToken = default) { return await (await GetQueryableAsync(cancellationToken))