mirror of
https://github.com/Radarr/Radarr
synced 2025-12-06 08:28:50 +01:00
Add 'qualitydefinition/limits' endpoint to get size limitations
(cherry picked from commit 24f03fc1e96eba215f96312c791cf167f10499c7)
This commit is contained in:
parent
b2e51d1613
commit
9c8d3b679d
9 changed files with 272 additions and 26 deletions
9
.gitignore
vendored
9
.gitignore
vendored
|
|
@ -165,15 +165,12 @@ Thumbs.db
|
||||||
/tools/Addins/*
|
/tools/Addins/*
|
||||||
packages.config.md5sum
|
packages.config.md5sum
|
||||||
|
|
||||||
|
|
||||||
# Common IntelliJ Platform excludes
|
|
||||||
|
|
||||||
# Ignore Rider projects completely for now
|
|
||||||
.idea/
|
|
||||||
|
|
||||||
# ignore node_modules symlink
|
# ignore node_modules symlink
|
||||||
node_modules
|
node_modules
|
||||||
node_modules.nosync
|
node_modules.nosync
|
||||||
|
|
||||||
# API doc generation
|
# API doc generation
|
||||||
.config/
|
.config/
|
||||||
|
|
||||||
|
# Ignore Jetbrains IntelliJ Workspace Directories
|
||||||
|
.idea/
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\NzbDrone.Core\Radarr.Core.csproj" />
|
<ProjectReference Include="..\NzbDrone.Core\Radarr.Core.csproj" />
|
||||||
<ProjectReference Include="..\NzbDrone.Test.Common\Radarr.Test.Common.csproj" />
|
<ProjectReference Include="..\NzbDrone.Test.Common\Radarr.Test.Common.csproj" />
|
||||||
|
<ProjectReference Include="..\Radarr.Api.V3\Radarr.Api.V3.csproj" />
|
||||||
<ProjectReference Include="..\Radarr.Http\Radarr.Http.csproj" />
|
<ProjectReference Include="..\Radarr.Http\Radarr.Http.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,198 @@
|
||||||
|
using FluentValidation.TestHelper;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
using Radarr.Api.V3.Qualities;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Test.v3.Qualities;
|
||||||
|
|
||||||
|
[Parallelizable(ParallelScope.All)]
|
||||||
|
public class QualityDefinitionResourceValidatorTests
|
||||||
|
{
|
||||||
|
private readonly QualityDefinitionResourceValidator _validator = new ();
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Validate_fails_when_min_size_is_below_min_limit()
|
||||||
|
{
|
||||||
|
var resource = new QualityDefinitionResource
|
||||||
|
{
|
||||||
|
MinSize = QualityDefinitionLimits.Min - 1,
|
||||||
|
PreferredSize = null,
|
||||||
|
MaxSize = null
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = _validator.TestValidate(resource);
|
||||||
|
|
||||||
|
result.ShouldHaveValidationErrorFor(r => r.MinSize)
|
||||||
|
.WithErrorCode("GreaterThanOrEqualTo");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Validate_fails_when_min_size_is_above_preferred_size_and_below_limit()
|
||||||
|
{
|
||||||
|
var resource = new QualityDefinitionResource
|
||||||
|
{
|
||||||
|
MinSize = 10,
|
||||||
|
PreferredSize = 5,
|
||||||
|
MaxSize = null
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = _validator.TestValidate(resource);
|
||||||
|
|
||||||
|
result.ShouldHaveValidationErrorFor(r => r.MinSize)
|
||||||
|
.WithErrorCode("LessThanOrEqualTo");
|
||||||
|
|
||||||
|
result.ShouldHaveValidationErrorFor(r => r.PreferredSize)
|
||||||
|
.WithErrorCode("GreaterThanOrEqualTo");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Validate_passes_when_min_size_is_within_limits()
|
||||||
|
{
|
||||||
|
var resource = new QualityDefinitionResource
|
||||||
|
{
|
||||||
|
MinSize = QualityDefinitionLimits.Min,
|
||||||
|
PreferredSize = null,
|
||||||
|
MaxSize = null
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = _validator.TestValidate(resource);
|
||||||
|
|
||||||
|
result.ShouldNotHaveAnyValidationErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Validate_fails_when_max_size_is_below_preferred_size_and_above_limit()
|
||||||
|
{
|
||||||
|
var resource = new QualityDefinitionResource
|
||||||
|
{
|
||||||
|
MinSize = null,
|
||||||
|
PreferredSize = 10,
|
||||||
|
MaxSize = 5
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = _validator.TestValidate(resource);
|
||||||
|
|
||||||
|
result.ShouldHaveValidationErrorFor(r => r.MaxSize)
|
||||||
|
.WithErrorCode("GreaterThanOrEqualTo");
|
||||||
|
|
||||||
|
result.ShouldHaveValidationErrorFor(r => r.PreferredSize)
|
||||||
|
.WithErrorCode("LessThanOrEqualTo");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Validate_fails_when_max_size_exceeds_max_limit()
|
||||||
|
{
|
||||||
|
var resource = new QualityDefinitionResource
|
||||||
|
{
|
||||||
|
MinSize = null,
|
||||||
|
PreferredSize = null,
|
||||||
|
MaxSize = QualityDefinitionLimits.Max + 1
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = _validator.TestValidate(resource);
|
||||||
|
|
||||||
|
result.ShouldHaveValidationErrorFor(r => r.MaxSize)
|
||||||
|
.WithErrorCode("LessThanOrEqualTo");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Validate_passes_when_max_size_is_within_limits()
|
||||||
|
{
|
||||||
|
var resource = new QualityDefinitionResource
|
||||||
|
{
|
||||||
|
MinSize = null,
|
||||||
|
PreferredSize = null,
|
||||||
|
MaxSize = QualityDefinitionLimits.Max
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = _validator.TestValidate(resource);
|
||||||
|
|
||||||
|
result.ShouldNotHaveAnyValidationErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Validate_fails_when_preferred_size_is_below_min_size_and_above_max_size()
|
||||||
|
{
|
||||||
|
var resource = new QualityDefinitionResource
|
||||||
|
{
|
||||||
|
MinSize = 10,
|
||||||
|
PreferredSize = 7,
|
||||||
|
MaxSize = 5
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = _validator.TestValidate(resource);
|
||||||
|
|
||||||
|
result.ShouldHaveValidationErrorFor(r => r.PreferredSize)
|
||||||
|
.WithErrorCode("GreaterThanOrEqualTo");
|
||||||
|
|
||||||
|
result.ShouldHaveValidationErrorFor(r => r.MaxSize)
|
||||||
|
.WithErrorCode("GreaterThanOrEqualTo");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Validate_passes_when_preferred_size_is_null_and_other_sizes_are_valid()
|
||||||
|
{
|
||||||
|
var resource = new QualityDefinitionResource
|
||||||
|
{
|
||||||
|
MinSize = 5,
|
||||||
|
PreferredSize = null,
|
||||||
|
MaxSize = 10
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = _validator.TestValidate(resource);
|
||||||
|
|
||||||
|
result.ShouldNotHaveAnyValidationErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Validate_passes_when_preferred_size_equals_limits()
|
||||||
|
{
|
||||||
|
var resource = new QualityDefinitionResource
|
||||||
|
{
|
||||||
|
MinSize = 5,
|
||||||
|
PreferredSize = 5,
|
||||||
|
MaxSize = 10
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = _validator.TestValidate(resource);
|
||||||
|
|
||||||
|
result.ShouldNotHaveAnyValidationErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Validate_fails_when_all_sizes_are_provided_and_invalid()
|
||||||
|
{
|
||||||
|
var resource = new QualityDefinitionResource
|
||||||
|
{
|
||||||
|
MinSize = 15,
|
||||||
|
PreferredSize = 10,
|
||||||
|
MaxSize = 5
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = _validator.TestValidate(resource);
|
||||||
|
|
||||||
|
result.ShouldHaveValidationErrorFor(r => r.MinSize)
|
||||||
|
.WithErrorCode("LessThanOrEqualTo");
|
||||||
|
|
||||||
|
result.ShouldHaveValidationErrorFor(r => r.MaxSize)
|
||||||
|
.WithErrorCode("GreaterThanOrEqualTo");
|
||||||
|
|
||||||
|
result.ShouldHaveValidationErrorFor(r => r.PreferredSize)
|
||||||
|
.WithErrorCode("GreaterThanOrEqualTo");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Validate_passes_when_preferred_size_is_valid_within_limits()
|
||||||
|
{
|
||||||
|
var resource = new QualityDefinitionResource
|
||||||
|
{
|
||||||
|
MinSize = 5,
|
||||||
|
PreferredSize = 7,
|
||||||
|
MaxSize = 10
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = _validator.TestValidate(resource);
|
||||||
|
|
||||||
|
result.ShouldNotHaveAnyValidationErrors();
|
||||||
|
}
|
||||||
|
}
|
||||||
7
src/NzbDrone.Core/Qualities/QualityDefinitionLimits.cs
Normal file
7
src/NzbDrone.Core/Qualities/QualityDefinitionLimits.cs
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace NzbDrone.Core.Qualities;
|
||||||
|
|
||||||
|
public static class QualityDefinitionLimits
|
||||||
|
{
|
||||||
|
public const int Min = 0;
|
||||||
|
public const int Max = 2000;
|
||||||
|
}
|
||||||
|
|
@ -12,14 +12,21 @@
|
||||||
namespace Radarr.Api.V3.Qualities
|
namespace Radarr.Api.V3.Qualities
|
||||||
{
|
{
|
||||||
[V3ApiController]
|
[V3ApiController]
|
||||||
public class QualityDefinitionController : RestControllerWithSignalR<QualityDefinitionResource, QualityDefinition>, IHandle<CommandExecutedEvent>
|
public class QualityDefinitionController :
|
||||||
|
RestControllerWithSignalR<QualityDefinitionResource, QualityDefinition>,
|
||||||
|
IHandle<CommandExecutedEvent>
|
||||||
{
|
{
|
||||||
private readonly IQualityDefinitionService _qualityDefinitionService;
|
private readonly IQualityDefinitionService _qualityDefinitionService;
|
||||||
|
|
||||||
public QualityDefinitionController(IQualityDefinitionService qualityDefinitionService, IBroadcastSignalRMessage signalRBroadcaster)
|
public QualityDefinitionController(
|
||||||
|
IQualityDefinitionService qualityDefinitionService,
|
||||||
|
IBroadcastSignalRMessage signalRBroadcaster)
|
||||||
: base(signalRBroadcaster)
|
: base(signalRBroadcaster)
|
||||||
{
|
{
|
||||||
_qualityDefinitionService = qualityDefinitionService;
|
_qualityDefinitionService = qualityDefinitionService;
|
||||||
|
|
||||||
|
SharedValidator.RuleFor(c => c)
|
||||||
|
.SetValidator(new QualityDefinitionResourceValidator());
|
||||||
}
|
}
|
||||||
|
|
||||||
[RestPutById]
|
[RestPutById]
|
||||||
|
|
@ -45,9 +52,7 @@ public List<QualityDefinitionResource> GetAll()
|
||||||
public object UpdateMany([FromBody] List<QualityDefinitionResource> resource)
|
public object UpdateMany([FromBody] List<QualityDefinitionResource> resource)
|
||||||
{
|
{
|
||||||
// Read from request
|
// Read from request
|
||||||
var qualityDefinitions = resource
|
var qualityDefinitions = resource.ToModel().ToList();
|
||||||
.ToModel()
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
_qualityDefinitionService.UpdateMany(qualityDefinitions);
|
_qualityDefinitionService.UpdateMany(qualityDefinitions);
|
||||||
|
|
||||||
|
|
@ -55,6 +60,14 @@ public object UpdateMany([FromBody] List<QualityDefinitionResource> resource)
|
||||||
.ToResource());
|
.ToResource());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("limits")]
|
||||||
|
public ActionResult<QualityDefinitionLimitsResource> GetLimits()
|
||||||
|
{
|
||||||
|
return Ok(new QualityDefinitionLimitsResource(
|
||||||
|
QualityDefinitionLimits.Min,
|
||||||
|
QualityDefinitionLimits.Max));
|
||||||
|
}
|
||||||
|
|
||||||
[NonAction]
|
[NonAction]
|
||||||
public void Handle(CommandExecutedEvent message)
|
public void Handle(CommandExecutedEvent message)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
namespace Radarr.Api.V3.Qualities;
|
||||||
|
|
||||||
|
// SA1313 still applies to records until https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3181 is available in a release build.
|
||||||
|
#pragma warning disable SA1313
|
||||||
|
public record QualityDefinitionLimitsResource(int Min, int Max);
|
||||||
|
#pragma warning restore SA1313
|
||||||
|
|
@ -8,11 +8,8 @@ namespace Radarr.Api.V3.Qualities
|
||||||
public class QualityDefinitionResource : RestResource
|
public class QualityDefinitionResource : RestResource
|
||||||
{
|
{
|
||||||
public Quality Quality { get; set; }
|
public Quality Quality { get; set; }
|
||||||
|
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
|
|
||||||
public int Weight { get; set; }
|
public int Weight { get; set; }
|
||||||
|
|
||||||
public double? MinSize { get; set; }
|
public double? MinSize { get; set; }
|
||||||
public double? MaxSize { get; set; }
|
public double? MaxSize { get; set; }
|
||||||
public double? PreferredSize { get; set; }
|
public double? PreferredSize { get; set; }
|
||||||
|
|
@ -30,13 +27,9 @@ public static QualityDefinitionResource ToResource(this QualityDefinition model)
|
||||||
return new QualityDefinitionResource
|
return new QualityDefinitionResource
|
||||||
{
|
{
|
||||||
Id = model.Id,
|
Id = model.Id,
|
||||||
|
|
||||||
Quality = model.Quality,
|
Quality = model.Quality,
|
||||||
|
|
||||||
Title = model.Title,
|
Title = model.Title,
|
||||||
|
|
||||||
Weight = model.Weight,
|
Weight = model.Weight,
|
||||||
|
|
||||||
MinSize = model.MinSize,
|
MinSize = model.MinSize,
|
||||||
MaxSize = model.MaxSize,
|
MaxSize = model.MaxSize,
|
||||||
PreferredSize = model.PreferredSize
|
PreferredSize = model.PreferredSize
|
||||||
|
|
@ -53,13 +46,9 @@ public static QualityDefinition ToModel(this QualityDefinitionResource resource)
|
||||||
return new QualityDefinition
|
return new QualityDefinition
|
||||||
{
|
{
|
||||||
Id = resource.Id,
|
Id = resource.Id,
|
||||||
|
|
||||||
Quality = resource.Quality,
|
Quality = resource.Quality,
|
||||||
|
|
||||||
Title = resource.Title,
|
Title = resource.Title,
|
||||||
|
|
||||||
Weight = resource.Weight,
|
Weight = resource.Weight,
|
||||||
|
|
||||||
MinSize = resource.MinSize,
|
MinSize = resource.MinSize,
|
||||||
MaxSize = resource.MaxSize,
|
MaxSize = resource.MaxSize,
|
||||||
PreferredSize = resource.PreferredSize
|
PreferredSize = resource.PreferredSize
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
using FluentValidation;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
|
||||||
|
namespace Radarr.Api.V3.Qualities;
|
||||||
|
|
||||||
|
public class QualityDefinitionResourceValidator : AbstractValidator<QualityDefinitionResource>
|
||||||
|
{
|
||||||
|
public QualityDefinitionResourceValidator()
|
||||||
|
{
|
||||||
|
RuleFor(c => c.MinSize)
|
||||||
|
.GreaterThanOrEqualTo(QualityDefinitionLimits.Min)
|
||||||
|
.WithErrorCode("GreaterThanOrEqualTo")
|
||||||
|
.LessThanOrEqualTo(c => c.PreferredSize ?? QualityDefinitionLimits.Max)
|
||||||
|
.WithErrorCode("LessThanOrEqualTo")
|
||||||
|
.When(c => c.MinSize is not null);
|
||||||
|
|
||||||
|
RuleFor(c => c.PreferredSize)
|
||||||
|
.GreaterThanOrEqualTo(c => c.MinSize ?? QualityDefinitionLimits.Min)
|
||||||
|
.WithErrorCode("GreaterThanOrEqualTo")
|
||||||
|
.LessThanOrEqualTo(c => c.MaxSize ?? QualityDefinitionLimits.Max)
|
||||||
|
.WithErrorCode("LessThanOrEqualTo")
|
||||||
|
.When(c => c.PreferredSize is not null);
|
||||||
|
|
||||||
|
RuleFor(c => c.MaxSize)
|
||||||
|
.GreaterThanOrEqualTo(c => c.PreferredSize ?? QualityDefinitionLimits.Min)
|
||||||
|
.WithErrorCode("GreaterThanOrEqualTo")
|
||||||
|
.LessThanOrEqualTo(QualityDefinitionLimits.Max)
|
||||||
|
.WithErrorCode("LessThanOrEqualTo")
|
||||||
|
.When(c => c.MaxSize is not null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -69,11 +69,15 @@ public override void OnActionExecuting(ActionExecutingContext context)
|
||||||
var skipValidate = skipAttribute?.Skip ?? false;
|
var skipValidate = skipAttribute?.Skip ?? false;
|
||||||
var skipShared = skipAttribute?.SkipShared ?? false;
|
var skipShared = skipAttribute?.SkipShared ?? false;
|
||||||
|
|
||||||
if (Request.Method == "POST" || Request.Method == "PUT")
|
if (Request.Method is "POST" or "PUT")
|
||||||
{
|
{
|
||||||
var resourceArgs = context.ActionArguments.Values.Where(x => x.GetType() == typeof(TResource))
|
var resourceArgs = context.ActionArguments.Values
|
||||||
.Select(x => x as TResource)
|
.SelectMany(x => x switch
|
||||||
.ToList();
|
{
|
||||||
|
TResource single => new[] { single },
|
||||||
|
IEnumerable<TResource> multiple => multiple,
|
||||||
|
_ => Enumerable.Empty<TResource>()
|
||||||
|
});
|
||||||
|
|
||||||
foreach (var resource in resourceArgs)
|
foreach (var resource in resourceArgs)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue