From 1fe2f0fb5738d69e4f214e4f6b6cec49df1dd836 Mon Sep 17 00:00:00 2001 From: Colton Hurst Date: Tue, 18 Jul 2023 15:32:47 -0400 Subject: [PATCH] SM-503: Add EmptySecretsManagerTrashJob (#2863) * SM-503: Add EmptySecretsManagerJob * SM-503: Fix date logic and refactor a few lines * SM-503: Add logging * SM-503: Move EmptySecretsManagerTrashJob to src/Api/SecretsManager/Jobs * SM-503: Update trigger time for EmptySecretsManagerTrashJob * SM-503: Switch to scope on one line * SM-768: Update EFCore and related packages to >= 7.0 * SM-768: Update more packages for the EF 7 upgrade * SM-768: Update the PostgreSQL package * SM-768: Run dotnet restore --force-evaluate * SM-768: Revert package upgrades for 3 projects * SM-768: Update the dotnet-ef tool * SM-503: Switch to using ExecuteDeleteAsync and fix param name * SM-503: Rename trigger to smTrashCleanupTrigger * SM-503: Fix OSS job issue * SM-503: Only add trigger if not OSS for SM Trash Job --- .../Repositories/SecretRepository.cs | 10 ++++++++ src/Api/Jobs/JobsHostedService.cs | 14 +++++++++++ .../Jobs/EmptySecretsManagerTrashJob.cs | 23 +++++++++++++++++++ src/Api/Startup.cs | 1 + .../Repositories/ISecretRepository.cs | 1 + 5 files changed, 49 insertions(+) create mode 100644 src/Api/SecretsManager/Jobs/EmptySecretsManagerTrashJob.cs diff --git a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/SecretRepository.cs b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/SecretRepository.cs index 6720c7116d..078147f3ab 100644 --- a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/SecretRepository.cs +++ b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/SecretsManager/Repositories/SecretRepository.cs @@ -293,6 +293,16 @@ public class SecretRepository : Repository s.DeletedDate != null && s.DeletedDate < currentDate.AddDays(-deleteAfterThisNumberOfDays)).ExecuteDeleteAsync(); + + await dbContext.SaveChangesAsync(); + } + private IQueryable SecretToPermissionDetails(IQueryable query, Guid userId, AccessClientType accessType) { var secrets = accessType switch diff --git a/src/Api/Jobs/JobsHostedService.cs b/src/Api/Jobs/JobsHostedService.cs index 29cd4842da..acd95a0213 100644 --- a/src/Api/Jobs/JobsHostedService.cs +++ b/src/Api/Jobs/JobsHostedService.cs @@ -41,6 +41,11 @@ public class JobsHostedService : BaseJobsHostedService .StartNow() .WithCronSchedule("0 30 */12 * * ?") .Build(); + var smTrashCleanupTrigger = TriggerBuilder.Create() + .WithIdentity("SMTrashCleanupTrigger") + .StartNow() + .WithCronSchedule("0 0 22 * * ?") + .Build(); var randomDailySponsorshipSyncTrigger = TriggerBuilder.Create() .WithIdentity("RandomDailySponsorshipSyncTrigger") .StartAt(DateBuilder.FutureDate(new Random().Next(24), IntervalUnit.Hour)) @@ -70,6 +75,10 @@ public class JobsHostedService : BaseJobsHostedService jobs.Add(new Tuple(typeof(SelfHostedSponsorshipSyncJob), randomDailySponsorshipSyncTrigger)); } +#if !OSS + jobs.Add(new Tuple(typeof(EmptySecretsManagerTrashJob), smTrashCleanupTrigger)); +#endif + Jobs = jobs; await base.StartAsync(cancellationToken); @@ -88,4 +97,9 @@ public class JobsHostedService : BaseJobsHostedService services.AddTransient(); services.AddTransient(); } + + public static void AddCommercialSecretsManagerJobServices(IServiceCollection services) + { + services.AddTransient(); + } } diff --git a/src/Api/SecretsManager/Jobs/EmptySecretsManagerTrashJob.cs b/src/Api/SecretsManager/Jobs/EmptySecretsManagerTrashJob.cs new file mode 100644 index 0000000000..f8668e8e53 --- /dev/null +++ b/src/Api/SecretsManager/Jobs/EmptySecretsManagerTrashJob.cs @@ -0,0 +1,23 @@ +using Bit.Core.Jobs; +using Bit.Core.SecretsManager.Repositories; +using Quartz; + +namespace Bit.Api.Jobs; + +public class EmptySecretsManagerTrashJob : BaseJob +{ + private ISecretRepository _secretRepository; + private const uint DeleteAfterThisNumberOfDays = 30; + + public EmptySecretsManagerTrashJob(ISecretRepository secretRepository, ILogger logger) : base(logger) + { + _secretRepository = secretRepository; + } + + protected override async Task ExecuteJobAsync(IJobExecutionContext context) + { + _logger.LogInformation("Execute job task: EmptySecretsManagerTrashJob: Start"); + await _secretRepository.EmptyTrash(DateTime.UtcNow, DeleteAfterThisNumberOfDays); + _logger.LogInformation("Execute job task: EmptySecretsManagerTrashJob: End"); + } +} diff --git a/src/Api/Startup.cs b/src/Api/Startup.cs index 6070a91b29..de47794932 100644 --- a/src/Api/Startup.cs +++ b/src/Api/Startup.cs @@ -147,6 +147,7 @@ public class Startup services.AddCommercialCoreServices(); services.AddCommercialSecretsManagerServices(); services.AddSecretsManagerEfRepositories(); + Jobs.JobsHostedService.AddCommercialSecretsManagerJobServices(services); #endif // MVC diff --git a/src/Core/SecretsManager/Repositories/ISecretRepository.cs b/src/Core/SecretsManager/Repositories/ISecretRepository.cs index 5b40a33278..68422cb44c 100644 --- a/src/Core/SecretsManager/Repositories/ISecretRepository.cs +++ b/src/Core/SecretsManager/Repositories/ISecretRepository.cs @@ -20,4 +20,5 @@ public interface ISecretRepository Task> ImportAsync(IEnumerable secrets); Task UpdateRevisionDates(IEnumerable ids); Task<(bool Read, bool Write)> AccessToSecretAsync(Guid id, Guid userId, AccessClientType accessType); + Task EmptyTrash(DateTime nowTime, uint deleteAfterThisNumberOfDays); }