From ce7d727a9cb8bcb25f51465b6c507ad358dcb889 Mon Sep 17 00:00:00 2001 From: Thomas Rittson Date: Sat, 27 Dec 2025 12:54:06 +1000 Subject: [PATCH] Move new sproc to separate PR --- ...maticallyConfirmOrganizationUserCommand.cs | 20 +++- .../ConfirmOrganizationUserCommand.cs | 21 +++- .../Repositories/ICollectionRepository.cs | 10 -- .../Repositories/CollectionRepository.cs | 24 ---- .../Repositories/CollectionRepository.cs | 68 ----------- .../Collection_UpsertDefaultCollection.sql | 87 -------------- .../AutomaticallyConfirmUsersCommandTests.cs | 28 +++-- .../ConfirmOrganizationUserCommandTests.cs | 15 ++- .../UpsertDefaultCollectionTests.cs | 110 ------------------ ..._01_Collection_UpsertDefaultCollection.sql | 89 -------------- ...nizationUser_MigrateDefaultCollection.sql} | 0 11 files changed, 60 insertions(+), 412 deletions(-) delete mode 100644 src/Sql/dbo/Stored Procedures/Collection_UpsertDefaultCollection.sql delete mode 100644 test/Infrastructure.IntegrationTest/AdminConsole/Repositories/CollectionRepository/UpsertDefaultCollectionTests.cs delete mode 100644 util/Migrator/DbScripts/2025-12-20_01_Collection_UpsertDefaultCollection.sql rename util/Migrator/DbScripts/{2025-12-20_02_OrganizationUser_MigrateDefaultCollection.sql => 2025-12-20_01_OrganizationUser_MigrateDefaultCollection.sql} (100%) diff --git a/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/AutoConfirmUser/AutomaticallyConfirmOrganizationUserCommand.cs b/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/AutoConfirmUser/AutomaticallyConfirmOrganizationUserCommand.cs index d8a3d763b4..4e347d36a0 100644 --- a/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/AutoConfirmUser/AutomaticallyConfirmOrganizationUserCommand.cs +++ b/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/AutoConfirmUser/AutomaticallyConfirmOrganizationUserCommand.cs @@ -2,7 +2,9 @@ using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces; using Bit.Core.AdminConsole.OrganizationFeatures.Policies; using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements; +using Bit.Core.Entities; using Bit.Core.Enums; +using Bit.Core.Models.Data; using Bit.Core.Platform.Push; using Bit.Core.Repositories; using Bit.Core.Services; @@ -77,10 +79,20 @@ public class AutomaticallyConfirmOrganizationUserCommand(IOrganizationUserReposi return; } - await collectionRepository.UpsertDefaultCollectionAsync( - request.Organization!.Id, - request.OrganizationUser!.Id, - request.DefaultUserCollectionName); + await collectionRepository.CreateAsync( + new Collection + { + OrganizationId = request.Organization!.Id, + Name = request.DefaultUserCollectionName, + Type = CollectionType.DefaultUserCollection, + DefaultCollectionOwnerId = request.OrganizationUserId + }, + groups: null, + [new CollectionAccessSelection + { + Id = request.OrganizationUser!.Id, + Manage = true + }]); } catch (Exception ex) { diff --git a/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/ConfirmOrganizationUserCommand.cs b/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/ConfirmOrganizationUserCommand.cs index 346a1557b7..4123cf3944 100644 --- a/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/ConfirmOrganizationUserCommand.cs +++ b/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/ConfirmOrganizationUserCommand.cs @@ -12,6 +12,7 @@ using Bit.Core.Billing.Enums; using Bit.Core.Entities; using Bit.Core.Enums; using Bit.Core.Exceptions; +using Bit.Core.Models.Data; using Bit.Core.Platform.Push; using Bit.Core.Repositories; using Bit.Core.Services; @@ -296,10 +297,22 @@ public class ConfirmOrganizationUserCommand : IConfirmOrganizationUserCommand return; } - await _collectionRepository.UpsertDefaultCollectionAsync( - organizationUser.OrganizationId, - organizationUser.Id, - defaultUserCollectionName); + var defaultCollection = new Collection + { + OrganizationId = organizationUser.OrganizationId, + Name = defaultUserCollectionName, + Type = CollectionType.DefaultUserCollection, + DefaultCollectionOwnerId = organizationUser.Id + }; + var collectionUser = new CollectionAccessSelection + { + Id = organizationUser.Id, + ReadOnly = false, + HidePasswords = false, + Manage = true + }; + + await _collectionRepository.CreateAsync(defaultCollection, groups: null, users: [collectionUser]); } /// diff --git a/src/Core/Repositories/ICollectionRepository.cs b/src/Core/Repositories/ICollectionRepository.cs index 4e0af70729..f86147ca7d 100644 --- a/src/Core/Repositories/ICollectionRepository.cs +++ b/src/Core/Repositories/ICollectionRepository.cs @@ -71,14 +71,4 @@ public interface ICollectionRepository : IRepository /// The encrypted string to use as the default collection name. /// Task UpsertDefaultCollectionsAsync(Guid organizationId, IEnumerable organizationUserIds, string defaultCollectionName); - - /// - /// Creates a default user collection for the specified organization user if they do not already have one. - /// This operation is idempotent - calling it multiple times will not create duplicate collections. - /// - /// The Organization ID. - /// The Organization User ID to create/find a default collection for. - /// The encrypted string to use as the default collection name. - /// True if a new collection was created; false if the user already had a default collection. - Task UpsertDefaultCollectionAsync(Guid organizationId, Guid organizationUserId, string defaultCollectionName); } diff --git a/src/Infrastructure.Dapper/Repositories/CollectionRepository.cs b/src/Infrastructure.Dapper/Repositories/CollectionRepository.cs index bd5248bd58..6396dd8f62 100644 --- a/src/Infrastructure.Dapper/Repositories/CollectionRepository.cs +++ b/src/Infrastructure.Dapper/Repositories/CollectionRepository.cs @@ -396,30 +396,6 @@ public class CollectionRepository : Repository, ICollectionRep } } - public async Task UpsertDefaultCollectionAsync(Guid organizationId, Guid organizationUserId, string defaultCollectionName) - { - using (var connection = new SqlConnection(ConnectionString)) - { - var collectionId = CoreHelpers.GenerateComb(); - var now = DateTime.UtcNow; - var parameters = new DynamicParameters(); - parameters.Add("@CollectionId", collectionId); - parameters.Add("@OrganizationId", organizationId); - parameters.Add("@OrganizationUserId", organizationUserId); - parameters.Add("@Name", defaultCollectionName); - parameters.Add("@CreationDate", now); - parameters.Add("@RevisionDate", now); - parameters.Add("@WasCreated", dbType: DbType.Boolean, direction: ParameterDirection.Output); - - await connection.ExecuteAsync( - $"[{Schema}].[Collection_UpsertDefaultCollection]", - parameters, - commandType: CommandType.StoredProcedure); - - return parameters.Get("@WasCreated"); - } - } - private async Task> GetOrgUserIdsWithDefaultCollectionAsync(SqlConnection connection, SqlTransaction transaction, Guid organizationId) { const string sql = @" diff --git a/src/Infrastructure.EntityFramework/Repositories/CollectionRepository.cs b/src/Infrastructure.EntityFramework/Repositories/CollectionRepository.cs index e1f0464259..b4c1a8e661 100644 --- a/src/Infrastructure.EntityFramework/Repositories/CollectionRepository.cs +++ b/src/Infrastructure.EntityFramework/Repositories/CollectionRepository.cs @@ -821,74 +821,6 @@ public class CollectionRepository : Repository UpsertDefaultCollectionAsync(Guid organizationId, Guid organizationUserId, string defaultCollectionName) - { - using var scope = ServiceScopeFactory.CreateScope(); - var dbContext = GetDatabaseContext(scope); - - try - { - // Create new default collection - var collectionId = CoreHelpers.GenerateComb(); - var now = DateTime.UtcNow; - - var collection = new Collection - { - Id = collectionId, - OrganizationId = organizationId, - Name = defaultCollectionName, - ExternalId = null, - CreationDate = now, - RevisionDate = now, - Type = CollectionType.DefaultUserCollection, - DefaultUserCollectionEmail = null, - DefaultCollectionOwnerId = organizationUserId - }; - - var collectionUser = new CollectionUser - { - CollectionId = collectionId, - OrganizationUserId = organizationUserId, - ReadOnly = false, - HidePasswords = false, - Manage = true - }; - - await dbContext.Collections.AddAsync(collection); - await dbContext.CollectionUsers.AddAsync(collectionUser); - await dbContext.SaveChangesAsync(); - - // Bump user account revision dates - await dbContext.UserBumpAccountRevisionDateByCollectionIdAsync(collectionId, organizationId); - await dbContext.SaveChangesAsync(); - - return true; - } - catch (DbUpdateException ex) when (IsUniqueConstraintViolation(ex)) - { - // Collection already exists, return false - return false; - } - } - - private static bool IsUniqueConstraintViolation(DbUpdateException ex) - { - switch (ex.InnerException) - { - // Check if the inner exception is a SQL Server unique constraint violation (error 2601 or 2627) - case Microsoft.Data.SqlClient.SqlException { Number: 2601 or 2627 }: - // Check if the inner exception is a PostgreSQL unique constraint violation (SQLSTATE 23505) - case Npgsql.PostgresException { SqlState: "23505" }: - // Check if the inner exception is a SQLite unique constraint violation (SQLITE_CONSTRAINT = 19) - case Microsoft.Data.Sqlite.SqliteException { SqliteErrorCode: 19 }: - // Check if the inner exception is a MySQL unique constraint violation (ER_DUP_ENTRY = 1062) - case MySqlConnector.MySqlException { ErrorCode: MySqlConnector.MySqlErrorCode.DuplicateKeyEntry }: - return true; - default: - return false; - } - } - private async Task> GetOrgUserIdsWithDefaultCollectionAsync(DatabaseContext dbContext, Guid organizationId) { var results = await dbContext.OrganizationUsers diff --git a/src/Sql/dbo/Stored Procedures/Collection_UpsertDefaultCollection.sql b/src/Sql/dbo/Stored Procedures/Collection_UpsertDefaultCollection.sql deleted file mode 100644 index 14da7c32a9..0000000000 --- a/src/Sql/dbo/Stored Procedures/Collection_UpsertDefaultCollection.sql +++ /dev/null @@ -1,87 +0,0 @@ --- This procedure prevents duplicate "My Items" collections for users using --- a filtered unique constraint on (DefaultCollectionOwnerId, OrganizationId, Type) WHERE Type = 1. - -CREATE PROCEDURE [dbo].[Collection_UpsertDefaultCollection] - @CollectionId UNIQUEIDENTIFIER, - @OrganizationId UNIQUEIDENTIFIER, - @OrganizationUserId UNIQUEIDENTIFIER, - @Name VARCHAR(MAX), - @CreationDate DATETIME2(7), - @RevisionDate DATETIME2(7), - @WasCreated BIT OUTPUT -AS -BEGIN - SET NOCOUNT ON - - BEGIN TRANSACTION - - BEGIN TRY - SET @WasCreated = 1 - - -- Insert Collection with DefaultCollectionOwnerId populated for constraint enforcement - INSERT INTO [dbo].[Collection] - ( - [Id], - [OrganizationId], - [Name], - [ExternalId], - [CreationDate], - [RevisionDate], - [DefaultUserCollectionEmail], - [Type], - [DefaultCollectionOwnerId] - ) - VALUES - ( - @CollectionId, - @OrganizationId, - @Name, - NULL, -- ExternalId - @CreationDate, - @RevisionDate, - NULL, -- DefaultUserCollectionEmail - 1, -- CollectionType.DefaultUserCollection - @OrganizationUserId - ) - - -- Insert CollectionUser - INSERT INTO [dbo].[CollectionUser] - ( - [CollectionId], - [OrganizationUserId], - [ReadOnly], - [HidePasswords], - [Manage] - ) - VALUES - ( - @CollectionId, - @OrganizationUserId, - 0, -- ReadOnly = false - 0, -- HidePasswords = false - 1 -- Manage = true - ) - - -- Bump user account revision dates - EXEC [dbo].[User_BumpAccountRevisionDateByCollectionId] @CollectionId, @OrganizationId - - COMMIT TRANSACTION - END TRY - BEGIN CATCH - -- Check if error is unique constraint violation (error 2601 or 2627) - IF ERROR_NUMBER() IN (2601, 2627) - BEGIN - -- Collection already exists, return gracefully - SET @WasCreated = 0 - IF @@TRANCOUNT > 0 - ROLLBACK TRANSACTION - END - ELSE - BEGIN - -- Unexpected error, rollback and re-throw - IF @@TRANCOUNT > 0 - ROLLBACK TRANSACTION - THROW - END - END CATCH -END diff --git a/test/Core.Test/AdminConsole/OrganizationFeatures/OrganizationUsers/AutoConfirmUsers/AutomaticallyConfirmUsersCommandTests.cs b/test/Core.Test/AdminConsole/OrganizationFeatures/OrganizationUsers/AutoConfirmUsers/AutomaticallyConfirmUsersCommandTests.cs index f1b3dc6ec1..bee45f5e20 100644 --- a/test/Core.Test/AdminConsole/OrganizationFeatures/OrganizationUsers/AutoConfirmUsers/AutomaticallyConfirmUsersCommandTests.cs +++ b/test/Core.Test/AdminConsole/OrganizationFeatures/OrganizationUsers/AutoConfirmUsers/AutomaticallyConfirmUsersCommandTests.cs @@ -9,6 +9,7 @@ using Bit.Core.AdminConsole.Utilities.v2; using Bit.Core.AdminConsole.Utilities.v2.Validation; using Bit.Core.Entities; using Bit.Core.Enums; +using Bit.Core.Models.Data; using Bit.Core.Platform.Push; using Bit.Core.Repositories; using Bit.Core.Services; @@ -202,10 +203,15 @@ public class AutomaticallyConfirmUsersCommandTests await sutProvider.GetDependency() .Received(1) - .UpsertDefaultCollectionAsync( - organization.Id, - organizationUser.Id, - defaultCollectionName); + .CreateAsync( + Arg.Is(c => + c.OrganizationId == organization.Id && + c.Name == defaultCollectionName && + c.Type == CollectionType.DefaultUserCollection && + c.DefaultCollectionOwnerId == request.OrganizationUserId), + Arg.Is>(groups => groups == null), + Arg.Is>(access => + access.FirstOrDefault(x => x.Id == organizationUser.Id && x.Manage) != null)); } [Theory] @@ -247,10 +253,9 @@ public class AutomaticallyConfirmUsersCommandTests await sutProvider.GetDependency() .DidNotReceive() - .UpsertDefaultCollectionAsync( - Arg.Any(), - Arg.Any(), - Arg.Any()); + .CreateAsync(Arg.Any(), + Arg.Any>(), + Arg.Any>()); } [Theory] @@ -286,10 +291,9 @@ public class AutomaticallyConfirmUsersCommandTests var collectionException = new Exception("Collection creation failed"); sutProvider.GetDependency() - .UpsertDefaultCollectionAsync( - Arg.Any(), - Arg.Any(), - Arg.Any()) + .CreateAsync(Arg.Any(), + Arg.Any>(), + Arg.Any>()) .ThrowsAsync(collectionException); // Act diff --git a/test/Core.Test/AdminConsole/OrganizationFeatures/OrganizationUsers/ConfirmOrganizationUserCommandTests.cs b/test/Core.Test/AdminConsole/OrganizationFeatures/OrganizationUsers/ConfirmOrganizationUserCommandTests.cs index 10643640e3..d94c08530c 100644 --- a/test/Core.Test/AdminConsole/OrganizationFeatures/OrganizationUsers/ConfirmOrganizationUserCommandTests.cs +++ b/test/Core.Test/AdminConsole/OrganizationFeatures/OrganizationUsers/ConfirmOrganizationUserCommandTests.cs @@ -12,6 +12,7 @@ using Bit.Core.Billing.Enums; using Bit.Core.Entities; using Bit.Core.Enums; using Bit.Core.Exceptions; +using Bit.Core.Models.Data; using Bit.Core.Models.Data.Organizations.OrganizationUsers; using Bit.Core.Platform.Push; using Bit.Core.Repositories; @@ -493,10 +494,16 @@ public class ConfirmOrganizationUserCommandTests await sutProvider.GetDependency() .Received(1) - .UpsertDefaultCollectionAsync( - organization.Id, - orgUser.Id, - collectionName); + .CreateAsync( + Arg.Is(c => + c.Name == collectionName && + c.OrganizationId == organization.Id && + c.Type == CollectionType.DefaultUserCollection && + c.DefaultCollectionOwnerId == orgUser.Id), + Arg.Any>(), + Arg.Is>(cu => + cu.Single().Id == orgUser.Id && + cu.Single().Manage)); } [Theory, BitAutoData] diff --git a/test/Infrastructure.IntegrationTest/AdminConsole/Repositories/CollectionRepository/UpsertDefaultCollectionTests.cs b/test/Infrastructure.IntegrationTest/AdminConsole/Repositories/CollectionRepository/UpsertDefaultCollectionTests.cs deleted file mode 100644 index 17dc36d153..0000000000 --- a/test/Infrastructure.IntegrationTest/AdminConsole/Repositories/CollectionRepository/UpsertDefaultCollectionTests.cs +++ /dev/null @@ -1,110 +0,0 @@ -using Bit.Core.Enums; -using Bit.Core.Repositories; -using Xunit; - -namespace Bit.Infrastructure.IntegrationTest.AdminConsole.Repositories.CollectionRepository; - -public class UpsertDefaultCollectionTests -{ - [Theory, DatabaseData] - public async Task UpsertDefaultCollectionAsync_ShouldCreateCollection_WhenUserDoesNotHaveDefaultCollection( - IOrganizationRepository organizationRepository, - IUserRepository userRepository, - IOrganizationUserRepository organizationUserRepository, - ICollectionRepository collectionRepository) - { - // Arrange - var organization = await organizationRepository.CreateTestOrganizationAsync(); - var user = await userRepository.CreateTestUserAsync(); - var orgUser = await organizationUserRepository.CreateTestOrganizationUserAsync(organization, user); - var defaultCollectionName = $"My Items - {organization.Id}"; - - // Act - var wasCreated = await collectionRepository.UpsertDefaultCollectionAsync( - organization.Id, - orgUser.Id, - defaultCollectionName); - - // Assert - Assert.True(wasCreated); - - var collectionDetails = await collectionRepository.GetManyByUserIdAsync(user.Id); - var defaultCollection = collectionDetails.SingleOrDefault(c => - c.OrganizationId == organization.Id && - c.Type == CollectionType.DefaultUserCollection); - - Assert.NotNull(defaultCollection); - Assert.Equal(defaultCollectionName, defaultCollection.Name); - Assert.True(defaultCollection.Manage); - Assert.False(defaultCollection.ReadOnly); - Assert.False(defaultCollection.HidePasswords); - } - - [Theory, DatabaseData] - public async Task UpsertDefaultCollectionAsync_ShouldReturnFalse_WhenUserAlreadyHasDefaultCollection( - IOrganizationRepository organizationRepository, - IUserRepository userRepository, - IOrganizationUserRepository organizationUserRepository, - ICollectionRepository collectionRepository) - { - // Arrange - var organization = await organizationRepository.CreateTestOrganizationAsync(); - var user = await userRepository.CreateTestUserAsync(); - var orgUser = await organizationUserRepository.CreateTestOrganizationUserAsync(organization, user); - var defaultCollectionName = $"My Items - {organization.Id}"; - - // Create initial collection - var firstWasCreated = await collectionRepository.UpsertDefaultCollectionAsync( - organization.Id, - orgUser.Id, - defaultCollectionName); - - // Act - Call again with same parameters - var secondWasCreated = await collectionRepository.UpsertDefaultCollectionAsync( - organization.Id, - orgUser.Id, - defaultCollectionName); - - // Assert - Assert.True(firstWasCreated); - Assert.False(secondWasCreated); - - // Verify only one default collection exists - var collectionDetails = await collectionRepository.GetManyByUserIdAsync(user.Id); - var defaultCollections = collectionDetails.Where(c => - c.OrganizationId == organization.Id && - c.Type == CollectionType.DefaultUserCollection).ToList(); - - Assert.Single(defaultCollections); - } - - [Theory, DatabaseData] - public async Task UpsertDefaultCollectionAsync_ShouldBeIdempotent_WhenCalledMultipleTimes( - IOrganizationRepository organizationRepository, - IUserRepository userRepository, - IOrganizationUserRepository organizationUserRepository, - ICollectionRepository collectionRepository) - { - // Arrange - var organization = await organizationRepository.CreateTestOrganizationAsync(); - var user = await userRepository.CreateTestUserAsync(); - var orgUser = await organizationUserRepository.CreateTestOrganizationUserAsync(organization, user); - var defaultCollectionName = $"My Items - {organization.Id}"; - - // Act - Call method 5 times - var tasks = Enumerable.Range(1, 5).Select(i => collectionRepository.UpsertDefaultCollectionAsync( - organization.Id, - orgUser.Id, - defaultCollectionName)); - var results = await Task.WhenAll(tasks); - - // Assert - Assert.Single(results, r => r); // First call should create successfully; all other results are implicitly false - - // Verify only one collection exists - var collectionDetails = await collectionRepository.GetManyByUserIdAsync(user.Id); - Assert.Single(collectionDetails, c => - c.OrganizationId == organization.Id && - c.Type == CollectionType.DefaultUserCollection); - } -} diff --git a/util/Migrator/DbScripts/2025-12-20_01_Collection_UpsertDefaultCollection.sql b/util/Migrator/DbScripts/2025-12-20_01_Collection_UpsertDefaultCollection.sql deleted file mode 100644 index 495f89d626..0000000000 --- a/util/Migrator/DbScripts/2025-12-20_01_Collection_UpsertDefaultCollection.sql +++ /dev/null @@ -1,89 +0,0 @@ --- Create the idempotent stored procedure for creating default collections --- This procedure prevents duplicate "My Items" collections for users using --- a filtered unique constraint on (DefaultCollectionOwnerId, OrganizationId, Type) WHERE Type = 1. - -CREATE OR ALTER PROCEDURE [dbo].[Collection_UpsertDefaultCollection] - @CollectionId UNIQUEIDENTIFIER, - @OrganizationId UNIQUEIDENTIFIER, - @OrganizationUserId UNIQUEIDENTIFIER, - @Name VARCHAR(MAX), - @CreationDate DATETIME2(7), - @RevisionDate DATETIME2(7), - @WasCreated BIT OUTPUT -AS -BEGIN - SET NOCOUNT ON - - BEGIN TRANSACTION - - BEGIN TRY - SET @WasCreated = 1 - - -- Insert Collection with DefaultCollectionOwnerId populated for constraint enforcement - INSERT INTO [dbo].[Collection] - ( - [Id], - [OrganizationId], - [Name], - [ExternalId], - [CreationDate], - [RevisionDate], - [DefaultUserCollectionEmail], - [Type], - [DefaultCollectionOwnerId] - ) - VALUES - ( - @CollectionId, - @OrganizationId, - @Name, - NULL, -- ExternalId - @CreationDate, - @RevisionDate, - NULL, -- DefaultUserCollectionEmail - 1, -- CollectionType.DefaultUserCollection - @OrganizationUserId - ) - - -- Insert CollectionUser - INSERT INTO [dbo].[CollectionUser] - ( - [CollectionId], - [OrganizationUserId], - [ReadOnly], - [HidePasswords], - [Manage] - ) - VALUES - ( - @CollectionId, - @OrganizationUserId, - 0, -- ReadOnly = false - 0, -- HidePasswords = false - 1 -- Manage = true - ) - - -- Bump user account revision dates - EXEC [dbo].[User_BumpAccountRevisionDateByCollectionId] @CollectionId, @OrganizationId - - COMMIT TRANSACTION - END TRY - BEGIN CATCH - -- Check if error is unique constraint violation (error 2601 or 2627) - IF ERROR_NUMBER() IN (2601, 2627) - BEGIN - -- Collection already exists, return gracefully - SET @WasCreated = 0 - IF @@TRANCOUNT > 0 - ROLLBACK TRANSACTION - END - ELSE - BEGIN - -- Unexpected error, rollback and re-throw - IF @@TRANCOUNT > 0 - ROLLBACK TRANSACTION - THROW - END - END CATCH -END -GO diff --git a/util/Migrator/DbScripts/2025-12-20_02_OrganizationUser_MigrateDefaultCollection.sql b/util/Migrator/DbScripts/2025-12-20_01_OrganizationUser_MigrateDefaultCollection.sql similarity index 100% rename from util/Migrator/DbScripts/2025-12-20_02_OrganizationUser_MigrateDefaultCollection.sql rename to util/Migrator/DbScripts/2025-12-20_01_OrganizationUser_MigrateDefaultCollection.sql