From 814612cb51bb70ced23fd49075027b2fd974ed89 Mon Sep 17 00:00:00 2001 From: Matt Gibson Date: Thu, 8 Jan 2026 08:45:38 -0800 Subject: [PATCH] Rename PlayData -> PlayItem This is still a join table, but the Data suffix was colliding with the concept of a JSON transfer model. The PlayItem name is designed to indicate that these records are not Play entities, but indications that a given Item (user or organization for now) is associated with a given Play --- .../Entities/{PlayData.cs => PlayItem.cs} | 20 ++++----- ...taRepository.cs => IPlayItemRepository.cs} | 4 +- src/Core/Services/Play/IPlayIdService.cs | 2 +- ...PlayDataService.cs => IPlayItemService.cs} | 6 +-- ...{PlayDataService.cs => PlayItemService.cs} | 6 +-- src/Core/Services/Play/README.md | 10 ++--- .../DapperServiceCollectionExtensions.cs | 2 +- ...ataRepository.cs => PlayItemRepository.cs} | 14 +++--- ....cs => PlayItemEntityTypeConfiguration.cs} | 8 ++-- ...ityFrameworkServiceCollectionExtensions.cs | 2 +- .../Models/{PlayData.cs => PlayItem.cs} | 8 ++-- .../Repositories/DatabaseContext.cs | 2 +- ...ataRepository.cs => PlayItemRepository.cs} | 14 +++--- ...anizationTrackingOrganizationRepository.cs | 8 ++-- .../DapperTestUserTrackingUserRepository.cs | 8 ++-- ...anizationTrackingOrganizationRepository.cs | 8 ++-- .../EFTestUserTrackingUserRepository.cs | 8 ++-- .../Utilities/ServiceCollectionExtensions.cs | 2 +- ...layData_Create.sql => PlayItem_Create.sql} | 4 +- ...PlayId.sql => PlayItem_DeleteByPlayId.sql} | 4 +- ...ByPlayId.sql => PlayItem_ReadByPlayId.sql} | 4 +- src/Sql/dbo/Tables/PlayData.sql | 23 ---------- src/Sql/dbo/Tables/PlayItem.sql | 23 ++++++++++ ...erviceTests.cs => PlayItemServiceTests.cs} | 42 +++++++++--------- ...layData.sql => 2025-11-04_00_PlayItem.sql} | 44 +++++++++---------- ...cs => 20251118024031_PlayItem.Designer.cs} | 12 ++--- ...PlayData.cs => 20251118024031_PlayItem.cs} | 26 +++++------ .../DatabaseContextModelSnapshot.cs | 8 ++-- ...cs => 20251118024041_PlayItem.Designer.cs} | 12 ++--- ...PlayData.cs => 20251118024041_PlayItem.cs} | 26 +++++------ .../DatabaseContextModelSnapshot.cs | 8 ++-- .../SeederApi/Commands/DestroySceneCommand.cs | 10 ++--- util/SeederApi/Queries/GetAllPlayIdsQuery.cs | 2 +- util/SeederApi/README.md | 8 ++-- ...cs => 20251118024036_PlayItem.Designer.cs} | 12 ++--- ...PlayData.cs => 20251118024036_PlayItem.cs} | 26 +++++------ .../DatabaseContextModelSnapshot.cs | 8 ++-- 37 files changed, 216 insertions(+), 218 deletions(-) rename src/Core/Entities/{PlayData.cs => PlayItem.cs} (73%) rename src/Core/Repositories/{IPlayDataRepository.cs => IPlayItemRepository.cs} (51%) rename src/Core/Services/Play/{IPlayDataService.cs => IPlayItemService.cs} (80%) rename src/Core/Services/Play/Implementations/{PlayDataService.cs => PlayItemService.cs} (71%) rename src/Infrastructure.Dapper/Repositories/{PlayDataRepository.cs => PlayItemRepository.cs} (69%) rename src/Infrastructure.EntityFramework/Configurations/{PlayDataEntityTypeConfiguration.cs => PlayItemEntityTypeConfiguration.cs} (82%) rename src/Infrastructure.EntityFramework/Models/{PlayData.cs => PlayItem.cs} (55%) rename src/Infrastructure.EntityFramework/Repositories/{PlayDataRepository.cs => PlayItemRepository.cs} (69%) rename src/Sql/dbo/Stored Procedures/{PlayData_Create.sql => PlayItem_Create.sql} (85%) rename src/Sql/dbo/Stored Procedures/{PlayData_DeleteByPlayId.sql => PlayItem_DeleteByPlayId.sql} (61%) rename src/Sql/dbo/Stored Procedures/{PlayData_ReadByPlayId.sql => PlayItem_ReadByPlayId.sql} (74%) delete mode 100644 src/Sql/dbo/Tables/PlayData.sql create mode 100644 src/Sql/dbo/Tables/PlayItem.sql rename test/Core.Test/Services/{PlayDataServiceTests.cs => PlayItemServiceTests.cs} (77%) rename util/Migrator/DbScripts/{2025-11-04_00_PlayData.sql => 2025-11-04_00_PlayItem.sql} (54%) rename util/MySqlMigrations/Migrations/{20251118024031_PlayData.Designer.cs => 20251118024031_PlayItem.Designer.cs} (99%) rename util/MySqlMigrations/Migrations/{20251118024031_PlayData.cs => 20251118024031_PlayItem.cs} (81%) rename util/PostgresMigrations/Migrations/{20251118024041_PlayData.Designer.cs => 20251118024041_PlayItem.Designer.cs} (99%) rename util/PostgresMigrations/Migrations/{20251118024041_PlayData.cs => 20251118024041_PlayItem.cs} (80%) rename util/SqliteMigrations/Migrations/{20251118024036_PlayData.Designer.cs => 20251118024036_PlayItem.Designer.cs} (99%) rename util/SqliteMigrations/Migrations/{20251118024036_PlayData.cs => 20251118024036_PlayItem.cs} (75%) diff --git a/src/Core/Entities/PlayData.cs b/src/Core/Entities/PlayItem.cs similarity index 73% rename from src/Core/Entities/PlayData.cs rename to src/Core/Entities/PlayItem.cs index 131cc1c676..cf2f5c946b 100644 --- a/src/Core/Entities/PlayData.cs +++ b/src/Core/Entities/PlayItem.cs @@ -5,11 +5,11 @@ using Bit.Core.Utilities; namespace Bit.Core.Entities; /// -/// PlayData is a join table tracking entities created during automated testing. +/// PlayItem is a join table tracking entities created during automated testing. /// A `PlayId` is supplied by the clients in the `x-play-id` header to inform the server /// that any data created should be associated with the play, and therefore cleaned up with it. /// -public class PlayData : ITableObject +public class PlayItem : ITableObject { public Guid Id { get; set; } [MaxLength(256)] @@ -27,14 +27,14 @@ public class PlayData : ITableObject } /// - /// Creates a new PlayData record associated with a User. + /// Creates a new PlayItem record associated with a User. /// /// The user entity created during the play. /// The play identifier from the x-play-id header. - /// A new PlayData instance tracking the user. - public static PlayData Create(User user, string playId) + /// A new PlayItem instance tracking the user. + public static PlayItem Create(User user, string playId) { - return new PlayData + return new PlayItem { PlayId = playId, UserId = user.Id, @@ -43,14 +43,14 @@ public class PlayData : ITableObject } /// - /// Creates a new PlayData record associated with an Organization. + /// Creates a new PlayItem record associated with an Organization. /// /// The organization entity created during the play. /// The play identifier from the x-play-id header. - /// A new PlayData instance tracking the organization. - public static PlayData Create(Organization organization, string playId) + /// A new PlayItem instance tracking the organization. + public static PlayItem Create(Organization organization, string playId) { - return new PlayData + return new PlayItem { PlayId = playId, OrganizationId = organization.Id, diff --git a/src/Core/Repositories/IPlayDataRepository.cs b/src/Core/Repositories/IPlayItemRepository.cs similarity index 51% rename from src/Core/Repositories/IPlayDataRepository.cs rename to src/Core/Repositories/IPlayItemRepository.cs index cf16dce16a..fb00be2bc1 100644 --- a/src/Core/Repositories/IPlayDataRepository.cs +++ b/src/Core/Repositories/IPlayItemRepository.cs @@ -4,8 +4,8 @@ namespace Bit.Core.Repositories; -public interface IPlayDataRepository : IRepository +public interface IPlayItemRepository : IRepository { - Task> GetByPlayIdAsync(string playId); + Task> GetByPlayIdAsync(string playId); Task DeleteByPlayIdAsync(string playId); } diff --git a/src/Core/Services/Play/IPlayIdService.cs b/src/Core/Services/Play/IPlayIdService.cs index ac1fa4b293..542de9725f 100644 --- a/src/Core/Services/Play/IPlayIdService.cs +++ b/src/Core/Services/Play/IPlayIdService.cs @@ -4,7 +4,7 @@ /// Service for managing Play identifiers in automated testing infrastructure. /// A "Play" is a test session that groups entities created during testing to enable cleanup. /// The PlayId flows from client request (x-play-id header) through PlayIdMiddleware to this service, -/// which repositories query to create PlayData tracking records via IPlayDataService. The SeederAPI uses these records +/// which repositories query to create PlayItem tracking records via IPlayItemService. The SeederAPI uses these records /// to bulk delete all entities associated with a PlayId. Only active in Development environments. /// public interface IPlayIdService diff --git a/src/Core/Services/Play/IPlayDataService.cs b/src/Core/Services/Play/IPlayItemService.cs similarity index 80% rename from src/Core/Services/Play/IPlayDataService.cs rename to src/Core/Services/Play/IPlayItemService.cs index 775506b9a2..5033aaf626 100644 --- a/src/Core/Services/Play/IPlayDataService.cs +++ b/src/Core/Services/Play/IPlayItemService.cs @@ -6,10 +6,10 @@ namespace Bit.Core.Services; /// /// Service used to track added users and organizations during a Play session. /// -public interface IPlayDataService +public interface IPlayItemService { /// - /// Records a PlayData entry for the given User created during a Play session. + /// Records a PlayItem entry for the given User created during a Play session. /// /// Does nothing if no Play Id is set for this http scope. /// @@ -17,7 +17,7 @@ public interface IPlayDataService /// Task Record(User user); /// - /// Records a PlayData entry for the given Organization created during a Play session. + /// Records a PlayItem entry for the given Organization created during a Play session. /// /// Does nothing if no Play Id is set for this http scope. /// diff --git a/src/Core/Services/Play/Implementations/PlayDataService.cs b/src/Core/Services/Play/Implementations/PlayItemService.cs similarity index 71% rename from src/Core/Services/Play/Implementations/PlayDataService.cs rename to src/Core/Services/Play/Implementations/PlayItemService.cs index 612ca3fd85..981445f2ea 100644 --- a/src/Core/Services/Play/Implementations/PlayDataService.cs +++ b/src/Core/Services/Play/Implementations/PlayItemService.cs @@ -5,14 +5,14 @@ using Microsoft.Extensions.Logging; namespace Bit.Core.Services; -public class PlayDataService(IPlayIdService playIdService, IPlayDataRepository playDataRepository, ILogger logger) : IPlayDataService +public class PlayItemService(IPlayIdService playIdService, IPlayItemRepository playItemRepository, ILogger logger) : IPlayItemService { public async Task Record(User user) { if (playIdService.InPlay(out var playId)) { logger.LogInformation("Associating user {UserId} with Play ID {PlayId}", user.Id, playId); - await playDataRepository.CreateAsync(PlayData.Create(user, playId)); + await playItemRepository.CreateAsync(PlayItem.Create(user, playId)); } } public async Task Record(Organization organization) @@ -20,7 +20,7 @@ public class PlayDataService(IPlayIdService playIdService, IPlayDataRepository p if (playIdService.InPlay(out var playId)) { logger.LogInformation("Associating organization {OrganizationId} with Play ID {PlayId}", organization.Id, playId); - await playDataRepository.CreateAsync(PlayData.Create(organization, playId)); + await playItemRepository.CreateAsync(PlayItem.Create(organization, playId)); } } } diff --git a/src/Core/Services/Play/README.md b/src/Core/Services/Play/README.md index a0d9ecfac8..b04b6a13c7 100644 --- a/src/Core/Services/Play/README.md +++ b/src/Core/Services/Play/README.md @@ -11,17 +11,17 @@ enable bulk cleanup via the SeederAPI. 1. Test client sends `x-play-id` header with a unique Play identifier 2. `PlayIdMiddleware` extracts the header and sets it on `IPlayIdService` 3. Repositories check `IPlayIdService.InPlay()` when creating entities -4. `IPlayDataService` records PlayData entries for tracked entities -5. SeederAPI uses PlayData records to bulk delete all entities associated with a PlayId +4. `IPlayItemService` records PlayItem entries for tracked entities +5. SeederAPI uses PlayItem records to bulk delete all entities associated with a PlayId Play services are **only active in Development environments**. ## Classes - **`IPlayIdService`** - Interface for managing Play identifiers in the current request scope -- **`IPlayDataService`** - Interface for tracking entities created during a Play session +- **`IPlayItemService`** - Interface for tracking entities created during a Play session - **`PlayIdService`** - Default scoped implementation for tracking Play sessions per HTTP request - **`NeverPlayIdServices`** - No-op implementation used as fallback when no HttpContext is available - **`PlayIdSingletonService`** - Singleton wrapper that allows singleton services to access scoped PlayIdService via -HttpContext -- **`PlayDataService`** - Implementation that records PlayData entries for entities created during Play sessions + HttpContext +- **`PlayItemService`** - Implementation that records PlayItem entries for entities created during Play sessions diff --git a/src/Infrastructure.Dapper/DapperServiceCollectionExtensions.cs b/src/Infrastructure.Dapper/DapperServiceCollectionExtensions.cs index 4d8b551fe4..dcb0dc1306 100644 --- a/src/Infrastructure.Dapper/DapperServiceCollectionExtensions.cs +++ b/src/Infrastructure.Dapper/DapperServiceCollectionExtensions.cs @@ -51,7 +51,7 @@ public static class DapperServiceCollectionExtensions services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); diff --git a/src/Infrastructure.Dapper/Repositories/PlayDataRepository.cs b/src/Infrastructure.Dapper/Repositories/PlayItemRepository.cs similarity index 69% rename from src/Infrastructure.Dapper/Repositories/PlayDataRepository.cs rename to src/Infrastructure.Dapper/Repositories/PlayItemRepository.cs index 7c5953201a..1fa8e88ce8 100644 --- a/src/Infrastructure.Dapper/Repositories/PlayDataRepository.cs +++ b/src/Infrastructure.Dapper/Repositories/PlayItemRepository.cs @@ -9,22 +9,22 @@ using Microsoft.Data.SqlClient; namespace Bit.Infrastructure.Dapper.Repositories; -public class PlayDataRepository : Repository, IPlayDataRepository +public class PlayItemRepository : Repository, IPlayItemRepository { - public PlayDataRepository(GlobalSettings globalSettings) + public PlayItemRepository(GlobalSettings globalSettings) : this(globalSettings.SqlServer.ConnectionString, globalSettings.SqlServer.ReadOnlyConnectionString) { } - public PlayDataRepository(string connectionString, string readOnlyConnectionString) + public PlayItemRepository(string connectionString, string readOnlyConnectionString) : base(connectionString, readOnlyConnectionString) { } - public async Task> GetByPlayIdAsync(string playId) + public async Task> GetByPlayIdAsync(string playId) { using (var connection = new SqlConnection(ConnectionString)) { - var results = await connection.QueryAsync( - "[dbo].[PlayData_ReadByPlayId]", + var results = await connection.QueryAsync( + "[dbo].[PlayItem_ReadByPlayId]", new { PlayId = playId }, commandType: CommandType.StoredProcedure); @@ -37,7 +37,7 @@ public class PlayDataRepository : Repository, IPlayDataRepositor using (var connection = new SqlConnection(ConnectionString)) { await connection.ExecuteAsync( - "[dbo].[PlayData_DeleteByPlayId]", + "[dbo].[PlayItem_DeleteByPlayId]", new { PlayId = playId }, commandType: CommandType.StoredProcedure); } diff --git a/src/Infrastructure.EntityFramework/Configurations/PlayDataEntityTypeConfiguration.cs b/src/Infrastructure.EntityFramework/Configurations/PlayItemEntityTypeConfiguration.cs similarity index 82% rename from src/Infrastructure.EntityFramework/Configurations/PlayDataEntityTypeConfiguration.cs rename to src/Infrastructure.EntityFramework/Configurations/PlayItemEntityTypeConfiguration.cs index 607b1324ed..91b26e5be4 100644 --- a/src/Infrastructure.EntityFramework/Configurations/PlayDataEntityTypeConfiguration.cs +++ b/src/Infrastructure.EntityFramework/Configurations/PlayItemEntityTypeConfiguration.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace Bit.Infrastructure.EntityFramework.Configurations; -public class PlayDataEntityTypeConfiguration : IEntityTypeConfiguration +public class PlayItemEntityTypeConfiguration : IEntityTypeConfiguration { - public void Configure(EntityTypeBuilder builder) + public void Configure(EntityTypeBuilder builder) { builder .Property(pd => pd.Id) @@ -37,9 +37,9 @@ public class PlayDataEntityTypeConfiguration : IEntityTypeConfiguration(); services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); diff --git a/src/Infrastructure.EntityFramework/Models/PlayData.cs b/src/Infrastructure.EntityFramework/Models/PlayItem.cs similarity index 55% rename from src/Infrastructure.EntityFramework/Models/PlayData.cs rename to src/Infrastructure.EntityFramework/Models/PlayItem.cs index 334555c0d8..3aafebd555 100644 --- a/src/Infrastructure.EntityFramework/Models/PlayData.cs +++ b/src/Infrastructure.EntityFramework/Models/PlayItem.cs @@ -4,16 +4,16 @@ using AutoMapper; namespace Bit.Infrastructure.EntityFramework.Models; -public class PlayData : Core.Entities.PlayData +public class PlayItem : Core.Entities.PlayItem { public virtual User? User { get; set; } public virtual AdminConsole.Models.Organization? Organization { get; set; } } -public class PlayDataMapperProfile : Profile +public class PlayItemMapperProfile : Profile { - public PlayDataMapperProfile() + public PlayItemMapperProfile() { - CreateMap().ReverseMap(); + CreateMap().ReverseMap(); } } diff --git a/src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs b/src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs index 84662a0f64..7b67a63912 100644 --- a/src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs +++ b/src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs @@ -57,7 +57,7 @@ public class DatabaseContext : DbContext public DbSet OrganizationApiKeys { get; set; } public DbSet OrganizationSponsorships { get; set; } public DbSet OrganizationConnections { get; set; } - public DbSet PlayData { get; set; } + public DbSet PlayItem { get; set; } public DbSet OrganizationIntegrations { get; set; } public DbSet OrganizationIntegrationConfigurations { get; set; } public DbSet OrganizationUsers { get; set; } diff --git a/src/Infrastructure.EntityFramework/Repositories/PlayDataRepository.cs b/src/Infrastructure.EntityFramework/Repositories/PlayItemRepository.cs similarity index 69% rename from src/Infrastructure.EntityFramework/Repositories/PlayDataRepository.cs rename to src/Infrastructure.EntityFramework/Repositories/PlayItemRepository.cs index ceee78686e..c8cf207b43 100644 --- a/src/Infrastructure.EntityFramework/Repositories/PlayDataRepository.cs +++ b/src/Infrastructure.EntityFramework/Repositories/PlayItemRepository.cs @@ -8,21 +8,21 @@ using Microsoft.Extensions.DependencyInjection; namespace Bit.Infrastructure.EntityFramework.Repositories; -public class PlayDataRepository : Repository, IPlayDataRepository +public class PlayItemRepository : Repository, IPlayItemRepository { - public PlayDataRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper) - : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.PlayData) + public PlayItemRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper) + : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.PlayItem) { } - public async Task> GetByPlayIdAsync(string playId) + public async Task> GetByPlayIdAsync(string playId) { using (var scope = ServiceScopeFactory.CreateScope()) { var dbContext = GetDatabaseContext(scope); - var playDataEntities = await GetDbSet(dbContext) + var playItemEntities = await GetDbSet(dbContext) .Where(pd => pd.PlayId == playId) .ToListAsync(); - return Mapper.Map>(playDataEntities); + return Mapper.Map>(playItemEntities); } } @@ -35,7 +35,7 @@ public class PlayDataRepository : Repository pd.PlayId == playId) .ToListAsync(); - dbContext.PlayData.RemoveRange(entities); + dbContext.PlayItem.RemoveRange(entities); await dbContext.SaveChangesAsync(); } } diff --git a/src/SharedWeb/Play/Repositories/DapperTestOrganizationTrackingOrganizationRepository.cs b/src/SharedWeb/Play/Repositories/DapperTestOrganizationTrackingOrganizationRepository.cs index b70738989a..0d11d9c5eb 100644 --- a/src/SharedWeb/Play/Repositories/DapperTestOrganizationTrackingOrganizationRepository.cs +++ b/src/SharedWeb/Play/Repositories/DapperTestOrganizationTrackingOrganizationRepository.cs @@ -12,21 +12,21 @@ namespace Bit.SharedWeb.Play.Repositories; /// public class DapperTestOrganizationTrackingOrganizationRepository : OrganizationRepository { - private readonly IPlayDataService _playDataService; + private readonly IPlayItemService _playItemService; public DapperTestOrganizationTrackingOrganizationRepository( - IPlayDataService playDataService, + IPlayItemService playItemService, GlobalSettings globalSettings, ILogger logger) : base(globalSettings, logger) { - _playDataService = playDataService; + _playItemService = playItemService; } public override async Task CreateAsync(Organization obj) { var createdOrganization = await base.CreateAsync(obj); - await _playDataService.Record(createdOrganization); + await _playItemService.Record(createdOrganization); return createdOrganization; } } diff --git a/src/SharedWeb/Play/Repositories/DapperTestUserTrackingUserRepository.cs b/src/SharedWeb/Play/Repositories/DapperTestUserTrackingUserRepository.cs index 9bedeaebc7..97954c0348 100644 --- a/src/SharedWeb/Play/Repositories/DapperTestUserTrackingUserRepository.cs +++ b/src/SharedWeb/Play/Repositories/DapperTestUserTrackingUserRepository.cs @@ -12,22 +12,22 @@ namespace Bit.SharedWeb.Play.Repositories; /// public class DapperTestUserTrackingUserRepository : UserRepository { - private readonly IPlayDataService _playDataService; + private readonly IPlayItemService _playItemService; public DapperTestUserTrackingUserRepository( - IPlayDataService playDataService, + IPlayItemService playItemService, GlobalSettings globalSettings, IDataProtectionProvider dataProtectionProvider) : base(globalSettings, dataProtectionProvider) { - _playDataService = playDataService; + _playItemService = playItemService; } public override async Task CreateAsync(User user) { var createdUser = await base.CreateAsync(user); - await _playDataService.Record(createdUser); + await _playItemService.Record(createdUser); return createdUser; } } diff --git a/src/SharedWeb/Play/Repositories/EFTestOrganizationTrackingOrganizationRepository.cs b/src/SharedWeb/Play/Repositories/EFTestOrganizationTrackingOrganizationRepository.cs index b0c6a28ce7..fdf0e4d685 100644 --- a/src/SharedWeb/Play/Repositories/EFTestOrganizationTrackingOrganizationRepository.cs +++ b/src/SharedWeb/Play/Repositories/EFTestOrganizationTrackingOrganizationRepository.cs @@ -12,22 +12,22 @@ namespace Bit.SharedWeb.Play.Repositories; /// public class EFTestOrganizationTrackingOrganizationRepository : OrganizationRepository { - private readonly IPlayDataService _playDataService; + private readonly IPlayItemService _playItemService; public EFTestOrganizationTrackingOrganizationRepository( - IPlayDataService playDataService, + IPlayItemService playItemService, IServiceScopeFactory serviceScopeFactory, IMapper mapper, ILogger logger) : base(serviceScopeFactory, mapper, logger) { - _playDataService = playDataService; + _playItemService = playItemService; } public override async Task CreateAsync(Core.AdminConsole.Entities.Organization organization) { var createdOrganization = await base.CreateAsync(organization); - await _playDataService.Record(createdOrganization); + await _playItemService.Record(createdOrganization); return createdOrganization; } } diff --git a/src/SharedWeb/Play/Repositories/EFTestUserTrackingUserRepository.cs b/src/SharedWeb/Play/Repositories/EFTestUserTrackingUserRepository.cs index 8d2fb2d502..bafcd17ba0 100644 --- a/src/SharedWeb/Play/Repositories/EFTestUserTrackingUserRepository.cs +++ b/src/SharedWeb/Play/Repositories/EFTestUserTrackingUserRepository.cs @@ -11,21 +11,21 @@ namespace Bit.SharedWeb.Play.Repositories; /// public class EFTestUserTrackingUserRepository : UserRepository { - private readonly IPlayDataService _playDataService; + private readonly IPlayItemService _playItemService; public EFTestUserTrackingUserRepository( - IPlayDataService playDataService, + IPlayItemService playItemService, IServiceScopeFactory serviceScopeFactory, IMapper mapper) : base(serviceScopeFactory, mapper) { - _playDataService = playDataService; + _playItemService = playItemService; } public override async Task CreateAsync(Core.Entities.User user) { var createdUser = await base.CreateAsync(user); - await _playDataService.Record(createdUser); + await _playItemService.Record(createdUser); return createdUser; } } diff --git a/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs b/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs index 3f95e970a1..1bb9cb6c7a 100644 --- a/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs +++ b/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs @@ -132,7 +132,7 @@ public static class ServiceCollectionExtensions // We need the http context accessor to use the Singleton version, which pulls from the scoped version services.AddHttpContextAccessor(); - services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddScoped(); diff --git a/src/Sql/dbo/Stored Procedures/PlayData_Create.sql b/src/Sql/dbo/Stored Procedures/PlayItem_Create.sql similarity index 85% rename from src/Sql/dbo/Stored Procedures/PlayData_Create.sql rename to src/Sql/dbo/Stored Procedures/PlayItem_Create.sql index 9d6c255ba1..cf75d03d10 100644 --- a/src/Sql/dbo/Stored Procedures/PlayData_Create.sql +++ b/src/Sql/dbo/Stored Procedures/PlayItem_Create.sql @@ -1,4 +1,4 @@ -CREATE PROCEDURE [dbo].[PlayData_Create] +CREATE PROCEDURE [dbo].[PlayItem_Create] @Id UNIQUEIDENTIFIER OUTPUT, @PlayId NVARCHAR(256), @UserId UNIQUEIDENTIFIER, @@ -8,7 +8,7 @@ AS BEGIN SET NOCOUNT ON - INSERT INTO [dbo].[PlayData] + INSERT INTO [dbo].[PlayItem] ( [Id], [PlayId], diff --git a/src/Sql/dbo/Stored Procedures/PlayData_DeleteByPlayId.sql b/src/Sql/dbo/Stored Procedures/PlayItem_DeleteByPlayId.sql similarity index 61% rename from src/Sql/dbo/Stored Procedures/PlayData_DeleteByPlayId.sql rename to src/Sql/dbo/Stored Procedures/PlayItem_DeleteByPlayId.sql index 9158cbd3b6..5e2a102e40 100644 --- a/src/Sql/dbo/Stored Procedures/PlayData_DeleteByPlayId.sql +++ b/src/Sql/dbo/Stored Procedures/PlayItem_DeleteByPlayId.sql @@ -1,4 +1,4 @@ -CREATE PROCEDURE [dbo].[PlayData_DeleteByPlayId] +CREATE PROCEDURE [dbo].[PlayItem_DeleteByPlayId] @PlayId NVARCHAR(256) AS BEGIN @@ -6,7 +6,7 @@ BEGIN DELETE FROM - [dbo].[PlayData] + [dbo].[PlayItem] WHERE [PlayId] = @PlayId END diff --git a/src/Sql/dbo/Stored Procedures/PlayData_ReadByPlayId.sql b/src/Sql/dbo/Stored Procedures/PlayItem_ReadByPlayId.sql similarity index 74% rename from src/Sql/dbo/Stored Procedures/PlayData_ReadByPlayId.sql rename to src/Sql/dbo/Stored Procedures/PlayItem_ReadByPlayId.sql index 77d3f7df4f..29592c527b 100644 --- a/src/Sql/dbo/Stored Procedures/PlayData_ReadByPlayId.sql +++ b/src/Sql/dbo/Stored Procedures/PlayItem_ReadByPlayId.sql @@ -1,4 +1,4 @@ -CREATE PROCEDURE [dbo].[PlayData_ReadByPlayId] +CREATE PROCEDURE [dbo].[PlayItem_ReadByPlayId] @PlayId NVARCHAR(256) AS BEGIN @@ -11,7 +11,7 @@ BEGIN [OrganizationId], [CreationDate] FROM - [dbo].[PlayData] + [dbo].[PlayItem] WHERE [PlayId] = @PlayId END diff --git a/src/Sql/dbo/Tables/PlayData.sql b/src/Sql/dbo/Tables/PlayData.sql deleted file mode 100644 index c433805ce8..0000000000 --- a/src/Sql/dbo/Tables/PlayData.sql +++ /dev/null @@ -1,23 +0,0 @@ -CREATE TABLE [dbo].[PlayData] ( - [Id] UNIQUEIDENTIFIER NOT NULL, - [PlayId] NVARCHAR (256) NOT NULL, - [UserId] UNIQUEIDENTIFIER NULL, - [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]) 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)) -); - -GO -CREATE NONCLUSTERED INDEX [IX_PlayData_PlayId] - ON [dbo].[PlayData]([PlayId] ASC); - -GO -CREATE NONCLUSTERED INDEX [IX_PlayData_UserId] - ON [dbo].[PlayData]([UserId] ASC); - -GO -CREATE NONCLUSTERED INDEX [IX_PlayData_OrganizationId] - ON [dbo].[PlayData]([OrganizationId] ASC); diff --git a/src/Sql/dbo/Tables/PlayItem.sql b/src/Sql/dbo/Tables/PlayItem.sql new file mode 100644 index 0000000000..fbf3d2e0dd --- /dev/null +++ b/src/Sql/dbo/Tables/PlayItem.sql @@ -0,0 +1,23 @@ +CREATE TABLE [dbo].[PlayItem] ( + [Id] UNIQUEIDENTIFIER NOT NULL, + [PlayId] NVARCHAR (256) NOT NULL, + [UserId] UNIQUEIDENTIFIER NULL, + [OrganizationId] UNIQUEIDENTIFIER NULL, + [CreationDate] DATETIME2 (7) NOT NULL, + CONSTRAINT [PK_PlayItem] PRIMARY KEY CLUSTERED ([Id] ASC), + CONSTRAINT [FK_PlayItem_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([Id]) ON DELETE CASCADE, + CONSTRAINT [FK_PlayItem_Organization] FOREIGN KEY ([OrganizationId]) REFERENCES [dbo].[Organization] ([Id]) ON DELETE CASCADE, + CONSTRAINT [CK_PlayItem_UserOrOrganization] CHECK (([UserId] IS NOT NULL AND [OrganizationId] IS NULL) OR ([UserId] IS NULL AND [OrganizationId] IS NOT NULL)) +); + +GO +CREATE NONCLUSTERED INDEX [IX_PlayItem_PlayId] + ON [dbo].[PlayItem]([PlayId] ASC); + +GO +CREATE NONCLUSTERED INDEX [IX_PlayItem_UserId] + ON [dbo].[PlayItem]([UserId] ASC); + +GO +CREATE NONCLUSTERED INDEX [IX_PlayItem_OrganizationId] + ON [dbo].[PlayItem]([OrganizationId] ASC); diff --git a/test/Core.Test/Services/PlayDataServiceTests.cs b/test/Core.Test/Services/PlayItemServiceTests.cs similarity index 77% rename from test/Core.Test/Services/PlayDataServiceTests.cs rename to test/Core.Test/Services/PlayItemServiceTests.cs index 83219451b2..02e815be59 100644 --- a/test/Core.Test/Services/PlayDataServiceTests.cs +++ b/test/Core.Test/Services/PlayItemServiceTests.cs @@ -11,14 +11,14 @@ using Xunit; namespace Bit.Core.Test.Services; [SutProviderCustomize] -public class PlayDataServiceTests +public class PlayItemServiceTests { [Theory] [BitAutoData] - public async Task Record_User_WhenInPlay_RecordsPlayData( + public async Task Record_User_WhenInPlay_RecordsPlayItem( string playId, User user, - SutProvider sutProvider) + SutProvider sutProvider) { sutProvider.GetDependency() .InPlay(out Arg.Any()) @@ -30,14 +30,14 @@ public class PlayDataServiceTests await sutProvider.Sut.Record(user); - await sutProvider.GetDependency() + await sutProvider.GetDependency() .Received(1) - .CreateAsync(Arg.Is(pd => + .CreateAsync(Arg.Is(pd => pd.PlayId == playId && pd.UserId == user.Id && pd.OrganizationId == null)); - sutProvider.GetDependency>() + sutProvider.GetDependency>() .Received(1) .Log( LogLevel.Information, @@ -49,9 +49,9 @@ public class PlayDataServiceTests [Theory] [BitAutoData] - public async Task Record_User_WhenNotInPlay_DoesNotRecordPlayData( + public async Task Record_User_WhenNotInPlay_DoesNotRecordPlayItem( User user, - SutProvider sutProvider) + SutProvider sutProvider) { sutProvider.GetDependency() .InPlay(out Arg.Any()) @@ -63,11 +63,11 @@ public class PlayDataServiceTests await sutProvider.Sut.Record(user); - await sutProvider.GetDependency() + await sutProvider.GetDependency() .DidNotReceive() - .CreateAsync(Arg.Any()); + .CreateAsync(Arg.Any()); - sutProvider.GetDependency>() + sutProvider.GetDependency>() .DidNotReceive() .Log( LogLevel.Information, @@ -79,10 +79,10 @@ public class PlayDataServiceTests [Theory] [BitAutoData] - public async Task Record_Organization_WhenInPlay_RecordsPlayData( + public async Task Record_Organization_WhenInPlay_RecordsPlayItem( string playId, Organization organization, - SutProvider sutProvider) + SutProvider sutProvider) { sutProvider.GetDependency() .InPlay(out Arg.Any()) @@ -94,14 +94,14 @@ public class PlayDataServiceTests await sutProvider.Sut.Record(organization); - await sutProvider.GetDependency() + await sutProvider.GetDependency() .Received(1) - .CreateAsync(Arg.Is(pd => + .CreateAsync(Arg.Is(pd => pd.PlayId == playId && pd.OrganizationId == organization.Id && pd.UserId == null)); - sutProvider.GetDependency>() + sutProvider.GetDependency>() .Received(1) .Log( LogLevel.Information, @@ -113,9 +113,9 @@ public class PlayDataServiceTests [Theory] [BitAutoData] - public async Task Record_Organization_WhenNotInPlay_DoesNotRecordPlayData( + public async Task Record_Organization_WhenNotInPlay_DoesNotRecordPlayItem( Organization organization, - SutProvider sutProvider) + SutProvider sutProvider) { sutProvider.GetDependency() .InPlay(out Arg.Any()) @@ -127,11 +127,11 @@ public class PlayDataServiceTests await sutProvider.Sut.Record(organization); - await sutProvider.GetDependency() + await sutProvider.GetDependency() .DidNotReceive() - .CreateAsync(Arg.Any()); + .CreateAsync(Arg.Any()); - sutProvider.GetDependency>() + sutProvider.GetDependency>() .DidNotReceive() .Log( LogLevel.Information, diff --git a/util/Migrator/DbScripts/2025-11-04_00_PlayData.sql b/util/Migrator/DbScripts/2025-11-04_00_PlayItem.sql similarity index 54% rename from util/Migrator/DbScripts/2025-11-04_00_PlayData.sql rename to util/Migrator/DbScripts/2025-11-04_00_PlayItem.sql index 492e8a5143..789538cb1c 100644 --- a/util/Migrator/DbScripts/2025-11-04_00_PlayData.sql +++ b/util/Migrator/DbScripts/2025-11-04_00_PlayItem.sql @@ -1,31 +1,31 @@ --- Create PlayData table -IF OBJECT_ID('dbo.PlayData') IS NULL +-- Create PlayItem table +IF OBJECT_ID('dbo.PlayItem') IS NULL BEGIN - CREATE TABLE [dbo].[PlayData] ( + CREATE TABLE [dbo].[PlayItem] ( [Id] UNIQUEIDENTIFIER NOT NULL, [PlayId] NVARCHAR (256) NOT NULL, [UserId] UNIQUEIDENTIFIER NULL, [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]) 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)) + CONSTRAINT [PK_PlayItem] PRIMARY KEY CLUSTERED ([Id] ASC), + CONSTRAINT [FK_PlayItem_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([Id]) ON DELETE CASCADE, + CONSTRAINT [FK_PlayItem_Organization] FOREIGN KEY ([OrganizationId]) REFERENCES [dbo].[Organization] ([Id]) ON DELETE CASCADE, + CONSTRAINT [CK_PlayItem_UserOrOrganization] CHECK (([UserId] IS NOT NULL AND [OrganizationId] IS NULL) OR ([UserId] IS NULL AND [OrganizationId] IS NOT NULL)) ); - CREATE NONCLUSTERED INDEX [IX_PlayData_PlayId] - ON [dbo].[PlayData]([PlayId] ASC); + CREATE NONCLUSTERED INDEX [IX_PlayItem_PlayId] + ON [dbo].[PlayItem]([PlayId] ASC); - CREATE NONCLUSTERED INDEX [IX_PlayData_UserId] - ON [dbo].[PlayData]([UserId] ASC); + CREATE NONCLUSTERED INDEX [IX_PlayItem_UserId] + ON [dbo].[PlayItem]([UserId] ASC); - CREATE NONCLUSTERED INDEX [IX_PlayData_OrganizationId] - ON [dbo].[PlayData]([OrganizationId] ASC); + CREATE NONCLUSTERED INDEX [IX_PlayItem_OrganizationId] + ON [dbo].[PlayItem]([OrganizationId] ASC); END GO --- Create PlayData_Create stored procedure -CREATE OR ALTER PROCEDURE [dbo].[PlayData_Create] +-- Create PlayItem_Create stored procedure +CREATE OR ALTER PROCEDURE [dbo].[PlayItem_Create] @Id UNIQUEIDENTIFIER OUTPUT, @PlayId NVARCHAR(256), @UserId UNIQUEIDENTIFIER, @@ -35,7 +35,7 @@ AS BEGIN SET NOCOUNT ON - INSERT INTO [dbo].[PlayData] + INSERT INTO [dbo].[PlayItem] ( [Id], [PlayId], @@ -54,8 +54,8 @@ BEGIN END GO --- Create PlayData_ReadByPlayId stored procedure -CREATE OR ALTER PROCEDURE [dbo].[PlayData_ReadByPlayId] +-- Create PlayItem_ReadByPlayId stored procedure +CREATE OR ALTER PROCEDURE [dbo].[PlayItem_ReadByPlayId] @PlayId NVARCHAR(256) AS BEGIN @@ -68,14 +68,14 @@ BEGIN [OrganizationId], [CreationDate] FROM - [dbo].[PlayData] + [dbo].[PlayItem] WHERE [PlayId] = @PlayId END GO --- Create PlayData_DeleteByPlayId stored procedure -CREATE OR ALTER PROCEDURE [dbo].[PlayData_DeleteByPlayId] +-- Create PlayItem_DeleteByPlayId stored procedure +CREATE OR ALTER PROCEDURE [dbo].[PlayItem_DeleteByPlayId] @PlayId NVARCHAR(256) AS BEGIN @@ -83,7 +83,7 @@ BEGIN DELETE FROM - [dbo].[PlayData] + [dbo].[PlayItem] WHERE [PlayId] = @PlayId END diff --git a/util/MySqlMigrations/Migrations/20251118024031_PlayData.Designer.cs b/util/MySqlMigrations/Migrations/20251118024031_PlayItem.Designer.cs similarity index 99% rename from util/MySqlMigrations/Migrations/20251118024031_PlayData.Designer.cs rename to util/MySqlMigrations/Migrations/20251118024031_PlayItem.Designer.cs index 3cecfd2664..775479dc58 100644 --- a/util/MySqlMigrations/Migrations/20251118024031_PlayData.Designer.cs +++ b/util/MySqlMigrations/Migrations/20251118024031_PlayItem.Designer.cs @@ -12,8 +12,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace Bit.MySqlMigrations.Migrations { [DbContext(typeof(DatabaseContext))] - [Migration("20251118024031_PlayData")] - partial class PlayData + [Migration("20251118024031_PlayItem")] + partial class PlayItem { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -1624,7 +1624,7 @@ namespace Bit.MySqlMigrations.Migrations b.ToTable("OrganizationUser", (string)null); }); - modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayData", b => + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayItem", b => { b.Property("Id") .HasColumnType("char(36)"); @@ -1654,9 +1654,9 @@ namespace Bit.MySqlMigrations.Migrations b.HasIndex("UserId") .HasAnnotation("SqlServer:Clustered", false); - b.ToTable("PlayData", null, t => + b.ToTable("PlayItem", null, t => { - t.HasCheckConstraint("CK_PlayData_UserOrOrganization", "(\"UserId\" IS NOT NULL AND \"OrganizationId\" IS NULL) OR (\"UserId\" IS NULL AND \"OrganizationId\" IS NOT NULL)"); + t.HasCheckConstraint("CK_PlayItem_UserOrOrganization", "(\"UserId\" IS NOT NULL AND \"OrganizationId\" IS NULL) OR (\"UserId\" IS NULL AND \"OrganizationId\" IS NOT NULL)"); }); }); @@ -3033,7 +3033,7 @@ namespace Bit.MySqlMigrations.Migrations b.Navigation("User"); }); - modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayData", b => + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayItem", b => { b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") .WithMany() diff --git a/util/MySqlMigrations/Migrations/20251118024031_PlayData.cs b/util/MySqlMigrations/Migrations/20251118024031_PlayItem.cs similarity index 81% rename from util/MySqlMigrations/Migrations/20251118024031_PlayData.cs rename to util/MySqlMigrations/Migrations/20251118024031_PlayItem.cs index 785a0df196..ac95ac5412 100644 --- a/util/MySqlMigrations/Migrations/20251118024031_PlayData.cs +++ b/util/MySqlMigrations/Migrations/20251118024031_PlayItem.cs @@ -5,7 +5,7 @@ namespace Bit.MySqlMigrations.Migrations; /// -public partial class PlayData : Migration +public partial class PlayItem : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) @@ -19,7 +19,7 @@ public partial class PlayData : Migration oldType: "int"); migrationBuilder.CreateTable( - name: "PlayData", + name: "PlayItem", columns: table => new { Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), @@ -31,16 +31,16 @@ public partial class PlayData : Migration }, constraints: table => { - table.PrimaryKey("PK_PlayData", x => x.Id); - table.CheckConstraint("CK_PlayData_UserOrOrganization", "(\"UserId\" IS NOT NULL AND \"OrganizationId\" IS NULL) OR (\"UserId\" IS NULL AND \"OrganizationId\" IS NOT NULL)"); + table.PrimaryKey("PK_PlayItem", x => x.Id); + table.CheckConstraint("CK_PlayItem_UserOrOrganization", "(\"UserId\" IS NOT NULL AND \"OrganizationId\" IS NULL) OR (\"UserId\" IS NULL AND \"OrganizationId\" IS NOT NULL)"); table.ForeignKey( - name: "FK_PlayData_Organization_OrganizationId", + name: "FK_PlayItem_Organization_OrganizationId", column: x => x.OrganizationId, principalTable: "Organization", principalColumn: "Id", onDelete: ReferentialAction.Cascade); table.ForeignKey( - name: "FK_PlayData_User_UserId", + name: "FK_PlayItem_User_UserId", column: x => x.UserId, principalTable: "User", principalColumn: "Id", @@ -49,18 +49,18 @@ public partial class PlayData : Migration .Annotation("MySql:CharSet", "utf8mb4"); migrationBuilder.CreateIndex( - name: "IX_PlayData_OrganizationId", - table: "PlayData", + name: "IX_PlayItem_OrganizationId", + table: "PlayItem", column: "OrganizationId"); migrationBuilder.CreateIndex( - name: "IX_PlayData_PlayId", - table: "PlayData", + name: "IX_PlayItem_PlayId", + table: "PlayItem", column: "PlayId"); migrationBuilder.CreateIndex( - name: "IX_PlayData_UserId", - table: "PlayData", + name: "IX_PlayItem_UserId", + table: "PlayItem", column: "UserId"); } @@ -68,7 +68,7 @@ public partial class PlayData : Migration protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropTable( - name: "PlayData"); + name: "PlayItem"); migrationBuilder.AlterColumn( name: "WaitTimeDays", diff --git a/util/MySqlMigrations/Migrations/DatabaseContextModelSnapshot.cs b/util/MySqlMigrations/Migrations/DatabaseContextModelSnapshot.cs index d0a7a61082..7720418b7c 100644 --- a/util/MySqlMigrations/Migrations/DatabaseContextModelSnapshot.cs +++ b/util/MySqlMigrations/Migrations/DatabaseContextModelSnapshot.cs @@ -1627,7 +1627,7 @@ namespace Bit.MySqlMigrations.Migrations b.ToTable("OrganizationUser", (string)null); }); - modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayData", b => + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayItem", b => { b.Property("Id") .HasColumnType("char(36)"); @@ -1657,9 +1657,9 @@ namespace Bit.MySqlMigrations.Migrations b.HasIndex("UserId") .HasAnnotation("SqlServer:Clustered", false); - b.ToTable("PlayData", null, t => + b.ToTable("PlayItem", null, t => { - t.HasCheckConstraint("CK_PlayData_UserOrOrganization", "(\"UserId\" IS NOT NULL AND \"OrganizationId\" IS NULL) OR (\"UserId\" IS NULL AND \"OrganizationId\" IS NOT NULL)"); + t.HasCheckConstraint("CK_PlayItem_UserOrOrganization", "(\"UserId\" IS NOT NULL AND \"OrganizationId\" IS NULL) OR (\"UserId\" IS NULL AND \"OrganizationId\" IS NOT NULL)"); }); }); @@ -3039,7 +3039,7 @@ namespace Bit.MySqlMigrations.Migrations b.Navigation("User"); }); - modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayData", b => + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayItem", b => { b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") .WithMany() diff --git a/util/PostgresMigrations/Migrations/20251118024041_PlayData.Designer.cs b/util/PostgresMigrations/Migrations/20251118024041_PlayItem.Designer.cs similarity index 99% rename from util/PostgresMigrations/Migrations/20251118024041_PlayData.Designer.cs rename to util/PostgresMigrations/Migrations/20251118024041_PlayItem.Designer.cs index 020ea27c1e..6ad07209ea 100644 --- a/util/PostgresMigrations/Migrations/20251118024041_PlayData.Designer.cs +++ b/util/PostgresMigrations/Migrations/20251118024041_PlayItem.Designer.cs @@ -12,8 +12,8 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace Bit.PostgresMigrations.Migrations { [DbContext(typeof(DatabaseContext))] - [Migration("20251118024041_PlayData")] - partial class PlayData + [Migration("20251118024041_PlayItem")] + partial class PlayItem { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -1629,7 +1629,7 @@ namespace Bit.PostgresMigrations.Migrations b.ToTable("OrganizationUser", (string)null); }); - modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayData", b => + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayItem", b => { b.Property("Id") .HasColumnType("uuid"); @@ -1659,9 +1659,9 @@ namespace Bit.PostgresMigrations.Migrations b.HasIndex("UserId") .HasAnnotation("SqlServer:Clustered", false); - b.ToTable("PlayData", null, t => + b.ToTable("PlayItem", null, t => { - t.HasCheckConstraint("CK_PlayData_UserOrOrganization", "(\"UserId\" IS NOT NULL AND \"OrganizationId\" IS NULL) OR (\"UserId\" IS NULL AND \"OrganizationId\" IS NOT NULL)"); + t.HasCheckConstraint("CK_PlayItem_UserOrOrganization", "(\"UserId\" IS NOT NULL AND \"OrganizationId\" IS NULL) OR (\"UserId\" IS NULL AND \"OrganizationId\" IS NOT NULL)"); }); }); @@ -3039,7 +3039,7 @@ namespace Bit.PostgresMigrations.Migrations b.Navigation("User"); }); - modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayData", b => + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayItem", b => { b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") .WithMany() diff --git a/util/PostgresMigrations/Migrations/20251118024041_PlayData.cs b/util/PostgresMigrations/Migrations/20251118024041_PlayItem.cs similarity index 80% rename from util/PostgresMigrations/Migrations/20251118024041_PlayData.cs rename to util/PostgresMigrations/Migrations/20251118024041_PlayItem.cs index 9feb83d14b..9b32fb4a27 100644 --- a/util/PostgresMigrations/Migrations/20251118024041_PlayData.cs +++ b/util/PostgresMigrations/Migrations/20251118024041_PlayItem.cs @@ -5,7 +5,7 @@ namespace Bit.PostgresMigrations.Migrations; /// -public partial class PlayData : Migration +public partial class PlayItem : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) @@ -19,7 +19,7 @@ public partial class PlayData : Migration oldType: "integer"); migrationBuilder.CreateTable( - name: "PlayData", + name: "PlayItem", columns: table => new { Id = table.Column(type: "uuid", nullable: false), @@ -30,16 +30,16 @@ public partial class PlayData : Migration }, constraints: table => { - table.PrimaryKey("PK_PlayData", x => x.Id); - table.CheckConstraint("CK_PlayData_UserOrOrganization", "(\"UserId\" IS NOT NULL AND \"OrganizationId\" IS NULL) OR (\"UserId\" IS NULL AND \"OrganizationId\" IS NOT NULL)"); + table.PrimaryKey("PK_PlayItem", x => x.Id); + table.CheckConstraint("CK_PlayItem_UserOrOrganization", "(\"UserId\" IS NOT NULL AND \"OrganizationId\" IS NULL) OR (\"UserId\" IS NULL AND \"OrganizationId\" IS NOT NULL)"); table.ForeignKey( - name: "FK_PlayData_Organization_OrganizationId", + name: "FK_PlayItem_Organization_OrganizationId", column: x => x.OrganizationId, principalTable: "Organization", principalColumn: "Id", onDelete: ReferentialAction.Cascade); table.ForeignKey( - name: "FK_PlayData_User_UserId", + name: "FK_PlayItem_User_UserId", column: x => x.UserId, principalTable: "User", principalColumn: "Id", @@ -47,18 +47,18 @@ public partial class PlayData : Migration }); migrationBuilder.CreateIndex( - name: "IX_PlayData_OrganizationId", - table: "PlayData", + name: "IX_PlayItem_OrganizationId", + table: "PlayItem", column: "OrganizationId"); migrationBuilder.CreateIndex( - name: "IX_PlayData_PlayId", - table: "PlayData", + name: "IX_PlayItem_PlayId", + table: "PlayItem", column: "PlayId"); migrationBuilder.CreateIndex( - name: "IX_PlayData_UserId", - table: "PlayData", + name: "IX_PlayItem_UserId", + table: "PlayItem", column: "UserId"); } @@ -66,7 +66,7 @@ public partial class PlayData : Migration protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropTable( - name: "PlayData"); + name: "PlayItem"); migrationBuilder.AlterColumn( name: "WaitTimeDays", diff --git a/util/PostgresMigrations/Migrations/DatabaseContextModelSnapshot.cs b/util/PostgresMigrations/Migrations/DatabaseContextModelSnapshot.cs index 6a9733d077..eb37177076 100644 --- a/util/PostgresMigrations/Migrations/DatabaseContextModelSnapshot.cs +++ b/util/PostgresMigrations/Migrations/DatabaseContextModelSnapshot.cs @@ -1632,7 +1632,7 @@ namespace Bit.PostgresMigrations.Migrations b.ToTable("OrganizationUser", (string)null); }); - modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayData", b => + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayItem", b => { b.Property("Id") .HasColumnType("uuid"); @@ -1662,9 +1662,9 @@ namespace Bit.PostgresMigrations.Migrations b.HasIndex("UserId") .HasAnnotation("SqlServer:Clustered", false); - b.ToTable("PlayData", null, t => + b.ToTable("PlayItem", null, t => { - t.HasCheckConstraint("CK_PlayData_UserOrOrganization", "(\"UserId\" IS NOT NULL AND \"OrganizationId\" IS NULL) OR (\"UserId\" IS NULL AND \"OrganizationId\" IS NOT NULL)"); + t.HasCheckConstraint("CK_PlayItem_UserOrOrganization", "(\"UserId\" IS NOT NULL AND \"OrganizationId\" IS NULL) OR (\"UserId\" IS NULL AND \"OrganizationId\" IS NOT NULL)"); }); }); @@ -3045,7 +3045,7 @@ namespace Bit.PostgresMigrations.Migrations b.Navigation("User"); }); - modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayData", b => + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayItem", b => { b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") .WithMany() diff --git a/util/SeederApi/Commands/DestroySceneCommand.cs b/util/SeederApi/Commands/DestroySceneCommand.cs index f70fd861fc..0e0f4edd6d 100644 --- a/util/SeederApi/Commands/DestroySceneCommand.cs +++ b/util/SeederApi/Commands/DestroySceneCommand.cs @@ -9,16 +9,16 @@ public class DestroySceneCommand( DatabaseContext databaseContext, ILogger logger, IUserRepository userRepository, - IPlayDataRepository playDataRepository, + IPlayItemRepository playItemRepository, IOrganizationRepository organizationRepository) : IDestroySceneCommand { public async Task DestroyAsync(string playId) { - // Note, delete cascade will remove PlayData entries + // Note, delete cascade will remove PlayItem entries - var playData = await playDataRepository.GetByPlayIdAsync(playId); - var userIds = playData.Select(pd => pd.UserId).Distinct().ToList(); - var organizationIds = playData.Select(pd => pd.OrganizationId).Distinct().ToList(); + var playItem = await playItemRepository.GetByPlayIdAsync(playId); + var userIds = playItem.Select(pd => pd.UserId).Distinct().ToList(); + var organizationIds = playItem.Select(pd => pd.OrganizationId).Distinct().ToList(); // Delete Users before Organizations to respect foreign key constraints if (userIds.Count > 0) diff --git a/util/SeederApi/Queries/GetAllPlayIdsQuery.cs b/util/SeederApi/Queries/GetAllPlayIdsQuery.cs index c21b5ba6a3..7bc72e5b07 100644 --- a/util/SeederApi/Queries/GetAllPlayIdsQuery.cs +++ b/util/SeederApi/Queries/GetAllPlayIdsQuery.cs @@ -7,7 +7,7 @@ public class GetAllPlayIdsQuery(DatabaseContext databaseContext) : IGetAllPlayId { public List GetAllPlayIds() { - return databaseContext.PlayData + return databaseContext.PlayItem .Select(pd => pd.PlayId) .Distinct() .ToList(); diff --git a/util/SeederApi/README.md b/util/SeederApi/README.md index 2d67faf768..a5a5d4ab9f 100644 --- a/util/SeederApi/README.md +++ b/util/SeederApi/README.md @@ -85,9 +85,7 @@ curl -X POST http://localhost:5000/query \ **Response:** ```json -[ - "/accept-emergency?..." -] +["/accept-emergency?..."] ``` ### Destroying Seeded Data @@ -148,7 +146,7 @@ The SeederApi requires the following configuration: ## Play ID Tracking Certain entities such as Users and Organizations are tracked when created by a request including a PlayId. This enables -entities to be deleted after using the PlayId. +entities to be deleted after using the PlayId. ### The X-Play-Id Header @@ -168,7 +166,7 @@ When `TestPlayIdTrackingEnabled` is enabled in GlobalSettings, the `PlayIdMiddle 1. **Extracts** the `X-Play-Id` header from incoming requests 2. **Sets** the play ID in the `PlayIdService` for the request scope 3. **Tracks** all entities (users, organizations, etc.) created during the request -4. **Associates** them with the play ID in the `PlayData` table +4. **Associates** them with the play ID in the `PlayItem` table 5. **Enables** complete cleanup via the delete endpoints This tracking works for **any API request** that includes the `X-Play-Id` header, not just SeederApi endpoints. This means diff --git a/util/SqliteMigrations/Migrations/20251118024036_PlayData.Designer.cs b/util/SqliteMigrations/Migrations/20251118024036_PlayItem.Designer.cs similarity index 99% rename from util/SqliteMigrations/Migrations/20251118024036_PlayData.Designer.cs rename to util/SqliteMigrations/Migrations/20251118024036_PlayItem.Designer.cs index 79c859b6e6..5819502470 100644 --- a/util/SqliteMigrations/Migrations/20251118024036_PlayData.Designer.cs +++ b/util/SqliteMigrations/Migrations/20251118024036_PlayItem.Designer.cs @@ -11,8 +11,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace Bit.SqliteMigrations.Migrations { [DbContext(typeof(DatabaseContext))] - [Migration("20251118024036_PlayData")] - partial class PlayData + [Migration("20251118024036_PlayItem")] + partial class PlayItem { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -1613,7 +1613,7 @@ namespace Bit.SqliteMigrations.Migrations b.ToTable("OrganizationUser", (string)null); }); - modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayData", b => + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayItem", b => { b.Property("Id") .HasColumnType("TEXT"); @@ -1643,9 +1643,9 @@ namespace Bit.SqliteMigrations.Migrations b.HasIndex("UserId") .HasAnnotation("SqlServer:Clustered", false); - b.ToTable("PlayData", null, t => + b.ToTable("PlayItem", null, t => { - t.HasCheckConstraint("CK_PlayData_UserOrOrganization", "(\"UserId\" IS NOT NULL AND \"OrganizationId\" IS NULL) OR (\"UserId\" IS NULL AND \"OrganizationId\" IS NOT NULL)"); + t.HasCheckConstraint("CK_PlayItem_UserOrOrganization", "(\"UserId\" IS NOT NULL AND \"OrganizationId\" IS NULL) OR (\"UserId\" IS NULL AND \"OrganizationId\" IS NOT NULL)"); }); }); @@ -3022,7 +3022,7 @@ namespace Bit.SqliteMigrations.Migrations b.Navigation("User"); }); - modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayData", b => + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayItem", b => { b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") .WithMany() diff --git a/util/SqliteMigrations/Migrations/20251118024036_PlayData.cs b/util/SqliteMigrations/Migrations/20251118024036_PlayItem.cs similarity index 75% rename from util/SqliteMigrations/Migrations/20251118024036_PlayData.cs rename to util/SqliteMigrations/Migrations/20251118024036_PlayItem.cs index f15cd4d9f2..ec949267b7 100644 --- a/util/SqliteMigrations/Migrations/20251118024036_PlayData.cs +++ b/util/SqliteMigrations/Migrations/20251118024036_PlayItem.cs @@ -5,13 +5,13 @@ namespace Bit.SqliteMigrations.Migrations; /// -public partial class PlayData : Migration +public partial class PlayItem : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.CreateTable( - name: "PlayData", + name: "PlayItem", columns: table => new { Id = table.Column(type: "TEXT", nullable: false), @@ -22,16 +22,16 @@ public partial class PlayData : Migration }, constraints: table => { - table.PrimaryKey("PK_PlayData", x => x.Id); - table.CheckConstraint("CK_PlayData_UserOrOrganization", "(\"UserId\" IS NOT NULL AND \"OrganizationId\" IS NULL) OR (\"UserId\" IS NULL AND \"OrganizationId\" IS NOT NULL)"); + table.PrimaryKey("PK_PlayItem", x => x.Id); + table.CheckConstraint("CK_PlayItem_UserOrOrganization", "(\"UserId\" IS NOT NULL AND \"OrganizationId\" IS NULL) OR (\"UserId\" IS NULL AND \"OrganizationId\" IS NOT NULL)"); table.ForeignKey( - name: "FK_PlayData_Organization_OrganizationId", + name: "FK_PlayItem_Organization_OrganizationId", column: x => x.OrganizationId, principalTable: "Organization", principalColumn: "Id", onDelete: ReferentialAction.Cascade); table.ForeignKey( - name: "FK_PlayData_User_UserId", + name: "FK_PlayItem_User_UserId", column: x => x.UserId, principalTable: "User", principalColumn: "Id", @@ -39,18 +39,18 @@ public partial class PlayData : Migration }); migrationBuilder.CreateIndex( - name: "IX_PlayData_OrganizationId", - table: "PlayData", + name: "IX_PlayItem_OrganizationId", + table: "PlayItem", column: "OrganizationId"); migrationBuilder.CreateIndex( - name: "IX_PlayData_PlayId", - table: "PlayData", + name: "IX_PlayItem_PlayId", + table: "PlayItem", column: "PlayId"); migrationBuilder.CreateIndex( - name: "IX_PlayData_UserId", - table: "PlayData", + name: "IX_PlayItem_UserId", + table: "PlayItem", column: "UserId"); } @@ -58,6 +58,6 @@ public partial class PlayData : Migration protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropTable( - name: "PlayData"); + name: "PlayItem"); } } diff --git a/util/SqliteMigrations/Migrations/DatabaseContextModelSnapshot.cs b/util/SqliteMigrations/Migrations/DatabaseContextModelSnapshot.cs index 64427fb108..d96b3eb3f0 100644 --- a/util/SqliteMigrations/Migrations/DatabaseContextModelSnapshot.cs +++ b/util/SqliteMigrations/Migrations/DatabaseContextModelSnapshot.cs @@ -1616,7 +1616,7 @@ namespace Bit.SqliteMigrations.Migrations b.ToTable("OrganizationUser", (string)null); }); - modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayData", b => + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayItem", b => { b.Property("Id") .HasColumnType("TEXT"); @@ -1646,9 +1646,9 @@ namespace Bit.SqliteMigrations.Migrations b.HasIndex("UserId") .HasAnnotation("SqlServer:Clustered", false); - b.ToTable("PlayData", null, t => + b.ToTable("PlayItem", null, t => { - t.HasCheckConstraint("CK_PlayData_UserOrOrganization", "(\"UserId\" IS NOT NULL AND \"OrganizationId\" IS NULL) OR (\"UserId\" IS NULL AND \"OrganizationId\" IS NOT NULL)"); + t.HasCheckConstraint("CK_PlayItem_UserOrOrganization", "(\"UserId\" IS NOT NULL AND \"OrganizationId\" IS NULL) OR (\"UserId\" IS NULL AND \"OrganizationId\" IS NOT NULL)"); }); }); @@ -3028,7 +3028,7 @@ namespace Bit.SqliteMigrations.Migrations b.Navigation("User"); }); - modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayData", b => + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.PlayItem", b => { b.HasOne("Bit.Infrastructure.EntityFramework.AdminConsole.Models.Organization", "Organization") .WithMany()