Updated Nancy to 2.0
This commit is contained in:
parent
54604e45e0
commit
90fb1646e0
|
@ -40,7 +40,7 @@ export default function createAjaxRequest(originalAjaxOptions) {
|
|||
}
|
||||
}
|
||||
|
||||
const ajaxOptions = { ...originalAjaxOptions };
|
||||
const ajaxOptions = { dataType: 'json', ...originalAjaxOptions };
|
||||
|
||||
if (isRelative(ajaxOptions)) {
|
||||
moveBodyToQuery(ajaxOptions);
|
||||
|
|
|
@ -26,11 +26,11 @@ namespace NzbDrone.Api.Calendar
|
|||
_episodeService = episodeService;
|
||||
_tagService = tagService;
|
||||
|
||||
Get["/NzbDrone.ics"] = options => GetCalendarFeed();
|
||||
Get["/Sonarr.ics"] = options => GetCalendarFeed();
|
||||
Get("/NzbDrone.ics", options => GetCalendarFeed());
|
||||
Get("/Sonarr.ics", options => GetCalendarFeed());
|
||||
}
|
||||
|
||||
private Response GetCalendarFeed()
|
||||
private object GetCalendarFeed()
|
||||
{
|
||||
var pastDays = 7;
|
||||
var futureDays = 28;
|
||||
|
|
|
@ -2,13 +2,10 @@
|
|||
using System.Linq;
|
||||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
using Nancy.Responses;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Organizer;
|
||||
using Nancy.ModelBinding;
|
||||
using Sonarr.Http.Extensions;
|
||||
using Sonarr.Http;
|
||||
using Sonarr.Http.Mapping;
|
||||
|
||||
namespace NzbDrone.Api.Config
|
||||
{
|
||||
|
@ -33,7 +30,7 @@ namespace NzbDrone.Api.Config
|
|||
GetResourceById = GetNamingConfig;
|
||||
UpdateResource = UpdateNamingConfig;
|
||||
|
||||
Get["/samples"] = x => GetExamples(this.Bind<NamingConfigResource>());
|
||||
Get("/samples", x => GetExamples(this.Bind<NamingConfigResource>()));
|
||||
|
||||
SharedValidator.RuleFor(c => c.MultiEpisodeStyle).InclusiveBetween(0, 5);
|
||||
SharedValidator.RuleFor(c => c.StandardEpisodeFormat).ValidEpisodeFormat();
|
||||
|
@ -71,7 +68,7 @@ namespace NzbDrone.Api.Config
|
|||
return GetNamingConfig();
|
||||
}
|
||||
|
||||
private JsonResponse<NamingSampleResource> GetExamples(NamingConfigResource config)
|
||||
private object GetExamples(NamingConfigResource config)
|
||||
{
|
||||
var nameSpec = config.ToModel();
|
||||
var sampleResource = new NamingSampleResource();
|
||||
|
@ -114,7 +111,7 @@ namespace NzbDrone.Api.Config
|
|||
? "Invalid format"
|
||||
: _filenameSampleService.GetSpecialsFolderSample(nameSpec);
|
||||
|
||||
return sampleResource.AsResponse();
|
||||
return sampleResource;
|
||||
}
|
||||
|
||||
private void ValidateFormatResult(NamingConfig nameSpec)
|
||||
|
|
|
@ -23,49 +23,49 @@ namespace NzbDrone.Api.FileSystem
|
|||
_fileSystemLookupService = fileSystemLookupService;
|
||||
_diskProvider = diskProvider;
|
||||
_diskScanService = diskScanService;
|
||||
Get["/"] = x => GetContents();
|
||||
Get["/type"] = x => GetEntityType();
|
||||
Get["/mediafiles"] = x => GetMediaFiles();
|
||||
Get("/", x => GetContents());
|
||||
Get("/type", x => GetEntityType());
|
||||
Get("/mediafiles", x => GetMediaFiles());
|
||||
}
|
||||
|
||||
private Response GetContents()
|
||||
private object GetContents()
|
||||
{
|
||||
var pathQuery = Request.Query.path;
|
||||
var includeFiles = Request.GetBooleanQueryParameter("includeFiles");
|
||||
var allowFoldersWithoutTrailingSlashes = Request.GetBooleanQueryParameter("allowFoldersWithoutTrailingSlashes");
|
||||
|
||||
return _fileSystemLookupService.LookupContents((string)pathQuery.Value, includeFiles, allowFoldersWithoutTrailingSlashes).AsResponse();
|
||||
return _fileSystemLookupService.LookupContents((string)pathQuery.Value, includeFiles, allowFoldersWithoutTrailingSlashes);
|
||||
}
|
||||
|
||||
private Response GetEntityType()
|
||||
private object GetEntityType()
|
||||
{
|
||||
var pathQuery = Request.Query.path;
|
||||
var path = (string)pathQuery.Value;
|
||||
|
||||
if (_diskProvider.FileExists(path))
|
||||
{
|
||||
return new { type = "file" }.AsResponse();
|
||||
return new { type = "file" };
|
||||
}
|
||||
|
||||
//Return folder even if it doesn't exist on disk to avoid leaking anything from the UI about the underlying system
|
||||
return new { type = "folder" }.AsResponse();
|
||||
return new { type = "folder" };
|
||||
}
|
||||
|
||||
private Response GetMediaFiles()
|
||||
private object GetMediaFiles()
|
||||
{
|
||||
var pathQuery = Request.Query.path;
|
||||
var path = (string)pathQuery.Value;
|
||||
|
||||
if (!_diskProvider.FolderExists(path))
|
||||
{
|
||||
return new string[0].AsResponse();
|
||||
return new string[0];
|
||||
}
|
||||
|
||||
return _diskScanService.GetVideoFiles(path).Select(f => new {
|
||||
Path = f,
|
||||
RelativePath = path.GetRelativePath(f),
|
||||
Name = Path.GetFileName(f)
|
||||
}).AsResponse();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,10 +3,8 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using Nancy;
|
||||
using NzbDrone.Api.Episodes;
|
||||
using Sonarr.Http.Extensions;
|
||||
using NzbDrone.Api.Series;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.History;
|
||||
|
@ -30,8 +28,8 @@ namespace NzbDrone.Api.History
|
|||
_failedDownloadService = failedDownloadService;
|
||||
GetResourcePaged = GetHistory;
|
||||
|
||||
Get["/since"] = x => GetHistorySince();
|
||||
Post["/failed"] = x => MarkAsFailed();
|
||||
Get("/since", x => GetHistorySince());
|
||||
Post("/failed", x => MarkAsFailed());
|
||||
}
|
||||
|
||||
protected HistoryResource MapToResource(Core.History.History model)
|
||||
|
@ -91,11 +89,11 @@ namespace NzbDrone.Api.History
|
|||
return _historyService.Since(date, eventType).Select(MapToResource).ToList();
|
||||
}
|
||||
|
||||
private Response MarkAsFailed()
|
||||
private object MarkAsFailed()
|
||||
{
|
||||
var id = (int)Request.Form.Id;
|
||||
_failedDownloadService.MarkAsFailed(id);
|
||||
return new object().AsResponse();
|
||||
return new object();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ using NzbDrone.Core.IndexerSearch;
|
|||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using Nancy.ModelBinding;
|
||||
using Sonarr.Http.Extensions;
|
||||
using NzbDrone.Common.Cache;
|
||||
using HttpStatusCode = System.Net.HttpStatusCode;
|
||||
|
||||
|
@ -43,7 +42,7 @@ namespace NzbDrone.Api.Indexers
|
|||
_logger = logger;
|
||||
|
||||
GetResourceAll = GetReleases;
|
||||
Post["/"] = x => DownloadRelease(this.Bind<ReleaseResource>());
|
||||
Post("/", x => DownloadRelease(this.Bind<ReleaseResource>()));
|
||||
|
||||
PostValidator.RuleFor(s => s.DownloadAllowed).Equal(true);
|
||||
PostValidator.RuleFor(s => s.Guid).NotEmpty();
|
||||
|
@ -51,7 +50,7 @@ namespace NzbDrone.Api.Indexers
|
|||
_remoteEpisodeCache = cacheManager.GetCache<RemoteEpisode>(GetType(), "remoteEpisodes");
|
||||
}
|
||||
|
||||
private Response DownloadRelease(ReleaseResource release)
|
||||
private object DownloadRelease(ReleaseResource release)
|
||||
{
|
||||
var remoteEpisode = _remoteEpisodeCache.Find(GetCacheKey(release));
|
||||
|
||||
|
@ -72,7 +71,7 @@ namespace NzbDrone.Api.Indexers
|
|||
throw new NzbDroneClientException(HttpStatusCode.Conflict, "Getting release from indexer failed");
|
||||
}
|
||||
|
||||
return release.AsResponse();
|
||||
return release;
|
||||
}
|
||||
|
||||
private List<ReleaseResource> GetReleases()
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FluentValidation;
|
||||
using Nancy;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Datastore;
|
||||
|
@ -9,7 +8,6 @@ using NzbDrone.Core.DecisionEngine;
|
|||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using Sonarr.Http.Extensions;
|
||||
|
||||
namespace NzbDrone.Api.Indexers
|
||||
{
|
||||
|
@ -30,7 +28,7 @@ namespace NzbDrone.Api.Indexers
|
|||
_indexerFactory = indexerFactory;
|
||||
_logger = logger;
|
||||
|
||||
Post["/push"] = x => ProcessRelease(ReadResourceFromRequest());
|
||||
Post("/push", x => ProcessRelease(ReadResourceFromRequest()));
|
||||
|
||||
PostValidator.RuleFor(s => s.Title).NotEmpty();
|
||||
PostValidator.RuleFor(s => s.DownloadUrl).NotEmpty();
|
||||
|
@ -38,7 +36,7 @@ namespace NzbDrone.Api.Indexers
|
|||
PostValidator.RuleFor(s => s.PublishDate).NotEmpty();
|
||||
}
|
||||
|
||||
private Response ProcessRelease(ReleaseResource release)
|
||||
private object ProcessRelease(ReleaseResource release)
|
||||
{
|
||||
_logger.Info("Release pushed: {0} - {1}", release.Title, release.DownloadUrl);
|
||||
|
||||
|
@ -51,7 +49,7 @@ namespace NzbDrone.Api.Indexers
|
|||
var decisions = _downloadDecisionMaker.GetRssDecision(new List<ReleaseInfo> { info });
|
||||
_downloadDecisionProcessor.ProcessDecisions(decisions);
|
||||
|
||||
return MapDecisions(decisions).First().AsResponse();
|
||||
return MapDecisions(decisions).First();
|
||||
}
|
||||
|
||||
private void ResolveIndexer(ReleaseInfo release)
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace NzbDrone.Api.Logs
|
|||
_configFileProvider = configFileProvider;
|
||||
GetResourceAll = GetLogFilesResponse;
|
||||
|
||||
Get[LOGFILE_ROUTE] = options => GetLogFileResponse(options.filename);
|
||||
Get(LOGFILE_ROUTE, options => GetLogFileResponse(options.filename));
|
||||
}
|
||||
|
||||
private List<LogFileResource> GetLogFilesResponse()
|
||||
|
@ -53,7 +53,7 @@ namespace NzbDrone.Api.Logs
|
|||
return result.OrderByDescending(l => l.LastWriteTime).ToList();
|
||||
}
|
||||
|
||||
private Response GetLogFileResponse(string filename)
|
||||
private object GetLogFileResponse(string filename)
|
||||
{
|
||||
LogManager.Flush();
|
||||
|
||||
|
|
|
@ -22,10 +22,10 @@ namespace NzbDrone.Api.MediaCovers
|
|||
_appFolderInfo = appFolderInfo;
|
||||
_diskProvider = diskProvider;
|
||||
|
||||
Get[MEDIA_COVER_ROUTE] = options => GetMediaCover(options.seriesId, options.filename);
|
||||
Get(MEDIA_COVER_ROUTE, options => GetMediaCover(options.seriesId, options.filename));
|
||||
}
|
||||
|
||||
private Response GetMediaCover(int seriesId, string filename)
|
||||
private object GetMediaCover(int seriesId, string filename)
|
||||
{
|
||||
var filePath = Path.Combine(_appFolderInfo.GetAppDataPath(), "MediaCover", seriesId.ToString(), filename);
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
using Nancy;
|
||||
using Sonarr.Http;
|
||||
|
||||
namespace NzbDrone.Api
|
||||
{
|
||||
public abstract class NzbDroneApiModule : NancyModule
|
||||
public abstract class NzbDroneApiModule : SonarrModule
|
||||
{
|
||||
protected NzbDroneApiModule(string resource)
|
||||
: base("/api/" + resource.Trim('/'))
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
using Nancy;
|
||||
using Sonarr.Http;
|
||||
|
||||
namespace NzbDrone.Api
|
||||
{
|
||||
public abstract class NzbDroneFeedModule : NancyModule
|
||||
public abstract class NzbDroneFeedModule : SonarrModule
|
||||
{
|
||||
protected NzbDroneFeedModule(string resource)
|
||||
: base("/feed/" + resource.Trim('/'))
|
||||
|
|
|
@ -8,13 +8,13 @@ namespace NzbDrone.Api.Profiles
|
|||
public LegacyProfileModule()
|
||||
: base("qualityprofile")
|
||||
{
|
||||
Get["/"] = x =>
|
||||
Get("/", x =>
|
||||
{
|
||||
string queryString = ConvertQueryParams(Request.Query);
|
||||
var url = string.Format("/api/profile?{0}", queryString);
|
||||
|
||||
return Response.AsRedirect(url);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private string ConvertQueryParams(DynamicDictionary query)
|
||||
|
|
|
@ -3,15 +3,12 @@ using System.Linq;
|
|||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
using Nancy;
|
||||
using Sonarr.Http.Extensions;
|
||||
using NzbDrone.Common.Reflection;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using Sonarr.Http;
|
||||
using Sonarr.Http.ClientSchema;
|
||||
using Sonarr.Http.Mapping;
|
||||
|
||||
namespace NzbDrone.Api
|
||||
{
|
||||
|
@ -27,9 +24,9 @@ namespace NzbDrone.Api
|
|||
{
|
||||
_providerFactory = providerFactory;
|
||||
|
||||
Get["schema"] = x => GetTemplates();
|
||||
Post["test"] = x => Test(ReadResourceFromRequest(true));
|
||||
Post["action/{action}"] = x => RequestAction(x.action, ReadResourceFromRequest(true));
|
||||
Get("schema", x => GetTemplates());
|
||||
Post("test", x => Test(ReadResourceFromRequest(true)));
|
||||
Post("action/{action}", x => RequestAction(x.action, ReadResourceFromRequest(true)));
|
||||
|
||||
GetResourceAll = GetAll;
|
||||
GetResourceById = GetProviderById;
|
||||
|
@ -146,7 +143,7 @@ namespace NzbDrone.Api
|
|||
_providerFactory.Delete(id);
|
||||
}
|
||||
|
||||
private Response GetTemplates()
|
||||
private object GetTemplates()
|
||||
{
|
||||
var defaultDefinitions = _providerFactory.GetDefaultDefinitions().OrderBy(p => p.ImplementationName).ToList();
|
||||
|
||||
|
@ -170,10 +167,10 @@ namespace NzbDrone.Api
|
|||
result.Add(providerResource);
|
||||
}
|
||||
|
||||
return result.AsResponse();
|
||||
return result;
|
||||
}
|
||||
|
||||
private Response Test(TProviderResource providerResource)
|
||||
private object Test(TProviderResource providerResource)
|
||||
{
|
||||
// Don't validate when getting the definition so we can validate afterwards (avoids validation being skipped because the provider is disabled)
|
||||
var providerDefinition = GetDefinition(providerResource, true, false);
|
||||
|
@ -185,7 +182,7 @@ namespace NzbDrone.Api
|
|||
}
|
||||
|
||||
|
||||
private Response RequestAction(string action, TProviderResource providerResource)
|
||||
private object RequestAction(string action, TProviderResource providerResource)
|
||||
{
|
||||
var providerDefinition = GetDefinition(providerResource, true, false);
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using Nancy;
|
||||
using Nancy.Responses;
|
||||
using Sonarr.Http.Extensions;
|
||||
using Sonarr.Http.REST;
|
||||
using NzbDrone.Core.Download;
|
||||
|
@ -37,12 +36,12 @@ namespace NzbDrone.Api.Queue
|
|||
_pendingReleaseService = pendingReleaseService;
|
||||
_downloadService = downloadService;
|
||||
|
||||
Delete[@"/(?<id>[\d]{1,10})"] = x => Remove((int)x.Id);
|
||||
Post["/import"] = x => Import();
|
||||
Post["/grab"] = x => Grab();
|
||||
Delete(@"/(?<id>[\d]{1,10})", x => Remove((int)x.Id));
|
||||
Post("/import", x => Import());
|
||||
Post("/grab", x => Grab());
|
||||
}
|
||||
|
||||
private Response Remove(int id)
|
||||
private object Remove(int id)
|
||||
{
|
||||
var blacklist = false;
|
||||
var blacklistQuery = Request.Query.blacklist;
|
||||
|
@ -58,7 +57,7 @@ namespace NzbDrone.Api.Queue
|
|||
{
|
||||
_pendingReleaseService.RemovePendingQueueItems(pendingRelease.Id);
|
||||
|
||||
return new object().AsResponse();
|
||||
return new object();
|
||||
}
|
||||
|
||||
var trackedDownload = GetTrackedDownload(id);
|
||||
|
@ -82,20 +81,20 @@ namespace NzbDrone.Api.Queue
|
|||
_failedDownloadService.MarkAsFailed(trackedDownload.DownloadItem.DownloadId);
|
||||
}
|
||||
|
||||
return new object().AsResponse();
|
||||
return new object();
|
||||
}
|
||||
|
||||
private JsonResponse<QueueResource> Import()
|
||||
private object Import()
|
||||
{
|
||||
var resource = Request.Body.FromJson<QueueResource>();
|
||||
var trackedDownload = GetTrackedDownload(resource.Id);
|
||||
|
||||
_completedDownloadService.Process(trackedDownload, true);
|
||||
|
||||
return resource.AsResponse();
|
||||
return resource;
|
||||
}
|
||||
|
||||
private JsonResponse<QueueResource> Grab()
|
||||
private object Grab()
|
||||
{
|
||||
var resource = Request.Body.FromJson<QueueResource>();
|
||||
|
||||
|
@ -108,7 +107,7 @@ namespace NzbDrone.Api.Queue
|
|||
|
||||
_downloadService.DownloadReport(pendingRelease.RemoteEpisode);
|
||||
|
||||
return resource.AsResponse();
|
||||
return resource;
|
||||
}
|
||||
|
||||
private TrackedDownload GetTrackedDownload(int queueId)
|
||||
|
|
|
@ -12,10 +12,10 @@ namespace NzbDrone.Api.SeasonPass
|
|||
: base("/seasonpass")
|
||||
{
|
||||
_episodeMonitoredService = episodeMonitoredService;
|
||||
Post["/"] = series => UpdateAll();
|
||||
Post("/", series => UpdateAll());
|
||||
}
|
||||
|
||||
private Response UpdateAll()
|
||||
private object UpdateAll()
|
||||
{
|
||||
//Read from request
|
||||
var request = Request.Body.FromJson<SeasonPassResource>();
|
||||
|
@ -25,7 +25,7 @@ namespace NzbDrone.Api.SeasonPass
|
|||
_episodeMonitoredService.SetEpisodeMonitoredStatus(s, request.MonitoringOptions);
|
||||
}
|
||||
|
||||
return "ok".AsResponse(HttpStatusCode.Accepted);
|
||||
return ResponseWithCode("ok", HttpStatusCode.Accepted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,10 +17,10 @@ namespace NzbDrone.Api.Series
|
|||
{
|
||||
_seriesService = seriesService;
|
||||
_languageProfileService = languageProfileService;
|
||||
Put["/"] = series => SaveAll();
|
||||
Put("/", series => SaveAll());
|
||||
}
|
||||
|
||||
private Response SaveAll()
|
||||
private object SaveAll()
|
||||
{
|
||||
var resources = Request.Body.FromJson<List<SeriesResource>>();
|
||||
|
||||
|
@ -41,9 +41,9 @@ namespace NzbDrone.Api.Series
|
|||
return updatedSeries;
|
||||
}).ToList();
|
||||
|
||||
return _seriesService.UpdateSeries(seriesToUpdate, true)
|
||||
return ResponseWithCode(_seriesService.UpdateSeries(seriesToUpdate, true)
|
||||
.ToResource(false)
|
||||
.AsResponse(HttpStatusCode.Accepted);
|
||||
, HttpStatusCode.Accepted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
using System.Collections.Generic;
|
||||
using Nancy;
|
||||
using Sonarr.Http.Extensions;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
using System.Linq;
|
||||
using Sonarr.Http;
|
||||
using Sonarr.Http.Mapping;
|
||||
|
||||
namespace NzbDrone.Api.Series
|
||||
{
|
||||
|
@ -17,14 +15,14 @@ namespace NzbDrone.Api.Series
|
|||
: base("/series/lookup")
|
||||
{
|
||||
_searchProxy = searchProxy;
|
||||
Get["/"] = x => Search();
|
||||
Get("/", x => Search());
|
||||
}
|
||||
|
||||
|
||||
private Response Search()
|
||||
private object Search()
|
||||
{
|
||||
var tvDbResults = _searchProxy.SearchForNewSeries((string)Request.Query.term);
|
||||
return MapToResource(tvDbResults).AsResponse();
|
||||
return MapToResource(tvDbResults);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="FluentValidation" Version="8.4.0" />
|
||||
<PackageReference Include="Ical.Net" Version="2.2.32" />
|
||||
<PackageReference Include="Nancy" Version="1.4.4" />
|
||||
<PackageReference Include="Nancy.Authentication.Basic" Version="1.4.1" />
|
||||
<PackageReference Include="Nancy.Authentication.Forms" Version="1.4.1" />
|
||||
<PackageReference Include="Nancy" Version="2.0.0" />
|
||||
<PackageReference Include="Nancy.Authentication.Basic" Version="2.0.0" />
|
||||
<PackageReference Include="Nancy.Authentication.Forms" Version="2.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
using Nancy;
|
||||
using Nancy.Routing;
|
||||
using Sonarr.Http.Extensions;
|
||||
using Nancy.Routing;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
@ -37,13 +35,13 @@ namespace NzbDrone.Api.System
|
|||
_configFileProvider = configFileProvider;
|
||||
_database = database;
|
||||
_lifecycleService = lifecycleService;
|
||||
Get["/status"] = x => GetStatus();
|
||||
Get["/routes"] = x => GetRoutes();
|
||||
Post["/shutdown"] = x => Shutdown();
|
||||
Post["/restart"] = x => Restart();
|
||||
Get("/status", x => GetStatus());
|
||||
Get("/routes", x => GetRoutes());
|
||||
Post("/shutdown", x => Shutdown());
|
||||
Post("/restart", x => Restart());
|
||||
}
|
||||
|
||||
private Response GetStatus()
|
||||
private object GetStatus()
|
||||
{
|
||||
return new
|
||||
{
|
||||
|
@ -68,24 +66,24 @@ namespace NzbDrone.Api.System
|
|||
UrlBase = _configFileProvider.UrlBase,
|
||||
RuntimeVersion = _platformInfo.Version,
|
||||
RuntimeName = PlatformInfo.Platform
|
||||
}.AsResponse();
|
||||
};
|
||||
}
|
||||
|
||||
private Response GetRoutes()
|
||||
private object GetRoutes()
|
||||
{
|
||||
return _routeCacheProvider.GetCache().Values.AsResponse();
|
||||
return _routeCacheProvider.GetCache().Values;
|
||||
}
|
||||
|
||||
private Response Shutdown()
|
||||
private object Shutdown()
|
||||
{
|
||||
_lifecycleService.Shutdown();
|
||||
return "".AsResponse();
|
||||
return "";
|
||||
}
|
||||
|
||||
private Response Restart()
|
||||
private object Restart()
|
||||
{
|
||||
_lifecycleService.Restart();
|
||||
return "".AsResponse();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,13 +7,13 @@ namespace NzbDrone.Api.Wanted
|
|||
{
|
||||
public LegacyMissingModule() : base("missing")
|
||||
{
|
||||
Get["/"] = x =>
|
||||
Get("/", x =>
|
||||
{
|
||||
string queryString = ConvertQueryParams(Request.Query);
|
||||
var url = string.Format("/api/wanted/missing?{0}", queryString);
|
||||
|
||||
return Response.AsRedirect(url);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private string ConvertQueryParams(DynamicDictionary query)
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
using System.Collections.Generic;
|
||||
using Nancy.Bootstrapper;
|
||||
using Sonarr.Http;
|
||||
using NzbDrone.Common.Composition;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Http.Dispatchers;
|
||||
using NzbDrone.SignalR;
|
||||
using Sonarr.Http;
|
||||
|
||||
namespace NzbDrone.Host
|
||||
{
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNet.SignalR.SelfHost" Version="2.4.0" />
|
||||
<PackageReference Include="Nancy.Owin" Version="1.4.1" />
|
||||
<PackageReference Include="Nancy.Owin" Version="2.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\NzbDrone.Api\Sonarr.Api.csproj" />
|
||||
|
|
|
@ -27,10 +27,10 @@ namespace Sonarr.Api.V3.Calendar
|
|||
_episodeService = episodeService;
|
||||
_tagService = tagService;
|
||||
|
||||
Get["/Sonarr.ics"] = options => GetCalendarFeed();
|
||||
Get("/Sonarr.ics", options => GetCalendarFeed());
|
||||
}
|
||||
|
||||
private Response GetCalendarFeed()
|
||||
private object GetCalendarFeed()
|
||||
{
|
||||
var pastDays = 7;
|
||||
var futureDays = 28;
|
||||
|
|
|
@ -3,12 +3,9 @@ using System.Linq;
|
|||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
using Nancy.ModelBinding;
|
||||
using Nancy.Responses;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Organizer;
|
||||
using Sonarr.Http;
|
||||
using Sonarr.Http.Extensions;
|
||||
using Sonarr.Http.Mapping;
|
||||
|
||||
namespace Sonarr.Api.V3.Config
|
||||
{
|
||||
|
@ -33,7 +30,7 @@ namespace Sonarr.Api.V3.Config
|
|||
GetResourceById = GetNamingConfig;
|
||||
UpdateResource = UpdateNamingConfig;
|
||||
|
||||
Get["/examples"] = x => GetExamples(this.Bind<NamingConfigResource>());
|
||||
Get("/examples", x => GetExamples(this.Bind<NamingConfigResource>()));
|
||||
|
||||
SharedValidator.RuleFor(c => c.MultiEpisodeStyle).InclusiveBetween(0, 5);
|
||||
SharedValidator.RuleFor(c => c.StandardEpisodeFormat).ValidEpisodeFormat();
|
||||
|
@ -71,7 +68,7 @@ namespace Sonarr.Api.V3.Config
|
|||
return GetNamingConfig();
|
||||
}
|
||||
|
||||
private JsonResponse<NamingExampleResource> GetExamples(NamingConfigResource config)
|
||||
private object GetExamples(NamingConfigResource config)
|
||||
{
|
||||
if (config.Id == 0)
|
||||
{
|
||||
|
@ -119,7 +116,7 @@ namespace Sonarr.Api.V3.Config
|
|||
? null
|
||||
: _filenameSampleService.GetSpecialsFolderSample(nameSpec);
|
||||
|
||||
return sampleResource.AsResponse();
|
||||
return sampleResource;
|
||||
}
|
||||
|
||||
private void ValidateFormatResult(NamingConfig nameSpec)
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using Sonarr.Http;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
||||
namespace Sonarr.Api.V3.Config
|
||||
{
|
||||
|
|
|
@ -43,8 +43,8 @@ namespace Sonarr.Api.V3.EpisodeFiles
|
|||
UpdateResource = SetQuality;
|
||||
DeleteResource = DeleteEpisodeFile;
|
||||
|
||||
Put["/editor"] = episodeFiles => SetQuality();
|
||||
Delete["/bulk"] = episodeFiles => DeleteEpisodeFiles();
|
||||
Put("/editor", episodeFiles => SetQuality());
|
||||
Delete("/bulk", episodeFiles => DeleteEpisodeFiles());
|
||||
}
|
||||
|
||||
private EpisodeFileResource GetEpisodeFile(int id)
|
||||
|
@ -97,7 +97,7 @@ namespace Sonarr.Api.V3.EpisodeFiles
|
|||
_mediaFileService.Update(episodeFile);
|
||||
}
|
||||
|
||||
private Response SetQuality()
|
||||
private object SetQuality()
|
||||
{
|
||||
var resource = Request.Body.FromJson<EpisodeFileListResource>();
|
||||
var episodeFiles = _mediaFileService.GetFiles(resource.EpisodeFileIds);
|
||||
|
@ -119,8 +119,8 @@ namespace Sonarr.Api.V3.EpisodeFiles
|
|||
|
||||
var series = _seriesService.GetSeries(episodeFiles.First().SeriesId);
|
||||
|
||||
return episodeFiles.ConvertAll(f => f.ToResource(series, _upgradableSpecification))
|
||||
.AsResponse(HttpStatusCode.Accepted);
|
||||
return ResponseWithCode(episodeFiles.ConvertAll(f => f.ToResource(series, _upgradableSpecification))
|
||||
, HttpStatusCode.Accepted);
|
||||
}
|
||||
|
||||
private void DeleteEpisodeFile(int id)
|
||||
|
@ -137,7 +137,7 @@ namespace Sonarr.Api.V3.EpisodeFiles
|
|||
_mediaFileDeletionService.DeleteEpisodeFile(series, episodeFile);
|
||||
}
|
||||
|
||||
private Response DeleteEpisodeFiles()
|
||||
private object DeleteEpisodeFiles()
|
||||
{
|
||||
var resource = Request.Body.FromJson<EpisodeFileListResource>();
|
||||
var episodeFiles = _mediaFileService.GetFiles(resource.EpisodeFileIds);
|
||||
|
@ -148,7 +148,7 @@ namespace Sonarr.Api.V3.EpisodeFiles
|
|||
_mediaFileDeletionService.DeleteEpisodeFile(series, episodeFile);
|
||||
}
|
||||
|
||||
return new object().AsResponse();
|
||||
return new object();
|
||||
}
|
||||
|
||||
public void Handle(EpisodeFileAddedEvent message)
|
||||
|
|
|
@ -20,8 +20,8 @@ namespace Sonarr.Api.V3.Episodes
|
|||
: base(episodeService, seriesService, upgradableSpecification, signalRBroadcaster)
|
||||
{
|
||||
GetResourceAll = GetEpisodes;
|
||||
Put[@"/(?<id>[\d]{1,10})"] = x => SetEpisodeMonitored(x.Id);
|
||||
Put["/monitor"] = x => SetEpisodesMonitored();
|
||||
Put(@"/(?<id>[\d]{1,10})", x => SetEpisodeMonitored(x.Id));
|
||||
Put("/monitor", x => SetEpisodesMonitored());
|
||||
}
|
||||
|
||||
private List<EpisodeResource> GetEpisodes()
|
||||
|
@ -57,23 +57,23 @@ namespace Sonarr.Api.V3.Episodes
|
|||
return MapToResource(_episodeService.GetEpisodes(episodeIds), false, false, includeImages);
|
||||
}
|
||||
|
||||
private Response SetEpisodeMonitored(int id)
|
||||
private object SetEpisodeMonitored(int id)
|
||||
{
|
||||
var resource = Request.Body.FromJson<EpisodeResource>();
|
||||
_episodeService.SetEpisodeMonitored(id, resource.Monitored);
|
||||
|
||||
return MapToResource(_episodeService.GetEpisode(id), false, false, false).AsResponse(HttpStatusCode.Accepted);
|
||||
return ResponseWithCode(MapToResource(_episodeService.GetEpisode(id), false, false, false), HttpStatusCode.Accepted);
|
||||
}
|
||||
|
||||
private Response SetEpisodesMonitored()
|
||||
private object SetEpisodesMonitored()
|
||||
{
|
||||
var includeImages = Request.GetBooleanQueryParameter("includeImages", false);
|
||||
var resource = Request.Body.FromJson<EpisodesMonitoredResource>();
|
||||
|
||||
_episodeService.SetMonitored(resource.EpisodeIds, resource.Monitored);
|
||||
|
||||
return MapToResource(_episodeService.GetEpisodes(resource.EpisodeIds), false, false, includeImages)
|
||||
.AsResponse(HttpStatusCode.Accepted);
|
||||
return ResponseWithCode(MapToResource(_episodeService.GetEpisodes(resource.EpisodeIds), false, false, includeImages)
|
||||
, HttpStatusCode.Accepted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,49 +23,49 @@ namespace Sonarr.Api.V3.FileSystem
|
|||
_fileSystemLookupService = fileSystemLookupService;
|
||||
_diskProvider = diskProvider;
|
||||
_diskScanService = diskScanService;
|
||||
Get["/"] = x => GetContents();
|
||||
Get["/type"] = x => GetEntityType();
|
||||
Get["/mediafiles"] = x => GetMediaFiles();
|
||||
Get("/", x => GetContents());
|
||||
Get("/type", x => GetEntityType());
|
||||
Get("/mediafiles", x => GetMediaFiles());
|
||||
}
|
||||
|
||||
private Response GetContents()
|
||||
private object GetContents()
|
||||
{
|
||||
var pathQuery = Request.Query.path;
|
||||
var includeFiles = Request.GetBooleanQueryParameter("includeFiles");
|
||||
var allowFoldersWithoutTrailingSlashes = Request.GetBooleanQueryParameter("allowFoldersWithoutTrailingSlashes");
|
||||
|
||||
return _fileSystemLookupService.LookupContents((string)pathQuery.Value, includeFiles, allowFoldersWithoutTrailingSlashes).AsResponse();
|
||||
return _fileSystemLookupService.LookupContents((string)pathQuery.Value, includeFiles, allowFoldersWithoutTrailingSlashes);
|
||||
}
|
||||
|
||||
private Response GetEntityType()
|
||||
private object GetEntityType()
|
||||
{
|
||||
var pathQuery = Request.Query.path;
|
||||
var path = (string)pathQuery.Value;
|
||||
|
||||
if (_diskProvider.FileExists(path))
|
||||
{
|
||||
return new { type = "file" }.AsResponse();
|
||||
return new { type = "file" };
|
||||
}
|
||||
|
||||
//Return folder even if it doesn't exist on disk to avoid leaking anything from the UI about the underlying system
|
||||
return new { type = "folder" }.AsResponse();
|
||||
return new { type = "folder" };
|
||||
}
|
||||
|
||||
private Response GetMediaFiles()
|
||||
private object GetMediaFiles()
|
||||
{
|
||||
var pathQuery = Request.Query.path;
|
||||
var path = (string)pathQuery.Value;
|
||||
|
||||
if (!_diskProvider.FolderExists(path))
|
||||
{
|
||||
return new string[0].AsResponse();
|
||||
return new string[0];
|
||||
}
|
||||
|
||||
return _diskScanService.GetVideoFiles(path).Select(f => new {
|
||||
Path = f,
|
||||
RelativePath = path.GetRelativePath(f),
|
||||
Name = Path.GetFileName(f)
|
||||
}).AsResponse();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,9 +30,9 @@ namespace Sonarr.Api.V3.History
|
|||
_failedDownloadService = failedDownloadService;
|
||||
GetResourcePaged = GetHistory;
|
||||
|
||||
Get["/since"] = x => GetHistorySince();
|
||||
Get["/series"] = x => GetSeriesHistory();
|
||||
Post["/failed"] = x => MarkAsFailed();
|
||||
Get("/since", x => GetHistorySince());
|
||||
Get("/series", x => GetSeriesHistory());
|
||||
Post("/failed", x => MarkAsFailed());
|
||||
}
|
||||
|
||||
protected HistoryResource MapToResource(NzbDrone.Core.History.History model, bool includeSeries, bool includeEpisode)
|
||||
|
@ -143,11 +143,11 @@ namespace Sonarr.Api.V3.History
|
|||
return _historyService.GetBySeries(seriesId, eventType).Select(h => MapToResource(h, includeSeries, includeEpisode)).ToList();
|
||||
}
|
||||
|
||||
private Response MarkAsFailed()
|
||||
private object MarkAsFailed()
|
||||
{
|
||||
var id = (int)Request.Form.Id;
|
||||
_failedDownloadService.MarkAsFailed(id);
|
||||
return new object().AsResponse();
|
||||
return new object();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ using NzbDrone.Core.Parser;
|
|||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Validation;
|
||||
using Sonarr.Http.Extensions;
|
||||
using HttpStatusCode = System.Net.HttpStatusCode;
|
||||
|
||||
namespace Sonarr.Api.V3.Indexers
|
||||
|
@ -58,12 +57,12 @@ namespace Sonarr.Api.V3.Indexers
|
|||
PostValidator.RuleFor(s => s.Guid).NotEmpty();
|
||||
|
||||
GetResourceAll = GetReleases;
|
||||
Post["/"] = x => DownloadRelease(ReadResourceFromRequest());
|
||||
Post("/", x => DownloadRelease(ReadResourceFromRequest()));
|
||||
|
||||
_remoteEpisodeCache = cacheManager.GetCache<RemoteEpisode>(GetType(), "remoteEpisodes");
|
||||
}
|
||||
|
||||
private Response DownloadRelease(ReleaseResource release)
|
||||
private object DownloadRelease(ReleaseResource release)
|
||||
{
|
||||
var remoteEpisode = _remoteEpisodeCache.Find(GetCacheKey(release));
|
||||
|
||||
|
@ -130,7 +129,7 @@ namespace Sonarr.Api.V3.Indexers
|
|||
throw new NzbDroneClientException(HttpStatusCode.Conflict, "Getting release from indexer failed");
|
||||
}
|
||||
|
||||
return release.AsResponse();
|
||||
return release;
|
||||
}
|
||||
|
||||
private List<ReleaseResource> GetReleases()
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
using System.Linq;
|
||||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
using Nancy;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Datastore;
|
||||
|
@ -10,7 +9,6 @@ using NzbDrone.Core.DecisionEngine;
|
|||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using Sonarr.Http.Extensions;
|
||||
|
||||
namespace Sonarr.Api.V3.Indexers
|
||||
{
|
||||
|
@ -36,10 +34,10 @@ namespace Sonarr.Api.V3.Indexers
|
|||
PostValidator.RuleFor(s => s.Protocol).NotEmpty();
|
||||
PostValidator.RuleFor(s => s.PublishDate).NotEmpty();
|
||||
|
||||
Post["/push"] = x => ProcessRelease(ReadResourceFromRequest());
|
||||
Post("/push", x => ProcessRelease(ReadResourceFromRequest()));
|
||||
}
|
||||
|
||||
private Response ProcessRelease(ReleaseResource release)
|
||||
private object ProcessRelease(ReleaseResource release)
|
||||
{
|
||||
_logger.Info("Release pushed: {0} - {1}", release.Title, release.DownloadUrl);
|
||||
|
||||
|
@ -59,7 +57,7 @@ namespace Sonarr.Api.V3.Indexers
|
|||
throw new ValidationException(new List<ValidationFailure>{ new ValidationFailure("Title", "Unable to parse", release.Title) });
|
||||
}
|
||||
|
||||
return MapDecisions(new [] { firstDecision }).AsResponse();
|
||||
return MapDecisions(new [] { firstDecision });
|
||||
}
|
||||
|
||||
private void ResolveIndexer(ReleaseInfo release)
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace Sonarr.Api.V3.Logs
|
|||
_configFileProvider = configFileProvider;
|
||||
GetResourceAll = GetLogFilesResponse;
|
||||
|
||||
Get[LOGFILE_ROUTE] = options => GetLogFileResponse(options.filename);
|
||||
Get(LOGFILE_ROUTE, options => GetLogFileResponse(options.filename));
|
||||
}
|
||||
|
||||
private List<LogFileResource> GetLogFilesResponse()
|
||||
|
@ -52,7 +52,7 @@ namespace Sonarr.Api.V3.Logs
|
|||
return result.OrderByDescending(l => l.LastWriteTime).ToList();
|
||||
}
|
||||
|
||||
private Response GetLogFileResponse(string filename)
|
||||
private object GetLogFileResponse(string filename)
|
||||
{
|
||||
var filePath = GetLogFilePath(filename);
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace Sonarr.Api.V3.ManualImport
|
|||
_manualImportService = manualImportService;
|
||||
|
||||
GetResourceAll = GetMediaFiles;
|
||||
Post["/"] = x => ReprocessItems();
|
||||
Post("/", x => ReprocessItems());
|
||||
}
|
||||
|
||||
private List<ManualImportResource> GetMediaFiles()
|
||||
|
@ -32,7 +32,7 @@ namespace Sonarr.Api.V3.ManualImport
|
|||
return _manualImportService.GetMediaFiles(folder, downloadId, seriesId, filterExistingFiles).ToResource().Select(AddQualityWeight).ToList();
|
||||
}
|
||||
|
||||
private Response ReprocessItems()
|
||||
private object ReprocessItems()
|
||||
{
|
||||
var items = Request.Body.FromJson<List<ManualImportReprocessResource>>();
|
||||
|
||||
|
@ -44,7 +44,7 @@ namespace Sonarr.Api.V3.ManualImport
|
|||
item.Episodes = processedItem.Episodes.ToResource();
|
||||
}
|
||||
|
||||
return items.AsResponse();
|
||||
return items;
|
||||
}
|
||||
|
||||
private ManualImportResource AddQualityWeight(ManualImportResource item)
|
||||
|
|
|
@ -22,10 +22,10 @@ namespace Sonarr.Api.V3.MediaCovers
|
|||
_appFolderInfo = appFolderInfo;
|
||||
_diskProvider = diskProvider;
|
||||
|
||||
Get[MEDIA_COVER_ROUTE] = options => GetMediaCover(options.seriesId, options.filename);
|
||||
Get(MEDIA_COVER_ROUTE, options => GetMediaCover(options.seriesId, options.filename));
|
||||
}
|
||||
|
||||
private Response GetMediaCover(int seriesId, string filename)
|
||||
private object GetMediaCover(int seriesId, string filename)
|
||||
{
|
||||
var filePath = Path.Combine(_appFolderInfo.GetAppDataPath(), "MediaCover", seriesId.ToString(), filename);
|
||||
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
using Nancy;
|
||||
using NzbDrone.Core.Profiles.Delay;
|
||||
using Sonarr.Http;
|
||||
using Sonarr.Http.Extensions;
|
||||
using Sonarr.Http.REST;
|
||||
using Sonarr.Http.Validation;
|
||||
|
||||
|
@ -24,7 +22,7 @@ namespace Sonarr.Api.V3.Profiles.Delay
|
|||
UpdateResource = Update;
|
||||
CreateResource = Create;
|
||||
DeleteResource = DeleteProfile;
|
||||
Put[@"/reorder/(?<id>[\d]{1,10})"] = options => Reorder(options.Id);
|
||||
Put(@"/reorder/(?<id>[\d]{1,10})", options => Reorder(options.Id));
|
||||
|
||||
SharedValidator.RuleFor(d => d.Tags).NotEmpty().When(d => d.Id != 1);
|
||||
SharedValidator.RuleFor(d => d.Tags).EmptyCollection<DelayProfileResource, int>().When(d => d.Id == 1);
|
||||
|
@ -75,14 +73,14 @@ namespace Sonarr.Api.V3.Profiles.Delay
|
|||
return _delayProfileService.All().ToResource();
|
||||
}
|
||||
|
||||
private Response Reorder(int id)
|
||||
private object Reorder(int id)
|
||||
{
|
||||
ValidateId(id);
|
||||
|
||||
var afterIdQuery = Request.Query.After;
|
||||
int? afterId = afterIdQuery.HasValue ? Convert.ToInt32(afterIdQuery.Value) : null;
|
||||
|
||||
return _delayProfileService.Reorder(id, afterId).ToResource().AsResponse();
|
||||
return _delayProfileService.Reorder(id, afterId).ToResource();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,12 +3,10 @@ using System.Linq;
|
|||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
using Nancy;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
using Sonarr.Http;
|
||||
using Sonarr.Http.Extensions;
|
||||
|
||||
namespace Sonarr.Api.V3
|
||||
{
|
||||
|
@ -26,10 +24,10 @@ namespace Sonarr.Api.V3
|
|||
_providerFactory = providerFactory;
|
||||
_resourceMapper = resourceMapper;
|
||||
|
||||
Get["schema"] = x => GetTemplates();
|
||||
Post["test"] = x => Test(ReadResourceFromRequest(true));
|
||||
Post["testall"] = x => TestAll();
|
||||
Post["action/{action}"] = x => RequestAction(x.action, ReadResourceFromRequest(true));
|
||||
Get("schema", x => GetTemplates());
|
||||
Post("test", x => Test(ReadResourceFromRequest(true)));
|
||||
Post("testall", x => TestAll());
|
||||
Post("action/{action}", x => RequestAction(x.action, ReadResourceFromRequest(true)));
|
||||
|
||||
GetResourceAll = GetAll;
|
||||
GetResourceById = GetProviderById;
|
||||
|
@ -112,7 +110,7 @@ namespace Sonarr.Api.V3
|
|||
_providerFactory.Delete(id);
|
||||
}
|
||||
|
||||
private Response GetTemplates()
|
||||
private object GetTemplates()
|
||||
{
|
||||
var defaultDefinitions = _providerFactory.GetDefaultDefinitions().OrderBy(p => p.ImplementationName).ToList();
|
||||
|
||||
|
@ -133,10 +131,10 @@ namespace Sonarr.Api.V3
|
|||
result.Add(providerResource);
|
||||
}
|
||||
|
||||
return result.AsResponse();
|
||||
return result;
|
||||
}
|
||||
|
||||
private Response Test(TProviderResource providerResource)
|
||||
private object Test(TProviderResource providerResource)
|
||||
{
|
||||
var providerDefinition = GetDefinition(providerResource, true);
|
||||
|
||||
|
@ -145,7 +143,7 @@ namespace Sonarr.Api.V3
|
|||
return "{}";
|
||||
}
|
||||
|
||||
private Response TestAll()
|
||||
private object TestAll()
|
||||
{
|
||||
var providerDefinitions = _providerFactory.All()
|
||||
.Where(c => c.Settings.Validate().IsValid && c.Enable)
|
||||
|
@ -163,10 +161,10 @@ namespace Sonarr.Api.V3
|
|||
});
|
||||
}
|
||||
|
||||
return result.AsResponse(result.Any(c => !c.IsValid) ? HttpStatusCode.BadRequest : HttpStatusCode.OK);
|
||||
return ResponseWithCode(result, result.Any(c => !c.IsValid) ? HttpStatusCode.BadRequest : HttpStatusCode.OK);
|
||||
}
|
||||
|
||||
private Response RequestAction(string action, TProviderResource providerResource)
|
||||
private object RequestAction(string action, TProviderResource providerResource)
|
||||
{
|
||||
var providerDefinition = GetDefinition(providerResource, true, false);
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace Sonarr.Api.V3.Qualities
|
|||
GetResourceAll = GetAll;
|
||||
GetResourceById = GetById;
|
||||
UpdateResource = Update;
|
||||
Put["/update"] = d => UpdateMany();
|
||||
Put("/update", d => UpdateMany());
|
||||
}
|
||||
|
||||
private void Update(QualityDefinitionResource resource)
|
||||
|
@ -37,7 +37,7 @@ namespace Sonarr.Api.V3.Qualities
|
|||
return _qualityDefinitionService.All().ToResource();
|
||||
}
|
||||
|
||||
private Response UpdateMany()
|
||||
private object UpdateMany()
|
||||
{
|
||||
//Read from request
|
||||
var qualityDefinitions = Request.Body.FromJson<List<QualityDefinitionResource>>()
|
||||
|
@ -46,9 +46,9 @@ namespace Sonarr.Api.V3.Qualities
|
|||
|
||||
_qualityDefinitionService.UpdateMany(qualityDefinitions);
|
||||
|
||||
return _qualityDefinitionService.All()
|
||||
return ResponseWithCode(_qualityDefinitionService.All()
|
||||
.ToResource()
|
||||
.AsResponse(HttpStatusCode.Accepted);
|
||||
, HttpStatusCode.Accepted);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -34,14 +34,14 @@ namespace Sonarr.Api.V3.Queue
|
|||
_pendingReleaseService = pendingReleaseService;
|
||||
_downloadService = downloadService;
|
||||
|
||||
Post[@"/grab/(?<id>[\d]{1,10})"] = x => Grab((int)x.Id);
|
||||
Post["/grab/bulk"] = x => Grab();
|
||||
Post(@"/grab/(?<id>[\d]{1,10})", x => Grab((int)x.Id));
|
||||
Post("/grab/bulk", x => Grab());
|
||||
|
||||
Delete[@"/(?<id>[\d]{1,10})"] = x => Remove((int)x.Id);
|
||||
Delete["/bulk"] = x => Remove();
|
||||
Delete(@"/(?<id>[\d]{1,10})", x => Remove((int)x.Id));
|
||||
Delete("/bulk", x => Remove());
|
||||
}
|
||||
|
||||
private Response Grab(int id)
|
||||
private object Grab(int id)
|
||||
{
|
||||
var pendingRelease = _pendingReleaseService.FindPendingQueueItem(id);
|
||||
|
||||
|
@ -52,10 +52,10 @@ namespace Sonarr.Api.V3.Queue
|
|||
|
||||
_downloadService.DownloadReport(pendingRelease.RemoteEpisode);
|
||||
|
||||
return new object().AsResponse();
|
||||
return new object();
|
||||
}
|
||||
|
||||
private Response Grab()
|
||||
private object Grab()
|
||||
{
|
||||
var resource = Request.Body.FromJson<QueueBulkResource>();
|
||||
|
||||
|
@ -71,10 +71,10 @@ namespace Sonarr.Api.V3.Queue
|
|||
_downloadService.DownloadReport(pendingRelease.RemoteEpisode);
|
||||
}
|
||||
|
||||
return new object().AsResponse();
|
||||
return new object();
|
||||
}
|
||||
|
||||
private Response Remove(int id)
|
||||
private object Remove(int id)
|
||||
{
|
||||
var blacklist = Request.GetBooleanQueryParameter("blacklist");
|
||||
|
||||
|
@ -85,10 +85,10 @@ namespace Sonarr.Api.V3.Queue
|
|||
_trackedDownloadService.StopTracking(trackedDownload.DownloadItem.DownloadId);
|
||||
}
|
||||
|
||||
return new object().AsResponse();
|
||||
return new object();
|
||||
}
|
||||
|
||||
private Response Remove()
|
||||
private object Remove()
|
||||
{
|
||||
var blacklist = Request.GetBooleanQueryParameter("blacklist");
|
||||
|
||||
|
@ -107,7 +107,7 @@ namespace Sonarr.Api.V3.Queue
|
|||
|
||||
_trackedDownloadService.StopTracking(trackedDownloadIds);
|
||||
|
||||
return new object().AsResponse();
|
||||
return new object();
|
||||
}
|
||||
|
||||
private TrackedDownload Remove(int id, bool blacklist)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using Nancy.Responses;
|
||||
using NzbDrone.Common.TPL;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
using NzbDrone.Core.Download.Pending;
|
||||
|
@ -8,7 +7,6 @@ using NzbDrone.Core.Messaging.Events;
|
|||
using NzbDrone.Core.Queue;
|
||||
using NzbDrone.SignalR;
|
||||
using Sonarr.Http;
|
||||
using Sonarr.Http.Extensions;
|
||||
|
||||
namespace Sonarr.Api.V3.Queue
|
||||
{
|
||||
|
@ -29,12 +27,12 @@ namespace Sonarr.Api.V3.Queue
|
|||
_broadcastDebounce = new Debouncer(BroadcastChange, TimeSpan.FromSeconds(5));
|
||||
|
||||
|
||||
Get["/"] = x => GetQueueStatusResponse();
|
||||
Get("/", x => GetQueueStatusResponse());
|
||||
}
|
||||
|
||||
private JsonResponse<QueueStatusResource> GetQueueStatusResponse()
|
||||
private object GetQueueStatusResponse()
|
||||
{
|
||||
return GetQueueStatus().AsResponse();
|
||||
return GetQueueStatus();
|
||||
}
|
||||
|
||||
private QueueStatusResource GetQueueStatus()
|
||||
|
|
|
@ -15,10 +15,10 @@ namespace Sonarr.Api.V3.SeasonPass
|
|||
{
|
||||
_seriesService = seriesService;
|
||||
_episodeMonitoredService = episodeMonitoredService;
|
||||
Post["/"] = series => UpdateAll();
|
||||
Post("/", series => UpdateAll());
|
||||
}
|
||||
|
||||
private Response UpdateAll()
|
||||
private object UpdateAll()
|
||||
{
|
||||
//Read from request
|
||||
var request = Request.Body.FromJson<SeasonPassResource>();
|
||||
|
@ -54,7 +54,7 @@ namespace Sonarr.Api.V3.SeasonPass
|
|||
_episodeMonitoredService.SetEpisodeMonitoredStatus(series, request.MonitoringOptions);
|
||||
}
|
||||
|
||||
return "ok".AsResponse(HttpStatusCode.Accepted);
|
||||
return ResponseWithCode("ok", HttpStatusCode.Accepted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,11 +19,11 @@ namespace Sonarr.Api.V3.Series
|
|||
{
|
||||
_seriesService = seriesService;
|
||||
_commandQueueManager = commandQueueManager;
|
||||
Put["/"] = series => SaveAll();
|
||||
Delete["/"] = series => DeleteSeries();
|
||||
Put("/", series => SaveAll());
|
||||
Delete("/", series => DeleteSeries());
|
||||
}
|
||||
|
||||
private Response SaveAll()
|
||||
private object SaveAll()
|
||||
{
|
||||
var resource = Request.Body.FromJson<SeriesEditorResource>();
|
||||
var seriesToUpdate = _seriesService.GetSeries(resource.SeriesIds);
|
||||
|
@ -95,12 +95,12 @@ namespace Sonarr.Api.V3.Series
|
|||
});
|
||||
}
|
||||
|
||||
return _seriesService.UpdateSeries(seriesToUpdate, !resource.MoveFiles)
|
||||
return ResponseWithCode(_seriesService.UpdateSeries(seriesToUpdate, !resource.MoveFiles)
|
||||
.ToResource()
|
||||
.AsResponse(HttpStatusCode.Accepted);
|
||||
, HttpStatusCode.Accepted);
|
||||
}
|
||||
|
||||
private Response DeleteSeries()
|
||||
private object DeleteSeries()
|
||||
{
|
||||
var resource = Request.Body.FromJson<SeriesEditorResource>();
|
||||
|
||||
|
@ -109,7 +109,7 @@ namespace Sonarr.Api.V3.Series
|
|||
_seriesService.DeleteSeries(seriesId, false);
|
||||
}
|
||||
|
||||
return new object().AsResponse();
|
||||
return new object();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,16 +14,16 @@ namespace Sonarr.Api.V3.Series
|
|||
: base("/series/import")
|
||||
{
|
||||
_addSeriesService = addSeriesService;
|
||||
Post["/"] = x => Import();
|
||||
Post("/", x => Import());
|
||||
}
|
||||
|
||||
|
||||
private Response Import()
|
||||
private object Import()
|
||||
{
|
||||
var resource = Request.Body.FromJson<List<SeriesResource>>();
|
||||
var newSeries = resource.ToModel();
|
||||
|
||||
return _addSeriesService.AddSeries(newSeries).ToResource().AsResponse();
|
||||
return _addSeriesService.AddSeries(newSeries).ToResource();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ using NzbDrone.Core.MetadataSource;
|
|||
using NzbDrone.Core.Organizer;
|
||||
using NzbDrone.Core.SeriesStats;
|
||||
using Sonarr.Http;
|
||||
using Sonarr.Http.Extensions;
|
||||
|
||||
namespace Sonarr.Api.V3.Series
|
||||
{
|
||||
|
@ -20,13 +19,13 @@ namespace Sonarr.Api.V3.Series
|
|||
{
|
||||
_searchProxy = searchProxy;
|
||||
_fileNameBuilder = fileNameBuilder;
|
||||
Get["/"] = x => Search();
|
||||
Get("/", x => Search());
|
||||
}
|
||||
|
||||
private Response Search()
|
||||
private object Search()
|
||||
{
|
||||
var tvDbResults = _searchProxy.SearchForNewSeries((string)Request.Query.term);
|
||||
return MapToResource(tvDbResults).AsResponse();
|
||||
return MapToResource(tvDbResults);
|
||||
}
|
||||
|
||||
private IEnumerable<SeriesResource> MapToResource(IEnumerable<NzbDrone.Core.Tv.Series> series)
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="FluentValidation" Version="8.4.0" />
|
||||
<PackageReference Include="Ical.Net" Version="2.2.32" />
|
||||
<PackageReference Include="Nancy" Version="1.4.4" />
|
||||
<PackageReference Include="Nancy.Authentication.Basic" Version="1.4.1" />
|
||||
<PackageReference Include="Nancy.Authentication.Forms" Version="1.4.1" />
|
||||
<PackageReference Include="Nancy" Version="2.0.0" />
|
||||
<PackageReference Include="Nancy.Authentication.Basic" Version="2.0.0" />
|
||||
<PackageReference Include="Nancy.Authentication.Forms" Version="2.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
||||
<PackageReference Include="NLog" Version="4.6.6" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
using Nancy;
|
||||
using Sonarr.Http;
|
||||
|
||||
namespace Sonarr.Api.V3
|
||||
{
|
||||
public abstract class SonarrV3FeedModule : NancyModule
|
||||
public abstract class SonarrV3FeedModule : SonarrModule
|
||||
{
|
||||
protected SonarrV3FeedModule(string resource)
|
||||
: base("/feed/v3/" + resource.Trim('/'))
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
using Nancy;
|
||||
using Sonarr.Http;
|
||||
|
||||
namespace Sonarr.Api.V3
|
||||
{
|
||||
public abstract class SonarrV3Module : NancyModule
|
||||
public abstract class SonarrV3Module : SonarrModule
|
||||
{
|
||||
protected SonarrV3Module(string resource)
|
||||
: base("/api/v3/" + resource.Trim('/'))
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Nancy;
|
||||
using NzbDrone.Common.Crypto;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Backup;
|
||||
using Sonarr.Http;
|
||||
using Sonarr.Http.Extensions;
|
||||
using Sonarr.Http.REST;
|
||||
|
||||
namespace Sonarr.Api.V3.System.Backup
|
||||
|
@ -32,8 +30,8 @@ namespace Sonarr.Api.V3.System.Backup
|
|||
GetResourceAll = GetBackupFiles;
|
||||
DeleteResource = DeleteBackup;
|
||||
|
||||
Post[@"/restore/(?<id>[\d]{1,10})"] = x => Restore((int)x.Id);
|
||||
Post["/restore/upload"] = x => UploadAndRestore();
|
||||
Post(@"/restore/(?<id>[\d]{1,10})", x => Restore((int)x.Id));
|
||||
Post("/restore/upload", x => UploadAndRestore());
|
||||
}
|
||||
|
||||
public List<BackupResource> GetBackupFiles()
|
||||
|
@ -65,7 +63,7 @@ namespace Sonarr.Api.V3.System.Backup
|
|||
_diskProvider.DeleteFile(path);
|
||||
}
|
||||
|
||||
public Response Restore(int id)
|
||||
public object Restore(int id)
|
||||
{
|
||||
var backup = GetBackup(id);
|
||||
|
||||
|
@ -81,10 +79,10 @@ namespace Sonarr.Api.V3.System.Backup
|
|||
return new
|
||||
{
|
||||
RestartRequired = true
|
||||
}.AsResponse();
|
||||
};
|
||||
}
|
||||
|
||||
public Response UploadAndRestore()
|
||||
public object UploadAndRestore()
|
||||
{
|
||||
var files = Context.Request.Files.ToList();
|
||||
|
||||
|
@ -112,7 +110,7 @@ namespace Sonarr.Api.V3.System.Backup
|
|||
return new
|
||||
{
|
||||
RestartRequired = true
|
||||
}.AsResponse();
|
||||
};
|
||||
}
|
||||
|
||||
private string GetBackupPath(NzbDrone.Core.Backup.Backup backup)
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
using System.Threading.Tasks;
|
||||
using Nancy;
|
||||
using Nancy.Routing;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Lifecycle;
|
||||
using Sonarr.Http.Extensions;
|
||||
|
||||
namespace Sonarr.Api.V3.System
|
||||
{
|
||||
|
@ -42,13 +40,13 @@ namespace Sonarr.Api.V3.System
|
|||
_database = database;
|
||||
_lifecycleService = lifecycleService;
|
||||
_deploymentInfoProvider = deploymentInfoProvider;
|
||||
Get["/status"] = x => GetStatus();
|
||||
Get["/routes"] = x => GetRoutes();
|
||||
Post["/shutdown"] = x => Shutdown();
|
||||
Post["/restart"] = x => Restart();
|
||||
Get("/status", x => GetStatus());
|
||||
Get("/routes", x => GetRoutes());
|
||||
Post("/shutdown", x => Shutdown());
|
||||
Post("/restart", x => Restart());
|
||||
}
|
||||
|
||||
private Response GetStatus()
|
||||
private object GetStatus()
|
||||
{
|
||||
return new
|
||||
{
|
||||
|
@ -78,24 +76,24 @@ namespace Sonarr.Api.V3.System
|
|||
PackageVersion = _deploymentInfoProvider.PackageVersion,
|
||||
PackageAuthor = _deploymentInfoProvider.PackageAuthor,
|
||||
PackageUpdateMechanism = _deploymentInfoProvider.PackageUpdateMechanism
|
||||
}.AsResponse();
|
||||
};
|
||||
}
|
||||
|
||||
private Response GetRoutes()
|
||||
private object GetRoutes()
|
||||
{
|
||||
return _routeCacheProvider.GetCache().Values.AsResponse();
|
||||
return _routeCacheProvider.GetCache().Values;
|
||||
}
|
||||
|
||||
private Response Shutdown()
|
||||
private object Shutdown()
|
||||
{
|
||||
Task.Factory.StartNew(() => _lifecycleService.Shutdown());
|
||||
return new { ShuttingDown = true }.AsResponse();
|
||||
return new { ShuttingDown = true };
|
||||
}
|
||||
|
||||
private Response Restart()
|
||||
private object Restart()
|
||||
{
|
||||
Task.Factory.StartNew(() => _lifecycleService.Restart());
|
||||
return new { Restarting = true }.AsResponse();
|
||||
return new { Restarting = true };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
using Nancy;
|
||||
using Nancy.Authentication.Basic;
|
||||
using Nancy.Authentication.Forms;
|
||||
using Nancy.Bootstrapper;
|
||||
using Nancy.Cryptography;
|
||||
using NzbDrone.Api.Extensions.Pipelines;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
||||
namespace NzbDrone.Api.Authentication
|
||||
{
|
||||
public class EnableAuthInNancy : IRegisterNancyPipeline
|
||||
{
|
||||
private readonly IAuthenticationService _authenticationService;
|
||||
private readonly IConfigService _configService;
|
||||
private readonly IConfigFileProvider _configFileProvider;
|
||||
|
||||
public EnableAuthInNancy(IAuthenticationService authenticationService,
|
||||
IConfigService configService,
|
||||
IConfigFileProvider configFileProvider)
|
||||
{
|
||||
_authenticationService = authenticationService;
|
||||
_configService = configService;
|
||||
_configFileProvider = configFileProvider;
|
||||
}
|
||||
|
||||
public void Register(IPipelines pipelines)
|
||||
{
|
||||
RegisterFormsAuth(pipelines);
|
||||
pipelines.EnableBasicAuthentication(new BasicAuthenticationConfiguration(_authenticationService, "Sonarr"));
|
||||
pipelines.BeforeRequest.AddItemToEndOfPipeline(RequiresAuthentication);
|
||||
}
|
||||
|
||||
private Response RequiresAuthentication(NancyContext context)
|
||||
{
|
||||
Response response = null;
|
||||
|
||||
if (!_authenticationService.IsAuthenticated(context))
|
||||
{
|
||||
response = new Response { StatusCode = HttpStatusCode.Unauthorized };
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private void RegisterFormsAuth(IPipelines pipelines)
|
||||
{
|
||||
var cryptographyConfiguration = new CryptographyConfiguration(
|
||||
new RijndaelEncryptionProvider(new PassphraseKeyGenerator(_configService.RijndaelPassphrase,
|
||||
new byte[] {1, 2, 3, 4, 5, 6, 7, 8})),
|
||||
new DefaultHmacProvider(new PassphraseKeyGenerator(_configService.HmacPassphrase,
|
||||
new byte[] {1, 2, 3, 4, 5, 6, 7, 8}))
|
||||
);
|
||||
|
||||
FormsAuthentication.Enable(pipelines, new FormsAuthenticationConfiguration
|
||||
{
|
||||
RedirectUrl = "~/login",
|
||||
UserMapper = _authenticationService,
|
||||
CryptographyConfiguration = cryptographyConfiguration
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,9 +3,6 @@ using Nancy;
|
|||
using Nancy.Authentication.Forms;
|
||||
using Nancy.Extensions;
|
||||
using Nancy.ModelBinding;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Instrumentation;
|
||||
using NzbDrone.Core.Authentication;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
||||
namespace Sonarr.Http.Authentication
|
||||
|
@ -19,8 +16,8 @@ namespace Sonarr.Http.Authentication
|
|||
{
|
||||
_authService = authService;
|
||||
_configFileProvider = configFileProvider;
|
||||
Post["/login"] = x => Login(this.Bind<LoginResource>());
|
||||
Get["/logout"] = x => Logout();
|
||||
Post("/login", x => Login(this.Bind<LoginResource>()));
|
||||
Get("/logout", x => Logout());
|
||||
}
|
||||
|
||||
private Response Login(LoginResource resource)
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Principal;
|
||||
using Nancy;
|
||||
using Nancy.Authentication.Basic;
|
||||
using Nancy.Authentication.Forms;
|
||||
using Nancy.Security;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Instrumentation;
|
||||
using NzbDrone.Core.Authentication;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using Sonarr.Http.Extensions;
|
||||
|
@ -26,7 +26,7 @@ namespace Sonarr.Http.Authentication
|
|||
public class AuthenticationService : IAuthenticationService
|
||||
{
|
||||
private static readonly Logger _authLogger = LogManager.GetLogger("Auth");
|
||||
private static readonly NzbDroneUser AnonymousUser = new NzbDroneUser { UserName = "Anonymous" };
|
||||
private const string AnonymousUser = "Anonymous";
|
||||
private readonly IUserService _userService;
|
||||
private readonly NancyContext _nancyContext;
|
||||
|
||||
|
@ -80,15 +80,15 @@ namespace Sonarr.Http.Authentication
|
|||
|
||||
if (context.CurrentUser != null)
|
||||
{
|
||||
LogLogout(context, context.CurrentUser.UserName);
|
||||
LogLogout(context, context.CurrentUser.Identity.Name);
|
||||
}
|
||||
}
|
||||
|
||||
public IUserIdentity Validate(string username, string password)
|
||||
public ClaimsPrincipal Validate(string username, string password)
|
||||
{
|
||||
if (AUTH_METHOD == AuthenticationType.None)
|
||||
{
|
||||
return AnonymousUser;
|
||||
return new ClaimsPrincipal(new GenericIdentity(AnonymousUser));
|
||||
}
|
||||
|
||||
var user = _userService.FindUser(username, password);
|
||||
|
@ -101,7 +101,7 @@ namespace Sonarr.Http.Authentication
|
|||
LogSuccess(_context, username);
|
||||
}
|
||||
|
||||
return new NzbDroneUser { UserName = user.Username };
|
||||
return new ClaimsPrincipal(new GenericIdentity(user.Username));
|
||||
}
|
||||
|
||||
LogFailure(_context, username);
|
||||
|
@ -109,18 +109,18 @@ namespace Sonarr.Http.Authentication
|
|||
return null;
|
||||
}
|
||||
|
||||
public IUserIdentity GetUserFromIdentifier(Guid identifier, NancyContext context)
|
||||
public ClaimsPrincipal GetUserFromIdentifier(Guid identifier, NancyContext context)
|
||||
{
|
||||
if (AUTH_METHOD == AuthenticationType.None)
|
||||
{
|
||||
return AnonymousUser;
|
||||
return new ClaimsPrincipal(new GenericIdentity(AnonymousUser));
|
||||
}
|
||||
|
||||
var user = _userService.FindUser(identifier);
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
return new NzbDroneUser { UserName = user.Username };
|
||||
return new ClaimsPrincipal(new GenericIdentity(user.Username));
|
||||
}
|
||||
|
||||
LogInvalidated(_context);
|
||||
|
|
|
@ -76,7 +76,7 @@ namespace Sonarr.Http.Authentication
|
|||
FormsAuthentication.FormsAuthenticationCookieName = "SonarrAuth";
|
||||
|
||||
var cryptographyConfiguration = new CryptographyConfiguration(
|
||||
new RijndaelEncryptionProvider(new PassphraseKeyGenerator(_configService.RijndaelPassphrase, Encoding.ASCII.GetBytes(_configService.RijndaelSalt))),
|
||||
new AesEncryptionProvider(new PassphraseKeyGenerator(_configService.RijndaelPassphrase, Encoding.ASCII.GetBytes(_configService.RijndaelSalt))),
|
||||
new DefaultHmacProvider(new PassphraseKeyGenerator(_configService.HmacPassphrase, Encoding.ASCII.GetBytes(_configService.HmacSalt)))
|
||||
);
|
||||
|
||||
|
@ -99,7 +99,7 @@ namespace Sonarr.Http.Authentication
|
|||
context.Response.Headers["Location"].StartsWith($"{_configFileProvider.UrlBase}/login", StringComparison.InvariantCultureIgnoreCase)) ||
|
||||
context.Response.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
context.Response = new { Error = "Unauthorized" }.AsResponse(HttpStatusCode.Unauthorized);
|
||||
context.Response = new { Error = "Unauthorized" }.AsResponse(context, HttpStatusCode.Unauthorized);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using Nancy.Security;
|
||||
|
||||
namespace Sonarr.Http.Authentication
|
||||
{
|
||||
public class NzbDroneUser : IUserIdentity
|
||||
{
|
||||
public string UserName { get; set; }
|
||||
|
||||
public IEnumerable<string> Claims { get; set; }
|
||||
}
|
||||
}
|
|
@ -14,7 +14,9 @@ namespace Sonarr.Http.ErrorManagement
|
|||
public void Handle(HttpStatusCode statusCode, NancyContext context)
|
||||
{
|
||||
if (statusCode == HttpStatusCode.SeeOther || statusCode == HttpStatusCode.OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (statusCode == HttpStatusCode.Continue)
|
||||
{
|
||||
|
@ -23,13 +25,17 @@ namespace Sonarr.Http.ErrorManagement
|
|||
}
|
||||
|
||||
if (statusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (context.Response.ContentType == "text/html" || context.Response.ContentType == "text/plain")
|
||||
{
|
||||
context.Response = new ErrorModel
|
||||
{
|
||||
Message = statusCode.ToString()
|
||||
}.AsResponse(statusCode);
|
||||
{
|
||||
Message = statusCode.ToString()
|
||||
}.AsResponse(context, statusCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,14 +27,14 @@ namespace Sonarr.Http.ErrorManagement
|
|||
if (exception is ApiException apiException)
|
||||
{
|
||||
_logger.Warn(apiException, "API Error");
|
||||
return apiException.ToErrorResponse();
|
||||
return apiException.ToErrorResponse(context);
|
||||
}
|
||||
|
||||
if (exception is ValidationException validationException)
|
||||
{
|
||||
_logger.Warn("Invalid request {0}", validationException.Message);
|
||||
|
||||
return validationException.Errors.AsResponse(HttpStatusCode.BadRequest);
|
||||
return validationException.Errors.AsResponse(context, HttpStatusCode.BadRequest);
|
||||
}
|
||||
|
||||
if (exception is NzbDroneClientException clientException)
|
||||
|
@ -43,7 +43,7 @@ namespace Sonarr.Http.ErrorManagement
|
|||
{
|
||||
Message = exception.Message,
|
||||
Description = exception.ToString()
|
||||
}.AsResponse((HttpStatusCode)clientException.StatusCode);
|
||||
}.AsResponse(context, (HttpStatusCode)clientException.StatusCode);
|
||||
}
|
||||
|
||||
if (exception is ModelNotFoundException notFoundException)
|
||||
|
@ -52,7 +52,7 @@ namespace Sonarr.Http.ErrorManagement
|
|||
{
|
||||
Message = exception.Message,
|
||||
Description = exception.ToString()
|
||||
}.AsResponse(HttpStatusCode.NotFound);
|
||||
}.AsResponse(context, HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
if (exception is ModelConflictException conflictException)
|
||||
|
@ -61,7 +61,7 @@ namespace Sonarr.Http.ErrorManagement
|
|||
{
|
||||
Message = exception.Message,
|
||||
Description = exception.ToString()
|
||||
}.AsResponse(HttpStatusCode.Conflict);
|
||||
}.AsResponse(context, HttpStatusCode.Conflict);
|
||||
}
|
||||
|
||||
if (exception is SQLiteException sqLiteException)
|
||||
|
@ -72,7 +72,7 @@ namespace Sonarr.Http.ErrorManagement
|
|||
return new ErrorModel
|
||||
{
|
||||
Message = exception.Message,
|
||||
}.AsResponse(HttpStatusCode.Conflict);
|
||||
}.AsResponse(context, HttpStatusCode.Conflict);
|
||||
}
|
||||
|
||||
_logger.Error(sqLiteException, "[{0} {1}]", context.Request.Method, context.Request.Path);
|
||||
|
@ -84,7 +84,7 @@ namespace Sonarr.Http.ErrorManagement
|
|||
{
|
||||
Message = exception.Message,
|
||||
Description = exception.ToString()
|
||||
}.AsResponse(HttpStatusCode.InternalServerError);
|
||||
}.AsResponse(context, HttpStatusCode.InternalServerError);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,9 +19,9 @@ namespace Sonarr.Http.Exceptions
|
|||
Content = content;
|
||||
}
|
||||
|
||||
public JsonResponse<ErrorModel> ToErrorResponse()
|
||||
public JsonResponse<ErrorModel> ToErrorResponse(NancyContext context)
|
||||
{
|
||||
return new ErrorModel(this).AsResponse(StatusCode);
|
||||
return new ErrorModel(this).AsResponse(context, StatusCode);
|
||||
}
|
||||
|
||||
private static string GetMessage(HttpStatusCode statusCode, object content)
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Nancy;
|
||||
using Nancy.Responses.Negotiation;
|
||||
using NzbDrone.Common.Serializer;
|
||||
|
||||
namespace Sonarr.Http.Extensions
|
||||
{
|
||||
public class NancyJsonSerializer : ISerializer
|
||||
{
|
||||
public bool CanSerialize(string contentType)
|
||||
public bool CanSerialize(MediaRange contentType)
|
||||
{
|
||||
return true;
|
||||
return contentType == "application/json";
|
||||
}
|
||||
|
||||
public void Serialize<TModel>(string contentType, TModel model, Stream outputStream)
|
||||
public void Serialize<TModel>(MediaRange contentType, TModel model, Stream outputStream)
|
||||
{
|
||||
Json.Serialize(model, outputStream);
|
||||
}
|
||||
|
|
|
@ -32,9 +32,9 @@ namespace Sonarr.Http.Extensions
|
|||
return Json.Deserialize(value, type);
|
||||
}
|
||||
|
||||
public static JsonResponse<TModel> AsResponse<TModel>(this TModel model, HttpStatusCode statusCode = HttpStatusCode.OK)
|
||||
public static JsonResponse<TModel> AsResponse<TModel>(this TModel model, NancyContext context, HttpStatusCode statusCode = HttpStatusCode.OK)
|
||||
{
|
||||
var response = new JsonResponse<TModel>(model, NancySerializer) { StatusCode = statusCode };
|
||||
var response = new JsonResponse<TModel>(model, NancySerializer, context.Environment) { StatusCode = statusCode };
|
||||
response.Headers.DisableCache();
|
||||
|
||||
return response;
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace Sonarr.Http.Frontend
|
|||
_apiKey = configFileProvider.ApiKey;
|
||||
_urlBase = configFileProvider.UrlBase;
|
||||
|
||||
Get["/initialize.js"] = x => Index();
|
||||
Get("/initialize.js", x => Index());
|
||||
}
|
||||
|
||||
private Response Index()
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Nancy;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
|
|
|
@ -18,8 +18,8 @@ namespace Sonarr.Http.Frontend
|
|||
_requestMappers = requestMappers;
|
||||
_logger = logger;
|
||||
|
||||
Get["/{resource*}"] = x => Index();
|
||||
Get["/"] = x => Index();
|
||||
Get("/{resource*}", x => Index());
|
||||
Get("/", x => Index());
|
||||
}
|
||||
|
||||
private Response Index()
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using FluentValidation;
|
||||
using Nancy;
|
||||
using Nancy.Responses.Negotiation;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using Sonarr.Http.Extensions;
|
||||
|
@ -72,13 +73,13 @@ namespace Sonarr.Http.REST
|
|||
set
|
||||
{
|
||||
_deleteResource = value;
|
||||
Delete[ID_ROUTE] = options =>
|
||||
Delete(ID_ROUTE, options =>
|
||||
{
|
||||
ValidateId(options.Id);
|
||||
DeleteResource((int)options.Id);
|
||||
|
||||
return new object().AsResponse();
|
||||
};
|
||||
return new object();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,7 +89,7 @@ namespace Sonarr.Http.REST
|
|||
set
|
||||
{
|
||||
_getResourceById = value;
|
||||
Get[ID_ROUTE] = options =>
|
||||
Get(ID_ROUTE, options =>
|
||||
{
|
||||
ValidateId(options.Id);
|
||||
try
|
||||
|
@ -100,13 +101,13 @@ namespace Sonarr.Http.REST
|
|||
return new NotFoundResponse();
|
||||
}
|
||||
|
||||
return resource.AsResponse();
|
||||
return resource;
|
||||
}
|
||||
catch (ModelNotFoundException)
|
||||
{
|
||||
return new NotFoundResponse();
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,11 +118,11 @@ namespace Sonarr.Http.REST
|
|||
{
|
||||
_getResourceAll = value;
|
||||
|
||||
Get[ROOT_ROUTE] = options =>
|
||||
Get(ROOT_ROUTE, options =>
|
||||
{
|
||||
var resource = GetResourceAll();
|
||||
return resource.AsResponse();
|
||||
};
|
||||
return resource;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,11 +133,11 @@ namespace Sonarr.Http.REST
|
|||
{
|
||||
_getResourcePaged = value;
|
||||
|
||||
Get[ROOT_ROUTE] = options =>
|
||||
Get(ROOT_ROUTE, options =>
|
||||
{
|
||||
var resource = GetResourcePaged(ReadPagingResourceFromRequest());
|
||||
return resource.AsResponse();
|
||||
};
|
||||
return resource;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,11 +148,11 @@ namespace Sonarr.Http.REST
|
|||
{
|
||||
_getResourceSingle = value;
|
||||
|
||||
Get[ROOT_ROUTE] = options =>
|
||||
Get(ROOT_ROUTE, options =>
|
||||
{
|
||||
var resource = GetResourceSingle();
|
||||
return resource.AsResponse();
|
||||
};
|
||||
return resource;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,12 +162,11 @@ namespace Sonarr.Http.REST
|
|||
set
|
||||
{
|
||||
_createResource = value;
|
||||
Post[ROOT_ROUTE] = options =>
|
||||
Post(ROOT_ROUTE, options =>
|
||||
{
|
||||
var id = CreateResource(ReadResourceFromRequest());
|
||||
return GetResourceById(id).AsResponse(HttpStatusCode.Created);
|
||||
};
|
||||
|
||||
return ResponseWithCode(GetResourceById(id), HttpStatusCode.Created);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,23 +176,28 @@ namespace Sonarr.Http.REST
|
|||
set
|
||||
{
|
||||
_updateResource = value;
|
||||
Put[ROOT_ROUTE] = options =>
|
||||
Put(ROOT_ROUTE, options =>
|
||||
{
|
||||
var resource = ReadResourceFromRequest();
|
||||
UpdateResource(resource);
|
||||
return GetResourceById(resource.Id).AsResponse(HttpStatusCode.Accepted);
|
||||
};
|
||||
return ResponseWithCode(GetResourceById(resource.Id), HttpStatusCode.Accepted);
|
||||
});
|
||||
|
||||
Put[ID_ROUTE] = options =>
|
||||
Put(ID_ROUTE, options =>
|
||||
{
|
||||
var resource = ReadResourceFromRequest();
|
||||
resource.Id = options.Id;
|
||||
UpdateResource(resource);
|
||||
return GetResourceById(resource.Id).AsResponse(HttpStatusCode.Accepted);
|
||||
};
|
||||
return ResponseWithCode(GetResourceById(resource.Id), HttpStatusCode.Accepted);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected Negotiator ResponseWithCode(object model, HttpStatusCode statusCode)
|
||||
{
|
||||
return Negotiate.WithModel(model).WithStatusCode(statusCode);
|
||||
}
|
||||
|
||||
protected TResource ReadResourceFromRequest(bool skipValidate = false)
|
||||
{
|
||||
TResource resource;
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentValidation" Version="8.4.0" />
|
||||
<PackageReference Include="Nancy" Version="1.4.4" />
|
||||
<PackageReference Include="Nancy.Authentication.Basic" Version="1.4.1" />
|
||||
<PackageReference Include="Nancy.Authentication.Forms" Version="1.4.1" />
|
||||
<PackageReference Include="Nancy" Version="2.0.0" />
|
||||
<PackageReference Include="Nancy.Authentication.Basic" Version="2.0.0" />
|
||||
<PackageReference Include="Nancy.Authentication.Forms" Version="2.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
||||
<PackageReference Include="NLog" Version="4.6.6" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
using System.Linq;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Nancy;
|
||||
using Nancy.Bootstrapper;
|
||||
using Nancy.Diagnostics;
|
||||
using Nancy.Responses.Negotiation;
|
||||
using NLog;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Instrumentation;
|
||||
using NzbDrone.Core.Instrumentation;
|
||||
using NzbDrone.Core.Lifecycle;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using Sonarr.Http.Extensions.Pipelines;
|
||||
using TinyIoC;
|
||||
|
||||
|
@ -51,7 +52,19 @@ namespace Sonarr.Http
|
|||
return _tinyIoCContainer;
|
||||
}
|
||||
|
||||
protected override DiagnosticsConfiguration DiagnosticsConfiguration => new DiagnosticsConfiguration { Password = @"password" };
|
||||
protected override Func<ITypeCatalog, NancyInternalConfiguration> InternalConfiguration
|
||||
{
|
||||
get
|
||||
{
|
||||
// We don't support Xml Serialization atm
|
||||
return NancyInternalConfiguration.WithOverrides(x => x.ResponseProcessors.Remove(typeof(XmlProcessor)));
|
||||
}
|
||||
}
|
||||
|
||||
public override void Configure(Nancy.Configuration.INancyEnvironment environment)
|
||||
{
|
||||
environment.Diagnostics(password: @"password");
|
||||
}
|
||||
|
||||
protected override byte[] FavIcon => null;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
using Nancy;
|
||||
using Nancy.Responses.Negotiation;
|
||||
|
||||
namespace Sonarr.Http
|
||||
{
|
||||
public abstract class SonarrModule : NancyModule
|
||||
{
|
||||
protected SonarrModule(string resource)
|
||||
: base(resource)
|
||||
{
|
||||
}
|
||||
|
||||
protected Negotiator ResponseWithCode(object model, HttpStatusCode statusCode)
|
||||
{
|
||||
return Negotiate.WithModel(model).WithStatusCode(statusCode);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ using System.Reflection;
|
|||
using Nancy;
|
||||
using Nancy.Diagnostics;
|
||||
using Nancy.Bootstrapper;
|
||||
using Nancy.Configuration;
|
||||
|
||||
namespace Sonarr.Http
|
||||
{
|
||||
|
@ -52,6 +53,47 @@ namespace Sonarr.Http
|
|||
return this.ApplicationContainer.Resolve<INancyEngine>();
|
||||
}
|
||||
|
||||
//
|
||||
// Summary:
|
||||
// Gets the Nancy.Configuration.INancyEnvironmentConfigurator used by th.
|
||||
//
|
||||
// Returns:
|
||||
// An Nancy.Configuration.INancyEnvironmentConfigurator instance.
|
||||
protected override INancyEnvironmentConfigurator GetEnvironmentConfigurator()
|
||||
{
|
||||
return this.ApplicationContainer.Resolve<INancyEnvironmentConfigurator>();
|
||||
}
|
||||
|
||||
//
|
||||
// Summary:
|
||||
// Get the Nancy.Configuration.INancyEnvironment instance.
|
||||
//
|
||||
// Returns:
|
||||
// An configured Nancy.Configuration.INancyEnvironment instance.
|
||||
//
|
||||
// Remarks:
|
||||
// The boostrapper must be initialised (Nancy.Bootstrapper.INancyBootstrapper.Initialise)
|
||||
// prior to calling this.
|
||||
public override INancyEnvironment GetEnvironment()
|
||||
{
|
||||
return this.ApplicationContainer.Resolve<INancyEnvironment>();
|
||||
}
|
||||
|
||||
//
|
||||
// Summary:
|
||||
// Registers an Nancy.Configuration.INancyEnvironment instance in the container.
|
||||
//
|
||||
// Parameters:
|
||||
// container:
|
||||
// The container to register into.
|
||||
//
|
||||
// environment:
|
||||
// The Nancy.Configuration.INancyEnvironment instance to register.
|
||||
protected override void RegisterNancyEnvironment(TinyIoCContainer container, INancyEnvironment environment)
|
||||
{
|
||||
ApplicationContainer.Register<INancyEnvironment>(environment);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a default, unconfigured, container
|
||||
/// </summary>
|
||||
|
|
Loading…
Reference in New Issue