2020-03-03 16:28:26 +00:00
|
|
|
using System;
|
2020-02-09 18:08:34 +00:00
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.IO;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Threading;
|
|
|
|
using Jackett.Common.Models;
|
2018-05-01 12:03:16 +00:00
|
|
|
using Jackett.Common.Models.Config;
|
|
|
|
using Jackett.Common.Services.Interfaces;
|
|
|
|
using Jackett.Common.Utils;
|
2018-05-01 12:55:09 +00:00
|
|
|
using Microsoft.AspNetCore.Mvc;
|
2018-05-01 12:03:16 +00:00
|
|
|
using NLog;
|
|
|
|
|
2018-05-01 12:55:09 +00:00
|
|
|
namespace Jackett.Server.Controllers
|
2018-05-01 12:03:16 +00:00
|
|
|
{
|
2018-05-01 12:55:09 +00:00
|
|
|
[Route("api/v2.0/server/[action]")]
|
|
|
|
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
|
|
|
|
public class ServerConfigurationController : Controller
|
2018-05-01 12:03:16 +00:00
|
|
|
{
|
|
|
|
private readonly IConfigurationService configService;
|
2020-02-10 22:16:19 +00:00
|
|
|
private readonly ServerConfig serverConfig;
|
|
|
|
private readonly IServerService serverService;
|
|
|
|
private readonly IProcessService processService;
|
|
|
|
private readonly IIndexerManagerService indexerService;
|
|
|
|
private readonly ISecuityService securityService;
|
2020-12-12 17:44:08 +00:00
|
|
|
private readonly ICacheService cacheService;
|
2020-02-10 22:16:19 +00:00
|
|
|
private readonly IUpdateService updater;
|
|
|
|
private readonly ILogCacheService logCache;
|
|
|
|
private readonly Logger logger;
|
2018-05-01 12:03:16 +00:00
|
|
|
|
2020-12-12 17:44:08 +00:00
|
|
|
public ServerConfigurationController(IConfigurationService c, IServerService s, IProcessService p,
|
|
|
|
IIndexerManagerService i, ISecuityService ss, ICacheService cs, IUpdateService u, ILogCacheService lc,
|
|
|
|
Logger l, ServerConfig sc)
|
2018-05-01 12:03:16 +00:00
|
|
|
{
|
|
|
|
configService = c;
|
|
|
|
serverConfig = sc;
|
|
|
|
serverService = s;
|
|
|
|
processService = p;
|
|
|
|
indexerService = i;
|
|
|
|
securityService = ss;
|
2020-12-12 17:44:08 +00:00
|
|
|
cacheService = cs;
|
2018-05-01 12:03:16 +00:00
|
|
|
updater = u;
|
|
|
|
logCache = lc;
|
|
|
|
logger = l;
|
|
|
|
}
|
|
|
|
|
|
|
|
[HttpPost]
|
2021-05-16 18:13:54 +00:00
|
|
|
public IActionResult AdminPassword([FromBody] string password)
|
2018-05-01 12:03:16 +00:00
|
|
|
{
|
|
|
|
var oldPassword = serverConfig.AdminPassword;
|
|
|
|
if (string.IsNullOrEmpty(password))
|
|
|
|
password = null;
|
|
|
|
|
|
|
|
if (oldPassword != password)
|
|
|
|
{
|
|
|
|
serverConfig.AdminPassword = securityService.HashPassword(password);
|
|
|
|
configService.SaveConfig(serverConfig);
|
|
|
|
}
|
2018-05-05 07:10:36 +00:00
|
|
|
|
|
|
|
return new NoContentResult();
|
2018-05-01 12:03:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
[HttpPost]
|
2020-02-25 16:08:03 +00:00
|
|
|
public void Update() => updater.CheckForUpdatesNow();
|
2018-05-01 12:03:16 +00:00
|
|
|
|
|
|
|
[HttpGet]
|
|
|
|
public Common.Models.DTO.ServerConfig Config()
|
|
|
|
{
|
2019-04-27 10:59:33 +00:00
|
|
|
var dto = new Common.Models.DTO.ServerConfig(serverService.notices, serverConfig, configService.GetVersion(), serverService.MonoUserCanRunNetCore());
|
2018-05-01 12:03:16 +00:00
|
|
|
return dto;
|
|
|
|
}
|
|
|
|
|
|
|
|
[ActionName("Config")]
|
|
|
|
[HttpPost]
|
2021-05-16 18:13:54 +00:00
|
|
|
public IActionResult UpdateConfig([FromBody] Common.Models.DTO.ServerConfig config)
|
2018-05-01 12:03:16 +00:00
|
|
|
{
|
2020-02-10 22:16:19 +00:00
|
|
|
var webHostRestartNeeded = false;
|
2018-07-13 12:15:09 +00:00
|
|
|
|
2018-05-01 12:03:16 +00:00
|
|
|
var originalPort = serverConfig.Port;
|
|
|
|
var originalAllowExternal = serverConfig.AllowExternal;
|
2020-02-10 22:16:19 +00:00
|
|
|
var port = config.port;
|
|
|
|
var external = config.external;
|
|
|
|
var saveDir = config.blackholedir;
|
|
|
|
var updateDisabled = config.updatedisabled;
|
|
|
|
var preRelease = config.prerelease;
|
2020-09-26 23:19:46 +00:00
|
|
|
var enhancedLogging = config.logging;
|
|
|
|
|
2020-02-10 22:16:19 +00:00
|
|
|
var basePathOverride = config.basepathoverride;
|
2018-05-01 12:03:16 +00:00
|
|
|
if (basePathOverride != null)
|
|
|
|
{
|
|
|
|
basePathOverride = basePathOverride.TrimEnd('/');
|
|
|
|
if (!string.IsNullOrWhiteSpace(basePathOverride) && !basePathOverride.StartsWith("/"))
|
|
|
|
throw new Exception("The Base Path Override must start with a /");
|
|
|
|
}
|
|
|
|
|
2020-12-11 22:14:21 +00:00
|
|
|
var cacheEnabled = config.cache_enabled;
|
|
|
|
var cacheTtl = config.cache_ttl;
|
|
|
|
var cacheMaxResultsPerIndexer = config.cache_max_results_per_indexer;
|
2020-02-10 22:16:19 +00:00
|
|
|
var omdbApiKey = config.omdbkey;
|
|
|
|
var omdbApiUrl = config.omdburl;
|
2018-05-01 12:03:16 +00:00
|
|
|
|
2018-07-13 12:15:09 +00:00
|
|
|
if (config.basepathoverride != serverConfig.BasePathOverride)
|
|
|
|
{
|
|
|
|
webHostRestartNeeded = true;
|
|
|
|
}
|
|
|
|
|
2018-05-01 12:03:16 +00:00
|
|
|
serverConfig.UpdateDisabled = updateDisabled;
|
|
|
|
serverConfig.UpdatePrerelease = preRelease;
|
|
|
|
serverConfig.BasePathOverride = basePathOverride;
|
2020-12-11 22:14:21 +00:00
|
|
|
serverConfig.CacheEnabled = cacheEnabled;
|
|
|
|
serverConfig.CacheTtl = cacheTtl;
|
|
|
|
serverConfig.CacheMaxResultsPerIndexer = cacheMaxResultsPerIndexer;
|
|
|
|
|
2018-05-01 12:55:09 +00:00
|
|
|
serverConfig.RuntimeSettings.BasePath = serverService.BasePath();
|
2018-05-01 12:03:16 +00:00
|
|
|
configService.SaveConfig(serverConfig);
|
|
|
|
|
2020-12-13 20:42:10 +00:00
|
|
|
if (config.flaresolverrurl != serverConfig.FlareSolverrUrl)
|
|
|
|
{
|
2020-12-19 19:13:23 +00:00
|
|
|
if (string.IsNullOrWhiteSpace(config.flaresolverrurl))
|
|
|
|
config.flaresolverrurl = "";
|
|
|
|
else if (!Uri.TryCreate(config.flaresolverrurl, UriKind.Absolute, out var uri)
|
|
|
|
|| !(uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps))
|
|
|
|
throw new Exception("FlareSolverr API URL is invalid. Example: http://127.0.0.1:8191");
|
|
|
|
|
2020-12-13 20:42:10 +00:00
|
|
|
serverConfig.FlareSolverrUrl = config.flaresolverrurl;
|
|
|
|
configService.SaveConfig(serverConfig);
|
|
|
|
webHostRestartNeeded = true;
|
|
|
|
}
|
|
|
|
|
2018-07-09 11:00:17 +00:00
|
|
|
if (omdbApiKey != serverConfig.OmdbApiKey || omdbApiUrl != serverConfig.OmdbApiUrl)
|
2018-05-01 12:03:16 +00:00
|
|
|
{
|
|
|
|
serverConfig.OmdbApiKey = omdbApiKey;
|
2018-07-09 11:00:17 +00:00
|
|
|
serverConfig.OmdbApiUrl = omdbApiUrl.TrimEnd('/');
|
2018-05-01 12:55:09 +00:00
|
|
|
configService.SaveConfig(serverConfig);
|
2018-05-01 12:03:16 +00:00
|
|
|
// HACK
|
2021-05-08 20:24:18 +00:00
|
|
|
indexerService.InitMetaIndexers();
|
2018-05-01 12:03:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (config.proxy_type != serverConfig.ProxyType ||
|
|
|
|
config.proxy_url != serverConfig.ProxyUrl ||
|
|
|
|
config.proxy_port != serverConfig.ProxyPort ||
|
|
|
|
config.proxy_username != serverConfig.ProxyUsername ||
|
|
|
|
config.proxy_password != serverConfig.ProxyPassword)
|
|
|
|
{
|
|
|
|
if (config.proxy_port < 1 || config.proxy_port > 65535)
|
|
|
|
throw new Exception("The port you have selected is invalid, it must be below 65535.");
|
|
|
|
|
2020-09-26 20:28:29 +00:00
|
|
|
serverConfig.ProxyType = string.IsNullOrWhiteSpace(config.proxy_url) ? ProxyType.Disabled : config.proxy_type;
|
2018-05-01 12:03:16 +00:00
|
|
|
serverConfig.ProxyUrl = config.proxy_url;
|
|
|
|
serverConfig.ProxyPort = config.proxy_port;
|
|
|
|
serverConfig.ProxyUsername = config.proxy_username;
|
|
|
|
serverConfig.ProxyPassword = config.proxy_password;
|
|
|
|
configService.SaveConfig(serverConfig);
|
2019-10-20 02:41:51 +00:00
|
|
|
webHostRestartNeeded = true;
|
2020-12-12 17:44:08 +00:00
|
|
|
|
|
|
|
// Remove all results from cache so we can test the new proxy
|
|
|
|
cacheService.CleanCache();
|
2018-05-01 12:03:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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.");
|
|
|
|
|
|
|
|
if (port < 1 || port > 65535)
|
|
|
|
throw new Exception("The port you have selected is invalid, it must be below 65535.");
|
|
|
|
|
|
|
|
// Save port to the config so it can be picked up by the if needed when running as admin below.
|
|
|
|
serverConfig.AllowExternal = external;
|
|
|
|
serverConfig.Port = port;
|
|
|
|
configService.SaveConfig(serverConfig);
|
|
|
|
|
|
|
|
// On Windows change the url reservations
|
2020-12-12 17:44:08 +00:00
|
|
|
if (Environment.OSVersion.Platform != PlatformID.Unix)
|
2018-05-01 12:03:16 +00:00
|
|
|
{
|
|
|
|
if (!ServerUtil.IsUserAdministrator())
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2020-12-12 20:38:33 +00:00
|
|
|
var consoleExePath = EnvironmentUtil.JackettExecutablePath().Replace(".dll", ".exe");
|
2018-06-17 02:39:03 +00:00
|
|
|
processService.StartProcessAndLog(consoleExePath, "--ReserveUrls", true);
|
2018-05-01 12:03:16 +00:00
|
|
|
}
|
|
|
|
catch
|
|
|
|
{
|
|
|
|
serverConfig.Port = originalPort;
|
|
|
|
serverConfig.AllowExternal = originalAllowExternal;
|
|
|
|
configService.SaveConfig(serverConfig);
|
|
|
|
|
|
|
|
throw new Exception("Failed to acquire admin permissions to reserve the new port.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-12-12 17:44:08 +00:00
|
|
|
serverService.ReserveUrls();
|
2018-05-01 12:03:16 +00:00
|
|
|
}
|
|
|
|
}
|
2018-06-16 08:06:14 +00:00
|
|
|
|
2018-07-13 12:15:09 +00:00
|
|
|
webHostRestartNeeded = true;
|
2018-05-01 12:03:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (saveDir != serverConfig.BlackholeDir)
|
|
|
|
{
|
|
|
|
if (!string.IsNullOrEmpty(saveDir))
|
|
|
|
{
|
|
|
|
if (!Directory.Exists(saveDir))
|
|
|
|
{
|
|
|
|
throw new Exception("Blackhole directory does not exist");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
serverConfig.BlackholeDir = saveDir;
|
|
|
|
configService.SaveConfig(serverConfig);
|
|
|
|
}
|
2018-05-01 12:55:09 +00:00
|
|
|
|
2018-07-13 12:15:09 +00:00
|
|
|
if (webHostRestartNeeded)
|
|
|
|
{
|
2020-09-26 23:19:46 +00:00
|
|
|
// we have to restore log level when the server restarts because we are not saving the state in the
|
|
|
|
// configuration. when the server restarts the UI is inconsistent with the active log level
|
|
|
|
// https://github.com/Jackett/Jackett/issues/8315
|
2020-12-12 17:44:08 +00:00
|
|
|
SetEnhancedLogLevel(false);
|
2020-09-26 23:19:46 +00:00
|
|
|
|
2018-07-13 12:15:09 +00:00
|
|
|
Thread.Sleep(500);
|
|
|
|
logger.Info("Restarting webhost due to configuration change");
|
|
|
|
Helper.RestartWebHost();
|
|
|
|
}
|
2020-09-26 23:19:46 +00:00
|
|
|
else
|
2020-12-12 17:44:08 +00:00
|
|
|
SetEnhancedLogLevel(enhancedLogging);
|
2018-07-13 12:15:09 +00:00
|
|
|
|
2018-05-01 12:03:16 +00:00
|
|
|
serverConfig.ConfigChanged();
|
2018-05-01 12:55:09 +00:00
|
|
|
|
|
|
|
return Json(serverConfig);
|
2018-05-01 12:03:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
[HttpGet]
|
2020-02-25 16:08:03 +00:00
|
|
|
public List<CachedLog> Logs() => logCache.Logs;
|
2020-09-26 23:19:46 +00:00
|
|
|
|
2020-12-12 17:44:08 +00:00
|
|
|
private void SetEnhancedLogLevel(bool enabled)
|
2020-09-26 23:19:46 +00:00
|
|
|
{
|
|
|
|
Helper.SetLogLevel(enabled ? LogLevel.Debug : LogLevel.Info);
|
|
|
|
serverConfig.RuntimeSettings.TracingEnabled = enabled;
|
|
|
|
}
|
2018-05-01 12:03:16 +00:00
|
|
|
}
|
|
|
|
}
|