diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index eac6812bc..30ccb6973 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -192,6 +192,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); } } } diff --git a/src/Ombi.Schedule.Tests/IssuesPurgeTests.cs b/src/Ombi.Schedule.Tests/IssuesPurgeTests.cs new file mode 100644 index 000000000..932022cd8 --- /dev/null +++ b/src/Ombi.Schedule.Tests/IssuesPurgeTests.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Moq; +using NUnit.Framework; +using Ombi.Core.Settings; +using Ombi.Schedule.Jobs.Ombi; +using Ombi.Settings.Settings.Models; +using Ombi.Store.Entities.Requests; +using Ombi.Store.Repository; +using System.Threading.Tasks; + +namespace Ombi.Schedule.Tests +{ + [TestFixture] + public class IssuesPurgeTests + { + + [SetUp] + public void Setup() + { + Repo = new Mock>(); + Settings = new Mock>(); + Settings.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new IssueSettings()); + Job = new IssuesPurge(Repo.Object, Settings.Object); + } + + public Mock> Repo { get; set; } + public Mock> Settings { get; set; } + public IssuesPurge Job { get; set; } + + [Test] + public async Task DoesNotRun_WhenDisabled() + { + await Job.Start(); + Repo.Verify(x => x.GetAll(),Times.Never); + } + + [Test] + public async Task Deletes_Correct_Issue() + { + var issues = new List() + { + new Issues + { + Status = IssueStatus.Resolved, + ResovledDate = DateTime.Now.AddDays(-5).AddHours(-1) + } + }; + + Settings.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new IssueSettings { DeleteIssues = true, DaysAfterResolvedToDelete = 5 }); + Repo.Setup(x => x.GetAll()).Returns(new EnumerableQuery(issues)); + await Job.Start(); + + Assert.That(issues.First().Status, Is.EqualTo(IssueStatus.Deleted)); + Repo.Verify(x => x.SaveChangesAsync(), Times.Once); + } + + [Test] + public async Task DoesNot_Delete_AnyIssues() + { + var issues = new List() + { + new Issues + { + Status = IssueStatus.Resolved, + ResovledDate = DateTime.Now.AddDays(-2) + }, + new Issues + { + Status = IssueStatus.Resolved, + ResovledDate = DateTime.Now.AddDays(-6) + } + }; + + Settings.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new IssueSettings { DeleteIssues = true, DaysAfterResolvedToDelete = 5 }); + Repo.Setup(x => x.GetAll()).Returns(new EnumerableQuery(issues)); + await Job.Start(); + + Assert.That(issues[0].Status, Is.Not.EqualTo(IssueStatus.Deleted)); + Assert.That(issues[1].Status, Is.EqualTo(IssueStatus.Deleted)); + Repo.Verify(x => x.SaveChangesAsync(), Times.Once); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Ombi/IIssuesPurge.cs b/src/Ombi.Schedule/Jobs/Ombi/IIssuesPurge.cs new file mode 100644 index 000000000..fbd1e3aaf --- /dev/null +++ b/src/Ombi.Schedule/Jobs/Ombi/IIssuesPurge.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace Ombi.Schedule.Jobs.Ombi +{ + public interface IIssuesPurge : IBaseJob + { + Task Start(); + } +} \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Ombi/IssuesPurge.cs b/src/Ombi.Schedule/Jobs/Ombi/IssuesPurge.cs new file mode 100644 index 000000000..92ca31071 --- /dev/null +++ b/src/Ombi.Schedule/Jobs/Ombi/IssuesPurge.cs @@ -0,0 +1,63 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Ombi.Core.Settings; +using Ombi.Settings.Settings.Models; +using Ombi.Store.Entities.Requests; +using Ombi.Store.Repository; + +namespace Ombi.Schedule.Jobs.Ombi +{ + public class IssuesPurge : IIssuesPurge + { + public IssuesPurge(IRepository issuesRepo, ISettingsService issueSettings) + { + _issuesRepository = issuesRepo; + _settings = issueSettings; + _settings.ClearCache(); + } + + private readonly IRepository _issuesRepository; + private readonly ISettingsService _settings; + + public async Task Start() + { + var settings = await _settings.GetSettingsAsync(); + if (!settings.DeleteIssues) + { + return; + } + + var now = DateTime.Now.AddDays(-settings.DaysAfterResolvedToDelete).Date; + var resolved = _issuesRepository.GetAll().Where(x => x.Status == IssueStatus.Resolved); + var toDelete = resolved.Where(x => x.ResovledDate.HasValue && x.ResovledDate.Value.Date <= now); + + foreach (var d in toDelete) + { + d.Status = IssueStatus.Deleted; + } + + await _issuesRepository.SaveChangesAsync(); + } + + private bool _disposed; + protected virtual void Dispose(bool disposing) + { + if (_disposed) + return; + + if (disposing) + { + _issuesRepository?.Dispose(); + _settings?.Dispose(); + } + _disposed = true; + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/IssueSettings.cs b/src/Ombi.Settings/Settings/Models/IssueSettings.cs index e025c82d1..d7a35c0d9 100644 --- a/src/Ombi.Settings/Settings/Models/IssueSettings.cs +++ b/src/Ombi.Settings/Settings/Models/IssueSettings.cs @@ -4,5 +4,8 @@ { public bool Enabled { get; set; } public bool EnableInProgress { get; set; } + + public bool DeleteIssues { get; set; } + public int DaysAfterResolvedToDelete { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/JobSettings.cs b/src/Ombi.Settings/Settings/Models/JobSettings.cs index 48c721e29..8b283cdf7 100644 --- a/src/Ombi.Settings/Settings/Models/JobSettings.cs +++ b/src/Ombi.Settings/Settings/Models/JobSettings.cs @@ -14,5 +14,6 @@ public string RefreshMetadata { get; set; } public string Newsletter { get; set; } public string LidarrArtistSync { get; set; } + public string IssuesPurge { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs index 0f8fec5fd..4491ca27a 100644 --- a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs +++ b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs @@ -57,6 +57,11 @@ namespace Ombi.Settings.Settings.Models return Get(s.LidarrArtistSync, Cron.Hourly(40)); } + public static string IssuePurge(JobSettings s) + { + return Get(s.IssuesPurge, Cron.Daily()); + } + private static string Get(string settings, string defaultCron) { return settings.HasValue() ? settings : defaultCron; diff --git a/src/Ombi.Store/Entities/Requests/Issues.cs b/src/Ombi.Store/Entities/Requests/Issues.cs index b1021e362..9fbc6a83e 100644 --- a/src/Ombi.Store/Entities/Requests/Issues.cs +++ b/src/Ombi.Store/Entities/Requests/Issues.cs @@ -29,5 +29,6 @@ namespace Ombi.Store.Entities.Requests Pending = 0, InProgress = 1, Resolved = 2, + Deleted = 3, } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index 5f1b255a4..f1934a994 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISettings.ts @@ -144,11 +144,14 @@ export interface IJobSettings { newsletter: string; plexRecentlyAddedSync: string; lidarrArtistSync: string; + issuesPurge: string; } export interface IIssueSettings extends ISettings { enabled: boolean; enableInProgress: boolean; + deleteIssues: boolean; + daysAfterResolvedToDelete: number; } export interface IAuthenticationSettings extends ISettings { diff --git a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html index f86d3351d..c4c903da2 100644 --- a/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html +++ b/src/Ombi/ClientApp/app/requests/music/musicrequests.component.html @@ -59,7 +59,7 @@

- {{request.title}} + {{request.title | truncate: 36}}

diff --git a/src/Ombi/ClientApp/app/settings/issues/issues.component.ts b/src/Ombi/ClientApp/app/settings/issues/issues.component.ts index 005202f1e..cfe0bd65c 100644 --- a/src/Ombi/ClientApp/app/settings/issues/issues.component.ts +++ b/src/Ombi/ClientApp/app/settings/issues/issues.component.ts @@ -21,8 +21,10 @@ export class IssuesComponent implements OnInit { public ngOnInit() { this.settingsService.getIssueSettings().subscribe(x => { this.form = this.fb.group({ - enabled: [x.enabled], - enableInProgress: [x.enableInProgress], + enabled: [x.enabled], + enableInProgress: [x.enableInProgress], + deleteIssues: [x.deleteIssues], + daysAfterResolvedToDelete: [x.daysAfterResolvedToDelete], }); }); this.getCategories(); diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html index a4dcd6fb3..1365710f0 100644 --- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html +++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html @@ -85,12 +85,19 @@
-
+
The Newsletter is required
+ +
+ + + The Issues Purge is required + +
diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts index 756d6ba89..d8ce106ae 100644 --- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts +++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.ts @@ -35,6 +35,7 @@ export class JobsComponent implements OnInit { newsletter: [x.newsletter, Validators.required], plexRecentlyAddedSync: [x.plexRecentlyAddedSync, Validators.required], lidarrArtistSync: [x.lidarrArtistSync, Validators.required], + issuesPurge: [x.issuesPurge, Validators.required], }); }); } diff --git a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html index bf0e53895..3f44a808b 100644 --- a/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html +++ b/src/Ombi/ClientApp/app/usermanagement/usermanagement-user.component.html @@ -147,7 +147,7 @@
-
+
@@ -165,7 +165,7 @@
-
+
@@ -182,7 +182,7 @@
-
+
-
+