Fixed: Added /transmission/ part to UrlBase in Transmission settings making it configurable.

fixes #556
pull/4/head
Taloth Saldono 10 years ago
parent fb02499823
commit dc91fa0206

@ -27,24 +27,23 @@ namespace NzbDrone.Api.Config
GetResourceById = GetHostConfig; GetResourceById = GetHostConfig;
UpdateResource = SaveHostConfig; UpdateResource = SaveHostConfig;
SharedValidator.RuleFor(c => c.Branch).NotEmpty().WithMessage("Branch name is required, 'master' is the default"); SharedValidator.RuleFor(c => c.BindAddress)
.ValidIp4Address()
.NotListenAllIp4Address()
.When(c => c.BindAddress != "*");
SharedValidator.RuleFor(c => c.Port).ValidPort(); SharedValidator.RuleFor(c => c.Port).ValidPort();
SharedValidator.RuleFor(c => c.UrlBase).ValidUrlBase();
SharedValidator.RuleFor(c => c.Username).NotEmpty().When(c => c.AuthenticationMethod != AuthenticationType.None); SharedValidator.RuleFor(c => c.Username).NotEmpty().When(c => c.AuthenticationMethod != AuthenticationType.None);
SharedValidator.RuleFor(c => c.Password).NotEmpty().When(c => c.AuthenticationMethod != AuthenticationType.None); SharedValidator.RuleFor(c => c.Password).NotEmpty().When(c => c.AuthenticationMethod != AuthenticationType.None);
SharedValidator.RuleFor(c => c.SslPort).ValidPort().When(c => c.EnableSsl); SharedValidator.RuleFor(c => c.SslPort).ValidPort().When(c => c.EnableSsl);
SharedValidator.RuleFor(c => c.SslCertHash).NotEmpty().When(c => c.EnableSsl && OsInfo.IsWindows); SharedValidator.RuleFor(c => c.SslCertHash).NotEmpty().When(c => c.EnableSsl && OsInfo.IsWindows);
SharedValidator.RuleFor(c => c.Branch).NotEmpty().WithMessage("Branch name is required, 'master' is the default");
SharedValidator.RuleFor(c => c.UpdateScriptPath).IsValidPath().When(c => c.UpdateMechanism == UpdateMechanism.Script); SharedValidator.RuleFor(c => c.UpdateScriptPath).IsValidPath().When(c => c.UpdateMechanism == UpdateMechanism.Script);
SharedValidator.RuleFor(c => c.BindAddress)
.ValidIp4Address()
.NotListenAllIp4Address()
.When(c => c.BindAddress != "*");
SharedValidator.RuleFor(c => c.UrlBase)
.ValidUrlBase();
} }
private HostConfigResource GetHostConfig() private HostConfigResource GetHostConfig()

@ -9,7 +9,7 @@ using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Migration namespace NzbDrone.Core.Test.Datastore.Migration
{ {
[TestFixture] [TestFixture]
public class disable_eztv : MigrationTest<Core.Datastore.Migration.disable_eztv> public class disable_eztvFixture : MigrationTest<Core.Datastore.Migration.disable_eztv>
{ {
[Test] [Test]
public void should_disable_rss_for_eztv() public void should_disable_rss_for_eztv()

@ -10,7 +10,7 @@ using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.Datastore.Migration namespace NzbDrone.Core.Test.Datastore.Migration
{ {
[TestFixture] [TestFixture]
public class dedupe_tags : MigrationTest<Core.Datastore.Migration.dedupe_tags> public class dedupe_tagsFixture : MigrationTest<Core.Datastore.Migration.dedupe_tags>
{ {
[Test] [Test]
public void should_not_fail_if_series_tags_are_null() public void should_not_fail_if_series_tags_are_null()

@ -11,7 +11,7 @@ using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Migration namespace NzbDrone.Core.Test.Datastore.Migration
{ {
[TestFixture] [TestFixture]
public class move_dot_prefix_to_transmission_category : MigrationTest<Core.Datastore.Migration.move_dot_prefix_to_transmission_category> public class move_dot_prefix_to_transmission_categoryFixture : MigrationTest<Core.Datastore.Migration.move_dot_prefix_to_transmission_category>
{ {
[Test] [Test]
public void should_not_fail_if_no_transmission() public void should_not_fail_if_no_transmission()

@ -8,7 +8,7 @@ using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Migration namespace NzbDrone.Core.Test.Datastore.Migration
{ {
[TestFixture] [TestFixture]
public class update_quality_minmax_size : MigrationTest<Core.Datastore.Migration.update_quality_minmax_size> public class update_quality_minmax_sizeFixture : MigrationTest<Core.Datastore.Migration.update_quality_minmax_size>
{ {
[Test] [Test]
public void should_not_fail_if_empty() public void should_not_fail_if_empty()

@ -0,0 +1,98 @@
using System;
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Download;
using NzbDrone.Core.Download.Clients.Deluge;
using NzbDrone.Core.Download.Clients.Sabnzbd;
using NzbDrone.Core.Download.Clients.Transmission;
using NzbDrone.Core.Test.Framework;
using System.Drawing;
namespace NzbDrone.Core.Test.Datastore.Migration
{
[TestFixture]
public class expand_transmission_urlbaseFixture : MigrationTest<Core.Datastore.Migration.expand_transmission_urlbase>
{
[Test]
public void should_not_fail_if_no_transmission()
{
WithTestDb(c =>
{
c.Insert.IntoTable("DownloadClients").Row(new
{
Enable = 1,
Name = "Deluge",
Implementation = "Deluge",
Settings = new DelugeSettings
{
Host = "127.0.0.1",
TvCategory = "abc",
UrlBase = "/my/"
}.ToJson(),
ConfigContract = "DelugeSettings"
});
});
var items = Mocker.Resolve<DownloadClientRepository>().All();
items.Should().HaveCount(1);
items.First().Settings.As<DelugeSettings>().UrlBase.Should().Be("/my/");
}
[Test]
public void should_be_updated_for_transmission()
{
WithTestDb(c =>
{
c.Insert.IntoTable("DownloadClients").Row(new
{
Enable = 1,
Name = "Trans",
Implementation = "Transmission",
Settings = new TransmissionSettings
{
Host = "127.0.0.1",
TvCategory = "abc",
UrlBase = null
}.ToJson(),
ConfigContract = "TransmissionSettings"
});
});
var items = Mocker.Resolve<DownloadClientRepository>().All();
items.Should().HaveCount(1);
items.First().Settings.As<TransmissionSettings>().UrlBase.Should().Be("/transmission/");
}
[Test]
public void should_be_append_to_existing_urlbase()
{
WithTestDb(c =>
{
c.Insert.IntoTable("DownloadClients").Row(new
{
Enable = 1,
Name = "Trans",
Implementation = "Transmission",
Settings = new TransmissionSettings
{
Host = "127.0.0.1",
TvCategory = "abc",
UrlBase = "/my/url/"
}.ToJson(),
ConfigContract = "TransmissionSettings"
});
});
var items = Mocker.Resolve<DownloadClientRepository>().All();
items.Should().HaveCount(1);
items.First().Settings.As<TransmissionSettings>().UrlBase.Should().Be("/my/url/transmission/");
}
}
}

@ -118,9 +118,10 @@
<Compile Include="Datastore\MappingExtentionFixture.cs" /> <Compile Include="Datastore\MappingExtentionFixture.cs" />
<Compile Include="Datastore\MarrDataLazyLoadingFixture.cs" /> <Compile Include="Datastore\MarrDataLazyLoadingFixture.cs" />
<Compile Include="Datastore\Migration\071_unknown_quality_in_profileFixture.cs" /> <Compile Include="Datastore\Migration\071_unknown_quality_in_profileFixture.cs" />
<Compile Include="Datastore\Migration\074_disable_eztv.cs" /> <Compile Include="Datastore\Migration\074_disable_eztvFixture.cs" />
<Compile Include="Datastore\Migration\072_history_grabIdFixture.cs" /> <Compile Include="Datastore\Migration\072_history_grabIdFixture.cs" />
<Compile Include="Datastore\Migration\070_delay_profileFixture.cs" /> <Compile Include="Datastore\Migration\070_delay_profileFixture.cs" />
<Compile Include="Datastore\Migration\085_expand_transmission_urlbaseFixture.cs" />
<Compile Include="Datastore\Migration\084_update_quality_minmax_sizeFixture.cs" /> <Compile Include="Datastore\Migration\084_update_quality_minmax_sizeFixture.cs" />
<Compile Include="Datastore\Migration\081_move_dot_prefix_to_transmission_categoryFixture.cs" /> <Compile Include="Datastore\Migration\081_move_dot_prefix_to_transmission_categoryFixture.cs" />
<Compile Include="Datastore\Migration\079_dedupe_tagsFixture.cs" /> <Compile Include="Datastore\Migration\079_dedupe_tagsFixture.cs" />

@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using FluentMigrator;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(85)]
public class expand_transmission_urlbase : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Execute.WithConnection(UpdateTransmissionSettings);
}
private void UpdateTransmissionSettings(IDbConnection conn, IDbTransaction tran)
{
using (var cmd = conn.CreateCommand())
{
cmd.Transaction = tran;
cmd.CommandText = "SELECT Id, Settings FROM DownloadClients WHERE Implementation = 'Transmission'";
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
var id = reader.GetInt32(0);
var settingsJson = reader.GetString(1);
var settings = Json.Deserialize<Dictionary<string, object>>(settingsJson);
var urlBase = settings.GetValueOrDefault("urlBase", "") as string;
if (urlBase.IsNullOrWhiteSpace())
{
settings["urlBase"] = "/transmission/";
}
else
{
settings["urlBase"] = string.Format("/{0}/transmission/", urlBase.Trim('/'));
}
using (var updateCmd = conn.CreateCommand())
{
updateCmd.Transaction = tran;
updateCmd.CommandText = "UPDATE DownloadClients SET Settings = ? WHERE Id = ?";
updateCmd.AddParameter(settings.ToJson());
updateCmd.AddParameter(id);
updateCmd.ExecuteNonQuery();
}
}
}
}
}
}
}

@ -260,15 +260,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission
{ {
var protocol = settings.UseSsl ? "https" : "http"; var protocol = settings.UseSsl ? "https" : "http";
String url; var url = String.Format(@"{0}://{1}:{2}/{3}/rpc", protocol, settings.Host, settings.Port, settings.UrlBase.Trim('/'));
if (!settings.UrlBase.IsNullOrWhiteSpace())
{
url = String.Format(@"{0}://{1}:{2}/{3}/transmission/rpc", protocol, settings.Host, settings.Port, settings.UrlBase.Trim('/'));
}
else
{
url = String.Format(@"{0}://{1}:{2}/transmission/rpc", protocol, settings.Host, settings.Port);
}
var restClient = RestClientFactory.BuildClient(url); var restClient = RestClientFactory.BuildClient(url);
restClient.FollowRedirects = false; restClient.FollowRedirects = false;

@ -13,6 +13,8 @@ namespace NzbDrone.Core.Download.Clients.Transmission
RuleFor(c => c.Host).ValidHost(); RuleFor(c => c.Host).ValidHost();
RuleFor(c => c.Port).GreaterThan(0); RuleFor(c => c.Port).GreaterThan(0);
RuleFor(c => c.UrlBase).ValidUrlBase();
RuleFor(c => c.TvCategory).Matches(@"^\.?[-a-z]*$").WithMessage("Allowed characters a-z and -"); RuleFor(c => c.TvCategory).Matches(@"^\.?[-a-z]*$").WithMessage("Allowed characters a-z and -");
} }
} }
@ -25,6 +27,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission
{ {
Host = "localhost"; Host = "localhost";
Port = 9091; Port = 9091;
UrlBase = "/transmission/";
} }
[FieldDefinition(0, Label = "Host", Type = FieldType.Textbox)] [FieldDefinition(0, Label = "Host", Type = FieldType.Textbox)]
@ -33,7 +36,7 @@ namespace NzbDrone.Core.Download.Clients.Transmission
[FieldDefinition(1, Label = "Port", Type = FieldType.Textbox)] [FieldDefinition(1, Label = "Port", Type = FieldType.Textbox)]
public Int32 Port { get; set; } public Int32 Port { get; set; }
[FieldDefinition(2, Label = "Url Base", Type = FieldType.Textbox, Advanced = true, HelpText = "Adds a prefix to the transmission rpc url, see http://[host]:[port]/[urlBase]/transmission/rpc")] [FieldDefinition(2, Label = "Url Base", Type = FieldType.Textbox, Advanced = true, HelpText = "Adds a prefix to the transmission rpc url, eg http://[host]:[port]/[urlBase]/rpc, defaults to '/transmission/'")]
public String UrlBase { get; set; } public String UrlBase { get; set; }
[FieldDefinition(3, Label = "Username", Type = FieldType.Textbox)] [FieldDefinition(3, Label = "Username", Type = FieldType.Textbox)]

@ -253,6 +253,7 @@
<Compile Include="Datastore\Migration\074_disable_eztv.cs" /> <Compile Include="Datastore\Migration\074_disable_eztv.cs" />
<Compile Include="Datastore\Migration\073_clear_ratings.cs" /> <Compile Include="Datastore\Migration\073_clear_ratings.cs" />
<Compile Include="Datastore\Migration\077_add_add_options_to_series.cs" /> <Compile Include="Datastore\Migration\077_add_add_options_to_series.cs" />
<Compile Include="Datastore\Migration\085_expand_transmission_urlbase.cs" />
<Compile Include="Datastore\Migration\081_move_dot_prefix_to_transmission_category.cs" /> <Compile Include="Datastore\Migration\081_move_dot_prefix_to_transmission_category.cs" />
<Compile Include="Datastore\Migration\079_dedupe_tags.cs" /> <Compile Include="Datastore\Migration\079_dedupe_tags.cs" />
<Compile Include="Datastore\Migration\070_delay_profile.cs" /> <Compile Include="Datastore\Migration\070_delay_profile.cs" />

@ -34,6 +34,11 @@ namespace NzbDrone.Core.Validation
return ruleBuilder.SetValidator(new RegularExpressionValidator("^https?://[-a-z0-9.]+", RegexOptions.IgnoreCase)).WithMessage("must be valid URL that starts with http(s)://"); return ruleBuilder.SetValidator(new RegularExpressionValidator("^https?://[-a-z0-9.]+", RegexOptions.IgnoreCase)).WithMessage("must be valid URL that starts with http(s)://");
} }
public static IRuleBuilderOptions<T, string> ValidUrlBase<T>(this IRuleBuilder<T, string> ruleBuilder)
{
return ruleBuilder.SetValidator(new RegularExpressionValidator(@"^(?!\/?https?://[-a-z0-9.]+)", RegexOptions.IgnoreCase)).WithMessage("Must be a valid URL path (ie: '/sonarr')");
}
public static IRuleBuilderOptions<T, int> ValidPort<T>(this IRuleBuilder<T, int> ruleBuilder) public static IRuleBuilderOptions<T, int> ValidPort<T>(this IRuleBuilder<T, int> ruleBuilder)
{ {
return ruleBuilder.SetValidator(new InclusiveBetweenValidator(1, 65535)) return ruleBuilder.SetValidator(new InclusiveBetweenValidator(1, 65535))
@ -62,10 +67,5 @@ namespace NzbDrone.Core.Validation
{ {
return ruleBuilder.WithState(v => NzbDroneValidationState.Warning); return ruleBuilder.WithState(v => NzbDroneValidationState.Warning);
} }
public static IRuleBuilderOptions<T, string> ValidUrlBase<T>(this IRuleBuilder<T, string> ruleBuilder)
{
return ruleBuilder.SetValidator(new RegularExpressionValidator(@"^(?!\/?https?://[-a-z0-9.]+)", RegexOptions.IgnoreCase)).WithMessage("Must be a valid URL path (ie: '/sonarr')");
}
} }
} }
Loading…
Cancel
Save