Refactor controllers for ASP.NET Core (Authentication disabled for now)

This commit is contained in:
flightlevel 2018-05-01 22:55:09 +10:00
parent a752683965
commit f162902b36
7 changed files with 261 additions and 283 deletions

View File

@ -1,39 +1,37 @@
using Newtonsoft.Json.Linq;
using Jackett.Common.Models.Config;
using Jackett.Common.Services.Interfaces;
using Jackett.Common.Utils;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
using NLog;
using System;
using System.IO;
using System.Text;
using System.Net;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using Jackett.Common.Models.Config;
using Jackett.Common.Services.Interfaces;
using Jackett.Common.Utils;
namespace Jackett.Controllers
namespace Jackett.Server.Controllers
{
[AllowAnonymous]
[JackettAPINoCache]
public class BlackholeController : ApiController
//[AllowAnonymous]
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
[Route("bh/{indexerID}")]
public class BlackholeController : Controller
{
private Logger logger;
private IIndexerManagerService indexerService;
private readonly ServerConfig serverConfig;
IProtectionService protectionService;
private IProtectionService protectionService;
public BlackholeController(IIndexerManagerService i, Logger l, ServerConfig config, IProtectionService ps)
{
logger = l;
indexerService = i;
serverConfig = config;
protectionService = ps;
}
[HttpGet]
public async Task<IHttpActionResult> Blackhole(string indexerID, string path, string jackett_apikey, string file)
public async Task<IActionResult> Blackhole(string indexerID, string path, string jackett_apikey, string file)
{
var jsonReply = new JObject();
try
{
@ -47,7 +45,7 @@ namespace Jackett.Controllers
if (serverConfig.APIKey != jackett_apikey)
throw new Exception("Incorrect API key");
path = Encoding.UTF8.GetString(HttpServerUtility.UrlTokenDecode(path));
path = WebUtility.UrlDecode(path);
path = protectionService.UnProtect(path);
var remoteFile = new Uri(path, UriKind.RelativeOrAbsolute);
var fileExtension = ".torrent";
@ -81,9 +79,9 @@ namespace Jackett.Controllers
if (string.IsNullOrWhiteSpace(file))
fileName += fileExtension;
else
fileName += "-"+StringUtil.MakeValidFileName(file + fileExtension, '_', false); // call MakeValidFileName() again to avoid any possibility of path traversal attacks
fileName += "-" + StringUtil.MakeValidFileName(file + fileExtension, '_', false); // call MakeValidFileName() again to avoid any possibility of path traversal attacks
File.WriteAllBytes(Path.Combine(serverConfig.BlackholeDir, fileName), downloadBytes);
System.IO.File.WriteAllBytes(Path.Combine(serverConfig.BlackholeDir, fileName), downloadBytes);
jsonReply["result"] = "success";
}
catch (Exception ex)

View File

@ -1,26 +1,24 @@
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using BencodeNET.Parsing;
using BencodeNET.Parsing;
using Jackett.Common.Models.Config;
using Jackett.Common.Services.Interfaces;
using Jackett.Common.Utils;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.WebUtilities;
using NLog;
using System;
using System.Text;
using System.Threading.Tasks;
namespace Jackett.Controllers
namespace Jackett.Server.Controllers
{
[AllowAnonymous]
[JackettAPINoCache]
public class DownloadController : ApiController
//[AllowAnonymous]
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
[Route("dl/{indexerID}")]
public class DownloadController : Controller
{
private ServerConfig config;
private Logger logger;
private IIndexerManagerService indexerService;
private IIndexerManagerService indexerService;
private IProtectionService protectionService;
public DownloadController(IIndexerManagerService i, Logger l, IProtectionService ps, ServerConfig serverConfig)
@ -32,7 +30,7 @@ namespace Jackett.Controllers
}
[HttpGet]
public async Task<HttpResponseMessage> Download(string indexerID, string path, string jackett_apikey, string file)
public async Task<IActionResult> Download(string indexerID, string path, string jackett_apikey, string file)
{
try
{
@ -41,14 +39,14 @@ namespace Jackett.Controllers
if (!indexer.IsConfigured)
{
logger.Warn(string.Format("Rejected a request to {0} which is unconfigured.", indexer.DisplayName));
return Request.CreateResponse(HttpStatusCode.Forbidden, "This indexer is not configured.");
return Forbid("This indexer is not configured.");
}
path = Encoding.UTF8.GetString(HttpServerUtility.UrlTokenDecode(path));
path = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(path));
path = protectionService.UnProtect(path);
if (config.APIKey != jackett_apikey)
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
return Unauthorized();
var target = new Uri(path, UriKind.RelativeOrAbsolute);
var downloadBytes = await indexer.Download(target);
@ -65,9 +63,7 @@ namespace Jackett.Controllers
)
{
var magneturi = Encoding.UTF8.GetString(downloadBytes);
var response = Request.CreateResponse(HttpStatusCode.Moved);
response.Headers.Location = new Uri(magneturi);
return response;
return Redirect(new Uri(magneturi).ToString());
}
// This will fix torrents where the keys are not sorted, and thereby not supported by Sonarr.
@ -75,19 +71,14 @@ namespace Jackett.Controllers
var torrentDictionary = parser.Parse(downloadBytes);
byte[] sortedDownloadBytes = torrentDictionary.EncodeAsBytes();
var result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new ByteArrayContent(sortedDownloadBytes);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-bittorrent");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = StringUtil.MakeValidFileName(file, '_', false) + ".torrent" // call MakeValidFileName again to avoid any kind of injection attack
};
return result;
string fileName = StringUtil.MakeValidFileName(file, '_', false) + ".torrent"; // call MakeValidFileName again to avoid any kind of injection attack
return File(sortedDownloadBytes, "application/x-bittorrent", fileName);
}
catch (Exception e)
{
logger.Error(e, "Error downloading " + indexerID + " " + path);
return new HttpResponseMessage(HttpStatusCode.NotFound);
return NotFound();
}
}
}

View File

@ -1,21 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using Jackett.Common;
using Jackett.Common.Indexers;
using Jackett.Common.Indexers;
using Jackett.Common.Models;
using Jackett.Common.Services.Interfaces;
using Jackett.Common.Utils;
using Jackett.Utils;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NLog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Jackett.Controllers
namespace Jackett.Server.Controllers
{
public interface IIndexerController
{
@ -23,19 +20,17 @@ namespace Jackett.Controllers
IIndexer CurrentIndexer { get; set; }
}
public class RequiresIndexerAttribute : ActionFilterAttribute
public class RequiresIndexer : IActionFilter
{
public override void OnActionExecuting(HttpActionContext actionContext)
public void OnActionExecuting(ActionExecutingContext context)
{
base.OnActionExecuting(actionContext);
var controller = actionContext.ControllerContext.Controller;
var controller = context.Controller;
if (!(controller is IIndexerController))
return;
var indexerController = controller as IIndexerController;
var parameters = actionContext.RequestContext.RouteData.Values;
var parameters = context.RouteData.Values;
if (!parameters.ContainsKey("indexerId"))
{
@ -51,15 +46,23 @@ namespace Jackett.Controllers
var indexer = indexerService.GetIndexer(indexerId);
indexerController.CurrentIndexer = indexer;
}
public void OnActionExecuted(ActionExecutedContext context)
{
// do something after the action executes
}
}
[RoutePrefix("api/v2.0/indexers")]
[JackettAuthorized]
[JackettAPINoCache]
public class IndexerApiController : ApiController, IIndexerController
[Route("api/v2.0/indexers")]
//[JackettAuthorized]
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
public class IndexerApiController : Controller, IIndexerController
{
public IIndexerManagerService IndexerService { get; private set; }
public IIndexer CurrentIndexer { get; set; }
private Logger logger;
private IServerService serverService;
private ICacheService cacheService;
public IndexerApiController(IIndexerManagerService indexerManagerService, IServerService ss, ICacheService c, Logger logger)
{
@ -70,16 +73,17 @@ namespace Jackett.Controllers
}
[HttpGet]
[RequiresIndexer]
public async Task<IHttpActionResult> Config()
[TypeFilter(typeof(RequiresIndexer))]
[Route("{indexerId?}/Config")]
public async Task<IActionResult> Config()
{
var config = await CurrentIndexer.GetConfigurationForSetup();
return Ok(config.ToJson(null));
}
[HttpPost]
[ActionName("Config")]
[RequiresIndexer]
[Route("{indexerId?}/Config")]
[TypeFilter(typeof(RequiresIndexer))]
public async Task UpdateConfig([FromBody]Common.Models.DTO.ConfigItem[] config)
{
try
@ -111,14 +115,16 @@ namespace Jackett.Controllers
}
[HttpPost]
[RequiresIndexer]
public async Task Test()
[Route("{indexerid}/[action]")]
[TypeFilter(typeof(RequiresIndexer))]
public async Task<IActionResult> Test()
{
JToken jsonReply = new JObject();
try
{
await IndexerService.TestIndexer(CurrentIndexer.ID);
CurrentIndexer.LastError = null;
return NoContent();
}
catch (Exception ex)
{
@ -134,8 +140,8 @@ namespace Jackett.Controllers
}
[HttpDelete]
[RequiresIndexer]
[Route("{indexerId}")]
[TypeFilter(typeof(RequiresIndexer))]
[Route("{indexerid}")]
public void Delete()
{
IndexerService.DeleteIndexer(CurrentIndexer.ID);
@ -160,14 +166,10 @@ namespace Jackett.Controllers
var link = result.Link;
var file = StringUtil.MakeValidFileName(result.Title, '_', false);
result.Link = serverService.ConvertToProxyLink(link, serverUrl, result.TrackerId, "dl", file);
if (result.Link != null && result.Link.Scheme != "magnet" && !string.IsNullOrWhiteSpace(Engine.ServerConfig.BlackholeDir))
if (result.Link != null && result.Link.Scheme != "magnet" && !string.IsNullOrWhiteSpace(serverService.GetBlackholeDirectory()))
result.BlackholeLink = serverService.ConvertToProxyLink(link, serverUrl, result.TrackerId, "bh", file);
}
}
private Logger logger;
private IServerService serverService;
private ICacheService cacheService;
}
}

View File

@ -1,59 +1,73 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using System.Xml.Linq;
using Jackett.Common;
using Jackett.Common;
using Jackett.Common.Indexers;
using Jackett.Common.Indexers.Meta;
using Jackett.Common.Models;
using Jackett.Common.Models.DTO;
using Jackett.Common.Services.Interfaces;
using Jackett.Common.Utils;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using NLog;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Jackett.Controllers
namespace Jackett.Server.Controllers
{
public class RequiresApiKeyAttribute : AuthorizationFilterAttribute
public class RequiresApiKey : IActionFilter
{
public override void OnAuthorization(HttpActionContext actionContext)
public IServerService serverService;
public RequiresApiKey(IServerService ss)
{
var validApiKey = Engine.ServerConfig.APIKey;
var queryParams = actionContext.Request.GetQueryNameValuePairs();
serverService = ss;
}
public void OnActionExecuting(ActionExecutingContext context)
{
var validApiKey = serverService.GetApiKey();
var queryParams = context.HttpContext.Request.Query;
var queryApiKey = queryParams.Where(x => x.Key == "apikey" || x.Key == "passkey").Select(x => x.Value).FirstOrDefault();
#if DEBUG
if (Debugger.IsAttached)
{
return;
}
#endif
if (queryApiKey != validApiKey)
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
{
context.Result = new UnauthorizedResult();
return;
}
}
public void OnActionExecuted(ActionExecutedContext context)
{
// do something after the action executes
}
}
public class RequiresConfiguredIndexerAttribute : ActionFilterAttribute
public class RequiresConfiguredIndexer : IActionFilter
{
public override void OnActionExecuting(HttpActionContext actionContext)
public void OnActionExecuting(ActionExecutingContext context)
{
var controller = actionContext.ControllerContext.Controller;
var controller = context.Controller;
if (!(controller is IIndexerController))
return;
var indexerController = controller as IIndexerController;
var parameters = actionContext.RequestContext.RouteData.Values;
var parameters = context.RouteData.Values;
if (!parameters.ContainsKey("indexerId"))
{
indexerController.CurrentIndexer = null;
actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Invalid parameter");
context.Result = new UnauthorizedResult();
return;
}
@ -61,7 +75,7 @@ namespace Jackett.Controllers
if (indexerId.IsNullOrEmptyOrWhitespace())
{
indexerController.CurrentIndexer = null;
actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Invalid parameter");
context.Result = new UnauthorizedResult();
return;
}
@ -71,63 +85,68 @@ namespace Jackett.Controllers
if (indexer == null)
{
indexerController.CurrentIndexer = null;
actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Invalid parameter");
context.Result = new UnauthorizedResult();
return;
}
if (!indexer.IsConfigured)
{
indexerController.CurrentIndexer = null;
actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Indexer is not configured");
context.Result = new UnauthorizedResult();
return;
}
indexerController.CurrentIndexer = indexer;
}
public void OnActionExecuted(ActionExecutedContext context)
{
// do something after the action executes
}
}
public class RequiresValidQueryAttribute : RequiresConfiguredIndexerAttribute
public class RequiresValidQuery : IActionFilter
{
public override void OnActionExecuting(HttpActionContext actionContext)
public void OnActionExecuting(ActionExecutingContext context)
{
base.OnActionExecuting(actionContext);
if (actionContext.Response != null)
return;
//TODO: Not sure what this is meant to do
//if (context.HttpContext.Response != null)
// return;
var controller = actionContext.ControllerContext.Controller;
var controller = context.Controller;
if (!(controller is IResultController))
{
return;
}
var resultController = controller as IResultController;
var query = actionContext.ActionArguments.First().Value;
var query = context.ActionArguments.First().Value;
var queryType = query.GetType();
var converter = queryType.GetMethod("ToTorznabQuery", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
if (converter == null)
actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, "");
{
context.Result = new BadRequestResult();
}
var converted = converter.Invoke(null, new object[] { query });
var torznabQuery = converted as TorznabQuery;
resultController.CurrentQuery = torznabQuery;
if (queryType == typeof(ApiSearch)) // Skip CanHandleQuery() check for manual search (CurrentIndexer isn't used during manul search)
{
return;
}
if (!resultController.CurrentIndexer.CanHandleQuery(resultController.CurrentQuery))
actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, $"{resultController.CurrentIndexer.ID} does not support the requested query. Please check the capabilities (t=caps) and make sure the search mode and categories are supported.");
{
context.Result = new BadRequestObjectResult($"{resultController.CurrentIndexer.ID} does not support the requested query. Please check the capabilities (t=caps) and make sure the search mode and categories are supported.");
}
}
}
public class JsonResponseAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
public void OnActionExecuted(ActionExecutedContext context)
{
base.OnActionExecuted(actionExecutedContext);
if (actionExecutedContext.Exception != null)
throw new Exception("Error while executing request", actionExecutedContext.Exception);
var content = actionExecutedContext.Response.Content as ObjectContent;
actionExecutedContext.Response.Content = new JsonContent(content.Value);
// do something after the action executes
}
}
@ -136,12 +155,13 @@ namespace Jackett.Controllers
TorznabQuery CurrentQuery { get; set; }
}
[AllowAnonymous]
[JackettAPINoCache]
[RoutePrefix("api/v2.0/indexers")]
[RequiresApiKey]
[RequiresValidQuery]
public class ResultsController : ApiController, IResultController
//[AllowAnonymous]
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
[Route("api/v2.0/indexers/{indexerId}/results")]
[TypeFilter(typeof(RequiresApiKey))]
[TypeFilter(typeof(RequiresConfiguredIndexer))]
[TypeFilter(typeof(RequiresValidQuery))]
public class ResultsController : Controller, IResultController
{
public IIndexerManagerService IndexerService { get; private set; }
public IIndexer CurrentIndexer { get; set; }
@ -155,13 +175,39 @@ namespace Jackett.Controllers
this.logger = logger;
}
[Route("")]
[HttpGet]
public async Task<ManualSearchResult> Results([FromUri]ApiSearch request)
public async Task<IActionResult> Results([FromQuery] ApiSearch requestt)
{
//TODO: Better way to parse querystring
ApiSearch request = new ApiSearch();
foreach (var t in Request.Query)
{
if (t.Key == "Tracker[]")
{
request.Tracker = t.Value.ToString().Split(",");
}
if (t.Key == "Category[]")
{
request.Category = t.Value.ToString().Split(",").Select(Int32.Parse).ToArray();
}
if (t.Key == "query")
{
request.Query = t.Value.ToString();
}
}
var manualResult = new ManualSearchResult();
var trackers = IndexerService.GetAllIndexers().Where(t => t.IsConfigured);
var trackers = IndexerService.GetAllIndexers().ToList().Where(t => t.IsConfigured);
if (request.Tracker != null)
{
trackers = trackers.Where(t => request.Tracker.Contains(t.ID));
}
trackers = trackers.Where(t => t.CanHandleQuery(CurrentQuery));
var tasks = trackers.ToList().Select(t => t.ResultsForQuery(CurrentQuery)).ToList();
@ -235,18 +281,16 @@ namespace Jackett.Controllers
ConfigureCacheResults(manualResult.Results);
logger.Info(string.Format("Manual search for \"{0}\" on {1} with {2} results.", CurrentQuery.SanitizedSearchTerm, string.Join(", ", manualResult.Indexers.Select(i => i.ID)), manualResult.Results.Count()));
return manualResult;
return Json(manualResult);
}
[Route("[action]/{ignored?}")]
[HttpGet]
public async Task<IHttpActionResult> Torznab([FromUri]Common.Models.DTO.TorznabRequest request)
public async Task<IActionResult> Torznab([FromQuery]TorznabRequest request)
{
if (string.Equals(CurrentQuery.QueryType, "caps", StringComparison.InvariantCultureIgnoreCase))
{
return ResponseMessage(new HttpResponseMessage()
{
Content = new StringContent(CurrentIndexer.TorznabCaps.ToXml(), Encoding.UTF8, "application/xml")
});
return Content(CurrentIndexer.TorznabCaps.ToXml(), "application/rss+xml", Encoding.UTF8);
}
// indexers - returns a list of all included indexers (meta indexers only)
@ -254,7 +298,7 @@ namespace Jackett.Controllers
{
if (!(CurrentIndexer is BaseMetaIndexer)) // shouldn't be needed because CanHandleQuery should return false
{
logger.Warn($"A search request with t=indexers from {Request.GetOwinContext().Request.RemoteIpAddress} was made but the indexer {CurrentIndexer.DisplayName} isn't a meta indexer.");
logger.Warn($"A search request with t=indexers from {Request.HttpContext.Connection.RemoteIpAddress} was made but the indexer {CurrentIndexer.DisplayName} isn't a meta indexer.");
return GetErrorXML(203, "Function Not Available: this isn't a meta indexer");
}
var CurrentBaseMetaIndexer = (BaseMetaIndexer)CurrentIndexer;
@ -281,30 +325,27 @@ namespace Jackett.Controllers
)
);
return ResponseMessage(new HttpResponseMessage()
{
Content = new StringContent(xdoc.Declaration.ToString() + Environment.NewLine + xdoc.ToString(), Encoding.UTF8, "application/xml")
});
return Content(xdoc.Declaration.ToString() + Environment.NewLine + xdoc.ToString(), "application/xml", Encoding.UTF8);
}
if (CurrentQuery.ImdbID != null)
{
if (!string.IsNullOrEmpty(CurrentQuery.SearchTerm))
{
logger.Warn($"A search request from {Request.GetOwinContext().Request.RemoteIpAddress} was made containing q and imdbid.");
logger.Warn($"A search request from {Request.HttpContext.Connection.RemoteIpAddress} was made containing q and imdbid.");
return GetErrorXML(201, "Incorrect parameter: please specify either imdbid or q");
}
CurrentQuery.ImdbID = ParseUtil.GetFullImdbID(CurrentQuery.ImdbID); // normalize ImdbID
if (CurrentQuery.ImdbID == null)
{
logger.Warn($"A search request from {Request.GetOwinContext().Request.RemoteIpAddress} was made with an invalid imdbid.");
logger.Warn($"A search request from {Request.HttpContext.Connection.RemoteIpAddress} was made with an invalid imdbid.");
return GetErrorXML(201, "Incorrect parameter: invalid imdbid format");
}
if (!CurrentIndexer.TorznabCaps.SupportsImdbSearch)
{
logger.Warn($"A search request with imdbid from {Request.GetOwinContext().Request.RemoteIpAddress} was made but the indexer {CurrentIndexer.DisplayName} doesn't support it.");
logger.Warn($"A search request with imdbid from {Request.HttpContext.Connection.RemoteIpAddress} was made but the indexer {CurrentIndexer.DisplayName} doesn't support it.");
return GetErrorXML(203, "Function Not Available: imdbid is not supported by this indexer");
}
}
@ -361,13 +402,12 @@ namespace Jackett.Controllers
var xml = resultPage.ToXml(new Uri(serverUrl));
// Force the return as XML
return ResponseMessage(new HttpResponseMessage()
{
Content = new StringContent(xml, Encoding.UTF8, "application/rss+xml")
});
return Content(xml, "application/rss+xml", Encoding.UTF8);
}
public IHttpActionResult GetErrorXML(int code, string description)
[Route("[action]/{ignored?}")]
public IActionResult GetErrorXML(int code, string description)
{
var xdoc = new XDocument(
new XDeclaration("1.0", "UTF-8", null),
@ -378,16 +418,12 @@ namespace Jackett.Controllers
);
var xml = xdoc.Declaration.ToString() + Environment.NewLine + xdoc.ToString();
return ResponseMessage(new HttpResponseMessage()
{
Content = new StringContent(xml, Encoding.UTF8, "application/xml")
});
return Content(xml, "application/xml", Encoding.UTF8);
}
[Route("[action]/{ignored?}")]
[HttpGet]
[JsonResponse]
public async Task<TorrentPotatoResponse> Potato([FromUri]TorrentPotatoRequest request)
public async Task<TorrentPotatoResponse> Potato([FromQuery]TorrentPotatoRequest request)
{
var result = await CurrentIndexer.ResultsForQuery(CurrentQuery);
@ -431,6 +467,7 @@ namespace Jackett.Controllers
return potatoResponse;
}
[Route("[action]/{ignored?}")]
private void ConfigureCacheResults(IEnumerable<TrackerCacheResult> results)
{
var serverUrl = serverService.GetServerUrl(Request);
@ -439,9 +476,8 @@ namespace Jackett.Controllers
var link = result.Link;
var file = StringUtil.MakeValidFileName(result.Title, '_', false);
result.Link = serverService.ConvertToProxyLink(link, serverUrl, result.TrackerId, "dl", file);
if (result.Link != null && result.Link.Scheme != "magnet" && !string.IsNullOrWhiteSpace(Engine.ServerConfig.BlackholeDir))
if (result.Link != null && result.Link.Scheme != "magnet" && !string.IsNullOrWhiteSpace(serverService.GetBlackholeDirectory()))
result.BlackholeLink = serverService.ConvertToProxyLink(link, serverUrl, result.TrackerId, "bh", file);
}
}

View File

@ -1,23 +1,20 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Web.Http;
using Jackett.Common;
using Jackett.Common.Models;
using Jackett.Common.Models;
using Jackett.Common.Models.Config;
using Jackett.Common.Services.Interfaces;
using Jackett.Common.Utils;
using Jackett.Utils;
using Microsoft.AspNetCore.Mvc;
using NLog;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Jackett.Controllers
namespace Jackett.Server.Controllers
{
[RoutePrefix("api/v2.0/server")]
[JackettAuthorized]
[JackettAPINoCache]
public class ServerConfigurationController : ApiController
[Route("api/v2.0/server/[action]")]
//[JackettAuthorized]
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
public class ServerConfigurationController : Controller
{
private readonly IConfigurationService configService;
private ServerConfig serverConfig;
@ -29,7 +26,7 @@ namespace Jackett.Controllers
private ILogCacheService logCache;
private Logger logger;
public ServerConfigurationController(IConfigurationService c, IServerService s, IProcessService p, IIndexerManagerService i, ISecuityService ss, IUpdateService u, ILogCacheService lc, Logger l, ServerConfig sc)
public ServerConfigurationController(IConfigurationService c, IServerService s, IProcessService p, IIndexerManagerService i, ISecuityService ss, IUpdateService u, ILogCacheService lc, Logger l, ServerConfig sc)
{
configService = c;
serverConfig = sc;
@ -65,14 +62,13 @@ namespace Jackett.Controllers
[HttpGet]
public Common.Models.DTO.ServerConfig Config()
{
var dto = new Common.Models.DTO.ServerConfig(serverService.notices, serverConfig, configService.GetVersion());
return dto;
}
[ActionName("Config")]
[HttpPost]
public void UpdateConfig([FromBody]Common.Models.DTO.ServerConfig config)
public IActionResult UpdateConfig([FromBody]Common.Models.DTO.ServerConfig config)
{
var originalPort = serverConfig.Port;
var originalAllowExternal = serverConfig.AllowExternal;
@ -95,16 +91,16 @@ namespace Jackett.Controllers
serverConfig.UpdateDisabled = updateDisabled;
serverConfig.UpdatePrerelease = preRelease;
serverConfig.BasePathOverride = basePathOverride;
serverConfig.RuntimeSettings.BasePath = Engine.Server.BasePath();
serverConfig.RuntimeSettings.BasePath = serverService.BasePath();
configService.SaveConfig(serverConfig);
Engine.SetLogLevel(logging ? LogLevel.Debug : LogLevel.Info);
Initialisation.SetLogLevel(logging ? LogLevel.Debug : LogLevel.Info);
serverConfig.RuntimeSettings.TracingEnabled = logging;
if (omdbApiKey != serverConfig.OmdbApiKey)
{
serverConfig.OmdbApiKey = omdbApiKey;
configService.SaveConfig(serverConfig);
configService.SaveConfig(serverConfig);
// HACK
indexerService.InitAggregateIndexer();
}
@ -128,7 +124,6 @@ namespace Jackett.Controllers
if (port != serverConfig.Port || external != serverConfig.AllowExternal)
{
if (ServerUtil.RestrictedPorts.Contains(port))
throw new Exception("The port you have selected is restricted, try a different one.");
@ -147,7 +142,8 @@ namespace Jackett.Controllers
{
try
{
processService.StartProcessAndLog(System.Windows.Forms.Application.ExecutablePath, "--ReserveUrls", true);
//TODO
//processService.StartProcessAndLog(System.Windows.Forms.Application.ExecutablePath, "--ReserveUrls", true);
}
catch
{
@ -163,15 +159,15 @@ namespace Jackett.Controllers
serverService.ReserveUrls(true);
}
}
(new Thread(() =>
{
Thread.Sleep(500);
serverService.Stop();
Engine.BuildContainer(serverConfig.RuntimeSettings, new WebApi2Module());
Engine.Server.Initalize();
Engine.Server.Start();
})).Start();
//TODO
//(new Thread(() =>
//{
// Thread.Sleep(500);
// serverService.Stop();
// Engine.BuildContainer(serverConfig.RuntimeSettings, new WebApi2Module());
// Engine.Server.Initalize();
// Engine.Server.Start();
//})).Start();
}
if (saveDir != serverConfig.BlackholeDir)
@ -187,8 +183,10 @@ namespace Jackett.Controllers
serverConfig.BlackholeDir = saveDir;
configService.SaveConfig(serverConfig);
}
serverConfig.ConfigChanged();
return Json(serverConfig);
}
[HttpGet]
@ -196,7 +194,5 @@ namespace Jackett.Controllers
{
return logCache.Logs;
}
}
}

View File

@ -1,21 +1,20 @@
using System.IO;
using Jackett.Common.Models.Config;
using Jackett.Common.Services.Interfaces;
using Microsoft.AspNetCore.Mvc;
using MimeMapping;
using NLog;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Web.Http;
using Jackett.Common.Models.Config;
using Jackett.Common.Services.Interfaces;
using Jackett.Utils;
using MimeMapping;
using NLog;
namespace Jackett.Controllers
namespace Jackett.Server.Controllers
{
[RoutePrefix("UI")]
[JackettAuthorized]
[JackettAPINoCache]
public class WebUIController : ApiController
[Route("UI/[action]")]
//[JackettAuthorized]
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
public class WebUIController : Controller
{
private IConfigurationService config;
private ServerConfig serverConfig;
@ -42,50 +41,50 @@ namespace Jackett.Controllers
}
[HttpGet]
[AllowAnonymous]
public IHttpActionResult Logout()
//[AllowAnonymous]
public IActionResult Logout()
{
var ctx = Request.GetOwinContext();
var authManager = ctx.Authentication;
authManager.SignOut("ApplicationCookie");
return Redirect("UI/Dashboard");
var ctx = Request.HttpContext;
//TODO
//var authManager = ctx.Authentication;
//authManager.SignOut("ApplicationCookie");
return Redirect("Dashboard");
}
[HttpGet]
[HttpPost]
[AllowAnonymous]
//[AllowAnonymous]
public async Task<HttpResponseMessage> Dashboard()
{
if (Request.RequestUri.Query != null && Request.RequestUri.Query.Contains("logout"))
if (Request.Path != null && Request.Path.ToString().Contains("logout"))
{
var file = GetFile("login.html");
securityService.Logout(file);
return file;
}
//TODO
if (securityService.CheckAuthorised(Request))
{
return GetFile("index.html");
//if (securityService.CheckAuthorised(Request))
//{
return GetFile("index.html");
}
else
{
var formData = await Request.Content.ReadAsFormDataAsync();
//}
//else
//{
// var formData = await Request.ReadFormAsync();
if (formData != null && securityService.HashPassword(formData["password"]) == serverConfig.AdminPassword)
{
var file = GetFile("index.html");
securityService.Login(file);
return file;
}
else
{
return GetFile("login.html");
}
}
// if (formData != null && securityService.HashPassword(formData["password"]) == serverConfig.AdminPassword)
// {
// var file = GetFile("index.html");
// securityService.Login(file);
// return file;
// }
// else
// {
// return GetFile("login.html");
// }
//}
}
}
}

View File

@ -1,44 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace Jackett.Server.Controllers
{
[Route("api/[controller]")]
public class ValuesController : Controller
{
// GET api/values
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
[HttpGet("{id}")]
public string Get(int id)
{
return "value";
}
// POST api/values
[HttpPost]
public void Post([FromBody]string value)
{
}
// PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
}