jellyfin/Jellyfin.Api/Controllers/SystemController.cs

232 lines
8.9 KiB
C#
Raw Normal View History

2020-09-12 15:41:37 +00:00
using System;
2020-06-10 13:18:13 +00:00
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Net.Mime;
using Jellyfin.Api.Attributes;
2020-06-10 13:18:13 +00:00
using Jellyfin.Api.Constants;
using MediaBrowser.Common.Api;
2020-06-10 13:18:13 +00:00
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions;
2020-06-10 13:18:13 +00:00
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
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;
2023-01-31 11:18:10 +00:00
namespace Jellyfin.Api.Controllers;
/// <summary>
/// The system controller.
/// </summary>
public class SystemController : BaseJellyfinApiController
2020-06-10 13:18:13 +00:00
{
2023-10-04 18:34:53 +00:00
private readonly ILogger<SystemController> _logger;
2023-01-31 11:18:10 +00:00
private readonly IServerApplicationHost _appHost;
private readonly IApplicationPaths _appPaths;
private readonly IFileSystem _fileSystem;
2023-10-04 18:34:53 +00:00
private readonly INetworkManager _networkManager;
private readonly ISystemManager _systemManager;
2023-01-31 11:18:10 +00:00
2020-06-10 13:18:13 +00:00
/// <summary>
2023-01-31 11:18:10 +00:00
/// Initializes a new instance of the <see cref="SystemController"/> class.
2020-06-10 13:18:13 +00:00
/// </summary>
2023-10-04 18:34:53 +00:00
/// <param name="logger">Instance of <see cref="ILogger{SystemController}"/> interface.</param>
/// <param name="appPaths">Instance of <see cref="IServerApplicationPaths"/> interface.</param>
2023-01-31 11:18:10 +00:00
/// <param name="appHost">Instance of <see cref="IServerApplicationHost"/> interface.</param>
/// <param name="fileSystem">Instance of <see cref="IFileSystem"/> interface.</param>
2023-10-04 18:34:53 +00:00
/// <param name="networkManager">Instance of <see cref="INetworkManager"/> interface.</param>
/// <param name="systemManager">Instance of <see cref="ISystemManager"/> interface.</param>
2023-01-31 11:18:10 +00:00
public SystemController(
2023-10-04 18:34:53 +00:00
ILogger<SystemController> logger,
2023-01-31 11:18:10 +00:00
IServerApplicationHost appHost,
2023-10-04 18:34:53 +00:00
IServerApplicationPaths appPaths,
2023-01-31 11:18:10 +00:00
IFileSystem fileSystem,
2023-10-04 18:34:53 +00:00
INetworkManager networkManager,
ISystemManager systemManager)
2020-06-10 13:18:13 +00:00
{
2023-10-04 18:34:53 +00:00
_logger = logger;
2023-01-31 11:18:10 +00:00
_appHost = appHost;
2023-10-04 18:34:53 +00:00
_appPaths = appPaths;
2023-01-31 11:18:10 +00:00
_fileSystem = fileSystem;
2023-10-04 18:34:53 +00:00
_networkManager = networkManager;
_systemManager = systemManager;
2023-01-31 11:18:10 +00:00
}
2020-06-10 13:18:13 +00:00
2023-01-31 11:18:10 +00:00
/// <summary>
/// Gets information about the server.
/// </summary>
/// <response code="200">Information retrieved.</response>
/// <response code="403">User does not have permission to retrieve information.</response>
2023-01-31 11:18:10 +00:00
/// <returns>A <see cref="SystemInfo"/> with info about the system.</returns>
[HttpGet("Info")]
[Authorize(Policy = Policies.FirstTimeSetupOrIgnoreParentalControl)]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
2023-01-31 11:18:10 +00:00
public ActionResult<SystemInfo> GetSystemInfo()
2023-10-04 18:34:53 +00:00
=> _systemManager.GetSystemInfo(Request);
2020-06-10 13:18:13 +00:00
2023-01-31 11:18:10 +00:00
/// <summary>
/// Gets public information about the server.
/// </summary>
/// <response code="200">Information retrieved.</response>
/// <returns>A <see cref="PublicSystemInfo"/> with public info about the system.</returns>
[HttpGet("Info/Public")]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<PublicSystemInfo> GetPublicSystemInfo()
2023-10-04 18:34:53 +00:00
=> _systemManager.GetPublicSystemInfo(Request);
2020-06-10 13:18:13 +00:00
2023-01-31 11:18:10 +00:00
/// <summary>
/// Pings the system.
/// </summary>
/// <response code="200">Information retrieved.</response>
/// <returns>The server name.</returns>
[HttpGet("Ping", Name = "GetPingSystem")]
[HttpPost("Ping", Name = "PostPingSystem")]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<string> PingSystem()
2023-10-04 18:34:53 +00:00
=> _appHost.Name;
2020-06-10 13:18:13 +00:00
2023-01-31 11:18:10 +00:00
/// <summary>
/// Restarts the application.
/// </summary>
/// <response code="204">Server restarted.</response>
/// <response code="403">User does not have permission to restart server.</response>
2023-01-31 11:18:10 +00:00
/// <returns>No content. Server restarted.</returns>
[HttpPost("Restart")]
[Authorize(Policy = Policies.LocalAccessOrRequiresElevation)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
2023-01-31 11:18:10 +00:00
public ActionResult RestartApplication()
{
2023-10-04 18:34:53 +00:00
_systemManager.Restart();
2023-01-31 11:18:10 +00:00
return NoContent();
}
2020-06-10 13:18:13 +00:00
2023-01-31 11:18:10 +00:00
/// <summary>
/// Shuts down the application.
/// </summary>
/// <response code="204">Server shut down.</response>
/// <response code="403">User does not have permission to shutdown server.</response>
2023-01-31 11:18:10 +00:00
/// <returns>No content. Server shut down.</returns>
[HttpPost("Shutdown")]
[Authorize(Policy = Policies.RequiresElevation)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
2023-01-31 11:18:10 +00:00
public ActionResult ShutdownApplication()
{
2023-10-04 18:34:53 +00:00
_systemManager.Shutdown();
2023-01-31 11:18:10 +00:00
return NoContent();
}
/// <summary>
/// Gets a list of available server log files.
/// </summary>
/// <response code="200">Information retrieved.</response>
/// <response code="403">User does not have permission to get server logs.</response>
2023-01-31 11:18:10 +00:00
/// <returns>An array of <see cref="LogFile"/> with the available log files.</returns>
[HttpGet("Logs")]
[Authorize(Policy = Policies.RequiresElevation)]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
2023-01-31 11:18:10 +00:00
public ActionResult<LogFile[]> GetServerLogs()
{
IEnumerable<FileSystemMetadata> files;
2020-06-10 13:18:13 +00:00
2023-01-31 11:18:10 +00:00
try
2020-06-10 13:18:13 +00:00
{
2023-01-31 11:18:10 +00:00
files = _fileSystem.GetFiles(_appPaths.LogDirectoryPath, new[] { ".txt", ".log" }, true, false);
2020-06-10 13:18:13 +00:00
}
2023-01-31 11:18:10 +00:00
catch (IOException ex)
2020-06-10 13:18:13 +00:00
{
2023-01-31 11:18:10 +00:00
_logger.LogError(ex, "Error getting logs");
files = Enumerable.Empty<FileSystemMetadata>();
2020-06-10 13:18:13 +00:00
}
2023-01-31 11:18:10 +00:00
var result = files.Select(i => new LogFile
2020-06-10 13:18:13 +00:00
{
2023-01-31 11:18:10 +00:00
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();
2020-06-10 13:18:13 +00:00
2023-01-31 11:18:10 +00:00
return result;
}
2020-06-10 13:18:13 +00:00
2023-01-31 11:18:10 +00:00
/// <summary>
/// Gets information about the request endpoint.
/// </summary>
/// <response code="200">Information retrieved.</response>
/// <response code="403">User does not have permission to get endpoint information.</response>
2023-01-31 11:18:10 +00:00
/// <returns><see cref="EndPointInfo"/> with information about the endpoint.</returns>
[HttpGet("Endpoint")]
2023-02-08 22:55:26 +00:00
[Authorize]
2023-01-31 11:18:10 +00:00
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
2023-01-31 11:18:10 +00:00
public ActionResult<EndPointInfo> GetEndpointInfo()
{
return new EndPointInfo
2020-06-10 13:18:13 +00:00
{
2023-01-31 11:18:10 +00:00
IsLocal = HttpContext.IsLocal(),
2023-10-04 18:34:53 +00:00
IsInNetwork = _networkManager.IsInLocalNetwork(HttpContext.GetNormalizedRemoteIP())
2023-01-31 11:18:10 +00:00
};
}
/// <summary>
/// Gets a log file.
/// </summary>
/// <param name="name">The name of the log file to get.</param>
/// <response code="200">Log file retrieved.</response>
/// <response code="403">User does not have permission to get log files.</response>
2024-02-03 21:25:44 +00:00
/// <response code="404">Could not find a log file with the name.</response>
2023-01-31 11:18:10 +00:00
/// <returns>The log file.</returns>
[HttpGet("Logs/Log")]
[Authorize(Policy = Policies.RequiresElevation)]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
2024-02-03 21:25:44 +00:00
[ProducesResponseType(StatusCodes.Status404NotFound)]
2023-01-31 11:18:10 +00:00
[ProducesFile(MediaTypeNames.Text.Plain)]
public ActionResult GetLogFile([FromQuery, Required] string name)
{
2024-02-03 21:25:44 +00:00
var file = _fileSystem
.GetFiles(_appPaths.LogDirectoryPath)
.FirstOrDefault(i => string.Equals(i.Name, name, StringComparison.OrdinalIgnoreCase));
if (file is null)
{
return NotFound("Log file not found.");
}
2023-01-31 11:18:10 +00:00
// 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, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
return File(stream, "text/plain; charset=utf-8");
}
/// <summary>
/// Gets wake on lan information.
/// </summary>
/// <response code="200">Information retrieved.</response>
/// <returns>An <see cref="IEnumerable{WakeOnLanInfo}"/> with the WakeOnLan infos.</returns>
[HttpGet("WakeOnLanInfo")]
2023-02-08 22:55:26 +00:00
[Authorize]
2023-01-31 11:18:10 +00:00
[Obsolete("This endpoint is obsolete.")]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<IEnumerable<WakeOnLanInfo>> GetWakeOnLanInfo()
{
2023-10-04 18:34:53 +00:00
var result = _networkManager.GetMacAddresses()
2023-01-31 11:18:10 +00:00
.Select(i => new WakeOnLanInfo(i));
return Ok(result);
2020-06-10 13:18:13 +00:00
}
}