From 8ba3e27a7dddb8ff52540e81c1b95ba7fa7f0b7a Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Wed, 25 Oct 2017 11:36:54 -0400 Subject: [PATCH] allow user delete if they are not the only owner --- .../IOrganizationUserRepository.cs | 2 +- .../SqlServer/OrganizationUserRepository.cs | 4 +-- .../Services/Implementations/UserService.cs | 9 +++---- src/Sql/Sql.sqlproj | 2 +- .../OrganizationUser_ReadCountByOnlyOwner.sql | 25 +++++++++++++++++++ ...nUser_ReadCountByOrganizationOwnerUser.sql | 15 ----------- .../dbo/Stored Procedures/User_DeleteById.sql | 1 - 7 files changed, 33 insertions(+), 25 deletions(-) create mode 100644 src/Sql/dbo/Stored Procedures/OrganizationUser_ReadCountByOnlyOwner.sql delete mode 100644 src/Sql/dbo/Stored Procedures/OrganizationUser_ReadCountByOrganizationOwnerUser.sql diff --git a/src/Core/Repositories/IOrganizationUserRepository.cs b/src/Core/Repositories/IOrganizationUserRepository.cs index cd36a67a90..8648c075d6 100644 --- a/src/Core/Repositories/IOrganizationUserRepository.cs +++ b/src/Core/Repositories/IOrganizationUserRepository.cs @@ -11,7 +11,7 @@ namespace Bit.Core.Repositories { Task GetCountByOrganizationIdAsync(Guid organizationId); Task GetCountByFreeOrganizationAdminUserAsync(Guid userId); - Task GetCountByOrganizationOwnerUserAsync(Guid userId); + Task GetCountByOnlyOwnerAsync(Guid userId); Task> GetManyByUserAsync(Guid userId); Task> GetManyByOrganizationAsync(Guid organizationId, OrganizationUserType? type); Task GetByOrganizationAsync(Guid organizationId, string email); diff --git a/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs b/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs index 0c5ba67275..754bf8535c 100644 --- a/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs +++ b/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs @@ -49,12 +49,12 @@ namespace Bit.Core.Repositories.SqlServer } } - public async Task GetCountByOrganizationOwnerUserAsync(Guid userId) + public async Task GetCountByOnlyOwnerAsync(Guid userId) { using(var connection = new SqlConnection(ConnectionString)) { var results = await connection.ExecuteScalarAsync( - "[dbo].[OrganizationUser_ReadCountByOrganizationOwnerUser]", + "[dbo].[OrganizationUser_ReadCountByOnlyOwner]", new { UserId = userId }, commandType: CommandType.StoredProcedure); diff --git a/src/Core/Services/Implementations/UserService.cs b/src/Core/Services/Implementations/UserService.cs index 1517707d96..505efd1754 100644 --- a/src/Core/Services/Implementations/UserService.cs +++ b/src/Core/Services/Implementations/UserService.cs @@ -7,7 +7,6 @@ using Microsoft.Extensions.Options; using Bit.Core.Models.Table; using Bit.Core.Repositories; using System.Linq; -using Microsoft.AspNetCore.Builder; using Bit.Core.Enums; using System.Security.Claims; using Bit.Core.Models; @@ -161,13 +160,13 @@ namespace Bit.Core.Services public override async Task DeleteAsync(User user) { - // Check if user is the owner of any organizations. - var organizationOwnerCount = await _organizationUserRepository.GetCountByOrganizationOwnerUserAsync(user.Id); - if(organizationOwnerCount > 0) + // Check if user is the only owner of any organizations. + var onlyOwnerCount = await _organizationUserRepository.GetCountByOnlyOwnerAsync(user.Id); + if(onlyOwnerCount > 0) { return IdentityResult.Failed(new IdentityError { - Description = "You must leave or delete any organizations that you are the owner of first." + Description = "You must leave or delete any organizations that you are the only owner of first." }); } diff --git a/src/Sql/Sql.sqlproj b/src/Sql/Sql.sqlproj index b7ba0d9235..942f5b89f9 100644 --- a/src/Sql/Sql.sqlproj +++ b/src/Sql/Sql.sqlproj @@ -114,7 +114,7 @@ - + diff --git a/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadCountByOnlyOwner.sql b/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadCountByOnlyOwner.sql new file mode 100644 index 0000000000..56b5b85040 --- /dev/null +++ b/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadCountByOnlyOwner.sql @@ -0,0 +1,25 @@ +CREATE PROCEDURE [dbo].[OrganizationUser_ReadCountByOnlyOwner] + @UserId UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + ;WITH [OwnerCountCTE] AS + ( + SELECT + OU.[UserId], + COUNT(1) OVER (PARTITION BY OU.[OrganizationId]) [ConfirmedOwnerCount] + FROM + [dbo].[OrganizationUser] OU + WHERE + OU.[Type] = 0 -- 0 = Owner + AND OU.[Status] = 2 -- 2 = Confirmed + ) + SELECT + COUNT(1) + FROM + [OwnerCountCTE] OC + WHERE + OC.[UserId] = @UserId + AND OC.[ConfirmedOwnerCount] = 1 +END diff --git a/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadCountByOrganizationOwnerUser.sql b/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadCountByOrganizationOwnerUser.sql deleted file mode 100644 index 8b6ad85048..0000000000 --- a/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadCountByOrganizationOwnerUser.sql +++ /dev/null @@ -1,15 +0,0 @@ -CREATE PROCEDURE [dbo].[OrganizationUser_ReadCountByOrganizationOwnerUser] - @UserId UNIQUEIDENTIFIER -AS -BEGIN - SET NOCOUNT ON - - SELECT - COUNT(1) - FROM - [dbo].[OrganizationUser] OU - WHERE - OU.[UserId] = @UserId - AND OU.[Type] = 0 - AND OU.[Status] = 2 -- 2 = Confirmed -END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/User_DeleteById.sql b/src/Sql/dbo/Stored Procedures/User_DeleteById.sql index 36cc209b26..fa1c3c92cb 100644 --- a/src/Sql/dbo/Stored Procedures/User_DeleteById.sql +++ b/src/Sql/dbo/Stored Procedures/User_DeleteById.sql @@ -64,7 +64,6 @@ BEGIN [dbo].[OrganizationUser] WHERE [UserId] = @Id - AND [Type] != 0 -- 0 = owner -- Finally, delete the user DELETE