DEV Community

Tobias Mesquita for Quasar Framework Brasil

Posted on • Updated on

QPANC - Parte 5 - ASP.NET - Documentação Interativa com Swagger

QPANC são as iniciais de Quasar PostgreSQL ASP NET Core.

10 Documentação Interativa

Agora que terminamos de configurar o Banco de Dados e a camada da aplicação responsável por acessa-lo, iremos trabalhar sobre a API REST, e começaremos pelo Swagger, que ia nós prover uma documentação interativa para a nossa API.

Vá até o projeto ./QPANC.Api e adicione o pacote:

cd QPANC.Api
dotnet add package Swashbuckle.AspNetCore

Agora, iremos criar um Middleware, para que apenas desenvolvedores possam acessar acessar a documentação interativa.

./QPANC.Api/Middlewares/SwaggerBasicAuthMiddleware.cs

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using QPANC.Domain.Identity;
using System;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace QPANC.Api.Middlewares
{
    public class SwaggerBasicAuthMiddleware
    {
        private readonly RequestDelegate _next;

        public SwaggerBasicAuthMiddleware(RequestDelegate next)
        {
            this._next = next;
        }

        public async Task InvokeAsync(HttpContext context, UserManager<User> userManager)
        {
            if (context.Request.Path.StartsWithSegments("/swagger"))
            {
                var isAuthorized = false;
                string authorization = context.Request.Headers["Authorization"];
                if (authorization != default && authorization.StartsWith("Basic "))
                {
                    var encoded = authorization.Split(' ', 2, StringSplitOptions.RemoveEmptyEntries)[1]?.Trim();

                    var binary = Convert.FromBase64String(encoded);
                    var decoded = Encoding.UTF8.GetString(binary).Split(':', 2);
                    var username = decoded[0];
                    var password = decoded[1];
                    var user = await userManager.FindByNameAsync(username + "@qpanc.app");
                    if (user != default)
                    {
                        var isAuthenticated = await userManager.CheckPasswordAsync(user, password);
                        if (isAuthenticated)
                        {
                            isAuthorized = await userManager.IsInRoleAsync(user, "Developer");
                        }
                    }
                }
                if (isAuthorized)
                {
                    await this._next.Invoke(context);
                }
                else
                {
                    context.Response.Headers["WWW-Authenticate"] = "Basic";
                    context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                }
            }
            else
            {
                await this._next.Invoke(context);
            }
        }
    }
}

então, configure o Swagger no ./QPANC.Api/Startup.cs

using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using QPANC.Api.Middlewares;

namespace QPANC.Api
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSwaggerGen(config =>
            {
                config.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
                {
                    Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
                    Name = "Authorization",
                    In = ParameterLocation.Header,
                    Type = SecuritySchemeType.ApiKey
                });

                var requirements = new OpenApiSecurityRequirement();
                var bearerSchema = new OpenApiSecurityScheme()
                {
                    Reference = new OpenApiReference
                    {
                        Type = ReferenceType.SecurityScheme,
                        Id = "Bearer"
                    },
                    Scheme = "oauth2",
                    Name = "Bearer",
                    In = ParameterLocation.Header
                };
                requirements.Add(bearerSchema, new string[] { });
                config.AddSecurityRequirement(requirements);
                config.SwaggerDoc("v1", new OpenApiInfo
                {
                    Title = "API - QPANC - Quasar, PostgreSQL, ASP.NET Core and Docker",
                    Description = "API - QPANC - Quasar, PostgreSQL, ASP.NET Core and Docker",
                    Version = "v1",
                    Contact = new OpenApiContact
                    {
                        Name = "QPANC - Quasar, PostgreSQL, ASP.NET Core and Docker",
                        Email = "developer@qpanc.app",
                        Url = new Uri("http://www.qpanc.app")
                    },
                });
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ISeeder seeder)
        {
            app.UseAuthentication();

            app.UseAuthorization();

            app.UseMiddleware<SwaggerBasicAuthMiddleware>();
            app.UseSwagger(c =>
            {
                c.RouteTemplate = "swagger/{documentName}/swagger.json";
            });
            app.UseSwaggerUI(c =>
            {

                c.SwaggerEndpoint("/swagger/v1/swagger.json", "QPANC - Quasar, PostgreSQL, ASP.NET Core and Docker");
                c.RoutePrefix = "swagger";
            });
        }
    }
}

Execute a aplicação e acesse o path 'http://localhost:34512/swagger', se estiver utilizando o Visual Studio, poderá atualizar as propriedades do projeto ./QPANC em Properties > Debug > Web Server Settings > http://localhost:34512/swagger

Alt Text

Você deve ter notado que foi necessário informar um usuário e uma senha para acessar a documentação, o que pode ser um incomodo durante o desenvolvimento, neste caso, podemos desativar o middleware durante o desenvolvimento.

namespace QPANC.Api
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ISeeder seeder)
        {
            if (!env.IsDevelopment())
            {
                app.UseMiddleware<SwaggerBasicAuthMiddleware>();
            }
        }
    }
}

Discussion (0)