diff --git a/src/Api/Controllers/OrganizationUsersController.cs b/src/Api/Controllers/OrganizationUsersController.cs index 7bf2ded914..8bd173467b 100644 --- a/src/Api/Controllers/OrganizationUsersController.cs +++ b/src/Api/Controllers/OrganizationUsersController.cs @@ -75,7 +75,7 @@ namespace Bit.Api.Controllers var userId = _userService.GetProperUserId(User); var result = await _organizationService.InviteUserAsync(orgGuidId, userId.Value, model.Email, model.Type.Value, - model.Subvaults?.Select(s => s.ToSubvaultUser())); + model.AccessAllSubvaults, model.Subvaults?.Select(s => s.ToSubvaultUser())); } [HttpPut("{id}/reinvite")] diff --git a/src/Core/Models/Api/Request/Organizations/OrganizationUserRequestModels.cs b/src/Core/Models/Api/Request/Organizations/OrganizationUserRequestModels.cs index 05911c1d96..c0bd953ea8 100644 --- a/src/Core/Models/Api/Request/Organizations/OrganizationUserRequestModels.cs +++ b/src/Core/Models/Api/Request/Organizations/OrganizationUserRequestModels.cs @@ -12,6 +12,7 @@ namespace Bit.Core.Models.Api public string Email { get; set; } [Required] public Enums.OrganizationUserType? Type { get; set; } + public bool AccessAllSubvaults { get; set; } public IEnumerable Subvaults { get; set; } } @@ -31,11 +32,13 @@ namespace Bit.Core.Models.Api { [Required] public Enums.OrganizationUserType? Type { get; set; } + public bool AccessAllSubvaults { get; set; } public IEnumerable Subvaults { get; set; } public OrganizationUser ToOrganizationUser(OrganizationUser existingUser) { existingUser.Type = Type.Value; + existingUser.AccessAllSubvaults = AccessAllSubvaults; return existingUser; } } diff --git a/src/Core/Models/Api/Response/OrganizationUserResponseModel.cs b/src/Core/Models/Api/Response/OrganizationUserResponseModel.cs index 43f0ad0de1..43f99cb06a 100644 --- a/src/Core/Models/Api/Response/OrganizationUserResponseModel.cs +++ b/src/Core/Models/Api/Response/OrganizationUserResponseModel.cs @@ -22,6 +22,7 @@ namespace Bit.Core.Models.Api Email = organizationUser.Email; Type = organizationUser.Type; Status = organizationUser.Status; + AccessAllSubvaults = organizationUser.AccessAllSubvaults; } public string Id { get; set; } @@ -30,6 +31,7 @@ namespace Bit.Core.Models.Api public string Email { get; set; } public OrganizationUserType Type { get; set; } public OrganizationUserStatusType Status { get; set; } + public bool AccessAllSubvaults { get; set; } } public class OrganizationUserDetailsResponseModel : OrganizationUserResponseModel diff --git a/src/Core/Models/Api/Response/SubvaultUserResponseModel.cs b/src/Core/Models/Api/Response/SubvaultUserResponseModel.cs index 044e4702a6..c99f9bf9b6 100644 --- a/src/Core/Models/Api/Response/SubvaultUserResponseModel.cs +++ b/src/Core/Models/Api/Response/SubvaultUserResponseModel.cs @@ -15,9 +15,10 @@ namespace Bit.Core.Models.Api throw new ArgumentNullException(nameof(subvaultUser)); } - Id = subvaultUser.Id.ToString(); + Id = subvaultUser.Id?.ToString(); OrganizationUserId = subvaultUser.OrganizationUserId.ToString(); - SubvaultId = subvaultUser.SubvaultId.ToString(); + SubvaultId = subvaultUser.SubvaultId?.ToString(); + AccessAllSubvaults = subvaultUser.AccessAllSubvaults; Name = subvaultUser.Name; Email = subvaultUser.Email; Type = subvaultUser.Type; @@ -28,6 +29,7 @@ namespace Bit.Core.Models.Api public string Id { get; set; } public string OrganizationUserId { get; set; } public string SubvaultId { get; set; } + public bool AccessAllSubvaults { get; set; } public string Name { get; set; } public string Email { get; set; } public OrganizationUserType Type { get; set; } diff --git a/src/Core/Models/Data/OrganizationUserUserDetails.cs b/src/Core/Models/Data/OrganizationUserUserDetails.cs index 2e25e70511..3f4c6b7840 100644 --- a/src/Core/Models/Data/OrganizationUserUserDetails.cs +++ b/src/Core/Models/Data/OrganizationUserUserDetails.cs @@ -11,5 +11,6 @@ namespace Bit.Core.Models.Data public string Email { get; set; } public Enums.OrganizationUserStatusType Status { get; set; } public Enums.OrganizationUserType Type { get; set; } + public bool AccessAllSubvaults { get; set; } } } diff --git a/src/Core/Models/Data/SubvaultUserUserDetails.cs b/src/Core/Models/Data/SubvaultUserUserDetails.cs index aaf7b66748..55b72518a3 100644 --- a/src/Core/Models/Data/SubvaultUserUserDetails.cs +++ b/src/Core/Models/Data/SubvaultUserUserDetails.cs @@ -4,9 +4,10 @@ namespace Bit.Core.Models.Data { public class SubvaultUserUserDetails { - public Guid Id { get; set; } + public Guid? Id { get; set; } public Guid OrganizationUserId { get; set; } - public Guid SubvaultId { get; set; } + public Guid? SubvaultId { get; set; } + public bool AccessAllSubvaults { get; set; } public string Name { get; set; } public string Email { get; set; } public Enums.OrganizationUserStatusType Status { get; set; } diff --git a/src/Core/Models/Table/OrganizationUser.cs b/src/Core/Models/Table/OrganizationUser.cs index e6c746d1fc..30c74d480e 100644 --- a/src/Core/Models/Table/OrganizationUser.cs +++ b/src/Core/Models/Table/OrganizationUser.cs @@ -13,6 +13,7 @@ namespace Bit.Core.Models.Table public string Key { get; set; } public OrganizationUserStatusType Status { get; set; } public OrganizationUserType Type { get; set; } + public bool AccessAllSubvaults { get; set; } public DateTime CreationDate { get; internal set; } = DateTime.UtcNow; public DateTime RevisionDate { get; internal set; } = DateTime.UtcNow; diff --git a/src/Core/Services/IOrganizationService.cs b/src/Core/Services/IOrganizationService.cs index 7681574576..878e097b2f 100644 --- a/src/Core/Services/IOrganizationService.cs +++ b/src/Core/Services/IOrganizationService.cs @@ -19,7 +19,7 @@ namespace Bit.Core.Services Task DeleteAsync(Organization organization); Task UpdateAsync(Organization organization, bool updateBilling = false); Task InviteUserAsync(Guid organizationId, Guid invitingUserId, string email, - Enums.OrganizationUserType type, IEnumerable subvaults); + Enums.OrganizationUserType type, bool accessAllSubvaults, IEnumerable subvaults); Task ResendInviteAsync(Guid organizationId, Guid invitingUserId, Guid organizationUserId); Task AcceptUserAsync(Guid organizationUserId, User user, string token); Task ConfirmUserAsync(Guid organizationId, Guid organizationUserId, string key, Guid confirmingUserId); diff --git a/src/Core/Services/Implementations/OrganizationService.cs b/src/Core/Services/Implementations/OrganizationService.cs index 156011133a..2195f3be8d 100644 --- a/src/Core/Services/Implementations/OrganizationService.cs +++ b/src/Core/Services/Implementations/OrganizationService.cs @@ -475,7 +475,7 @@ namespace Bit.Core.Services $"{plan.MaxAdditionalSeats.GetValueOrDefault(0)} additional users."); } - if(plan.Type == Enums.PlanType.Free) + if(plan.Type == PlanType.Free) { var ownerExistingOrgCount = await _organizationUserRepository.GetCountByFreeOrganizationAdminUserAsync(signup.Owner.Id); @@ -555,6 +555,7 @@ namespace Bit.Core.Services Key = signup.OwnerKey, Type = OrganizationUserType.Owner, Status = OrganizationUserStatusType.Confirmed, + AccessAllSubvaults = true, CreationDate = DateTime.UtcNow, RevisionDate = DateTime.UtcNow }; @@ -631,7 +632,7 @@ namespace Bit.Core.Services } public async Task InviteUserAsync(Guid organizationId, Guid invitingUserId, string email, - OrganizationUserType type, IEnumerable subvaults) + OrganizationUserType type, bool accessAllSubvaults, IEnumerable subvaults) { var organization = await _organizationRepository.GetByIdAsync(organizationId); if(organization == null) @@ -664,12 +665,16 @@ namespace Bit.Core.Services Key = null, Type = type, Status = OrganizationUserStatusType.Invited, + AccessAllSubvaults = accessAllSubvaults, CreationDate = DateTime.UtcNow, RevisionDate = DateTime.UtcNow }; await _organizationUserRepository.CreateAsync(orgUser); - await SaveUserSubvaultsAsync(orgUser, subvaults, true); + if(!orgUser.AccessAllSubvaults && subvaults.Any()) + { + await SaveUserSubvaultsAsync(orgUser, subvaults, true); + } await SendInviteAsync(orgUser); return orgUser; @@ -786,6 +791,12 @@ namespace Bit.Core.Services } await _organizationUserRepository.ReplaceAsync(user); + + if(user.AccessAllSubvaults) + { + // We don't need any subvaults if we're flagged to have all access. + subvaults = new List(); + } await SaveUserSubvaultsAsync(user, subvaults, false); } diff --git a/src/Sql/dbo/Functions/UserCanEditCipher.sql b/src/Sql/dbo/Functions/UserCanEditCipher.sql index c1c9b63cf8..fdcfdc7651 100644 --- a/src/Sql/dbo/Functions/UserCanEditCipher.sql +++ b/src/Sql/dbo/Functions/UserCanEditCipher.sql @@ -5,22 +5,22 @@ BEGIN ;WITH [CTE] AS( SELECT - CASE WHEN SU.[ReadOnly] = 0 THEN 1 ELSE 0 END [CanEdit] + CASE WHEN OU.[AccessAllSubvaults] = 1 OR SU.[ReadOnly] = 0 THEN 1 ELSE 0 END [CanEdit] FROM - [dbo].[SubvaultUser] SU + [dbo].[Cipher] C INNER JOIN - [dbo].[SubvaultCipher] SC ON SC.SubvaultId = SU.SubvaultId + [dbo].[Organization] O ON C.[UserId] IS NULL AND O.[Id] = C.[OrganizationId] INNER JOIN - [dbo].[Cipher] C ON SC.[CipherId] = C.[Id] - INNER JOIN - [dbo].[OrganizationUser] OU ON OU.Id = SU.OrganizationUserId AND OU.OrganizationId = C.OrganizationId - INNER JOIN - [dbo].[Organization] O ON O.Id = C.OrganizationId + [dbo].[OrganizationUser] OU ON OU.[OrganizationId] = O.[Id] AND OU.[UserId] = @UserId + LEFT JOIN + [dbo].[SubvaultCipher] SC ON C.[UserId] IS NULL AND OU.[AccessAllSubvaults] = 0 AND SC.[CipherId] = C.[Id] + LEFT JOIN + [dbo].[SubvaultUser] SU ON SU.[SubvaultId] = SC.[SubvaultId] AND SU.[OrganizationUserId] = OU.[Id] WHERE C.[Id] = @CipherId - AND OU.[UserId] = @UserId AND OU.[Status] = 2 -- 2 = Confirmed AND O.[Enabled] = 1 + AND (OU.[AccessAllSubvaults] = 1 OR SU.[SubvaultId] IS NOT NULL) ) SELECT @CanEdit = CASE WHEN COUNT(1) > 0 THEN 1 ELSE 0 END diff --git a/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByIdUserId.sql b/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByIdUserId.sql index 71850bf0fa..98571e2443 100644 --- a/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByIdUserId.sql +++ b/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByIdUserId.sql @@ -9,23 +9,23 @@ BEGIN C.* FROM [dbo].[CipherDetails](@UserId) C - LEFT JOIN - [dbo].[SubvaultCipher] SC ON C.[UserId] IS NULL AND SC.[CipherId] = C.[Id] - LEFT JOIN - [dbo].[SubvaultUser] SU ON SU.[SubvaultId] = SC.[SubvaultId] - LEFT JOIN - [dbo].[OrganizationUser] OU ON OU.[Id] = SU.[OrganizationUserId] LEFT JOIN [dbo].[Organization] O ON C.[UserId] IS NULL AND O.[Id] = C.[OrganizationId] + LEFT JOIN + [dbo].[OrganizationUser] OU ON OU.[OrganizationId] = O.[Id] AND OU.[UserId] = @UserId + LEFT JOIN + [dbo].[SubvaultCipher] SC ON C.[UserId] IS NULL AND OU.[AccessAllSubvaults] = 0 AND SC.[CipherId] = C.[Id] + LEFT JOIN + [dbo].[SubvaultUser] SU ON SU.[SubvaultId] = SC.[SubvaultId] AND SU.[OrganizationUserId] = OU.[Id] WHERE C.Id = @Id AND ( C.[UserId] = @UserId OR ( C.[UserId] IS NULL - AND OU.[UserId] = @UserId AND OU.[Status] = 2 -- 2 = Confirmed AND O.[Enabled] = 1 + AND (OU.[AccessAllSubvaults] = 1 OR SU.[SubvaultId] IS NOT NULL) ) ) END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByTypeUserId.sql b/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByTypeUserId.sql index e624a96989..631eb59988 100644 --- a/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByTypeUserId.sql +++ b/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByTypeUserId.sql @@ -9,23 +9,23 @@ BEGIN C.* FROM [dbo].[CipherDetails](@UserId) C - LEFT JOIN - [dbo].[SubvaultCipher] SC ON C.[UserId] IS NULL AND SC.[CipherId] = C.[Id] - LEFT JOIN - [dbo].[SubvaultUser] SU ON SU.[SubvaultId] = SC.[SubvaultId] - LEFT JOIN - [dbo].[OrganizationUser] OU ON OU.[Id] = SU.[OrganizationUserId] LEFT JOIN [dbo].[Organization] O ON C.[UserId] IS NULL AND O.[Id] = C.[OrganizationId] + LEFT JOIN + [dbo].[OrganizationUser] OU ON OU.[OrganizationId] = O.[Id] AND OU.[UserId] = @UserId + LEFT JOIN + [dbo].[SubvaultCipher] SC ON C.[UserId] IS NULL AND OU.[AccessAllSubvaults] = 0 AND SC.[CipherId] = C.[Id] + LEFT JOIN + [dbo].[SubvaultUser] SU ON SU.[SubvaultId] = SC.[SubvaultId] AND SU.[OrganizationUserId] = OU.[Id] WHERE C.[Type] = @Type AND ( C.[UserId] = @UserId OR ( C.[UserId] IS NULL - AND OU.[UserId] = @UserId AND OU.[Status] = 2 -- 2 = Confirmed AND O.[Enabled] = 1 + AND (OU.[AccessAllSubvaults] = 1 OR SU.[SubvaultId] IS NOT NULL) ) ) END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByUserId.sql b/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByUserId.sql index 2ace5b4c3a..d58988e76b 100644 --- a/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByUserId.sql +++ b/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByUserId.sql @@ -8,20 +8,20 @@ BEGIN C.* FROM [dbo].[CipherDetails](@UserId) C - LEFT JOIN - [dbo].[SubvaultCipher] SC ON C.[UserId] IS NULL AND SC.[CipherId] = C.[Id] - LEFT JOIN - [dbo].[SubvaultUser] SU ON SU.[SubvaultId] = SC.[SubvaultId] - LEFT JOIN - [dbo].[OrganizationUser] OU ON OU.[Id] = SU.[OrganizationUserId] LEFT JOIN [dbo].[Organization] O ON C.[UserId] IS NULL AND O.[Id] = C.[OrganizationId] + LEFT JOIN + [dbo].[OrganizationUser] OU ON OU.[OrganizationId] = O.[Id] AND OU.[UserId] = @UserId + LEFT JOIN + [dbo].[SubvaultCipher] SC ON C.[UserId] IS NULL AND OU.[AccessAllSubvaults] = 0 AND SC.[CipherId] = C.[Id] + LEFT JOIN + [dbo].[SubvaultUser] SU ON SU.[SubvaultId] = SC.[SubvaultId] AND SU.[OrganizationUserId] = OU.[Id] WHERE C.[UserId] = @UserId OR ( C.[UserId] IS NULL - AND OU.[UserId] = @UserId AND OU.[Status] = 2 -- 2 = Confirmed AND O.[Enabled] = 1 + AND (OU.[AccessAllSubvaults] = 1 OR SU.[SubvaultId] IS NOT NULL) ) END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByUserIdHasSubvault.sql b/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByUserIdHasSubvault.sql index 6e9da6481a..4e2a86aee9 100644 --- a/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByUserIdHasSubvault.sql +++ b/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByUserIdHasSubvault.sql @@ -8,16 +8,16 @@ BEGIN C.* FROM [dbo].[CipherDetails](@UserId) C - INNER JOIN - [dbo].[SubvaultCipher] SC ON C.[UserId] IS NULL AND SC.[CipherId] = C.[Id] - INNER JOIN - [dbo].[SubvaultUser] SU ON SU.[SubvaultId] = SC.[SubvaultId] - INNER JOIN - [dbo].[OrganizationUser] OU ON OU.[Id] = SU.[OrganizationUserId] INNER JOIN [dbo].[Organization] O ON C.[UserId] IS NULL AND O.[Id] = C.[OrganizationId] + INNER JOIN + [dbo].[OrganizationUser] OU ON OU.[OrganizationId] = O.[Id] AND OU.[UserId] = @UserId + LEFT JOIN + [dbo].[SubvaultCipher] SC ON C.[UserId] IS NULL AND OU.[AccessAllSubvaults] = 0 AND SC.[CipherId] = C.[Id] + LEFT JOIN + [dbo].[SubvaultUser] SU ON SU.[SubvaultId] = SC.[SubvaultId] AND SU.[OrganizationUserId] = OU.[Id] WHERE - OU.[UserId] = @UserId - AND OU.[Status] = 2 -- 2 = Confirmed + OU.[Status] = 2 -- 2 = Confirmed AND O.[Enabled] = 1 + AND (OU.[AccessAllSubvaults] = 1 OR SU.[SubvaultId] IS NOT NULL) END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/CipherFullDetails_ReadByIdUserId.sql b/src/Sql/dbo/Stored Procedures/CipherFullDetails_ReadByIdUserId.sql index 2d498ad78f..043093a04c 100644 --- a/src/Sql/dbo/Stored Procedures/CipherFullDetails_ReadByIdUserId.sql +++ b/src/Sql/dbo/Stored Procedures/CipherFullDetails_ReadByIdUserId.sql @@ -13,23 +13,23 @@ BEGIN END [Edit] FROM [dbo].[CipherDetails](@UserId) C - LEFT JOIN - [dbo].[SubvaultCipher] SC ON C.[UserId] IS NULL AND SC.[CipherId] = C.[Id] - LEFT JOIN - [dbo].[SubvaultUser] SU ON SU.[SubvaultId] = SC.[SubvaultId] - LEFT JOIN - [dbo].[OrganizationUser] OU ON OU.[Id] = SU.[OrganizationUserId] LEFT JOIN [dbo].[Organization] O ON C.[UserId] IS NULL AND O.[Id] = C.[OrganizationId] + LEFT JOIN + [dbo].[OrganizationUser] OU ON OU.[OrganizationId] = O.[Id] AND OU.[UserId] = @UserId + LEFT JOIN + [dbo].[SubvaultCipher] SC ON C.[UserId] IS NULL AND OU.[AccessAllSubvaults] = 0 AND SC.[CipherId] = C.[Id] + LEFT JOIN + [dbo].[SubvaultUser] SU ON SU.[SubvaultId] = SC.[SubvaultId] AND SU.[OrganizationUserId] = OU.[Id] WHERE C.Id = @Id AND ( C.[UserId] = @UserId OR ( C.[UserId] IS NULL - AND OU.[UserId] = @UserId AND OU.[Status] = 2 -- 2 = Confirmed AND O.[Enabled] = 1 + AND (OU.[AccessAllSubvaults] = 1 OR SU.[SubvaultId] IS NOT NULL) ) ) END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/Cipher_UpdateWithSubvaults.sql b/src/Sql/dbo/Stored Procedures/Cipher_UpdateWithSubvaults.sql index aef29fd7ec..3971ff35ad 100644 --- a/src/Sql/dbo/Stored Procedures/Cipher_UpdateWithSubvaults.sql +++ b/src/Sql/dbo/Stored Procedures/Cipher_UpdateWithSubvaults.sql @@ -24,21 +24,21 @@ BEGIN WHERE [Id] = @Id - ;WITH [AvailableSubvaultsCTE] AS( SELECT - SU.SubvaultId + S.[Id] FROM - [dbo].[SubvaultUser] SU + [dbo].[Subvault] S INNER JOIN - [dbo].[OrganizationUser] OU ON OU.[Id] = SU.[OrganizationUserId] + [Organization] O ON O.[Id] = S.[OrganizationId] INNER JOIN - [dbo].[Organization] O ON O.[Id] = OU.[OrganizationId] + [dbo].[OrganizationUser] OU ON OU.[OrganizationId] = O.[Id] AND OU.[UserId] = @UserId + LEFT JOIN + [dbo].[SubvaultUser] SU ON OU.[AccessAllSubvaults] = 0 AND SU.[SubvaultId] = S.[Id] AND SU.[OrganizationUserId] = OU.[Id] WHERE - OU.[UserId] = @UserId - AND SU.[ReadOnly] = 0 - AND OU.[Status] = 2 -- Confirmed + OU.[Status] = 2 -- Confirmed AND O.[Enabled] = 1 + AND (OU.[AccessAllSubvaults] = 1 OR SU.[ReadOnly] = 0) ) INSERT INTO [dbo].[SubvaultCipher] ( @@ -46,10 +46,10 @@ BEGIN [CipherId] ) SELECT - Id, + [Id], @Id FROM @SubvaultIds WHERE - Id IN (SELECT SubvaultId FROM [AvailableSubvaultsCTE]) + [Id] IN (SELECT [Id] FROM [AvailableSubvaultsCTE]) END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/OrganizationUser_Create.sql b/src/Sql/dbo/Stored Procedures/OrganizationUser_Create.sql index e898231d76..3f14003170 100644 --- a/src/Sql/dbo/Stored Procedures/OrganizationUser_Create.sql +++ b/src/Sql/dbo/Stored Procedures/OrganizationUser_Create.sql @@ -6,6 +6,7 @@ @Key VARCHAR(MAX), @Status TINYINT, @Type TINYINT, + @AccessAllSubvaults BIT, @CreationDate DATETIME2(7), @RevisionDate DATETIME2(7) AS @@ -21,6 +22,7 @@ BEGIN [Key], [Status], [Type], + [AccessAllSubvaults], [CreationDate], [RevisionDate] ) @@ -33,6 +35,7 @@ BEGIN @Key, @Status, @Type, + @AccessAllSubvaults, @CreationDate, @RevisionDate ) diff --git a/src/Sql/dbo/Stored Procedures/OrganizationUser_Update.sql b/src/Sql/dbo/Stored Procedures/OrganizationUser_Update.sql index 88249959d6..997bfdc24c 100644 --- a/src/Sql/dbo/Stored Procedures/OrganizationUser_Update.sql +++ b/src/Sql/dbo/Stored Procedures/OrganizationUser_Update.sql @@ -6,6 +6,7 @@ @Key VARCHAR(MAX), @Status TINYINT, @Type TINYINT, + @AccessAllSubvaults BIT, @CreationDate DATETIME2(7), @RevisionDate DATETIME2(7) AS @@ -21,6 +22,7 @@ BEGIN [Key] = @Key, [Status] = @Status, [Type] = @Type, + [AccessAllSubvaults] = @AccessAllSubvaults, [CreationDate] = @CreationDate, [RevisionDate] = @RevisionDate WHERE diff --git a/src/Sql/dbo/Stored Procedures/SubvaultCipher_ReadByUserId.sql b/src/Sql/dbo/Stored Procedures/SubvaultCipher_ReadByUserId.sql index 990b974003..bb30df996a 100644 --- a/src/Sql/dbo/Stored Procedures/SubvaultCipher_ReadByUserId.sql +++ b/src/Sql/dbo/Stored Procedures/SubvaultCipher_ReadByUserId.sql @@ -9,10 +9,12 @@ BEGIN FROM [dbo].[SubvaultCipher] SC INNER JOIN - [dbo].[SubvaultUser] SU ON SU.[SubvaultId] = SC.[SubvaultId] + [dbo].[Subvault] S ON S.[Id] = SC.[SubvaultId] INNER JOIN - [dbo].[OrganizationUser] OU ON OU.[Id] = SU.[OrganizationUserId] + [dbo].[OrganizationUser] OU ON OU.[OrganizationId] = S.[OrganizationId] AND OU.[UserId] = @UserId + LEFT JOIN + [dbo].[SubvaultUser] SU ON OU.[AccessAllSubvaults] = 0 AND SU.[SubvaultId] = S.[Id] AND SU.[OrganizationUserId] = OU.[Id] WHERE - OU.[UserId] = @UserId - AND OU.[Status] = 2 -- Confirmed + OU.[Status] = 2 -- Confirmed + AND (OU.[AccessAllSubvaults] = 1 OR SU.[SubvaultId] IS NOT NULL) END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/SubvaultCipher_ReadByUserIdCipherId.sql b/src/Sql/dbo/Stored Procedures/SubvaultCipher_ReadByUserIdCipherId.sql index b0969e46b4..1fffe951e7 100644 --- a/src/Sql/dbo/Stored Procedures/SubvaultCipher_ReadByUserIdCipherId.sql +++ b/src/Sql/dbo/Stored Procedures/SubvaultCipher_ReadByUserIdCipherId.sql @@ -10,11 +10,13 @@ BEGIN FROM [dbo].[SubvaultCipher] SC INNER JOIN - [dbo].[SubvaultUser] SU ON SU.[SubvaultId] = SC.[SubvaultId] + [dbo].[Subvault] S ON S.[Id] = SC.[SubvaultId] INNER JOIN - [dbo].[OrganizationUser] OU ON OU.[Id] = SU.[OrganizationUserId] + [dbo].[OrganizationUser] OU ON OU.[OrganizationId] = S.[OrganizationId] AND OU.[UserId] = @UserId + LEFT JOIN + [dbo].[SubvaultUser] SU ON OU.[AccessAllSubvaults] = 0 AND SU.[SubvaultId] = S.[Id] AND SU.[OrganizationUserId] = OU.[Id] WHERE SC.[CipherId] = @CipherId - AND OU.[UserId] = @UserId AND OU.[Status] = 2 -- Confirmed + AND (OU.[AccessAllSubvaults] = 1 OR SU.[SubvaultId] IS NOT NULL) END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/SubvaultCipher_UpdateSubvaults.sql b/src/Sql/dbo/Stored Procedures/SubvaultCipher_UpdateSubvaults.sql index 1795ba0e19..3e340bdc6a 100644 --- a/src/Sql/dbo/Stored Procedures/SubvaultCipher_UpdateSubvaults.sql +++ b/src/Sql/dbo/Stored Procedures/SubvaultCipher_UpdateSubvaults.sql @@ -8,18 +8,19 @@ BEGIN ;WITH [AvailableSubvaultsCTE] AS( SELECT - SU.SubvaultId + S.[Id] FROM - [dbo].[SubvaultUser] SU + [dbo].[Subvault] S INNER JOIN - [dbo].[OrganizationUser] OU ON OU.[Id] = SU.[OrganizationUserId] + [Organization] O ON O.[Id] = S.[OrganizationId] INNER JOIN - [dbo].[Organization] O ON O.[Id] = OU.[OrganizationId] + [dbo].[OrganizationUser] OU ON OU.[OrganizationId] = O.[Id] AND OU.[UserId] = @UserId + LEFT JOIN + [dbo].[SubvaultUser] SU ON OU.[AccessAllSubvaults] = 0 AND SU.[SubvaultId] = S.[Id] AND SU.[OrganizationUserId] = OU.[Id] WHERE - OU.[UserId] = @UserId - AND SU.[ReadOnly] = 0 - AND OU.[Status] = 2 -- Confirmed + OU.[Status] = 2 -- Confirmed AND O.[Enabled] = 1 + AND (OU.[AccessAllSubvaults] = 1 OR SU.[ReadOnly] = 0) ) MERGE [dbo].[SubvaultCipher] AS [Target] @@ -29,7 +30,7 @@ BEGIN [Target].[SubvaultId] = [Source].[Id] AND [Target].[CipherId] = @CipherId WHEN NOT MATCHED BY TARGET - AND [Source].[Id] IN (SELECT [SubvaultId] FROM [AvailableSubvaultsCTE]) THEN + AND [Source].[Id] IN (SELECT [Id] FROM [AvailableSubvaultsCTE]) THEN INSERT VALUES ( [Source].[Id], @@ -37,7 +38,7 @@ BEGIN ) WHEN NOT MATCHED BY SOURCE AND [Target].[CipherId] = @CipherId - AND [Target].[SubvaultId] IN (SELECT [SubvaultId] FROM [AvailableSubvaultsCTE]) THEN + AND [Target].[SubvaultId] IN (SELECT [Id] FROM [AvailableSubvaultsCTE]) THEN DELETE ; END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/SubvaultUserUserDetails_ReadBySubvaultId.sql b/src/Sql/dbo/Stored Procedures/SubvaultUserUserDetails_ReadBySubvaultId.sql index 4e556c3740..5e84a8cb36 100644 --- a/src/Sql/dbo/Stored Procedures/SubvaultUserUserDetails_ReadBySubvaultId.sql +++ b/src/Sql/dbo/Stored Procedures/SubvaultUserUserDetails_ReadBySubvaultId.sql @@ -5,11 +5,10 @@ BEGIN SET NOCOUNT ON SELECT - SU.* + * FROM - [dbo].[SubvaultUserUserDetailsView] SU - INNER JOIN - [OrganizationUser] OU ON SU.[OrganizationUserId] = OU.[Id] + [dbo].[SubvaultUserUserDetailsView] WHERE - SU.[SubvaultId] = @SubvaultId + [AccessAllSubvaults] = 1 + OR [SubvaultId] = @SubvaultId END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/Subvault_ReadByUserId.sql b/src/Sql/dbo/Stored Procedures/Subvault_ReadByUserId.sql index 079b62c6e1..64532c4042 100644 --- a/src/Sql/dbo/Stored Procedures/Subvault_ReadByUserId.sql +++ b/src/Sql/dbo/Stored Procedures/Subvault_ReadByUserId.sql @@ -9,13 +9,13 @@ BEGIN FROM [dbo].[SubvaultView] S INNER JOIN - [SubvaultUser] SU ON SU.[SubvaultId] = S.[Id] + [Organization] O ON O.[Id] = S.[OrganizationId] INNER JOIN - [OrganizationUser] OU ON OU.[Id] = SU.[OrganizationUserId] - INNER JOIN - [Organization] O ON O.[Id] = OU.[OrganizationId] + [dbo].[OrganizationUser] OU ON OU.[OrganizationId] = O.[Id] AND OU.[UserId] = @UserId + LEFT JOIN + [dbo].[SubvaultUser] SU ON OU.[AccessAllSubvaults] = 0 AND SU.[SubvaultId] = S.[Id] AND SU.[OrganizationUserId] = OU.[Id] WHERE - OU.[UserId] = @UserId - AND OU.[Status] = 2 -- Confirmed + OU.[Status] = 2 -- Confirmed AND O.[Enabled] = 1 + AND (OU.[AccessAllSubvaults] = 1 OR SU.[SubvaultId] IS NOT NULL) END \ No newline at end of file diff --git a/src/Sql/dbo/Tables/OrganizationUser.sql b/src/Sql/dbo/Tables/OrganizationUser.sql index 7d5d89002a..4ba27ef0e1 100644 --- a/src/Sql/dbo/Tables/OrganizationUser.sql +++ b/src/Sql/dbo/Tables/OrganizationUser.sql @@ -1,13 +1,14 @@ CREATE TABLE [dbo].[OrganizationUser] ( - [Id] UNIQUEIDENTIFIER NOT NULL, - [OrganizationId] UNIQUEIDENTIFIER NOT NULL, - [UserId] UNIQUEIDENTIFIER NULL, - [Email] NVARCHAR (50) NULL, - [Key] VARCHAR (MAX) NULL, - [Status] TINYINT NOT NULL, - [Type] TINYINT NOT NULL, - [CreationDate] DATETIME2 (7) NOT NULL, - [RevisionDate] DATETIME2 (7) NOT NULL, + [Id] UNIQUEIDENTIFIER NOT NULL, + [OrganizationId] UNIQUEIDENTIFIER NOT NULL, + [UserId] UNIQUEIDENTIFIER NULL, + [Email] NVARCHAR (50) NULL, + [Key] VARCHAR (MAX) NULL, + [Status] TINYINT NOT NULL, + [Type] TINYINT NOT NULL, + [AccessAllSubvaults] BIT NOT NULL, + [CreationDate] DATETIME2 (7) NOT NULL, + [RevisionDate] DATETIME2 (7) NOT NULL, CONSTRAINT [PK_OrganizationUser] PRIMARY KEY CLUSTERED ([Id] ASC), CONSTRAINT [FK_OrganizationUser_Organization] FOREIGN KEY ([OrganizationId]) REFERENCES [dbo].[Organization] ([Id]) ON DELETE CASCADE, CONSTRAINT [FK_OrganizationUser_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([Id]) diff --git a/src/Sql/dbo/Views/OrganizationUserUserDetailsView.sql b/src/Sql/dbo/Views/OrganizationUserUserDetailsView.sql index c982dd2d66..a935032b61 100644 --- a/src/Sql/dbo/Views/OrganizationUserUserDetailsView.sql +++ b/src/Sql/dbo/Views/OrganizationUserUserDetailsView.sql @@ -7,7 +7,8 @@ SELECT U.[Name], ISNULL(U.[Email], OU.[Email]) Email, OU.[Status], - OU.[Type] + OU.[Type], + OU.[AccessAllSubvaults] FROM [dbo].[OrganizationUser] OU LEFT JOIN diff --git a/src/Sql/dbo/Views/SubvaultUserUserDetailsView.sql b/src/Sql/dbo/Views/SubvaultUserUserDetailsView.sql index 29222d5456..27fe69ce21 100644 --- a/src/Sql/dbo/Views/SubvaultUserUserDetailsView.sql +++ b/src/Sql/dbo/Views/SubvaultUserUserDetailsView.sql @@ -1,17 +1,18 @@ CREATE VIEW [dbo].[SubvaultUserUserDetailsView] AS SELECT + OU.[Id] AS [OrganizationUserId], + OU.[AccessAllSubvaults], SU.[Id], - SU.[OrganizationUserId], SU.[SubvaultId], U.[Name], ISNULL(U.[Email], OU.[Email]) Email, OU.[Status], OU.[Type], - SU.[ReadOnly] + CASE WHEN OU.[AccessAllSubvaults] = 0 AND SU.[ReadOnly] = 1 THEN 1 ELSE 0 END [ReadOnly] FROM - [dbo].[SubvaultUser] SU -INNER JOIN - [dbo].[OrganizationUser] OU ON OU.[Id] = SU.[OrganizationUserId] + [dbo].[OrganizationUser] OU +LEFT JOIN + [dbo].[SubvaultUser] SU ON OU.[AccessAllSubvaults] = 0 AND SU.[OrganizationUserId] = OU.[Id] LEFT JOIN [dbo].[User] U ON U.[Id] = OU.[UserId] \ No newline at end of file