From f0d7dc802396dd52e1466b4ed2ae8130c64ee2ea Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Thu, 11 May 2017 10:32:25 -0400 Subject: [PATCH] Group access & sproc/model refactoring. --- src/Api/Controllers/CollectionsController.cs | 9 ++- .../OrganizationUsersController.cs | 8 +-- .../Api/Response/CollectionResponseModel.cs | 25 -------- ...OrganizationUserCollectionResponseModel.cs | 26 -------- .../Response/OrganizationUserResponseModel.cs | 64 ++++++++++++++++--- ...lectionDetails.cs => SelectionReadOnly.cs} | 4 +- .../Repositories/ICollectionUserRepository.cs | 1 - .../IOrganizationUserRepository.cs | 2 +- .../SqlServer/CollectionRepository.cs | 8 ++- .../SqlServer/CollectionUserRepository.cs | 19 ++---- .../SqlServer/OrganizationUserRepository.cs | 11 ++-- src/Sql/Sql.sqlproj | 6 +- .../CipherDetails_ReadByIdUserId.sql | 15 ++++- .../CipherDetails_ReadByTypeUserId.sql | 15 ++++- .../CipherDetails_ReadByUserId.sql | 15 ++++- ...ipherDetails_ReadByUserIdHasCollection.sql | 15 ++++- .../Cipher_UpdateWithCollections.sql | 13 +++- .../CollectionCipher_ReadByUserId.sql | 19 ++++-- .../CollectionCipher_ReadByUserIdCipherId.sql | 21 ++++-- .../CollectionCipher_UpdateCollections.sql | 21 ++++-- ...tionUserCollectionDetails_ReadByUserId.sql | 13 ---- .../Collection_ReadByUserId.sql | 22 +++++-- .../OrganizationUserUserDetails_ReadById.sql | 20 ------ ...ganizationUser_ReadWithCollectionsById.sql | 18 ++++++ .../CollectionUserCollectionDetailsView.sql | 18 ------ .../Views/CollectionUserUserDetailsView.sql | 13 +++- 26 files changed, 238 insertions(+), 183 deletions(-) delete mode 100644 src/Core/Models/Api/Response/OrganizationUserCollectionResponseModel.cs rename src/Core/Models/Data/{CollectionUserCollectionDetails.cs => SelectionReadOnly.cs} (51%) delete mode 100644 src/Sql/dbo/Stored Procedures/CollectionUserCollectionDetails_ReadByUserId.sql delete mode 100644 src/Sql/dbo/Stored Procedures/OrganizationUserUserDetails_ReadById.sql create mode 100644 src/Sql/dbo/Stored Procedures/OrganizationUser_ReadWithCollectionsById.sql delete mode 100644 src/Sql/dbo/Views/CollectionUserCollectionDetailsView.sql diff --git a/src/Api/Controllers/CollectionsController.cs b/src/Api/Controllers/CollectionsController.cs index dab97618b..053a51037 100644 --- a/src/Api/Controllers/CollectionsController.cs +++ b/src/Api/Controllers/CollectionsController.cs @@ -74,12 +74,11 @@ namespace Bit.Api.Controllers } [HttpGet("~/collections")] - public async Task> GetUser() + public async Task> GetUser() { - var collections = await _collectionUserRepository.GetManyDetailsByUserIdAsync( - _userService.GetProperUserId(User).Value); - var responses = collections.Select(c => new CollectionUserDetailsResponseModel(c)); - return new ListResponseModel(responses); + var collections = await _collectionRepository.GetManyByUserIdAsync(_userService.GetProperUserId(User).Value); + var responses = collections.Select(c => new CollectionResponseModel(c)); + return new ListResponseModel(responses); } [HttpPost("")] diff --git a/src/Api/Controllers/OrganizationUsersController.cs b/src/Api/Controllers/OrganizationUsersController.cs index daedeaa32..bbd5779b8 100644 --- a/src/Api/Controllers/OrganizationUsersController.cs +++ b/src/Api/Controllers/OrganizationUsersController.cs @@ -45,7 +45,7 @@ namespace Bit.Api.Controllers [HttpGet("{id}")] public async Task Get(string orgId, string id) { - var organizationUser = await _organizationUserRepository.GetDetailsByIdAsync(new Guid(id)); + var organizationUser = await _organizationUserRepository.GetByIdWithCollectionsAsync(new Guid(id)); if(organizationUser == null || !_currentContext.OrganizationAdmin(organizationUser.Item1.OrganizationId)) { throw new NotFoundException(); @@ -55,7 +55,7 @@ namespace Bit.Api.Controllers } [HttpGet("")] - public async Task> Get(string orgId) + public async Task> Get(string orgId) { var orgGuidId = new Guid(orgId); if(!_currentContext.OrganizationAdmin(orgGuidId)) @@ -64,8 +64,8 @@ namespace Bit.Api.Controllers } var organizationUsers = await _organizationUserRepository.GetManyDetailsByOrganizationAsync(orgGuidId); - var responses = organizationUsers.Select(o => new OrganizationUserResponseModel(o)); - return new ListResponseModel(responses); + var responses = organizationUsers.Select(o => new OrganizationUserUserDetailsResponseModel(o)); + return new ListResponseModel(responses); } [HttpGet("{id}/groups")] diff --git a/src/Core/Models/Api/Response/CollectionResponseModel.cs b/src/Core/Models/Api/Response/CollectionResponseModel.cs index e42d5d07a..dc75f06f4 100644 --- a/src/Core/Models/Api/Response/CollectionResponseModel.cs +++ b/src/Core/Models/Api/Response/CollectionResponseModel.cs @@ -1,6 +1,5 @@ using System; using Bit.Core.Models.Table; -using Bit.Core.Models.Data; using System.Collections.Generic; namespace Bit.Core.Models.Api @@ -20,19 +19,6 @@ namespace Bit.Core.Models.Api Name = collection.Name; } - public CollectionResponseModel(CollectionUserCollectionDetails collection, string obj = "collection") - : base(obj) - { - if(collection == null) - { - throw new ArgumentNullException(nameof(collection)); - } - - Id = collection.Id.ToString(); - OrganizationId = collection.OrganizationId.ToString(); - Name = collection.Name; - } - public string Id { get; set; } public string OrganizationId { get; set; } public string Name { get; set; } @@ -48,15 +34,4 @@ namespace Bit.Core.Models.Api public IEnumerable GroupIds { get; set; } } - - public class CollectionUserDetailsResponseModel : CollectionResponseModel - { - public CollectionUserDetailsResponseModel(CollectionUserCollectionDetails collection) - : base(collection, "collectionUserDetails") - { - ReadOnly = collection.ReadOnly; - } - - public bool ReadOnly { get; set; } - } } diff --git a/src/Core/Models/Api/Response/OrganizationUserCollectionResponseModel.cs b/src/Core/Models/Api/Response/OrganizationUserCollectionResponseModel.cs deleted file mode 100644 index 796769ffa..000000000 --- a/src/Core/Models/Api/Response/OrganizationUserCollectionResponseModel.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using Bit.Core.Models.Data; - -namespace Bit.Core.Models.Api -{ - public class OrganizationUserCollectionResponseModel : ResponseModel - { - public OrganizationUserCollectionResponseModel(CollectionUserCollectionDetails details, - string obj = "organizationUserCollection") - : base(obj) - { - if(details == null) - { - throw new ArgumentNullException(nameof(details)); - } - - Id = details.Id.ToString(); - Name = details.Name; - ReadOnly = details.ReadOnly; - } - - public string Id { get; set; } - public string Name { get; set; } - public bool ReadOnly { get; set; } - } -} diff --git a/src/Core/Models/Api/Response/OrganizationUserResponseModel.cs b/src/Core/Models/Api/Response/OrganizationUserResponseModel.cs index 6075f963e..0b1ef2612 100644 --- a/src/Core/Models/Api/Response/OrganizationUserResponseModel.cs +++ b/src/Core/Models/Api/Response/OrganizationUserResponseModel.cs @@ -3,11 +3,27 @@ using Bit.Core.Enums; using Bit.Core.Models.Data; using System.Collections.Generic; using System.Linq; +using Bit.Core.Models.Table; namespace Bit.Core.Models.Api { public class OrganizationUserResponseModel : ResponseModel { + public OrganizationUserResponseModel(OrganizationUser organizationUser, string obj = "organizationUser") + : base(obj) + { + if(organizationUser == null) + { + throw new ArgumentNullException(nameof(organizationUser)); + } + + Id = organizationUser.Id.ToString(); + UserId = organizationUser.UserId?.ToString(); + Type = organizationUser.Type; + Status = organizationUser.Status; + AccessAll = organizationUser.AccessAll; + } + public OrganizationUserResponseModel(OrganizationUserUserDetails organizationUser, string obj = "organizationUser") : base(obj) { @@ -18,8 +34,6 @@ namespace Bit.Core.Models.Api Id = organizationUser.Id.ToString(); UserId = organizationUser.UserId?.ToString(); - Name = organizationUser.Name; - Email = organizationUser.Email; Type = organizationUser.Type; Status = organizationUser.Status; AccessAll = organizationUser.AccessAll; @@ -27,8 +41,6 @@ namespace Bit.Core.Models.Api public string Id { get; set; } public string UserId { get; set; } - public string Name { get; set; } - public string Email { get; set; } public OrganizationUserType Type { get; set; } public OrganizationUserStatusType Status { get; set; } public bool AccessAll { get; set; } @@ -36,14 +48,48 @@ namespace Bit.Core.Models.Api public class OrganizationUserDetailsResponseModel : OrganizationUserResponseModel { - public OrganizationUserDetailsResponseModel(OrganizationUserUserDetails organizationUser, - IEnumerable collections) + public OrganizationUserDetailsResponseModel(OrganizationUser organizationUser, + IEnumerable collections) : base(organizationUser, "organizationUserDetails") { - Collections = new ListResponseModel( - collections.Select(c => new OrganizationUserCollectionResponseModel(c))); + Collections = collections.Select(c => new CollectionSelection(c)); } - public ListResponseModel Collections { get; set; } + public IEnumerable Collections { get; set; } + + public class CollectionSelection + { + public CollectionSelection(Data.SelectionReadOnly selection) + { + if(selection == null) + { + throw new ArgumentNullException(nameof(selection)); + } + + Id = selection.Id.ToString(); + ReadOnly = selection.ReadOnly; + } + + public string Id { get; set; } + public bool ReadOnly { get; set; } + } + } + public class OrganizationUserUserDetailsResponseModel : OrganizationUserResponseModel + { + public OrganizationUserUserDetailsResponseModel(OrganizationUserUserDetails organizationUser, + string obj = "organizationUserUserDetails") + : base(organizationUser, obj) + { + if(organizationUser == null) + { + throw new ArgumentNullException(nameof(organizationUser)); + } + + Name = organizationUser.Name; + Email = organizationUser.Email; + } + + public string Name { get; set; } + public string Email { get; set; } } } diff --git a/src/Core/Models/Data/CollectionUserCollectionDetails.cs b/src/Core/Models/Data/SelectionReadOnly.cs similarity index 51% rename from src/Core/Models/Data/CollectionUserCollectionDetails.cs rename to src/Core/Models/Data/SelectionReadOnly.cs index d4fd03cfe..a8193e5fc 100644 --- a/src/Core/Models/Data/CollectionUserCollectionDetails.cs +++ b/src/Core/Models/Data/SelectionReadOnly.cs @@ -2,11 +2,9 @@ namespace Bit.Core.Models.Data { - public class CollectionUserCollectionDetails + public class SelectionReadOnly { public Guid Id { get; set; } - public Guid OrganizationId { get; set; } - public string Name { get; set; } public bool ReadOnly { get; set; } } } diff --git a/src/Core/Repositories/ICollectionUserRepository.cs b/src/Core/Repositories/ICollectionUserRepository.cs index d74161473..cc7ad4e00 100644 --- a/src/Core/Repositories/ICollectionUserRepository.cs +++ b/src/Core/Repositories/ICollectionUserRepository.cs @@ -9,7 +9,6 @@ namespace Bit.Core.Repositories public interface ICollectionUserRepository : IRepository { Task> GetManyByOrganizationUserIdAsync(Guid orgUserId); - Task> GetManyDetailsByUserIdAsync(Guid userId); Task> GetManyDetailsByCollectionIdAsync(Guid organizationId, Guid collectionId); } } diff --git a/src/Core/Repositories/IOrganizationUserRepository.cs b/src/Core/Repositories/IOrganizationUserRepository.cs index eaf2fb975..877d29008 100644 --- a/src/Core/Repositories/IOrganizationUserRepository.cs +++ b/src/Core/Repositories/IOrganizationUserRepository.cs @@ -16,7 +16,7 @@ namespace Bit.Core.Repositories Task> GetManyByOrganizationAsync(Guid organizationId, OrganizationUserType? type); Task GetByOrganizationAsync(Guid organizationId, string email); Task GetByOrganizationAsync(Guid organizationId, Guid userId); - Task>> GetDetailsByIdAsync(Guid id); + Task>> GetByIdWithCollectionsAsync(Guid id); Task> GetManyDetailsByOrganizationAsync(Guid organizationId); Task> GetManyDetailsByUserAsync(Guid userId, OrganizationUserStatusType? status = null); diff --git a/src/Core/Repositories/SqlServer/CollectionRepository.cs b/src/Core/Repositories/SqlServer/CollectionRepository.cs index 6477bbc65..fcabacd8c 100644 --- a/src/Core/Repositories/SqlServer/CollectionRepository.cs +++ b/src/Core/Repositories/SqlServer/CollectionRepository.cs @@ -68,11 +68,15 @@ namespace Bit.Core.Repositories.SqlServer using(var connection = new SqlConnection(ConnectionString)) { var results = await connection.QueryAsync( - $"[{Schema}].[{Table}_ReadByUserId]", + $"[{Schema}].[Collection_ReadByUserId]", new { UserId = userId }, commandType: CommandType.StoredProcedure); - return results.ToList(); + // Return distinct Id results. + return results + .GroupBy(c => c.Id) + .Select(c => c.First()) + .ToList(); } } diff --git a/src/Core/Repositories/SqlServer/CollectionUserRepository.cs b/src/Core/Repositories/SqlServer/CollectionUserRepository.cs index 811a9d0cc..2d2047ba8 100644 --- a/src/Core/Repositories/SqlServer/CollectionUserRepository.cs +++ b/src/Core/Repositories/SqlServer/CollectionUserRepository.cs @@ -33,19 +33,6 @@ namespace Bit.Core.Repositories.SqlServer } } - public async Task> GetManyDetailsByUserIdAsync(Guid userId) - { - using(var connection = new SqlConnection(ConnectionString)) - { - var results = await connection.QueryAsync( - $"[{Schema}].[CollectionUserCollectionDetails_ReadByUserId]", - new { UserId = userId }, - commandType: CommandType.StoredProcedure); - - return results.ToList(); - } - } - public async Task> GetManyDetailsByCollectionIdAsync(Guid organizationId, Guid collectionId) { @@ -56,7 +43,11 @@ namespace Bit.Core.Repositories.SqlServer new { OrganizationId = organizationId, CollectionId = collectionId }, commandType: CommandType.StoredProcedure); - return results.ToList(); + // Return distinct Id results. If at least one of the grouped results is not ReadOnly, that we return it. + return results + .GroupBy(c => c.Id) + .Select(g => g.OrderBy(og => og.ReadOnly).First()) + .ToList(); } } } diff --git a/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs b/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs index 49efb1767..f9e562488 100644 --- a/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs +++ b/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs @@ -114,19 +114,18 @@ namespace Bit.Core.Repositories.SqlServer } } - public async Task>> - GetDetailsByIdAsync(Guid id) + public async Task>> GetByIdWithCollectionsAsync(Guid id) { using(var connection = new SqlConnection(ConnectionString)) { var results = await connection.QueryMultipleAsync( - "[dbo].[OrganizationUserUserDetails_ReadById]", + "[dbo].[OrganizationUser_ReadWithCollectionsById]", new { Id = id }, commandType: CommandType.StoredProcedure); - var user = (await results.ReadAsync()).SingleOrDefault(); - var collections = (await results.ReadAsync()).ToList(); - return new Tuple>(user, collections); + var user = (await results.ReadAsync()).SingleOrDefault(); + var collections = (await results.ReadAsync()).ToList(); + return new Tuple>(user, collections); } } diff --git a/src/Sql/Sql.sqlproj b/src/Sql/Sql.sqlproj index 3d5aa779c..011a8da6c 100644 --- a/src/Sql/Sql.sqlproj +++ b/src/Sql/Sql.sqlproj @@ -82,7 +82,6 @@ - @@ -119,7 +118,6 @@ - @@ -137,7 +135,7 @@ - + @@ -174,7 +172,7 @@ - + diff --git a/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByIdUserId.sql b/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByIdUserId.sql index 6e45b2fca..1d3cb1ea5 100644 --- a/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByIdUserId.sql +++ b/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByIdUserId.sql @@ -8,7 +8,7 @@ BEGIN SELECT TOP 1 C.*, CASE - WHEN C.[UserId] IS NOT NULL OR OU.[AccessAll] = 1 OR CU.[ReadOnly] = 0 THEN 1 + WHEN C.[UserId] IS NOT NULL OR OU.[AccessAll] = 1 OR CU.[ReadOnly] = 0 OR G.[AccessAll] = 1 OR CG.[ReadOnly] = 0 THEN 1 ELSE 0 END [Edit] FROM @@ -21,6 +21,12 @@ BEGIN [dbo].[CollectionCipher] CC ON C.[UserId] IS NULL AND OU.[AccessAll] = 0 AND CC.[CipherId] = C.[Id] LEFT JOIN [dbo].[CollectionUser] CU ON CU.[CollectionId] = CC.[CollectionId] AND CU.[OrganizationUserId] = OU.[Id] + LEFT JOIN + [dbo].[GroupUser] GU ON C.[UserId] IS NULL AND 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] = CC.[CollectionId] AND CG.[GroupId] = GU.[GroupId] WHERE C.Id = @Id AND ( @@ -29,7 +35,12 @@ BEGIN C.[UserId] IS NULL AND OU.[Status] = 2 -- 2 = Confirmed AND O.[Enabled] = 1 - AND (OU.[AccessAll] = 1 OR CU.[CollectionId] IS NOT NULL) + AND ( + OU.[AccessAll] = 1 + OR CU.[CollectionId] IS NOT NULL + OR G.[AccessAll] = 1 + OR CG.[CollectionId] IS NOT NULL + ) ) ) ORDER BY diff --git a/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByTypeUserId.sql b/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByTypeUserId.sql index c58bf263c..a8245a17d 100644 --- a/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByTypeUserId.sql +++ b/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByTypeUserId.sql @@ -8,7 +8,7 @@ BEGIN SELECT C.*, CASE - WHEN C.[UserId] IS NOT NULL OR OU.[AccessAll] = 1 OR CU.[ReadOnly] = 0 THEN 1 + WHEN C.[UserId] IS NOT NULL OR OU.[AccessAll] = 1 OR CU.[ReadOnly] = 0 OR G.[AccessAll] = 1 OR CG.[ReadOnly] = 0 THEN 1 ELSE 0 END [Edit] FROM @@ -21,6 +21,12 @@ BEGIN [dbo].[CollectionCipher] CC ON C.[UserId] IS NULL AND OU.[AccessAll] = 0 AND CC.[CipherId] = C.[Id] LEFT JOIN [dbo].[CollectionUser] CU ON CU.[CollectionId] = CC.[CollectionId] AND CU.[OrganizationUserId] = OU.[Id] + LEFT JOIN + [dbo].[GroupUser] GU ON C.[UserId] IS NULL AND 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] = CC.[CollectionId] AND CG.[GroupId] = GU.[GroupId] WHERE C.[Type] = @Type AND ( @@ -29,7 +35,12 @@ BEGIN C.[UserId] IS NULL AND OU.[Status] = 2 -- 2 = Confirmed AND O.[Enabled] = 1 - AND (OU.[AccessAll] = 1 OR CU.[CollectionId] IS NOT NULL) + AND ( + OU.[AccessAll] = 1 + OR CU.[CollectionId] IS NOT NULL + OR G.[AccessAll] = 1 + OR CG.[CollectionId] 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 558a73f93..c3ac47e4a 100644 --- a/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByUserId.sql +++ b/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByUserId.sql @@ -7,7 +7,7 @@ BEGIN SELECT C.*, CASE - WHEN C.[UserId] IS NOT NULL OR OU.[AccessAll] = 1 OR CU.[ReadOnly] = 0 THEN 1 + WHEN C.[UserId] IS NOT NULL OR OU.[AccessAll] = 1 OR CU.[ReadOnly] = 0 OR G.[AccessAll] = 1 OR CG.[ReadOnly] = 0 THEN 1 ELSE 0 END [Edit] FROM @@ -20,12 +20,23 @@ BEGIN [dbo].[CollectionCipher] CC ON C.[UserId] IS NULL AND OU.[AccessAll] = 0 AND CC.[CipherId] = C.[Id] LEFT JOIN [dbo].[CollectionUser] CU ON CU.[CollectionId] = CC.[CollectionId] AND CU.[OrganizationUserId] = OU.[Id] + LEFT JOIN + [dbo].[GroupUser] GU ON C.[UserId] IS NULL AND 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] = CC.[CollectionId] AND CG.[GroupId] = GU.[GroupId] WHERE C.[UserId] = @UserId OR ( C.[UserId] IS NULL AND OU.[Status] = 2 -- 2 = Confirmed AND O.[Enabled] = 1 - AND (OU.[AccessAll] = 1 OR CU.[CollectionId] IS NOT NULL) + AND ( + OU.[AccessAll] = 1 + OR CU.[CollectionId] IS NOT NULL + OR G.[AccessAll] = 1 + OR CG.[CollectionId] IS NOT NULL + ) ) END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByUserIdHasCollection.sql b/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByUserIdHasCollection.sql index 893785d0a..871015704 100644 --- a/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByUserIdHasCollection.sql +++ b/src/Sql/dbo/Stored Procedures/CipherDetails_ReadByUserIdHasCollection.sql @@ -7,7 +7,7 @@ BEGIN SELECT C.*, CASE - WHEN OU.[AccessAll] = 1 OR CU.[ReadOnly] = 0 THEN 1 + WHEN C.[UserId] IS NOT NULL OR OU.[AccessAll] = 1 OR CU.[ReadOnly] = 0 OR G.[AccessAll] = 1 OR CG.[ReadOnly] = 0 THEN 1 ELSE 0 END [Edit] FROM @@ -20,8 +20,19 @@ BEGIN [dbo].[CollectionCipher] CC ON C.[UserId] IS NULL AND OU.[AccessAll] = 0 AND CC.[CipherId] = C.[Id] LEFT JOIN [dbo].[CollectionUser] CU ON CU.[CollectionId] = CC.[CollectionId] AND CU.[OrganizationUserId] = OU.[Id] + LEFT JOIN + [dbo].[GroupUser] GU ON C.[UserId] IS NULL AND 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] = CC.[CollectionId] AND CG.[GroupId] = GU.[GroupId] WHERE OU.[Status] = 2 -- 2 = Confirmed AND O.[Enabled] = 1 - AND (OU.[AccessAll] = 1 OR CU.[CollectionId] IS NOT NULL) + AND ( + OU.[AccessAll] = 1 + OR CU.[CollectionId] IS NOT NULL + OR G.[AccessAll] = 1 + OR CG.[CollectionId] IS NOT NULL + ) END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/Cipher_UpdateWithCollections.sql b/src/Sql/dbo/Stored Procedures/Cipher_UpdateWithCollections.sql index 6a1d7e9d3..3d552149b 100644 --- a/src/Sql/dbo/Stored Procedures/Cipher_UpdateWithCollections.sql +++ b/src/Sql/dbo/Stored Procedures/Cipher_UpdateWithCollections.sql @@ -35,11 +35,22 @@ BEGIN [dbo].[OrganizationUser] OU ON OU.[OrganizationId] = O.[Id] AND OU.[UserId] = @UserId LEFT JOIN [dbo].[CollectionUser] CU ON OU.[AccessAll] = 0 AND CU.[CollectionId] = S.[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.[GroupId] = GU.[GroupId] WHERE O.[Id] = @OrganizationId AND O.[Enabled] = 1 AND OU.[Status] = 2 -- Confirmed - AND (OU.[AccessAll] = 1 OR CU.[ReadOnly] = 0) + AND ( + OU.[AccessAll] = 1 + OR CU.[ReadOnly] = 0 + OR G.[AccessAll] = 1 + OR CG.[ReadOnly] = 0 + ) ) INSERT INTO [dbo].[CollectionCipher] ( diff --git a/src/Sql/dbo/Stored Procedures/CollectionCipher_ReadByUserId.sql b/src/Sql/dbo/Stored Procedures/CollectionCipher_ReadByUserId.sql index c489055fe..9a73ce6a1 100644 --- a/src/Sql/dbo/Stored Procedures/CollectionCipher_ReadByUserId.sql +++ b/src/Sql/dbo/Stored Procedures/CollectionCipher_ReadByUserId.sql @@ -5,16 +5,27 @@ BEGIN SET NOCOUNT ON SELECT - SC.* + CC.* FROM - [dbo].[CollectionCipher] SC + [dbo].[CollectionCipher] CC INNER JOIN - [dbo].[Collection] S ON S.[Id] = SC.[CollectionId] + [dbo].[Collection] S ON S.[Id] = CC.[CollectionId] INNER JOIN [dbo].[OrganizationUser] OU ON OU.[OrganizationId] = S.[OrganizationId] AND OU.[UserId] = @UserId LEFT JOIN [dbo].[CollectionUser] CU ON OU.[AccessAll] = 0 AND CU.[CollectionId] = S.[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] = CC.[CollectionId] AND CG.[GroupId] = GU.[GroupId] WHERE OU.[Status] = 2 -- Confirmed - AND (OU.[AccessAll] = 1 OR CU.[CollectionId] IS NOT NULL) + AND ( + OU.[AccessAll] = 1 + OR CU.[CollectionId] IS NOT NULL + OR G.[AccessAll] = 1 + OR CG.[CollectionId] IS NOT NULL + ) END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/CollectionCipher_ReadByUserIdCipherId.sql b/src/Sql/dbo/Stored Procedures/CollectionCipher_ReadByUserIdCipherId.sql index fa376126d..b83607d65 100644 --- a/src/Sql/dbo/Stored Procedures/CollectionCipher_ReadByUserIdCipherId.sql +++ b/src/Sql/dbo/Stored Procedures/CollectionCipher_ReadByUserIdCipherId.sql @@ -6,17 +6,28 @@ BEGIN SET NOCOUNT ON SELECT - SC.* + CC.* FROM - [dbo].[CollectionCipher] SC + [dbo].[CollectionCipher] CC INNER JOIN - [dbo].[Collection] S ON S.[Id] = SC.[CollectionId] + [dbo].[Collection] S ON S.[Id] = CC.[CollectionId] INNER JOIN [dbo].[OrganizationUser] OU ON OU.[OrganizationId] = S.[OrganizationId] AND OU.[UserId] = @UserId LEFT JOIN [dbo].[CollectionUser] CU ON OU.[AccessAll] = 0 AND CU.[CollectionId] = S.[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] = CC.[CollectionId] AND CG.[GroupId] = GU.[GroupId] WHERE - SC.[CipherId] = @CipherId + CC.[CipherId] = @CipherId AND OU.[Status] = 2 -- Confirmed - AND (OU.[AccessAll] = 1 OR CU.[CollectionId] IS NOT NULL) + AND ( + OU.[AccessAll] = 1 + OR CU.[CollectionId] IS NOT NULL + OR G.[AccessAll] = 1 + OR CG.[CollectionId] IS NOT NULL + ) END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/CollectionCipher_UpdateCollections.sql b/src/Sql/dbo/Stored Procedures/CollectionCipher_UpdateCollections.sql index 2a24494a3..53dbfaa76 100644 --- a/src/Sql/dbo/Stored Procedures/CollectionCipher_UpdateCollections.sql +++ b/src/Sql/dbo/Stored Procedures/CollectionCipher_UpdateCollections.sql @@ -17,20 +17,31 @@ BEGIN ;WITH [AvailableCollectionsCTE] AS( SELECT - S.[Id] + C.[Id] FROM - [dbo].[Collection] S + [dbo].[Collection] C INNER JOIN - [Organization] O ON O.[Id] = S.[OrganizationId] + [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] = S.[Id] AND CU.[OrganizationUserId] = OU.[Id] + [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] = @OrgId AND O.[Enabled] = 1 AND OU.[Status] = 2 -- Confirmed - AND (OU.[AccessAll] = 1 OR CU.[ReadOnly] = 0) + AND ( + OU.[AccessAll] = 1 + OR CU.[CollectionId] IS NOT NULL + OR G.[AccessAll] = 1 + OR CG.[CollectionId] IS NOT NULL + ) ) MERGE [dbo].[CollectionCipher] AS [Target] diff --git a/src/Sql/dbo/Stored Procedures/CollectionUserCollectionDetails_ReadByUserId.sql b/src/Sql/dbo/Stored Procedures/CollectionUserCollectionDetails_ReadByUserId.sql deleted file mode 100644 index 9514c94dd..000000000 --- a/src/Sql/dbo/Stored Procedures/CollectionUserCollectionDetails_ReadByUserId.sql +++ /dev/null @@ -1,13 +0,0 @@ -CREATE PROCEDURE [dbo].[CollectionUserCollectionDetails_ReadByUserId] - @UserId UNIQUEIDENTIFIER -AS -BEGIN - SET NOCOUNT ON - - SELECT - * - FROM - [dbo].[CollectionUserCollectionDetailsView] - WHERE - [UserId] = @UserId -END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/Collection_ReadByUserId.sql b/src/Sql/dbo/Stored Procedures/Collection_ReadByUserId.sql index a87aced68..3618bc2b6 100644 --- a/src/Sql/dbo/Stored Procedures/Collection_ReadByUserId.sql +++ b/src/Sql/dbo/Stored Procedures/Collection_ReadByUserId.sql @@ -9,13 +9,21 @@ BEGIN FROM [dbo].[CollectionView] C INNER JOIN - [Organization] O ON O.[Id] = C.[OrganizationId] - INNER JOIN - [dbo].[OrganizationUser] OU ON OU.[OrganizationId] = O.[Id] AND OU.[UserId] = @UserId + [dbo].[OrganizationUser] OU ON C.[OrganizationId] = OU.[OrganizationId] LEFT JOIN - [dbo].[CollectionUser] CU ON OU.[AccessAll] = 0 AND CU.[CollectionId] = C.[Id] AND CU.[OrganizationUserId] = OU.[Id] + [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 - OU.[Status] = 2 -- Confirmed - AND O.[Enabled] = 1 - AND (OU.[AccessAll] = 1 OR CU.[CollectionId] IS NOT NULL) + OU.[UserId] = @UserId + AND ( + OU.[AccessAll] = 1 + OR CU.[Id] IS NOT NULL + OR G.[AccessAll] = 1 + OR CG.[CollectionId] IS NOT NULL + ) END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/OrganizationUserUserDetails_ReadById.sql b/src/Sql/dbo/Stored Procedures/OrganizationUserUserDetails_ReadById.sql deleted file mode 100644 index fe0ac62df..000000000 --- a/src/Sql/dbo/Stored Procedures/OrganizationUserUserDetails_ReadById.sql +++ /dev/null @@ -1,20 +0,0 @@ -CREATE PROCEDURE [dbo].[OrganizationUserUserDetails_ReadById] - @Id UNIQUEIDENTIFIER -AS -BEGIN - SET NOCOUNT ON - - SELECT - * - FROM - [dbo].[OrganizationUserUserDetailsView] - WHERE - [Id] = @Id - - SELECT - * - FROM - [dbo].[CollectionUserCollectionDetailsView] - WHERE - [OrganizationUserId] = @Id -END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadWithCollectionsById.sql b/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadWithCollectionsById.sql new file mode 100644 index 000000000..39177f37f --- /dev/null +++ b/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadWithCollectionsById.sql @@ -0,0 +1,18 @@ +CREATE PROCEDURE [dbo].[OrganizationUser_ReadWithCollectionsById] + @Id UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + EXEC [OrganizationUser_ReadById] @Id + + SELECT + CU.[CollectionId] Id, + CU.[ReadOnly] + FROM + [dbo].[OrganizationUser] OU + INNER JOIN + [dbo].[CollectionUser] CU ON OU.[AccessAll] = 0 AND CU.[OrganizationUserId] = [OU].[Id] + WHERE + [OrganizationUserId] = @Id +END \ No newline at end of file diff --git a/src/Sql/dbo/Views/CollectionUserCollectionDetailsView.sql b/src/Sql/dbo/Views/CollectionUserCollectionDetailsView.sql deleted file mode 100644 index 161821237..000000000 --- a/src/Sql/dbo/Views/CollectionUserCollectionDetailsView.sql +++ /dev/null @@ -1,18 +0,0 @@ -CREATE VIEW [dbo].[CollectionUserCollectionDetailsView] -AS -SELECT - C.[Id] Id, - C.[OrganizationId], - C.[Name], - OU.[UserId], - OU.[Id] AS [OrganizationUserId], - CASE WHEN OU.[AccessAll] = 0 AND CU.[ReadOnly] = 1 THEN 1 ELSE 0 END [ReadOnly] -FROM - [dbo].[Collection] C -INNER JOIN - [dbo].[OrganizationUser] OU ON C.[OrganizationId] = OU.[OrganizationId] -LEFT JOIN - [dbo].[CollectionUser] CU ON OU.[AccessAll] = 0 AND CU.[CollectionId] = C.[Id] AND CU.[OrganizationUserId] = [OU].[Id] -WHERE - OU.[AccessAll] = 1 - OR CU.[Id] IS NOT NULL \ No newline at end of file diff --git a/src/Sql/dbo/Views/CollectionUserUserDetailsView.sql b/src/Sql/dbo/Views/CollectionUserUserDetailsView.sql index 8e05d7923..7fb9b8852 100644 --- a/src/Sql/dbo/Views/CollectionUserUserDetailsView.sql +++ b/src/Sql/dbo/Views/CollectionUserUserDetailsView.sql @@ -10,10 +10,19 @@ SELECT ISNULL(U.[Email], OU.[Email]) Email, OU.[Status], OU.[Type], - CASE WHEN OU.[AccessAll] = 0 AND CU.[ReadOnly] = 1 THEN 1 ELSE 0 END [ReadOnly] + CASE + WHEN OU.[AccessAll] = 0 AND CU.[ReadOnly] = 1 AND G.[AccessAll] = 0 AND CG.[ReadOnly] = 1 THEN 1 + ELSE 0 + END [ReadOnly] FROM [dbo].[OrganizationUser] OU LEFT JOIN [dbo].[CollectionUser] CU ON OU.[AccessAll] = 0 AND CU.[OrganizationUserId] = OU.[Id] LEFT JOIN - [dbo].[User] U ON U.[Id] = OU.[UserId] \ No newline at end of file + [dbo].[User] U ON U.[Id] = OU.[UserId] +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.[GroupId] = GU.[GroupId] \ No newline at end of file