mirror of
https://github.com/Sonarr/Sonarr
synced 2026-05-08 21:21:47 +02:00
Fix: Validate release/push download client configuration
This commit is contained in:
parent
a4f210855e
commit
b197a2d9cb
2 changed files with 244 additions and 7 deletions
|
|
@ -0,0 +1,173 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FluentValidation;
|
||||
using Moq;
|
||||
using NLog;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Profiles.Qualities;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Test.Common;
|
||||
using Sonarr.Api.V3.Indexers;
|
||||
|
||||
namespace NzbDrone.Api.Test.v3.Indexers;
|
||||
|
||||
[TestFixture]
|
||||
public class ReleasePushControllerFixture : TestBase<ReleasePushController>
|
||||
{
|
||||
[SetUp]
|
||||
public void SetupController()
|
||||
{
|
||||
var qualityProfile = new QualityProfile
|
||||
{
|
||||
Items = new List<QualityProfileQualityItem>
|
||||
{
|
||||
new()
|
||||
{
|
||||
Allowed = true,
|
||||
Quality = Quality.Bluray720p
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Mocker.SetConstant(LogManager.GetLogger(nameof(ReleasePushControllerFixture)));
|
||||
|
||||
Mocker.GetMock<IQualityProfileService>()
|
||||
.Setup(x => x.GetDefaultProfile(It.IsAny<string>()))
|
||||
.Returns(qualityProfile);
|
||||
}
|
||||
|
||||
private ReleaseResource BuildRelease(Action<ReleaseResource> configure = null)
|
||||
{
|
||||
var resource = new ReleaseResource
|
||||
{
|
||||
Title = "Test Release",
|
||||
DownloadUrl = "https://example.com/release.torrent",
|
||||
PublishDate = DateTime.UtcNow,
|
||||
Protocol = DownloadProtocol.Torrent
|
||||
};
|
||||
|
||||
configure?.Invoke(resource);
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_fail_when_download_client_name_unknown()
|
||||
{
|
||||
Mocker.GetMock<IDownloadClientFactory>()
|
||||
.Setup(x => x.All())
|
||||
.Returns(new List<DownloadClientDefinition>());
|
||||
|
||||
var release = BuildRelease(r => r.DownloadClient = "missing-client");
|
||||
|
||||
var exception = Assert.Throws<ValidationException>(() => Subject.Create(release));
|
||||
|
||||
Assert.That(exception, Is.Not.Null);
|
||||
Assert.That(exception!.Errors.Select(e => e.PropertyName), Does.Contain("DownloadClient"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_fail_when_download_client_name_disabled()
|
||||
{
|
||||
var disabledClient = new DownloadClientDefinition
|
||||
{
|
||||
Id = 5,
|
||||
Name = "Disabled Client",
|
||||
Enable = false
|
||||
};
|
||||
|
||||
Mocker.GetMock<IDownloadClientFactory>()
|
||||
.Setup(x => x.All())
|
||||
.Returns(new List<DownloadClientDefinition> { disabledClient });
|
||||
|
||||
var release = BuildRelease(r => r.DownloadClient = "Disabled Client");
|
||||
|
||||
var exception = Assert.Throws<ValidationException>(() => Subject.Create(release));
|
||||
|
||||
Assert.That(exception, Is.Not.Null);
|
||||
Assert.That(exception!.Errors.Select(e => e.PropertyName), Does.Contain("DownloadClient"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_fail_when_download_client_id_unknown()
|
||||
{
|
||||
const int requestedId = 42;
|
||||
|
||||
Mocker.GetMock<IDownloadClientFactory>()
|
||||
.Setup(x => x.Get(requestedId))
|
||||
.Throws(new ModelNotFoundException(typeof(DownloadClientDefinition), requestedId));
|
||||
|
||||
var release = BuildRelease(r => r.DownloadClientId = requestedId);
|
||||
|
||||
var exception = Assert.Throws<ValidationException>(() => Subject.Create(release));
|
||||
|
||||
Assert.That(exception, Is.Not.Null);
|
||||
Assert.That(exception!.Errors.Select(e => e.PropertyName), Does.Contain("DownloadClientId"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_fail_when_download_client_id_disabled()
|
||||
{
|
||||
const int requestedId = 11;
|
||||
|
||||
var disabledClient = new DownloadClientDefinition
|
||||
{
|
||||
Id = requestedId,
|
||||
Name = "Disabled Client",
|
||||
Enable = false
|
||||
};
|
||||
|
||||
Mocker.GetMock<IDownloadClientFactory>()
|
||||
.Setup(x => x.Get(requestedId))
|
||||
.Returns(disabledClient);
|
||||
|
||||
var release = BuildRelease(r => r.DownloadClientId = requestedId);
|
||||
|
||||
var exception = Assert.Throws<ValidationException>(() => Subject.Create(release));
|
||||
|
||||
Assert.That(exception, Is.Not.Null);
|
||||
Assert.That(exception!.Errors.Select(e => e.PropertyName), Does.Contain("DownloadClientId"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_fail_when_download_client_name_and_id_mismatch()
|
||||
{
|
||||
const int requestedId = 7;
|
||||
var definitionByName = new DownloadClientDefinition
|
||||
{
|
||||
Id = 21,
|
||||
Name = "Known Client",
|
||||
Enable = true
|
||||
};
|
||||
var definitionById = new DownloadClientDefinition
|
||||
{
|
||||
Id = requestedId,
|
||||
Name = "Different Client",
|
||||
Enable = true
|
||||
};
|
||||
|
||||
Mocker.GetMock<IDownloadClientFactory>()
|
||||
.Setup(x => x.All())
|
||||
.Returns(new List<DownloadClientDefinition> { definitionByName });
|
||||
|
||||
Mocker.GetMock<IDownloadClientFactory>()
|
||||
.Setup(x => x.Get(requestedId))
|
||||
.Returns(definitionById);
|
||||
|
||||
var release = BuildRelease(r =>
|
||||
{
|
||||
r.DownloadClient = "Known Client";
|
||||
r.DownloadClientId = requestedId;
|
||||
});
|
||||
|
||||
var exception = Assert.Throws<ValidationException>(() => Subject.Create(release));
|
||||
|
||||
Assert.That(exception, Is.Not.Null);
|
||||
var properties = exception!.Errors.Select(e => e.PropertyName).ToList();
|
||||
Assert.That(properties, Does.Contain("DownloadClient"));
|
||||
Assert.That(properties, Does.Contain("DownloadClientId"));
|
||||
}
|
||||
}
|
||||
|
|
@ -120,20 +120,84 @@ private void ResolveIndexer(ReleaseInfo release)
|
|||
|
||||
private int? ResolveDownloadClientId(ReleaseResource release)
|
||||
{
|
||||
var downloadClientId = release.DownloadClientId.GetValueOrDefault();
|
||||
var requestedId = release.DownloadClientId.GetValueOrDefault();
|
||||
var requestedName = release.DownloadClient?.Trim();
|
||||
var resolvedClientByName = default(DownloadClientDefinition);
|
||||
var resolvedClient = default(DownloadClientDefinition);
|
||||
|
||||
if (downloadClientId == 0 && release.DownloadClient.IsNotNullOrWhiteSpace())
|
||||
if (requestedName.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
var downloadClient = _downloadClientFactory.All().FirstOrDefault(v => v.Name.EqualsIgnoreCase(release.DownloadClient));
|
||||
resolvedClientByName = _downloadClientFactory.All()
|
||||
.FirstOrDefault(v => v.Name.EqualsIgnoreCase(requestedName));
|
||||
|
||||
if (downloadClient != null)
|
||||
if (resolvedClientByName != null)
|
||||
{
|
||||
_logger.Debug("Push Release {0} associated with download client {1} - {2}.", release.Title, downloadClientId, release.DownloadClient);
|
||||
if (!resolvedClientByName.Enable)
|
||||
{
|
||||
throw new ValidationException(new List<ValidationFailure>
|
||||
{
|
||||
new("DownloadClient", "Download client is disabled.", requestedName)
|
||||
});
|
||||
}
|
||||
|
||||
return downloadClient.Id;
|
||||
release.DownloadClient = resolvedClientByName.Name;
|
||||
resolvedClient = resolvedClientByName;
|
||||
}
|
||||
else if (requestedId == 0)
|
||||
{
|
||||
throw new ValidationException(new List<ValidationFailure>
|
||||
{
|
||||
new("DownloadClient", "Download client does not exist.", requestedName)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (requestedId != 0)
|
||||
{
|
||||
DownloadClientDefinition clientById;
|
||||
|
||||
try
|
||||
{
|
||||
clientById = _downloadClientFactory.Get(requestedId);
|
||||
}
|
||||
catch (ModelNotFoundException)
|
||||
{
|
||||
throw new ValidationException(new List<ValidationFailure>
|
||||
{
|
||||
new("DownloadClientId", "Download client does not exist.", requestedId.ToString())
|
||||
});
|
||||
}
|
||||
|
||||
_logger.Debug("Push Release {0} not associated with known download client {1}.", release.Title, release.DownloadClient);
|
||||
if (resolvedClientByName != null && clientById.Id != resolvedClientByName.Id)
|
||||
{
|
||||
throw new ValidationException(new List<ValidationFailure>
|
||||
{
|
||||
new("DownloadClientId", "Download client id does not match the provided name.", requestedId.ToString()),
|
||||
new("DownloadClient", "Download client name does not match the provided id.", requestedName)
|
||||
});
|
||||
}
|
||||
|
||||
if (!clientById.Enable)
|
||||
{
|
||||
throw new ValidationException(new List<ValidationFailure>
|
||||
{
|
||||
new("DownloadClientId", "Download client is disabled.", requestedId.ToString())
|
||||
});
|
||||
}
|
||||
|
||||
if (resolvedClientByName == null && requestedName.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
release.DownloadClient = clientById.Name;
|
||||
}
|
||||
|
||||
resolvedClient = clientById;
|
||||
}
|
||||
|
||||
if (resolvedClient != null)
|
||||
{
|
||||
_logger.Debug("Push Release {0} associated with download client {1} - {2}.", release.Title, resolvedClient.Id, resolvedClient.Name);
|
||||
|
||||
return resolvedClient.Id;
|
||||
}
|
||||
|
||||
return release.DownloadClientId;
|
||||
|
|
|
|||
Loading…
Reference in a new issue