Forráskód Böngészése

Merge pull request #5208 from crobibero/api-post-image

Add image file accept to openapi
Bond-009 4 éve
szülő
commit
76d66e0dee

+ 28 - 0
Jellyfin.Api/Attributes/AcceptsFileAttribute.cs

@@ -0,0 +1,28 @@
+using System;
+
+namespace Jellyfin.Api.Attributes
+{
+    /// <summary>
+    /// Internal produces image attribute.
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Method)]
+    public class AcceptsFileAttribute : Attribute
+    {
+        private readonly string[] _contentTypes;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AcceptsFileAttribute"/> class.
+        /// </summary>
+        /// <param name="contentTypes">Content types this endpoint produces.</param>
+        public AcceptsFileAttribute(params string[] contentTypes)
+        {
+            _contentTypes = contentTypes;
+        }
+
+        /// <summary>
+        /// Gets the configured content types.
+        /// </summary>
+        /// <returns>the configured content types.</returns>
+        public string[] GetContentTypes() => _contentTypes;
+    }
+}

+ 18 - 0
Jellyfin.Api/Attributes/AcceptsImageFileAttribute.cs

@@ -0,0 +1,18 @@
+namespace Jellyfin.Api.Attributes
+{
+    /// <summary>
+    /// Produces file attribute of "image/*".
+    /// </summary>
+    public class AcceptsImageFileAttribute : AcceptsFileAttribute
+    {
+        private const string ContentType = "image/*";
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AcceptsImageFileAttribute"/> class.
+        /// </summary>
+        public AcceptsImageFileAttribute()
+            : base(ContentType)
+        {
+        }
+    }
+}

+ 4 - 0
Jellyfin.Api/Controllers/ImageController.cs

@@ -87,6 +87,7 @@ namespace Jellyfin.Api.Controllers
         /// <returns>A <see cref="NoContentResult"/>.</returns>
         [HttpPost("Users/{userId}/Images/{imageType}")]
         [Authorize(Policy = Policies.DefaultAuthorization)]
+        [AcceptsImageFile]
         [ProducesResponseType(StatusCodes.Status204NoContent)]
         [ProducesResponseType(StatusCodes.Status403Forbidden)]
         [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "imageType", Justification = "Imported from ServiceStack")]
@@ -133,6 +134,7 @@ namespace Jellyfin.Api.Controllers
         /// <returns>A <see cref="NoContentResult"/>.</returns>
         [HttpPost("Users/{userId}/Images/{imageType}/{index}")]
         [Authorize(Policy = Policies.DefaultAuthorization)]
+        [AcceptsImageFile]
         [ProducesResponseType(StatusCodes.Status204NoContent)]
         [ProducesResponseType(StatusCodes.Status403Forbidden)]
         [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "imageType", Justification = "Imported from ServiceStack")]
@@ -312,6 +314,7 @@ namespace Jellyfin.Api.Controllers
         /// <returns>A <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if item not found.</returns>
         [HttpPost("Items/{itemId}/Images/{imageType}")]
         [Authorize(Policy = Policies.RequiresElevation)]
+        [AcceptsImageFile]
         [ProducesResponseType(StatusCodes.Status204NoContent)]
         [ProducesResponseType(StatusCodes.Status404NotFound)]
         [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")]
@@ -346,6 +349,7 @@ namespace Jellyfin.Api.Controllers
         /// <returns>A <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if item not found.</returns>
         [HttpPost("Items/{itemId}/Images/{imageType}/{imageIndex}")]
         [Authorize(Policy = Policies.RequiresElevation)]
+        [AcceptsImageFile]
         [ProducesResponseType(StatusCodes.Status204NoContent)]
         [ProducesResponseType(StatusCodes.Status404NotFound)]
         [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")]

+ 1 - 0
Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs

@@ -316,6 +316,7 @@ namespace Jellyfin.Server.Extensions
 
                 c.OperationFilter<SecurityRequirementsOperationFilter>();
                 c.OperationFilter<FileResponseFilter>();
+                c.OperationFilter<FileRequestFilter>();
                 c.OperationFilter<ParameterObsoleteFilter>();
                 c.DocumentFilter<WebsocketModelFilter>();
             });

+ 43 - 0
Jellyfin.Server/Filters/FileRequestFilter.cs

@@ -0,0 +1,43 @@
+using System.Collections.Generic;
+using Jellyfin.Api.Attributes;
+using Microsoft.OpenApi.Models;
+using Swashbuckle.AspNetCore.SwaggerGen;
+
+namespace Jellyfin.Server.Filters
+{
+    /// <inheritdoc />
+    public class FileRequestFilter : IOperationFilter
+    {
+        /// <inheritdoc />
+        public void Apply(OpenApiOperation operation, OperationFilterContext context)
+        {
+            foreach (var attribute in context.ApiDescription.ActionDescriptor.EndpointMetadata)
+            {
+                if (attribute is AcceptsFileAttribute acceptsFileAttribute)
+                {
+                    operation.RequestBody = GetRequestBody(acceptsFileAttribute.GetContentTypes());
+                    break;
+                }
+            }
+        }
+
+        private static OpenApiRequestBody GetRequestBody(IEnumerable<string> contentTypes)
+        {
+            var body = new OpenApiRequestBody();
+            var mediaType = new OpenApiMediaType
+            {
+                Schema = new OpenApiSchema
+                {
+                    Type = "string",
+                    Format = "binary"
+                }
+            };
+            foreach (var contentType in contentTypes)
+            {
+                body.Content.Add(contentType, mediaType);
+            }
+
+            return body;
+        }
+    }
+}