1
0
mirror of https://github.com/bitwarden/server synced 2026-01-08 19:43:34 +00:00

Use a header to track seeded data. This has benefits client side in simplicity and allows us to track entities added during a test, as long as they include the play id header.

This commit is contained in:
Matt Gibson
2025-11-10 18:17:41 -08:00
parent 0b22af53da
commit f2116734a2
20 changed files with 125 additions and 148 deletions

View File

@@ -1,4 +1,6 @@
using Microsoft.Extensions.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace Bit.Core.Services;
@@ -11,3 +13,38 @@ public class PlayIdService(IHostEnvironment hostEnvironment) : IPlayIdService
return !string.IsNullOrEmpty(PlayId) && hostEnvironment.IsDevelopment();
}
}
public class PlayIdSingletonService(IHttpContextAccessor httpContextAccessor, IHostEnvironment hostEnvironment) : IPlayIdService
{
private PlayIdService Current
{
get
{
var httpContext = httpContextAccessor.HttpContext;
if (httpContext == null)
{
throw new InvalidOperationException("HttpContext is not available");
}
return httpContext.RequestServices.GetRequiredService<PlayIdService>();
}
}
public string? PlayId
{
get => Current.PlayId;
set => Current.PlayId = value;
}
public bool InPlay(out string playId)
{
if (hostEnvironment.IsDevelopment())
{
return Current.InPlay(out playId);
}
else
{
playId = string.Empty;
return false;
}
}
}

View File

@@ -1,12 +0,0 @@
namespace Bit.Infrastructure.EntityFramework.Models;
public class SeededData
{
public Guid Id { get; set; }
public required string RecipeName { get; set; }
/// <summary>
/// JSON blob containing all
/// </summary>
public required string Data { get; set; }
public DateTime CreationDate { get; set; }
}

View File

@@ -90,7 +90,6 @@ public class DatabaseContext : DbContext
public DbSet<OrganizationInstallation> OrganizationInstallations { get; set; }
public DbSet<OrganizationReport> OrganizationReports { get; set; }
public DbSet<OrganizationApplication> OrganizationApplications { get; set; }
public DbSet<SeededData> SeededData { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{

View File

@@ -5,7 +5,7 @@ namespace Bit.SharedWeb.Utilities;
public sealed class PlayIdMiddleware(RequestDelegate next)
{
public Task Invoke(HttpContext context, IPlayIdService playIdService)
public Task Invoke(HttpContext context, PlayIdService playIdService)
{
if (context.Request.Headers.TryGetValue("x-play-id", out var playId))
{

View File

@@ -119,8 +119,11 @@ public static class ServiceCollectionExtensions
}
// Include PlayIdService for tracking Play Ids in repositories
services.AddScoped<IPlayIdService, PlayIdService>();
// We need the http context accessor to use the Singleton version, which pulls from the scoped version
services.AddHttpContextAccessor();
services.AddSingleton<IPlayIdService, PlayIdSingletonService>();
services.AddScoped<PlayIdService>();
return provider;
}

View File

@@ -5,8 +5,8 @@ CREATE TABLE [dbo].[PlayData] (
[OrganizationId] UNIQUEIDENTIFIER NULL,
[CreationDate] DATETIME2 (7) NOT NULL,
CONSTRAINT [PK_PlayData] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_PlayData_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([Id]),
CONSTRAINT [FK_PlayData_Organization] FOREIGN KEY ([OrganizationId]) REFERENCES [dbo].[Organization] ([Id]),
CONSTRAINT [FK_PlayData_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([Id]) ON DELETE CASCADE,
CONSTRAINT [FK_PlayData_Organization] FOREIGN KEY ([OrganizationId]) REFERENCES [dbo].[Organization] ([Id]) ON DELETE CASCADE,
CONSTRAINT [CK_PlayData_UserOrOrganization] CHECK (([UserId] IS NOT NULL AND [OrganizationId] IS NULL) OR ([UserId] IS NULL AND [OrganizationId] IS NOT NULL))
);

View File

@@ -1,6 +0,0 @@
CREATE TABLE [dbo].[SeededData] (
[Id] UNIQUEIDENTIFIER NOT NULL,
[RecipeName] NVARCHAR (MAX) NOT NULL,
[Data] NVARCHAR (MAX) NULL,
[CreationDate] DATETIME2 (7) NOT NULL,
);