diff --git a/src/Lidarr.Api.V1/Artist/ArtistController.cs b/src/Lidarr.Api.V1/Artist/ArtistController.cs index 58f3fea59..f5a874f7d 100644 --- a/src/Lidarr.Api.V1/Artist/ArtistController.cs +++ b/src/Lidarr.Api.V1/Artist/ArtistController.cs @@ -53,6 +53,7 @@ namespace Lidarr.Api.V1.Artist IMapCoversToLocal coverMapper, IManageCommandQueue commandQueueManager, IRootFolderService rootFolderService, + RecycleBinValidator recycleBinValidator, RootFolderValidator rootFolderValidator, MappedNetworkDriveValidator mappedNetworkDriveValidator, ArtistPathValidator artistPathValidator, @@ -82,6 +83,7 @@ namespace Lidarr.Api.V1.Artist .SetValidator(mappedNetworkDriveValidator) .SetValidator(artistPathValidator) .SetValidator(artistAncestorValidator) + .SetValidator(recycleBinValidator) .SetValidator(systemFolderValidator) .When(s => !s.Path.IsNullOrWhiteSpace()); diff --git a/src/Lidarr.Api.V1/Config/MediaManagementConfigController.cs b/src/Lidarr.Api.V1/Config/MediaManagementConfigController.cs index d2acc26a8..8a19c6175 100644 --- a/src/Lidarr.Api.V1/Config/MediaManagementConfigController.cs +++ b/src/Lidarr.Api.V1/Config/MediaManagementConfigController.cs @@ -10,12 +10,28 @@ namespace Lidarr.Api.V1.Config [V1ApiController("config/mediamanagement")] public class MediaManagementConfigController : ConfigController { - public MediaManagementConfigController(IConfigService configService, PathExistsValidator pathExistsValidator, FolderChmodValidator folderChmodValidator) + public MediaManagementConfigController(IConfigService configService, + PathExistsValidator pathExistsValidator, + FolderChmodValidator folderChmodValidator, + FolderWritableValidator folderWritableValidator, + ArtistPathValidator artistPathValidator, + StartupFolderValidator startupFolderValidator, + SystemFolderValidator systemFolderValidator, + RootFolderAncestorValidator rootFolderAncestorValidator, + RootFolderValidator rootFolderValidator) : base(configService) { + SharedValidator.RuleFor(c => c.RecycleBin).IsValidPath() + .SetValidator(folderWritableValidator) + .SetValidator(rootFolderValidator) + .SetValidator(pathExistsValidator) + .SetValidator(artistPathValidator) + .SetValidator(rootFolderAncestorValidator) + .SetValidator(startupFolderValidator) + .SetValidator(systemFolderValidator) + .When(c => !string.IsNullOrWhiteSpace(c.RecycleBin)); SharedValidator.RuleFor(c => c.RecycleBinCleanupDays).GreaterThanOrEqualTo(0); SharedValidator.RuleFor(c => c.ChmodFolder).SetValidator(folderChmodValidator).When(c => !string.IsNullOrEmpty(c.ChmodFolder) && (OsInfo.IsLinux || OsInfo.IsOsx)); - SharedValidator.RuleFor(c => c.RecycleBin).IsValidPath().SetValidator(pathExistsValidator).When(c => !string.IsNullOrWhiteSpace(c.RecycleBin)); SharedValidator.RuleFor(c => c.MinimumFreeSpaceWhenImporting).GreaterThanOrEqualTo(100); } diff --git a/src/Lidarr.Api.V1/RootFolders/RootFolderController.cs b/src/Lidarr.Api.V1/RootFolders/RootFolderController.cs index 48584f3bb..8d7473b4c 100644 --- a/src/Lidarr.Api.V1/RootFolders/RootFolderController.cs +++ b/src/Lidarr.Api.V1/RootFolders/RootFolderController.cs @@ -21,6 +21,7 @@ namespace Lidarr.Api.V1.RootFolders RootFolderValidator rootFolderValidator, PathExistsValidator pathExistsValidator, MappedNetworkDriveValidator mappedNetworkDriveValidator, + RecycleBinValidator recycleBinValidator, StartupFolderValidator startupFolderValidator, SystemFolderValidator systemFolderValidator, FolderWritableValidator folderWritableValidator, @@ -35,6 +36,7 @@ namespace Lidarr.Api.V1.RootFolders .IsValidPath() .SetValidator(mappedNetworkDriveValidator) .SetValidator(startupFolderValidator) + .SetValidator(recycleBinValidator) .SetValidator(pathExistsValidator) .SetValidator(systemFolderValidator) .SetValidator(folderWritableValidator); diff --git a/src/NzbDrone.Core/Music/Utilities/AddArtistValidator.cs b/src/NzbDrone.Core/Music/Utilities/AddArtistValidator.cs index c77cfacc2..77287c780 100644 --- a/src/NzbDrone.Core/Music/Utilities/AddArtistValidator.cs +++ b/src/NzbDrone.Core/Music/Utilities/AddArtistValidator.cs @@ -13,6 +13,7 @@ namespace NzbDrone.Core.Music public class AddArtistValidator : AbstractValidator, IAddArtistValidator { public AddArtistValidator(RootFolderValidator rootFolderValidator, + RecycleBinValidator recycleBinValidator, ArtistPathValidator artistPathValidator, ArtistAncestorValidator artistAncestorValidator, QualityProfileExistsValidator qualityProfileExistsValidator, @@ -21,6 +22,7 @@ namespace NzbDrone.Core.Music RuleFor(c => c.Path).Cascade(CascadeMode.StopOnFirstFailure) .IsValidPath() .SetValidator(rootFolderValidator) + .SetValidator(recycleBinValidator) .SetValidator(artistPathValidator) .SetValidator(artistAncestorValidator); diff --git a/src/NzbDrone.Core/Validation/Paths/ArtistPathValidator.cs b/src/NzbDrone.Core/Validation/Paths/ArtistPathValidator.cs index 69f6c7c5d..824974e37 100644 --- a/src/NzbDrone.Core/Validation/Paths/ArtistPathValidator.cs +++ b/src/NzbDrone.Core/Validation/Paths/ArtistPathValidator.cs @@ -10,7 +10,7 @@ namespace NzbDrone.Core.Validation.Paths private readonly IArtistService _artistService; public ArtistPathValidator(IArtistService artistService) - : base("Path is already configured for another artist") + : base("Path is already configured for an existing artist") { _artistService = artistService; } diff --git a/src/NzbDrone.Core/Validation/Paths/RecycleBinValidator.cs b/src/NzbDrone.Core/Validation/Paths/RecycleBinValidator.cs new file mode 100644 index 000000000..a8a714fe6 --- /dev/null +++ b/src/NzbDrone.Core/Validation/Paths/RecycleBinValidator.cs @@ -0,0 +1,44 @@ +using FluentValidation.Validators; +using NzbDrone.Common.Extensions; +using NzbDrone.Core.Configuration; + +namespace NzbDrone.Core.Validation.Paths +{ + public class RecycleBinValidator : PropertyValidator + { + private readonly IConfigService _configService; + + public RecycleBinValidator(IConfigService configService) + : base("Path is {relationship} configured recycle bin folder") + { + _configService = configService; + } + + protected override bool IsValid(PropertyValidatorContext context) + { + var recycleBin = _configService.RecycleBin; + var folder = context.PropertyValue.ToString(); + + if (context.PropertyValue == null || recycleBin.IsNullOrWhiteSpace()) + { + return true; + } + + if (recycleBin.PathEquals(folder)) + { + context.MessageFormatter.AppendArgument("relationship", "set to"); + + return false; + } + + if (recycleBin.IsParentPath(folder)) + { + context.MessageFormatter.AppendArgument("relationship", "child of"); + + return false; + } + + return true; + } + } +} diff --git a/src/NzbDrone.Core/Validation/Paths/RootFolderAncestorValidator.cs b/src/NzbDrone.Core/Validation/Paths/RootFolderAncestorValidator.cs new file mode 100644 index 000000000..19f0800b5 --- /dev/null +++ b/src/NzbDrone.Core/Validation/Paths/RootFolderAncestorValidator.cs @@ -0,0 +1,28 @@ +using System.Linq; +using FluentValidation.Validators; +using NzbDrone.Common.Extensions; +using NzbDrone.Core.RootFolders; + +namespace NzbDrone.Core.Validation.Paths +{ + public class RootFolderAncestorValidator : PropertyValidator + { + private readonly IRootFolderService _rootFolderService; + + public RootFolderAncestorValidator(IRootFolderService rootFolderService) + : base("Path is an ancestor of an existing root folder") + { + _rootFolderService = rootFolderService; + } + + protected override bool IsValid(PropertyValidatorContext context) + { + if (context.PropertyValue == null) + { + return true; + } + + return !_rootFolderService.All().Any(s => context.PropertyValue.ToString().IsParentPath(s.Path)); + } + } +}