diff --git a/src/Core/Services/Implementations/PlayIdService.cs b/src/Core/Services/Implementations/PlayIdService.cs index 0c64f1dd14..4549631ebb 100644 --- a/src/Core/Services/Implementations/PlayIdService.cs +++ b/src/Core/Services/Implementations/PlayIdService.cs @@ -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(); + } + } + + 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; + } + } +} diff --git a/src/Infrastructure.EntityFramework/Models/SeededData.cs b/src/Infrastructure.EntityFramework/Models/SeededData.cs deleted file mode 100644 index 3a7805c399..0000000000 --- a/src/Infrastructure.EntityFramework/Models/SeededData.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Bit.Infrastructure.EntityFramework.Models; - -public class SeededData -{ - public Guid Id { get; set; } - public required string RecipeName { get; set; } - /// - /// JSON blob containing all - /// - public required string Data { get; set; } - public DateTime CreationDate { get; set; } -} diff --git a/src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs b/src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs index f856501de1..84662a0f64 100644 --- a/src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs +++ b/src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs @@ -90,7 +90,6 @@ public class DatabaseContext : DbContext public DbSet OrganizationInstallations { get; set; } public DbSet OrganizationReports { get; set; } public DbSet OrganizationApplications { get; set; } - public DbSet SeededData { get; set; } protected override void OnModelCreating(ModelBuilder builder) { diff --git a/src/SharedWeb/Utilities/PlayIdMiddleware.cs b/src/SharedWeb/Utilities/PlayIdMiddleware.cs index 4f3c55f43c..848d2ec50a 100644 --- a/src/SharedWeb/Utilities/PlayIdMiddleware.cs +++ b/src/SharedWeb/Utilities/PlayIdMiddleware.cs @@ -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)) { diff --git a/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs b/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs index 6952ecb149..2ee8d5b572 100644 --- a/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs +++ b/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs @@ -119,8 +119,11 @@ public static class ServiceCollectionExtensions } // Include PlayIdService for tracking Play Ids in repositories - services.AddScoped(); + // We need the http context accessor to use the Singleton version, which pulls from the scoped version + services.AddHttpContextAccessor(); + services.AddSingleton(); + services.AddScoped(); return provider; } diff --git a/src/Sql/dbo/Tables/PlayData.sql b/src/Sql/dbo/Tables/PlayData.sql index 5d5e776938..c433805ce8 100644 --- a/src/Sql/dbo/Tables/PlayData.sql +++ b/src/Sql/dbo/Tables/PlayData.sql @@ -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)) ); diff --git a/src/Sql/dbo/Tables/SeededData.sql b/src/Sql/dbo/Tables/SeededData.sql deleted file mode 100644 index b1e1d65821..0000000000 --- a/src/Sql/dbo/Tables/SeededData.sql +++ /dev/null @@ -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, -); diff --git a/util/Migrator/DbScripts/2025-10-07_00_SeededData.sql b/util/Migrator/DbScripts/2025-10-07_00_SeededData.sql deleted file mode 100644 index c70091240e..0000000000 --- a/util/Migrator/DbScripts/2025-10-07_00_SeededData.sql +++ /dev/null @@ -1,10 +0,0 @@ -IF OBJECT_ID('dbo.SeededData') IS NULL -BEGIN - CREATE TABLE [dbo].[SeededData] ( - [Id] UNIQUEIDENTIFIER NOT NULL, - [RecipeName] NVARCHAR (MAX) NOT NULL, - [Data] NVARCHAR (MAX) NULL, - [CreationDate] DATETIME2 (7) NOT NULL, - ); -END -GO diff --git a/util/Migrator/DbScripts/2025-11-04_00_PlayData.sql b/util/Migrator/DbScripts/2025-11-04_00_PlayData.sql index cc8a8146a9..4c9468ed29 100644 --- a/util/Migrator/DbScripts/2025-11-04_00_PlayData.sql +++ b/util/Migrator/DbScripts/2025-11-04_00_PlayData.sql @@ -8,8 +8,8 @@ BEGIN [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)) ); diff --git a/util/Seeder/Factories/OrganizationSeeder.cs b/util/Seeder/Factories/OrganizationSeeder.cs index f6f05d9525..331d359bfc 100644 --- a/util/Seeder/Factories/OrganizationSeeder.cs +++ b/util/Seeder/Factories/OrganizationSeeder.cs @@ -1,7 +1,7 @@ using Bit.Core.Billing.Enums; +using Bit.Core.Entities; using Bit.Core.Enums; using Bit.Infrastructure.EntityFramework.AdminConsole.Models; -using Bit.Infrastructure.EntityFramework.Models; namespace Bit.Seeder.Factories; diff --git a/util/Seeder/Factories/UserSeeder.cs b/util/Seeder/Factories/UserSeeder.cs index 389e807656..dd5fc159c0 100644 --- a/util/Seeder/Factories/UserSeeder.cs +++ b/util/Seeder/Factories/UserSeeder.cs @@ -1,6 +1,6 @@ -using Bit.Core.Enums; +using Bit.Core.Entities; +using Bit.Core.Enums; using Bit.Core.Utilities; -using Bit.Infrastructure.EntityFramework.Models; using Bit.RustSDK; using Microsoft.AspNetCore.Identity; diff --git a/util/Seeder/IScene.cs b/util/Seeder/IScene.cs index b791ee22d8..257f475409 100644 --- a/util/Seeder/IScene.cs +++ b/util/Seeder/IScene.cs @@ -3,7 +3,7 @@ public interface IScene { Type GetRequestType(); - SceneResult Seed(object request); + Task> SeedAsync(object request); } /// @@ -12,19 +12,19 @@ public interface IScene /// public interface IScene : IScene where TRequest : class { - SceneResult Seed(TRequest request); + Task SeedAsync(TRequest request); Type IScene.GetRequestType() => typeof(TRequest); - SceneResult IScene.Seed(object request) + async Task> IScene.SeedAsync(object request) { - var result = Seed((TRequest)request); - return new SceneResult(mangleMap: result.MangleMap, trackedEntities: result.TrackedEntities); + var result = await SeedAsync((TRequest)request); + return new SceneResult(mangleMap: result.MangleMap); } } public interface IScene : IScene where TRequest : class where TResult : class { - SceneResult Seed(TRequest request); + Task> SeedAsync(TRequest request); Type IScene.GetRequestType() => typeof(TRequest); - SceneResult IScene.Seed(object request) => (SceneResult)Seed((TRequest)request); + async Task> IScene.SeedAsync(object request) => (SceneResult)await SeedAsync((TRequest)request); } diff --git a/util/Seeder/Recipes/OrganizationWithUsersRecipe.cs b/util/Seeder/Recipes/OrganizationWithUsersRecipe.cs index 53daddd7bf..db0003fd14 100644 --- a/util/Seeder/Recipes/OrganizationWithUsersRecipe.cs +++ b/util/Seeder/Recipes/OrganizationWithUsersRecipe.cs @@ -1,4 +1,4 @@ -using Bit.Infrastructure.EntityFramework.Models; +using Bit.Core.Entities; using Bit.Infrastructure.EntityFramework.Repositories; using Bit.Seeder.Factories; using LinqToDB.EntityFrameworkCore; diff --git a/util/Seeder/SceneResult.cs b/util/Seeder/SceneResult.cs index b732cef4c4..0e7abdce47 100644 --- a/util/Seeder/SceneResult.cs +++ b/util/Seeder/SceneResult.cs @@ -2,21 +2,19 @@ public class SceneResult : SceneResult { - public SceneResult(Dictionary mangleMap, Dictionary> trackedEntities) - : base(result: null, mangleMap: mangleMap, trackedEntities: trackedEntities) { } + public SceneResult(Dictionary mangleMap) + : base(result: null, mangleMap: mangleMap) { } } public class SceneResult { public TResult Result { get; init; } public Dictionary MangleMap { get; init; } - public Dictionary> TrackedEntities { get; init; } - public SceneResult(TResult result, Dictionary mangleMap, Dictionary> trackedEntities) + public SceneResult(TResult result, Dictionary mangleMap) { Result = result; MangleMap = mangleMap; - TrackedEntities = trackedEntities; } public static explicit operator SceneResult(SceneResult v) @@ -25,11 +23,11 @@ public class SceneResult if (result is null) { - return new SceneResult(result: null, mangleMap: v.MangleMap, trackedEntities: v.TrackedEntities); + return new SceneResult(result: null, mangleMap: v.MangleMap); } else { - return new SceneResult(result: result, mangleMap: v.MangleMap, trackedEntities: v.TrackedEntities); + return new SceneResult(result: result, mangleMap: v.MangleMap); } } } diff --git a/util/Seeder/Scenes/SingleUserScene.cs b/util/Seeder/Scenes/SingleUserScene.cs index d0dfa30da4..793c475c8f 100644 --- a/util/Seeder/Scenes/SingleUserScene.cs +++ b/util/Seeder/Scenes/SingleUserScene.cs @@ -1,10 +1,10 @@ using System.ComponentModel.DataAnnotations; -using Bit.Infrastructure.EntityFramework.Repositories; +using Bit.Core.Repositories; using Bit.Seeder.Factories; namespace Bit.Seeder.Scenes; -public class SingleUserScene(DatabaseContext db, UserSeeder userSeeder) : IScene +public class SingleUserScene(UserSeeder userSeeder, IUserRepository userRepository) : IScene { public class Request { @@ -14,12 +14,11 @@ public class SingleUserScene(DatabaseContext db, UserSeeder userSeeder) : IScene public bool Premium { get; set; } = false; } - public SceneResult Seed(Request request) + public async Task SeedAsync(Request request) { var user = userSeeder.CreateUser(request.Email, request.EmailVerified, request.Premium); - db.Add(user); - db.SaveChanges(); + await userRepository.CreateAsync(user); return new SceneResult(mangleMap: userSeeder.GetMangleMap(user, new UserData { @@ -31,9 +30,6 @@ public class SingleUserScene(DatabaseContext db, UserSeeder userSeeder) : IScene ApiKey = user.ApiKey, Kdf = user.Kdf, KdfIterations = user.KdfIterations, - }), trackedEntities: new Dictionary> - { - ["User"] = [user.Id] - }); + })); } } diff --git a/util/SeederApi/Controllers/SeedController.cs b/util/SeederApi/Controllers/SeedController.cs index c33d8d4b1a..c3f22ec91d 100644 --- a/util/SeederApi/Controllers/SeedController.cs +++ b/util/SeederApi/Controllers/SeedController.cs @@ -6,17 +6,18 @@ using Microsoft.AspNetCore.Mvc; namespace Bit.SeederApi.Controllers; [Route("seed")] -public class SeedController(ILogger logger, ISceneService sceneService) +public class SeedController(ILogger logger, ISceneService sceneService, IServiceProvider serviceProvider) : Controller { [HttpPost] - public IActionResult Seed([FromBody] SeedRequestModel request) + public async Task Seed([FromBody] SeedRequestModel request) { + logger.LogInformation("Received seed request {Provider}", serviceProvider.GetType().FullName); logger.LogInformation("Seeding with template: {Template}", request.Template); try { - SceneResponseModel response = sceneService.ExecuteScene(request.Template, request.Arguments); + SceneResponseModel response = await sceneService.ExecuteScene(request.Template, request.Arguments); return Json(response); } @@ -36,24 +37,24 @@ public class SeedController(ILogger logger, ISceneService sceneS } [HttpDelete("batch")] - public async Task DeleteBatch([FromBody] List seedIds) + public async Task DeleteBatch([FromBody] List playIds) { - logger.LogInformation("Deleting batch of seeded data with IDs: {SeedIds}", string.Join(", ", seedIds)); + logger.LogInformation("Deleting batch of seeded data with IDs: {PlayIds}", string.Join(", ", playIds)); var aggregateException = new AggregateException(); await Task.Run(async () => { - foreach (var seedId in seedIds) + foreach (var playId in playIds) { try { - await sceneService.DestroyScene(seedId); + await sceneService.DestroyScene(playId); } catch (Exception ex) { aggregateException = new AggregateException(aggregateException, ex); - logger.LogError(ex, "Error deleting seeded data: {SeedId}", seedId); + logger.LogError(ex, "Error deleting seeded data: {SeedId}", playId); } } }); @@ -72,20 +73,20 @@ public class SeedController(ILogger logger, ISceneService sceneS }); } - [HttpDelete("{seedId}")] - public async Task Delete([FromRoute] Guid seedId) + [HttpDelete("{playId}")] + public async Task Delete([FromRoute] string playId) { - logger.LogInformation("Deleting seeded data with ID: {SeedId}", seedId); + logger.LogInformation("Deleting seeded data with ID: {PlayId}", playId); try { - var result = await sceneService.DestroyScene(seedId); + var result = await sceneService.DestroyScene(playId); return Json(result); } catch (SceneExecutionException ex) { - logger.LogError(ex, "Error deleting seeded data: {SeedId}", seedId); + logger.LogError(ex, "Error deleting seeded data: {PlayId}", playId); return BadRequest(new { Error = ex.Message, @@ -101,25 +102,23 @@ public class SeedController(ILogger logger, ISceneService sceneS logger.LogInformation("Deleting all seeded data"); // Pull all Seeded Data ids - var seededData = sceneService.GetAllSeededData(); + + var playIds = sceneService.GetAllPlayIds(); var aggregateException = new AggregateException(); - await Task.Run(async () => + foreach (var playId in playIds) { - foreach (var sd in seededData) + try { - try - { - await sceneService.DestroyScene(sd.Id); - } - catch (Exception ex) - { - aggregateException = new AggregateException(aggregateException, ex); - logger.LogError(ex, "Error deleting seeded data: {SeedId}", sd.Id); - } + await sceneService.DestroyScene(playId); } - }); + catch (Exception ex) + { + aggregateException = new AggregateException(aggregateException, ex); + logger.LogError(ex, "Error deleting seeded data: {PlayId}", playId); + } + } if (aggregateException.InnerExceptions.Count > 0) { diff --git a/util/SeederApi/Models/Response/SeedResponseModel.cs b/util/SeederApi/Models/Response/SeedResponseModel.cs index 9b9244eb78..a8913c76c8 100644 --- a/util/SeederApi/Models/Response/SeedResponseModel.cs +++ b/util/SeederApi/Models/Response/SeedResponseModel.cs @@ -4,17 +4,15 @@ namespace Bit.SeederApi.Models.Response; public class SceneResponseModel { - public required Guid? SeedId { get; init; } public required Dictionary? MangleMap { get; init; } public required object? Result { get; init; } - public static SceneResponseModel FromSceneResult(SceneResult sceneResult, Guid? seedId) + public static SceneResponseModel FromSceneResult(SceneResult sceneResult) { return new SceneResponseModel { Result = sceneResult.Result, MangleMap = sceneResult.MangleMap, - SeedId = seedId }; } } diff --git a/util/SeederApi/Program.cs b/util/SeederApi/Program.cs index 44666e615f..b0b4a856b6 100644 --- a/util/SeederApi/Program.cs +++ b/util/SeederApi/Program.cs @@ -6,6 +6,7 @@ using Bit.SharedWeb.Utilities; var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); +builder.Services.AddHttpContextAccessor(); var globalSettings = builder.Services.AddGlobalSettingsServices(builder.Configuration, builder.Environment); @@ -26,6 +27,9 @@ builder.Services.AddQueries(); var app = builder.Build(); +// Add PlayIdMiddleware services +app.UseMiddleware(); + // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { diff --git a/util/SeederApi/Services/ISceneService.cs b/util/SeederApi/Services/ISceneService.cs index b393f3b53d..20a279c4ba 100644 --- a/util/SeederApi/Services/ISceneService.cs +++ b/util/SeederApi/Services/ISceneService.cs @@ -1,5 +1,4 @@ using System.Text.Json; -using Bit.Infrastructure.EntityFramework.Models; using Bit.SeederApi.Models.Response; namespace Bit.SeederApi.Services; @@ -14,14 +13,14 @@ public interface ISceneService /// A tuple containing the result and optional seed ID for tracked entities /// Thrown when the scene template is not found /// Thrown when there's an error executing the scene - SceneResponseModel ExecuteScene(string templateName, JsonElement? arguments); + Task ExecuteScene(string templateName, JsonElement? arguments); /// /// Destroys data created by a scene using the seeded data ID. /// - /// The ID of the seeded data to destroy + /// The ID of the seeded data to destroy /// The result of the destroy operation /// Thrown when there's an error destroying the seeded data - Task DestroyScene(Guid seedId); - List GetAllSeededData(); + Task DestroyScene(string playId); + List GetAllPlayIds(); } diff --git a/util/SeederApi/Services/SceneService.cs b/util/SeederApi/Services/SceneService.cs index d25a604f2c..6aaddfecdc 100644 --- a/util/SeederApi/Services/SceneService.cs +++ b/util/SeederApi/Services/SceneService.cs @@ -1,6 +1,5 @@ using System.Text.Json; using Bit.Core.Repositories; -using Bit.Infrastructure.EntityFramework.Models; using Bit.Infrastructure.EntityFramework.Repositories; using Bit.Seeder; using Bit.SeederApi.Models.Response; @@ -12,6 +11,7 @@ public class SceneService( ILogger logger, IServiceProvider serviceProvider, IUserRepository userRepository, + IPlayDataRepository playDataRepository, IOrganizationRepository organizationRepository) : ISceneService { @@ -21,35 +21,18 @@ public class SceneService( PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; - public List GetAllSeededData() + public List GetAllPlayIds() { - return databaseContext.SeededData.ToList(); + return [.. databaseContext.PlayData + .Select(pd => pd.PlayId) + .Distinct()]; } - public SceneResponseModel ExecuteScene(string templateName, JsonElement? arguments) + public async Task ExecuteScene(string templateName, JsonElement? arguments) { - var result = ExecuteSceneMethod(templateName, arguments, "Seed"); + var result = await ExecuteSceneMethod(templateName, arguments, "Seed"); - if (result.TrackedEntities.Count == 0) - { - return SceneResponseModel.FromSceneResult(result, seedId: null); - } - - var seededData = new SeededData - { - Id = Guid.NewGuid(), - RecipeName = templateName, - Data = JsonSerializer.Serialize(result.TrackedEntities), - CreationDate = DateTime.UtcNow - }; - - databaseContext.Add(seededData); - databaseContext.SaveChanges(); - - logger.LogInformation("Saved seeded data with ID {SeedId} for scene {SceneName}", - seededData.Id, templateName); - - return SceneResponseModel.FromSceneResult(result, seededData.Id); + return SceneResponseModel.FromSceneResult(result); } public object ExecuteQuery(string queryName, JsonElement? arguments) @@ -113,31 +96,23 @@ public class SceneService( } } - public async Task DestroyScene(Guid seedId) + public async Task DestroyScene(string playId) { - var seededData = databaseContext.SeededData.FirstOrDefault(s => s.Id == seedId); - if (seededData == null) - { - logger.LogInformation("No seeded data found with ID {SeedId}, skipping", seedId); - return null; - } + // Note, delete cascade will remove PlayData entries - var trackedEntities = JsonSerializer.Deserialize>>(seededData.Data); - if (trackedEntities == null) - { - throw new SceneExecutionException($"Failed to deserialize tracked entities for seed ID {seedId}"); - } + var playData = await playDataRepository.GetByPlayIdAsync(playId); + var userIds = playData.Select(pd => pd.UserId).Distinct().ToList(); + var organizationIds = playData.Select(pd => pd.OrganizationId).Distinct().ToList(); - // Delete in reverse order to respect foreign key constraints - if (trackedEntities.TryGetValue("User", out var userIds)) + // Delete Users before Oraganizations to respect foreign key constraints + if (userIds.Count > 0) { var users = databaseContext.Users.Where(u => userIds.Contains(u.Id)); await userRepository.DeleteManyAsync(users); } - - if (trackedEntities.TryGetValue("Organization", out var orgIds)) + if (organizationIds.Count > 0) { - var organizations = databaseContext.Organizations.Where(o => orgIds.Contains(o.Id)); + var organizations = databaseContext.Organizations.Where(o => organizationIds.Contains(o.Id)); var aggregateException = new AggregateException(); foreach (var org in organizations) { @@ -153,21 +128,18 @@ public class SceneService( if (aggregateException.InnerExceptions.Count > 0) { throw new SceneExecutionException( - $"One or more errors occurred while deleting organizations for seed ID {seedId}", + $"One or more errors occurred while deleting organizations for seed ID {playId}", aggregateException); } } - databaseContext.Remove(seededData); - databaseContext.SaveChanges(); + logger.LogInformation("Successfully destroyed seeded data with ID {PlayId}", + playId); - logger.LogInformation("Successfully destroyed seeded data with ID {SeedId} for scene {SceneName}", - seedId, seededData.RecipeName); - - return new { SeedId = seedId, SceneName = seededData.RecipeName }; + return new { PlayId = playId }; } - private SceneResult ExecuteSceneMethod(string templateName, JsonElement? arguments, string methodName) + private async Task> ExecuteSceneMethod(string templateName, JsonElement? arguments, string methodName) { try { @@ -214,7 +186,7 @@ public class SceneService( } } - var result = scene.Seed(requestModel); + var result = await scene.SeedAsync(requestModel); logger.LogInformation("Successfully executed {MethodName} on scene: {TemplateName}", methodName, templateName); return result;