aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Api/Controllers/DashboardController.cs
diff options
context:
space:
mode:
authorJoshua M. Boniface <joshua@boniface.me>2021-08-18 02:46:59 -0400
committerGitHub <noreply@github.com>2021-08-18 02:46:59 -0400
commit72d3f7020ad80ce1a53eeae8c5d57abeb22a4679 (patch)
treedd43e663838cdc7d99a4af565523df58ae23c856 /Jellyfin.Api/Controllers/DashboardController.cs
parent7aef0fce444e6d8e06386553ec7ea1401a01bbb1 (diff)
parente5cbafdb6b47377052e0d638908ef96e30a997d6 (diff)
Merge branch 'master' into patch-2
Diffstat (limited to 'Jellyfin.Api/Controllers/DashboardController.cs')
-rw-r--r--Jellyfin.Api/Controllers/DashboardController.cs216
1 files changed, 28 insertions, 188 deletions
diff --git a/Jellyfin.Api/Controllers/DashboardController.cs b/Jellyfin.Api/Controllers/DashboardController.cs
index 33abe3ccd..445733c24 100644
--- a/Jellyfin.Api/Controllers/DashboardController.cs
+++ b/Jellyfin.Api/Controllers/DashboardController.cs
@@ -1,19 +1,15 @@
-using System;
+using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Net.Mime;
+using Jellyfin.Api.Attributes;
using Jellyfin.Api.Models;
using MediaBrowser.Common.Plugins;
-using MediaBrowser.Controller;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Extensions;
-using MediaBrowser.Controller.Plugins;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Plugins;
using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace Jellyfin.Api.Controllers
@@ -25,85 +21,35 @@ namespace Jellyfin.Api.Controllers
public class DashboardController : BaseJellyfinApiController
{
private readonly ILogger<DashboardController> _logger;
- private readonly IServerApplicationHost _appHost;
- private readonly IConfiguration _appConfig;
- private readonly IServerConfigurationManager _serverConfigurationManager;
- private readonly IResourceFileManager _resourceFileManager;
+ private readonly IPluginManager _pluginManager;
/// <summary>
/// Initializes a new instance of the <see cref="DashboardController"/> class.
/// </summary>
/// <param name="logger">Instance of <see cref="ILogger{DashboardController}"/> interface.</param>
- /// <param name="appHost">Instance of <see cref="IServerApplicationHost"/> interface.</param>
- /// <param name="appConfig">Instance of <see cref="IConfiguration"/> interface.</param>
- /// <param name="resourceFileManager">Instance of <see cref="IResourceFileManager"/> interface.</param>
- /// <param name="serverConfigurationManager">Instance of <see cref="IServerConfigurationManager"/> interface.</param>
+ /// <param name="pluginManager">Instance of <see cref="IPluginManager"/> interface.</param>
public DashboardController(
ILogger<DashboardController> logger,
- IServerApplicationHost appHost,
- IConfiguration appConfig,
- IResourceFileManager resourceFileManager,
- IServerConfigurationManager serverConfigurationManager)
+ IPluginManager pluginManager)
{
_logger = logger;
- _appHost = appHost;
- _appConfig = appConfig;
- _resourceFileManager = resourceFileManager;
- _serverConfigurationManager = serverConfigurationManager;
+ _pluginManager = pluginManager;
}
/// <summary>
- /// Gets the path of the directory containing the static web interface content, or null if the server is not
- /// hosting the web client.
- /// </summary>
- private string? WebClientUiPath => GetWebClientUiPath(_appConfig, _serverConfigurationManager);
-
- /// <summary>
/// Gets the configuration pages.
/// </summary>
/// <param name="enableInMainMenu">Whether to enable in the main menu.</param>
- /// <param name="pageType">The <see cref="ConfigurationPageInfo"/>.</param>
/// <response code="200">ConfigurationPages returned.</response>
/// <response code="404">Server still loading.</response>
/// <returns>An <see cref="IEnumerable{ConfigurationPageInfo}"/> with infos about the plugins.</returns>
[HttpGet("web/ConfigurationPages")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
- public ActionResult<IEnumerable<ConfigurationPageInfo?>> GetConfigurationPages(
- [FromQuery] bool? enableInMainMenu,
- [FromQuery] ConfigurationPageType? pageType)
+ public ActionResult<IEnumerable<ConfigurationPageInfo>> GetConfigurationPages(
+ [FromQuery] bool? enableInMainMenu)
{
- const string unavailableMessage = "The server is still loading. Please try again momentarily.";
-
- var pages = _appHost.GetExports<IPluginConfigurationPage>().ToList();
-
- if (pages == null)
- {
- return NotFound(unavailableMessage);
- }
-
- // Don't allow a failing plugin to fail them all
- var configPages = pages.Select(p =>
- {
- try
- {
- return new ConfigurationPageInfo(p);
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error getting plugin information from {Plugin}", p.GetType().Name);
- return null;
- }
- })
- .Where(i => i != null)
- .ToList();
-
- configPages.AddRange(_appHost.Plugins.SelectMany(GetConfigPages));
-
- if (pageType.HasValue)
- {
- configPages = configPages.Where(p => p!.ConfigurationPageType == pageType).ToList();
- }
+ var configPages = _pluginManager.Plugins.SelectMany(GetConfigPages).ToList();
if (enableInMainMenu.HasValue)
{
@@ -123,151 +69,45 @@ namespace Jellyfin.Api.Controllers
[HttpGet("web/ConfigurationPage")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
+ [ProducesFile(MediaTypeNames.Text.Html, "application/x-javascript")]
public ActionResult GetDashboardConfigurationPage([FromQuery] string? name)
{
- IPlugin? plugin = null;
- Stream? stream = null;
-
- var isJs = false;
- var isTemplate = false;
-
- var page = _appHost.GetExports<IPluginConfigurationPage>().FirstOrDefault(p => string.Equals(p.Name, name, StringComparison.OrdinalIgnoreCase));
- if (page != null)
- {
- plugin = page.Plugin;
- stream = page.GetHtmlStream();
- }
-
- if (plugin == null)
- {
- var altPage = GetPluginPages().FirstOrDefault(p => string.Equals(p.Item1.Name, name, StringComparison.OrdinalIgnoreCase));
- if (altPage != null)
- {
- plugin = altPage.Item2;
- stream = plugin.GetType().Assembly.GetManifestResourceStream(altPage.Item1.EmbeddedResourcePath);
-
- isJs = string.Equals(Path.GetExtension(altPage.Item1.EmbeddedResourcePath), ".js", StringComparison.OrdinalIgnoreCase);
- isTemplate = altPage.Item1.EmbeddedResourcePath.EndsWith(".template.html", StringComparison.Ordinal);
- }
- }
-
- if (plugin != null && stream != null)
- {
- if (isJs)
- {
- return File(stream, MimeTypes.GetMimeType("page.js"));
- }
-
- if (isTemplate)
- {
- return File(stream, MimeTypes.GetMimeType("page.html"));
- }
-
- return File(stream, MimeTypes.GetMimeType("page.html"));
- }
-
- return NotFound();
- }
-
- /// <summary>
- /// Gets the robots.txt.
- /// </summary>
- /// <response code="200">Robots.txt returned.</response>
- /// <returns>The robots.txt.</returns>
- [HttpGet("robots.txt")]
- [ProducesResponseType(StatusCodes.Status200OK)]
- [ApiExplorerSettings(IgnoreApi = true)]
- public ActionResult GetRobotsTxt()
- {
- return GetWebClientResource("robots.txt");
- }
-
- /// <summary>
- /// Gets a resource from the web client.
- /// </summary>
- /// <param name="resourceName">The resource name.</param>
- /// <response code="200">Web client returned.</response>
- /// <response code="404">Server does not host a web client.</response>
- /// <returns>The resource.</returns>
- [HttpGet("web/{*resourceName}")]
- [ApiExplorerSettings(IgnoreApi = true)]
- [ProducesResponseType(StatusCodes.Status200OK)]
- [ProducesResponseType(StatusCodes.Status404NotFound)]
- public ActionResult GetWebClientResource([FromRoute] string resourceName)
- {
- if (!_appConfig.HostWebClient() || WebClientUiPath == null)
- {
- return NotFound("Server does not host a web client.");
- }
-
- var path = resourceName;
- var basePath = WebClientUiPath;
-
- var requestPathAndQuery = Request.GetEncodedPathAndQuery();
- // Bounce them to the startup wizard if it hasn't been completed yet
- if (!_serverConfigurationManager.Configuration.IsStartupWizardCompleted
- && !requestPathAndQuery.Contains("wizard", StringComparison.OrdinalIgnoreCase)
- && requestPathAndQuery.Contains("index", StringComparison.OrdinalIgnoreCase))
- {
- return Redirect("index.html?start=wizard#!/wizardstart.html");
- }
-
- var stream = new FileStream(_resourceFileManager.GetResourcePath(basePath, path), FileMode.Open, FileAccess.Read);
- return File(stream, MimeTypes.GetMimeType(path));
- }
-
- /// <summary>
- /// Gets the favicon.
- /// </summary>
- /// <response code="200">Favicon.ico returned.</response>
- /// <returns>The favicon.</returns>
- [HttpGet("favicon.ico")]
- [ProducesResponseType(StatusCodes.Status200OK)]
- [ApiExplorerSettings(IgnoreApi = true)]
- public ActionResult GetFavIcon()
- {
- return GetWebClientResource("favicon.ico");
- }
-
- /// <summary>
- /// Gets the path of the directory containing the static web interface content.
- /// </summary>
- /// <param name="appConfig">The app configuration.</param>
- /// <param name="serverConfigManager">The server configuration manager.</param>
- /// <returns>The directory path, or null if the server is not hosting the web client.</returns>
- public static string? GetWebClientUiPath(IConfiguration appConfig, IServerConfigurationManager serverConfigManager)
- {
- if (!appConfig.HostWebClient())
+ var altPage = GetPluginPages().FirstOrDefault(p => string.Equals(p.Item1.Name, name, StringComparison.OrdinalIgnoreCase));
+ if (altPage == null)
{
- return null;
+ return NotFound();
}
- if (!string.IsNullOrEmpty(serverConfigManager.Configuration.DashboardSourcePath))
+ IPlugin plugin = altPage.Item2;
+ string resourcePath = altPage.Item1.EmbeddedResourcePath;
+ Stream? stream = plugin.GetType().Assembly.GetManifestResourceStream(resourcePath);
+ if (stream == null)
{
- return serverConfigManager.Configuration.DashboardSourcePath;
+ _logger.LogError("Failed to get resource {Resource} from plugin {Plugin}", resourcePath, plugin.Name);
+ return NotFound();
}
- return serverConfigManager.ApplicationPaths.WebPath;
+ return File(stream, MimeTypes.GetMimeType(resourcePath));
}
- private IEnumerable<ConfigurationPageInfo> GetConfigPages(IPlugin plugin)
+ private IEnumerable<ConfigurationPageInfo> GetConfigPages(LocalPlugin plugin)
{
- return GetPluginPages(plugin).Select(i => new ConfigurationPageInfo(plugin, i.Item1));
+ return GetPluginPages(plugin).Select(i => new ConfigurationPageInfo(plugin.Instance, i.Item1));
}
- private IEnumerable<Tuple<PluginPageInfo, IPlugin>> GetPluginPages(IPlugin plugin)
+ private IEnumerable<Tuple<PluginPageInfo, IPlugin>> GetPluginPages(LocalPlugin plugin)
{
- if (!(plugin is IHasWebPages hasWebPages))
+ if (plugin.Instance is not IHasWebPages hasWebPages)
{
- return new List<Tuple<PluginPageInfo, IPlugin>>();
+ return Enumerable.Empty<Tuple<PluginPageInfo, IPlugin>>();
}
- return hasWebPages.GetPages().Select(i => new Tuple<PluginPageInfo, IPlugin>(i, plugin));
+ return hasWebPages.GetPages().Select(i => new Tuple<PluginPageInfo, IPlugin>(i, plugin.Instance));
}
private IEnumerable<Tuple<PluginPageInfo, IPlugin>> GetPluginPages()
{
- return _appHost.Plugins.SelectMany(GetPluginPages);
+ return _pluginManager.Plugins.SelectMany(GetPluginPages);
}
}
}