diff --git a/Jellyfin.Api/Controllers/ConfigurationController.cs b/Jellyfin.Api/Controllers/ConfigurationController.cs index 74f1677bdb..d275ed2eba 100644 --- a/Jellyfin.Api/Controllers/ConfigurationController.cs +++ b/Jellyfin.Api/Controllers/ConfigurationController.cs @@ -68,7 +68,7 @@ namespace Jellyfin.Api.Controllers /// Configuration key. /// Configuration returned. /// Configuration. - [HttpGet("Configuration/{Key}")] + [HttpGet("Configuration/{key}")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetNamedConfiguration([FromRoute] string key) { @@ -81,7 +81,7 @@ namespace Jellyfin.Api.Controllers /// Configuration key. /// Named configuration updated. /// Update status. - [HttpPost("Configuration/{Key}")] + [HttpPost("Configuration/{key}")] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task UpdateNamedConfiguration([FromRoute] string key) diff --git a/Jellyfin.Api/Controllers/DevicesController.cs b/Jellyfin.Api/Controllers/DevicesController.cs index 78368eed60..55ca7b7c0f 100644 --- a/Jellyfin.Api/Controllers/DevicesController.cs +++ b/Jellyfin.Api/Controllers/DevicesController.cs @@ -133,6 +133,7 @@ namespace Jellyfin.Api.Controllers /// A on success, or a if the device could not be found. [HttpDelete] [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult DeleteDevice([FromQuery, BindRequired] string id) { var existingDevice = _deviceManager.GetDevice(id); diff --git a/Jellyfin.Api/Controllers/DisplayPreferencesController.cs b/Jellyfin.Api/Controllers/DisplayPreferencesController.cs index 697a0baf42..56ac215a96 100644 --- a/Jellyfin.Api/Controllers/DisplayPreferencesController.cs +++ b/Jellyfin.Api/Controllers/DisplayPreferencesController.cs @@ -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 /// Client. /// Display preferences retrieved. /// An containing the display preferences on success, or a if the display preferences could not be found. - [HttpGet("{DisplayPreferencesId}")] + [HttpGet("{displayPreferencesId}")] [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult GetDisplayPreferences( [FromRoute] string displayPreferencesId, [FromQuery] [Required] string userId, @@ -52,30 +52,24 @@ namespace Jellyfin.Api.Controllers /// User Id. /// Client. /// New Display Preferences object. - /// Display preferences updated. - /// An on success, or a if the display preferences could not be found. - [HttpPost("{DisplayPreferencesId}")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(typeof(ModelStateDictionary), StatusCodes.Status400BadRequest)] - [ProducesResponseType(StatusCodes.Status404NotFound)] + /// Display preferences updated. + /// An on success. + [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(); } } } diff --git a/Jellyfin.Api/Controllers/ImageByNameController.cs b/Jellyfin.Api/Controllers/ImageByNameController.cs index 70f46ffa49..0e3c32d3cc 100644 --- a/Jellyfin.Api/Controllers/ImageByNameController.cs +++ b/Jellyfin.Api/Controllers/ImageByNameController.cs @@ -58,7 +58,7 @@ namespace Jellyfin.Api.Controllers /// Image stream retrieved. /// Image not found. /// A containing the image contents on success, or a if the image could not be found. - [HttpGet("General/{Name}/{Type}")] + [HttpGet("General/{name}/{type}")] [AllowAnonymous] [Produces(MediaTypeNames.Application.Octet)] [ProducesResponseType(StatusCodes.Status200OK)] @@ -103,7 +103,7 @@ namespace Jellyfin.Api.Controllers /// Image stream retrieved. /// Image not found. /// A containing the image contents on success, or a if the image could not be found. - [HttpGet("Ratings/{Theme}/{Name}")] + [HttpGet("Ratings/{theme}/{name}")] [AllowAnonymous] [Produces(MediaTypeNames.Application.Octet)] [ProducesResponseType(StatusCodes.Status200OK)] @@ -136,7 +136,7 @@ namespace Jellyfin.Api.Controllers /// Image stream retrieved. /// Image not found. /// A containing the image contents on success, or a if the image could not be found. - [HttpGet("MediaInfo/{Theme}/{Name}")] + [HttpGet("MediaInfo/{theme}/{name}")] [AllowAnonymous] [Produces(MediaTypeNames.Application.Octet)] [ProducesResponseType(StatusCodes.Status200OK)] diff --git a/Jellyfin.Api/Controllers/ItemRefreshController.cs b/Jellyfin.Api/Controllers/ItemRefreshController.cs index 6a16a89c5a..f10f9fb3d8 100644 --- a/Jellyfin.Api/Controllers/ItemRefreshController.cs +++ b/Jellyfin.Api/Controllers/ItemRefreshController.cs @@ -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 /// /// Refreshes metadata for an item. /// - /// Item id. + /// Item id. /// (Optional) Specifies the metadata refresh mode. /// (Optional) Specifies the image refresh mode. /// (Optional) Determines if metadata should be replaced. Only applicable if mode is FullRefresh. /// (Optional) Determines if images should be replaced. Only applicable if mode is FullRefresh. /// (Unused) Indicates if the refresh should occur recursively. - /// Item metadata refresh queued. + /// Item metadata refresh queued. /// Item to refresh not found. /// An on success, or a if the item could not be found. - [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(); } } } diff --git a/Jellyfin.Api/Controllers/NotificationsController.cs b/Jellyfin.Api/Controllers/NotificationsController.cs index 01dd23c77f..f226364894 100644 --- a/Jellyfin.Api/Controllers/NotificationsController.cs +++ b/Jellyfin.Api/Controllers/NotificationsController.cs @@ -42,7 +42,7 @@ namespace Jellyfin.Api.Controllers /// An optional limit on the number of notifications returned. /// Notifications returned. /// An containing a list of notifications. - [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 /// The user's ID. /// Summary of user's notifications returned. /// An containing a summary of the users notifications. - [HttpGet("{UserID}/Summary")] + [HttpGet("{userId}/Summary")] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Imported from ServiceStack")] public ActionResult GetNotificationsSummary( @@ -138,7 +138,7 @@ namespace Jellyfin.Api.Controllers /// A comma-separated list of the IDs of notifications which should be set as read. /// Notifications set as read. /// A . - [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 /// A comma-separated list of the IDs of notifications which should be set as unread. /// Notifications set as unread. /// A . - [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")] diff --git a/Jellyfin.Api/Controllers/PackageController.cs b/Jellyfin.Api/Controllers/PackageController.cs index 943c23f8e9..486575d23a 100644 --- a/Jellyfin.Api/Controllers/PackageController.cs +++ b/Jellyfin.Api/Controllers/PackageController.cs @@ -35,9 +35,10 @@ namespace Jellyfin.Api.Controllers /// /// The name of the package. /// The GUID of the associated assembly. + /// Package retrieved. /// A containing package information. - [HttpGet("/{Name}")] - [ProducesResponseType(typeof(PackageInfo), StatusCodes.Status200OK)] + [HttpGet("/{name}")] + [ProducesResponseType(StatusCodes.Status200OK)] public async Task> GetPackageInfo( [FromRoute] [Required] string name, [FromQuery] string? assemblyGuid) @@ -54,9 +55,10 @@ namespace Jellyfin.Api.Controllers /// /// Gets available packages. /// + /// Available packages returned. /// An containing available packages information. [HttpGet] - [ProducesResponseType(typeof(PackageInfo[]), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status200OK)] public async Task> GetPackages() { IEnumerable packages = await _installationManager.GetAvailablePackages().ConfigureAwait(false); @@ -73,7 +75,7 @@ namespace Jellyfin.Api.Controllers /// Package found. /// Package not found. /// A on success, or a if the package could not be found. - [HttpPost("/Installed/{Name}")] + [HttpPost("/Installed/{name}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] [Authorize(Policy = Policies.RequiresElevation)] @@ -102,17 +104,16 @@ namespace Jellyfin.Api.Controllers /// /// Cancels a package installation. /// - /// Installation Id. + /// Installation Id. /// Installation cancelled. /// A on successfully cancelling a package installation. - [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(); } } diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index 6075544cf7..8a0913307e 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/Jellyfin.Api/Controllers/PluginsController.cs @@ -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 /// Installed plugins returned. /// List of currently installed plugins. [HttpGet] + [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "isAppStoreEnabled", Justification = "Imported from ServiceStack")] public ActionResult> GetPlugins([FromRoute] bool? isAppStoreEnabled) { @@ -55,11 +57,13 @@ namespace Jellyfin.Api.Controllers /// Uninstalls a plugin. /// /// Plugin id. - /// Plugin uninstalled. + /// Plugin uninstalled. /// Plugin not found. /// An on success, or a if the file could not be found. [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(); } /// @@ -80,6 +84,8 @@ namespace Jellyfin.Api.Controllers /// Plugin not found or plugin configuration not found. /// Plugin configuration. [HttpGet("{pluginId}/Configuration")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult 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. /// /// Plugin id. - /// Plugin configuration updated. - /// Plugin not found or plugin does not have configuration. + /// Plugin configuration updated. + /// Plugin not found or plugin does not have configuration. /// /// A that represents the asynchronous operation to update plugin configuration. /// The task result contains an indicating success, or /// when plugin not found or plugin doesn't have configuration. /// [HttpPost("{pluginId}/Configuration")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task 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(); } /// @@ -126,6 +134,7 @@ namespace Jellyfin.Api.Controllers /// Plugin security info. [Obsolete("This endpoint should not be used.")] [HttpGet("SecurityInfo")] + [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetPluginSecurityInfo() { return new PluginSecurityInfo @@ -139,14 +148,15 @@ namespace Jellyfin.Api.Controllers /// Updates plugin security info. /// /// Plugin security info. - /// Plugin security info updated. - /// An . + /// Plugin security info updated. + /// An . [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(); } /// @@ -157,6 +167,7 @@ namespace Jellyfin.Api.Controllers /// Mb registration record. [Obsolete("This endpoint should not be used.")] [HttpPost("RegistrationRecords/{name}")] + [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetRegistrationStatus([FromRoute] string name) { return new MBRegistrationRecord @@ -178,6 +189,7 @@ namespace Jellyfin.Api.Controllers /// This endpoint is not implemented. [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, diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs index 80983ee649..41b7f98ee1 100644 --- a/Jellyfin.Api/Controllers/RemoteImageController.cs +++ b/Jellyfin.Api/Controllers/RemoteImageController.cs @@ -55,7 +55,7 @@ namespace Jellyfin.Api.Controllers /// /// Gets available remote images for an item. /// - /// Item Id. + /// Item Id. /// The image type. /// Optional. The record index to start at. All items with a lower index will be dropped from the results. /// Optional. The maximum number of records to return. @@ -64,18 +64,18 @@ namespace Jellyfin.Api.Controllers /// Remote Images returned. /// Item not found. /// Remote Image Result. - [HttpGet("{Id}/RemoteImages")] + [HttpGet("{itemId}/RemoteImages")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task> 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 /// /// Gets available remote image providers for an item. /// - /// Item Id. + /// Item Id. /// Returned remote image providers. /// Item not found. /// List of remote image providers. - [HttpGet("{Id}/RemoteImages/Providers")] + [HttpGet("{itemId}/RemoteImages/Providers")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult> GetRemoteImageProviders([FromRoute] string id) + public ActionResult> 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 /// /// Downloads a remote image for an item. /// - /// Item Id. + /// Item Id. /// The image type. /// The image url. - /// Remote image downloaded. + /// Remote image downloaded. /// Remote image not found. /// Download status. - [HttpPost("{Id}/RemoteImages/Download")] - [ProducesResponseType(StatusCodes.Status200OK)] + [HttpPost("{itemId}/RemoteImages/Download")] + [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task 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(); } /// diff --git a/Jellyfin.Api/Controllers/SessionController.cs b/Jellyfin.Api/Controllers/SessionController.cs index 4f259536a1..315bc9728b 100644 --- a/Jellyfin.Api/Controllers/SessionController.cs +++ b/Jellyfin.Api/Controllers/SessionController.cs @@ -113,16 +113,16 @@ namespace Jellyfin.Api.Controllers /// /// Instructs a session to browse to an item or view. /// - /// The session Id. + /// The session Id. /// The type of item to browse to. /// The Id of the item. /// The name of the item. /// Instruction sent to session. /// A . - [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 /// /// Instructs a session to play an item. /// - /// The session id. + /// The session id. /// The ids of the items to play, comma delimited. /// The starting position of the first item. /// The type of play command to issue (PlayNow, PlayNext, PlayLast). Clients who have not yet implemented play next and play last may play now. /// The . /// Instruction sent to session. /// A . - [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 /// /// Issues a playstate command to a client. /// - /// The session id. + /// The session id. /// The . /// Playstate command sent to session. /// A . - [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 /// /// Issues a system command to a client. /// - /// The session id. + /// The session id. /// The command to send. /// System command sent to session. /// A . - [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 /// /// Issues a general command to a client. /// - /// The session id. + /// The session id. /// The command to send. /// General command sent to session. /// A . - [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 /// /// Issues a full general command to a client. /// - /// The session id. + /// The session id. /// The . /// Full general command sent to session. /// A . - [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 /// /// Issues a command to a client to display a message to the user. /// - /// The session id. + /// The session id. /// The message test. /// The message header. /// The message timeout. If omitted the user will have to confirm viewing the message. /// Message sent. /// A . - [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 /// /// Adds an additional user to a session. /// - /// The session id. + /// The session id. /// The user id. /// User added to session. /// A . - [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(); } /// /// Removes an additional user from a session. /// - /// The session id. + /// The session id. /// The user id. /// User removed from session. /// A . - [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(); } diff --git a/Jellyfin.Api/Controllers/SubtitleController.cs b/Jellyfin.Api/Controllers/SubtitleController.cs index 74ec5f9b52..95cc39524c 100644 --- a/Jellyfin.Api/Controllers/SubtitleController.cs +++ b/Jellyfin.Api/Controllers/SubtitleController.cs @@ -75,20 +75,20 @@ namespace Jellyfin.Api.Controllers /// /// Deletes an external subtitle file. /// - /// The item id. + /// The item id. /// The index of the subtitle file. /// Subtitle deleted. /// Item not found. /// A . - [HttpDelete("/Videos/{id}/Subtitles/{index}")] + [HttpDelete("/Videos/{itemId}/Subtitles/{index}")] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult 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 /// /// Search remote subtitles. /// - /// The item id. + /// The item id. /// The language of the subtitles. /// Optional. Only show subtitles which are a perfect match. /// Subtitles retrieved. /// An array of . - [HttpGet("/Items/{id}/RemoteSearch/Subtitles/{language}")] + [HttpGet("/Items/{itemId}/RemoteSearch/Subtitles/{language}")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] public async Task>> 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 /// /// Downloads a remote subtitle. /// - /// The item id. + /// The item id. /// The subtitle id. /// Subtitle downloaded. /// A . - [HttpPost("/Items/{id}/RemoteSearch/Subtitles/{subtitleId}")] + [HttpPost("/Items/{itemId}/RemoteSearch/Subtitles/{subtitleId}")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task 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 /// /// Gets subtitles in a specified format. /// - /// The item id. + /// The item id. /// The media source id. /// The subtitle stream index. /// The format of the returned subtitle. - /// Optional. The start position of the subtitle in ticks. /// Optional. The end position of the subtitle in ticks. /// Optional. Whether to copy the timestamps. /// Optional. Whether to add a VTT time map. + /// Optional. The start position of the subtitle in ticks. /// File returned. /// A with the subtitle file. - [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 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 /// /// Gets an HLS subtitle playlist. /// - /// The item id. + /// The item id. /// The subtitle stream index. /// The media source id. /// The subtitle segment length. /// Subtitle playlist retrieved. /// A with the HLS subtitle playlist. - [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 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); diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs index 68ab5813ce..0d57dcc837 100644 --- a/Jellyfin.Api/Controllers/UserController.cs +++ b/Jellyfin.Api/Controllers/UserController.cs @@ -105,17 +105,17 @@ namespace Jellyfin.Api.Controllers /// /// Gets a user by Id. /// - /// The user id. + /// The user id. /// User returned. /// User not found. /// An with information about the user or a if the user was not found. - [HttpGet("{id}")] + [HttpGet("{userId}")] [Authorize(Policy = Policies.IgnoreSchedule)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult GetUserById([FromRoute] Guid id) + public ActionResult 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 /// /// Deletes a user. /// - /// The user id. + /// The user id. /// User deleted. /// User not found. /// A indicating success or a if the user was not found. - [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 /// /// Authenticates a user. /// - /// The user id. + /// The user id. /// The password as plain text. /// The password sha1-hash. /// User authenticated. /// Sha1-hashed password only is not allowed. /// User not found. /// A containing an . - [HttpPost("{id}/Authenticate")] + [HttpPost("{userId}/Authenticate")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task> 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 /// /// Updates a user's password. /// - /// The user id. + /// The user id. /// The request. /// Password successfully reset. /// User is not allowed to update the password. /// User not found. /// A indicating success or a or a on failure. - [HttpPost("{id}/Password")] + [HttpPost("{userId}/Password")] [Authorize] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task 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 /// /// Updates a user's easy password. /// - /// The user id. + /// The user id. /// The request. /// Password successfully reset. /// User is not allowed to update the password. /// User not found. /// A indicating success or a or a on failure. - [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 /// /// Updates a user. /// - /// The user id. + /// The user id. /// The updated user model. /// User updated. /// User information was not supplied. /// User update forbidden. /// A indicating success or a or a on failure. - [HttpPost("{id}")] + [HttpPost("{userId}")] [Authorize] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task 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 /// /// Updates a user policy. /// - /// The user id. + /// The user id. /// The new user policy. /// User policy updated. /// User policy was not supplied. /// User policy update forbidden. /// A indicating success or a or a on failure.. - [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 /// /// Updates a user configuration. /// - /// The user id. + /// The user id. /// The new user configuration. /// User configuration updated. /// User configuration update forbidden. /// A indicating success. - [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(); } diff --git a/Jellyfin.Api/Controllers/VideoAttachmentsController.cs b/Jellyfin.Api/Controllers/VideoAttachmentsController.cs index 2528fd75d0..943ba8af3d 100644 --- a/Jellyfin.Api/Controllers/VideoAttachmentsController.cs +++ b/Jellyfin.Api/Controllers/VideoAttachmentsController.cs @@ -44,7 +44,7 @@ namespace Jellyfin.Api.Controllers /// Attachment retrieved. /// Video or attachment not found. /// An containing the attachment stream on success, or a if the attachment could not be found. - [HttpGet("{VideoID}/{MediaSourceID}/Attachments/{Index}")] + [HttpGet("{videoId}/{mediaSourceId}/Attachments/{index}")] [Produces(MediaTypeNames.Application.Octet)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)]