diff --git a/NzbDrone.Api.Test/MappingTests/ResourceMappingFixture.cs b/NzbDrone.Api.Test/MappingTests/ResourceMappingFixture.cs
index 61c85d643..87ccf537b 100644
--- a/NzbDrone.Api.Test/MappingTests/ResourceMappingFixture.cs
+++ b/NzbDrone.Api.Test/MappingTests/ResourceMappingFixture.cs
@@ -2,7 +2,9 @@
using NUnit.Framework;
using NzbDrone.Api.Episodes;
using NzbDrone.Api.Mapping;
+using NzbDrone.Api.RootFolders;
using NzbDrone.Api.Series;
+using NzbDrone.Core.RootFolders;
using NzbDrone.Test.Common;
namespace NzbDrone.Api.Test.MappingTests
@@ -12,6 +14,7 @@ namespace NzbDrone.Api.Test.MappingTests
{
[TestCase(typeof(Core.Tv.Series), typeof(SeriesResource))]
[TestCase(typeof(Core.Tv.Episode), typeof(EpisodeResource))]
+ [TestCase(typeof(RootFolder), typeof(RootFolderResource))]
public void matching_fields(Type modelType, Type resourceType)
{
MappingValidation.ValidateMapping(modelType, resourceType);
diff --git a/NzbDrone.Api/Calendar/CalendarModule.cs b/NzbDrone.Api/Calendar/CalendarModule.cs
index 799b98215..fc1b625ac 100644
--- a/NzbDrone.Api/Calendar/CalendarModule.cs
+++ b/NzbDrone.Api/Calendar/CalendarModule.cs
@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
using AutoMapper;
using Nancy;
using NzbDrone.Api.Extensions;
diff --git a/NzbDrone.Api/NzbDrone.Api.csproj b/NzbDrone.Api/NzbDrone.Api.csproj
index 29e633ecf..e7b035444 100644
--- a/NzbDrone.Api/NzbDrone.Api.csproj
+++ b/NzbDrone.Api/NzbDrone.Api.csproj
@@ -101,6 +101,7 @@
+
diff --git a/NzbDrone.Api/NzbDroneRestModule.cs b/NzbDrone.Api/NzbDroneRestModule.cs
index 81a515a5e..e5ba93fdf 100644
--- a/NzbDrone.Api/NzbDroneRestModule.cs
+++ b/NzbDrone.Api/NzbDroneRestModule.cs
@@ -1,10 +1,20 @@
-using NzbDrone.Api.REST;
+using System;
+using System.Collections.Generic;
+using NzbDrone.Api.REST;
using NzbDrone.Api.Validation;
+using NzbDrone.Core.Datastore;
+using NzbDrone.Api.Mapping;
namespace NzbDrone.Api
{
public abstract class NzbDroneRestModule : RestModule where TResource : RestResource, new()
{
+ protected NzbDroneRestModule()
+ : this(new TResource().ResourceName)
+ {
+
+ }
+
protected NzbDroneRestModule(string resource)
: base("/api/" + resource.Trim('/'))
{
@@ -12,5 +22,25 @@ namespace NzbDrone.Api
PutValidator.RuleFor(r => r.Id).ValidId();
}
+
+ protected TResource Apply(Func function, TResource resource) where TModel : ModelBase, new()
+ {
+ var model = resource.InjectTo();
+ function(model);
+ return model.InjectTo();
+ }
+
+ protected List Apply(Func> function) where TModel : ModelBase, new()
+ {
+ var modelList = function();
+ return modelList.InjectTo>();
+ }
+
+ protected TResource Apply(Func action, int id) where TModel : ModelBase, new()
+ {
+ var model = action(id);
+ return model.InjectTo();
+ }
+
}
}
\ No newline at end of file
diff --git a/NzbDrone.Api/REST/RestModule.cs b/NzbDrone.Api/REST/RestModule.cs
index 951650f83..b0a234ee6 100644
--- a/NzbDrone.Api/REST/RestModule.cs
+++ b/NzbDrone.Api/REST/RestModule.cs
@@ -10,17 +10,19 @@ namespace NzbDrone.Api.REST
public abstract class RestModule : NancyModule
where TResource : RestResource, new()
{
- protected ResourceValidator PostValidator { get; private set; }
- protected ResourceValidator PutValidator { get; private set; }
- protected ResourceValidator SharedValidator { get; private set; }
private const string ROOT_ROUTE = "/";
private const string ID_ROUTE = "/{id}";
- protected RestModule()
- : this(new TResource().ResourceName)
- {
+ private Action _deleteResource;
+ private Func _getResourceById;
+ private Func> _getResourceAll;
+ private Func _createResource;
+ private Func _updateResource;
+
+ protected ResourceValidator PostValidator { get; private set; }
+ protected ResourceValidator PutValidator { get; private set; }
+ protected ResourceValidator SharedValidator { get; private set; }
- }
protected RestModule(string modulePath)
: base(modulePath)
@@ -29,61 +31,81 @@ namespace NzbDrone.Api.REST
PostValidator = new ResourceValidator();
PutValidator = new ResourceValidator();
SharedValidator = new ResourceValidator();
+ }
- Get[ROOT_ROUTE] = options =>
+ protected Action DeleteResource
+ {
+ private get { return _deleteResource; }
+ set
{
- EnsureImplementation(GetResourceAll);
- var resource = GetResourceAll();
- return resource.AsResponse();
- };
+ _deleteResource = value;
+ Delete[ID_ROUTE] = options =>
+ {
+ DeleteResource((int)options.Id);
+ return new Response { StatusCode = HttpStatusCode.OK };
+ };
+ }
+ }
- Get[ID_ROUTE] = options =>
+ protected Func GetResourceById
+ {
+ private get { return _getResourceById; }
+ set
{
- EnsureImplementation(GetResourceById);
- var resource = GetResourceById((int)options.Id);
- return resource.AsResponse();
- };
+ _getResourceById = value;
+ Get[ID_ROUTE] = options =>
+ {
+ var resource = GetResourceById((int)options.Id);
+ return resource.AsResponse();
+ };
+ }
+ }
- Post[ROOT_ROUTE] = options =>
+ protected Func> GetResourceAll
+ {
+ private get { return _getResourceAll; }
+ set
{
- EnsureImplementation(CreateResource);
- var resource = CreateResource(ReadFromRequest());
- return resource.AsResponse(HttpStatusCode.Created);
- };
+ _getResourceAll = value;
- Put[ROOT_ROUTE] = options =>
- {
- EnsureImplementation(UpdateResource);
- var resource = UpdateResource(ReadFromRequest());
- return resource.AsResponse(HttpStatusCode.Accepted);
- };
+ Get[ROOT_ROUTE] = options =>
+ {
+ var resource = GetResourceAll();
+ return resource.AsResponse();
+ };
+ }
+ }
- Delete[ID_ROUTE] = options =>
+ protected Func CreateResource
+ {
+ private get { return _createResource; }
+ set
{
- EnsureImplementation(DeleteResource);
- DeleteResource((int)options.Id);
- return new Response { StatusCode = HttpStatusCode.OK };
- };
-
-
-
+ _createResource = value;
+ Post[ROOT_ROUTE] = options =>
+ {
+ var resource = CreateResource(ReadFromRequest());
+ return resource.AsResponse(HttpStatusCode.Created);
+ };
+ }
}
- protected Action DeleteResource { get; set; }
- protected Func GetResourceById { get; set; }
- protected Func> GetResourceAll { get; set; }
- protected Func CreateResource { get; set; }
- protected Func UpdateResource { get; set; }
-
- private void EnsureImplementation(Delegate implementation)
+ protected Func UpdateResource
{
- if (implementation == null)
+ private get { return _updateResource; }
+ set
{
- throw new NotImplementedException();
+ _updateResource = value;
+ Put[ROOT_ROUTE] = options =>
+ {
+ var resource = UpdateResource(ReadFromRequest());
+ return resource.AsResponse(HttpStatusCode.Accepted);
+ };
}
}
+
private TResource ReadFromRequest()
{
var resource = Request.Body.FromJson();
diff --git a/NzbDrone.Api/REST/RestResource.cs b/NzbDrone.Api/REST/RestResource.cs
index 03f547a5a..5d0470ab3 100644
--- a/NzbDrone.Api/REST/RestResource.cs
+++ b/NzbDrone.Api/REST/RestResource.cs
@@ -10,7 +10,7 @@ namespace NzbDrone.Api.REST
{
get
{
- return GetType().Name.ToLower();
+ return GetType().Name.ToLower().Replace("resource", "");
}
}
}
diff --git a/NzbDrone.Api/RootFolders/RootFolderModule.cs b/NzbDrone.Api/RootFolders/RootFolderModule.cs
index 1227ec68a..82226114e 100644
--- a/NzbDrone.Api/RootFolders/RootFolderModule.cs
+++ b/NzbDrone.Api/RootFolders/RootFolderModule.cs
@@ -1,41 +1,34 @@
-using System.Linq;
-using Nancy;
-using NzbDrone.Api.Extensions;
-using NzbDrone.Core.Providers;
-
+using System.Collections.Generic;
using NzbDrone.Core.RootFolders;
namespace NzbDrone.Api.RootFolders
{
- public class RootFolderModule : NzbDroneApiModule
+ public class RootFolderModule : NzbDroneRestModule
{
private readonly RootFolderService _rootFolderService;
public RootFolderModule(RootFolderService rootFolderService)
- : base("/rootfolder")
{
_rootFolderService = rootFolderService;
- Get["/"] = x => GetRootFolders();
- Post["/"] = x => AddRootFolder();
- Delete["/{id}"] = x => DeleteRootFolder((int)x.id);
+ GetResourceAll = GetRootFolders;
+ CreateResource = CreateRootFolder;
+ DeleteResource = DeleteFolder;
}
- private Response AddRootFolder()
+ private RootFolderResource CreateRootFolder(RootFolderResource rootFolderResource)
{
- var dir = _rootFolderService.Add(Request.Body.FromJson());
- return dir.AsResponse(HttpStatusCode.Created);
+ return Apply(_rootFolderService.Add, rootFolderResource);
}
- private Response GetRootFolders()
+ private List GetRootFolders()
{
- return _rootFolderService.All().AsResponse();
+ return Apply(_rootFolderService.All);
}
- private Response DeleteRootFolder(int folderId)
+ private void DeleteFolder(int id)
{
- _rootFolderService.Remove(folderId);
- return new Response { StatusCode = HttpStatusCode.OK };
+ _rootFolderService.Remove(id);
}
}
}
\ No newline at end of file
diff --git a/NzbDrone.Api/RootFolders/RootFolderResource.cs b/NzbDrone.Api/RootFolders/RootFolderResource.cs
new file mode 100644
index 000000000..dd38cb765
--- /dev/null
+++ b/NzbDrone.Api/RootFolders/RootFolderResource.cs
@@ -0,0 +1,11 @@
+using System;
+using NzbDrone.Api.REST;
+
+namespace NzbDrone.Api.RootFolders
+{
+ public class RootFolderResource : RestResource
+ {
+ public String Path { get; set; }
+ public UInt64 FreeSpace { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/NzbDrone.Api/Series/SeriesModule.cs b/NzbDrone.Api/Series/SeriesModule.cs
index 9bb148601..57cafeb0c 100644
--- a/NzbDrone.Api/Series/SeriesModule.cs
+++ b/NzbDrone.Api/Series/SeriesModule.cs
@@ -2,11 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using FluentValidation;
-using NzbDrone.Api.Extensions;
-using NzbDrone.Common;
-using NzbDrone.Common;
using NzbDrone.Core.SeriesStats;
-using NzbDrone.Api.Mapping;
using NzbDrone.Core.Tv;
using NzbDrone.Api.Validation;
@@ -40,10 +36,8 @@ namespace NzbDrone.Api.Series
private List AllSeries()
{
- var series = _seriesService.GetAllSeries().ToList();
var seriesStats = _seriesStatisticsService.SeriesStatistics();
-
- var seriesModels = series.InjectTo>();
+ var seriesModels = Apply(_seriesService.GetAllSeries);
foreach (var s in seriesModels)
{
@@ -61,40 +55,22 @@ namespace NzbDrone.Api.Series
private SeriesResource GetSeries(int id)
{
- var series = _seriesService.GetSeries(id);
- return series.InjectTo();
+ return Apply(_seriesService.GetSeries, id);
}
private SeriesResource AddSeries(SeriesResource seriesResource)
{
- var newSeries = Request.Body.FromJson();
-
//Todo: Alert the user if this series already exists
//Todo: We need to create the folder if the user is adding a new series
//(we can just create the folder and it won't blow up if it already exists)
//We also need to remove any special characters from the filename before attempting to create it
- var series = seriesResource.InjectTo();
- _seriesService.AddSeries(series);
- return series.InjectTo();
+
+ return Apply(_seriesService.AddSeries, seriesResource);
}
private SeriesResource UpdateSeries(SeriesResource seriesResource)
{
- var series = _seriesService.GetSeries(seriesResource.Id);
-
- series.Monitored = seriesResource.Monitored;
- series.SeasonFolder = seriesResource.SeasonFolder;
- series.QualityProfileId = seriesResource.QualityProfileId;
-
- //Todo: Do we want to force a scan when this path changes? Can we use events instead?
- series.RootFolderId = seriesResource.RootFolderId;
- series.FolderName = seriesResource.FolderName;
-
- series.BacklogSetting = seriesResource.BacklogSetting;
-
- _seriesService.UpdateSeries(series);
-
- return series.InjectTo();
+ return Apply(_seriesService.UpdateSeries, seriesResource);
}
private void DeleteSeries(int id)
diff --git a/NzbDrone.Core/Tv/SeriesService.cs b/NzbDrone.Core/Tv/SeriesService.cs
index cfb65460d..4ffe0c736 100644
--- a/NzbDrone.Core/Tv/SeriesService.cs
+++ b/NzbDrone.Core/Tv/SeriesService.cs
@@ -24,14 +24,14 @@ namespace NzbDrone.Core.Tv
bool IsMonitored(int id);
Series UpdateSeriesInfo(int seriesId);
Series GetSeries(int seriesId);
- void AddSeries(Series newSeries);
+ Series AddSeries(Series newSeries);
void UpdateFromSeriesEditor(IList editedSeries);
Series FindByTvdbId(int tvdbId);
Series FindByTitle(string title);
void SetSeriesType(int seriesId, SeriesTypes seriesTypes);
void DeleteSeries(int seriesId, bool deleteFiles);
List GetAllSeries();
- void UpdateSeries(Series series);
+ Series UpdateSeries(Series series);
bool SeriesPathExists(string folder);
List GetSeriesInList(IEnumerable seriesIds);
}
@@ -93,7 +93,7 @@ namespace NzbDrone.Core.Tv
return _seriesRepository.Get(seriesId);
}
- public void AddSeries(Series newSeries)
+ public Series AddSeries(Series newSeries)
{
Ensure.That(() => newSeries).IsNotNull();
@@ -115,6 +115,8 @@ namespace NzbDrone.Core.Tv
_seriesRepository.Insert(newSeries);
_eventAggregator.Publish(new SeriesAddedEvent(newSeries));
+
+ return newSeries;
}
public void UpdateFromSeriesEditor(IList editedSeries)
@@ -164,9 +166,9 @@ namespace NzbDrone.Core.Tv
return _seriesRepository.All().ToList();
}
- public void UpdateSeries(Series series)
+ public Series UpdateSeries(Series series)
{
- _seriesRepository.Update(series);
+ return _seriesRepository.Update(series);
}
public bool SeriesPathExists(string folder)
diff --git a/NzbDrone.Integration.Test/Client/ClientBase.cs b/NzbDrone.Integration.Test/Client/ClientBase.cs
index 7a61831fb..daaa6e8e9 100644
--- a/NzbDrone.Integration.Test/Client/ClientBase.cs
+++ b/NzbDrone.Integration.Test/Client/ClientBase.cs
@@ -1,29 +1,32 @@
using System.Collections.Generic;
using System.Net;
using FluentAssertions;
-using FluentValidation;
-using FluentValidation.Results;
using NLog;
-using Newtonsoft.Json;
+using NzbDrone.Api.REST;
using RestSharp;
namespace NzbDrone.Integration.Test.Client
{
- public abstract class ClientBase where TResource : new()
+ public class ClientBase where TResource : RestResource, new()
{
private readonly IRestClient _restClient;
private readonly string _resource;
private readonly Logger _logger;
- protected ClientBase(IRestClient restClient, string resource)
+ public ClientBase(IRestClient restClient, string resource = null)
{
+ if (resource == null)
+ {
+ resource = new TResource().ResourceName;
+ }
+
_restClient = restClient;
_resource = resource;
_logger = LogManager.GetLogger("REST");
}
- public List GetAll()
+ public List All()
{
var request = BuildRequest();
return Get>(request);
@@ -36,6 +39,12 @@ namespace NzbDrone.Integration.Test.Client
return Post(request);
}
+ public void Delete(int id)
+ {
+ var request = BuildRequest(id.ToString());
+ Delete(request);
+ }
+
public List InvalidPost(TResource body)
{
var request = BuildRequest();
@@ -63,6 +72,12 @@ namespace NzbDrone.Integration.Test.Client
return Execute(request, statusCode);
}
+ public void Delete(IRestRequest request, HttpStatusCode statusCode = HttpStatusCode.OK)
+ {
+ request.Method = Method.DELETE;
+ Execute