Delete plugin working.

pull/4709/head
Greenback 4 years ago
parent 7986465cf7
commit a246a77ada

@ -78,8 +78,27 @@ namespace Emby.Server.Implementations
/// <returns>An IEnumerable{Assembly}.</returns> /// <returns>An IEnumerable{Assembly}.</returns>
public IEnumerable<Assembly> LoadAssemblies() public IEnumerable<Assembly> LoadAssemblies()
{ {
// Attempt to remove any deleted plugins and change any successors to be active.
for (int a = _plugins.Count - 1; a >= 0; a--)
{
var plugin = _plugins[a];
if (plugin.Manifest.Status == PluginStatus.DeleteOnStartup && DeletePlugin(plugin))
{
UpdateSuccessors(plugin);
}
}
// Now load the assemblies..
foreach (var plugin in _plugins) foreach (var plugin in _plugins)
{ {
CheckIfStillSuperceded(plugin);
if (plugin.IsEnabledAndSupported == false)
{
_logger.LogInformation("Skipping disabled plugin {Version} of {Name} ", plugin.Version, plugin.Name);
continue;
}
foreach (var file in plugin.DllFiles) foreach (var file in plugin.DllFiles)
{ {
try try
@ -183,15 +202,13 @@ namespace Emby.Server.Implementations
throw new ArgumentNullException(nameof(plugin)); throw new ArgumentNullException(nameof(plugin));
} }
plugin.Instance?.OnUninstalling();
if (DeletePlugin(plugin)) if (DeletePlugin(plugin))
{ {
return true; return true;
} }
// Unable to delete, so disable. // Unable to delete, so disable.
return ChangePluginState(plugin, PluginStatus.Disabled); return ChangePluginState(plugin, PluginStatus.DeleteOnStartup);
} }
/// <summary> /// <summary>
@ -205,11 +222,18 @@ namespace Emby.Server.Implementations
{ {
if (version == null) if (version == null)
{ {
// If no version is given, return the largest version number. (This is for backwards compatibility). // If no version is given, return the current instance.
plugin = _plugins.Where(p => p.Id.Equals(id)).OrderByDescending(p => p.Version).FirstOrDefault(); var plugins = _plugins.Where(p => p.Id.Equals(id));
plugin = plugins.FirstOrDefault(p => p.Instance != null);
if (plugin == null)
{
plugin = plugins.OrderByDescending(p => p.Version).FirstOrDefault();
}
} }
else else
{ {
// Match id and version number.
plugin = _plugins.FirstOrDefault(p => p.Id.Equals(id) && p.Version.Equals(version)); plugin = _plugins.FirstOrDefault(p => p.Id.Equals(id) && p.Version.Equals(version));
} }
@ -264,7 +288,6 @@ namespace Emby.Server.Implementations
var predecessor = _plugins.OrderByDescending(p => p.Version) var predecessor = _plugins.OrderByDescending(p => p.Version)
.FirstOrDefault( .FirstOrDefault(
p => p.Id.Equals(plugin.Id) p => p.Id.Equals(plugin.Id)
&& p.Name.Equals(plugin.Name, StringComparison.OrdinalIgnoreCase)
&& p.IsEnabledAndSupported && p.IsEnabledAndSupported
&& p.Version != plugin.Version); && p.Version != plugin.Version);
@ -381,17 +404,6 @@ namespace Emby.Server.Implementations
// Find the record for this plugin. // Find the record for this plugin.
var plugin = GetPluginByType(type); var plugin = GetPluginByType(type);
if (plugin != null)
{
CheckIfStillSuperceded(plugin);
if (plugin.IsEnabledAndSupported == true)
{
_logger.LogInformation("Skipping disabled plugin {Version} of {Name} ", plugin.Version, plugin.Name);
return null;
}
}
try try
{ {
_logger.LogDebug("Creating instance of {Type}", type); _logger.LogDebug("Creating instance of {Type}", type);
@ -489,6 +501,7 @@ namespace Emby.Server.Implementations
{ {
_logger.LogDebug("Deleting {Path}", plugin.Path); _logger.LogDebug("Deleting {Path}", plugin.Path);
Directory.Delete(plugin.Path, true); Directory.Delete(plugin.Path, true);
_plugins.Remove(plugin);
} }
#pragma warning disable CA1031 // Do not catch general exception types #pragma warning disable CA1031 // Do not catch general exception types
catch (Exception e) catch (Exception e)
@ -661,8 +674,8 @@ namespace Emby.Server.Implementations
continue; continue;
} }
// Update the manifest so its not loaded next time. manifest.Status = PluginStatus.DeleteOnStartup;
manifest.Status = PluginStatus.Disabled;
SaveManifest(manifest, entry.Path); SaveManifest(manifest, entry.Path);
} }
} }

@ -46,7 +46,6 @@ namespace Jellyfin.Api.Controllers
/// <returns>A <see cref="PackageInfo"/> containing package information.</returns> /// <returns>A <see cref="PackageInfo"/> containing package information.</returns>
[HttpGet("Packages/{name}")] [HttpGet("Packages/{name}")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[Produces(JsonDefaults.CamelCaseMediaType)]
public async Task<ActionResult<PackageInfo>> GetPackageInfo( public async Task<ActionResult<PackageInfo>> GetPackageInfo(
[FromRoute, Required] string name, [FromRoute, Required] string name,
[FromQuery] Guid? assemblyGuid) [FromQuery] Guid? assemblyGuid)
@ -73,7 +72,6 @@ namespace Jellyfin.Api.Controllers
/// <returns>An <see cref="PackageInfo"/> containing available packages information.</returns> /// <returns>An <see cref="PackageInfo"/> containing available packages information.</returns>
[HttpGet("Packages")] [HttpGet("Packages")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[Produces(JsonDefaults.CamelCaseMediaType)]
public async Task<IEnumerable<PackageInfo>> GetPackages() public async Task<IEnumerable<PackageInfo>> GetPackages()
{ {
IEnumerable<PackageInfo> packages = await _installationManager.GetAvailablePackages().ConfigureAwait(false); IEnumerable<PackageInfo> packages = await _installationManager.GetAvailablePackages().ConfigureAwait(false);
@ -148,7 +146,6 @@ namespace Jellyfin.Api.Controllers
/// <returns>An <see cref="OkResult"/> containing the list of package repositories.</returns> /// <returns>An <see cref="OkResult"/> containing the list of package repositories.</returns>
[HttpGet("Repositories")] [HttpGet("Repositories")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[Produces(JsonDefaults.CamelCaseMediaType)]
public ActionResult<IEnumerable<RepositoryInfo>> GetRepositories() public ActionResult<IEnumerable<RepositoryInfo>> GetRepositories()
{ {
return _serverConfigurationManager.Configuration.PluginRepositories; return _serverConfigurationManager.Configuration.PluginRepositories;

@ -14,7 +14,6 @@ using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Json; using MediaBrowser.Common.Json;
using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Plugins;
using MediaBrowser.Common.Updates; using MediaBrowser.Common.Updates;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Net; using MediaBrowser.Model.Net;
using MediaBrowser.Model.Plugins; using MediaBrowser.Model.Plugins;
@ -130,7 +129,7 @@ namespace Jellyfin.Api.Controllers
/// <response code="204">Plugin enabled.</response> /// <response code="204">Plugin enabled.</response>
/// <response code="404">Plugin not found.</response> /// <response code="404">Plugin not found.</response>
/// <returns>An <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if the file could not be found.</returns> /// <returns>An <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if the file could not be found.</returns>
[HttpPost("{pluginId}/Enable")] [HttpPost("{pluginId}/{version}/Enable")]
[Authorize(Policy = Policies.RequiresElevation)] [Authorize(Policy = Policies.RequiresElevation)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
@ -153,7 +152,7 @@ namespace Jellyfin.Api.Controllers
/// <response code="204">Plugin disabled.</response> /// <response code="204">Plugin disabled.</response>
/// <response code="404">Plugin not found.</response> /// <response code="404">Plugin not found.</response>
/// <returns>An <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if the file could not be found.</returns> /// <returns>An <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if the file could not be found.</returns>
[HttpPost("{pluginId}/Disable")] [HttpPost("{pluginId}/{version}/Disable")]
[Authorize(Policy = Policies.RequiresElevation)] [Authorize(Policy = Policies.RequiresElevation)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
@ -176,11 +175,11 @@ namespace Jellyfin.Api.Controllers
/// <response code="204">Plugin uninstalled.</response> /// <response code="204">Plugin uninstalled.</response>
/// <response code="404">Plugin not found.</response> /// <response code="404">Plugin not found.</response>
/// <returns>An <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if the file could not be found.</returns> /// <returns>An <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if the file could not be found.</returns>
[HttpDelete("{pluginId}")] [HttpDelete("{pluginId}/{version}")]
[Authorize(Policy = Policies.RequiresElevation)] [Authorize(Policy = Policies.RequiresElevation)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult UninstallPlugin([FromRoute, Required] Guid pluginId, Version version) public ActionResult UninstallPlugin([FromRoute, Required] Guid pluginId, [FromRoute, Required] Version version)
{ {
if (!_pluginManager.TryGetPlugin(pluginId, version, out var plugin)) if (!_pluginManager.TryGetPlugin(pluginId, version, out var plugin))
{ {
@ -195,7 +194,6 @@ namespace Jellyfin.Api.Controllers
/// Gets plugin configuration. /// Gets plugin configuration.
/// </summary> /// </summary>
/// <param name="pluginId">Plugin id.</param> /// <param name="pluginId">Plugin id.</param>
/// <param name="version">Plugin version.</param>
/// <response code="200">Plugin configuration returned.</response> /// <response code="200">Plugin configuration returned.</response>
/// <response code="404">Plugin not found or plugin configuration not found.</response> /// <response code="404">Plugin not found or plugin configuration not found.</response>
/// <returns>Plugin configuration.</returns> /// <returns>Plugin configuration.</returns>
@ -203,9 +201,9 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesFile(MediaTypeNames.Application.Json)] [ProducesFile(MediaTypeNames.Application.Json)]
public ActionResult<BasePluginConfiguration> GetPluginConfiguration([FromRoute, Required] Guid pluginId, [FromRoute] Version? version) public ActionResult<BasePluginConfiguration> GetPluginConfiguration([FromRoute, Required] Guid pluginId)
{ {
if (_pluginManager.TryGetPlugin(pluginId, version, out var plugin) if (_pluginManager.TryGetPlugin(pluginId, null, out var plugin)
&& plugin!.Instance is IHasPluginConfiguration configPlugin) && plugin!.Instance is IHasPluginConfiguration configPlugin)
{ {
return configPlugin.Configuration; return configPlugin.Configuration;
@ -221,7 +219,6 @@ namespace Jellyfin.Api.Controllers
/// Accepts plugin configuration as JSON body. /// Accepts plugin configuration as JSON body.
/// </remarks> /// </remarks>
/// <param name="pluginId">Plugin id.</param> /// <param name="pluginId">Plugin id.</param>
/// <param name="version">Plugin version.</param>
/// <response code="204">Plugin configuration updated.</response> /// <response code="204">Plugin configuration updated.</response>
/// <response code="404">Plugin not found or plugin does not have configuration.</response> /// <response code="404">Plugin not found or plugin does not have configuration.</response>
/// <returns> /// <returns>
@ -232,9 +229,9 @@ namespace Jellyfin.Api.Controllers
[HttpPost("{pluginId}/Configuration")] [HttpPost("{pluginId}/Configuration")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ActionResult> UpdatePluginConfiguration([FromRoute, Required] Guid pluginId, [FromRoute] Version? version) public async Task<ActionResult> UpdatePluginConfiguration([FromRoute, Required] Guid pluginId)
{ {
if (!_pluginManager.TryGetPlugin(pluginId, version, out var plugin) if (!_pluginManager.TryGetPlugin(pluginId, null, out var plugin)
|| plugin?.Instance is not IHasPluginConfiguration configPlugin) || plugin?.Instance is not IHasPluginConfiguration configPlugin)
{ {
return NotFound(); return NotFound();
@ -258,12 +255,12 @@ namespace Jellyfin.Api.Controllers
/// <param name="version">Plugin version.</param> /// <param name="version">Plugin version.</param>
/// <response code="200">Plugin image returned.</response> /// <response code="200">Plugin image returned.</response>
/// <returns>Plugin's image.</returns> /// <returns>Plugin's image.</returns>
[HttpGet("{pluginId}/Image")] [HttpGet("{pluginId}/{version}/Image")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesImageFile] [ProducesImageFile]
[AllowAnonymous] [AllowAnonymous]
public ActionResult GetPluginImage([FromRoute, Required] Guid pluginId, [FromRoute] Version? version) public ActionResult GetPluginImage([FromRoute, Required] Guid pluginId, [FromRoute, Required] Version version)
{ {
if (!_pluginManager.TryGetPlugin(pluginId, version, out var plugin)) if (!_pluginManager.TryGetPlugin(pluginId, version, out var plugin))
{ {
@ -292,12 +289,12 @@ namespace Jellyfin.Api.Controllers
/// <param name="version">Plugin version.</param> /// <param name="version">Plugin version.</param>
/// <response code="200">Plugin image returned.</response> /// <response code="200">Plugin image returned.</response>
/// <returns>Plugin's image.</returns> /// <returns>Plugin's image.</returns>
[HttpGet("{pluginId}/StatusImage")] [HttpGet("{pluginId}/{version}/StatusImage")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesImageFile] [ProducesImageFile]
[AllowAnonymous] [AllowAnonymous]
public ActionResult GetPluginStatusImage([FromRoute, Required] Guid pluginId, [FromRoute] Version? version) public ActionResult GetPluginStatusImage([FromRoute, Required] Guid pluginId, [FromRoute, Required] Version version)
{ {
if (!_pluginManager.TryGetPlugin(pluginId, version, out var plugin)) if (!_pluginManager.TryGetPlugin(pluginId, version, out var plugin))
{ {
@ -316,7 +313,6 @@ namespace Jellyfin.Api.Controllers
/// Gets a plugin's manifest. /// Gets a plugin's manifest.
/// </summary> /// </summary>
/// <param name="pluginId">Plugin id.</param> /// <param name="pluginId">Plugin id.</param>
/// <param name="version">Plugin version.</param>
/// <response code="204">Plugin manifest returned.</response> /// <response code="204">Plugin manifest returned.</response>
/// <response code="404">Plugin not found.</response> /// <response code="404">Plugin not found.</response>
/// <returns> /// <returns>
@ -328,9 +324,9 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesFile(MediaTypeNames.Application.Json)] [ProducesFile(MediaTypeNames.Application.Json)]
public ActionResult<PluginManifest> GetPluginManifest([FromRoute, Required] Guid pluginId, [FromRoute] Version? version) public ActionResult<PluginManifest> GetPluginManifest([FromRoute, Required] Guid pluginId)
{ {
if (_pluginManager.TryGetPlugin(pluginId, version, out var plugin)) if (_pluginManager.TryGetPlugin(pluginId, null, out var plugin))
{ {
return Ok(plugin!.Manifest); return Ok(plugin!.Manifest);
} }

@ -12,6 +12,7 @@ namespace MediaBrowser.Model.Plugins
Disabled = -1, Disabled = -1,
NotSupported = -2, NotSupported = -2,
Malfunction = -3, Malfunction = -3,
Superceded = -4 Superceded = -4,
DeleteOnStartup = -5
} }
} }

Loading…
Cancel
Save