From 32f19e9f90e729dfa6fcbf54586b3ca61b3c596c Mon Sep 17 00:00:00 2001 From: Chad Scharf <3904944+cscharf@users.noreply.github.com> Date: Thu, 9 Apr 2020 15:25:17 -0400 Subject: [PATCH 1/3] [Soft Delete] - Add not null/is null filters to soft delete and restore sprocs --- .../dbo/Stored Procedures/Cipher_Restore.sql | 3 +- .../Stored Procedures/Cipher_SoftDelete.sql | 1 + .../2020-04-09_00_CipherSoftDelete.sql | 136 ++++++++++++++++++ 3 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 util/Migrator/DbScripts/2020-04-09_00_CipherSoftDelete.sql diff --git a/src/Sql/dbo/Stored Procedures/Cipher_Restore.sql b/src/Sql/dbo/Stored Procedures/Cipher_Restore.sql index ab646b46ce..3d7cf7ff21 100644 --- a/src/Sql/dbo/Stored Procedures/Cipher_Restore.sql +++ b/src/Sql/dbo/Stored Procedures/Cipher_Restore.sql @@ -21,8 +21,9 @@ BEGIN [dbo].[UserCipherDetails](@UserId) WHERE [Edit] = 1 + AND [DeletedDate] IS NOT NULL AND [Id] IN (SELECT * FROM @Ids) - + DECLARE @UtcNow DATETIME2(7) = GETUTCDATE(); UPDATE [dbo].[Cipher] diff --git a/src/Sql/dbo/Stored Procedures/Cipher_SoftDelete.sql b/src/Sql/dbo/Stored Procedures/Cipher_SoftDelete.sql index 9e2b16bd88..0e354f13e5 100644 --- a/src/Sql/dbo/Stored Procedures/Cipher_SoftDelete.sql +++ b/src/Sql/dbo/Stored Procedures/Cipher_SoftDelete.sql @@ -21,6 +21,7 @@ BEGIN [dbo].[UserCipherDetails](@UserId) WHERE [Edit] = 1 + AND [DeletedDate] IS NULL AND [Id] IN (SELECT * FROM @Ids) -- Delete ciphers diff --git a/util/Migrator/DbScripts/2020-04-09_00_CipherSoftDelete.sql b/util/Migrator/DbScripts/2020-04-09_00_CipherSoftDelete.sql new file mode 100644 index 0000000000..debf204678 --- /dev/null +++ b/util/Migrator/DbScripts/2020-04-09_00_CipherSoftDelete.sql @@ -0,0 +1,136 @@ +/** + * Fix bulk Restore/Soft Delete sprocs for DateTime assignment + */ +IF OBJECT_ID('[dbo].[Cipher_Restore]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[Cipher_Restore]; +END +GO +CREATE PROCEDURE [dbo].[Cipher_Restore] + @Ids AS [dbo].[GuidIdArray] READONLY, + @UserId AS UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + CREATE TABLE #Temp + ( + [Id] UNIQUEIDENTIFIER NOT NULL, + [UserId] UNIQUEIDENTIFIER NULL, + [OrganizationId] UNIQUEIDENTIFIER NULL + ) + + INSERT INTO #Temp + SELECT + [Id], + [UserId], + [OrganizationId] + FROM + [dbo].[UserCipherDetails](@UserId) + WHERE + [Edit] = 1 + AND [DeletedDate] IS NOT NULL + AND [Id] IN (SELECT * FROM @Ids) + + DECLARE @UtcNow DATETIME2(7) = GETUTCDATE(); + UPDATE + [dbo].[Cipher] + SET + [DeletedDate] = NULL, + [RevisionDate] = @UtcNow + WHERE + [Id] IN (SELECT [Id] FROM #Temp) + + -- Bump orgs + DECLARE @OrgId UNIQUEIDENTIFIER + DECLARE [OrgCursor] CURSOR FORWARD_ONLY FOR + SELECT + [OrganizationId] + FROM + #Temp + WHERE + [OrganizationId] IS NOT NULL + GROUP BY + [OrganizationId] + OPEN [OrgCursor] + FETCH NEXT FROM [OrgCursor] INTO @OrgId + WHILE @@FETCH_STATUS = 0 BEGIN + EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrgId + FETCH NEXT FROM [OrgCursor] INTO @OrgId + END + CLOSE [OrgCursor] + DEALLOCATE [OrgCursor] + + -- Bump user + EXEC [dbo].[User_BumpAccountRevisionDate] @UserId + + DROP TABLE #Temp +END +GO + +IF OBJECT_ID('[dbo].[Cipher_SoftDelete]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[Cipher_SoftDelete]; +END +GO +CREATE PROCEDURE [dbo].[Cipher_SoftDelete] + @Ids AS [dbo].[GuidIdArray] READONLY, + @UserId AS UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + CREATE TABLE #Temp + ( + [Id] UNIQUEIDENTIFIER NOT NULL, + [UserId] UNIQUEIDENTIFIER NULL, + [OrganizationId] UNIQUEIDENTIFIER NULL + ) + + INSERT INTO #Temp + SELECT + [Id], + [UserId], + [OrganizationId] + FROM + [dbo].[UserCipherDetails](@UserId) + WHERE + [Edit] = 1 + AND [DeletedDate] IS NULL + AND [Id] IN (SELECT * FROM @Ids) + + -- Delete ciphers + DECLARE @UtcNow DATETIME2(7) = GETUTCDATE(); + UPDATE + [dbo].[Cipher] + SET + [DeletedDate] = @UtcNow, + [RevisionDate] = @UtcNow + WHERE + [Id] IN (SELECT [Id] FROM #Temp) + + -- Cleanup orgs + DECLARE @OrgId UNIQUEIDENTIFIER + DECLARE [OrgCursor] CURSOR FORWARD_ONLY FOR + SELECT + [OrganizationId] + FROM + #Temp + WHERE + [OrganizationId] IS NOT NULL + GROUP BY + [OrganizationId] + OPEN [OrgCursor] + FETCH NEXT FROM [OrgCursor] INTO @OrgId + WHILE @@FETCH_STATUS = 0 BEGIN + EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrgId + FETCH NEXT FROM [OrgCursor] INTO @OrgId + END + CLOSE [OrgCursor] + DEALLOCATE [OrgCursor] + + EXEC [dbo].[User_BumpAccountRevisionDate] @UserId + + DROP TABLE #Temp +END +GO \ No newline at end of file From 45e1e1a01bbc849eab3b14b7dd453b8f6640ed76 Mon Sep 17 00:00:00 2001 From: Chad Scharf <3904944+cscharf@users.noreply.github.com> Date: Fri, 10 Apr 2020 10:51:27 -0400 Subject: [PATCH 2/3] [Soft Delete] - cleanup whitespace in Cipher_Restore --- src/Sql/dbo/Stored Procedures/Cipher_Restore.sql | 2 +- util/Migrator/DbScripts/2020-04-02_00_CipherSoftDelete.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Sql/dbo/Stored Procedures/Cipher_Restore.sql b/src/Sql/dbo/Stored Procedures/Cipher_Restore.sql index 3d7cf7ff21..0df591bf57 100644 --- a/src/Sql/dbo/Stored Procedures/Cipher_Restore.sql +++ b/src/Sql/dbo/Stored Procedures/Cipher_Restore.sql @@ -23,7 +23,7 @@ BEGIN [Edit] = 1 AND [DeletedDate] IS NOT NULL AND [Id] IN (SELECT * FROM @Ids) - + DECLARE @UtcNow DATETIME2(7) = GETUTCDATE(); UPDATE [dbo].[Cipher] diff --git a/util/Migrator/DbScripts/2020-04-02_00_CipherSoftDelete.sql b/util/Migrator/DbScripts/2020-04-02_00_CipherSoftDelete.sql index af5c1537f7..e34b20784c 100644 --- a/util/Migrator/DbScripts/2020-04-02_00_CipherSoftDelete.sql +++ b/util/Migrator/DbScripts/2020-04-02_00_CipherSoftDelete.sql @@ -30,7 +30,7 @@ BEGIN WHERE [Edit] = 1 AND [Id] IN (SELECT * FROM @Ids) - + DECLARE @UtcNow DATETIME2(7) = GETUTCDATE(); UPDATE [dbo].[Cipher] From 145dcabba66afc9d108bb479e206c16e82257871 Mon Sep 17 00:00:00 2001 From: Chad Scharf <3904944+cscharf@users.noreply.github.com> Date: Fri, 10 Apr 2020 13:43:51 -0400 Subject: [PATCH 3/3] [Soft Delete] bulk import fails if DeletedDate null --- src/Core/Repositories/SqlServer/CipherRepository.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Core/Repositories/SqlServer/CipherRepository.cs b/src/Core/Repositories/SqlServer/CipherRepository.cs index 781b6efb04..1f9d52d079 100644 --- a/src/Core/Repositories/SqlServer/CipherRepository.cs +++ b/src/Core/Repositories/SqlServer/CipherRepository.cs @@ -629,7 +629,7 @@ namespace Bit.Core.Repositories.SqlServer ciphersTable.Columns.Add(creationDateColumn); var revisionDateColumn = new DataColumn(nameof(c.RevisionDate), c.RevisionDate.GetType()); ciphersTable.Columns.Add(revisionDateColumn); - var deletedDateColumn = new DataColumn(nameof(c.DeletedDate), c.DeletedDate.GetType()); + var deletedDateColumn = new DataColumn(nameof(c.DeletedDate), typeof(DateTime)); ciphersTable.Columns.Add(deletedDateColumn); foreach (DataColumn col in ciphersTable.Columns) @@ -655,7 +655,7 @@ namespace Bit.Core.Repositories.SqlServer row[attachmentsColumn] = cipher.Attachments; row[creationDateColumn] = cipher.CreationDate; row[revisionDateColumn] = cipher.RevisionDate; - row[deletedDateColumn] = cipher.DeletedDate; + row[deletedDateColumn] = cipher.DeletedDate.HasValue ? (object)cipher.DeletedDate : DBNull.Value; ciphersTable.Rows.Add(row); }