From 8ab09a45b280a60305f526884774ef8645feef36 Mon Sep 17 00:00:00 2001 From: Hinton Date: Thu, 8 Jan 2026 14:40:32 +0100 Subject: [PATCH] Extract TestTracking --- .../Repositories/OrganizationRepository.cs | 26 --------------- .../DapperServiceCollectionExtensions.cs | 11 ------- .../Repositories/UserRepository.cs | 31 ++--------------- .../Repositories/OrganizationRepository.cs | 27 --------------- ...ityFrameworkServiceCollectionExtensions.cs | 11 ------- .../Repositories/UserRepository.cs | 26 --------------- .../Play/PlayServiceCollectionExtensions.cs | 30 +++++++++++++++++ ...anizationTrackingOrganizationRepository.cs | 32 ++++++++++++++++++ .../DapperTestUserTrackingUserRepository.cs | 33 +++++++++++++++++++ ...anizationTrackingOrganizationRepository.cs | 33 +++++++++++++++++++ .../EFTestUserTrackingUserRepository.cs | 31 +++++++++++++++++ .../Utilities/ServiceCollectionExtensions.cs | 3 +- 12 files changed, 163 insertions(+), 131 deletions(-) create mode 100644 src/SharedWeb/Play/PlayServiceCollectionExtensions.cs create mode 100644 src/SharedWeb/Play/Repositories/DapperTestOrganizationTrackingOrganizationRepository.cs create mode 100644 src/SharedWeb/Play/Repositories/DapperTestUserTrackingUserRepository.cs create mode 100644 src/SharedWeb/Play/Repositories/EFTestOrganizationTrackingOrganizationRepository.cs create mode 100644 src/SharedWeb/Play/Repositories/EFTestUserTrackingUserRepository.cs diff --git a/src/Infrastructure.Dapper/AdminConsole/Repositories/OrganizationRepository.cs b/src/Infrastructure.Dapper/AdminConsole/Repositories/OrganizationRepository.cs index 8d31aa44b0..434edb7676 100644 --- a/src/Infrastructure.Dapper/AdminConsole/Repositories/OrganizationRepository.cs +++ b/src/Infrastructure.Dapper/AdminConsole/Repositories/OrganizationRepository.cs @@ -6,7 +6,6 @@ using Bit.Core.Entities; using Bit.Core.Models.Data.Organizations; using Bit.Core.Models.Data.Organizations.OrganizationUsers; using Bit.Core.Repositories; -using Bit.Core.Services; using Bit.Core.Settings; using Dapper; using Microsoft.Data.SqlClient; @@ -253,28 +252,3 @@ public class OrganizationRepository : Repository, IOrganizat commandType: CommandType.StoredProcedure); } } - -/// -/// Decorator around the that tracks -/// created Organizations for seeding. -/// -public class TestOrganizationTrackingOrganizationRepository : OrganizationRepository -{ - private readonly IPlayDataService _playDataService; - - public TestOrganizationTrackingOrganizationRepository( - IPlayDataService playDataService, - GlobalSettings globalSettings, - ILogger logger) - : base(globalSettings, logger) - { - _playDataService = playDataService; - } - - public override async Task CreateAsync(Organization obj) - { - var createdOrganization = await base.CreateAsync(obj); - await _playDataService.Record(createdOrganization); - return createdOrganization; - } -} diff --git a/src/Infrastructure.Dapper/DapperServiceCollectionExtensions.cs b/src/Infrastructure.Dapper/DapperServiceCollectionExtensions.cs index bead03812f..4d8b551fe4 100644 --- a/src/Infrastructure.Dapper/DapperServiceCollectionExtensions.cs +++ b/src/Infrastructure.Dapper/DapperServiceCollectionExtensions.cs @@ -83,15 +83,4 @@ public static class DapperServiceCollectionExtensions services.AddSingleton(); } } - - /// - /// Adds PlayId tracking decorators for User and Organization repositories. - /// This replaces the standard repository implementations with tracking versions - /// that record created entities for test data cleanup. Only call when TestPlayIdTrackingEnabled is true. - /// - public static void AddPlayIdTrackingRepositories(this IServiceCollection services) - { - services.AddSingleton(); - services.AddSingleton(); - } } diff --git a/src/Infrastructure.Dapper/Repositories/UserRepository.cs b/src/Infrastructure.Dapper/Repositories/UserRepository.cs index c02f357404..571319e4c7 100644 --- a/src/Infrastructure.Dapper/Repositories/UserRepository.cs +++ b/src/Infrastructure.Dapper/Repositories/UserRepository.cs @@ -8,7 +8,6 @@ using Bit.Core.KeyManagement.Models.Data; using Bit.Core.KeyManagement.UserKey; using Bit.Core.Models.Data; using Bit.Core.Repositories; -using Bit.Core.Services; using Bit.Core.Settings; using Bit.Core.Utilities; using Dapper; @@ -22,8 +21,8 @@ public class UserRepository : Repository, IUserRepository private readonly IDataProtector _dataProtector; public UserRepository( - IDataProtectionProvider dataProtectionProvider, - GlobalSettings globalSettings) + GlobalSettings globalSettings, + IDataProtectionProvider dataProtectionProvider) : base(globalSettings.SqlServer.ConnectionString, globalSettings.SqlServer.ReadOnlyConnectionString) { _dataProtector = dataProtectionProvider.CreateProtector(Constants.DatabaseFieldProtectorPurpose); @@ -500,29 +499,3 @@ public class UserRepository : Repository, IUserRepository } } } - -/// -/// Decorator around the that tracks -/// created Users for seeding. -/// -public class TestUserTrackingUserRepository : UserRepository -{ - private readonly IPlayDataService _playDataService; - - public TestUserTrackingUserRepository( - IPlayDataService playDataService, - GlobalSettings globalSettings, - IDataProtectionProvider dataProtectionProvider) - : base(dataProtectionProvider, globalSettings) - { - _playDataService = playDataService; - } - - public override async Task CreateAsync(User user) - { - var createdUser = await base.CreateAsync(user); - - await _playDataService.Record(createdUser); - return createdUser; - } -} diff --git a/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationRepository.cs b/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationRepository.cs index 2e43183f04..88410facf5 100644 --- a/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationRepository.cs +++ b/src/Infrastructure.EntityFramework/AdminConsole/Repositories/OrganizationRepository.cs @@ -10,7 +10,6 @@ using Bit.Core.Enums; using Bit.Core.Models.Data.Organizations; using Bit.Core.Models.Data.Organizations.OrganizationUsers; using Bit.Core.Repositories; -using Bit.Core.Services; using LinqToDB.Tools; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; @@ -441,29 +440,3 @@ public class OrganizationRepository : Repository o.RevisionDate, requestDate)); } } - -/// -/// Decorator around the that tracks -/// created Organizations for seeding. -/// -public class TestOrganizationTrackingOrganizationRepository : OrganizationRepository -{ - private readonly IPlayDataService _playDataService; - - public TestOrganizationTrackingOrganizationRepository( - IPlayDataService playDataService, - IServiceScopeFactory serviceScopeFactory, - IMapper mapper, - ILogger logger) - : base(serviceScopeFactory, mapper, logger) - { - _playDataService = playDataService; - } - - public override async Task CreateAsync(Core.AdminConsole.Entities.Organization organization) - { - var createdOrganization = await base.CreateAsync(organization); - await _playDataService.Record(createdOrganization); - return createdOrganization; - } -} diff --git a/src/Infrastructure.EntityFramework/EntityFrameworkServiceCollectionExtensions.cs b/src/Infrastructure.EntityFramework/EntityFrameworkServiceCollectionExtensions.cs index fb0925f9bc..d92be9113b 100644 --- a/src/Infrastructure.EntityFramework/EntityFrameworkServiceCollectionExtensions.cs +++ b/src/Infrastructure.EntityFramework/EntityFrameworkServiceCollectionExtensions.cs @@ -120,15 +120,4 @@ public static class EntityFrameworkServiceCollectionExtensions services.AddSingleton(); } } - - /// - /// Adds PlayId tracking decorators for User and Organization repositories. - /// This replaces the standard repository implementations with tracking versions - /// that record created entities for test data cleanup. Only call when TestPlayIdTrackingEnabled is true. - /// - public static void AddPlayIdTrackingEFRepositories(this IServiceCollection services) - { - services.AddSingleton(); - services.AddSingleton(); - } } diff --git a/src/Infrastructure.EntityFramework/Repositories/UserRepository.cs b/src/Infrastructure.EntityFramework/Repositories/UserRepository.cs index 604717b1c2..56d64094d0 100644 --- a/src/Infrastructure.EntityFramework/Repositories/UserRepository.cs +++ b/src/Infrastructure.EntityFramework/Repositories/UserRepository.cs @@ -6,7 +6,6 @@ using Bit.Core.KeyManagement.Models.Data; using Bit.Core.KeyManagement.UserKey; using Bit.Core.Models.Data; using Bit.Core.Repositories; -using Bit.Core.Services; using Bit.Infrastructure.EntityFramework.Models; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; @@ -530,28 +529,3 @@ public class UserRepository : Repository, IUserR } } } - -/// -/// Decorator around the that tracks -/// created Users for seeding. -/// -public class TestUserTrackingUserRepository : UserRepository -{ - private readonly IPlayDataService _playDataService; - - public TestUserTrackingUserRepository( - IPlayDataService playDataService, - IServiceScopeFactory serviceScopeFactory, - IMapper mapper) - : base(serviceScopeFactory, mapper) - { - _playDataService = playDataService; - } - - public override async Task CreateAsync(Core.Entities.User user) - { - var createdUser = await base.CreateAsync(user); - await _playDataService.Record(createdUser); - return createdUser; - } -} diff --git a/src/SharedWeb/Play/PlayServiceCollectionExtensions.cs b/src/SharedWeb/Play/PlayServiceCollectionExtensions.cs new file mode 100644 index 0000000000..2611d58bfb --- /dev/null +++ b/src/SharedWeb/Play/PlayServiceCollectionExtensions.cs @@ -0,0 +1,30 @@ +using Bit.Core.Repositories; +using Bit.SharedWeb.Play.Repositories; +using Microsoft.Extensions.DependencyInjection; + +namespace Bit.SharedWeb.Play; + +public static class PlayServiceCollectionExtensions +{ + /// + /// Adds PlayId tracking decorators for User and Organization repositories using Dapper implementations. + /// This replaces the standard repository implementations with tracking versions + /// that record created entities for test data cleanup. Only call when TestPlayIdTrackingEnabled is true. + /// + public static void AddPlayIdTrackingDapperRepositories(this IServiceCollection services) + { + services.AddSingleton(); + services.AddSingleton(); + } + + /// + /// Adds PlayId tracking decorators for User and Organization repositories using EntityFramework implementations. + /// This replaces the standard repository implementations with tracking versions + /// that record created entities for test data cleanup. Only call when TestPlayIdTrackingEnabled is true. + /// + public static void AddPlayIdTrackingEFRepositories(this IServiceCollection services) + { + services.AddSingleton(); + services.AddSingleton(); + } +} diff --git a/src/SharedWeb/Play/Repositories/DapperTestOrganizationTrackingOrganizationRepository.cs b/src/SharedWeb/Play/Repositories/DapperTestOrganizationTrackingOrganizationRepository.cs new file mode 100644 index 0000000000..b70738989a --- /dev/null +++ b/src/SharedWeb/Play/Repositories/DapperTestOrganizationTrackingOrganizationRepository.cs @@ -0,0 +1,32 @@ +using Bit.Core.AdminConsole.Entities; +using Bit.Core.Services; +using Bit.Core.Settings; +using Bit.Infrastructure.Dapper.Repositories; +using Microsoft.Extensions.Logging; + +namespace Bit.SharedWeb.Play.Repositories; + +/// +/// Dapper decorator around the that tracks +/// created Organizations for seeding. +/// +public class DapperTestOrganizationTrackingOrganizationRepository : OrganizationRepository +{ + private readonly IPlayDataService _playDataService; + + public DapperTestOrganizationTrackingOrganizationRepository( + IPlayDataService playDataService, + GlobalSettings globalSettings, + ILogger logger) + : base(globalSettings, logger) + { + _playDataService = playDataService; + } + + public override async Task CreateAsync(Organization obj) + { + var createdOrganization = await base.CreateAsync(obj); + await _playDataService.Record(createdOrganization); + return createdOrganization; + } +} diff --git a/src/SharedWeb/Play/Repositories/DapperTestUserTrackingUserRepository.cs b/src/SharedWeb/Play/Repositories/DapperTestUserTrackingUserRepository.cs new file mode 100644 index 0000000000..9bedeaebc7 --- /dev/null +++ b/src/SharedWeb/Play/Repositories/DapperTestUserTrackingUserRepository.cs @@ -0,0 +1,33 @@ +using Bit.Core.Entities; +using Bit.Core.Services; +using Bit.Core.Settings; +using Bit.Infrastructure.Dapper.Repositories; +using Microsoft.AspNetCore.DataProtection; + +namespace Bit.SharedWeb.Play.Repositories; + +/// +/// Dapper decorator around the that tracks +/// created Users for seeding. +/// +public class DapperTestUserTrackingUserRepository : UserRepository +{ + private readonly IPlayDataService _playDataService; + + public DapperTestUserTrackingUserRepository( + IPlayDataService playDataService, + GlobalSettings globalSettings, + IDataProtectionProvider dataProtectionProvider) + : base(globalSettings, dataProtectionProvider) + { + _playDataService = playDataService; + } + + public override async Task CreateAsync(User user) + { + var createdUser = await base.CreateAsync(user); + + await _playDataService.Record(createdUser); + return createdUser; + } +} diff --git a/src/SharedWeb/Play/Repositories/EFTestOrganizationTrackingOrganizationRepository.cs b/src/SharedWeb/Play/Repositories/EFTestOrganizationTrackingOrganizationRepository.cs new file mode 100644 index 0000000000..b0c6a28ce7 --- /dev/null +++ b/src/SharedWeb/Play/Repositories/EFTestOrganizationTrackingOrganizationRepository.cs @@ -0,0 +1,33 @@ +using AutoMapper; +using Bit.Core.Services; +using Bit.Infrastructure.EntityFramework.Repositories; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace Bit.SharedWeb.Play.Repositories; + +/// +/// EntityFramework decorator around the that tracks +/// created Organizations for seeding. +/// +public class EFTestOrganizationTrackingOrganizationRepository : OrganizationRepository +{ + private readonly IPlayDataService _playDataService; + + public EFTestOrganizationTrackingOrganizationRepository( + IPlayDataService playDataService, + IServiceScopeFactory serviceScopeFactory, + IMapper mapper, + ILogger logger) + : base(serviceScopeFactory, mapper, logger) + { + _playDataService = playDataService; + } + + public override async Task CreateAsync(Core.AdminConsole.Entities.Organization organization) + { + var createdOrganization = await base.CreateAsync(organization); + await _playDataService.Record(createdOrganization); + return createdOrganization; + } +} diff --git a/src/SharedWeb/Play/Repositories/EFTestUserTrackingUserRepository.cs b/src/SharedWeb/Play/Repositories/EFTestUserTrackingUserRepository.cs new file mode 100644 index 0000000000..8d2fb2d502 --- /dev/null +++ b/src/SharedWeb/Play/Repositories/EFTestUserTrackingUserRepository.cs @@ -0,0 +1,31 @@ +using AutoMapper; +using Bit.Core.Services; +using Bit.Infrastructure.EntityFramework.Repositories; +using Microsoft.Extensions.DependencyInjection; + +namespace Bit.SharedWeb.Play.Repositories; + +/// +/// EntityFramework decorator around the that tracks +/// created Users for seeding. +/// +public class EFTestUserTrackingUserRepository : UserRepository +{ + private readonly IPlayDataService _playDataService; + + public EFTestUserTrackingUserRepository( + IPlayDataService playDataService, + IServiceScopeFactory serviceScopeFactory, + IMapper mapper) + : base(serviceScopeFactory, mapper) + { + _playDataService = playDataService; + } + + public override async Task CreateAsync(Core.Entities.User user) + { + var createdUser = await base.CreateAsync(user); + await _playDataService.Record(createdUser); + return createdUser; + } +} diff --git a/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs b/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs index ab93acd97c..74061a4967 100644 --- a/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs +++ b/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs @@ -56,6 +56,7 @@ using Bit.Core.Vault; using Bit.Core.Vault.Services; using Bit.Infrastructure.Dapper; using Bit.Infrastructure.EntityFramework; +using Bit.SharedWeb.Play; using DnsClient; using Duende.IdentityModel; using LaunchDarkly.Sdk.Server; @@ -127,7 +128,7 @@ public static class ServiceCollectionExtensions // Replace standard repositories with PlayId tracking decorators if (provider == SupportedDatabaseProviders.SqlServer) { - services.AddPlayIdTrackingRepositories(); + services.AddPlayIdTrackingDapperRepositories(); } else {