Skip to content

Commit

Permalink
split openAPI docs into public vs non public
Browse files Browse the repository at this point in the history
  • Loading branch information
hahn-kev committed Sep 5, 2024
1 parent e3a8c21 commit f957630
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 45 deletions.
1 change: 1 addition & 0 deletions backend/LexBoxApi/Controllers/CrdtController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace LexBoxApi.Controllers;
[ApiController]
[Route("/api/crdt")]
[AdminRequired]
[ApiExplorerSettings(GroupName = LexBoxKernel.OpenApiPublicDocumentName)]
public class CrdtController(
LexBoxDbContext dbContext,
IHubContext<CrdtProjectChangeHub, IProjectChangeListener> hubContext,
Expand Down
1 change: 1 addition & 0 deletions backend/LexBoxApi/LexBoxKernel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace LexBoxApi;
public static class LexBoxKernel
{
public const string SwaggerDocumentName = "v1";
public const string OpenApiPublicDocumentName = "public";

public static void AddLexBoxApi(this IServiceCollection services,
ConfigurationManager configuration,
Expand Down
13 changes: 12 additions & 1 deletion backend/LexBoxApi/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
options.DocInclusionPredicate((docName, apiDesc) =>
{
//we only want docs marked as public in the public group, by default no docs are public. The default behavior is to include all apis in all docs.
if (docName == apiDesc.GroupName) return true;
if (docName == LexBoxKernel.OpenApiPublicDocumentName) return false;
return true;
});
options.SwaggerDoc(LexBoxKernel.OpenApiPublicDocumentName, new() { Title = "Lexbox Public Api", });
options.SwaggerDoc(LexBoxKernel.SwaggerDocumentName, new OpenApiInfo
{
Title = "LexBoxApi",
Expand Down Expand Up @@ -145,6 +153,9 @@
});
app.UseSwaggerUI(options =>
{
//the first doc is the default one
options.SwaggerEndpoint("/api/swagger/public/swagger.json", "Lexbox Public Api");
options.SwaggerEndpoint("/api/swagger/v1/swagger.json", "Lexbox Api");
options.RoutePrefix = "api/swagger";
options.ConfigObject.DisplayRequestDuration = true;
options.EnableTryItOutByDefault();
Expand All @@ -163,7 +174,7 @@

app.MapQuartzUI("/api/quartz").RequireAuthorization(new AdminRequiredAttribute());
app.MapControllers();
app.MapLfClassicApi().RequireAuthorization(new AdminRequiredAttribute()).WithOpenApi();
app.MapLfClassicApi().RequireAuthorization(new AdminRequiredAttribute()).WithOpenApi().WithGroupName(LexBoxKernel.OpenApiPublicDocumentName);
app.MapTus("/api/tus-test",
async context => await context.RequestServices.GetRequiredService<TusService>().GetTestConfig(context))
.RequireAuthorization(new AdminRequiredAttribute());
Expand Down
105 changes: 61 additions & 44 deletions backend/LfClassicData/LfClassicRoutes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,59 +12,75 @@ public static class LfClassicRoutes
public static IEndpointConventionBuilder MapLfClassicApi(this IEndpointRouteBuilder builder)
{
var group = builder.MapGroup("/api/lfclassic/{projectCode}");
group.MapGet("/writingSystems",
([FromRoute] string projectCode, [FromServices] ILexboxApiProvider provider) =>
{
var api = provider.GetProjectApi(projectCode);
return api.GetWritingSystems();
});
group.MapGet("/entries",
([FromRoute] string projectCode,
[FromServices] ILexboxApiProvider provider,
[AsParameters] ClassicQueryOptions options
) =>
{
var api = provider.GetProjectApi(projectCode);
return api.GetEntries(options.ToQueryOptions());
});
group.MapGet("/entries/{search}",
([FromRoute] string projectCode,
[FromServices] ILexboxApiProvider provider,
[FromRoute] string search,
[AsParameters] ClassicQueryOptions options) =>
{
var api = provider.GetProjectApi(projectCode);
return api.SearchEntries(search, options.ToQueryOptions());
});
group.MapGet("/entry/{id:Guid}",
([FromRoute] string projectCode, Guid id, [FromServices] ILexboxApiProvider provider) =>
{
var api = provider.GetProjectApi(projectCode);
return api.GetEntry(id);
});
group.MapGet("/parts-of-speech",
([FromRoute] string projectCode, [FromServices] ILexboxApiProvider provider) =>
{
var api = provider.GetProjectApi(projectCode);
return api.GetPartsOfSpeech();
});
group.MapGet("/semantic-domains",
([FromRoute] string projectCode, [FromServices] ILexboxApiProvider provider) =>
{
var api = provider.GetProjectApi(projectCode);
return api.GetSemanticDomains();
});
group.MapGet("/writingSystems", MiniLcm.GetWritingSystems);
group.MapGet("/entries", MiniLcm.GetEntries);
group.MapGet("/entries/{search}", MiniLcm.SearchEntries);
group.MapGet("/entry/{id:Guid}", MiniLcm.GetEntry);
group.MapGet("/parts-of-speech", MiniLcm.GetPartsOfSpeech);
group.MapGet("/semantic-domains", MiniLcm.GetSemanticDomains);
return group;
}

//swagger docs pickup their controller name from the type that the callback is defined in, that's why this type exists.
private static class MiniLcm
{
public static Task<WritingSystems> GetWritingSystems([FromRoute] string projectCode,
[FromServices] ILexboxApiProvider provider)
{
var api = provider.GetProjectApi(projectCode);
return api.GetWritingSystems();
}

public static IAsyncEnumerable<Entry> GetEntries([FromRoute] string projectCode,
[FromServices] ILexboxApiProvider provider,
[AsParameters] ClassicQueryOptions options)
{
var api = provider.GetProjectApi(projectCode);
return api.GetEntries(options.ToQueryOptions());
}

public static IAsyncEnumerable<Entry> SearchEntries([FromRoute] string projectCode,
[FromServices] ILexboxApiProvider provider,
[FromRoute] string search,
[AsParameters] ClassicQueryOptions options)
{
var api = provider.GetProjectApi(projectCode);
return api.SearchEntries(search, options.ToQueryOptions());
}

public static Task<Entry?> GetEntry([FromRoute] string projectCode,
Guid id,
[FromServices] ILexboxApiProvider provider)
{
var api = provider.GetProjectApi(projectCode);
return api.GetEntry(id);
}

public static IAsyncEnumerable<PartOfSpeech> GetPartsOfSpeech([FromRoute] string projectCode,
[FromServices] ILexboxApiProvider provider)
{
var api = provider.GetProjectApi(projectCode);
return api.GetPartsOfSpeech();
}

public static IAsyncEnumerable<SemanticDomain> GetSemanticDomains([FromRoute] string projectCode,
[FromServices] ILexboxApiProvider provider)
{
var api = provider.GetProjectApi(projectCode);
return api.GetSemanticDomains();
}
}

private class ClassicQueryOptions
{
public QueryOptions ToQueryOptions()
{
ExemplarOptions? exemplarOptions = string.IsNullOrEmpty(ExemplarValue) || ExemplarWritingSystem is null
? null
: new (ExemplarValue, ExemplarWritingSystem.Value);
var sortField = Enum.TryParse<SortField>(SortField, true, out var field) ? field : SortOptions.Default.Field;
: new(ExemplarValue, ExemplarWritingSystem.Value);
var sortField = Enum.TryParse<SortField>(SortField, true, out var field)
? field
: SortOptions.Default.Field;
return new QueryOptions(new SortOptions(sortField,
SortWritingSystem ?? SortOptions.Default.WritingSystem,
Ascending ?? SortOptions.Default.Ascending),
Expand All @@ -82,6 +98,7 @@ public QueryOptions ToQueryOptions()

[FromQuery]
public string? ExemplarValue { get; set; }

public WritingSystemId? ExemplarWritingSystem { get; set; }

[FromQuery]
Expand Down

0 comments on commit f957630

Please sign in to comment.