Added authentication

This commit is contained in:
2026-06-21 20:10:02 +02:00
parent efe63211ed
commit a50be1ec0b
50 changed files with 2596 additions and 328 deletions
-4
View File
@@ -1,4 +0,0 @@
namespace EonaCat.DoxaApi.Exporter
{
public static class DoxaApiExporter { }
}
+7
View File
@@ -0,0 +1,7 @@
namespace EonaCat.DoxaApi.Exporter
{
// This file is part of the EonaCat project(s) which is released under the Apache License.
// See the LICENSE file or go to https://EonaCat.com/license for full license details.
public static class DoxaApiExporter { }
}
+106 -1
View File
@@ -4,6 +4,8 @@ using EonaCat.DoxaApi.Models;
namespace EonaCat.DoxaApi.Interop
{
// This file is part of the EonaCat project(s) which is released under the Apache License.
// See the LICENSE file or go to https://EonaCat.com/license for full license details.
public static class OpenApiExporter
{
public static JsonObject Export(ApiDocument doc)
@@ -53,6 +55,24 @@ namespace EonaCat.DoxaApi.Interop
root["components"] = new JsonObject { ["schemas"] = schemas };
}
if (doc.SecuritySchemes.Count > 0)
{
var schemes = new JsonObject();
foreach (var (id, scheme) in doc.SecuritySchemes)
{
schemes[id] = SecuritySchemeToOpenApi(scheme);
}
if (root["components"] is JsonObject componentsObj)
{
componentsObj["securitySchemes"] = schemes;
}
else
{
root["components"] = new JsonObject { ["securitySchemes"] = schemes };
}
}
return root;
}
@@ -161,9 +181,94 @@ namespace EonaCat.DoxaApi.Interop
}
op["responses"] = responses;
if (endpoint.Security.Count > 0)
{
var security = new JsonArray();
foreach (var schemeId in endpoint.Security)
{
security.Add(new JsonObject { [schemeId] = new JsonArray() });
}
op["security"] = security;
}
return op;
}
private static JsonObject SecuritySchemeToOpenApi(SecuritySchemeModel scheme)
{
var obj = new JsonObject { ["type"] = scheme.Type };
if (scheme.Description is not null)
{
obj["description"] = scheme.Description;
}
switch (scheme.Type)
{
case "apiKey":
obj["name"] = scheme.Name ?? "X-API-Key";
obj["in"] = scheme.In ?? "header";
break;
case "http":
obj["scheme"] = scheme.Scheme ?? "bearer";
if (scheme.BearerFormat is not null)
{
obj["bearerFormat"] = scheme.BearerFormat;
}
break;
case "oauth2":
var flows = new JsonObject();
if (scheme.Flows?.ClientCredentials is OAuthFlowModel cc)
{
flows["clientCredentials"] = OAuthFlowToOpenApi(cc);
}
if (scheme.Flows?.AuthorizationCode is OAuthFlowModel ac)
{
flows["authorizationCode"] = OAuthFlowToOpenApi(ac);
}
if (scheme.Flows?.Password is OAuthFlowModel pw)
{
flows["password"] = OAuthFlowToOpenApi(pw);
}
if (scheme.Flows?.Implicit is OAuthFlowModel im)
{
flows["implicit"] = OAuthFlowToOpenApi(im);
}
obj["flows"] = flows;
break;
}
return obj;
}
private static JsonObject OAuthFlowToOpenApi(OAuthFlowModel flow)
{
var obj = new JsonObject();
if (flow.AuthorizationUrl is not null)
{
obj["authorizationUrl"] = flow.AuthorizationUrl;
}
if (flow.TokenUrl is not null)
{
obj["tokenUrl"] = flow.TokenUrl;
}
if (flow.RefreshUrl is not null)
{
obj["refreshUrl"] = flow.RefreshUrl;
}
var scopes = new JsonObject();
foreach (var (k, v) in flow.Scopes)
{
scopes[k] = v;
}
obj["scopes"] = scopes;
return obj;
}
private static JsonObject SchemaToOpenApi(SchemaModel schema)
{
@@ -269,4 +374,4 @@ namespace EonaCat.DoxaApi.Interop
_ => "Response"
};
}
}
}
+84 -1
View File
@@ -3,6 +3,9 @@ using EonaCat.DoxaApi.Models;
namespace EonaCat.DoxaApi.Interop
{
// This file is part of the EonaCat project(s) which is released under the Apache License.
// See the LICENSE file or go to https://EonaCat.com/license for full license details.
public static class SwaggerExporter
{
public static JsonObject Export(ApiDocument doc)
@@ -57,6 +60,17 @@ namespace EonaCat.DoxaApi.Interop
root["definitions"] = definitions;
}
if (doc.SecuritySchemes.Count > 0)
{
var defs = new JsonObject();
foreach (var (id, scheme) in doc.SecuritySchemes)
{
defs[id] = SecuritySchemeToSwagger(scheme);
}
root["securityDefinitions"] = defs;
}
return root;
}
@@ -157,6 +171,16 @@ namespace EonaCat.DoxaApi.Interop
}
op["responses"] = responses;
if (endpoint.Security.Count > 0)
{
var security = new JsonArray();
foreach (var schemeId in endpoint.Security)
{
security.Add(new JsonObject { [schemeId] = new JsonArray() });
}
op["security"] = security;
}
return op;
}
@@ -285,6 +309,65 @@ namespace EonaCat.DoxaApi.Interop
return obj;
}
private static JsonObject SecuritySchemeToSwagger(SecuritySchemeModel scheme)
{
var obj = new JsonObject();
if (scheme.Type == "apiKey")
{
obj["type"] = "apiKey";
obj["name"] = scheme.Name ?? "X-API-Key";
obj["in"] = scheme.In ?? "header";
}
else if (scheme.Type == "http" && scheme.Scheme == "basic")
{
obj["type"] = "basic";
}
else if (scheme.Type == "http" && scheme.Scheme == "bearer")
{
// Swagger 2.0 has no native bearer type; represent as an apiKey-style
// Authorization header for maximum tool compatibility.
obj["type"] = "apiKey";
obj["name"] = "Authorization";
obj["in"] = "header";
}
else if (scheme.Type == "oauth2")
{
obj["type"] = "oauth2";
var flow = scheme.Flows?.ClientCredentials;
if (flow is not null)
{
obj["flow"] = "application";
obj["tokenUrl"] = flow.TokenUrl;
var scopes = new JsonObject();
foreach (var (k, v) in flow.Scopes)
{
scopes[k] = v;
}
obj["scopes"] = scopes;
}
else if (scheme.Flows?.AuthorizationCode is OAuthFlowModel ac)
{
obj["flow"] = "accessCode";
obj["authorizationUrl"] = ac.AuthorizationUrl;
obj["tokenUrl"] = ac.TokenUrl;
var scopes = new JsonObject();
foreach (var (k, v) in ac.Scopes)
{
scopes[k] = v;
}
obj["scopes"] = scopes;
}
}
if (scheme.Description is not null)
{
obj["description"] = scheme.Description;
}
return obj;
}
private static string ToSwaggerPath(string path)
=> path.StartsWith('/') ? path : "/" + path;
@@ -301,4 +384,4 @@ namespace EonaCat.DoxaApi.Interop
_ => "Response"
};
}
}
}