mirror of
https://github.com/bitwarden/server
synced 2026-01-15 06:53:26 +00:00
Resolve review feedback
This commit is contained in:
@@ -29,6 +29,14 @@ public class NeverPlayIdServices : IPlayIdService
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Singleton wrapper service that bridges singleton-scoped service boundaries for PlayId tracking.
|
||||
/// This allows singleton services to access the scoped PlayIdService via HttpContext.RequestServices.
|
||||
///
|
||||
/// Uses IHttpContextAccessor to retrieve the current request's scoped PlayIdService instance, enabling
|
||||
/// singleton services to participate in Play session tracking without violating DI lifetime rules.
|
||||
/// Falls back to NeverPlayIdServices when no HttpContext is available (e.g., background jobs).
|
||||
/// </summary>
|
||||
public class PlayIdSingletonService(IHttpContextAccessor httpContextAccessor, IHostEnvironment hostEnvironment) : IPlayIdService
|
||||
{
|
||||
private IPlayIdService Current
|
||||
|
||||
@@ -9,7 +9,6 @@ using Bit.Core.NotificationCenter.Repositories;
|
||||
using Bit.Core.Platform.Installations;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.SecretsManager.Repositories;
|
||||
using Bit.Core.Settings;
|
||||
using Bit.Core.Tools.Repositories;
|
||||
using Bit.Core.Vault.Repositories;
|
||||
using Bit.Infrastructure.Dapper.AdminConsole.Repositories;
|
||||
@@ -29,19 +28,8 @@ namespace Bit.Infrastructure.Dapper;
|
||||
|
||||
public static class DapperServiceCollectionExtensions
|
||||
{
|
||||
public static void AddDapperRepositories(this IServiceCollection services, bool selfHosted, GlobalSettings globalSettings)
|
||||
public static void AddDapperRepositories(this IServiceCollection services, bool selfHosted)
|
||||
{
|
||||
if (globalSettings.TestPlayIdTrackingEnabled)
|
||||
{
|
||||
services.AddSingleton<IOrganizationRepository, TestOrganizationTrackingOrganizationRepository>();
|
||||
services.AddSingleton<IUserRepository, TestUserTrackingUserRepository>();
|
||||
}
|
||||
else
|
||||
{
|
||||
services.AddSingleton<IOrganizationRepository, OrganizationRepository>();
|
||||
services.AddSingleton<IUserRepository, UserRepository>();
|
||||
}
|
||||
|
||||
services.AddSingleton<IApiKeyRepository, ApiKeyRepository>();
|
||||
services.AddSingleton<IAuthRequestRepository, AuthRequestRepository>();
|
||||
services.AddSingleton<ICipherRepository, CipherRepository>();
|
||||
@@ -59,6 +47,7 @@ public static class DapperServiceCollectionExtensions
|
||||
services.AddSingleton<IOrganizationConnectionRepository, OrganizationConnectionRepository>();
|
||||
services.AddSingleton<IOrganizationIntegrationConfigurationRepository, OrganizationIntegrationConfigurationRepository>();
|
||||
services.AddSingleton<IOrganizationIntegrationRepository, OrganizationIntegrationRepository>();
|
||||
services.AddSingleton<IOrganizationRepository, OrganizationRepository>();
|
||||
services.AddSingleton<IOrganizationSponsorshipRepository, OrganizationSponsorshipRepository>();
|
||||
services.AddSingleton<IOrganizationUserRepository, OrganizationUserRepository>();
|
||||
services.AddSingleton<IPlayDataRepository, PlayDataRepository>();
|
||||
@@ -70,6 +59,7 @@ public static class DapperServiceCollectionExtensions
|
||||
services.AddSingleton<ISsoConfigRepository, SsoConfigRepository>();
|
||||
services.AddSingleton<ISsoUserRepository, SsoUserRepository>();
|
||||
services.AddSingleton<ITransactionRepository, TransactionRepository>();
|
||||
services.AddSingleton<IUserRepository, UserRepository>();
|
||||
services.AddSingleton<IOrganizationDomainRepository, OrganizationDomainRepository>();
|
||||
services.AddSingleton<IWebAuthnCredentialRepository, WebAuthnCredentialRepository>();
|
||||
services.AddSingleton<IProviderPlanRepository, ProviderPlanRepository>();
|
||||
@@ -92,4 +82,15 @@ 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>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,19 +68,8 @@ public static class EntityFrameworkServiceCollectionExtensions
|
||||
});
|
||||
}
|
||||
|
||||
public static void AddPasswordManagerEFRepositories(this IServiceCollection services, bool selfHosted, GlobalSettings globalSettings)
|
||||
public static void AddPasswordManagerEFRepositories(this IServiceCollection services, bool selfHosted)
|
||||
{
|
||||
if (globalSettings.TestPlayIdTrackingEnabled)
|
||||
{
|
||||
services.AddSingleton<IOrganizationRepository, TestOrganizationTrackingOrganizationRepository>();
|
||||
services.AddSingleton<IUserRepository, TestUserTrackingUserRepository>();
|
||||
}
|
||||
else
|
||||
{
|
||||
services.AddSingleton<IOrganizationRepository, OrganizationRepository>();
|
||||
services.AddSingleton<IUserRepository, UserRepository>();
|
||||
}
|
||||
|
||||
services.AddSingleton<IApiKeyRepository, ApiKeyRepository>();
|
||||
services.AddSingleton<IAuthRequestRepository, AuthRequestRepository>();
|
||||
services.AddSingleton<ICipherRepository, CipherRepository>();
|
||||
@@ -97,6 +86,7 @@ public static class EntityFrameworkServiceCollectionExtensions
|
||||
services.AddSingleton<IOrganizationConnectionRepository, OrganizationConnectionRepository>();
|
||||
services.AddSingleton<IOrganizationIntegrationRepository, OrganizationIntegrationRepository>();
|
||||
services.AddSingleton<IOrganizationIntegrationConfigurationRepository, OrganizationIntegrationConfigurationRepository>();
|
||||
services.AddSingleton<IOrganizationRepository, OrganizationRepository>();
|
||||
services.AddSingleton<IOrganizationSponsorshipRepository, OrganizationSponsorshipRepository>();
|
||||
services.AddSingleton<IOrganizationUserRepository, OrganizationUserRepository>();
|
||||
services.AddSingleton<IPlayDataRepository, PlayDataRepository>();
|
||||
@@ -108,6 +98,7 @@ public static class EntityFrameworkServiceCollectionExtensions
|
||||
services.AddSingleton<ISsoConfigRepository, SsoConfigRepository>();
|
||||
services.AddSingleton<ISsoUserRepository, SsoUserRepository>();
|
||||
services.AddSingleton<ITransactionRepository, TransactionRepository>();
|
||||
services.AddSingleton<IUserRepository, UserRepository>();
|
||||
services.AddSingleton<IOrganizationDomainRepository, OrganizationDomainRepository>();
|
||||
services.AddSingleton<IWebAuthnCredentialRepository, WebAuthnCredentialRepository>();
|
||||
services.AddSingleton<IProviderPlanRepository, ProviderPlanRepository>();
|
||||
@@ -130,4 +121,15 @@ 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>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,13 +11,31 @@ namespace Bit.SharedWeb.Utilities;
|
||||
/// <param name="next"></param>
|
||||
public sealed class PlayIdMiddleware(RequestDelegate next)
|
||||
{
|
||||
public Task Invoke(HttpContext context, PlayIdService playIdService)
|
||||
private const int MaxPlayIdLength = 256;
|
||||
|
||||
public async Task Invoke(HttpContext context, PlayIdService playIdService)
|
||||
{
|
||||
if (context.Request.Headers.TryGetValue("x-play-id", out var playId))
|
||||
{
|
||||
playIdService.PlayId = playId;
|
||||
var playIdValue = playId.ToString();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(playIdValue))
|
||||
{
|
||||
context.Response.StatusCode = StatusCodes.Status400BadRequest;
|
||||
await context.Response.WriteAsJsonAsync(new { Error = "x-play-id header cannot be empty or whitespace" });
|
||||
return;
|
||||
}
|
||||
|
||||
if (playIdValue.Length > MaxPlayIdLength)
|
||||
{
|
||||
context.Response.StatusCode = StatusCodes.Status400BadRequest;
|
||||
await context.Response.WriteAsJsonAsync(new { Error = $"x-play-id header cannot exceed {MaxPlayIdLength} characters" });
|
||||
return;
|
||||
}
|
||||
|
||||
playIdService.PlayId = playIdValue;
|
||||
}
|
||||
|
||||
return next(context);
|
||||
await next(context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,11 +96,11 @@ public static class ServiceCollectionExtensions
|
||||
|
||||
if (provider != SupportedDatabaseProviders.SqlServer)
|
||||
{
|
||||
services.AddPasswordManagerEFRepositories(globalSettings.SelfHosted, globalSettings);
|
||||
services.AddPasswordManagerEFRepositories(globalSettings.SelfHosted);
|
||||
}
|
||||
else
|
||||
{
|
||||
services.AddDapperRepositories(globalSettings.SelfHosted, globalSettings);
|
||||
services.AddDapperRepositories(globalSettings.SelfHosted);
|
||||
}
|
||||
|
||||
if (globalSettings.SelfHosted)
|
||||
@@ -123,6 +123,16 @@ public static class ServiceCollectionExtensions
|
||||
services.AddSingleton<IPlayDataService, PlayDataService>();
|
||||
services.AddSingleton<IPlayIdService, PlayIdSingletonService>();
|
||||
services.AddScoped<PlayIdService>();
|
||||
|
||||
// Replace standard repositories with PlayId tracking decorators
|
||||
if (provider == SupportedDatabaseProviders.SqlServer)
|
||||
{
|
||||
services.AddPlayIdTrackingRepositories();
|
||||
}
|
||||
else
|
||||
{
|
||||
services.AddPlayIdTrackingEFRepositories();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -5,7 +5,11 @@ BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
SELECT
|
||||
*
|
||||
[Id],
|
||||
[PlayId],
|
||||
[UserId],
|
||||
[OrganizationId],
|
||||
[CreationDate]
|
||||
FROM
|
||||
[dbo].[PlayData]
|
||||
WHERE
|
||||
|
||||
Reference in New Issue
Block a user