Added Auth, startup options to UI

Added caching to ConfigFileProvider,
pull/3113/head
kay.one 12 years ago
parent 8a5bd31da7
commit 4da6654440

@ -2,6 +2,7 @@
using Nancy.Security; using Nancy.Security;
using NzbDrone.Common; using NzbDrone.Common;
using NzbDrone.Common.Model; using NzbDrone.Common.Model;
using NzbDrone.Core.Configuration;
namespace NzbDrone.Api.Authentication namespace NzbDrone.Api.Authentication
{ {

@ -55,16 +55,34 @@ namespace NzbDrone.Api.Config
public class SettingsModule : NzbDroneApiModule public class SettingsModule : NzbDroneApiModule
{ {
private readonly IConfigService _configService; private readonly IConfigService _configService;
private readonly IConfigFileProvider _configFileProvider;
public SettingsModule(IConfigService configService) public SettingsModule(IConfigService configService, IConfigFileProvider configFileProvider)
: base("/settings") : base("/settings")
{ {
_configService = configService; _configService = configService;
Get["/"] = x => GetAllSettings(); _configFileProvider = configFileProvider;
Post["/"] = x => SaveSettings(); Get["/"] = x => GetGeneralSettings();
Post["/"] = x => SaveGeneralSettings();
Get["/host"] = x => GetHostSettings();
Post["/host"] = x => SaveHostSettings();
}
private Response SaveHostSettings()
{
var request = Request.Body.FromJson<Dictionary<string, object>>();
_configFileProvider.SaveConfigDictionary(request);
return GetHostSettings();
}
private Response GetHostSettings()
{
return _configFileProvider.GetConfigDictionary().AsResponse();
} }
private Response GetAllSettings() private Response GetGeneralSettings()
{ {
var collection = Request.Query.Collection; var collection = Request.Query.Collection;
@ -74,7 +92,7 @@ namespace NzbDrone.Api.Config
return _configService.AllWithDefaults().AsResponse(); return _configService.AllWithDefaults().AsResponse();
} }
private Response SaveSettings() private Response SaveGeneralSettings()
{ {
var request = Request.Body.FromJson<Dictionary<string, object>>(); var request = Request.Body.FromJson<Dictionary<string, object>>();
_configService.SaveValues(request); _configService.SaveValues(request);

@ -1,4 +1,5 @@
using FluentAssertions; using System.Collections.Generic;
using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common.Cache; using NzbDrone.Common.Cache;
@ -59,6 +60,21 @@ namespace NzbDrone.Common.Test.CacheTests
{ {
_cachedString.Remove("Test"); _cachedString.Remove("Test");
} }
[Test]
public void get_without_callback_should_throw_on_invalid_key()
{
Assert.Throws<KeyNotFoundException>(() => _cachedString.Get("InvalidKey"));
}
[Test]
public void should_be_able_to_update_key()
{
_cachedString.Set("Key", "Old");
_cachedString.Set("Key", "New");
_cachedString.Get("Key").Should().Be("New");
}
} }
public class Worker public class Worker

@ -2,16 +2,17 @@ using System;
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common.Cache; using NzbDrone.Common.Cache;
using NzbDrone.Test.Common;
namespace NzbDrone.Common.Test.CacheTests namespace NzbDrone.Common.Test.CacheTests
{ {
[TestFixture] [TestFixture]
public class CachedManagerFixture public class CachedManagerFixture:TestBase<ICacheManger>
{ {
[Test] [Test]
public void should_return_proper_type_of_cache() public void should_return_proper_type_of_cache()
{ {
var result = CacheManger.GetCache<DateTime>(typeof(string)); var result = Subject.GetCache<DateTime>(typeof(string));
result.Should().BeOfType<Cached<DateTime>>(); result.Should().BeOfType<Cached<DateTime>>();
} }
@ -20,8 +21,8 @@ namespace NzbDrone.Common.Test.CacheTests
[Test] [Test]
public void multiple_calls_should_get_the_same_cache() public void multiple_calls_should_get_the_same_cache()
{ {
var result1 = CacheManger.GetCache<DateTime>(typeof(string)); var result1 = Subject.GetCache<DateTime>(typeof(string));
var result2 = CacheManger.GetCache<DateTime>(typeof(string)); var result2 = Subject.GetCache<DateTime>(typeof(string));
result1.Should().BeSameAs(result2); result1.Should().BeSameAs(result2);
} }

@ -2,6 +2,7 @@
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common.Model; using NzbDrone.Common.Model;
using NzbDrone.Core.Configuration;
using NzbDrone.Test.Common; using NzbDrone.Test.Common;
namespace NzbDrone.Common.Test namespace NzbDrone.Common.Test
@ -143,15 +144,18 @@ namespace NzbDrone.Common.Test
} }
[Test] [Test]
public void Guid_should_return_the_same_every_time() public void SaveDictionary_should_save_proper_value()
{ {
int port = 20555;
var firstResponse = Subject.Guid; var dic = Subject.GetConfigDictionary();
var secondResponse = Subject.Guid; dic["Port"] = 20555;
Subject.SaveConfigDictionary(dic);
secondResponse.Should().Be(firstResponse); Subject.Port.Should().Be(port);
} }
} }
} }

@ -3,20 +3,32 @@ using NzbDrone.Common.EnsureThat;
namespace NzbDrone.Common.Cache namespace NzbDrone.Common.Cache
{ {
public static class CacheManger public interface ICacheManger
{ {
private static readonly ICached<object> Cache; ICached<T> GetCache<T>(Type type);
ICached<T> GetCache<T>(object host);
}
public class CacheManger : ICacheManger
{
private readonly ICached<object> _cache;
static CacheManger() public CacheManger()
{ {
Cache = new Cached<object>(); _cache = new Cached<object>();
} }
public static ICached<T> GetCache<T>(Type type) public ICached<T> GetCache<T>(Type type)
{ {
Ensure.That(() => type).IsNotNull(); Ensure.That(() => type).IsNotNull();
return (ICached<T>)Cache.Get(type.FullName, () => new Cached<T>()); return (ICached<T>)_cache.Get(type.FullName, () => new Cached<T>());
}
public ICached<T> GetCache<T>(object host)
{
return GetCache<T>(host.GetType());
} }
} }
} }

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic;
using NzbDrone.Common.EnsureThat; using NzbDrone.Common.EnsureThat;
namespace NzbDrone.Common.Cache namespace NzbDrone.Common.Cache
@ -16,7 +17,12 @@ namespace NzbDrone.Common.Cache
public void Set(string key, T value) public void Set(string key, T value)
{ {
Ensure.That(() => key).IsNotNullOrWhiteSpace(); Ensure.That(() => key).IsNotNullOrWhiteSpace();
_store.TryAdd(key, value); _store[key] = value;
}
public T Get(string key)
{
return Get(key, () => { throw new KeyNotFoundException(key); });
} }
public T Get(string key, Func<T> function) public T Get(string key, Func<T> function)

@ -9,5 +9,6 @@ namespace NzbDrone.Common.Cache
bool ContainsKey(string key); bool ContainsKey(string key);
void Clear(); void Clear();
void Remove(string key); void Remove(string key);
T Get(string key);
} }
} }

@ -1,151 +0,0 @@
using System;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using NzbDrone.Common.Model;
namespace NzbDrone.Common
{
public interface IConfigFileProvider
{
Guid Guid { get; }
int Port { get; set; }
bool LaunchBrowser { get; set; }
AuthenticationType AuthenticationType { get; set; }
string BasicAuthUsername { get; set; }
string BasicAuthPassword { get; set; }
int GetValueInt(string key, int defaultValue);
bool GetValueBoolean(string key, bool defaultValue);
string GetValue(string key, object defaultValue);
T GetValueEnum<T>(string key, T defaultValue);
void SetValue(string key, object value);
}
public class ConfigFileProvider : IConfigFileProvider
{
private readonly IEnvironmentProvider _environmentProvider;
private readonly string _configFile;
public ConfigFileProvider(IEnvironmentProvider environmentProvider)
{
_environmentProvider = environmentProvider;
_configFile = _environmentProvider.GetConfigPath();
CreateDefaultConfigFile();
}
public virtual Guid Guid
{
get
{
var key = "Guid";
if (string.IsNullOrWhiteSpace(GetValue(key, string.Empty)))
{
SetValue(key, Guid.NewGuid().ToString());
}
return Guid.Parse(GetValue(key, string.Empty));
}
}
public virtual int Port
{
get { return GetValueInt("Port", 8989); }
set { SetValue("Port", value); }
}
public virtual bool LaunchBrowser
{
get { return GetValueBoolean("LaunchBrowser", true); }
set { SetValue("LaunchBrowser", value); }
}
public virtual AuthenticationType AuthenticationType
{
get { return GetValueEnum("AuthenticationType", AuthenticationType.Anonymous); }
set { SetValue("AuthenticationType", value); }
}
public virtual string BasicAuthUsername
{
get { return GetValue("BasicAuthUsername", ""); }
set { SetValue("BasicAuthUsername", value); }
}
public virtual string BasicAuthPassword
{
get { return GetValue("BasicAuthPassword", ""); }
set { SetValue("BasicAuthPassword", value); }
}
public virtual int GetValueInt(string key, int defaultValue)
{
return Convert.ToInt32(GetValue(key, defaultValue));
}
public virtual bool GetValueBoolean(string key, bool defaultValue)
{
return Convert.ToBoolean(GetValue(key, defaultValue));
}
public T GetValueEnum<T>(string key, T defaultValue)
{
return (T)Enum.Parse(typeof(T), GetValue(key, defaultValue), true);
}
public virtual string GetValue(string key, object defaultValue)
{
var xDoc = XDocument.Load(_configFile);
var config = xDoc.Descendants("Config").Single();
var parentContainer = config;
var valueHolder = parentContainer.Descendants(key).ToList();
if (valueHolder.Count() == 1)
return valueHolder.First().Value;
//Save the value
SetValue(key, defaultValue);
//return the default value
return defaultValue.ToString();
}
public virtual void SetValue(string key, object value)
{
var xDoc = XDocument.Load(_configFile);
var config = xDoc.Descendants("Config").Single();
var parentContainer = config;
var keyHolder = parentContainer.Descendants(key);
if (keyHolder.Count() != 1)
parentContainer.Add(new XElement(key, value));
else
parentContainer.Descendants(key).Single().Value = value.ToString();
xDoc.Save(_configFile);
}
public void SetValue(string key, Enum value)
{
SetValue(key, value.ToString().ToLower());
}
private void CreateDefaultConfigFile()
{
if (!File.Exists(_configFile))
{
var xDoc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));
xDoc.Add(new XElement("Config"));
xDoc.Save(_configFile);
}
}
}
}

@ -55,10 +55,6 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Interop.NetFwTypeLib">
<HintPath>..\Libraries\Interop.NetFwTypeLib.dll</HintPath>
<EmbedInteropTypes>True</EmbedInteropTypes>
</Reference>
<Reference Include="Ionic.Zip"> <Reference Include="Ionic.Zip">
<HintPath>..\packages\DotNetZip.1.9.1.8\lib\net20\Ionic.Zip.dll</HintPath> <HintPath>..\packages\DotNetZip.1.9.1.8\lib\net20\Ionic.Zip.dll</HintPath>
</Reference> </Reference>
@ -75,8 +71,6 @@
<Reference Include="System.Configuration.Install" /> <Reference Include="System.Configuration.Install" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.ServiceProcess" /> <Reference Include="System.ServiceProcess" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="ArchiveProvider.cs" /> <Compile Include="ArchiveProvider.cs" />
@ -136,7 +130,6 @@
<Compile Include="ServiceFactory.cs" /> <Compile Include="ServiceFactory.cs" />
<Compile Include="StringExtention.cs" /> <Compile Include="StringExtention.cs" />
<Compile Include="HttpProvider.cs" /> <Compile Include="HttpProvider.cs" />
<Compile Include="IConfigFileProvider.cs" />
<Compile Include="ConsoleService.cs" /> <Compile Include="ConsoleService.cs" />
<Compile Include="Contract\ReportBase.cs" /> <Compile Include="Contract\ReportBase.cs" />
<Compile Include="Contract\ParseErrorReport.cs" /> <Compile Include="Contract\ParseErrorReport.cs" />
@ -149,12 +142,10 @@
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\SharedAssemblyInfo.cs" /> <Compile Include="Properties\SharedAssemblyInfo.cs" />
<Compile Include="RestProvider.cs" /> <Compile Include="RestProvider.cs" />
<Compile Include="FirewallAdapter.cs" />
<Compile Include="IServiceProvider.cs" /> <Compile Include="IServiceProvider.cs" />
<Compile Include="TinyIoC.cs" /> <Compile Include="TinyIoC.cs" />
<Compile Include="TryParseExtension.cs" /> <Compile Include="TryParseExtension.cs" />
<Compile Include="UdpProvider.cs" /> <Compile Include="UdpProvider.cs" />
<Compile Include="UrlAclAdapter.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="packages.config"> <None Include="packages.config">

@ -1,4 +1,7 @@
namespace NzbDrone.Common using System;
using System.Linq;
namespace NzbDrone.Common
{ {
public static class StringExtension public static class StringExtension
{ {
@ -13,5 +16,10 @@
{ {
return ((object)target).NullSafe().ToString(); return ((object)target).NullSafe().ToString();
} }
public static string FirstCharToUpper(this string input)
{
return input.First().ToString().ToUpper() + String.Join("", input.Skip(1));
}
} }
} }

@ -32,7 +32,6 @@ namespace NzbDrone.Core.Test.UpdateTests
public void Setup() public void Setup()
{ {
Mocker.GetMock<IEnvironmentProvider>().SetupGet(c => c.SystemTemp).Returns(TempFolder); Mocker.GetMock<IEnvironmentProvider>().SetupGet(c => c.SystemTemp).Returns(TempFolder);
Mocker.GetMock<IConfigFileProvider>().SetupGet(c => c.Guid).Returns(_clientGuid);
Mocker.GetMock<IUpdatePackageProvider>().Setup(c => c.GetLatestUpdate()).Returns(_updatePackage); Mocker.GetMock<IUpdatePackageProvider>().Setup(c => c.GetLatestUpdate()).Returns(_updatePackage);
Mocker.GetMock<IProcessProvider>().Setup(c => c.GetCurrentProcess()).Returns(new ProcessInfo { Id = 12 }); Mocker.GetMock<IProcessProvider>().Setup(c => c.GetCurrentProcess()).Returns(new ProcessInfo { Id = 12 });

@ -0,0 +1,189 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using NzbDrone.Common;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Model;
namespace NzbDrone.Core.Configuration
{
public interface IConfigFileProvider
{
Dictionary<string, object> GetConfigDictionary();
void SaveConfigDictionary(Dictionary<string, object> configValues);
int Port { get; set; }
bool LaunchBrowser { get; set; }
AuthenticationType AuthenticationType { get; set; }
string BasicAuthUsername { get; set; }
string BasicAuthPassword { get; set; }
}
public class ConfigFileProvider : IConfigFileProvider
{
private readonly IEnvironmentProvider _environmentProvider;
private readonly ICached<string> _cache;
private readonly string _configFile;
public ConfigFileProvider(IEnvironmentProvider environmentProvider, ICacheManger cacheManger)
{
_environmentProvider = environmentProvider;
_cache = cacheManger.GetCache<string>(this);
_configFile = _environmentProvider.GetConfigPath();
}
public Dictionary<string, object> GetConfigDictionary()
{
var dict = new Dictionary<string, object>(StringComparer.InvariantCultureIgnoreCase);
var type = GetType();
var properties = type.GetProperties();
foreach (var propertyInfo in properties)
{
var value = propertyInfo.GetValue(this, null);
dict.Add(propertyInfo.Name, value);
}
return dict;
}
public void SaveConfigDictionary(Dictionary<string, object> configValues)
{
_cache.Clear();
var allWithDefaults = GetConfigDictionary();
foreach (var configValue in configValues)
{
object currentValue;
allWithDefaults.TryGetValue(configValue.Key, out currentValue);
if (currentValue == null) continue;
var equal = configValue.Value.ToString().Equals(currentValue.ToString());
if (!equal)
{
SetValue(configValue.Key.FirstCharToUpper(), configValue.Value.ToString());
}
}
}
public int Port
{
get { return GetValueInt("Port", 8989); }
set { SetValue("Port", value); }
}
public bool LaunchBrowser
{
get { return GetValueBoolean("LaunchBrowser", true); }
set { SetValue("LaunchBrowser", value); }
}
public AuthenticationType AuthenticationType
{
get { return GetValueEnum("AuthenticationType", AuthenticationType.Anonymous); }
set { SetValue("AuthenticationType", value); }
}
public string BasicAuthUsername
{
get { return GetValue("BasicAuthUsername", ""); }
set { SetValue("BasicAuthUsername", value); }
}
public string BasicAuthPassword
{
get { return GetValue("BasicAuthPassword", ""); }
set { SetValue("BasicAuthPassword", value); }
}
public int GetValueInt(string key, int defaultValue)
{
return Convert.ToInt32(GetValue(key, defaultValue));
}
public bool GetValueBoolean(string key, bool defaultValue)
{
return Convert.ToBoolean(GetValue(key, defaultValue));
}
public T GetValueEnum<T>(string key, T defaultValue)
{
return (T)Enum.Parse(typeof(T), GetValue(key, defaultValue), true);
}
public string GetValue(string key, object defaultValue)
{
return _cache.Get(key, () =>
{
EnsureDefaultConfigFile();
var xDoc = XDocument.Load(_configFile);
var config = xDoc.Descendants("Config").Single();
var parentContainer = config;
var valueHolder = parentContainer.Descendants(key).ToList();
if (valueHolder.Count() == 1)
return valueHolder.First().Value;
//Save the value
SetValue(key, defaultValue);
//return the default value
return defaultValue.ToString();
});
}
public void SetValue(string key, object value)
{
EnsureDefaultConfigFile();
var xDoc = XDocument.Load(_configFile);
var config = xDoc.Descendants("Config").Single();
var parentContainer = config;
var keyHolder = parentContainer.Descendants(key);
if (keyHolder.Count() != 1)
{
parentContainer.Add(new XElement(key, value));
}
else
{
parentContainer.Descendants(key).Single().Value = value.ToString();
}
_cache.Set(key, value.ToString());
xDoc.Save(_configFile);
}
public void SetValue(string key, Enum value)
{
SetValue(key, value.ToString().ToLower());
}
private void EnsureDefaultConfigFile()
{
if (!File.Exists(_configFile))
{
var xDoc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));
xDoc.Add(new XElement("Config"));
xDoc.Save(_configFile);
}
}
}
}

@ -43,6 +43,23 @@ namespace NzbDrone.Core.Configuration
return dict; return dict;
} }
public void SaveValues(Dictionary<string, object> configValues)
{
var allWithDefaults = AllWithDefaults();
foreach (var configValue in configValues)
{
object currentValue;
allWithDefaults.TryGetValue(configValue.Key, out currentValue);
if (currentValue == null) continue;
var equal = configValue.Value.ToString().Equals(currentValue.ToString());
if (!equal)
SetValue(configValue.Key, configValue.Value.ToString());
}
}
public String SabHost public String SabHost
{ {
get { return GetValue("SabHost", "localhost"); } get { return GetValue("SabHost", "localhost"); }
@ -132,18 +149,6 @@ namespace NzbDrone.Core.Configuration
set { SetValue("UpdateUrl", value); } set { SetValue("UpdateUrl", value); }
} }
public string TwitterAccessToken
{
get { return GetValue("TwitterAccessToken", String.Empty); }
set { SetValue("TwitterAccessToken", value); }
}
public string TwitterAccessTokenSecret
{
get { return GetValue("TwitterAccessTokenSecret", String.Empty); }
set { SetValue("TwitterAccessTokenSecret", value); }
}
public bool EnableBacklogSearching public bool EnableBacklogSearching
{ {
get { return GetValueBoolean("EnableBacklogSearching"); } get { return GetValueBoolean("EnableBacklogSearching"); }
@ -365,22 +370,7 @@ namespace NzbDrone.Core.Configuration
SetValue(key, value.ToString().ToLower()); SetValue(key, value.ToString().ToLower());
} }
public void SaveValues(Dictionary<string, object> configValues)
{
var allWithDefaults = AllWithDefaults();
foreach (var configValue in configValues)
{
object currentValue;
allWithDefaults.TryGetValue(configValue.Key, out currentValue);
if (currentValue == null) continue;
var equal = configValue.Value.ToString().Equals(currentValue.ToString());
if (!equal)
SetValue(configValue.Key, configValue.Value.ToString());
}
}
private void EnsureCache() private void EnsureCache()
{ {

@ -23,8 +23,6 @@ namespace NzbDrone.Core.Configuration
bool UseSeasonFolder { get; set; } bool UseSeasonFolder { get; set; }
string SortingSeasonFolderFormat { get; set; } string SortingSeasonFolderFormat { get; set; }
int DefaultQualityProfile { get; set; } int DefaultQualityProfile { get; set; }
string TwitterAccessToken { get; set; }
string TwitterAccessTokenSecret { get; set; }
bool EnableBacklogSearching { get; set; } bool EnableBacklogSearching { get; set; }
bool AutoIgnorePreviouslyDownloadedEpisodes { get; set; } bool AutoIgnorePreviouslyDownloadedEpisodes { get; set; }
int Retention { get; set; } int Retention { get; set; }

@ -178,6 +178,7 @@
</Compile> </Compile>
<Compile Include="Annotations\FieldDefinitionAttribute.cs" /> <Compile Include="Annotations\FieldDefinitionAttribute.cs" />
<Compile Include="Configuration\Config.cs" /> <Compile Include="Configuration\Config.cs" />
<Compile Include="Configuration\ConfigFileProvider.cs" />
<Compile Include="Configuration\ConfigRepository.cs" /> <Compile Include="Configuration\ConfigRepository.cs" />
<Compile Include="Configuration\IConfigService.cs" /> <Compile Include="Configuration\IConfigService.cs" />
<Compile Include="Constants.cs" /> <Compile Include="Constants.cs" />

@ -7,6 +7,7 @@ using System.Linq;
using NLog; using NLog;
using NzbDrone.Common; using NzbDrone.Common;
using NzbDrone.Common.Messaging; using NzbDrone.Common.Messaging;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Update.Commands; using NzbDrone.Core.Update.Commands;
namespace NzbDrone.Core.Update namespace NzbDrone.Core.Update
@ -75,7 +76,7 @@ namespace NzbDrone.Core.Update
var startInfo = new ProcessStartInfo var startInfo = new ProcessStartInfo
{ {
FileName = _environmentProvider.GetUpdateClientExePath(), FileName = _environmentProvider.GetUpdateClientExePath(),
Arguments = string.Format("{0} {1}", _processProvider.GetCurrentProcess().Id, _configFileProvider.Guid) Arguments = string.Format("{0} {1}", _processProvider.GetCurrentProcess().Id)
}; };
var process = _processProvider.Start(startInfo); var process = _processProvider.Start(startInfo);

@ -11,6 +11,7 @@ using NzbDrone.Api.Commands;
using NzbDrone.Api.RootFolders; using NzbDrone.Api.RootFolders;
using NzbDrone.Common; using NzbDrone.Common;
using NzbDrone.Common.Composition; using NzbDrone.Common.Composition;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
using NzbDrone.Integration.Test.Client; using NzbDrone.Integration.Test.Client;
using NzbDrone.Owin; using NzbDrone.Owin;

@ -5,6 +5,7 @@ using Moq;
using NLog; using NLog;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common; using NzbDrone.Common;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Messaging; using NzbDrone.Common.Messaging;
using NzbDrone.Common.Serializer; using NzbDrone.Common.Serializer;
using NzbDrone.Test.Common.AutoMoq; using NzbDrone.Test.Common.AutoMoq;
@ -20,6 +21,8 @@ namespace NzbDrone.Test.Common
public void CoreTestSetup() public void CoreTestSetup()
{ {
_subject = null; _subject = null;
Mocker.SetConstant<ICacheManger>(new CacheManger());
} }
protected TSubject Subject protected TSubject Subject

@ -2,6 +2,8 @@
using System.ServiceProcess; using System.ServiceProcess;
using NLog; using NLog;
using NzbDrone.Common; using NzbDrone.Common;
using NzbDrone.Core.Configuration;
using NzbDrone.Host;
using NzbDrone.Owin; using NzbDrone.Owin;
namespace NzbDrone namespace NzbDrone

@ -1,8 +1,9 @@
using System; using System;
using NLog; using NLog;
using NetFwTypeLib; using NetFwTypeLib;
using NzbDrone.Core.Configuration;
namespace NzbDrone.Common namespace NzbDrone.Host
{ {
public interface IFirewallAdapter public interface IFirewallAdapter
{ {

@ -1,8 +1,10 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using NLog; using NLog;
using NzbDrone.Common;
using NzbDrone.Core.Configuration;
namespace NzbDrone.Common namespace NzbDrone.Host
{ {
public interface IUrlAclAdapter public interface IUrlAclAdapter
{ {

@ -89,6 +89,10 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FluentMigrator.1.0.6.0\tools\FluentMigrator.Runner.dll</HintPath> <HintPath>..\packages\FluentMigrator.1.0.6.0\tools\FluentMigrator.Runner.dll</HintPath>
</Reference> </Reference>
<Reference Include="Interop.NetFwTypeLib">
<HintPath>..\Libraries\Interop.NetFwTypeLib.dll</HintPath>
<EmbedInteropTypes>True</EmbedInteropTypes>
</Reference>
<Reference Include="Microsoft.AspNet.SignalR.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.AspNet.SignalR.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.SignalR.Core.1.0.1\lib\net40\Microsoft.AspNet.SignalR.Core.dll</HintPath> <HintPath>..\packages\Microsoft.AspNet.SignalR.Core.1.0.1\lib\net40\Microsoft.AspNet.SignalR.Core.dll</HintPath>
@ -137,6 +141,8 @@
<Compile Include="ApplicationServer.cs"> <Compile Include="ApplicationServer.cs">
<SubType>Component</SubType> <SubType>Component</SubType>
</Compile> </Compile>
<Compile Include="Host\FirewallAdapter.cs" />
<Compile Include="Host\UrlAclAdapter.cs" />
<Compile Include="MainAppContainerBuilder.cs" /> <Compile Include="MainAppContainerBuilder.cs" />
<Compile Include="ApplicationModes.cs" /> <Compile Include="ApplicationModes.cs" />
<Compile Include="AppMain.cs" /> <Compile Include="AppMain.cs" />

@ -3,6 +3,7 @@ using System.Collections.Generic;
using Microsoft.Owin.Hosting; using Microsoft.Owin.Hosting;
using NLog; using NLog;
using NzbDrone.Common; using NzbDrone.Common;
using NzbDrone.Core.Configuration;
using NzbDrone.Owin.MiddleWare; using NzbDrone.Owin.MiddleWare;
using Owin; using Owin;
using System.Linq; using System.Linq;

@ -0,0 +1,16 @@
"use strict";
define(['app'], function () {
NzbDrone.Settings.General.GeneralSettingsModel = Backbone.Model.extend({
url: NzbDrone.Constants.ApiRoot + '/settings/host',
initialize: function () {
this.on('change', function () {
this.isSaved = false;
}, this);
this.on('sync', function () {
this.isSaved = true;
}, this);
}
});
});

@ -0,0 +1,70 @@
<div class="form-horizontal">
<fieldset>
<legend>Start-Up</legend>
<div class="control-group">
<label class="control-label">Port Number</label>
<div class="controls">
<input type="text" placeholder="8989" name="port"/>
<span>
<i class="icon-exclamation-sign danger" title="Requires restart to take effect"></i>
</span>
</div>
</div>
<div class="control-group">
<label class="control-label">Open browser on start</label>
<div class="controls">
<label class="checkbox toggle well">
<input type="checkbox" name="launchBrowser"/>
<p>
<span>Yes</span>
<span>No</span>
</p>
<div class="btn btn-primary slide-button"></div>
</label>
<span class="help-inline-checkbox">
<i class="icon-question-sign" title="Open a web browser and navigate to NzbDrone homepage on app start. Has no effect if installed as a windows service"></i>
</span>
</div>
</div>
</fieldset>
<fieldset>
<legend>Security</legend>
<div class="control-group">
<label class="control-label">Authentication</label>
<div class="controls">
<select class="inputClass" name="authenticationType">
<option value="Anonymous">Anonymous</option>
<option value="Basic">Basic</option>
</select>
</div>
</div>
<div class="control-group">
<label class="control-label">Username</label>
<div class="controls">
<input type="text" placeholder="Username" name="basicAuthUsername"/>
</div>
</div>
<div class="control-group">
<label class="control-label">Password</label>
<div class="controls">
<input type="password" name="basicAuthPassword"/>
</div>
</div>
</fieldset>
</div>

@ -0,0 +1,31 @@
'use strict';
define(['app', 'Settings/SettingsModel', 'Shared/Messenger'], function () {
NzbDrone.Settings.General.GeneralView = Backbone.Marionette.ItemView.extend({
template: 'Settings/General/GeneralTemplate',
initialize: function () {
NzbDrone.vent.on(NzbDrone.Commands.SaveSettings, this.saveSettings, this);
},
saveSettings: function () {
if (!this.model.isSaved) {
this.model.save(undefined, this.syncNotification("Naming Settings Saved", "Couldn't Save Naming Settings"));
}
},
syncNotification: function (success, error) {
return {
success: function () {
NzbDrone.Shared.Messenger.show({message: 'General Settings Saved'});
},
error : function () {
NzbDrone.Shared.Messenger.show({message: "Couldn't Save General Settings", type: 'error'});
}
};
}
}
);
});

@ -1,4 +1,5 @@
<fieldset> <div class="form-horizontal">
<fieldset>
<legend>Episode Naming</legend> <legend>Episode Naming</legend>
<div class="control-group"> <div class="control-group">
@ -7,6 +8,7 @@
<div class="controls"> <div class="controls">
<label class="checkbox toggle well"> <label class="checkbox toggle well">
<input type="checkbox" name="useSceneName"/> <input type="checkbox" name="useSceneName"/>
<p> <p>
<span>On</span> <span>On</span>
<span>Off</span> <span>Off</span>
@ -27,6 +29,7 @@
<div class="controls"> <div class="controls">
<label class="checkbox toggle well"> <label class="checkbox toggle well">
<input type="checkbox" name="includeSeriesTitle"/> <input type="checkbox" name="includeSeriesTitle"/>
<p> <p>
<span>On</span> <span>On</span>
<span>Off</span> <span>Off</span>
@ -47,6 +50,7 @@
<div class="controls"> <div class="controls">
<label class="checkbox toggle well"> <label class="checkbox toggle well">
<input type="checkbox" name="includeEpisodeTitle"/> <input type="checkbox" name="includeEpisodeTitle"/>
<p> <p>
<span>On</span> <span>On</span>
<span>Off</span> <span>Off</span>
@ -67,6 +71,7 @@
<div class="controls"> <div class="controls">
<label class="checkbox toggle well"> <label class="checkbox toggle well">
<input type="checkbox" name="includeQuality"/> <input type="checkbox" name="includeQuality"/>
<p> <p>
<span>On</span> <span>On</span>
<span>Off</span> <span>Off</span>
@ -87,6 +92,7 @@
<div class="controls"> <div class="controls">
<label class="checkbox toggle well"> <label class="checkbox toggle well">
<input type="checkbox" name="replaceSpaces"/> <input type="checkbox" name="replaceSpaces"/>
<p> <p>
<span>On</span> <span>On</span>
<span>Off</span> <span>Off</span>
@ -189,3 +195,4 @@
</div> </div>
</div> </div>
</fieldset> </fieldset>
</div>

@ -3,7 +3,6 @@ define(['app', 'Settings/Naming/NamingModel'], function () {
NzbDrone.Settings.Naming.NamingView = Backbone.Marionette.ItemView.extend({ NzbDrone.Settings.Naming.NamingView = Backbone.Marionette.ItemView.extend({
template : 'Settings/Naming/NamingTemplate', template : 'Settings/Naming/NamingTemplate',
className: 'form-horizontal',
ui: { ui: {
tooltip: '[class^="help-inline"] i' tooltip: '[class^="help-inline"] i'

@ -6,7 +6,8 @@ define([
'Settings/Indexers/CollectionView', 'Settings/Indexers/CollectionView',
'Settings/DownloadClient/DownloadClientView', 'Settings/DownloadClient/DownloadClientView',
'Settings/Notifications/CollectionView', 'Settings/Notifications/CollectionView',
'Settings/System/SystemView', 'Settings/General/GeneralView',
'Settings/General/GeneralSettingsModel',
'Settings/Misc/MiscView' 'Settings/Misc/MiscView'
], ],
function () { function () {
@ -19,7 +20,7 @@ define([
indexers : '#indexers', indexers : '#indexers',
downloadClient: '#download-client', downloadClient: '#download-client',
notifications : '#notifications', notifications : '#notifications',
system : '#system', general : '#general',
misc : '#misc' misc : '#misc'
}, },
@ -29,7 +30,7 @@ define([
indexersTab : '.x-indexers-tab', indexersTab : '.x-indexers-tab',
downloadClientTab: '.x-download-client-tab', downloadClientTab: '.x-download-client-tab',
notificationsTab : '.x-notifications-tab', notificationsTab : '.x-notifications-tab',
systemTab : '.x-system-tab', generalTab : '.x-general-tab',
miscTab : '.x-misc-tab' miscTab : '.x-misc-tab'
}, },
@ -39,7 +40,7 @@ define([
'click .x-indexers-tab' : 'showIndexers', 'click .x-indexers-tab' : 'showIndexers',
'click .x-download-client-tab': 'showDownloadClient', 'click .x-download-client-tab': 'showDownloadClient',
'click .x-notifications-tab' : 'showNotifications', 'click .x-notifications-tab' : 'showNotifications',
'click .x-system-tab' : 'showSystem', 'click .x-general-tab' : 'showGeneral',
'click .x-misc-tab' : 'showMisc', 'click .x-misc-tab' : 'showMisc',
'click .x-save-settings' : 'save' 'click .x-save-settings' : 'save'
}, },
@ -89,13 +90,13 @@ define([
NzbDrone.Router.navigate('settings/notifications'); NzbDrone.Router.navigate('settings/notifications');
}, },
showSystem: function (e) { showGeneral: function (e) {
if (e) { if (e) {
e.preventDefault(); e.preventDefault();
} }
this.ui.systemTab.tab('show'); this.ui.generalTab.tab('show');
NzbDrone.Router.navigate('settings/system'); NzbDrone.Router.navigate('settings/general');
}, },
showMisc: function (e) { showMisc: function (e) {
@ -111,6 +112,9 @@ define([
this.settings = new NzbDrone.Settings.SettingsModel(); this.settings = new NzbDrone.Settings.SettingsModel();
this.settings.fetch(); this.settings.fetch();
this.generalSettings = new NzbDrone.Settings.General.GeneralSettingsModel();
this.generalSettings.fetch();
this.namingSettings = new NzbDrone.Settings.Naming.NamingModel(); this.namingSettings = new NzbDrone.Settings.Naming.NamingModel();
this.namingSettings.fetch(); this.namingSettings.fetch();
@ -131,7 +135,7 @@ define([
this.indexers.show(new NzbDrone.Settings.Indexers.CollectionView({collection: this.indexerSettings})); this.indexers.show(new NzbDrone.Settings.Indexers.CollectionView({collection: this.indexerSettings}));
this.downloadClient.show(new NzbDrone.Settings.DownloadClient.DownloadClientView({model: this.settings})); this.downloadClient.show(new NzbDrone.Settings.DownloadClient.DownloadClientView({model: this.settings}));
this.notifications.show(new NzbDrone.Settings.Notifications.CollectionView({collection: this.notificationSettings})); this.notifications.show(new NzbDrone.Settings.Notifications.CollectionView({collection: this.notificationSettings}));
this.system.show(new NzbDrone.Settings.System.SystemView({model: this.settings})); this.general.show(new NzbDrone.Settings.General.GeneralView({model: this.generalSettings}));
this.misc.show(new NzbDrone.Settings.Misc.MiscView({model: this.settings})); this.misc.show(new NzbDrone.Settings.Misc.MiscView({model: this.settings}));
}, },
@ -149,8 +153,8 @@ define([
case 'notifications': case 'notifications':
this.showNotifications(); this.showNotifications();
break; break;
case 'system': case 'general':
this.showSystem(); this.showGeneral();
break; break;
case 'misc': case 'misc':
this.showMisc(); this.showMisc();

@ -4,7 +4,7 @@
<li><a href="#indexers" class="x-indexers-tab">Indexers</a></li> <li><a href="#indexers" class="x-indexers-tab">Indexers</a></li>
<li><a href="#download-client" class="x-download-client-tab">Download Client</a></li> <li><a href="#download-client" class="x-download-client-tab">Download Client</a></li>
<li><a href="#notifications" class="x-notifications-tab">Notifications</a></li> <li><a href="#notifications" class="x-notifications-tab">Notifications</a></li>
<li><a href="#system" class="x-system-tab">System</a></li> <li><a href="#general" class="x-general-tab">general</a></li>
<li><a href="#misc" class="x-misc-tab">Misc</a></li> <li><a href="#misc" class="x-misc-tab">Misc</a></li>
</ul> </ul>
@ -14,7 +14,7 @@
<div class="tab-pane" id="indexers">Indexer Settings</div> <div class="tab-pane" id="indexers">Indexer Settings</div>
<div class="tab-pane" id="download-client">Download Client Settings</div> <div class="tab-pane" id="download-client">Download Client Settings</div>
<div class="tab-pane" id="notifications">Notification Settings</div> <div class="tab-pane" id="notifications">Notification Settings</div>
<div class="tab-pane" id="system">System Settings</div> <div class="tab-pane" id="general">general Settings</div>
<div class="tab-pane" id="misc">Misc Settings</div> <div class="tab-pane" id="misc">Misc Settings</div>
</div> </div>

@ -1,3 +0,0 @@
<div>
System settings will go here
</div>

@ -1,11 +0,0 @@
'use strict';
define([
'app', 'Settings/SettingsModel'
], function () {
NzbDrone.Settings.System.SystemView = Backbone.Marionette.ItemView.extend({
template: 'Settings/System/SystemTemplate'
});
});

@ -76,7 +76,7 @@ define('app', ['shared/modal/region'], function (ModalRegion) {
Indexers : {}, Indexers : {},
DownloadClient: {}, DownloadClient: {},
Notifications : {}, Notifications : {},
System : {}, General : {},
Misc : {} Misc : {}
}; };

Loading…
Cancel
Save