mirror of
				https://github.com/jellyfin/jellyfin.git
				synced 2025-11-03 19:17:24 -05:00 
			
		
		
		
	Add missing attributes, fix response codes, fix route parameter casing
This commit is contained in:
		
							parent
							
								
									deac459b62
								
							
						
					
					
						commit
						10ddbc34ec
					
				@ -68,7 +68,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <param name="key">Configuration key.</param>
 | 
			
		||||
        /// <response code="200">Configuration returned.</response>
 | 
			
		||||
        /// <returns>Configuration.</returns>
 | 
			
		||||
        [HttpGet("Configuration/{Key}")]
 | 
			
		||||
        [HttpGet("Configuration/{key}")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
        public ActionResult<object> GetNamedConfiguration([FromRoute] string key)
 | 
			
		||||
        {
 | 
			
		||||
@ -81,7 +81,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <param name="key">Configuration key.</param>
 | 
			
		||||
        /// <response code="204">Named configuration updated.</response>
 | 
			
		||||
        /// <returns>Update status.</returns>
 | 
			
		||||
        [HttpPost("Configuration/{Key}")]
 | 
			
		||||
        [HttpPost("Configuration/{key}")]
 | 
			
		||||
        [Authorize(Policy = Policies.RequiresElevation)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        public async Task<ActionResult> UpdateNamedConfiguration([FromRoute] string key)
 | 
			
		||||
 | 
			
		||||
@ -133,6 +133,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <returns>A <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if the device could not be found.</returns>
 | 
			
		||||
        [HttpDelete]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
			
		||||
        public ActionResult DeleteDevice([FromQuery, BindRequired] string id)
 | 
			
		||||
        {
 | 
			
		||||
            var existingDevice = _deviceManager.GetDevice(id);
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,5 @@
 | 
			
		||||
using System.ComponentModel.DataAnnotations;
 | 
			
		||||
using System.Diagnostics.CodeAnalysis;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using MediaBrowser.Controller.Persistence;
 | 
			
		||||
using MediaBrowser.Model.Entities;
 | 
			
		||||
@ -34,9 +35,8 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <param name="client">Client.</param>
 | 
			
		||||
        /// <response code="200">Display preferences retrieved.</response>
 | 
			
		||||
        /// <returns>An <see cref="OkResult"/> containing the display preferences on success, or a <see cref="NotFoundResult"/> if the display preferences could not be found.</returns>
 | 
			
		||||
        [HttpGet("{DisplayPreferencesId}")]
 | 
			
		||||
        [HttpGet("{displayPreferencesId}")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
			
		||||
        public ActionResult<DisplayPreferences> GetDisplayPreferences(
 | 
			
		||||
            [FromRoute] string displayPreferencesId,
 | 
			
		||||
            [FromQuery] [Required] string userId,
 | 
			
		||||
@ -52,30 +52,24 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <param name="userId">User Id.</param>
 | 
			
		||||
        /// <param name="client">Client.</param>
 | 
			
		||||
        /// <param name="displayPreferences">New Display Preferences object.</param>
 | 
			
		||||
        /// <response code="200">Display preferences updated.</response>
 | 
			
		||||
        /// <returns>An <see cref="OkResult"/> on success, or a <see cref="NotFoundResult"/> if the display preferences could not be found.</returns>
 | 
			
		||||
        [HttpPost("{DisplayPreferencesId}")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
        [ProducesResponseType(typeof(ModelStateDictionary), StatusCodes.Status400BadRequest)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
			
		||||
        /// <response code="204">Display preferences updated.</response>
 | 
			
		||||
        /// <returns>An <see cref="OkResult"/> on success.</returns>
 | 
			
		||||
        [HttpPost("{displayPreferencesId}")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "displayPreferencesId", Justification = "Imported from ServiceStack")]
 | 
			
		||||
        public ActionResult UpdateDisplayPreferences(
 | 
			
		||||
            [FromRoute] string displayPreferencesId,
 | 
			
		||||
            [FromQuery, BindRequired] string userId,
 | 
			
		||||
            [FromQuery, BindRequired] string client,
 | 
			
		||||
            [FromBody, BindRequired] DisplayPreferences displayPreferences)
 | 
			
		||||
        {
 | 
			
		||||
            if (displayPreferencesId == null)
 | 
			
		||||
            {
 | 
			
		||||
                // TODO - refactor so parameter doesn't exist or is actually used.
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            _displayPreferencesRepository.SaveDisplayPreferences(
 | 
			
		||||
                displayPreferences,
 | 
			
		||||
                userId,
 | 
			
		||||
                client,
 | 
			
		||||
                CancellationToken.None);
 | 
			
		||||
 | 
			
		||||
            return Ok();
 | 
			
		||||
            return NoContent();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -58,7 +58,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <response code="200">Image stream retrieved.</response>
 | 
			
		||||
        /// <response code="404">Image not found.</response>
 | 
			
		||||
        /// <returns>A <see cref="FileStreamResult"/> containing the image contents on success, or a <see cref="NotFoundResult"/> if the image could not be found.</returns>
 | 
			
		||||
        [HttpGet("General/{Name}/{Type}")]
 | 
			
		||||
        [HttpGet("General/{name}/{type}")]
 | 
			
		||||
        [AllowAnonymous]
 | 
			
		||||
        [Produces(MediaTypeNames.Application.Octet)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
@ -103,7 +103,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <response code="200">Image stream retrieved.</response>
 | 
			
		||||
        /// <response code="404">Image not found.</response>
 | 
			
		||||
        /// <returns>A <see cref="FileStreamResult"/> containing the image contents on success, or a <see cref="NotFoundResult"/> if the image could not be found.</returns>
 | 
			
		||||
        [HttpGet("Ratings/{Theme}/{Name}")]
 | 
			
		||||
        [HttpGet("Ratings/{theme}/{name}")]
 | 
			
		||||
        [AllowAnonymous]
 | 
			
		||||
        [Produces(MediaTypeNames.Application.Octet)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
@ -136,7 +136,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <response code="200">Image stream retrieved.</response>
 | 
			
		||||
        /// <response code="404">Image not found.</response>
 | 
			
		||||
        /// <returns>A <see cref="FileStreamResult"/> containing the image contents on success, or a <see cref="NotFoundResult"/> if the image could not be found.</returns>
 | 
			
		||||
        [HttpGet("MediaInfo/{Theme}/{Name}")]
 | 
			
		||||
        [HttpGet("MediaInfo/{theme}/{name}")]
 | 
			
		||||
        [AllowAnonymous]
 | 
			
		||||
        [Produces(MediaTypeNames.Application.Octet)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,4 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.ComponentModel;
 | 
			
		||||
using System.Diagnostics.CodeAnalysis;
 | 
			
		||||
using MediaBrowser.Controller.Library;
 | 
			
		||||
@ -40,29 +41,29 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Refreshes metadata for an item.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">Item id.</param>
 | 
			
		||||
        /// <param name="itemId">Item id.</param>
 | 
			
		||||
        /// <param name="metadataRefreshMode">(Optional) Specifies the metadata refresh mode.</param>
 | 
			
		||||
        /// <param name="imageRefreshMode">(Optional) Specifies the image refresh mode.</param>
 | 
			
		||||
        /// <param name="replaceAllMetadata">(Optional) Determines if metadata should be replaced. Only applicable if mode is FullRefresh.</param>
 | 
			
		||||
        /// <param name="replaceAllImages">(Optional) Determines if images should be replaced. Only applicable if mode is FullRefresh.</param>
 | 
			
		||||
        /// <param name="recursive">(Unused) Indicates if the refresh should occur recursively.</param>
 | 
			
		||||
        /// <response code="200">Item metadata refresh queued.</response>
 | 
			
		||||
        /// <response code="204">Item metadata refresh queued.</response>
 | 
			
		||||
        /// <response code="404">Item to refresh not found.</response>
 | 
			
		||||
        /// <returns>An <see cref="OkResult"/> on success, or a <see cref="NotFoundResult"/> if the item could not be found.</returns>
 | 
			
		||||
        [HttpPost("{Id}/Refresh")]
 | 
			
		||||
        [HttpPost("{itemId}/Refresh")]
 | 
			
		||||
        [Description("Refreshes metadata for an item.")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
			
		||||
        [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "recursive", Justification = "Imported from ServiceStack")]
 | 
			
		||||
        public ActionResult Post(
 | 
			
		||||
            [FromRoute] string id,
 | 
			
		||||
            [FromRoute] Guid itemId,
 | 
			
		||||
            [FromQuery] MetadataRefreshMode metadataRefreshMode = MetadataRefreshMode.None,
 | 
			
		||||
            [FromQuery] MetadataRefreshMode imageRefreshMode = MetadataRefreshMode.None,
 | 
			
		||||
            [FromQuery] bool replaceAllMetadata = false,
 | 
			
		||||
            [FromQuery] bool replaceAllImages = false,
 | 
			
		||||
            [FromQuery] bool recursive = false)
 | 
			
		||||
        {
 | 
			
		||||
            var item = _libraryManager.GetItemById(id);
 | 
			
		||||
            var item = _libraryManager.GetItemById(itemId);
 | 
			
		||||
            if (item == null)
 | 
			
		||||
            {
 | 
			
		||||
                return NotFound();
 | 
			
		||||
@ -82,7 +83,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            _providerManager.QueueRefresh(item.Id, refreshOptions, RefreshPriority.High);
 | 
			
		||||
            return Ok();
 | 
			
		||||
            return NoContent();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -42,7 +42,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <param name="limit">An optional limit on the number of notifications returned.</param>
 | 
			
		||||
        /// <response code="200">Notifications returned.</response>
 | 
			
		||||
        /// <returns>An <see cref="OkResult"/> containing a list of notifications.</returns>
 | 
			
		||||
        [HttpGet("{UserID}")]
 | 
			
		||||
        [HttpGet("{userId}")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
        [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Imported from ServiceStack")]
 | 
			
		||||
        [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "isRead", Justification = "Imported from ServiceStack")]
 | 
			
		||||
@ -63,7 +63,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <param name="userId">The user's ID.</param>
 | 
			
		||||
        /// <response code="200">Summary of user's notifications returned.</response>
 | 
			
		||||
        /// <returns>An <cref see="OkResult"/> containing a summary of the users notifications.</returns>
 | 
			
		||||
        [HttpGet("{UserID}/Summary")]
 | 
			
		||||
        [HttpGet("{userId}/Summary")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
        [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Imported from ServiceStack")]
 | 
			
		||||
        public ActionResult<NotificationsSummaryDto> GetNotificationsSummary(
 | 
			
		||||
@ -138,7 +138,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <param name="ids">A comma-separated list of the IDs of notifications which should be set as read.</param>
 | 
			
		||||
        /// <response code="204">Notifications set as read.</response>
 | 
			
		||||
        /// <returns>A <cref see="NoContentResult"/>.</returns>
 | 
			
		||||
        [HttpPost("{UserID}/Read")]
 | 
			
		||||
        [HttpPost("{userId}/Read")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Imported from ServiceStack")]
 | 
			
		||||
        [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "ids", Justification = "Imported from ServiceStack")]
 | 
			
		||||
@ -156,7 +156,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <param name="ids">A comma-separated list of the IDs of notifications which should be set as unread.</param>
 | 
			
		||||
        /// <response code="204">Notifications set as unread.</response>
 | 
			
		||||
        /// <returns>A <cref see="NoContentResult"/>.</returns>
 | 
			
		||||
        [HttpPost("{UserID}/Unread")]
 | 
			
		||||
        [HttpPost("{userId}/Unread")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Imported from ServiceStack")]
 | 
			
		||||
        [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "ids", Justification = "Imported from ServiceStack")]
 | 
			
		||||
 | 
			
		||||
@ -35,9 +35,10 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="name">The name of the package.</param>
 | 
			
		||||
        /// <param name="assemblyGuid">The GUID of the associated assembly.</param>
 | 
			
		||||
        /// <response code="200">Package retrieved.</response>
 | 
			
		||||
        /// <returns>A <see cref="PackageInfo"/> containing package information.</returns>
 | 
			
		||||
        [HttpGet("/{Name}")]
 | 
			
		||||
        [ProducesResponseType(typeof(PackageInfo), StatusCodes.Status200OK)]
 | 
			
		||||
        [HttpGet("/{name}")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
        public async Task<ActionResult<PackageInfo>> GetPackageInfo(
 | 
			
		||||
            [FromRoute] [Required] string name,
 | 
			
		||||
            [FromQuery] string? assemblyGuid)
 | 
			
		||||
@ -54,9 +55,10 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets available packages.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <response code="200">Available packages returned.</response>
 | 
			
		||||
        /// <returns>An <see cref="PackageInfo"/> containing available packages information.</returns>
 | 
			
		||||
        [HttpGet]
 | 
			
		||||
        [ProducesResponseType(typeof(PackageInfo[]), StatusCodes.Status200OK)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
        public async Task<IEnumerable<PackageInfo>> GetPackages()
 | 
			
		||||
        {
 | 
			
		||||
            IEnumerable<PackageInfo> packages = await _installationManager.GetAvailablePackages().ConfigureAwait(false);
 | 
			
		||||
@ -73,7 +75,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <response code="204">Package found.</response>
 | 
			
		||||
        /// <response code="404">Package not found.</response>
 | 
			
		||||
        /// <returns>A <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if the package could not be found.</returns>
 | 
			
		||||
        [HttpPost("/Installed/{Name}")]
 | 
			
		||||
        [HttpPost("/Installed/{name}")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
			
		||||
        [Authorize(Policy = Policies.RequiresElevation)]
 | 
			
		||||
@ -102,17 +104,16 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Cancels a package installation.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">Installation Id.</param>
 | 
			
		||||
        /// <param name="packageId">Installation Id.</param>
 | 
			
		||||
        /// <response code="204">Installation cancelled.</response>
 | 
			
		||||
        /// <returns>A <see cref="NoContentResult"/> on successfully cancelling a package installation.</returns>
 | 
			
		||||
        [HttpDelete("/Installing/{id}")]
 | 
			
		||||
        [HttpDelete("/Installing/{packageId}")]
 | 
			
		||||
        [Authorize(Policy = Policies.RequiresElevation)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        public IActionResult CancelPackageInstallation(
 | 
			
		||||
            [FromRoute] [Required] string id)
 | 
			
		||||
            [FromRoute] [Required] Guid packageId)
 | 
			
		||||
        {
 | 
			
		||||
            _installationManager.CancelInstallation(new Guid(id));
 | 
			
		||||
 | 
			
		||||
            _installationManager.CancelInstallation(packageId);
 | 
			
		||||
            return NoContent();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -11,6 +11,7 @@ using MediaBrowser.Common.Plugins;
 | 
			
		||||
using MediaBrowser.Common.Updates;
 | 
			
		||||
using MediaBrowser.Model.Plugins;
 | 
			
		||||
using Microsoft.AspNetCore.Authorization;
 | 
			
		||||
using Microsoft.AspNetCore.Http;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
 | 
			
		||||
 | 
			
		||||
@ -45,6 +46,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <response code="200">Installed plugins returned.</response>
 | 
			
		||||
        /// <returns>List of currently installed plugins.</returns>
 | 
			
		||||
        [HttpGet]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
        [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "isAppStoreEnabled", Justification = "Imported from ServiceStack")]
 | 
			
		||||
        public ActionResult<IEnumerable<PluginInfo>> GetPlugins([FromRoute] bool? isAppStoreEnabled)
 | 
			
		||||
        {
 | 
			
		||||
@ -55,11 +57,13 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// Uninstalls a plugin.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="pluginId">Plugin id.</param>
 | 
			
		||||
        /// <response code="200">Plugin uninstalled.</response>
 | 
			
		||||
        /// <response code="204">Plugin uninstalled.</response>
 | 
			
		||||
        /// <response code="404">Plugin not found.</response>
 | 
			
		||||
        /// <returns>An <see cref="OkResult"/> on success, or a <see cref="NotFoundResult"/> if the file could not be found.</returns>
 | 
			
		||||
        [HttpDelete("{pluginId}")]
 | 
			
		||||
        [Authorize(Policy = Policies.RequiresElevation)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
			
		||||
        public ActionResult UninstallPlugin([FromRoute] Guid pluginId)
 | 
			
		||||
        {
 | 
			
		||||
            var plugin = _appHost.Plugins.FirstOrDefault(p => p.Id == pluginId);
 | 
			
		||||
@ -69,7 +73,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            _installationManager.UninstallPlugin(plugin);
 | 
			
		||||
            return Ok();
 | 
			
		||||
            return NoContent();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
@ -80,6 +84,8 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <response code="404">Plugin not found or plugin configuration not found.</response>
 | 
			
		||||
        /// <returns>Plugin configuration.</returns>
 | 
			
		||||
        [HttpGet("{pluginId}/Configuration")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
			
		||||
        public ActionResult<BasePluginConfiguration> GetPluginConfiguration([FromRoute] Guid pluginId)
 | 
			
		||||
        {
 | 
			
		||||
            if (!(_appHost.Plugins.FirstOrDefault(p => p.Id == pluginId) is IHasPluginConfiguration plugin))
 | 
			
		||||
@ -97,14 +103,16 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// Accepts plugin configuration as JSON body.
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        /// <param name="pluginId">Plugin id.</param>
 | 
			
		||||
        /// <response code="200">Plugin configuration updated.</response>
 | 
			
		||||
        /// <response code="200">Plugin not found or plugin does not have configuration.</response>
 | 
			
		||||
        /// <response code="204">Plugin configuration updated.</response>
 | 
			
		||||
        /// <response code="404">Plugin not found or plugin does not have configuration.</response>
 | 
			
		||||
        /// <returns>
 | 
			
		||||
        /// A <see cref="Task" /> that represents the asynchronous operation to update plugin configuration.
 | 
			
		||||
        ///    The task result contains an <see cref="OkResult"/> indicating success, or <see cref="NotFoundResult"/>
 | 
			
		||||
        ///    when plugin not found or plugin doesn't have configuration.
 | 
			
		||||
        /// </returns>
 | 
			
		||||
        [HttpPost("{pluginId}/Configuration")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
			
		||||
        public async Task<ActionResult> UpdatePluginConfiguration([FromRoute] Guid pluginId)
 | 
			
		||||
        {
 | 
			
		||||
            if (!(_appHost.Plugins.FirstOrDefault(p => p.Id == pluginId) is IHasPluginConfiguration plugin))
 | 
			
		||||
@ -116,7 +124,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
                .ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
            plugin.UpdateConfiguration(configuration);
 | 
			
		||||
            return Ok();
 | 
			
		||||
            return NoContent();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
@ -126,6 +134,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <returns>Plugin security info.</returns>
 | 
			
		||||
        [Obsolete("This endpoint should not be used.")]
 | 
			
		||||
        [HttpGet("SecurityInfo")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
        public ActionResult<PluginSecurityInfo> GetPluginSecurityInfo()
 | 
			
		||||
        {
 | 
			
		||||
            return new PluginSecurityInfo
 | 
			
		||||
@ -139,14 +148,15 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// Updates plugin security info.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="pluginSecurityInfo">Plugin security info.</param>
 | 
			
		||||
        /// <response code="200">Plugin security info updated.</response>
 | 
			
		||||
        /// <returns>An <see cref="OkResult"/>.</returns>
 | 
			
		||||
        /// <response code="204">Plugin security info updated.</response>
 | 
			
		||||
        /// <returns>An <see cref="NoContentResult"/>.</returns>
 | 
			
		||||
        [Obsolete("This endpoint should not be used.")]
 | 
			
		||||
        [HttpPost("SecurityInfo")]
 | 
			
		||||
        [Authorize(Policy = Policies.RequiresElevation)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        public ActionResult UpdatePluginSecurityInfo([FromBody, BindRequired] PluginSecurityInfo pluginSecurityInfo)
 | 
			
		||||
        {
 | 
			
		||||
            return Ok();
 | 
			
		||||
            return NoContent();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
@ -157,6 +167,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <returns>Mb registration record.</returns>
 | 
			
		||||
        [Obsolete("This endpoint should not be used.")]
 | 
			
		||||
        [HttpPost("RegistrationRecords/{name}")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
        public ActionResult<MBRegistrationRecord> GetRegistrationStatus([FromRoute] string name)
 | 
			
		||||
        {
 | 
			
		||||
            return new MBRegistrationRecord
 | 
			
		||||
@ -178,6 +189,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <exception cref="NotImplementedException">This endpoint is not implemented.</exception>
 | 
			
		||||
        [Obsolete("Paid plugins are not supported")]
 | 
			
		||||
        [HttpGet("/Registrations/{name}")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status501NotImplemented)]
 | 
			
		||||
        public ActionResult GetRegistration([FromRoute] string name)
 | 
			
		||||
        {
 | 
			
		||||
            // TODO Once we have proper apps and plugins and decide to break compatibility with paid plugins,
 | 
			
		||||
 | 
			
		||||
@ -55,7 +55,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets available remote images for an item.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">Item Id.</param>
 | 
			
		||||
        /// <param name="itemId">Item Id.</param>
 | 
			
		||||
        /// <param name="type">The image type.</param>
 | 
			
		||||
        /// <param name="startIndex">Optional. The record index to start at. All items with a lower index will be dropped from the results.</param>
 | 
			
		||||
        /// <param name="limit">Optional. The maximum number of records to return.</param>
 | 
			
		||||
@ -64,18 +64,18 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <response code="200">Remote Images returned.</response>
 | 
			
		||||
        /// <response code="404">Item not found.</response>
 | 
			
		||||
        /// <returns>Remote Image Result.</returns>
 | 
			
		||||
        [HttpGet("{Id}/RemoteImages")]
 | 
			
		||||
        [HttpGet("{itemId}/RemoteImages")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
			
		||||
        public async Task<ActionResult<RemoteImageResult>> GetRemoteImages(
 | 
			
		||||
            [FromRoute] string id,
 | 
			
		||||
            [FromRoute] Guid itemId,
 | 
			
		||||
            [FromQuery] ImageType? type,
 | 
			
		||||
            [FromQuery] int? startIndex,
 | 
			
		||||
            [FromQuery] int? limit,
 | 
			
		||||
            [FromQuery] string providerName,
 | 
			
		||||
            [FromQuery] bool includeAllLanguages)
 | 
			
		||||
        {
 | 
			
		||||
            var item = _libraryManager.GetItemById(id);
 | 
			
		||||
            var item = _libraryManager.GetItemById(itemId);
 | 
			
		||||
            if (item == null)
 | 
			
		||||
            {
 | 
			
		||||
                return NotFound();
 | 
			
		||||
@ -123,16 +123,16 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets available remote image providers for an item.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">Item Id.</param>
 | 
			
		||||
        /// <param name="itemId">Item Id.</param>
 | 
			
		||||
        /// <response code="200">Returned remote image providers.</response>
 | 
			
		||||
        /// <response code="404">Item not found.</response>
 | 
			
		||||
        /// <returns>List of remote image providers.</returns>
 | 
			
		||||
        [HttpGet("{Id}/RemoteImages/Providers")]
 | 
			
		||||
        [HttpGet("{itemId}/RemoteImages/Providers")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
			
		||||
        public ActionResult<IEnumerable<ImageProviderInfo>> GetRemoteImageProviders([FromRoute] string id)
 | 
			
		||||
        public ActionResult<IEnumerable<ImageProviderInfo>> GetRemoteImageProviders([FromRoute] Guid itemId)
 | 
			
		||||
        {
 | 
			
		||||
            var item = _libraryManager.GetItemById(id);
 | 
			
		||||
            var item = _libraryManager.GetItemById(itemId);
 | 
			
		||||
            if (item == null)
 | 
			
		||||
            {
 | 
			
		||||
                return NotFound();
 | 
			
		||||
@ -195,21 +195,21 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Downloads a remote image for an item.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">Item Id.</param>
 | 
			
		||||
        /// <param name="itemId">Item Id.</param>
 | 
			
		||||
        /// <param name="type">The image type.</param>
 | 
			
		||||
        /// <param name="imageUrl">The image url.</param>
 | 
			
		||||
        /// <response code="200">Remote image downloaded.</response>
 | 
			
		||||
        /// <response code="204">Remote image downloaded.</response>
 | 
			
		||||
        /// <response code="404">Remote image not found.</response>
 | 
			
		||||
        /// <returns>Download status.</returns>
 | 
			
		||||
        [HttpPost("{Id}/RemoteImages/Download")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
        [HttpPost("{itemId}/RemoteImages/Download")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
			
		||||
        public async Task<ActionResult> DownloadRemoteImage(
 | 
			
		||||
            [FromRoute] string id,
 | 
			
		||||
            [FromRoute] Guid itemId,
 | 
			
		||||
            [FromQuery, BindRequired] ImageType type,
 | 
			
		||||
            [FromQuery] string imageUrl)
 | 
			
		||||
        {
 | 
			
		||||
            var item = _libraryManager.GetItemById(id);
 | 
			
		||||
            var item = _libraryManager.GetItemById(itemId);
 | 
			
		||||
            if (item == null)
 | 
			
		||||
            {
 | 
			
		||||
                return NotFound();
 | 
			
		||||
@ -219,7 +219,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
                .ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
            item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None);
 | 
			
		||||
            return Ok();
 | 
			
		||||
            return NoContent();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
 | 
			
		||||
@ -113,16 +113,16 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Instructs a session to browse to an item or view.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The session Id.</param>
 | 
			
		||||
        /// <param name="sessionId">The session Id.</param>
 | 
			
		||||
        /// <param name="itemType">The type of item to browse to.</param>
 | 
			
		||||
        /// <param name="itemId">The Id of the item.</param>
 | 
			
		||||
        /// <param name="itemName">The name of the item.</param>
 | 
			
		||||
        /// <response code="204">Instruction sent to session.</response>
 | 
			
		||||
        /// <returns>A <see cref="NoContentResult"/>.</returns>
 | 
			
		||||
        [HttpPost("/Sessions/{id}/Viewing")]
 | 
			
		||||
        [HttpPost("/Sessions/{sessionId}/Viewing")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        public ActionResult DisplayContent(
 | 
			
		||||
            [FromRoute] string id,
 | 
			
		||||
            [FromRoute] string sessionId,
 | 
			
		||||
            [FromQuery] string itemType,
 | 
			
		||||
            [FromQuery] string itemId,
 | 
			
		||||
            [FromQuery] string itemName)
 | 
			
		||||
@ -136,7 +136,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
 | 
			
		||||
            _sessionManager.SendBrowseCommand(
 | 
			
		||||
                RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id,
 | 
			
		||||
                id,
 | 
			
		||||
                sessionId,
 | 
			
		||||
                command,
 | 
			
		||||
                CancellationToken.None);
 | 
			
		||||
 | 
			
		||||
@ -146,17 +146,17 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Instructs a session to play an item.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The session id.</param>
 | 
			
		||||
        /// <param name="sessionId">The session id.</param>
 | 
			
		||||
        /// <param name="itemIds">The ids of the items to play, comma delimited.</param>
 | 
			
		||||
        /// <param name="startPositionTicks">The starting position of the first item.</param>
 | 
			
		||||
        /// <param name="playCommand">The type of play command to issue (PlayNow, PlayNext, PlayLast). Clients who have not yet implemented play next and play last may play now.</param>
 | 
			
		||||
        /// <param name="playRequest">The <see cref="PlayRequest"/>.</param>
 | 
			
		||||
        /// <response code="204">Instruction sent to session.</response>
 | 
			
		||||
        /// <returns>A <see cref="NoContentResult"/>.</returns>
 | 
			
		||||
        [HttpPost("/Sessions/{id}/Playing")]
 | 
			
		||||
        [HttpPost("/Sessions/{sessionId}/Playing")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        public ActionResult Play(
 | 
			
		||||
            [FromRoute] string id,
 | 
			
		||||
            [FromRoute] string sessionId,
 | 
			
		||||
            [FromQuery] Guid[] itemIds,
 | 
			
		||||
            [FromQuery] long? startPositionTicks,
 | 
			
		||||
            [FromQuery] PlayCommand playCommand,
 | 
			
		||||
@ -173,7 +173,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
 | 
			
		||||
            _sessionManager.SendPlayCommand(
 | 
			
		||||
                RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id,
 | 
			
		||||
                id,
 | 
			
		||||
                sessionId,
 | 
			
		||||
                playRequest,
 | 
			
		||||
                CancellationToken.None);
 | 
			
		||||
 | 
			
		||||
@ -183,19 +183,19 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Issues a playstate command to a client.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The session id.</param>
 | 
			
		||||
        /// <param name="sessionId">The session id.</param>
 | 
			
		||||
        /// <param name="playstateRequest">The <see cref="PlaystateRequest"/>.</param>
 | 
			
		||||
        /// <response code="204">Playstate command sent to session.</response>
 | 
			
		||||
        /// <returns>A <see cref="NoContentResult"/>.</returns>
 | 
			
		||||
        [HttpPost("/Sessions/{id}/Playing/{command}")]
 | 
			
		||||
        [HttpPost("/Sessions/{sessionId}/Playing/{command}")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        public ActionResult SendPlaystateCommand(
 | 
			
		||||
            [FromRoute] string id,
 | 
			
		||||
            [FromRoute] string sessionId,
 | 
			
		||||
            [FromBody] PlaystateRequest playstateRequest)
 | 
			
		||||
        {
 | 
			
		||||
            _sessionManager.SendPlaystateCommand(
 | 
			
		||||
                RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id,
 | 
			
		||||
                id,
 | 
			
		||||
                sessionId,
 | 
			
		||||
                playstateRequest,
 | 
			
		||||
                CancellationToken.None);
 | 
			
		||||
 | 
			
		||||
@ -205,14 +205,14 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Issues a system command to a client.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The session id.</param>
 | 
			
		||||
        /// <param name="sessionId">The session id.</param>
 | 
			
		||||
        /// <param name="command">The command to send.</param>
 | 
			
		||||
        /// <response code="204">System command sent to session.</response>
 | 
			
		||||
        /// <returns>A <see cref="NoContentResult"/>.</returns>
 | 
			
		||||
        [HttpPost("/Sessions/{id}/System/{Command}")]
 | 
			
		||||
        [HttpPost("/Sessions/{sessionId}/System/{command}")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        public ActionResult SendSystemCommand(
 | 
			
		||||
            [FromRoute] string id,
 | 
			
		||||
            [FromRoute] string sessionId,
 | 
			
		||||
            [FromRoute] string command)
 | 
			
		||||
        {
 | 
			
		||||
            var name = command;
 | 
			
		||||
@ -228,7 +228,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
                ControllingUserId = currentSession.UserId
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            _sessionManager.SendGeneralCommand(currentSession.Id, id, generalCommand, CancellationToken.None);
 | 
			
		||||
            _sessionManager.SendGeneralCommand(currentSession.Id, sessionId, generalCommand, CancellationToken.None);
 | 
			
		||||
 | 
			
		||||
            return NoContent();
 | 
			
		||||
        }
 | 
			
		||||
@ -236,14 +236,14 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Issues a general command to a client.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The session id.</param>
 | 
			
		||||
        /// <param name="sessionId">The session id.</param>
 | 
			
		||||
        /// <param name="command">The command to send.</param>
 | 
			
		||||
        /// <response code="204">General command sent to session.</response>
 | 
			
		||||
        /// <returns>A <see cref="NoContentResult"/>.</returns>
 | 
			
		||||
        [HttpPost("/Sessions/{id}/Command/{Command}")]
 | 
			
		||||
        [HttpPost("/Sessions/{sessionId}/Command/{Command}")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        public ActionResult SendGeneralCommand(
 | 
			
		||||
            [FromRoute] string id,
 | 
			
		||||
            [FromRoute] string sessionId,
 | 
			
		||||
            [FromRoute] string command)
 | 
			
		||||
        {
 | 
			
		||||
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authContext, Request);
 | 
			
		||||
@ -254,7 +254,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
                ControllingUserId = currentSession.UserId
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            _sessionManager.SendGeneralCommand(currentSession.Id, id, generalCommand, CancellationToken.None);
 | 
			
		||||
            _sessionManager.SendGeneralCommand(currentSession.Id, sessionId, generalCommand, CancellationToken.None);
 | 
			
		||||
 | 
			
		||||
            return NoContent();
 | 
			
		||||
        }
 | 
			
		||||
@ -262,14 +262,14 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Issues a full general command to a client.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The session id.</param>
 | 
			
		||||
        /// <param name="sessionId">The session id.</param>
 | 
			
		||||
        /// <param name="command">The <see cref="GeneralCommand"/>.</param>
 | 
			
		||||
        /// <response code="204">Full general command sent to session.</response>
 | 
			
		||||
        /// <returns>A <see cref="NoContentResult"/>.</returns>
 | 
			
		||||
        [HttpPost("/Sessions/{id}/Command")]
 | 
			
		||||
        [HttpPost("/Sessions/{sessionId}/Command")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        public ActionResult SendFullGeneralCommand(
 | 
			
		||||
            [FromRoute] string id,
 | 
			
		||||
            [FromRoute] string sessionId,
 | 
			
		||||
            [FromBody, Required] GeneralCommand command)
 | 
			
		||||
        {
 | 
			
		||||
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authContext, Request);
 | 
			
		||||
@ -283,7 +283,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
 | 
			
		||||
            _sessionManager.SendGeneralCommand(
 | 
			
		||||
                currentSession.Id,
 | 
			
		||||
                id,
 | 
			
		||||
                sessionId,
 | 
			
		||||
                command,
 | 
			
		||||
                CancellationToken.None);
 | 
			
		||||
 | 
			
		||||
@ -293,16 +293,16 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Issues a command to a client to display a message to the user.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The session id.</param>
 | 
			
		||||
        /// <param name="sessionId">The session id.</param>
 | 
			
		||||
        /// <param name="text">The message test.</param>
 | 
			
		||||
        /// <param name="header">The message header.</param>
 | 
			
		||||
        /// <param name="timeoutMs">The message timeout. If omitted the user will have to confirm viewing the message.</param>
 | 
			
		||||
        /// <response code="204">Message sent.</response>
 | 
			
		||||
        /// <returns>A <see cref="NoContentResult"/>.</returns>
 | 
			
		||||
        [HttpPost("/Sessions/{id}/Message")]
 | 
			
		||||
        [HttpPost("/Sessions/{sessionId}/Message")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        public ActionResult SendMessageCommand(
 | 
			
		||||
            [FromRoute] string id,
 | 
			
		||||
            [FromRoute] string sessionId,
 | 
			
		||||
            [FromQuery] string text,
 | 
			
		||||
            [FromQuery] string header,
 | 
			
		||||
            [FromQuery] long? timeoutMs)
 | 
			
		||||
@ -314,7 +314,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
                Text = text
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            _sessionManager.SendMessageCommand(RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id, id, command, CancellationToken.None);
 | 
			
		||||
            _sessionManager.SendMessageCommand(RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id, sessionId, command, CancellationToken.None);
 | 
			
		||||
 | 
			
		||||
            return NoContent();
 | 
			
		||||
        }
 | 
			
		||||
@ -322,34 +322,34 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Adds an additional user to a session.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The session id.</param>
 | 
			
		||||
        /// <param name="sessionId">The session id.</param>
 | 
			
		||||
        /// <param name="userId">The user id.</param>
 | 
			
		||||
        /// <response code="204">User added to session.</response>
 | 
			
		||||
        /// <returns>A <see cref="NoContentResult"/>.</returns>
 | 
			
		||||
        [HttpPost("/Sessions/{id}/User/{userId}")]
 | 
			
		||||
        [HttpPost("/Sessions/{sessionId}/User/{userId}")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        public ActionResult AddUserToSession(
 | 
			
		||||
            [FromRoute] string id,
 | 
			
		||||
            [FromRoute] string sessionId,
 | 
			
		||||
            [FromRoute] Guid userId)
 | 
			
		||||
        {
 | 
			
		||||
            _sessionManager.AddAdditionalUser(id, userId);
 | 
			
		||||
            _sessionManager.AddAdditionalUser(sessionId, userId);
 | 
			
		||||
            return NoContent();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Removes an additional user from a session.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The session id.</param>
 | 
			
		||||
        /// <param name="sessionId">The session id.</param>
 | 
			
		||||
        /// <param name="userId">The user id.</param>
 | 
			
		||||
        /// <response code="204">User removed from session.</response>
 | 
			
		||||
        /// <returns>A <see cref="NoContentResult"/>.</returns>
 | 
			
		||||
        [HttpDelete("/Sessions/{id}/User/{userId}")]
 | 
			
		||||
        [HttpDelete("/Sessions/{sessionId}/User/{userId}")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        public ActionResult RemoveUserFromSession(
 | 
			
		||||
            [FromRoute] string id,
 | 
			
		||||
            [FromRoute] string sessionId,
 | 
			
		||||
            [FromRoute] Guid userId)
 | 
			
		||||
        {
 | 
			
		||||
            _sessionManager.RemoveAdditionalUser(id, userId);
 | 
			
		||||
            _sessionManager.RemoveAdditionalUser(sessionId, userId);
 | 
			
		||||
            return NoContent();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -75,20 +75,20 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Deletes an external subtitle file.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The item id.</param>
 | 
			
		||||
        /// <param name="itemId">The item id.</param>
 | 
			
		||||
        /// <param name="index">The index of the subtitle file.</param>
 | 
			
		||||
        /// <response code="204">Subtitle deleted.</response>
 | 
			
		||||
        /// <response code="404">Item not found.</response>
 | 
			
		||||
        /// <returns>A <see cref="NoContentResult"/>.</returns>
 | 
			
		||||
        [HttpDelete("/Videos/{id}/Subtitles/{index}")]
 | 
			
		||||
        [HttpDelete("/Videos/{itemId}/Subtitles/{index}")]
 | 
			
		||||
        [Authorize(Policy = Policies.RequiresElevation)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
			
		||||
        public ActionResult<Task> DeleteSubtitle(
 | 
			
		||||
            [FromRoute] Guid id,
 | 
			
		||||
            [FromRoute] Guid itemId,
 | 
			
		||||
            [FromRoute] int index)
 | 
			
		||||
        {
 | 
			
		||||
            var item = _libraryManager.GetItemById(id);
 | 
			
		||||
            var item = _libraryManager.GetItemById(itemId);
 | 
			
		||||
 | 
			
		||||
            if (item == null)
 | 
			
		||||
            {
 | 
			
		||||
@ -102,20 +102,20 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Search remote subtitles.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The item id.</param>
 | 
			
		||||
        /// <param name="itemId">The item id.</param>
 | 
			
		||||
        /// <param name="language">The language of the subtitles.</param>
 | 
			
		||||
        /// <param name="isPerfectMatch">Optional. Only show subtitles which are a perfect match.</param>
 | 
			
		||||
        /// <response code="200">Subtitles retrieved.</response>
 | 
			
		||||
        /// <returns>An array of <see cref="RemoteSubtitleInfo"/>.</returns>
 | 
			
		||||
        [HttpGet("/Items/{id}/RemoteSearch/Subtitles/{language}")]
 | 
			
		||||
        [HttpGet("/Items/{itemId}/RemoteSearch/Subtitles/{language}")]
 | 
			
		||||
        [Authorize(Policy = Policies.DefaultAuthorization)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
        public async Task<ActionResult<IEnumerable<RemoteSubtitleInfo>>> SearchRemoteSubtitles(
 | 
			
		||||
            [FromRoute] Guid id,
 | 
			
		||||
            [FromRoute] Guid itemId,
 | 
			
		||||
            [FromRoute] string language,
 | 
			
		||||
            [FromQuery] bool? isPerfectMatch)
 | 
			
		||||
        {
 | 
			
		||||
            var video = (Video)_libraryManager.GetItemById(id);
 | 
			
		||||
            var video = (Video)_libraryManager.GetItemById(itemId);
 | 
			
		||||
 | 
			
		||||
            return await _subtitleManager.SearchSubtitles(video, language, isPerfectMatch, CancellationToken.None).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
@ -123,18 +123,18 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Downloads a remote subtitle.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The item id.</param>
 | 
			
		||||
        /// <param name="itemId">The item id.</param>
 | 
			
		||||
        /// <param name="subtitleId">The subtitle id.</param>
 | 
			
		||||
        /// <response code="204">Subtitle downloaded.</response>
 | 
			
		||||
        /// <returns>A <see cref="NoContentResult"/>.</returns>
 | 
			
		||||
        [HttpPost("/Items/{id}/RemoteSearch/Subtitles/{subtitleId}")]
 | 
			
		||||
        [HttpPost("/Items/{itemId}/RemoteSearch/Subtitles/{subtitleId}")]
 | 
			
		||||
        [Authorize(Policy = Policies.DefaultAuthorization)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        public async Task<ActionResult> DownloadRemoteSubtitles(
 | 
			
		||||
            [FromRoute] Guid id,
 | 
			
		||||
            [FromRoute] Guid itemId,
 | 
			
		||||
            [FromRoute] string subtitleId)
 | 
			
		||||
        {
 | 
			
		||||
            var video = (Video)_libraryManager.GetItemById(id);
 | 
			
		||||
            var video = (Video)_libraryManager.GetItemById(itemId);
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
@ -171,28 +171,28 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets subtitles in a specified format.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The item id.</param>
 | 
			
		||||
        /// <param name="itemId">The item id.</param>
 | 
			
		||||
        /// <param name="mediaSourceId">The media source id.</param>
 | 
			
		||||
        /// <param name="index">The subtitle stream index.</param>
 | 
			
		||||
        /// <param name="format">The format of the returned subtitle.</param>
 | 
			
		||||
        /// <param name="startPositionTicks">Optional. The start position of the subtitle in ticks.</param>
 | 
			
		||||
        /// <param name="endPositionTicks">Optional. The end position of the subtitle in ticks.</param>
 | 
			
		||||
        /// <param name="copyTimestamps">Optional. Whether to copy the timestamps.</param>
 | 
			
		||||
        /// <param name="addVttTimeMap">Optional. Whether to add a VTT time map.</param>
 | 
			
		||||
        /// <param name="startPositionTicks">Optional. The start position of the subtitle in ticks.</param>
 | 
			
		||||
        /// <response code="200">File returned.</response>
 | 
			
		||||
        /// <returns>A <see cref="FileContentResult"/> with the subtitle file.</returns>
 | 
			
		||||
        [HttpGet("/Videos/{id}/{mediaSourceId}/Subtitles/{index}/Stream.{format}")]
 | 
			
		||||
        [HttpGet("/Videos/{id}/{mediaSourceId}/Subtitles/{index}/{startPositionTicks}/Stream.{format}")]
 | 
			
		||||
        [HttpGet("/Videos/{itemId}/{mediaSourceId}/Subtitles/{index}/Stream.{format}")]
 | 
			
		||||
        [HttpGet("/Videos/{itemId}/{mediaSourceId}/Subtitles/{index}/{startPositionTicks?}/Stream.{format}")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
        public async Task<ActionResult> GetSubtitle(
 | 
			
		||||
            [FromRoute, Required] Guid id,
 | 
			
		||||
            [FromRoute, Required] Guid itemId,
 | 
			
		||||
            [FromRoute, Required] string mediaSourceId,
 | 
			
		||||
            [FromRoute, Required] int index,
 | 
			
		||||
            [FromRoute, Required] string format,
 | 
			
		||||
            [FromRoute] long startPositionTicks,
 | 
			
		||||
            [FromQuery] long? endPositionTicks,
 | 
			
		||||
            [FromQuery] bool copyTimestamps,
 | 
			
		||||
            [FromQuery] bool addVttTimeMap)
 | 
			
		||||
            [FromQuery] bool addVttTimeMap,
 | 
			
		||||
            [FromRoute] long startPositionTicks = 0)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.Equals(format, "js", StringComparison.OrdinalIgnoreCase))
 | 
			
		||||
            {
 | 
			
		||||
@ -201,9 +201,9 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
 | 
			
		||||
            if (string.IsNullOrEmpty(format))
 | 
			
		||||
            {
 | 
			
		||||
                var item = (Video)_libraryManager.GetItemById(id);
 | 
			
		||||
                var item = (Video)_libraryManager.GetItemById(itemId);
 | 
			
		||||
 | 
			
		||||
                var idString = id.ToString("N", CultureInfo.InvariantCulture);
 | 
			
		||||
                var idString = itemId.ToString("N", CultureInfo.InvariantCulture);
 | 
			
		||||
                var mediaSource = _mediaSourceManager.GetStaticMediaSources(item, false)
 | 
			
		||||
                    .First(i => string.Equals(i.Id, mediaSourceId ?? idString, StringComparison.Ordinal));
 | 
			
		||||
 | 
			
		||||
@ -216,7 +216,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
 | 
			
		||||
            if (string.Equals(format, "vtt", StringComparison.OrdinalIgnoreCase) && addVttTimeMap)
 | 
			
		||||
            {
 | 
			
		||||
                await using Stream stream = await EncodeSubtitles(id, mediaSourceId, index, format, startPositionTicks, endPositionTicks, copyTimestamps).ConfigureAwait(false);
 | 
			
		||||
                await using Stream stream = await EncodeSubtitles(itemId, mediaSourceId, index, format, startPositionTicks, endPositionTicks, copyTimestamps).ConfigureAwait(false);
 | 
			
		||||
                using var reader = new StreamReader(stream);
 | 
			
		||||
 | 
			
		||||
                var text = await reader.ReadToEndAsync().ConfigureAwait(false);
 | 
			
		||||
@ -228,7 +228,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
 | 
			
		||||
            return File(
 | 
			
		||||
                await EncodeSubtitles(
 | 
			
		||||
                    id,
 | 
			
		||||
                    itemId,
 | 
			
		||||
                    mediaSourceId,
 | 
			
		||||
                    index,
 | 
			
		||||
                    format,
 | 
			
		||||
@ -241,23 +241,23 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets an HLS subtitle playlist.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The item id.</param>
 | 
			
		||||
        /// <param name="itemId">The item id.</param>
 | 
			
		||||
        /// <param name="index">The subtitle stream index.</param>
 | 
			
		||||
        /// <param name="mediaSourceId">The media source id.</param>
 | 
			
		||||
        /// <param name="segmentLength">The subtitle segment length.</param>
 | 
			
		||||
        /// <response code="200">Subtitle playlist retrieved.</response>
 | 
			
		||||
        /// <returns>A <see cref="FileContentResult"/> with the HLS subtitle playlist.</returns>
 | 
			
		||||
        [HttpGet("/Videos/{id}/{mediaSourceId}/Subtitles/{index}/subtitles.m3u8")]
 | 
			
		||||
        [HttpGet("/Videos/{itemId}/{mediaSourceId}/Subtitles/{index}/subtitles.m3u8")]
 | 
			
		||||
        [Authorize(Policy = Policies.DefaultAuthorization)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
        [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")]
 | 
			
		||||
        public async Task<ActionResult> GetSubtitlePlaylist(
 | 
			
		||||
            [FromRoute] Guid id,
 | 
			
		||||
            [FromRoute] Guid itemId,
 | 
			
		||||
            [FromRoute] int index,
 | 
			
		||||
            [FromRoute] string mediaSourceId,
 | 
			
		||||
            [FromQuery, Required] int segmentLength)
 | 
			
		||||
        {
 | 
			
		||||
            var item = (Video)_libraryManager.GetItemById(id);
 | 
			
		||||
            var item = (Video)_libraryManager.GetItemById(itemId);
 | 
			
		||||
 | 
			
		||||
            var mediaSource = await _mediaSourceManager.GetMediaSource(item, mediaSourceId, null, false, CancellationToken.None).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -105,17 +105,17 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets a user by Id.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The user id.</param>
 | 
			
		||||
        /// <param name="userId">The user id.</param>
 | 
			
		||||
        /// <response code="200">User returned.</response>
 | 
			
		||||
        /// <response code="404">User not found.</response>
 | 
			
		||||
        /// <returns>An <see cref="UserDto"/> with information about the user or a <see cref="NotFoundResult"/> if the user was not found.</returns>
 | 
			
		||||
        [HttpGet("{id}")]
 | 
			
		||||
        [HttpGet("{userId}")]
 | 
			
		||||
        [Authorize(Policy = Policies.IgnoreSchedule)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
			
		||||
        public ActionResult<UserDto> GetUserById([FromRoute] Guid id)
 | 
			
		||||
        public ActionResult<UserDto> GetUserById([FromRoute] Guid userId)
 | 
			
		||||
        {
 | 
			
		||||
            var user = _userManager.GetUserById(id);
 | 
			
		||||
            var user = _userManager.GetUserById(userId);
 | 
			
		||||
 | 
			
		||||
            if (user == null)
 | 
			
		||||
            {
 | 
			
		||||
@ -129,17 +129,17 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Deletes a user.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The user id.</param>
 | 
			
		||||
        /// <param name="userId">The user id.</param>
 | 
			
		||||
        /// <response code="200">User deleted.</response>
 | 
			
		||||
        /// <response code="404">User not found.</response>
 | 
			
		||||
        /// <returns>A <see cref="NoContentResult"/> indicating success or a <see cref="NotFoundResult"/> if the user was not found.</returns>
 | 
			
		||||
        [HttpDelete("{id}")]
 | 
			
		||||
        [HttpDelete("{userId}")]
 | 
			
		||||
        [Authorize(Policy = Policies.RequiresElevation)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
			
		||||
        public ActionResult DeleteUser([FromRoute] Guid id)
 | 
			
		||||
        public ActionResult DeleteUser([FromRoute] Guid userId)
 | 
			
		||||
        {
 | 
			
		||||
            var user = _userManager.GetUserById(id);
 | 
			
		||||
            var user = _userManager.GetUserById(userId);
 | 
			
		||||
 | 
			
		||||
            if (user == null)
 | 
			
		||||
            {
 | 
			
		||||
@ -154,23 +154,23 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Authenticates a user.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The user id.</param>
 | 
			
		||||
        /// <param name="userId">The user id.</param>
 | 
			
		||||
        /// <param name="pw">The password as plain text.</param>
 | 
			
		||||
        /// <param name="password">The password sha1-hash.</param>
 | 
			
		||||
        /// <response code="200">User authenticated.</response>
 | 
			
		||||
        /// <response code="403">Sha1-hashed password only is not allowed.</response>
 | 
			
		||||
        /// <response code="404">User not found.</response>
 | 
			
		||||
        /// <returns>A <see cref="Task"/> containing an <see cref="AuthenticationResult"/>.</returns>
 | 
			
		||||
        [HttpPost("{id}/Authenticate")]
 | 
			
		||||
        [HttpPost("{userId}/Authenticate")]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status403Forbidden)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
			
		||||
        public async Task<ActionResult<AuthenticationResult>> AuthenticateUser(
 | 
			
		||||
            [FromRoute, Required] Guid id,
 | 
			
		||||
            [FromRoute, Required] Guid userId,
 | 
			
		||||
            [FromQuery, BindRequired] string pw,
 | 
			
		||||
            [FromQuery, BindRequired] string password)
 | 
			
		||||
        {
 | 
			
		||||
            var user = _userManager.GetUserById(id);
 | 
			
		||||
            var user = _userManager.GetUserById(userId);
 | 
			
		||||
 | 
			
		||||
            if (user == null)
 | 
			
		||||
            {
 | 
			
		||||
@ -230,27 +230,27 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Updates a user's password.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The user id.</param>
 | 
			
		||||
        /// <param name="userId">The user id.</param>
 | 
			
		||||
        /// <param name="request">The <see cref="UpdateUserPassword"/> request.</param>
 | 
			
		||||
        /// <response code="200">Password successfully reset.</response>
 | 
			
		||||
        /// <response code="403">User is not allowed to update the password.</response>
 | 
			
		||||
        /// <response code="404">User not found.</response>
 | 
			
		||||
        /// <returns>A <see cref="NoContentResult"/> indicating success or a <see cref="ForbidResult"/> or a <see cref="NotFoundResult"/> on failure.</returns>
 | 
			
		||||
        [HttpPost("{id}/Password")]
 | 
			
		||||
        [HttpPost("{userId}/Password")]
 | 
			
		||||
        [Authorize]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status403Forbidden)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
			
		||||
        public async Task<ActionResult> UpdateUserPassword(
 | 
			
		||||
            [FromRoute] Guid id,
 | 
			
		||||
            [FromRoute] Guid userId,
 | 
			
		||||
            [FromBody] UpdateUserPassword request)
 | 
			
		||||
        {
 | 
			
		||||
            if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, id, true))
 | 
			
		||||
            if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true))
 | 
			
		||||
            {
 | 
			
		||||
                return Forbid("User is not allowed to update the password.");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var user = _userManager.GetUserById(id);
 | 
			
		||||
            var user = _userManager.GetUserById(userId);
 | 
			
		||||
 | 
			
		||||
            if (user == null)
 | 
			
		||||
            {
 | 
			
		||||
@ -288,27 +288,27 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Updates a user's easy password.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The user id.</param>
 | 
			
		||||
        /// <param name="userId">The user id.</param>
 | 
			
		||||
        /// <param name="request">The <see cref="UpdateUserEasyPassword"/> request.</param>
 | 
			
		||||
        /// <response code="200">Password successfully reset.</response>
 | 
			
		||||
        /// <response code="403">User is not allowed to update the password.</response>
 | 
			
		||||
        /// <response code="404">User not found.</response>
 | 
			
		||||
        /// <returns>A <see cref="NoContentResult"/> indicating success or a <see cref="ForbidResult"/> or a <see cref="NotFoundResult"/> on failure.</returns>
 | 
			
		||||
        [HttpPost("{id}/EasyPassword")]
 | 
			
		||||
        [HttpPost("{userId}/EasyPassword")]
 | 
			
		||||
        [Authorize]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status403Forbidden)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
			
		||||
        public ActionResult UpdateUserEasyPassword(
 | 
			
		||||
            [FromRoute] Guid id,
 | 
			
		||||
            [FromRoute] Guid userId,
 | 
			
		||||
            [FromBody] UpdateUserEasyPassword request)
 | 
			
		||||
        {
 | 
			
		||||
            if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, id, true))
 | 
			
		||||
            if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true))
 | 
			
		||||
            {
 | 
			
		||||
                return Forbid("User is not allowed to update the easy password.");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var user = _userManager.GetUserById(id);
 | 
			
		||||
            var user = _userManager.GetUserById(userId);
 | 
			
		||||
 | 
			
		||||
            if (user == null)
 | 
			
		||||
            {
 | 
			
		||||
@ -330,19 +330,19 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Updates a user.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The user id.</param>
 | 
			
		||||
        /// <param name="userId">The user id.</param>
 | 
			
		||||
        /// <param name="updateUser">The updated user model.</param>
 | 
			
		||||
        /// <response code="204">User updated.</response>
 | 
			
		||||
        /// <response code="400">User information was not supplied.</response>
 | 
			
		||||
        /// <response code="403">User update forbidden.</response>
 | 
			
		||||
        /// <returns>A <see cref="NoContentResult"/> indicating success or a <see cref="BadRequestResult"/> or a <see cref="ForbidResult"/> on failure.</returns>
 | 
			
		||||
        [HttpPost("{id}")]
 | 
			
		||||
        [HttpPost("{userId}")]
 | 
			
		||||
        [Authorize]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status400BadRequest)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status403Forbidden)]
 | 
			
		||||
        public async Task<ActionResult> UpdateUser(
 | 
			
		||||
            [FromRoute] Guid id,
 | 
			
		||||
            [FromRoute] Guid userId,
 | 
			
		||||
            [FromBody] UserDto updateUser)
 | 
			
		||||
        {
 | 
			
		||||
            if (updateUser == null)
 | 
			
		||||
@ -350,12 +350,12 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
                return BadRequest();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, id, false))
 | 
			
		||||
            if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, false))
 | 
			
		||||
            {
 | 
			
		||||
                return Forbid("User update not allowed.");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var user = _userManager.GetUserById(id);
 | 
			
		||||
            var user = _userManager.GetUserById(userId);
 | 
			
		||||
 | 
			
		||||
            if (string.Equals(user.Username, updateUser.Name, StringComparison.Ordinal))
 | 
			
		||||
            {
 | 
			
		||||
@ -374,19 +374,19 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Updates a user policy.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The user id.</param>
 | 
			
		||||
        /// <param name="userId">The user id.</param>
 | 
			
		||||
        /// <param name="newPolicy">The new user policy.</param>
 | 
			
		||||
        /// <response code="204">User policy updated.</response>
 | 
			
		||||
        /// <response code="400">User policy was not supplied.</response>
 | 
			
		||||
        /// <response code="403">User policy update forbidden.</response>
 | 
			
		||||
        /// <returns>A <see cref="NoContentResult"/> indicating success or a <see cref="BadRequestResult"/> or a <see cref="ForbidResult"/> on failure..</returns>
 | 
			
		||||
        [HttpPost("{id}/Policy")]
 | 
			
		||||
        [HttpPost("{userId}/Policy")]
 | 
			
		||||
        [Authorize]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status400BadRequest)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status403Forbidden)]
 | 
			
		||||
        public ActionResult UpdateUserPolicy(
 | 
			
		||||
            [FromRoute] Guid id,
 | 
			
		||||
            [FromRoute] Guid userId,
 | 
			
		||||
            [FromBody] UserPolicy newPolicy)
 | 
			
		||||
        {
 | 
			
		||||
            if (newPolicy == null)
 | 
			
		||||
@ -394,7 +394,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
                return BadRequest();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var user = _userManager.GetUserById(id);
 | 
			
		||||
            var user = _userManager.GetUserById(userId);
 | 
			
		||||
 | 
			
		||||
            // If removing admin access
 | 
			
		||||
            if (!(newPolicy.IsAdministrator && user.HasPermission(PermissionKind.IsAdministrator)))
 | 
			
		||||
@ -423,7 +423,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
                _sessionManager.RevokeUserTokens(user.Id, currentToken);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            _userManager.UpdatePolicy(id, newPolicy);
 | 
			
		||||
            _userManager.UpdatePolicy(userId, newPolicy);
 | 
			
		||||
 | 
			
		||||
            return NoContent();
 | 
			
		||||
        }
 | 
			
		||||
@ -431,25 +431,25 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Updates a user configuration.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="id">The user id.</param>
 | 
			
		||||
        /// <param name="userId">The user id.</param>
 | 
			
		||||
        /// <param name="userConfig">The new user configuration.</param>
 | 
			
		||||
        /// <response code="204">User configuration updated.</response>
 | 
			
		||||
        /// <response code="403">User configuration update forbidden.</response>
 | 
			
		||||
        /// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
 | 
			
		||||
        [HttpPost("{id}/Configuration")]
 | 
			
		||||
        [HttpPost("{userId}/Configuration")]
 | 
			
		||||
        [Authorize]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status204NoContent)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status403Forbidden)]
 | 
			
		||||
        public ActionResult UpdateUserConfiguration(
 | 
			
		||||
            [FromRoute] Guid id,
 | 
			
		||||
            [FromRoute] Guid userId,
 | 
			
		||||
            [FromBody] UserConfiguration userConfig)
 | 
			
		||||
        {
 | 
			
		||||
            if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, id, false))
 | 
			
		||||
            if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, false))
 | 
			
		||||
            {
 | 
			
		||||
                return Forbid("User configuration update not allowed");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            _userManager.UpdateConfiguration(id, userConfig);
 | 
			
		||||
            _userManager.UpdateConfiguration(userId, userConfig);
 | 
			
		||||
 | 
			
		||||
            return NoContent();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -44,7 +44,7 @@ namespace Jellyfin.Api.Controllers
 | 
			
		||||
        /// <response code="200">Attachment retrieved.</response>
 | 
			
		||||
        /// <response code="404">Video or attachment not found.</response>
 | 
			
		||||
        /// <returns>An <see cref="FileStreamResult"/> containing the attachment stream on success, or a <see cref="NotFoundResult"/> if the attachment could not be found.</returns>
 | 
			
		||||
        [HttpGet("{VideoID}/{MediaSourceID}/Attachments/{Index}")]
 | 
			
		||||
        [HttpGet("{videoId}/{mediaSourceId}/Attachments/{index}")]
 | 
			
		||||
        [Produces(MediaTypeNames.Application.Octet)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status200OK)]
 | 
			
		||||
        [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user