From 5f6e6bed7c4d7d1cded7ae21371b6775da1e4b5a Mon Sep 17 00:00:00 2001 From: Jimmy Vo Date: Mon, 6 Apr 2026 15:41:46 -0400 Subject: [PATCH 1/4] [PM-34147] Add GetManyConfirmedAndAcceptedDetailsByUserAsync to IOrganizationUserRepository. --- .../IOrganizationUserRepository.cs | 1 + .../OrganizationUserRepository.cs | 13 ++++++++++++ .../OrganizationUserRepository.cs | 17 +++++++++++++++- ...tails_ReadConfirmedAndAcceptedByUserId.sql | 14 +++++++++++++ ...tails_ReadConfirmedAndAcceptedByUserId.sql | 20 +++++++++++++++++++ 5 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 src/Sql/dbo/Stored Procedures/OrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId.sql create mode 100644 util/Migrator/DbScripts/2026-04-06_00_AddOrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId.sql diff --git a/src/Core/AdminConsole/Repositories/IOrganizationUserRepository.cs b/src/Core/AdminConsole/Repositories/IOrganizationUserRepository.cs index 4a965eb22cde..5c1fe73fa3d7 100644 --- a/src/Core/AdminConsole/Repositories/IOrganizationUserRepository.cs +++ b/src/Core/AdminConsole/Repositories/IOrganizationUserRepository.cs @@ -46,6 +46,7 @@ public interface IOrganizationUserRepository : IRepository> GetManyDetailsByOrganizationAsync_vNext(Guid organizationId, bool includeGroups = false, bool includeSharedCollections = false); Task> GetManyDetailsByUserAsync(Guid userId, OrganizationUserStatusType? status = null); + Task> GetManyConfirmedAndAcceptedDetailsByUserAsync(Guid userId); Task GetDetailsByUserAsync(Guid userId, Guid organizationId, OrganizationUserStatusType? status = null); Task UpdateGroupsAsync(Guid orgUserId, IEnumerable groupIds); diff --git a/src/Infrastructure.Dapper/AdminConsole/Repositories/OrganizationUserRepository.cs b/src/Infrastructure.Dapper/AdminConsole/Repositories/OrganizationUserRepository.cs index 7dbe4b18ff8e..054c50b65914 100644 --- a/src/Infrastructure.Dapper/AdminConsole/Repositories/OrganizationUserRepository.cs +++ b/src/Infrastructure.Dapper/AdminConsole/Repositories/OrganizationUserRepository.cs @@ -344,6 +344,19 @@ public async Task> GetManyDetai } } + public async Task> GetManyConfirmedAndAcceptedDetailsByUserAsync(Guid userId) + { + using (var connection = new SqlConnection(ConnectionString)) + { + var results = await connection.QueryAsync( + "[dbo].[OrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId]", + new { UserId = userId }, + commandType: CommandType.StoredProcedure); + + return results.ToList(); + } + } + public async Task GetDetailsByUserAsync(Guid userId, Guid organizationId, OrganizationUserStatusType? status = null) { diff --git a/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationUserRepository.cs b/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationUserRepository.cs index afc3de9e487f..03c79aba4b8f 100644 --- a/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationUserRepository.cs +++ b/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationUserRepository.cs @@ -380,7 +380,6 @@ public async Task GetDetailsByUserAsync(Gui { var dbContext = GetDatabaseContext(scope); var view = new OrganizationUserOrganizationDetailsViewQuery(); - var t = await (view.Run(dbContext)).ToArrayAsync(); var entity = await view.Run(dbContext) .FirstOrDefaultAsync(o => o.UserId == userId && o.OrganizationId == organizationId && @@ -574,6 +573,22 @@ public async Task> GetManyDetai } } + public async Task> GetManyConfirmedAndAcceptedDetailsByUserAsync(Guid userId) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var view = new OrganizationUserOrganizationDetailsViewQuery(); + var query = from organizationUserDetails in view.Run(dbContext) + where organizationUserDetails.UserId == userId && + (organizationUserDetails.Status == OrganizationUserStatusType.Confirmed || + organizationUserDetails.Status == OrganizationUserStatusType.Accepted) + select organizationUserDetails; + var organizationUsers = await query.ToListAsync(); + return organizationUsers; + } + } + public async Task> GetManyPublicKeysByOrganizationUserAsync(Guid organizationId, IEnumerable Ids) { using (var scope = ServiceScopeFactory.CreateScope()) diff --git a/src/Sql/dbo/Stored Procedures/OrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId.sql b/src/Sql/dbo/Stored Procedures/OrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId.sql new file mode 100644 index 000000000000..163f92f081ab --- /dev/null +++ b/src/Sql/dbo/Stored Procedures/OrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId.sql @@ -0,0 +1,14 @@ +CREATE PROCEDURE [dbo].[OrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId] + @UserId UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + SELECT + * + FROM + [dbo].[OrganizationUserOrganizationDetailsView] + WHERE + [UserId] = @UserId + AND [Status] IN (1, 2) -- Accepted = 1, Confirmed = 2 +END \ No newline at end of file diff --git a/util/Migrator/DbScripts/2026-04-06_00_AddOrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId.sql b/util/Migrator/DbScripts/2026-04-06_00_AddOrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId.sql new file mode 100644 index 000000000000..1abeb6213318 --- /dev/null +++ b/util/Migrator/DbScripts/2026-04-06_00_AddOrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId.sql @@ -0,0 +1,20 @@ +IF OBJECT_ID('[dbo].[OrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[OrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId] +END +GO + +CREATE PROCEDURE [dbo].[OrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId] + @UserId UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + SELECT + * + FROM + [dbo].[OrganizationUserOrganizationDetailsView] + WHERE + [UserId] = @UserId + AND [Status] IN (1, 2) -- Accepted = 1, Confirmed = 2 +END From 7ceb07e772bea00bd8e0752d2def5c77d5948878 Mon Sep 17 00:00:00 2001 From: Jimmy Vo Date: Mon, 6 Apr 2026 16:22:12 -0400 Subject: [PATCH 2/4] [PM-34147] Add database integration tests. --- ...irmedAndAcceptedDetailsByUserAsyncTests.cs | 157 ++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 test/Infrastructure.IntegrationTest/AdminConsole/Repositories/OrganizationUserRepository/GetManyConfirmedAndAcceptedDetailsByUserAsyncTests.cs diff --git a/test/Infrastructure.IntegrationTest/AdminConsole/Repositories/OrganizationUserRepository/GetManyConfirmedAndAcceptedDetailsByUserAsyncTests.cs b/test/Infrastructure.IntegrationTest/AdminConsole/Repositories/OrganizationUserRepository/GetManyConfirmedAndAcceptedDetailsByUserAsyncTests.cs new file mode 100644 index 000000000000..77e6a90fce70 --- /dev/null +++ b/test/Infrastructure.IntegrationTest/AdminConsole/Repositories/OrganizationUserRepository/GetManyConfirmedAndAcceptedDetailsByUserAsyncTests.cs @@ -0,0 +1,157 @@ +using Bit.Core.Enums; +using Bit.Core.Repositories; +using Xunit; + +namespace Bit.Infrastructure.IntegrationTest.AdminConsole.Repositories.OrganizationUserRepository; + +public class GetManyConfirmedAndAcceptedDetailsByUserAsyncTests +{ + [Theory, DatabaseData] + public async Task ReturnsDetails_WhenUserIsConfirmed( + IUserRepository userRepository, + IOrganizationRepository organizationRepository, + IOrganizationUserRepository organizationUserRepository) + { + // Arrange + var user = await userRepository.CreateTestUserAsync(); + var organization = await organizationRepository.CreateTestOrganizationAsync(); + await organizationUserRepository.CreateConfirmedTestOrganizationUserAsync(organization, user); + + // Act + var results = await organizationUserRepository.GetManyConfirmedAndAcceptedDetailsByUserAsync(user.Id); + + // Assert + Assert.Single(results); + var result = results.Single(); + Assert.Equal(organization.Id, result.OrganizationId); + Assert.Equal(user.Id, result.UserId); + Assert.Equal(OrganizationUserStatusType.Confirmed, result.Status); + + // Annul + await organizationRepository.DeleteAsync(organization); + await userRepository.DeleteAsync(user); + } + + [Theory, DatabaseData] + public async Task ReturnsDetails_WhenUserIsAccepted( + IUserRepository userRepository, + IOrganizationRepository organizationRepository, + IOrganizationUserRepository organizationUserRepository) + { + // Arrange + var user = await userRepository.CreateTestUserAsync(); + var organization = await organizationRepository.CreateTestOrganizationAsync(); + await organizationUserRepository.CreateAcceptedTestOrganizationUserAsync(organization, user); + + // Act + var results = await organizationUserRepository.GetManyConfirmedAndAcceptedDetailsByUserAsync(user.Id); + + // Assert + Assert.Single(results); + var result = results.Single(); + Assert.Equal(organization.Id, result.OrganizationId); + Assert.Equal(user.Id, result.UserId); + Assert.Equal(OrganizationUserStatusType.Accepted, result.Status); + + // Annul + await organizationRepository.DeleteAsync(organization); + await userRepository.DeleteAsync(user); + } + + [Theory, DatabaseData] + public async Task ReturnsDetailsAcrossMultipleOrganizations_WhenUserIsConfirmedOrAccepted( + IUserRepository userRepository, + IOrganizationRepository organizationRepository, + IOrganizationUserRepository organizationUserRepository) + { + // Arrange + var user = await userRepository.CreateTestUserAsync(); + + var confirmedOrg = await organizationRepository.CreateTestOrganizationAsync(); + await organizationUserRepository.CreateConfirmedTestOrganizationUserAsync(confirmedOrg, user); + + var acceptedOrg = await organizationRepository.CreateTestOrganizationAsync(); + await organizationUserRepository.CreateAcceptedTestOrganizationUserAsync(acceptedOrg, user); + + // Act + var results = await organizationUserRepository.GetManyConfirmedAndAcceptedDetailsByUserAsync(user.Id); + + // Assert + Assert.Equal(2, results.Count); + Assert.Contains(results, r => r.OrganizationId == confirmedOrg.Id && r.Status == OrganizationUserStatusType.Confirmed); + Assert.Contains(results, r => r.OrganizationId == acceptedOrg.Id && r.Status == OrganizationUserStatusType.Accepted); + + // Annul + await organizationRepository.DeleteAsync(confirmedOrg); + await organizationRepository.DeleteAsync(acceptedOrg); + await userRepository.DeleteAsync(user); + } + + [Theory, DatabaseData] + public async Task DoesNotReturnDetails_WhenUserIsInvited( + IUserRepository userRepository, + IOrganizationRepository organizationRepository, + IOrganizationUserRepository organizationUserRepository) + { + // Arrange + var user = await userRepository.CreateTestUserAsync(); + var organization = await organizationRepository.CreateTestOrganizationAsync(); + await organizationUserRepository.CreateTestOrganizationUserInviteAsync(organization); + + // Act + var results = await organizationUserRepository.GetManyConfirmedAndAcceptedDetailsByUserAsync(user.Id); + + // Assert + Assert.DoesNotContain(results, r => r.OrganizationId == organization.Id); + + // Annul + await organizationRepository.DeleteAsync(organization); + await userRepository.DeleteAsync(user); + } + + [Theory, DatabaseData] + public async Task DoesNotReturnDetails_WhenUserIsRevoked( + IUserRepository userRepository, + IOrganizationRepository organizationRepository, + IOrganizationUserRepository organizationUserRepository) + { + // Arrange + var user = await userRepository.CreateTestUserAsync(); + var organization = await organizationRepository.CreateTestOrganizationAsync(); + await organizationUserRepository.CreateRevokedTestOrganizationUserAsync(organization, user); + + // Act + var results = await organizationUserRepository.GetManyConfirmedAndAcceptedDetailsByUserAsync(user.Id); + + // Assert + Assert.DoesNotContain(results, r => r.OrganizationId == organization.Id); + + // Annul + await organizationRepository.DeleteAsync(organization); + await userRepository.DeleteAsync(user); + } + + [Theory, DatabaseData] + public async Task DoesNotReturnDetails_ForOtherUsers( + IUserRepository userRepository, + IOrganizationRepository organizationRepository, + IOrganizationUserRepository organizationUserRepository) + { + // Arrange + var targetUser = await userRepository.CreateTestUserAsync(); + var otherUser = await userRepository.CreateTestUserAsync(); + + var organization = await organizationRepository.CreateTestOrganizationAsync(); + await organizationUserRepository.CreateConfirmedTestOrganizationUserAsync(organization, otherUser); + + // Act + var results = await organizationUserRepository.GetManyConfirmedAndAcceptedDetailsByUserAsync(targetUser.Id); + + // Assert + Assert.DoesNotContain(results, r => r.OrganizationId == organization.Id); + + // Annul + await organizationRepository.DeleteAsync(organization); + await userRepository.DeleteManyAsync([targetUser, otherUser]); + } +} From ace1ef4bcbe8965b1dea1f3c654c4b0558536e29 Mon Sep 17 00:00:00 2001 From: Jimmy Vo Date: Wed, 8 Apr 2026 11:52:46 -0400 Subject: [PATCH 3/4] [PM-34147] Address code reviews. --- .../IOrganizationUserRepository.cs | 2 +- .../OrganizationUserRepository.cs | 4 ++-- .../OrganizationUserRepository.cs | 2 +- ...Details_ReadAcceptedConfirmedByUserId.sql} | 2 +- ...nfirmedAcceptedDetailsByUserAsyncTests.cs} | 18 ++++++++--------- ...nDetails_ReadAcceptedConfirmedByUserId.sql | 15 ++++++++++++++ ...tails_ReadConfirmedAndAcceptedByUserId.sql | 20 ------------------- 7 files changed, 29 insertions(+), 34 deletions(-) rename src/Sql/dbo/Stored Procedures/{OrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId.sql => OrganizationUserOrganizationDetails_ReadAcceptedConfirmedByUserId.sql} (91%) rename test/Infrastructure.IntegrationTest/AdminConsole/Repositories/OrganizationUserRepository/{GetManyConfirmedAndAcceptedDetailsByUserAsyncTests.cs => GetManyConfirmedAcceptedDetailsByUserAsyncTests.cs} (94%) create mode 100644 util/Migrator/DbScripts/2026-04-06_00_AddOrganizationUserOrganizationDetails_ReadAcceptedConfirmedByUserId.sql delete mode 100644 util/Migrator/DbScripts/2026-04-06_00_AddOrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId.sql diff --git a/src/Core/AdminConsole/Repositories/IOrganizationUserRepository.cs b/src/Core/AdminConsole/Repositories/IOrganizationUserRepository.cs index 5c1fe73fa3d7..5087edd2aade 100644 --- a/src/Core/AdminConsole/Repositories/IOrganizationUserRepository.cs +++ b/src/Core/AdminConsole/Repositories/IOrganizationUserRepository.cs @@ -46,7 +46,7 @@ public interface IOrganizationUserRepository : IRepository> GetManyDetailsByOrganizationAsync_vNext(Guid organizationId, bool includeGroups = false, bool includeSharedCollections = false); Task> GetManyDetailsByUserAsync(Guid userId, OrganizationUserStatusType? status = null); - Task> GetManyConfirmedAndAcceptedDetailsByUserAsync(Guid userId); + Task> GetManyConfirmedAcceptedDetailsByUserAsync(Guid userId); Task GetDetailsByUserAsync(Guid userId, Guid organizationId, OrganizationUserStatusType? status = null); Task UpdateGroupsAsync(Guid orgUserId, IEnumerable groupIds); diff --git a/src/Infrastructure.Dapper/AdminConsole/Repositories/OrganizationUserRepository.cs b/src/Infrastructure.Dapper/AdminConsole/Repositories/OrganizationUserRepository.cs index 054c50b65914..e62303d56e54 100644 --- a/src/Infrastructure.Dapper/AdminConsole/Repositories/OrganizationUserRepository.cs +++ b/src/Infrastructure.Dapper/AdminConsole/Repositories/OrganizationUserRepository.cs @@ -344,12 +344,12 @@ public async Task> GetManyDetai } } - public async Task> GetManyConfirmedAndAcceptedDetailsByUserAsync(Guid userId) + public async Task> GetManyConfirmedAcceptedDetailsByUserAsync(Guid userId) { using (var connection = new SqlConnection(ConnectionString)) { var results = await connection.QueryAsync( - "[dbo].[OrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId]", + "[dbo].[OrganizationUserOrganizationDetails_ReadAcceptedConfirmedByUserId]", new { UserId = userId }, commandType: CommandType.StoredProcedure); diff --git a/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationUserRepository.cs b/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationUserRepository.cs index 03c79aba4b8f..ba428490588e 100644 --- a/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationUserRepository.cs +++ b/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationUserRepository.cs @@ -573,7 +573,7 @@ public async Task> GetManyDetai } } - public async Task> GetManyConfirmedAndAcceptedDetailsByUserAsync(Guid userId) + public async Task> GetManyConfirmedAcceptedDetailsByUserAsync(Guid userId) { using (var scope = ServiceScopeFactory.CreateScope()) { diff --git a/src/Sql/dbo/Stored Procedures/OrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId.sql b/src/Sql/dbo/Stored Procedures/OrganizationUserOrganizationDetails_ReadAcceptedConfirmedByUserId.sql similarity index 91% rename from src/Sql/dbo/Stored Procedures/OrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId.sql rename to src/Sql/dbo/Stored Procedures/OrganizationUserOrganizationDetails_ReadAcceptedConfirmedByUserId.sql index 163f92f081ab..90524e536ca0 100644 --- a/src/Sql/dbo/Stored Procedures/OrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId.sql +++ b/src/Sql/dbo/Stored Procedures/OrganizationUserOrganizationDetails_ReadAcceptedConfirmedByUserId.sql @@ -1,4 +1,4 @@ -CREATE PROCEDURE [dbo].[OrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId] +CREATE PROCEDURE [dbo].[OrganizationUserOrganizationDetails_ReadAcceptedConfirmedByUserId] @UserId UNIQUEIDENTIFIER AS BEGIN diff --git a/test/Infrastructure.IntegrationTest/AdminConsole/Repositories/OrganizationUserRepository/GetManyConfirmedAndAcceptedDetailsByUserAsyncTests.cs b/test/Infrastructure.IntegrationTest/AdminConsole/Repositories/OrganizationUserRepository/GetManyConfirmedAcceptedDetailsByUserAsyncTests.cs similarity index 94% rename from test/Infrastructure.IntegrationTest/AdminConsole/Repositories/OrganizationUserRepository/GetManyConfirmedAndAcceptedDetailsByUserAsyncTests.cs rename to test/Infrastructure.IntegrationTest/AdminConsole/Repositories/OrganizationUserRepository/GetManyConfirmedAcceptedDetailsByUserAsyncTests.cs index 77e6a90fce70..256e9cbb6cfd 100644 --- a/test/Infrastructure.IntegrationTest/AdminConsole/Repositories/OrganizationUserRepository/GetManyConfirmedAndAcceptedDetailsByUserAsyncTests.cs +++ b/test/Infrastructure.IntegrationTest/AdminConsole/Repositories/OrganizationUserRepository/GetManyConfirmedAcceptedDetailsByUserAsyncTests.cs @@ -1,10 +1,10 @@ -using Bit.Core.Enums; +using Bit.Core.Enums; using Bit.Core.Repositories; using Xunit; namespace Bit.Infrastructure.IntegrationTest.AdminConsole.Repositories.OrganizationUserRepository; -public class GetManyConfirmedAndAcceptedDetailsByUserAsyncTests +public class GetManyConfirmedAcceptedDetailsByUserAsyncTests { [Theory, DatabaseData] public async Task ReturnsDetails_WhenUserIsConfirmed( @@ -18,7 +18,7 @@ public async Task ReturnsDetails_WhenUserIsConfirmed( await organizationUserRepository.CreateConfirmedTestOrganizationUserAsync(organization, user); // Act - var results = await organizationUserRepository.GetManyConfirmedAndAcceptedDetailsByUserAsync(user.Id); + var results = await organizationUserRepository.GetManyConfirmedAcceptedDetailsByUserAsync(user.Id); // Assert Assert.Single(results); @@ -44,7 +44,7 @@ public async Task ReturnsDetails_WhenUserIsAccepted( await organizationUserRepository.CreateAcceptedTestOrganizationUserAsync(organization, user); // Act - var results = await organizationUserRepository.GetManyConfirmedAndAcceptedDetailsByUserAsync(user.Id); + var results = await organizationUserRepository.GetManyConfirmedAcceptedDetailsByUserAsync(user.Id); // Assert Assert.Single(results); @@ -74,7 +74,7 @@ public async Task ReturnsDetailsAcrossMultipleOrganizations_WhenUserIsConfirmedO await organizationUserRepository.CreateAcceptedTestOrganizationUserAsync(acceptedOrg, user); // Act - var results = await organizationUserRepository.GetManyConfirmedAndAcceptedDetailsByUserAsync(user.Id); + var results = await organizationUserRepository.GetManyConfirmedAcceptedDetailsByUserAsync(user.Id); // Assert Assert.Equal(2, results.Count); @@ -99,7 +99,7 @@ public async Task DoesNotReturnDetails_WhenUserIsInvited( await organizationUserRepository.CreateTestOrganizationUserInviteAsync(organization); // Act - var results = await organizationUserRepository.GetManyConfirmedAndAcceptedDetailsByUserAsync(user.Id); + var results = await organizationUserRepository.GetManyConfirmedAcceptedDetailsByUserAsync(user.Id); // Assert Assert.DoesNotContain(results, r => r.OrganizationId == organization.Id); @@ -121,7 +121,7 @@ public async Task DoesNotReturnDetails_WhenUserIsRevoked( await organizationUserRepository.CreateRevokedTestOrganizationUserAsync(organization, user); // Act - var results = await organizationUserRepository.GetManyConfirmedAndAcceptedDetailsByUserAsync(user.Id); + var results = await organizationUserRepository.GetManyConfirmedAcceptedDetailsByUserAsync(user.Id); // Assert Assert.DoesNotContain(results, r => r.OrganizationId == organization.Id); @@ -145,7 +145,7 @@ public async Task DoesNotReturnDetails_ForOtherUsers( await organizationUserRepository.CreateConfirmedTestOrganizationUserAsync(organization, otherUser); // Act - var results = await organizationUserRepository.GetManyConfirmedAndAcceptedDetailsByUserAsync(targetUser.Id); + var results = await organizationUserRepository.GetManyConfirmedAcceptedDetailsByUserAsync(targetUser.Id); // Assert Assert.DoesNotContain(results, r => r.OrganizationId == organization.Id); @@ -154,4 +154,4 @@ public async Task DoesNotReturnDetails_ForOtherUsers( await organizationRepository.DeleteAsync(organization); await userRepository.DeleteManyAsync([targetUser, otherUser]); } -} +} \ No newline at end of file diff --git a/util/Migrator/DbScripts/2026-04-06_00_AddOrganizationUserOrganizationDetails_ReadAcceptedConfirmedByUserId.sql b/util/Migrator/DbScripts/2026-04-06_00_AddOrganizationUserOrganizationDetails_ReadAcceptedConfirmedByUserId.sql new file mode 100644 index 000000000000..324e04a4dd39 --- /dev/null +++ b/util/Migrator/DbScripts/2026-04-06_00_AddOrganizationUserOrganizationDetails_ReadAcceptedConfirmedByUserId.sql @@ -0,0 +1,15 @@ +CREATE OR ALTER PROCEDURE [dbo].[OrganizationUserOrganizationDetails_ReadAcceptedConfirmedByUserId] + @UserId UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + SELECT + * + FROM + [dbo].[OrganizationUserOrganizationDetailsView] + WHERE + [UserId] = @UserId + AND [Status] IN (1,2) -- 1 = Accepted, 2 = Confirmed +END +GO diff --git a/util/Migrator/DbScripts/2026-04-06_00_AddOrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId.sql b/util/Migrator/DbScripts/2026-04-06_00_AddOrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId.sql deleted file mode 100644 index 1abeb6213318..000000000000 --- a/util/Migrator/DbScripts/2026-04-06_00_AddOrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId.sql +++ /dev/null @@ -1,20 +0,0 @@ -IF OBJECT_ID('[dbo].[OrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId]') IS NOT NULL -BEGIN - DROP PROCEDURE [dbo].[OrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId] -END -GO - -CREATE PROCEDURE [dbo].[OrganizationUserOrganizationDetails_ReadConfirmedAndAcceptedByUserId] - @UserId UNIQUEIDENTIFIER -AS -BEGIN - SET NOCOUNT ON - - SELECT - * - FROM - [dbo].[OrganizationUserOrganizationDetailsView] - WHERE - [UserId] = @UserId - AND [Status] IN (1, 2) -- Accepted = 1, Confirmed = 2 -END From e83678a5fe4d5366b02995f8a1369bf6d3ed69b4 Mon Sep 17 00:00:00 2001 From: Jimmy Vo Date: Wed, 8 Apr 2026 12:08:46 -0400 Subject: [PATCH 4/4] [PM-34147] Fix lint issues --- .../GetManyConfirmedAcceptedDetailsByUserAsyncTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Infrastructure.IntegrationTest/AdminConsole/Repositories/OrganizationUserRepository/GetManyConfirmedAcceptedDetailsByUserAsyncTests.cs b/test/Infrastructure.IntegrationTest/AdminConsole/Repositories/OrganizationUserRepository/GetManyConfirmedAcceptedDetailsByUserAsyncTests.cs index 256e9cbb6cfd..b41ea081042f 100644 --- a/test/Infrastructure.IntegrationTest/AdminConsole/Repositories/OrganizationUserRepository/GetManyConfirmedAcceptedDetailsByUserAsyncTests.cs +++ b/test/Infrastructure.IntegrationTest/AdminConsole/Repositories/OrganizationUserRepository/GetManyConfirmedAcceptedDetailsByUserAsyncTests.cs @@ -1,4 +1,4 @@ -using Bit.Core.Enums; +using Bit.Core.Enums; using Bit.Core.Repositories; using Xunit; @@ -154,4 +154,4 @@ public async Task DoesNotReturnDetails_ForOtherUsers( await organizationRepository.DeleteAsync(organization); await userRepository.DeleteManyAsync([targetUser, otherUser]); } -} \ No newline at end of file +}