From b16da095493bc207f4196b8b61cfc768a237a5bc Mon Sep 17 00:00:00 2001 From: David Date: Wed, 10 Jun 2020 15:18:13 +0200 Subject: Move /System Endpoint to Jellyfin.Api --- Jellyfin.Api/Controllers/SystemController.cs | 222 +++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 Jellyfin.Api/Controllers/SystemController.cs (limited to 'Jellyfin.Api/Controllers/SystemController.cs') diff --git a/Jellyfin.Api/Controllers/SystemController.cs b/Jellyfin.Api/Controllers/SystemController.cs new file mode 100644 index 000000000..cab6f308f --- /dev/null +++ b/Jellyfin.Api/Controllers/SystemController.cs @@ -0,0 +1,222 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Jellyfin.Api.Constants; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Net; +using MediaBrowser.Model.System; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; + +namespace Jellyfin.Api.Controllers +{ + /// + /// The system controller. + /// + [Route("/System")] + public class SystemController : BaseJellyfinApiController + { + private readonly IServerApplicationHost _appHost; + private readonly IApplicationPaths _appPaths; + private readonly IFileSystem _fileSystem; + private readonly INetworkManager _network; + private readonly ILogger _logger; + + /// + /// Initializes a new instance of the class. + /// + /// Instance of interface. + /// Instance of interface. + /// Instance of interface. + /// Instance of interface. + /// Instance of interface. + public SystemController( + IServerConfigurationManager serverConfigurationManager, + IServerApplicationHost appHost, + IFileSystem fileSystem, + INetworkManager network, + ILogger logger) + { + _appPaths = serverConfigurationManager.ApplicationPaths; + _appHost = appHost; + _fileSystem = fileSystem; + _network = network; + _logger = logger; + } + + /// + /// Gets information about the server. + /// + /// Information retrieved. + /// A with info about the system. + [HttpGet("Info")] + // TODO: Authorize EscapeParentalControl + [Authorize(Policy = Policies.FirstTimeSetupOrElevated)] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task> GetSystemInfo() + { + return await _appHost.GetSystemInfo(CancellationToken.None).ConfigureAwait(false); + } + + /// + /// Gets public information about the server. + /// + /// Information retrieved. + /// A with public info about the system. + [HttpGet("Info/Public")] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task> GetPublicSystemInfo() + { + return await _appHost.GetPublicSystemInfo(CancellationToken.None).ConfigureAwait(false); + } + + /// + /// Pings the system. + /// + /// Information retrieved. + /// The server name. + [HttpGet("Ping")] + [HttpPost("Ping")] + [ProducesResponseType(StatusCodes.Status200OK)] + public ActionResult PingSystem() + { + return _appHost.Name; + } + + /// + /// Restarts the application. + /// + /// Server restarted. + /// No content. Server restarted. + [HttpPost("Restart")] + // TODO: Authorize AllowLocal = true + [Authorize(Policy = Policies.RequiresElevation)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + public ActionResult RestartApplication() + { + Task.Run(async () => + { + await Task.Delay(100).ConfigureAwait(false); + _appHost.Restart(); + }); + return NoContent(); + } + + /// + /// Shuts down the application. + /// + /// Server shut down. + /// No content. Server shut down. + [HttpPost("Shutdown")] + [Authorize(Policy = Policies.RequiresElevation)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + public ActionResult ShutdownApplication() + { + Task.Run(async () => + { + await Task.Delay(100).ConfigureAwait(false); + await _appHost.Shutdown().ConfigureAwait(false); + }); + return NoContent(); + } + + /// + /// Gets a list of available server log files. + /// + /// Information retrieved. + /// An array of with the available log files. + [HttpGet("Logs")] + [Authorize(Policy = Policies.RequiresElevation)] + [ProducesResponseType(StatusCodes.Status200OK)] + public ActionResult GetServerLogs() + { + IEnumerable files; + + try + { + files = _fileSystem.GetFiles(_appPaths.LogDirectoryPath, new[] { ".txt", ".log" }, true, false); + } + catch (IOException ex) + { + _logger.LogError(ex, "Error getting logs"); + files = Enumerable.Empty(); + } + + var result = files.Select(i => new LogFile + { + DateCreated = _fileSystem.GetCreationTimeUtc(i), + DateModified = _fileSystem.GetLastWriteTimeUtc(i), + Name = i.Name, + Size = i.Length + }) + .OrderByDescending(i => i.DateModified) + .ThenByDescending(i => i.DateCreated) + .ThenBy(i => i.Name) + .ToArray(); + + return result; + } + + /// + /// Gets information about the request endpoint. + /// + /// Information retrieved. + /// with information about the endpoint. + [HttpGet("Endpoint")] + [Authorize] + [ProducesResponseType(StatusCodes.Status200OK)] + public ActionResult GetEndpointInfo() + { + return new EndPointInfo + { + IsLocal = Request.HttpContext.Connection.LocalIpAddress.Equals(Request.HttpContext.Connection.RemoteIpAddress), + IsInNetwork = _network.IsInLocalNetwork(Request.HttpContext.Connection.RemoteIpAddress.ToString()) + }; + } + + /// + /// Gets a log file. + /// + /// The name of the log file to get. + /// Log file retrieved. + /// The log file. + [HttpGet("Logs/Log")] + [Authorize(Policy = Policies.RequiresElevation)] + [ProducesResponseType(StatusCodes.Status200OK)] + public ActionResult GetLogFile([FromQuery, Required] string name) + { + var file = _fileSystem.GetFiles(_appPaths.LogDirectoryPath) + .First(i => string.Equals(i.Name, name, StringComparison.OrdinalIgnoreCase)); + + // For older files, assume fully static + var fileShare = file.LastWriteTimeUtc < DateTime.UtcNow.AddHours(-1) ? FileShare.Read : FileShare.ReadWrite; + + FileStream stream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, fileShare); + return File(stream, "text/plain"); + } + + /// + /// Gets wake on lan information. + /// + /// Information retrieved. + /// An with the WakeOnLan infos. + [HttpGet("WakeOnLanInfo")] + [Authorize] + [ProducesResponseType(StatusCodes.Status200OK)] + public ActionResult> GetWakeOnLanInfo() + { + var result = _appHost.GetWakeOnLanInfo(); + return Ok(result); + } + } +} -- cgit v1.2.3 From b51b9653ac9ff015d34233099bdc744fa153f8ee Mon Sep 17 00:00:00 2001 From: David Date: Fri, 19 Jun 2020 14:29:32 +0200 Subject: Add missing authorization policies --- Jellyfin.Api/Controllers/SystemController.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Jellyfin.Api/Controllers/SystemController.cs') diff --git a/Jellyfin.Api/Controllers/SystemController.cs b/Jellyfin.Api/Controllers/SystemController.cs index cab6f308f..f4dae40ef 100644 --- a/Jellyfin.Api/Controllers/SystemController.cs +++ b/Jellyfin.Api/Controllers/SystemController.cs @@ -60,7 +60,7 @@ namespace Jellyfin.Api.Controllers /// Information retrieved. /// A with info about the system. [HttpGet("Info")] - // TODO: Authorize EscapeParentalControl + [Authorize(Policy = Policies.IgnoreSchedule)] [Authorize(Policy = Policies.FirstTimeSetupOrElevated)] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> GetSystemInfo() @@ -99,7 +99,7 @@ namespace Jellyfin.Api.Controllers /// Server restarted. /// No content. Server restarted. [HttpPost("Restart")] - // TODO: Authorize AllowLocal = true + [Authorize(Policy = Policies.LocalAccessOnly)] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult RestartApplication() -- cgit v1.2.3 From 6b72fb86316786451be4fb84e4ba89d496b4ef2f Mon Sep 17 00:00:00 2001 From: David Date: Mon, 22 Jun 2020 15:49:15 +0200 Subject: Add missing default authorization policy --- Jellyfin.Api/Controllers/SystemController.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Jellyfin.Api/Controllers/SystemController.cs') diff --git a/Jellyfin.Api/Controllers/SystemController.cs b/Jellyfin.Api/Controllers/SystemController.cs index f4dae40ef..e33821b24 100644 --- a/Jellyfin.Api/Controllers/SystemController.cs +++ b/Jellyfin.Api/Controllers/SystemController.cs @@ -173,7 +173,7 @@ namespace Jellyfin.Api.Controllers /// Information retrieved. /// with information about the endpoint. [HttpGet("Endpoint")] - [Authorize] + [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetEndpointInfo() { @@ -211,7 +211,7 @@ namespace Jellyfin.Api.Controllers /// Information retrieved. /// An with the WakeOnLan infos. [HttpGet("WakeOnLanInfo")] - [Authorize] + [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetWakeOnLanInfo() { -- cgit v1.2.3