1
0
mirror of https://github.com/bitwarden/server synced 2026-01-11 21:13:50 +00:00

Extract TestTracking

This commit is contained in:
Hinton
2026-01-08 14:40:32 +01:00
parent 871e55b960
commit 8ab09a45b2
12 changed files with 163 additions and 131 deletions

View File

@@ -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<Organization, Guid>, IOrganizat
commandType: CommandType.StoredProcedure);
}
}
/// <summary>
/// Decorator around the <see cref="OrganizationRepository"/> that tracks
/// created Organizations for seeding.
/// </summary>
public class TestOrganizationTrackingOrganizationRepository : OrganizationRepository
{
private readonly IPlayDataService _playDataService;
public TestOrganizationTrackingOrganizationRepository(
IPlayDataService playDataService,
GlobalSettings globalSettings,
ILogger<OrganizationRepository> logger)
: base(globalSettings, logger)
{
_playDataService = playDataService;
}
public override async Task<Organization> CreateAsync(Organization obj)
{
var createdOrganization = await base.CreateAsync(obj);
await _playDataService.Record(createdOrganization);
return createdOrganization;
}
}

View File

@@ -83,15 +83,4 @@ public static class DapperServiceCollectionExtensions
services.AddSingleton<IEventRepository, EventRepository>();
}
}
/// <summary>
/// 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.
/// </summary>
public static void AddPlayIdTrackingRepositories(this IServiceCollection services)
{
services.AddSingleton<IOrganizationRepository, TestOrganizationTrackingOrganizationRepository>();
services.AddSingleton<IUserRepository, TestUserTrackingUserRepository>();
}
}

View File

@@ -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<User, Guid>, 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<User, Guid>, IUserRepository
}
}
}
/// <summary>
/// Decorator around the <see cref="UserRepository"/> that tracks
/// created Users for seeding.
/// </summary>
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<User> CreateAsync(User user)
{
var createdUser = await base.CreateAsync(user);
await _playDataService.Record(createdUser);
return createdUser;
}
}

View File

@@ -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<Core.AdminConsole.Entities.Orga
.SetProperty(o => o.RevisionDate, requestDate));
}
}
/// <summary>
/// Decorator around the <see cref="OrganizationRepository"/> that tracks
/// created Organizations for seeding.
/// </summary>
public class TestOrganizationTrackingOrganizationRepository : OrganizationRepository
{
private readonly IPlayDataService _playDataService;
public TestOrganizationTrackingOrganizationRepository(
IPlayDataService playDataService,
IServiceScopeFactory serviceScopeFactory,
IMapper mapper,
ILogger<OrganizationRepository> logger)
: base(serviceScopeFactory, mapper, logger)
{
_playDataService = playDataService;
}
public override async Task<Core.AdminConsole.Entities.Organization> CreateAsync(Core.AdminConsole.Entities.Organization organization)
{
var createdOrganization = await base.CreateAsync(organization);
await _playDataService.Record(createdOrganization);
return createdOrganization;
}
}

View File

@@ -120,15 +120,4 @@ public static class EntityFrameworkServiceCollectionExtensions
services.AddSingleton<IEventRepository, EventRepository>();
}
}
/// <summary>
/// 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.
/// </summary>
public static void AddPlayIdTrackingEFRepositories(this IServiceCollection services)
{
services.AddSingleton<IOrganizationRepository, TestOrganizationTrackingOrganizationRepository>();
services.AddSingleton<IUserRepository, TestUserTrackingUserRepository>();
}
}

View File

@@ -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<Core.Entities.User, User, Guid>, IUserR
}
}
}
/// <summary>
/// Decorator around the <see cref="UserRepository"/> that tracks
/// created Users for seeding.
/// </summary>
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<Core.Entities.User> CreateAsync(Core.Entities.User user)
{
var createdUser = await base.CreateAsync(user);
await _playDataService.Record(createdUser);
return createdUser;
}
}

View File

@@ -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
{
/// <summary>
/// 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.
/// </summary>
public static void AddPlayIdTrackingDapperRepositories(this IServiceCollection services)
{
services.AddSingleton<IOrganizationRepository, DapperTestOrganizationTrackingOrganizationRepository>();
services.AddSingleton<IUserRepository, DapperTestUserTrackingUserRepository>();
}
/// <summary>
/// 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.
/// </summary>
public static void AddPlayIdTrackingEFRepositories(this IServiceCollection services)
{
services.AddSingleton<IOrganizationRepository, EFTestOrganizationTrackingOrganizationRepository>();
services.AddSingleton<IUserRepository, EFTestUserTrackingUserRepository>();
}
}

View File

@@ -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;
/// <summary>
/// Dapper decorator around the <see cref="Bit.Infrastructure.Dapper.Repositories.OrganizationRepository"/> that tracks
/// created Organizations for seeding.
/// </summary>
public class DapperTestOrganizationTrackingOrganizationRepository : OrganizationRepository
{
private readonly IPlayDataService _playDataService;
public DapperTestOrganizationTrackingOrganizationRepository(
IPlayDataService playDataService,
GlobalSettings globalSettings,
ILogger<OrganizationRepository> logger)
: base(globalSettings, logger)
{
_playDataService = playDataService;
}
public override async Task<Organization> CreateAsync(Organization obj)
{
var createdOrganization = await base.CreateAsync(obj);
await _playDataService.Record(createdOrganization);
return createdOrganization;
}
}

View File

@@ -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;
/// <summary>
/// Dapper decorator around the <see cref="Bit.Infrastructure.Dapper.Repositories.UserRepository"/> that tracks
/// created Users for seeding.
/// </summary>
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<User> CreateAsync(User user)
{
var createdUser = await base.CreateAsync(user);
await _playDataService.Record(createdUser);
return createdUser;
}
}

View File

@@ -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;
/// <summary>
/// EntityFramework decorator around the <see cref="Bit.Infrastructure.EntityFramework.Repositories.OrganizationRepository"/> that tracks
/// created Organizations for seeding.
/// </summary>
public class EFTestOrganizationTrackingOrganizationRepository : OrganizationRepository
{
private readonly IPlayDataService _playDataService;
public EFTestOrganizationTrackingOrganizationRepository(
IPlayDataService playDataService,
IServiceScopeFactory serviceScopeFactory,
IMapper mapper,
ILogger<OrganizationRepository> logger)
: base(serviceScopeFactory, mapper, logger)
{
_playDataService = playDataService;
}
public override async Task<Core.AdminConsole.Entities.Organization> CreateAsync(Core.AdminConsole.Entities.Organization organization)
{
var createdOrganization = await base.CreateAsync(organization);
await _playDataService.Record(createdOrganization);
return createdOrganization;
}
}

View File

@@ -0,0 +1,31 @@
using AutoMapper;
using Bit.Core.Services;
using Bit.Infrastructure.EntityFramework.Repositories;
using Microsoft.Extensions.DependencyInjection;
namespace Bit.SharedWeb.Play.Repositories;
/// <summary>
/// EntityFramework decorator around the <see cref="Bit.Infrastructure.EntityFramework.Repositories.UserRepository"/> that tracks
/// created Users for seeding.
/// </summary>
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<Core.Entities.User> CreateAsync(Core.Entities.User user)
{
var createdUser = await base.CreateAsync(user);
await _playDataService.Record(createdUser);
return createdUser;
}
}

View File

@@ -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
{