indexer specific setting validation

This commit is contained in:
kay.one 2013-08-22 01:08:43 -07:00
parent 227e13d858
commit e4fc0c57b3
11 changed files with 93 additions and 26 deletions

View File

@ -1,11 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using FluentValidation.Internal;
using NzbDrone.Api.ClientSchema; using NzbDrone.Api.ClientSchema;
using NzbDrone.Api.Mapping; using NzbDrone.Api.Mapping;
using NzbDrone.Api.REST; using NzbDrone.Api.REST;
using NzbDrone.Api.Validation;
using NzbDrone.Core.Indexers; using NzbDrone.Core.Indexers;
using Omu.ValueInjecter; using Omu.ValueInjecter;
using FluentValidation; using FluentValidation;
@ -28,8 +26,6 @@ namespace NzbDrone.Api.Indexers
SharedValidator.RuleFor(c => c.Name).NotEmpty(); SharedValidator.RuleFor(c => c.Name).NotEmpty();
SharedValidator.RuleFor(c => c.Implementation).NotEmpty(); SharedValidator.RuleFor(c => c.Implementation).NotEmpty();
SharedValidator.RuleForField<string>(c=>c.Fields,"Url").NotEmpty();
PostValidator.RuleFor(c => c.Fields).NotEmpty(); PostValidator.RuleFor(c => c.Fields).NotEmpty();
} }
@ -67,6 +63,9 @@ namespace NzbDrone.Api.Indexers
var indexer = _indexerService.Get(indexerResource.Id); var indexer = _indexerService.Get(indexerResource.Id);
indexer.InjectFrom(indexerResource); indexer.InjectFrom(indexerResource);
indexer.Settings = SchemaDeserializer.DeserializeSchema(indexer.Settings, indexerResource.Fields); indexer.Settings = SchemaDeserializer.DeserializeSchema(indexer.Settings, indexerResource.Fields);
ValidateSetting(indexer.Settings);
indexer = _indexerService.Update(indexer); indexer = _indexerService.Update(indexer);
var response = indexer.InjectTo<IndexerResource>(); var response = indexer.InjectTo<IndexerResource>();
@ -75,6 +74,17 @@ namespace NzbDrone.Api.Indexers
return response; return response;
} }
private static void ValidateSetting(IIndexerSetting setting)
{
var validationResult = setting.Validate();
if (!validationResult.IsValid)
{
throw new ValidationException(validationResult.Errors);
}
}
private Indexer GetIndexer(IndexerResource indexerResource) private Indexer GetIndexer(IndexerResource indexerResource)
{ {
var indexer = _indexerService.Schema() var indexer = _indexerService.Schema()
@ -90,6 +100,8 @@ namespace NzbDrone.Api.Indexers
indexer.InjectFrom(indexerResource); indexer.InjectFrom(indexerResource);
indexer.Settings = SchemaDeserializer.DeserializeSchema(indexer.Settings, indexerResource.Fields); indexer.Settings = SchemaDeserializer.DeserializeSchema(indexer.Settings, indexerResource.Fields);
ValidateSetting(indexer.Settings);
return indexer; return indexer;
} }

View File

@ -1,4 +1,5 @@
using FluentValidation; using System.Text.RegularExpressions;
using FluentValidation;
using FluentValidation.Validators; using FluentValidation.Validators;
namespace NzbDrone.Api.Validation namespace NzbDrone.Api.Validation
@ -14,5 +15,10 @@ namespace NzbDrone.Api.Validation
{ {
return ruleBuilder.SetValidator(new EqualValidator(0)); return ruleBuilder.SetValidator(new EqualValidator(0));
} }
public static IRuleBuilderOptions<T, string> HaveHttpProtocol<T>(this IRuleBuilder<T, string> ruleBuilder)
{
return ruleBuilder.SetValidator(new RegularExpressionValidator("^http(s)?://", RegexOptions.IgnoreCase)).WithMessage("must start with http:// or https://");
}
} }
} }

View File

@ -55,6 +55,9 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FluentMigrator.1.1.1.0\tools\FluentMigrator.Runner.dll</HintPath> <HintPath>..\packages\FluentMigrator.1.1.1.0\tools\FluentMigrator.Runner.dll</HintPath>
</Reference> </Reference>
<Reference Include="FluentValidation">
<HintPath>..\packages\FluentValidation.4.0.0.1\lib\Net40\FluentValidation.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.Practices.ServiceLocation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.Practices.ServiceLocation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>

View File

@ -4,6 +4,7 @@
<package id="CommonServiceLocator" version="1.0" targetFramework="net40" /> <package id="CommonServiceLocator" version="1.0" targetFramework="net40" />
<package id="FluentAssertions" version="2.0.1" targetFramework="net40" /> <package id="FluentAssertions" version="2.0.1" targetFramework="net40" />
<package id="FluentMigrator" version="1.1.1.0" targetFramework="net40" /> <package id="FluentMigrator" version="1.1.1.0" targetFramework="net40" />
<package id="FluentValidation" version="4.0.0.1" targetFramework="net40" />
<package id="Moq" version="4.0.10827" /> <package id="Moq" version="4.0.10827" />
<package id="NBuilder" version="3.0.1.1" /> <package id="NBuilder" version="3.0.1.1" />
<package id="NCrunch.Framework" version="1.46.0.9" targetFramework="net40" /> <package id="NCrunch.Framework" version="1.46.0.9" targetFramework="net40" />

View File

@ -1,26 +1,20 @@
namespace NzbDrone.Core.Indexers using FluentValidation.Results;
namespace NzbDrone.Core.Indexers
{ {
public interface IIndexerSetting public interface IIndexerSetting
{ {
bool IsValid { get; } ValidationResult Validate();
} }
public class NullSetting : IIndexerSetting public class NullSetting : IIndexerSetting
{ {
public static NullSetting Instance = new NullSetting(); public static readonly NullSetting Instance = new NullSetting();
private NullSetting() public ValidationResult Validate()
{ {
return new ValidationResult();
}
public bool IsValid
{
get
{
return true;
}
} }
} }
} }

View File

@ -53,7 +53,7 @@ namespace NzbDrone.Core.Indexers
public List<IIndexer> GetAvailableIndexers() public List<IIndexer> GetAvailableIndexers()
{ {
return All().Where(c => c.Enable && c.Settings.IsValid).Select(c => c.Instance).ToList(); return All().Where(c => c.Enable && c.Settings.Validate().IsValid).Select(c => c.Instance).ToList();
} }
public Indexer Get(int id) public Indexer Get(int id)

View File

@ -1,6 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using FluentValidation;
using FluentValidation.Results;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.Newznab namespace NzbDrone.Core.Indexers.Newznab
{ {
@ -9,6 +12,7 @@ namespace NzbDrone.Core.Indexers.Newznab
public NewznabSettings() public NewznabSettings()
{ {
Categories = new[] { 5030, 5040 }; Categories = new[] { 5030, 5040 };
//RuleFor(c => c.Url).ValidRootUrl();
} }
[FieldDefinition(0, Label = "URL")] [FieldDefinition(0, Label = "URL")]
@ -26,5 +30,11 @@ namespace NzbDrone.Core.Indexers.Newznab
return !string.IsNullOrWhiteSpace(Url); return !string.IsNullOrWhiteSpace(Url);
} }
} }
public ValidationResult Validate()
{
return new ValidationResult();
//return Validate(this);
}
} }
} }

View File

@ -1,22 +1,28 @@
using System; using System;
using FluentValidation;
using FluentValidation.Results;
using NzbDrone.Core.Annotations; using NzbDrone.Core.Annotations;
namespace NzbDrone.Core.Indexers.Omgwtfnzbs namespace NzbDrone.Core.Indexers.Omgwtfnzbs
{ {
public class OmgwtfnzbsSetting : IIndexerSetting public class OmgwtfnzbsSetting : AbstractValidator<OmgwtfnzbsSetting>, IIndexerSetting
{ {
public OmgwtfnzbsSetting()
{
RuleFor(c => c.Username).NotEmpty();
RuleFor(c => c.ApiKey).NotEmpty();
}
[FieldDefinition(0, Label = "Username")] [FieldDefinition(0, Label = "Username")]
public String Username { get; set; } public String Username { get; set; }
[FieldDefinition(1, Label = "API Key")] [FieldDefinition(1, Label = "API Key")]
public String ApiKey { get; set; } public String ApiKey { get; set; }
public bool IsValid
public ValidationResult Validate()
{ {
get return Validate(this);
{
return !string.IsNullOrWhiteSpace(Username) && !string.IsNullOrWhiteSpace(ApiKey);
}
} }
} }
} }

View File

@ -67,6 +67,10 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FluentMigrator.1.1.1.0\tools\FluentMigrator.Runner.dll</HintPath> <HintPath>..\packages\FluentMigrator.1.1.1.0\tools\FluentMigrator.Runner.dll</HintPath>
</Reference> </Reference>
<Reference Include="FluentValidation, Version=4.0.0.1, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FluentValidation.4.0.0.1\lib\Net40\FluentValidation.dll</HintPath>
</Reference>
<Reference Include="Growl.Connector"> <Reference Include="Growl.Connector">
<HintPath>..\packages\Growl.0.6\lib\Growl.Connector.dll</HintPath> <HintPath>..\packages\Growl.0.6\lib\Growl.Connector.dll</HintPath>
</Reference> </Reference>
@ -490,6 +494,7 @@
<Compile Include="Update\UpdatePackageProvider.cs" /> <Compile Include="Update\UpdatePackageProvider.cs" />
<Compile Include="Update\UpdatePackage.cs" /> <Compile Include="Update\UpdatePackage.cs" />
<Compile Include="Update\UpdateCheckService.cs" /> <Compile Include="Update\UpdateCheckService.cs" />
<Compile Include="Validation\RuleBuilderExtensions.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client"> <BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client">

View File

@ -0,0 +1,29 @@
using System.Text.RegularExpressions;
using FluentValidation;
using FluentValidation.Validators;
namespace NzbDrone.Core.Validation
{
public static class RuleBuilderExtensions
{
public static IRuleBuilderOptions<T, int> ValidId<T>(this IRuleBuilder<T, int> ruleBuilder)
{
return ruleBuilder.SetValidator(new GreaterThanValidator(0));
}
public static IRuleBuilderOptions<T, int> IsZero<T>(this IRuleBuilder<T, int> ruleBuilder)
{
return ruleBuilder.SetValidator(new EqualValidator(0));
}
public static IRuleBuilderOptions<T, string> HaveHttpProtocol<T>(this IRuleBuilder<T, string> ruleBuilder)
{
return ruleBuilder.SetValidator(new RegularExpressionValidator("^http(s)?://", RegexOptions.IgnoreCase)).WithMessage("must start with http:// or https://");
}
public static IRuleBuilderOptions<T, string> ValidRootUrl<T>(this IRuleBuilder<T, string> ruleBuilder)
{
return ruleBuilder.SetValidator(new RegularExpressionValidator("^http(?:s)?://[a-z0-9-.]+", RegexOptions.IgnoreCase)).WithMessage("must be valid URL that");
}
}
}

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="FluentMigrator" version="1.1.1.0" targetFramework="net40" /> <package id="FluentMigrator" version="1.1.1.0" targetFramework="net40" />
<package id="FluentValidation" version="4.0.0.1" targetFramework="net40" />
<package id="Growl" version="0.6" /> <package id="Growl" version="0.6" />
<package id="MediaInfoNet" version="0.3" targetFramework="net40" /> <package id="MediaInfoNet" version="0.3" targetFramework="net40" />
<package id="Newtonsoft.Json" version="5.0.6" targetFramework="net40" /> <package id="Newtonsoft.Json" version="5.0.6" targetFramework="net40" />