diff --git a/util/SeederApi/Controllers/SeedController.cs b/util/SeederApi/Controllers/SeedController.cs index 413b7cd814..ab508d2b97 100644 --- a/util/SeederApi/Controllers/SeedController.cs +++ b/util/SeederApi/Controllers/SeedController.cs @@ -66,13 +66,13 @@ public class SeedController : Controller } [HttpDelete("/seed/{seedId}")] - public IActionResult Delete([FromRoute] Guid seedId) + public async Task Delete([FromRoute] Guid seedId) { _logger.LogInformation("Deleting seeded data with ID: {SeedId}", seedId); try { - var result = _recipeService.DestroyRecipe(seedId); + var result = await _recipeService.DestroyRecipe(seedId); return Ok(new { @@ -110,13 +110,13 @@ public class SeedController : Controller var aggregateException = new AggregateException(); - await Task.Run(() => + await Task.Run(async () => { foreach (var sd in seededData) { try { - _recipeService.DestroyRecipe(sd.Id); + await _recipeService.DestroyRecipe(sd.Id); } catch (Exception ex) { diff --git a/util/SeederApi/Services/IRecipeService.cs b/util/SeederApi/Services/IRecipeService.cs index 22e9d898ab..84bfe3ad9a 100644 --- a/util/SeederApi/Services/IRecipeService.cs +++ b/util/SeederApi/Services/IRecipeService.cs @@ -21,6 +21,6 @@ public interface IRecipeService /// The ID of the seeded data to destroy /// The result of the destroy operation /// Thrown when there's an error destroying the seeded data - object? DestroyRecipe(Guid seedId); + Task DestroyRecipe(Guid seedId); List GetAllSeededData(); } diff --git a/util/SeederApi/Services/RecipeService.cs b/util/SeederApi/Services/RecipeService.cs index 97f73d07f6..8a73ef326c 100644 --- a/util/SeederApi/Services/RecipeService.cs +++ b/util/SeederApi/Services/RecipeService.cs @@ -1,5 +1,6 @@ using System.Reflection; using System.Text.Json; +using Bit.Core.Repositories; using Bit.Infrastructure.EntityFramework.Models; using Bit.Infrastructure.EntityFramework.Repositories; using Bit.Seeder; @@ -11,12 +12,16 @@ public class RecipeService : IRecipeService private readonly DatabaseContext _databaseContext; private readonly ILogger _logger; private readonly IServiceProvider _serviceProvider; + private readonly IUserRepository _userRepository; + private readonly IOrganizationRepository _organizationRepository; - public RecipeService(DatabaseContext databaseContext, ILogger logger, IServiceProvider serviceProvider) + public RecipeService(DatabaseContext databaseContext, ILogger logger, IServiceProvider serviceProvider, IUserRepository userRepository, IOrganizationRepository organizationRepository) { _databaseContext = databaseContext; _logger = logger; _serviceProvider = serviceProvider; + _userRepository = userRepository; + _organizationRepository = organizationRepository; } public List GetAllSeededData() @@ -55,7 +60,7 @@ public class RecipeService : IRecipeService return (Result: recipeResult.Result, SeedId: seededData.Id); } - public object? DestroyRecipe(Guid seedId) + public async Task DestroyRecipe(Guid seedId) { var seededData = _databaseContext.SeededData.FirstOrDefault(s => s.Id == seedId); if (seededData == null) @@ -73,13 +78,30 @@ public class RecipeService : IRecipeService if (trackedEntities.TryGetValue("User", out var userIds)) { var users = _databaseContext.Users.Where(u => userIds.Contains(u.Id)); - _databaseContext.RemoveRange(users); + await _userRepository.DeleteManyAsync(users); } if (trackedEntities.TryGetValue("Organization", out var orgIds)) { var organizations = _databaseContext.Organizations.Where(o => orgIds.Contains(o.Id)); - _databaseContext.RemoveRange(organizations); + var aggregateException = new AggregateException(); + foreach (var org in organizations) + { + try + { + await _organizationRepository.DeleteAsync(org); + } + catch (Exception ex) + { + aggregateException = new AggregateException(aggregateException, ex); + } + } + if (aggregateException.InnerExceptions.Count > 0) + { + throw new RecipeExecutionException( + $"One or more errors occurred while deleting organizations for seed ID {seedId}", + aggregateException); + } } _databaseContext.Remove(seededData);