Add authorization options to swagger-ui
This commit is contained in:
parent
3dc64fad38
commit
c961111d55
3 changed files with 68 additions and 13 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Threading.RateLimiting;
|
using System.Threading.RateLimiting;
|
||||||
using Iceshrimp.Backend.Controllers.Schemas;
|
using Iceshrimp.Backend.Controllers.Schemas;
|
||||||
using Iceshrimp.Backend.Core.Configuration;
|
using Iceshrimp.Backend.Core.Configuration;
|
||||||
|
@ -10,7 +11,9 @@ using Microsoft.AspNetCore.DataProtection;
|
||||||
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption;
|
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption;
|
||||||
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel;
|
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel;
|
||||||
using Microsoft.AspNetCore.RateLimiting;
|
using Microsoft.AspNetCore.RateLimiting;
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
using StackExchange.Redis;
|
using StackExchange.Redis;
|
||||||
|
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||||
|
|
||||||
namespace Iceshrimp.Backend.Core.Extensions;
|
namespace Iceshrimp.Backend.Core.Extensions;
|
||||||
|
|
||||||
|
@ -82,6 +85,55 @@ public static class ServiceExtensions {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void AddSwaggerGenWithOptions(this IServiceCollection services) {
|
||||||
|
services.AddSwaggerGen(options => {
|
||||||
|
options.SwaggerDoc("v1", new OpenApiInfo { Title = "Iceshrimp.NET", Version = "1.0" });
|
||||||
|
options.AddSecurityDefinition("user", new OpenApiSecurityScheme {
|
||||||
|
Name = "Authorization token",
|
||||||
|
In = ParameterLocation.Header,
|
||||||
|
Type = SecuritySchemeType.Http,
|
||||||
|
Scheme = "bearer"
|
||||||
|
});
|
||||||
|
options.AddSecurityDefinition("admin", new OpenApiSecurityScheme {
|
||||||
|
Name = "Authorization token",
|
||||||
|
In = ParameterLocation.Header,
|
||||||
|
Type = SecuritySchemeType.Http,
|
||||||
|
Scheme = "bearer"
|
||||||
|
});
|
||||||
|
options.OperationFilter<AuthorizeCheckOperationFilter>();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("ReSharper", "ClassNeverInstantiated.Local",
|
||||||
|
Justification = "SwaggerGenOptions.OperationFilter<T> instantiates this class at runtime")]
|
||||||
|
private class AuthorizeCheckOperationFilter : IOperationFilter {
|
||||||
|
public void Apply(OpenApiOperation operation, OperationFilterContext context) {
|
||||||
|
if (context.MethodInfo.DeclaringType is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//TODO: separate admin & user authorize attributes
|
||||||
|
var hasAuthorize = context.MethodInfo.DeclaringType.GetCustomAttributes(true)
|
||||||
|
.OfType<AuthenticateAttribute>().Any() ||
|
||||||
|
context.MethodInfo.GetCustomAttributes(true)
|
||||||
|
.OfType<AuthenticateAttribute>().Any();
|
||||||
|
|
||||||
|
if (!hasAuthorize) return;
|
||||||
|
var schema = new OpenApiSecurityScheme {
|
||||||
|
Reference = new OpenApiReference {
|
||||||
|
Type = ReferenceType.SecurityScheme,
|
||||||
|
Id = "user"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
operation.Security = new List<OpenApiSecurityRequirement> {
|
||||||
|
new() {
|
||||||
|
[schema] = Array.Empty<string>()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void AddSlidingWindowRateLimiter(this IServiceCollection services) {
|
public static void AddSlidingWindowRateLimiter(this IServiceCollection services) {
|
||||||
//TODO: separate limiter for authenticated users, partitioned by user id
|
//TODO: separate limiter for authenticated users, partitioned by user id
|
||||||
//TODO: ipv6 /64 subnet buckets
|
//TODO: ipv6 /64 subnet buckets
|
||||||
|
|
|
@ -16,6 +16,20 @@ public static class WebApplicationExtensions {
|
||||||
.UseMiddleware<AuthorizedFetchMiddleware>();
|
.UseMiddleware<AuthorizedFetchMiddleware>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IApplicationBuilder UseSwaggerWithOptions(this WebApplication app) {
|
||||||
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI(options => {
|
||||||
|
options.DocumentTitle = "Iceshrimp API documentation";
|
||||||
|
options.SwaggerEndpoint("v1/swagger.json", "Iceshrimp.NET");
|
||||||
|
options.InjectStylesheet("/swagger/styles.css");
|
||||||
|
options.EnablePersistAuthorization();
|
||||||
|
options.EnableTryItOutByDefault();
|
||||||
|
options.DisplayRequestDuration();
|
||||||
|
options.DefaultModelsExpandDepth(-1); // Hide "Schemas" section
|
||||||
|
});
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
public static Config.InstanceSection Initialize(this WebApplication app, string[] args) {
|
public static Config.InstanceSection Initialize(this WebApplication app, string[] args) {
|
||||||
var instanceConfig = app.Configuration.GetSection("Instance").Get<Config.InstanceSection>() ??
|
var instanceConfig = app.Configuration.GetSection("Instance").Get<Config.InstanceSection>() ??
|
||||||
throw new Exception("Failed to read Instance config section");
|
throw new Exception("Failed to read Instance config section");
|
||||||
|
|
|
@ -23,9 +23,7 @@ builder.Services.AddApiVersioning(options => {
|
||||||
options.UnsupportedApiVersionStatusCode = 501;
|
options.UnsupportedApiVersionStatusCode = 501;
|
||||||
});
|
});
|
||||||
builder.Services.AddEndpointsApiExplorer();
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
builder.Services.AddSwaggerGen(options => {
|
builder.Services.AddSwaggerGenWithOptions();
|
||||||
options.SwaggerDoc("v1", new OpenApiInfo { Title = "Iceshrimp.NET", Version = "1.0" });
|
|
||||||
});
|
|
||||||
builder.Services.AddRazorPages();
|
builder.Services.AddRazorPages();
|
||||||
builder.Services.AddViteServices(options => {
|
builder.Services.AddViteServices(options => {
|
||||||
options.PackageDirectory = "../Iceshrimp.Frontend";
|
options.PackageDirectory = "../Iceshrimp.Frontend";
|
||||||
|
@ -47,16 +45,7 @@ var config = app.Initialize(args);
|
||||||
|
|
||||||
// This determines the order of middleware execution in the request pipeline
|
// This determines the order of middleware execution in the request pipeline
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
app.UseSwagger();
|
app.UseSwaggerWithOptions();
|
||||||
app.UseSwaggerUI(options => {
|
|
||||||
options.DocumentTitle = "Iceshrimp API documentation";
|
|
||||||
options.SwaggerEndpoint("v1/swagger.json", "Iceshrimp.NET");
|
|
||||||
options.InjectStylesheet("/swagger/styles.css");
|
|
||||||
options.EnablePersistAuthorization();
|
|
||||||
options.EnableTryItOutByDefault();
|
|
||||||
options.DisplayRequestDuration();
|
|
||||||
options.DefaultModelsExpandDepth(-1); // Hide "Schemas" section
|
|
||||||
});
|
|
||||||
app.UseStaticFiles();
|
app.UseStaticFiles();
|
||||||
app.UseRateLimiter();
|
app.UseRateLimiter();
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|
Loading…
Add table
Reference in a new issue