From cb6ea80adb9675cf752655a407e1f5e18281ec13 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Wed, 29 Sep 2021 21:24:56 +0200 Subject: [PATCH] Swagger: Handling PermissionsAttribute for the swagger's document --- .../OperationPermissionProcessor.cs | 80 +++++++++++++++++++ src/Kyoo.Swagger/SwaggerModule.cs | 19 ++++- 2 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 src/Kyoo.Swagger/OperationPermissionProcessor.cs diff --git a/src/Kyoo.Swagger/OperationPermissionProcessor.cs b/src/Kyoo.Swagger/OperationPermissionProcessor.cs new file mode 100644 index 00000000..b0511b24 --- /dev/null +++ b/src/Kyoo.Swagger/OperationPermissionProcessor.cs @@ -0,0 +1,80 @@ +// Kyoo - A portable and vast media library solution. +// Copyright (c) Kyoo. +// +// See AUTHORS.md and LICENSE file in the project root for full license information. +// +// Kyoo is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// Kyoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Kyoo. If not, see . + +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Kyoo.Abstractions.Models.Permissions; +using NSwag; +using NSwag.Generation.Processors; +using NSwag.Generation.Processors.Contexts; + +namespace Kyoo.Swagger +{ + /// + /// An operation processor that adds permissions information from the and the + /// . + /// + public class OperationPermissionProcessor : IOperationProcessor + { + /// + public bool Process(OperationProcessorContext context) + { + context.OperationDescription.Operation.Security ??= new List(); + OpenApiSecurityRequirement perms = context.MethodInfo.GetCustomAttributes() + .Aggregate(new OpenApiSecurityRequirement(), (agg, cur) => + { + ICollection permissions = _GetPermissionsList(agg, cur.Group); + permissions.Add($"{cur.Type}.{cur.Kind.ToString().ToLower()}"); + agg[cur.Group.ToString()] = permissions; + return agg; + }); + + PartialPermissionAttribute controller = context.ControllerType + .GetCustomAttribute(); + if (controller != null) + { + perms = context.MethodInfo.GetCustomAttributes() + .Aggregate(perms, (agg, cur) => + { + Group group = controller.Group != Group.Overall + ? controller.Group + : cur.Group; + string type = controller.Type ?? cur.Type; + Kind kind = controller.Type == null + ? controller.Kind + : cur.Kind; + ICollection permissions = _GetPermissionsList(agg, group); + permissions.Add($"{type}.{kind.ToString().ToLower()}"); + agg[group.ToString()] = permissions; + return agg; + }); + } + + context.OperationDescription.Operation.Security.Add(perms); + return true; + } + + private ICollection _GetPermissionsList(OpenApiSecurityRequirement security, Group group) + { + return security.TryGetValue(group.ToString(), out IEnumerable perms) + ? perms.ToList() + : new List(); + } + } +} diff --git a/src/Kyoo.Swagger/SwaggerModule.cs b/src/Kyoo.Swagger/SwaggerModule.cs index 1bf05ec3..1d8e56e1 100644 --- a/src/Kyoo.Swagger/SwaggerModule.cs +++ b/src/Kyoo.Swagger/SwaggerModule.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using Kyoo.Abstractions.Controllers; +using Kyoo.Abstractions.Models.Permissions; using Kyoo.Abstractions.Models.Utils; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Mvc.ApplicationModels; @@ -27,6 +28,7 @@ using NJsonSchema; using NJsonSchema.Generation.TypeMappers; using NSwag; using NSwag.Generation.AspNetCore; +using NSwag.Generation.Processors.Security; using static Kyoo.Abstractions.Models.Utils.Constants; namespace Kyoo.Swagger @@ -104,9 +106,24 @@ namespace Kyoo.Swagger }, AuthorizationUrl = "https://localhost:44333/core/connect/authorize", TokenUrl = "https://localhost:44333/core/connect/token" - }, + } } }); + document.OperationProcessors.Add(new OperationPermissionProcessor()); + document.DocumentProcessors.Add(new SecurityDefinitionAppender(Group.Overall.ToString(), new OpenApiSecurityScheme + { + Type = OpenApiSecuritySchemeType.ApiKey, + Name = "Authorization", + In = OpenApiSecurityApiKeyLocation.Header, + Description = "Type into the textbox: Bearer {your JWT token}. You can get a JWT token from /Authorization/Authenticate." + })); + document.DocumentProcessors.Add(new SecurityDefinitionAppender(Group.Admin.ToString(), new OpenApiSecurityScheme + { + Type = OpenApiSecuritySchemeType.ApiKey, + Name = "Authorization", + In = OpenApiSecurityApiKeyLocation.Header, + Description = "Type into the textbox: Bearer {your JWT token}. You can get a JWT token from /Authorization/Authenticate." + })); }); }