From 141786dc8da302b0a49c5bcff44aa495e2018288 Mon Sep 17 00:00:00 2001 From: Rui Tome Date: Thu, 6 Apr 2023 12:18:27 +0100 Subject: [PATCH] [AC-432] Checking if any of the selected Organizations is already assigned to a Provider --- .../Services/ProviderService.cs | 8 +++++++- .../IProviderOrganizationRepository.cs | 1 + .../ProviderOrganizationRepository.cs | 14 +++++++++++++ .../ProviderOrganizationRepository.cs | 12 +++++++++++ src/Sql/Sql.sqlproj | 1 + ...iderOrganization_ReadByOrganizationIds.sql | 18 +++++++++++++++++ ...22_00_ProviderAddExistingOrganizations.sql | 20 +++++++++++++++++++ 7 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/Sql/dbo/Stored Procedures/ProviderOrganization_ReadByOrganizationIds.sql diff --git a/bitwarden_license/src/Commercial.Core/Services/ProviderService.cs b/bitwarden_license/src/Commercial.Core/Services/ProviderService.cs index 7062655583..ad5315f0d7 100644 --- a/bitwarden_license/src/Commercial.Core/Services/ProviderService.cs +++ b/bitwarden_license/src/Commercial.Core/Services/ProviderService.cs @@ -370,7 +370,13 @@ public class ProviderService : IProviderService var provider = await _providerRepository.GetByIdAsync(providerId); if (provider.Type != ProviderType.Reseller) { - throw new BadRequestException("Organization must be of type Reseller in order to assign Organizations to it."); + throw new BadRequestException("Provider must be of type Reseller in order to assign Organizations to it."); + } + + var existingProviderOrganizations = await _providerOrganizationRepository.GetManyByOrganizationIdsAsync(organizationIds); + if (existingProviderOrganizations.Any()) + { + throw new BadRequestException("Organizations must not be assigned to any Provider."); } var providerOrganizationsToInsert = organizationIds.Select(orgId => new ProviderOrganization { ProviderId = providerId, OrganizationId = orgId }); diff --git a/src/Core/Repositories/IProviderOrganizationRepository.cs b/src/Core/Repositories/IProviderOrganizationRepository.cs index 282bd1d326..d691985982 100644 --- a/src/Core/Repositories/IProviderOrganizationRepository.cs +++ b/src/Core/Repositories/IProviderOrganizationRepository.cs @@ -9,4 +9,5 @@ public interface IProviderOrganizationRepository : IRepository> GetManyDetailsByProviderAsync(Guid providerId); Task GetByOrganizationId(Guid organizationId); Task> GetManyByUserAsync(Guid userId); + Task> GetManyByOrganizationIdsAsync(IEnumerable organizationIds); } diff --git a/src/Infrastructure.Dapper/Repositories/ProviderOrganizationRepository.cs b/src/Infrastructure.Dapper/Repositories/ProviderOrganizationRepository.cs index 2ea12e9443..3c4b5087ee 100644 --- a/src/Infrastructure.Dapper/Repositories/ProviderOrganizationRepository.cs +++ b/src/Infrastructure.Dapper/Repositories/ProviderOrganizationRepository.cs @@ -99,6 +99,20 @@ public class ProviderOrganizationRepository : Repository> GetManyByOrganizationIdsAsync( + IEnumerable organizationIds) + { + using (var connection = new SqlConnection(ConnectionString)) + { + var results = await connection.QueryAsync( + $"[{Schema}].[ProviderOrganization_ReadByOrganizationIds]", + new { Ids = organizationIds.ToGuidIdArrayTVP() }, + commandType: CommandType.StoredProcedure); + + return results.ToList(); + } + } + private DataTable BuildProviderOrganizationsTable(SqlBulkCopy bulkCopy, IEnumerable providerOrganizations) { var po = providerOrganizations.FirstOrDefault(); diff --git a/src/Infrastructure.EntityFramework/Repositories/ProviderOrganizationRepository.cs b/src/Infrastructure.EntityFramework/Repositories/ProviderOrganizationRepository.cs index 7426aa43a5..44ee1237a4 100644 --- a/src/Infrastructure.EntityFramework/Repositories/ProviderOrganizationRepository.cs +++ b/src/Infrastructure.EntityFramework/Repositories/ProviderOrganizationRepository.cs @@ -67,4 +67,16 @@ public class ProviderOrganizationRepository : return data; } } + + public async Task> GetManyByOrganizationIdsAsync(IEnumerable organizationIds) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var query = from po in dbContext.ProviderOrganizations + where organizationIds.Contains(po.OrganizationId) + select po; + return await query.ToListAsync(); + } + } } diff --git a/src/Sql/Sql.sqlproj b/src/Sql/Sql.sqlproj index 249c2a8397..31e699f837 100644 --- a/src/Sql/Sql.sqlproj +++ b/src/Sql/Sql.sqlproj @@ -264,6 +264,7 @@ + diff --git a/src/Sql/dbo/Stored Procedures/ProviderOrganization_ReadByOrganizationIds.sql b/src/Sql/dbo/Stored Procedures/ProviderOrganization_ReadByOrganizationIds.sql new file mode 100644 index 0000000000..08cee543d1 --- /dev/null +++ b/src/Sql/dbo/Stored Procedures/ProviderOrganization_ReadByOrganizationIds.sql @@ -0,0 +1,18 @@ +CREATE PROCEDURE [dbo].[ProviderOrganization_ReadByOrganizationIds] + @Ids AS [dbo].[GuidIdArray] READONLY +AS +BEGIN + SET NOCOUNT ON + + IF (SELECT COUNT(1) FROM @Ids) < 1 + BEGIN + RETURN(-1) + END + + SELECT + * + FROM + [dbo].[ProviderOrganizationView] + WHERE + [OrganizationId] IN (SELECT [Id] FROM @Ids) +END \ No newline at end of file diff --git a/util/Migrator/DbScripts/2023-03-22_00_ProviderAddExistingOrganizations.sql b/util/Migrator/DbScripts/2023-03-22_00_ProviderAddExistingOrganizations.sql index 72b0525948..96533fc5b7 100644 --- a/util/Migrator/DbScripts/2023-03-22_00_ProviderAddExistingOrganizations.sql +++ b/util/Migrator/DbScripts/2023-03-22_00_ProviderAddExistingOrganizations.sql @@ -51,4 +51,24 @@ BEGIN FETCH NEXT @Take ROWS ONLY END END +GO + +CREATE OR ALTER PROCEDURE [dbo].[ProviderOrganization_ReadByOrganizationIds] + @Ids AS [dbo].[GuidIdArray] READONLY +AS +BEGIN + SET NOCOUNT ON + + IF (SELECT COUNT(1) FROM @Ids) < 1 + BEGIN + RETURN(-1) + END + + SELECT + * + FROM + [dbo].[ProviderOrganizationView] + WHERE + [OrganizationId] IN (SELECT [Id] FROM @Ids) +END GO \ No newline at end of file