diff --git a/src/Core/Services/Implementations/OrganizationService.cs b/src/Core/Services/Implementations/OrganizationService.cs index 1bfa44ae1..91bae08da 100644 --- a/src/Core/Services/Implementations/OrganizationService.cs +++ b/src/Core/Services/Implementations/OrganizationService.cs @@ -444,9 +444,9 @@ namespace Bit.Core.Services if(plan.Type == PlanType.Free) { - var ownerExistingOrgCount = + var adminCount = await _organizationUserRepository.GetCountByFreeOrganizationAdminUserAsync(signup.Owner.Id); - if(ownerExistingOrgCount > 0) + if(adminCount > 0) { throw new BadRequestException("You can only be an admin of one free organization."); } @@ -894,10 +894,17 @@ namespace Bit.Core.Services throw new BadRequestException("Already accepted."); } - var ownerExistingOrgCount = await _organizationUserRepository.GetCountByFreeOrganizationAdminUserAsync(user.Id); - if(ownerExistingOrgCount > 0) + if(orgUser.Type == OrganizationUserType.Owner || orgUser.Type == OrganizationUserType.Admin) { - throw new BadRequestException("You can only be an admin of one free organization."); + var org = await _organizationRepository.GetByIdAsync(orgUser.OrganizationId); + if(org.PlanType == PlanType.Free) + { + var adminCount = await _organizationUserRepository.GetCountByFreeOrganizationAdminUserAsync(user.Id); + if(adminCount > 0) + { + throw new BadRequestException("You can only be an admin of one free organization."); + } + } } var tokenValidationFailed = true; @@ -944,17 +951,25 @@ namespace Bit.Core.Services throw new BadRequestException("User not valid."); } + var org = await _organizationRepository.GetByIdAsync(organizationId); + if(org.PlanType == PlanType.Free && + (orgUser.Type == OrganizationUserType.Admin || orgUser.Type == OrganizationUserType.Owner)) + { + var adminCount = await _organizationUserRepository.GetCountByFreeOrganizationAdminUserAsync( + orgUser.UserId.Value); + if(adminCount > 0) + { + throw new BadRequestException("User can only be an admin of one free organization."); + } + } + orgUser.Status = OrganizationUserStatusType.Confirmed; orgUser.Key = key; orgUser.Email = null; await _organizationUserRepository.ReplaceAsync(orgUser); var user = await _userRepository.GetByIdAsync(orgUser.UserId.Value); - var org = await _organizationRepository.GetByIdAsync(organizationId); - if(user != null && org != null) - { - await _mailService.SendOrganizationConfirmedEmailAsync(org.Name, user.Email); - } + await _mailService.SendOrganizationConfirmedEmailAsync(org.Name, user.Email); // self-hosted org users get premium access if(_globalSettings.SelfHosted && !user.Premium && org.Enabled) diff --git a/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadCountByFreeOrganizationAdminUser.sql b/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadCountByFreeOrganizationAdminUser.sql index 8dd25a15a..0e040bccb 100644 --- a/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadCountByFreeOrganizationAdminUser.sql +++ b/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadCountByFreeOrganizationAdminUser.sql @@ -14,4 +14,5 @@ BEGIN OU.[UserId] = @UserId AND OU.[Type] < 2 -- Owner or Admin AND O.[PlanType] = 0 -- Free + AND OU.[Status] = 2 -- 2 = Confirmed END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadCountByOrganizationOwnerUser.sql b/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadCountByOrganizationOwnerUser.sql index 33ba249be..8b6ad8504 100644 --- a/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadCountByOrganizationOwnerUser.sql +++ b/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadCountByOrganizationOwnerUser.sql @@ -11,4 +11,5 @@ BEGIN WHERE OU.[UserId] = @UserId AND OU.[Type] = 0 + AND OU.[Status] = 2 -- 2 = Confirmed END \ No newline at end of file diff --git a/util/Setup/DbScripts/2017-09-08_00_OrgUserCounts.sql b/util/Setup/DbScripts/2017-09-08_00_OrgUserCounts.sql new file mode 100644 index 000000000..9e9a36021 --- /dev/null +++ b/util/Setup/DbScripts/2017-09-08_00_OrgUserCounts.sql @@ -0,0 +1,48 @@ +IF OBJECT_ID('[dbo].[OrganizationUser_ReadCountByFreeOrganizationAdminUser]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[OrganizationUser_ReadCountByFreeOrganizationAdminUser] +END +GO + +CREATE PROCEDURE [dbo].[OrganizationUser_ReadCountByFreeOrganizationAdminUser] + @UserId UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + SELECT + COUNT(1) + FROM + [dbo].[OrganizationUser] OU + INNER JOIN + [dbo].[Organization] O ON O.Id = OU.[OrganizationId] + WHERE + OU.[UserId] = @UserId + AND OU.[Type] < 2 -- Owner or Admin + AND O.[PlanType] = 0 -- Free + AND OU.[Status] = 2 -- 2 = Confirmed +END +GO + +IF OBJECT_ID('[dbo].[OrganizationUser_ReadCountByOrganizationOwnerUser]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[OrganizationUser_ReadCountByOrganizationOwnerUser] +END +GO + +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 +GO diff --git a/util/Setup/Setup.csproj b/util/Setup/Setup.csproj index a97fb70cf..d043d35f7 100644 --- a/util/Setup/Setup.csproj +++ b/util/Setup/Setup.csproj @@ -8,6 +8,7 @@ +