Browse Source
* Add Manage permission to UserCipherDetails and CipherDetails_ReadByIdUserId * Add Manage property to CipherDetails and UserCipherDetailsQuery * Add integration test for CipherRepository Manage permission rules * Update CipherDetails_ReadWithoutOrganizationsByUserId to include Manage permission * Refactor UserCipherDetailsQuery to include detailed permission and organization properties * Refactor CipherRepositoryTests to improve test organization and readability - Split large test method into smaller, focused methods - Added helper methods for creating test data and performing assertions - Improved test coverage for cipher permissions in different scenarios - Maintained existing test logic while enhancing code structure * Refactor CipherRepositoryTests to consolidate cipher permission tests - Removed redundant helper methods for permission assertions - Simplified test methods for GetCipherPermissionsForOrganizationAsync, GetManyByUserIdAsync, and GetByIdAsync - Maintained existing test coverage for cipher manage permissions - Improved code readability and reduced code duplication * Add integration test for CipherRepository group collection manage permissions - Added new test method GetCipherPermissionsForOrganizationAsync_ManageProperty_RespectsCollectionGroupRules - Implemented helper method CreateCipherInOrganizationCollectionWithGroup to support group-based collection permission testing - Verified manage permissions are correctly applied based on group collection access settings * Add @Manage parameter to Cipher stored procedures - Updated CipherDetails_Create, CipherDetails_CreateWithCollections, and CipherDetails_Update stored procedures - Added @Manage parameter with comment "-- not used" - Included new stored procedure implementations in migration script - Consistent with previous work on adding Manage property to cipher details * Update UserCipherDetails functions to reorder Manage and ViewPassword columns * Reorder Manage and ViewPassword properties in cipher details queries * Bump date in migration scriptpull/5301/head
11 changed files with 645 additions and 12 deletions
@ -0,0 +1,309 @@
@@ -0,0 +1,309 @@
|
||||
CREATE OR ALTER FUNCTION [dbo].[UserCipherDetails](@UserId UNIQUEIDENTIFIER) |
||||
RETURNS TABLE |
||||
AS RETURN |
||||
WITH [CTE] AS ( |
||||
SELECT |
||||
[Id], |
||||
[OrganizationId] |
||||
FROM |
||||
[OrganizationUser] |
||||
WHERE |
||||
[UserId] = @UserId |
||||
AND [Status] = 2 -- Confirmed |
||||
) |
||||
SELECT |
||||
C.*, |
||||
CASE |
||||
WHEN COALESCE(CU.[ReadOnly], CG.[ReadOnly], 0) = 0 |
||||
THEN 1 |
||||
ELSE 0 |
||||
END [Edit], |
||||
CASE |
||||
WHEN COALESCE(CU.[HidePasswords], CG.[HidePasswords], 0) = 0 |
||||
THEN 1 |
||||
ELSE 0 |
||||
END [ViewPassword], |
||||
CASE |
||||
WHEN COALESCE(CU.[Manage], CG.[Manage], 0) = 1 |
||||
THEN 1 |
||||
ELSE 0 |
||||
END [Manage], |
||||
CASE |
||||
WHEN O.[UseTotp] = 1 |
||||
THEN 1 |
||||
ELSE 0 |
||||
END [OrganizationUseTotp] |
||||
FROM |
||||
[dbo].[CipherDetails](@UserId) C |
||||
INNER JOIN |
||||
[CTE] OU ON C.[UserId] IS NULL AND C.[OrganizationId] IN (SELECT [OrganizationId] FROM [CTE]) |
||||
INNER JOIN |
||||
[dbo].[Organization] O ON O.[Id] = OU.[OrganizationId] AND O.[Id] = C.[OrganizationId] AND O.[Enabled] = 1 |
||||
LEFT JOIN |
||||
[dbo].[CollectionCipher] CC ON 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 CU.[CollectionId] IS NULL AND GU.[OrganizationUserId] = OU.[Id] |
||||
LEFT JOIN |
||||
[dbo].[Group] G ON G.[Id] = GU.[GroupId] |
||||
LEFT JOIN |
||||
[dbo].[CollectionGroup] CG ON CG.[CollectionId] = CC.[CollectionId] AND CG.[GroupId] = GU.[GroupId] |
||||
WHERE |
||||
CU.[CollectionId] IS NOT NULL |
||||
OR CG.[CollectionId] IS NOT NULL |
||||
|
||||
UNION ALL |
||||
|
||||
SELECT |
||||
*, |
||||
1 [Edit], |
||||
1 [ViewPassword], |
||||
1 [Manage], |
||||
0 [OrganizationUseTotp] |
||||
FROM |
||||
[dbo].[CipherDetails](@UserId) |
||||
WHERE |
||||
[UserId] = @UserId |
||||
GO |
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[CipherDetails_ReadByIdUserId] |
||||
@Id UNIQUEIDENTIFIER, |
||||
@UserId UNIQUEIDENTIFIER |
||||
AS |
||||
BEGIN |
||||
SET NOCOUNT ON |
||||
|
||||
SELECT |
||||
[Id], |
||||
[UserId], |
||||
[OrganizationId], |
||||
[Type], |
||||
[Data], |
||||
[Attachments], |
||||
[CreationDate], |
||||
[RevisionDate], |
||||
[Favorite], |
||||
[FolderId], |
||||
[DeletedDate], |
||||
[Reprompt], |
||||
[Key], |
||||
[OrganizationUseTotp], |
||||
MAX ([Edit]) AS [Edit], |
||||
MAX ([ViewPassword]) AS [ViewPassword], |
||||
MAX ([Manage]) AS [Manage] |
||||
FROM |
||||
[dbo].[UserCipherDetails](@UserId) |
||||
WHERE |
||||
[Id] = @Id |
||||
GROUP BY |
||||
[Id], |
||||
[UserId], |
||||
[OrganizationId], |
||||
[Type], |
||||
[Data], |
||||
[Attachments], |
||||
[CreationDate], |
||||
[RevisionDate], |
||||
[Favorite], |
||||
[FolderId], |
||||
[DeletedDate], |
||||
[Reprompt], |
||||
[Key], |
||||
[OrganizationUseTotp] |
||||
END |
||||
GO |
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[CipherDetails_ReadWithoutOrganizationsByUserId] |
||||
@UserId UNIQUEIDENTIFIER |
||||
AS |
||||
BEGIN |
||||
SET NOCOUNT ON |
||||
|
||||
SELECT |
||||
*, |
||||
1 [Edit], |
||||
1 [ViewPassword], |
||||
1 [Manage], |
||||
0 [OrganizationUseTotp] |
||||
FROM |
||||
[dbo].[CipherDetails](@UserId) |
||||
WHERE |
||||
[UserId] = @UserId |
||||
END |
||||
GO |
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[CipherDetails_Create] |
||||
@Id UNIQUEIDENTIFIER, |
||||
@UserId UNIQUEIDENTIFIER, |
||||
@OrganizationId UNIQUEIDENTIFIER, |
||||
@Type TINYINT, |
||||
@Data NVARCHAR(MAX), |
||||
@Favorites NVARCHAR(MAX), -- not used |
||||
@Folders NVARCHAR(MAX), -- not used |
||||
@Attachments NVARCHAR(MAX), -- not used |
||||
@CreationDate DATETIME2(7), |
||||
@RevisionDate DATETIME2(7), |
||||
@FolderId UNIQUEIDENTIFIER, |
||||
@Favorite BIT, |
||||
@Edit BIT, -- not used |
||||
@ViewPassword BIT, -- not used |
||||
@Manage BIT, -- not used |
||||
@OrganizationUseTotp BIT, -- not used |
||||
@DeletedDate DATETIME2(7), |
||||
@Reprompt TINYINT, |
||||
@Key VARCHAR(MAX) = NULL |
||||
AS |
||||
BEGIN |
||||
SET NOCOUNT ON |
||||
|
||||
DECLARE @UserIdKey VARCHAR(50) = CONCAT('"', @UserId, '"') |
||||
DECLARE @UserIdPath VARCHAR(50) = CONCAT('$.', @UserIdKey) |
||||
|
||||
INSERT INTO [dbo].[Cipher] |
||||
( |
||||
[Id], |
||||
[UserId], |
||||
[OrganizationId], |
||||
[Type], |
||||
[Data], |
||||
[Favorites], |
||||
[Folders], |
||||
[CreationDate], |
||||
[RevisionDate], |
||||
[DeletedDate], |
||||
[Reprompt], |
||||
[Key] |
||||
) |
||||
VALUES |
||||
( |
||||
@Id, |
||||
CASE WHEN @OrganizationId IS NULL THEN @UserId ELSE NULL END, |
||||
@OrganizationId, |
||||
@Type, |
||||
@Data, |
||||
CASE WHEN @Favorite = 1 THEN CONCAT('{', @UserIdKey, ':true}') ELSE NULL END, |
||||
CASE WHEN @FolderId IS NOT NULL THEN CONCAT('{', @UserIdKey, ':"', @FolderId, '"', '}') ELSE NULL END, |
||||
@CreationDate, |
||||
@RevisionDate, |
||||
@DeletedDate, |
||||
@Reprompt, |
||||
@Key |
||||
) |
||||
|
||||
IF @OrganizationId IS NOT NULL |
||||
BEGIN |
||||
EXEC [dbo].[User_BumpAccountRevisionDateByCipherId] @Id, @OrganizationId |
||||
END |
||||
ELSE IF @UserId IS NOT NULL |
||||
BEGIN |
||||
EXEC [dbo].[User_BumpAccountRevisionDate] @UserId |
||||
END |
||||
END |
||||
GO |
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[CipherDetails_CreateWithCollections] |
||||
@Id UNIQUEIDENTIFIER, |
||||
@UserId UNIQUEIDENTIFIER, |
||||
@OrganizationId UNIQUEIDENTIFIER, |
||||
@Type TINYINT, |
||||
@Data NVARCHAR(MAX), |
||||
@Favorites NVARCHAR(MAX), -- not used |
||||
@Folders NVARCHAR(MAX), -- not used |
||||
@Attachments NVARCHAR(MAX), -- not used |
||||
@CreationDate DATETIME2(7), |
||||
@RevisionDate DATETIME2(7), |
||||
@FolderId UNIQUEIDENTIFIER, |
||||
@Favorite BIT, |
||||
@Edit BIT, -- not used |
||||
@ViewPassword BIT, -- not used |
||||
@Manage BIT, -- not used |
||||
@OrganizationUseTotp BIT, -- not used |
||||
@DeletedDate DATETIME2(7), |
||||
@Reprompt TINYINT, |
||||
@Key VARCHAR(MAX) = NULL, |
||||
@CollectionIds AS [dbo].[GuidIdArray] READONLY |
||||
AS |
||||
BEGIN |
||||
SET NOCOUNT ON |
||||
|
||||
EXEC [dbo].[CipherDetails_Create] @Id, @UserId, @OrganizationId, @Type, @Data, @Favorites, @Folders, |
||||
@Attachments, @CreationDate, @RevisionDate, @FolderId, @Favorite, @Edit, @ViewPassword, @Manage, |
||||
@OrganizationUseTotp, @DeletedDate, @Reprompt, @Key |
||||
|
||||
DECLARE @UpdateCollectionsSuccess INT |
||||
EXEC @UpdateCollectionsSuccess = [dbo].[Cipher_UpdateCollections] @Id, @UserId, @OrganizationId, @CollectionIds |
||||
END |
||||
GO |
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[CipherDetails_Update] |
||||
@Id UNIQUEIDENTIFIER, |
||||
@UserId UNIQUEIDENTIFIER, |
||||
@OrganizationId UNIQUEIDENTIFIER, |
||||
@Type TINYINT, |
||||
@Data NVARCHAR(MAX), |
||||
@Favorites NVARCHAR(MAX), -- not used |
||||
@Folders NVARCHAR(MAX), -- not used |
||||
@Attachments NVARCHAR(MAX), |
||||
@CreationDate DATETIME2(7), |
||||
@RevisionDate DATETIME2(7), |
||||
@FolderId UNIQUEIDENTIFIER, |
||||
@Favorite BIT, |
||||
@Edit BIT, -- not used |
||||
@ViewPassword BIT, -- not used |
||||
@Manage BIT, -- not used |
||||
@OrganizationUseTotp BIT, -- not used |
||||
@DeletedDate DATETIME2(2), |
||||
@Reprompt TINYINT, |
||||
@Key VARCHAR(MAX) = NULL |
||||
AS |
||||
BEGIN |
||||
SET NOCOUNT ON |
||||
|
||||
DECLARE @UserIdKey VARCHAR(50) = CONCAT('"', @UserId, '"') |
||||
DECLARE @UserIdPath VARCHAR(50) = CONCAT('$.', @UserIdKey) |
||||
|
||||
UPDATE |
||||
[dbo].[Cipher] |
||||
SET |
||||
[UserId] = CASE WHEN @OrganizationId IS NULL THEN @UserId ELSE NULL END, |
||||
[OrganizationId] = @OrganizationId, |
||||
[Type] = @Type, |
||||
[Data] = @Data, |
||||
[Folders] = |
||||
CASE |
||||
WHEN @FolderId IS NOT NULL AND [Folders] IS NULL THEN |
||||
CONCAT('{', @UserIdKey, ':"', @FolderId, '"', '}') |
||||
WHEN @FolderId IS NOT NULL THEN |
||||
JSON_MODIFY([Folders], @UserIdPath, CAST(@FolderId AS VARCHAR(50))) |
||||
ELSE |
||||
JSON_MODIFY([Folders], @UserIdPath, NULL) |
||||
END, |
||||
[Favorites] = |
||||
CASE |
||||
WHEN @Favorite = 1 AND [Favorites] IS NULL THEN |
||||
CONCAT('{', @UserIdKey, ':true}') |
||||
WHEN @Favorite = 1 THEN |
||||
JSON_MODIFY([Favorites], @UserIdPath, CAST(1 AS BIT)) |
||||
ELSE |
||||
JSON_MODIFY([Favorites], @UserIdPath, NULL) |
||||
END, |
||||
[Attachments] = @Attachments, |
||||
[Reprompt] = @Reprompt, |
||||
[CreationDate] = @CreationDate, |
||||
[RevisionDate] = @RevisionDate, |
||||
[DeletedDate] = @DeletedDate, |
||||
[Key] = @Key |
||||
WHERE |
||||
[Id] = @Id |
||||
|
||||
IF @OrganizationId IS NOT NULL |
||||
BEGIN |
||||
EXEC [dbo].[User_BumpAccountRevisionDateByCipherId] @Id, @OrganizationId |
||||
END |
||||
ELSE IF @UserId IS NOT NULL |
||||
BEGIN |
||||
EXEC [dbo].[User_BumpAccountRevisionDate] @UserId |
||||
END |
||||
END |
||||
GO |
||||
Loading…
Reference in new issue