From 0b166a080e6ef327a021d13151b89f07b356a5e0 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Mon, 22 Oct 2018 14:09:55 -0400 Subject: [PATCH] limit collection scope option when creating cipher --- src/Api/Controllers/CiphersController.cs | 4 +- src/Core/Services/ICipherService.cs | 15 +++-- .../Services/Implementations/CipherService.cs | 9 ++- .../Cipher_UpdateCollections.sql | 67 +++++++++++-------- .../DbScripts/2018-10-17_00_ManagerRole.sql | 67 +++++++++++-------- 5 files changed, 98 insertions(+), 64 deletions(-) diff --git a/src/Api/Controllers/CiphersController.cs b/src/Api/Controllers/CiphersController.cs index 46d84d623..d296b64f4 100644 --- a/src/Api/Controllers/CiphersController.cs +++ b/src/Api/Controllers/CiphersController.cs @@ -143,7 +143,7 @@ namespace Bit.Api.Controllers } var userId = _userService.GetProperUserId(User).Value; - await _cipherService.SaveAsync(cipher, userId, model.CollectionIds, true); + await _cipherService.SaveAsync(cipher, userId, model.CollectionIds, true, false); var response = new CipherMiniResponseModel(cipher, _globalSettings, false); return response; @@ -188,7 +188,7 @@ namespace Bit.Api.Controllers // object cannot be a descendant of CipherDetails, so let's clone it. var cipherClone = CoreHelpers.CloneObject(model.ToCipher(cipher)); - await _cipherService.SaveAsync(cipherClone, userId, null, true); + await _cipherService.SaveAsync(cipherClone, userId, null, true, false); var response = new CipherMiniResponseModel(cipherClone, _globalSettings, cipher.OrganizationUseTotp); return response; diff --git a/src/Core/Services/ICipherService.cs b/src/Core/Services/ICipherService.cs index f8b92d61c..12b53ff37 100644 --- a/src/Core/Services/ICipherService.cs +++ b/src/Core/Services/ICipherService.cs @@ -9,11 +9,14 @@ namespace Bit.Core.Services { public interface ICipherService { - Task SaveAsync(Cipher cipher, Guid savingUserId, IEnumerable collectionIds = null, bool skipPermissionCheck = false); - Task SaveDetailsAsync(CipherDetails cipher, Guid savingUserId, IEnumerable collectionIds = null, bool skipPermissionCheck = false); + Task SaveAsync(Cipher cipher, Guid savingUserId, IEnumerable collectionIds = null, + bool skipPermissionCheck = false, bool limitCollectionScope = true); + Task SaveDetailsAsync(CipherDetails cipher, Guid savingUserId, IEnumerable collectionIds = null, + bool skipPermissionCheck = false); Task CreateAttachmentAsync(Cipher cipher, Stream stream, string fileName, long requestLength, Guid savingUserId, bool orgAdmin = false); - Task CreateAttachmentShareAsync(Cipher cipher, Stream stream, string fileName, long requestLength, string attachmentId, + Task CreateAttachmentShareAsync(Cipher cipher, Stream stream, string fileName, long requestLength, + string attachmentId, Guid organizationShareId); Task DeleteAsync(Cipher cipher, Guid deletingUserId, bool orgAdmin = false); Task DeleteManyAsync(IEnumerable cipherIds, Guid deletingUserId); @@ -22,8 +25,10 @@ namespace Bit.Core.Services Task MoveManyAsync(IEnumerable cipherIds, Guid? destinationFolderId, Guid movingUserId); Task SaveFolderAsync(Folder folder); Task DeleteFolderAsync(Folder folder); - Task ShareAsync(Cipher originalCipher, Cipher cipher, Guid organizationId, IEnumerable collectionIds, Guid userId); - Task ShareManyAsync(IEnumerable ciphers, Guid organizationId, IEnumerable collectionIds, Guid sharingUserId); + Task ShareAsync(Cipher originalCipher, Cipher cipher, Guid organizationId, IEnumerable collectionIds, + Guid userId); + Task ShareManyAsync(IEnumerable ciphers, Guid organizationId, IEnumerable collectionIds, + Guid sharingUserId); Task SaveCollectionsAsync(Cipher cipher, IEnumerable collectionIds, Guid savingUserId, bool orgAdmin); Task ImportCiphersAsync(List folders, List ciphers, IEnumerable> folderRelationships); diff --git a/src/Core/Services/Implementations/CipherService.cs b/src/Core/Services/Implementations/CipherService.cs index 046a2b7fe..8bff0b1f3 100644 --- a/src/Core/Services/Implementations/CipherService.cs +++ b/src/Core/Services/Implementations/CipherService.cs @@ -56,7 +56,7 @@ namespace Bit.Core.Services } public async Task SaveAsync(Cipher cipher, Guid savingUserId, IEnumerable collectionIds = null, - bool skipPermissionCheck = false) + bool skipPermissionCheck = false, bool limitCollectionScope = true) { if(!skipPermissionCheck && !(await UserCanEditAsync(cipher, savingUserId))) { @@ -67,8 +67,11 @@ namespace Bit.Core.Services { if(cipher.OrganizationId.HasValue && collectionIds != null) { - // Set user ID to limit scope of collection ids in the create sproc - cipher.UserId = savingUserId; + if(limitCollectionScope) + { + // Set user ID to limit scope of collection ids in the create sproc + cipher.UserId = savingUserId; + } await _cipherRepository.CreateAsync(cipher, collectionIds); } else diff --git a/src/Sql/dbo/Stored Procedures/Cipher_UpdateCollections.sql b/src/Sql/dbo/Stored Procedures/Cipher_UpdateCollections.sql index 7e99e05dc..fa5adf0b5 100644 --- a/src/Sql/dbo/Stored Procedures/Cipher_UpdateCollections.sql +++ b/src/Sql/dbo/Stored Procedures/Cipher_UpdateCollections.sql @@ -16,33 +16,46 @@ BEGIN [Id] UNIQUEIDENTIFIER ) - INSERT INTO #AvailableCollections - SELECT - C.[Id] - FROM - [dbo].[Collection] C - INNER JOIN - [Organization] O ON O.[Id] = C.[OrganizationId] - INNER JOIN - [dbo].[OrganizationUser] OU ON OU.[OrganizationId] = O.[Id] AND OU.[UserId] = @UserId - LEFT JOIN - [dbo].[CollectionUser] CU ON OU.[AccessAll] = 0 AND CU.[CollectionId] = C.[Id] AND CU.[OrganizationUserId] = OU.[Id] - LEFT JOIN - [dbo].[GroupUser] GU ON CU.[CollectionId] IS NULL AND OU.[AccessAll] = 0 AND GU.[OrganizationUserId] = OU.[Id] - LEFT JOIN - [dbo].[Group] G ON G.[Id] = GU.[GroupId] - LEFT JOIN - [dbo].[CollectionGroup] CG ON G.[AccessAll] = 0 AND CG.[CollectionId] = C.[Id] AND CG.[GroupId] = GU.[GroupId] - WHERE - O.[Id] = @OrganizationId - AND O.[Enabled] = 1 - AND OU.[Status] = 2 -- Confirmed - AND ( - OU.[AccessAll] = 1 - OR CU.[ReadOnly] = 0 - OR G.[AccessAll] = 1 - OR CG.[ReadOnly] = 0 - ) + IF @UserId IS NULL + BEGIN + INSERT INTO #AvailableCollections + SELECT + [Id] + FROM + [dbo].[Collection] + WHERE + [Id] = @OrganizationId + END + ELSE + BEGIN + INSERT INTO #AvailableCollections + SELECT + C.[Id] + FROM + [dbo].[Collection] C + INNER JOIN + [Organization] O ON O.[Id] = C.[OrganizationId] + INNER JOIN + [dbo].[OrganizationUser] OU ON OU.[OrganizationId] = O.[Id] AND OU.[UserId] = @UserId + LEFT JOIN + [dbo].[CollectionUser] CU ON OU.[AccessAll] = 0 AND CU.[CollectionId] = C.[Id] AND CU.[OrganizationUserId] = OU.[Id] + LEFT JOIN + [dbo].[GroupUser] GU ON CU.[CollectionId] IS NULL AND OU.[AccessAll] = 0 AND GU.[OrganizationUserId] = OU.[Id] + LEFT JOIN + [dbo].[Group] G ON G.[Id] = GU.[GroupId] + LEFT JOIN + [dbo].[CollectionGroup] CG ON G.[AccessAll] = 0 AND CG.[CollectionId] = C.[Id] AND CG.[GroupId] = GU.[GroupId] + WHERE + O.[Id] = @OrganizationId + AND O.[Enabled] = 1 + AND OU.[Status] = 2 -- Confirmed + AND ( + OU.[AccessAll] = 1 + OR CU.[ReadOnly] = 0 + OR G.[AccessAll] = 1 + OR CG.[ReadOnly] = 0 + ) + END IF (SELECT COUNT(1) FROM #AvailableCollections) < 1 BEGIN diff --git a/util/Setup/DbScripts/2018-10-17_00_ManagerRole.sql b/util/Setup/DbScripts/2018-10-17_00_ManagerRole.sql index d0c7d6125..7a4bfb660 100644 --- a/util/Setup/DbScripts/2018-10-17_00_ManagerRole.sql +++ b/util/Setup/DbScripts/2018-10-17_00_ManagerRole.sql @@ -255,33 +255,46 @@ BEGIN [Id] UNIQUEIDENTIFIER ) - INSERT INTO #AvailableCollections - SELECT - C.[Id] - FROM - [dbo].[Collection] C - INNER JOIN - [Organization] O ON O.[Id] = C.[OrganizationId] - INNER JOIN - [dbo].[OrganizationUser] OU ON OU.[OrganizationId] = O.[Id] AND OU.[UserId] = @UserId - LEFT JOIN - [dbo].[CollectionUser] CU ON OU.[AccessAll] = 0 AND CU.[CollectionId] = C.[Id] AND CU.[OrganizationUserId] = OU.[Id] - LEFT JOIN - [dbo].[GroupUser] GU ON CU.[CollectionId] IS NULL AND OU.[AccessAll] = 0 AND GU.[OrganizationUserId] = OU.[Id] - LEFT JOIN - [dbo].[Group] G ON G.[Id] = GU.[GroupId] - LEFT JOIN - [dbo].[CollectionGroup] CG ON G.[AccessAll] = 0 AND CG.[CollectionId] = C.[Id] AND CG.[GroupId] = GU.[GroupId] - WHERE - O.[Id] = @OrganizationId - AND O.[Enabled] = 1 - AND OU.[Status] = 2 -- Confirmed - AND ( - OU.[AccessAll] = 1 - OR CU.[ReadOnly] = 0 - OR G.[AccessAll] = 1 - OR CG.[ReadOnly] = 0 - ) + IF @UserId IS NULL + BEGIN + INSERT INTO #AvailableCollections + SELECT + [Id] + FROM + [dbo].[Collection] + WHERE + [Id] = @OrganizationId + END + ELSE + BEGIN + INSERT INTO #AvailableCollections + SELECT + C.[Id] + FROM + [dbo].[Collection] C + INNER JOIN + [Organization] O ON O.[Id] = C.[OrganizationId] + INNER JOIN + [dbo].[OrganizationUser] OU ON OU.[OrganizationId] = O.[Id] AND OU.[UserId] = @UserId + LEFT JOIN + [dbo].[CollectionUser] CU ON OU.[AccessAll] = 0 AND CU.[CollectionId] = C.[Id] AND CU.[OrganizationUserId] = OU.[Id] + LEFT JOIN + [dbo].[GroupUser] GU ON CU.[CollectionId] IS NULL AND OU.[AccessAll] = 0 AND GU.[OrganizationUserId] = OU.[Id] + LEFT JOIN + [dbo].[Group] G ON G.[Id] = GU.[GroupId] + LEFT JOIN + [dbo].[CollectionGroup] CG ON G.[AccessAll] = 0 AND CG.[CollectionId] = C.[Id] AND CG.[GroupId] = GU.[GroupId] + WHERE + O.[Id] = @OrganizationId + AND O.[Enabled] = 1 + AND OU.[Status] = 2 -- Confirmed + AND ( + OU.[AccessAll] = 1 + OR CU.[ReadOnly] = 0 + OR G.[AccessAll] = 1 + OR CG.[ReadOnly] = 0 + ) + END IF (SELECT COUNT(1) FROM #AvailableCollections) < 1 BEGIN