| | | 1 | | using System.Reflection; |
| | | 2 | | using Scalar.AspNetCore; |
| | | 3 | | using Microsoft.OpenApi.Any; |
| | | 4 | | using Syki.Back.Auth.Schemes; |
| | | 5 | | using Microsoft.OpenApi.Models; |
| | | 6 | | using Microsoft.OpenApi.Interfaces; |
| | | 7 | | |
| | | 8 | | namespace Syki.Back.Configs; |
| | | 9 | | |
| | | 10 | | public static class DocsConfigs |
| | | 11 | | { |
| | | 12 | | public static void AddDocsConfigs(this WebApplicationBuilder builder) |
| | | 13 | | { |
| | 2 | 14 | | builder.Services.AddSwaggerGen(options => |
| | 2 | 15 | | { |
| | 2 | 16 | | options.SwaggerDoc("v1", new OpenApiInfo |
| | 2 | 17 | | { |
| | 2 | 18 | | Title = "Syki API Docs", |
| | 2 | 19 | | Description = ReadResource("api-intro.md"), |
| | 2 | 20 | | Extensions = new Dictionary<string, IOpenApiExtension> |
| | 2 | 21 | | { |
| | 2 | 22 | | { "x-logo", new OpenApiObject |
| | 2 | 23 | | { |
| | 2 | 24 | | { "url", new OpenApiString("/syki-logo.png") }, |
| | 2 | 25 | | }} |
| | 2 | 26 | | }, |
| | 2 | 27 | | }); |
| | 2 | 28 | | |
| | 2 | 29 | | options.EnableAnnotations(); |
| | 2 | 30 | | |
| | 2 | 31 | | options.TagActionsBy(api => |
| | 2 | 32 | | { |
| | 0 | 33 | | var group = api.RelativePath.Split("/")[0]; |
| | 0 | 34 | | if (group == "campi") return ["🏫 Campi"]; |
| | 0 | 35 | | if (group == "courses") return ["📚 Courses"]; |
| | 0 | 36 | | if (group == "course-curriculums") return ["📋 Curriculums"]; |
| | 0 | 37 | | if (group == "course-offerings") return ["🗓️ Offerings"]; |
| | 0 | 38 | | if (group == "disciplines") return ["📖 Disciplines"]; |
| | 0 | 39 | | if (group == "periods") return ["📅 Periods"]; |
| | 0 | 40 | | if (group == "students") return ["🎓 Students"]; |
| | 0 | 41 | | if (group == "teachers") return ["👨🏫 Teachers"]; |
| | 0 | 42 | | if (group == "identity") return ["🛡️ Identity"]; |
| | 0 | 43 | | if (group == "users") return ["👩🏻🎓 Users"]; |
| | 0 | 44 | | return ["🧱 Cross"]; |
| | 2 | 45 | | }); |
| | 2 | 46 | | options.DocInclusionPredicate((name, api) => true); |
| | 2 | 47 | | |
| | 2 | 48 | | options.SchemaFilter<EnumSchemaFilter>(); |
| | 2 | 49 | | options.OperationFilter<AuthOperationsFilter>(); |
| | 2 | 50 | | options.OperationFilter<IdParameterExamplesFilter>(); |
| | 2 | 51 | | options.OperationFilter<ExamplesOperationsFilterFilter>(); |
| | 2 | 52 | | options.DocumentFilter<HttpMethodSorterDocumentFilter>(); |
| | 2 | 53 | | |
| | 2 | 54 | | options.ExampleFilters(); |
| | 2 | 55 | | |
| | 2 | 56 | | options.AddSecurityDefinition( |
| | 2 | 57 | | JwtBearerScheme.Name, |
| | 2 | 58 | | new OpenApiSecurityScheme |
| | 2 | 59 | | { |
| | 2 | 60 | | In = ParameterLocation.Cookie, |
| | 2 | 61 | | Name = JwtBearerScheme.Cookie, |
| | 2 | 62 | | Type = SecuritySchemeType.ApiKey, |
| | 2 | 63 | | Description = "JWT enviado no cookie http only", |
| | 2 | 64 | | }); |
| | 2 | 65 | | |
| | 2 | 66 | | options.DescribeAllParametersInCamelCase(); |
| | 2 | 67 | | |
| | 2 | 68 | | var xmlPath = Path.Combine(AppContext.BaseDirectory, "Back.xml"); |
| | 2 | 69 | | options.IncludeXmlComments(xmlPath, includeControllerXmlComments: true); |
| | 4 | 70 | | }); |
| | | 71 | | |
| | 2 | 72 | | builder.Services.AddSwaggerExamplesFromAssemblyOf(typeof(Program)); |
| | 2 | 73 | | builder.Services.AddOpenApi(); |
| | 2 | 74 | | } |
| | | 75 | | |
| | | 76 | | public static void MapScalarDocs(this IEndpointRouteBuilder options) |
| | | 77 | | { |
| | 2 | 78 | | options.MapScalarApiReference("/docs", options => |
| | 2 | 79 | | { |
| | 0 | 80 | | options.WithModels(false); |
| | 0 | 81 | | options.WithTitle("Syki API Docs"); |
| | 0 | 82 | | options.WithDocumentDownloadType(DocumentDownloadType.Json); |
| | 0 | 83 | | options.WithOpenApiRoutePattern("/swagger/{documentName}/swagger.json"); |
| | 0 | 84 | | options |
| | 0 | 85 | | .AddPreferredSecuritySchemes("Bearer") |
| | 0 | 86 | | .AddHttpAuthentication("Bearer", x => x.Token = "your.bearer.token"); |
| | 2 | 87 | | |
| | 0 | 88 | | options.CustomCss = @" |
| | 0 | 89 | | :root { |
| | 0 | 90 | | --scalar-sidebar-width: 300px; |
| | 0 | 91 | | } |
| | 0 | 92 | | "; |
| | 2 | 93 | | }); |
| | 2 | 94 | | } |
| | | 95 | | |
| | | 96 | | public static void UseDocs(this IApplicationBuilder app) |
| | | 97 | | { |
| | 2 | 98 | | app.UseStaticFiles(); |
| | 2 | 99 | | app.UseSwagger(); |
| | 2 | 100 | | } |
| | | 101 | | |
| | | 102 | | private static string ReadResource(string name) |
| | | 103 | | { |
| | 2 | 104 | | var assembly = Assembly.GetExecutingAssembly(); |
| | 4 | 105 | | var resourcePath = assembly.GetManifestResourceNames().Single(str => str.EndsWith(name)); |
| | | 106 | | |
| | 2 | 107 | | using Stream stream = assembly.GetManifestResourceStream(resourcePath)!; |
| | 2 | 108 | | using StreamReader reader = new(stream); |
| | | 109 | | |
| | 2 | 110 | | return reader.ReadToEnd(); |
| | 2 | 111 | | } |
| | | 112 | | } |