diff --git a/src/Sql/Sql.sqlproj b/src/Sql/Sql.sqlproj index 08040a0c30..ba8e0e9b74 100644 --- a/src/Sql/Sql.sqlproj +++ b/src/Sql/Sql.sqlproj @@ -214,5 +214,7 @@ + + \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/CipherDetails_Create.sql b/src/Sql/dbo/Stored Procedures/CipherDetails_Create.sql index 8b10900101..706372cab7 100644 --- a/src/Sql/dbo/Stored Procedures/CipherDetails_Create.sql +++ b/src/Sql/dbo/Stored Procedures/CipherDetails_Create.sql @@ -47,7 +47,7 @@ BEGIN IF @OrganizationId IS NOT NULL BEGIN - EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId + EXEC [dbo].[User_BumpAccountRevisionDateByCipherId] @Id, @OrganizationId END ELSE IF @UserId IS NOT NULL BEGIN diff --git a/src/Sql/dbo/Stored Procedures/CipherDetails_Update.sql b/src/Sql/dbo/Stored Procedures/CipherDetails_Update.sql index 951cb4bfe3..0dc6009c83 100644 --- a/src/Sql/dbo/Stored Procedures/CipherDetails_Update.sql +++ b/src/Sql/dbo/Stored Procedures/CipherDetails_Update.sql @@ -52,7 +52,7 @@ BEGIN IF @OrganizationId IS NOT NULL BEGIN - EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId + EXEC [dbo].[User_BumpAccountRevisionDateByCipherId] @Id, @OrganizationId END ELSE IF @UserId IS NOT NULL BEGIN diff --git a/src/Sql/dbo/Stored Procedures/Cipher_Create.sql b/src/Sql/dbo/Stored Procedures/Cipher_Create.sql index 83a044cecd..6990b35075 100644 --- a/src/Sql/dbo/Stored Procedures/Cipher_Create.sql +++ b/src/Sql/dbo/Stored Procedures/Cipher_Create.sql @@ -42,7 +42,7 @@ BEGIN IF @OrganizationId IS NOT NULL BEGIN - EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId + EXEC [dbo].[User_BumpAccountRevisionDateByCipherId] @Id, @OrganizationId END ELSE IF @UserId IS NOT NULL BEGIN diff --git a/src/Sql/dbo/Stored Procedures/Cipher_DeleteAttachment.sql b/src/Sql/dbo/Stored Procedures/Cipher_DeleteAttachment.sql index 69e6f2d92c..380045e87a 100644 --- a/src/Sql/dbo/Stored Procedures/Cipher_DeleteAttachment.sql +++ b/src/Sql/dbo/Stored Procedures/Cipher_DeleteAttachment.sql @@ -28,7 +28,7 @@ BEGIN IF @OrganizationId IS NOT NULL BEGIN EXEC [dbo].[Organization_UpdateStorage] @OrganizationId - EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId + EXEC [dbo].[User_BumpAccountRevisionDateByCipherId] @Id, @OrganizationId END ELSE IF @UserId IS NOT NULL BEGIN diff --git a/src/Sql/dbo/Stored Procedures/Cipher_DeleteById.sql b/src/Sql/dbo/Stored Procedures/Cipher_DeleteById.sql index 6d5a3628e8..b9b8f35558 100644 --- a/src/Sql/dbo/Stored Procedures/Cipher_DeleteById.sql +++ b/src/Sql/dbo/Stored Procedures/Cipher_DeleteById.sql @@ -30,7 +30,7 @@ BEGIN BEGIN EXEC [dbo].[Organization_UpdateStorage] @OrganizationId END - EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId + EXEC [dbo].[User_BumpAccountRevisionDateByCipherId] @Id, @OrganizationId END ELSE IF @UserId IS NOT NULL BEGIN diff --git a/src/Sql/dbo/Stored Procedures/Cipher_Move.sql b/src/Sql/dbo/Stored Procedures/Cipher_Move.sql index cd238381ef..c6b9c8ddc2 100644 --- a/src/Sql/dbo/Stored Procedures/Cipher_Move.sql +++ b/src/Sql/dbo/Stored Procedures/Cipher_Move.sql @@ -34,5 +34,4 @@ BEGIN [Id] IN (SELECT * FROM [IdsToMoveCTE]) EXEC [dbo].[User_BumpAccountRevisionDate] @UserId - -- TODO: What if some that were updated were organization ciphers? Then bump by org ids. END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/Cipher_Update.sql b/src/Sql/dbo/Stored Procedures/Cipher_Update.sql index 32d08b7d26..d8c17f21da 100644 --- a/src/Sql/dbo/Stored Procedures/Cipher_Update.sql +++ b/src/Sql/dbo/Stored Procedures/Cipher_Update.sql @@ -30,7 +30,7 @@ BEGIN IF @OrganizationId IS NOT NULL BEGIN - EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId + EXEC [dbo].[User_BumpAccountRevisionDateByCipherId] @Id, @OrganizationId END ELSE IF @UserId IS NOT NULL BEGIN diff --git a/src/Sql/dbo/Stored Procedures/Cipher_UpdateAttachment.sql b/src/Sql/dbo/Stored Procedures/Cipher_UpdateAttachment.sql index 2461639b25..520df72505 100644 --- a/src/Sql/dbo/Stored Procedures/Cipher_UpdateAttachment.sql +++ b/src/Sql/dbo/Stored Procedures/Cipher_UpdateAttachment.sql @@ -27,7 +27,7 @@ BEGIN IF @OrganizationId IS NOT NULL BEGIN EXEC [dbo].[Organization_UpdateStorage] @OrganizationId - EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId + EXEC [dbo].[User_BumpAccountRevisionDateByCipherId] @Id, @OrganizationId END ELSE IF @UserId IS NOT NULL BEGIN diff --git a/src/Sql/dbo/Stored Procedures/Cipher_UpdateWithCollections.sql b/src/Sql/dbo/Stored Procedures/Cipher_UpdateWithCollections.sql index bca9d6f328..ebdd3a3de1 100644 --- a/src/Sql/dbo/Stored Procedures/Cipher_UpdateWithCollections.sql +++ b/src/Sql/dbo/Stored Procedures/Cipher_UpdateWithCollections.sql @@ -84,7 +84,7 @@ BEGIN EXEC [dbo].[User_UpdateStorage] @UserId END - EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId + EXEC [dbo].[User_BumpAccountRevisionDateByCipherId] @Id, @OrganizationId SELECT 0 -- 0 = Success END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/CollectionCipher_Create.sql b/src/Sql/dbo/Stored Procedures/CollectionCipher_Create.sql index e6cee3ad80..52ae9b0f2a 100644 --- a/src/Sql/dbo/Stored Procedures/CollectionCipher_Create.sql +++ b/src/Sql/dbo/Stored Procedures/CollectionCipher_Create.sql @@ -19,6 +19,6 @@ BEGIN DECLARE @OrganizationId UNIQUEIDENTIFIER = (SELECT TOP 1 [OrganizationId] FROM [dbo].[Cipher] WHERE [Id] = @CipherId) IF @OrganizationId IS NOT NULL BEGIN - EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId + EXEC [dbo].[User_BumpAccountRevisionDateByCollectionId] @CollectionId, @OrganizationId END END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/CollectionCipher_Delete.sql b/src/Sql/dbo/Stored Procedures/CollectionCipher_Delete.sql index b2b6f75aeb..d337c3b423 100644 --- a/src/Sql/dbo/Stored Procedures/CollectionCipher_Delete.sql +++ b/src/Sql/dbo/Stored Procedures/CollectionCipher_Delete.sql @@ -15,6 +15,6 @@ BEGIN DECLARE @OrganizationId UNIQUEIDENTIFIER = (SELECT TOP 1 [OrganizationId] FROM [dbo].[Cipher] WHERE [Id] = @CipherId) IF @OrganizationId IS NOT NULL BEGIN - EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId + EXEC [dbo].[User_BumpAccountRevisionDateByCollectionId] @CollectionId, @OrganizationId END END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/Collection_Create.sql b/src/Sql/dbo/Stored Procedures/Collection_Create.sql index 7e281184e6..b939fb4146 100644 --- a/src/Sql/dbo/Stored Procedures/Collection_Create.sql +++ b/src/Sql/dbo/Stored Procedures/Collection_Create.sql @@ -24,4 +24,6 @@ BEGIN @CreationDate, @RevisionDate ) + + EXEC [dbo].[User_BumpAccountRevisionDateByCollectionId] @Id, @OrganizationId END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/Collection_CreateWithGroups.sql b/src/Sql/dbo/Stored Procedures/Collection_CreateWithGroups.sql index 107a8422ac..c4f90cd782 100644 --- a/src/Sql/dbo/Stored Procedures/Collection_CreateWithGroups.sql +++ b/src/Sql/dbo/Stored Procedures/Collection_CreateWithGroups.sql @@ -33,4 +33,6 @@ BEGIN @Groups WHERE [Id] IN (SELECT [Id] FROM [AvailableGroupsCTE]) + + EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/Collection_DeleteById.sql b/src/Sql/dbo/Stored Procedures/Collection_DeleteById.sql index e2e7172376..148a08be16 100644 --- a/src/Sql/dbo/Stored Procedures/Collection_DeleteById.sql +++ b/src/Sql/dbo/Stored Procedures/Collection_DeleteById.sql @@ -4,6 +4,12 @@ AS BEGIN SET NOCOUNT ON + DECLARE @OrganizationId UNIQUEIDENTIFIER = (SELECT TOP 1 [OrganizationId] FROM [dbo].[Collection] WHERE [Id] = @Id) + IF @OrganizationId IS NOT NULL + BEGIN + EXEC [dbo].[User_BumpAccountRevisionDateByCollectionId] @Id, @OrganizationId + END + DELETE FROM [dbo].[CollectionGroup] diff --git a/src/Sql/dbo/Stored Procedures/Collection_Update.sql b/src/Sql/dbo/Stored Procedures/Collection_Update.sql index 1ca0b74ea0..b6e7dbfc8c 100644 --- a/src/Sql/dbo/Stored Procedures/Collection_Update.sql +++ b/src/Sql/dbo/Stored Procedures/Collection_Update.sql @@ -17,4 +17,6 @@ BEGIN [RevisionDate] = @RevisionDate WHERE [Id] = @Id + + EXEC [dbo].[User_BumpAccountRevisionDateByCollectionId] @Id, @OrganizationId END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/Collection_UpdateWithGroups.sql b/src/Sql/dbo/Stored Procedures/Collection_UpdateWithGroups.sql index 2477fa49d8..6a4d23d6e7 100644 --- a/src/Sql/dbo/Stored Procedures/Collection_UpdateWithGroups.sql +++ b/src/Sql/dbo/Stored Procedures/Collection_UpdateWithGroups.sql @@ -41,5 +41,5 @@ BEGIN DELETE ; - -- TODO: Update user revision date times that this affects + EXEC [dbo].[User_BumpAccountRevisionDateByCollectionId] @Id, @OrganizationId END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/GroupUser_UpdateUsers.sql b/src/Sql/dbo/Stored Procedures/GroupUser_UpdateUsers.sql index c1cb7110c3..1e41def02d 100644 --- a/src/Sql/dbo/Stored Procedures/GroupUser_UpdateUsers.sql +++ b/src/Sql/dbo/Stored Procedures/GroupUser_UpdateUsers.sql @@ -42,5 +42,5 @@ BEGIN DELETE ; - -- TODO: Bump account revision date for all @OrganizationUserIds + EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrgId END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/Group_CreateWithCollections.sql b/src/Sql/dbo/Stored Procedures/Group_CreateWithCollections.sql index b8e13b11ea..8719632cc4 100644 --- a/src/Sql/dbo/Stored Procedures/Group_CreateWithCollections.sql +++ b/src/Sql/dbo/Stored Procedures/Group_CreateWithCollections.sql @@ -35,4 +35,6 @@ BEGIN @Collections WHERE [Id] IN (SELECT [Id] FROM [AvailableCollectionsCTE]) + + EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/Group_DeleteById.sql b/src/Sql/dbo/Stored Procedures/Group_DeleteById.sql index 4ad4dcd3bb..9c9b715fcb 100644 --- a/src/Sql/dbo/Stored Procedures/Group_DeleteById.sql +++ b/src/Sql/dbo/Stored Procedures/Group_DeleteById.sql @@ -4,6 +4,12 @@ AS BEGIN SET NOCOUNT ON + DECLARE @OrganizationId UNIQUEIDENTIFIER = (SELECT TOP 1 [OrganizationId] FROM [dbo].[Group] WHERE [Id] = @Id) + IF @OrganizationId IS NOT NULL + BEGIN + EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId + END + DELETE FROM [dbo].[Group] diff --git a/src/Sql/dbo/Stored Procedures/Group_UpdateWithCollections.sql b/src/Sql/dbo/Stored Procedures/Group_UpdateWithCollections.sql index f5132ddd47..27200ec36b 100644 --- a/src/Sql/dbo/Stored Procedures/Group_UpdateWithCollections.sql +++ b/src/Sql/dbo/Stored Procedures/Group_UpdateWithCollections.sql @@ -43,5 +43,5 @@ BEGIN DELETE ; - -- TODO: Update user revision date times that this affects + EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/OrganizationUser_DeleteById.sql b/src/Sql/dbo/Stored Procedures/OrganizationUser_DeleteById.sql index 4b342b5a9c..b8f751ac93 100644 --- a/src/Sql/dbo/Stored Procedures/OrganizationUser_DeleteById.sql +++ b/src/Sql/dbo/Stored Procedures/OrganizationUser_DeleteById.sql @@ -3,6 +3,8 @@ AS BEGIN SET NOCOUNT ON + + EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationUserId] @Id DELETE FROM diff --git a/src/Sql/dbo/Stored Procedures/User_BumpAccountRevisionDateByCipherId.sql b/src/Sql/dbo/Stored Procedures/User_BumpAccountRevisionDateByCipherId.sql new file mode 100644 index 0000000000..53a12ed6e0 --- /dev/null +++ b/src/Sql/dbo/Stored Procedures/User_BumpAccountRevisionDateByCipherId.sql @@ -0,0 +1,39 @@ +CREATE PROCEDURE [dbo].[User_BumpAccountRevisionDateByCipherId] + @CipherId UNIQUEIDENTIFIER, + @OrganizationId UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + UPDATE + U + SET + U.[AccountRevisionDate] = GETUTCDATE() + FROM + [dbo].[User] U + LEFT JOIN + [dbo].[OrganizationUser] OU ON OU.[UserId] = U.[Id] + LEFT JOIN + [dbo].[CollectionCipher] CC ON CC.[CipherId] = @CipherId + LEFT JOIN + [dbo].[CollectionUser] CU ON OU.[AccessAll] = 0 AND CU.[OrganizationUserId] = OU.[Id] AND CU.[CollectionId] = CC.[CollectionId] + 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] AND CG.[CollectionId] = CC.[CollectionId] + WHERE + OU.[Status] = 2 -- 2 = Confirmed + AND ( + CU.[CollectionId] IS NOT NULL + OR CG.[CollectionId] IS NOT NULL + OR ( + OU.[OrganizationId] = @OrganizationId + AND ( + OU.[AccessAll] = 1 + OR G.[AccessAll] = 1 + ) + ) + ) +END diff --git a/src/Sql/dbo/Stored Procedures/User_BumpAccountRevisionDateByCollectionId.sql b/src/Sql/dbo/Stored Procedures/User_BumpAccountRevisionDateByCollectionId.sql new file mode 100644 index 0000000000..0300fd2c8a --- /dev/null +++ b/src/Sql/dbo/Stored Procedures/User_BumpAccountRevisionDateByCollectionId.sql @@ -0,0 +1,37 @@ +CREATE PROCEDURE [dbo].[User_BumpAccountRevisionDateByCollectionId] + @CollectionId UNIQUEIDENTIFIER, + @OrganizationId UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + UPDATE + U + SET + U.[AccountRevisionDate] = GETUTCDATE() + FROM + [dbo].[User] U + LEFT JOIN + [dbo].[OrganizationUser] OU ON OU.[UserId] = U.[Id] + LEFT JOIN + [dbo].[CollectionUser] CU ON OU.[AccessAll] = 0 AND CU.[OrganizationUserId] = OU.[Id] AND CU.[CollectionId] = @CollectionId + 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] AND CG.[CollectionId] = @CollectionId + WHERE + OU.[Status] = 2 -- 2 = Confirmed + AND ( + CU.[CollectionId] IS NOT NULL + OR CG.[CollectionId] IS NOT NULL + OR ( + OU.[OrganizationId] = @OrganizationId + AND ( + OU.[AccessAll] = 1 + OR G.[AccessAll] = 1 + ) + ) + ) +END diff --git a/util/Setup/DbScripts/2017-11-24_00_UpdateProcs.sql b/util/Setup/DbScripts/2017-11-24_00_UpdateProcs.sql new file mode 100644 index 0000000000..96f8695932 --- /dev/null +++ b/util/Setup/DbScripts/2017-11-24_00_UpdateProcs.sql @@ -0,0 +1,1224 @@ +IF OBJECT_ID('[dbo].[Cipher_DeleteByUserId]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[Cipher_DeleteByUserId] +END +GO + +CREATE PROCEDURE [dbo].[Cipher_DeleteByUserId] + @UserId AS UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + DECLARE @BatchSize INT = 100 + + -- Delete ciphers + WHILE @BatchSize > 0 + BEGIN + BEGIN TRANSACTION Cipher_DeleteByUserId_Ciphers + + DELETE TOP(@BatchSize) + FROM + [dbo].[Cipher] + WHERE + [UserId] = @UserId + + SET @BatchSize = @@ROWCOUNT + + COMMIT TRANSACTION Cipher_DeleteByUserId_Ciphers + END + + -- Delete folders + DELETE + FROM + [dbo].[Folder] + WHERE + [UserId] = @UserId + + -- Cleanup user + EXEC [dbo].[User_UpdateStorage] @UserId + EXEC [dbo].[User_BumpAccountRevisionDate] @UserId +END +GO + +IF OBJECT_ID('[dbo].[User_DeleteById]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[User_DeleteById] +END +GO + +CREATE PROCEDURE [dbo].[User_DeleteById] + @Id UNIQUEIDENTIFIER +WITH RECOMPILE +AS +BEGIN + SET NOCOUNT ON + DECLARE @BatchSize INT = 100 + + -- Delete ciphers + WHILE @BatchSize > 0 + BEGIN + BEGIN TRANSACTION User_DeleteById_Ciphers + + DELETE TOP(@BatchSize) + FROM + [dbo].[Cipher] + WHERE + [UserId] = @Id + + SET @BatchSize = @@ROWCOUNT + + COMMIT TRANSACTION User_DeleteById_Ciphers + END + + BEGIN TRANSACTION User_DeleteById + + -- Delete folders + DELETE + FROM + [dbo].[Folder] + WHERE + [UserId] = @Id + + -- Delete devices + DELETE + FROM + [dbo].[Device] + WHERE + [UserId] = @Id + + -- Delete collection users + DELETE + CU + FROM + [dbo].[CollectionUser] CU + INNER JOIN + [dbo].[OrganizationUser] OU ON OU.[Id] = CU.[OrganizationUserId] + WHERE + OU.[UserId] = @Id + + -- Delete group users + DELETE + GU + FROM + [dbo].[GroupUser] GU + INNER JOIN + [dbo].[OrganizationUser] OU ON OU.[Id] = GU.[OrganizationUserId] + WHERE + OU.[UserId] = @Id + + -- Delete organization users + DELETE + FROM + [dbo].[OrganizationUser] + WHERE + [UserId] = @Id + + -- Delete U2F logins + DELETE + FROM + [dbo].[U2f] + WHERE + [UserId] = @Id + + -- Finally, delete the user + DELETE + FROM + [dbo].[User] + WHERE + [Id] = @Id + + COMMIT TRANSACTION User_DeleteById +END +GO + +IF OBJECT_ID('[dbo].[CipherDetails_Create]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[CipherDetails_Create] +END +GO + +CREATE 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 + @OrganizationUseTotp BIT -- not used +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] + ) + 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 + ) + + 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 + +IF OBJECT_ID('[dbo].[CipherDetails_Update]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[CipherDetails_Update] +END +GO + +CREATE 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), -- not used + @CreationDate DATETIME2(7), + @RevisionDate DATETIME2(7), + @FolderId UNIQUEIDENTIFIER, + @Favorite BIT, + @Edit BIT, -- not used + @OrganizationUseTotp BIT -- not used +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, + [CreationDate] = @CreationDate, + [RevisionDate] = @RevisionDate + 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 + +IF OBJECT_ID('[dbo].[Cipher_Create]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[Cipher_Create] +END +GO + +CREATE PROCEDURE [dbo].[Cipher_Create] + @Id UNIQUEIDENTIFIER, + @UserId UNIQUEIDENTIFIER, + @OrganizationId UNIQUEIDENTIFIER, + @Type TINYINT, + @Data NVARCHAR(MAX), + @Favorites NVARCHAR(MAX), + @Folders NVARCHAR(MAX), + @Attachments NVARCHAR(MAX), + @CreationDate DATETIME2(7), + @RevisionDate DATETIME2(7) +AS +BEGIN + SET NOCOUNT ON + + INSERT INTO [dbo].[Cipher] + ( + [Id], + [UserId], + [OrganizationId], + [Type], + [Data], + [Favorites], + [Folders], + [Attachments], + [CreationDate], + [RevisionDate] + ) + VALUES + ( + @Id, + @UserId, + @OrganizationId, + @Type, + @Data, + @Favorites, + @Folders, + @Attachments, + @CreationDate, + @RevisionDate + ) + + 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 + +IF OBJECT_ID('[dbo].[Cipher_DeleteAttachment]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[Cipher_DeleteAttachment] +END +GO + +CREATE PROCEDURE [dbo].[Cipher_DeleteAttachment] + @Id UNIQUEIDENTIFIER, + @AttachmentId VARCHAR(50) +AS +BEGIN + SET NOCOUNT ON + + DECLARE @AttachmentIdKey VARCHAR(50) = CONCAT('"', @AttachmentId, '"') + DECLARE @AttachmentIdPath VARCHAR(50) = CONCAT('$.', @AttachmentIdKey) + + DECLARE @UserId UNIQUEIDENTIFIER + DECLARE @OrganizationId UNIQUEIDENTIFIER + + SELECT + @UserId = [UserId], + @OrganizationId = [OrganizationId] + FROM + [dbo].[Cipher] + WHERE [Id] = @Id + + UPDATE + [dbo].[Cipher] + SET + [Attachments] = JSON_MODIFY([Attachments], @AttachmentIdPath, NULL) + WHERE + [Id] = @Id + + IF @OrganizationId IS NOT NULL + BEGIN + EXEC [dbo].[Organization_UpdateStorage] @OrganizationId + EXEC [dbo].[User_BumpAccountRevisionDateByCipherId] @Id, @OrganizationId + END + ELSE IF @UserId IS NOT NULL + BEGIN + EXEC [dbo].[User_UpdateStorage] @UserId + EXEC [dbo].[User_BumpAccountRevisionDate] @UserId + END +END +GO + +IF OBJECT_ID('[dbo].[Cipher_DeleteById]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[Cipher_DeleteById] +END +GO + +CREATE PROCEDURE [dbo].[Cipher_DeleteById] + @Id UNIQUEIDENTIFIER +WITH RECOMPILE +AS +BEGIN + SET NOCOUNT ON + + DECLARE @UserId UNIQUEIDENTIFIER + DECLARE @OrganizationId UNIQUEIDENTIFIER + DECLARE @Attachments BIT + + SELECT TOP 1 + @UserId = [UserId], + @OrganizationId = [OrganizationId], + @Attachments = CASE WHEN [Attachments] IS NOT NULL THEN 1 ELSE 0 END + FROM + [dbo].[Cipher] + WHERE + [Id] = @Id + + DELETE + FROM + [dbo].[Cipher] + WHERE + [Id] = @Id + + IF @OrganizationId IS NOT NULL + BEGIN + IF @Attachments = 1 + BEGIN + EXEC [dbo].[Organization_UpdateStorage] @OrganizationId + END + EXEC [dbo].[User_BumpAccountRevisionDateByCipherId] @Id, @OrganizationId + END + ELSE IF @UserId IS NOT NULL + BEGIN + IF @Attachments = 1 + BEGIN + EXEC [dbo].[User_UpdateStorage] @UserId + END + EXEC [dbo].[User_BumpAccountRevisionDate] @UserId + END +END +GO + +IF OBJECT_ID('[dbo].[Cipher_Move]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[Cipher_Move] +END +GO + +CREATE PROCEDURE [dbo].[Cipher_Move] + @Ids AS [dbo].[GuidIdArray] READONLY, + @FolderId AS UNIQUEIDENTIFIER, + @UserId AS UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + DECLARE @UserIdKey VARCHAR(50) = CONCAT('"', @UserId, '"') + DECLARE @UserIdPath VARCHAR(50) = CONCAT('$.', @UserIdKey) + + ;WITH [IdsToMoveCTE] AS ( + SELECT + [Id] + FROM + [dbo].[UserCipherDetails](@UserId) + WHERE + [Edit] = 1 + AND [Id] IN (SELECT * FROM @Ids) + ) + UPDATE + [dbo].[Cipher] + SET + [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 + WHERE + [Id] IN (SELECT * FROM [IdsToMoveCTE]) + + EXEC [dbo].[User_BumpAccountRevisionDate] @UserId +END +GO + +IF OBJECT_ID('[dbo].[Cipher_Update]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[Cipher_Update] +END +GO + +CREATE PROCEDURE [dbo].[Cipher_Update] + @Id UNIQUEIDENTIFIER, + @UserId UNIQUEIDENTIFIER, + @OrganizationId UNIQUEIDENTIFIER, + @Type TINYINT, + @Data NVARCHAR(MAX), + @Favorites NVARCHAR(MAX), + @Folders NVARCHAR(MAX), + @Attachments NVARCHAR(MAX), + @CreationDate DATETIME2(7), + @RevisionDate DATETIME2(7) +AS +BEGIN + SET NOCOUNT ON + + UPDATE + [dbo].[Cipher] + SET + [UserId] = @UserId, + [OrganizationId] = @OrganizationId, + [Type] = @Type, + [Data] = @Data, + [Favorites] = @Favorites, + [Folders] = @Folders, + [Attachments] = @Attachments, + [CreationDate] = @CreationDate, + [RevisionDate] = @RevisionDate + 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 + +IF OBJECT_ID('[dbo].[Cipher_UpdateAttachment]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[Cipher_UpdateAttachment] +END +GO + +CREATE PROCEDURE [dbo].[Cipher_UpdateAttachment] + @Id UNIQUEIDENTIFIER, + @UserId UNIQUEIDENTIFIER, + @OrganizationId UNIQUEIDENTIFIER, + @AttachmentId VARCHAR(50), + @AttachmentData NVARCHAR(MAX) +AS +BEGIN + SET NOCOUNT ON + + DECLARE @AttachmentIdKey VARCHAR(50) = CONCAT('"', @AttachmentId, '"') + DECLARE @AttachmentIdPath VARCHAR(50) = CONCAT('$.', @AttachmentIdKey) + + UPDATE + [dbo].[Cipher] + SET + [Attachments] = + CASE + WHEN [Attachments] IS NULL THEN + CONCAT('{', @AttachmentIdKey, ':', @AttachmentData, '}') + ELSE + JSON_MODIFY([Attachments], @AttachmentIdPath, JSON_QUERY(@AttachmentData, '$')) + END + WHERE + [Id] = @Id + + IF @OrganizationId IS NOT NULL + BEGIN + EXEC [dbo].[Organization_UpdateStorage] @OrganizationId + EXEC [dbo].[User_BumpAccountRevisionDateByCipherId] @Id, @OrganizationId + END + ELSE IF @UserId IS NOT NULL + BEGIN + EXEC [dbo].[User_UpdateStorage] @UserId + EXEC [dbo].[User_BumpAccountRevisionDate] @UserId + END +END +GO + +IF OBJECT_ID('[dbo].[Cipher_UpdateWithCollections]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[Cipher_UpdateWithCollections] +END +GO + +CREATE PROCEDURE [dbo].[Cipher_UpdateWithCollections] + @Id UNIQUEIDENTIFIER, + @UserId UNIQUEIDENTIFIER, + @OrganizationId UNIQUEIDENTIFIER, + @Type TINYINT, + @Data NVARCHAR(MAX), + @Favorites NVARCHAR(MAX), + @Folders NVARCHAR(MAX), + @Attachments NVARCHAR(MAX), + @CreationDate DATETIME2(7), + @RevisionDate DATETIME2(7), + @CollectionIds AS [dbo].[GuidIdArray] READONLY +AS +BEGIN + SET NOCOUNT ON + + CREATE TABLE #AvailableCollections ( + [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.[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 (SELECT COUNT(1) FROM #AvailableCollections) < 1 + BEGIN + -- No writable collections available to share with in this organization. + SELECT -1 -- -1 = Failure + RETURN + END + + UPDATE + [dbo].[Cipher] + SET + [UserId] = NULL, + [OrganizationId] = @OrganizationId, + [Data] = @Data, + [Attachments] = @Attachments, + [RevisionDate] = @RevisionDate + -- No need to update CreationDate, Favorites, Folders, or Type since that data will not change + WHERE + [Id] = @Id + + INSERT INTO [dbo].[CollectionCipher] + ( + [CollectionId], + [CipherId] + ) + SELECT + [Id], + @Id + FROM + @CollectionIds + WHERE + [Id] IN (SELECT [Id] FROM #AvailableCollections) + + IF @Attachments IS NOT NULL + BEGIN + EXEC [dbo].[Organization_UpdateStorage] @OrganizationId + EXEC [dbo].[User_UpdateStorage] @UserId + END + + EXEC [dbo].[User_BumpAccountRevisionDateByCipherId] @Id, @OrganizationId + + SELECT 0 -- 0 = Success +END +GO + +IF OBJECT_ID('[dbo].[CollectionCipher_Create]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[CollectionCipher_Create] +END +GO + +CREATE PROCEDURE [dbo].[CollectionCipher_Create] + @CollectionId UNIQUEIDENTIFIER, + @CipherId UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + INSERT INTO [dbo].[CollectionCipher] + ( + [CollectionId], + [CipherId] + ) + VALUES + ( + @CollectionId, + @CipherId + ) + + DECLARE @OrganizationId UNIQUEIDENTIFIER = (SELECT TOP 1 [OrganizationId] FROM [dbo].[Cipher] WHERE [Id] = @CipherId) + IF @OrganizationId IS NOT NULL + BEGIN + EXEC [dbo].[User_BumpAccountRevisionDateByCollectionId] @CollectionId, @OrganizationId + END +END +GO + +IF OBJECT_ID('[dbo].[CollectionCipher_Delete]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[CollectionCipher_Delete] +END +GO + +CREATE PROCEDURE [dbo].[CollectionCipher_Delete] + @CollectionId UNIQUEIDENTIFIER, + @CipherId UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + DELETE + FROM + [dbo].[CollectionCipher] + WHERE + [CollectionId] = @CollectionId + AND [CipherId] = @CipherId + + DECLARE @OrganizationId UNIQUEIDENTIFIER = (SELECT TOP 1 [OrganizationId] FROM [dbo].[Cipher] WHERE [Id] = @CipherId) + IF @OrganizationId IS NOT NULL + BEGIN + EXEC [dbo].[User_BumpAccountRevisionDateByCollectionId] @CollectionId, @OrganizationId + END +END +GO + +IF OBJECT_ID('[dbo].[Collection_Create]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[Collection_Create] +END +GO + +CREATE PROCEDURE [dbo].[Collection_Create] + @Id UNIQUEIDENTIFIER, + @OrganizationId UNIQUEIDENTIFIER, + @Name VARCHAR(MAX), + @CreationDate DATETIME2(7), + @RevisionDate DATETIME2(7) +AS +BEGIN + SET NOCOUNT ON + + INSERT INTO [dbo].[Collection] + ( + [Id], + [OrganizationId], + [Name], + [CreationDate], + [RevisionDate] + ) + VALUES + ( + @Id, + @OrganizationId, + @Name, + @CreationDate, + @RevisionDate + ) + + EXEC [dbo].[User_BumpAccountRevisionDateByCollectionId] @Id, @OrganizationId +END +GO + +IF OBJECT_ID('[dbo].[Collection_CreateWithGroups]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[Collection_CreateWithGroups] +END +GO + +CREATE PROCEDURE [dbo].[Collection_CreateWithGroups] + @Id UNIQUEIDENTIFIER, + @OrganizationId UNIQUEIDENTIFIER, + @Name VARCHAR(MAX), + @CreationDate DATETIME2(7), + @RevisionDate DATETIME2(7), + @Groups AS [dbo].[SelectionReadOnlyArray] READONLY +AS +BEGIN + SET NOCOUNT ON + + EXEC [dbo].[Collection_Create] @Id, @OrganizationId, @Name, @CreationDate, @RevisionDate + + ;WITH [AvailableGroupsCTE] AS( + SELECT + [Id] + FROM + [dbo].[Group] + WHERE + [OrganizationId] = @OrganizationId + ) + INSERT INTO [dbo].[CollectionGroup] + ( + [CollectionId], + [GroupId], + [ReadOnly] + ) + SELECT + @Id, + [Id], + [ReadOnly] + FROM + @Groups + WHERE + [Id] IN (SELECT [Id] FROM [AvailableGroupsCTE]) + + EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId +END +GO + +IF OBJECT_ID('[dbo].[Collection_DeleteById]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[Collection_DeleteById] +END +GO + +CREATE PROCEDURE [dbo].[Collection_DeleteById] + @Id UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + DECLARE @OrganizationId UNIQUEIDENTIFIER = (SELECT TOP 1 [OrganizationId] FROM [dbo].[Collection] WHERE [Id] = @Id) + IF @OrganizationId IS NOT NULL + BEGIN + EXEC [dbo].[User_BumpAccountRevisionDateByCollectionId] @Id, @OrganizationId + END + + DELETE + FROM + [dbo].[CollectionGroup] + WHERE + [CollectionId] = @Id + + DELETE + FROM + [dbo].[Collection] + WHERE + [Id] = @Id +END +GO + +IF OBJECT_ID('[dbo].[Collection_Update]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[Collection_Update] +END +GO + +CREATE PROCEDURE [dbo].[Collection_Update] + @Id UNIQUEIDENTIFIER, + @OrganizationId UNIQUEIDENTIFIER, + @Name VARCHAR(MAX), + @CreationDate DATETIME2(7), + @RevisionDate DATETIME2(7) +AS +BEGIN + SET NOCOUNT ON + + UPDATE + [dbo].[Collection] + SET + [OrganizationId] = @OrganizationId, + [Name] = @Name, + [CreationDate] = @CreationDate, + [RevisionDate] = @RevisionDate + WHERE + [Id] = @Id + + EXEC [dbo].[User_BumpAccountRevisionDateByCollectionId] @Id, @OrganizationId +END +GO + +IF OBJECT_ID('[dbo].[Collection_UpdateWithGroups]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[Collection_UpdateWithGroups] +END +GO + +CREATE PROCEDURE [dbo].[Collection_UpdateWithGroups] + @Id UNIQUEIDENTIFIER, + @OrganizationId UNIQUEIDENTIFIER, + @Name VARCHAR(MAX), + @CreationDate DATETIME2(7), + @RevisionDate DATETIME2(7), + @Groups AS [dbo].[SelectionReadOnlyArray] READONLY +AS +BEGIN + SET NOCOUNT ON + + EXEC [dbo].[Collection_Update] @Id, @OrganizationId, @Name, @CreationDate, @RevisionDate + + ;WITH [AvailableGroupsCTE] AS( + SELECT + Id + FROM + [dbo].[Group] + WHERE + OrganizationId = @OrganizationId + ) + MERGE + [dbo].[CollectionGroup] AS [Target] + USING + @Groups AS [Source] + ON + [Target].[CollectionId] = @Id + AND [Target].[GroupId] = [Source].[Id] + WHEN NOT MATCHED BY TARGET + AND [Source].[Id] IN (SELECT [Id] FROM [AvailableGroupsCTE]) THEN + INSERT VALUES + ( + @Id, + [Source].[Id], + [Source].[ReadOnly] + ) + WHEN MATCHED AND [Target].[ReadOnly] != [Source].[ReadOnly] THEN + UPDATE SET [Target].[ReadOnly] = [Source].[ReadOnly] + WHEN NOT MATCHED BY SOURCE + AND [Target].[CollectionId] = @Id THEN + DELETE + ; + + EXEC [dbo].[User_BumpAccountRevisionDateByCollectionId] @Id, @OrganizationId +END +GO + +IF OBJECT_ID('[dbo].[GroupUser_UpdateUsers]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[GroupUser_UpdateUsers] +END +GO + +CREATE PROCEDURE [dbo].[GroupUser_UpdateUsers] + @GroupId UNIQUEIDENTIFIER, + @OrganizationUserIds AS [dbo].[GuidIdArray] READONLY +AS +BEGIN + SET NOCOUNT ON + + DECLARE @OrgId UNIQUEIDENTIFIER = ( + SELECT TOP 1 + [OrganizationId] + FROM + [dbo].[Group] + WHERE + [Id] = @GroupId + ) + + ;WITH [AvailableUsersCTE] AS( + SELECT + [Id] + FROM + [dbo].[OrganizationUser] + WHERE + [OrganizationId] = @OrgId + ) + MERGE + [dbo].[GroupUser] AS [Target] + USING + @OrganizationUserIds AS [Source] + ON + [Target].[GroupId] = @GroupId + AND [Target].[OrganizationUserId] = [Source].[Id] + WHEN NOT MATCHED BY TARGET + AND [Source].[Id] IN (SELECT [Id] FROM [AvailableUsersCTE]) THEN + INSERT VALUES + ( + @GroupId, + [Source].[Id] + ) + WHEN NOT MATCHED BY SOURCE + AND [Target].[GroupId] = @GroupId + AND [Target].[OrganizationUserId] IN (SELECT [Id] FROM [AvailableUsersCTE]) THEN + DELETE + ; + + EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrgId +END +GO + +IF OBJECT_ID('[dbo].[Group_CreateWithCollections]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[Group_CreateWithCollections] +END +GO + +CREATE PROCEDURE [dbo].[Group_CreateWithCollections] + @Id UNIQUEIDENTIFIER, + @OrganizationId UNIQUEIDENTIFIER, + @Name VARCHAR(MAX), + @AccessAll BIT, + @ExternalId NVARCHAR(300), + @CreationDate DATETIME2(7), + @RevisionDate DATETIME2(7), + @Collections AS [dbo].[SelectionReadOnlyArray] READONLY +AS +BEGIN + SET NOCOUNT ON + + EXEC [dbo].[Group_Create] @Id, @OrganizationId, @Name, @AccessAll, @ExternalId, @CreationDate, @RevisionDate + + ;WITH [AvailableCollectionsCTE] AS( + SELECT + [Id] + FROM + [dbo].[Collection] + WHERE + [OrganizationId] = @OrganizationId + ) + INSERT INTO [dbo].[CollectionGroup] + ( + [CollectionId], + [GroupId], + [ReadOnly] + ) + SELECT + [Id], + @Id, + [ReadOnly] + FROM + @Collections + WHERE + [Id] IN (SELECT [Id] FROM [AvailableCollectionsCTE]) + + EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId +END +GO + +IF OBJECT_ID('[dbo].[Group_DeleteById]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[Group_DeleteById] +END +GO + +CREATE PROCEDURE [dbo].[Group_DeleteById] + @Id UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + DECLARE @OrganizationId UNIQUEIDENTIFIER = (SELECT TOP 1 [OrganizationId] FROM [dbo].[Group] WHERE [Id] = @Id) + IF @OrganizationId IS NOT NULL + BEGIN + EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId + END + + DELETE + FROM + [dbo].[Group] + WHERE + [Id] = @Id +END +GO + +IF OBJECT_ID('[dbo].[Group_UpdateWithCollections]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[Group_UpdateWithCollections] +END +GO + +CREATE PROCEDURE [dbo].[Group_UpdateWithCollections] + @Id UNIQUEIDENTIFIER, + @OrganizationId UNIQUEIDENTIFIER, + @Name VARCHAR(MAX), + @AccessAll BIT, + @ExternalId NVARCHAR(300), + @CreationDate DATETIME2(7), + @RevisionDate DATETIME2(7), + @Collections AS [dbo].[SelectionReadOnlyArray] READONLY +AS +BEGIN + SET NOCOUNT ON + + EXEC [dbo].[Group_Update] @Id, @OrganizationId, @Name, @AccessAll, @ExternalId, @CreationDate, @RevisionDate + + ;WITH [AvailableCollectionsCTE] AS( + SELECT + Id + FROM + [dbo].[Collection] + WHERE + OrganizationId = @OrganizationId + ) + MERGE + [dbo].[CollectionGroup] AS [Target] + USING + @Collections AS [Source] + ON + [Target].[CollectionId] = [Source].[Id] + AND [Target].[GroupId] = @Id + WHEN NOT MATCHED BY TARGET + AND [Source].[Id] IN (SELECT [Id] FROM [AvailableCollectionsCTE]) THEN + INSERT VALUES + ( + [Source].[Id], + @Id, + [Source].[ReadOnly] + ) + WHEN MATCHED AND [Target].[ReadOnly] != [Source].[ReadOnly] THEN + UPDATE SET [Target].[ReadOnly] = [Source].[ReadOnly] + WHEN NOT MATCHED BY SOURCE + AND [Target].[GroupId] = @Id THEN + DELETE + ; + + EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId +END +GO + +IF OBJECT_ID('[dbo].[OrganizationUser_DeleteById]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[OrganizationUser_DeleteById] +END +GO + +CREATE PROCEDURE [dbo].[OrganizationUser_DeleteById] + @Id UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationUserId] @Id + + DELETE + FROM + [dbo].[CollectionUser] + WHERE + [OrganizationUserId] = @Id + + DELETE + FROM + [dbo].[GroupUser] + WHERE + [OrganizationUserId] = @Id + + DELETE + FROM + [dbo].[OrganizationUser] + WHERE + [Id] = @Id +END +GO + +IF OBJECT_ID('[dbo].[User_BumpAccountRevisionDateByCipherId]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[User_BumpAccountRevisionDateByCipherId] +END +GO + +CREATE PROCEDURE [dbo].[User_BumpAccountRevisionDateByCipherId] + @CipherId UNIQUEIDENTIFIER, + @OrganizationId UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + UPDATE + U + SET + U.[AccountRevisionDate] = GETUTCDATE() + FROM + [dbo].[User] U + LEFT JOIN + [dbo].[OrganizationUser] OU ON OU.[UserId] = U.[Id] + LEFT JOIN + [dbo].[CollectionCipher] CC ON CC.[CipherId] = @CipherId + LEFT JOIN + [dbo].[CollectionUser] CU ON OU.[AccessAll] = 0 AND CU.[OrganizationUserId] = OU.[Id] AND CU.[CollectionId] = CC.[CollectionId] + 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] AND CG.[CollectionId] = CC.[CollectionId] + WHERE + OU.[Status] = 2 -- 2 = Confirmed + AND ( + CU.[CollectionId] IS NOT NULL + OR CG.[CollectionId] IS NOT NULL + OR ( + OU.[OrganizationId] = @OrganizationId + AND ( + OU.[AccessAll] = 1 + OR G.[AccessAll] = 1 + ) + ) + ) +END +GO + +IF OBJECT_ID('[dbo].[User_BumpAccountRevisionDateByCollectionId]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[User_BumpAccountRevisionDateByCollectionId] +END +GO + +CREATE PROCEDURE [dbo].[User_BumpAccountRevisionDateByCollectionId] + @CollectionId UNIQUEIDENTIFIER, + @OrganizationId UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + UPDATE + U + SET + U.[AccountRevisionDate] = GETUTCDATE() + FROM + [dbo].[User] U + LEFT JOIN + [dbo].[OrganizationUser] OU ON OU.[UserId] = U.[Id] + LEFT JOIN + [dbo].[CollectionUser] CU ON OU.[AccessAll] = 0 AND CU.[OrganizationUserId] = OU.[Id] AND CU.[CollectionId] = @CollectionId + 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] AND CG.[CollectionId] = @CollectionId + WHERE + OU.[Status] = 2 -- 2 = Confirmed + AND ( + CU.[CollectionId] IS NOT NULL + OR CG.[CollectionId] IS NOT NULL + OR ( + OU.[OrganizationId] = @OrganizationId + AND ( + OU.[AccessAll] = 1 + OR G.[AccessAll] = 1 + ) + ) + ) +END +GO diff --git a/util/Setup/Setup.csproj b/util/Setup/Setup.csproj index 0bad8f259b..bd14b4f476 100644 --- a/util/Setup/Setup.csproj +++ b/util/Setup/Setup.csproj @@ -8,6 +8,7 @@ +