diff --git a/authentik.go b/authentik.go index c26dcb1..49ae1c7 100644 --- a/authentik.go +++ b/authentik.go @@ -235,6 +235,8 @@ func authentikMiddleware(cfg AuthentikConfig, publicPaths func() []string) gin.H func cloneAuthentikConfig(cfg AuthentikConfig) AuthentikConfig { out := cfg + out.Issuer = strings.TrimSpace(out.Issuer) + out.ClientID = strings.TrimSpace(out.ClientID) out.PublicPaths = normalisePublicPaths(cfg.PublicPaths) return out } diff --git a/options.go b/options.go index 2887978..6f10798 100644 --- a/options.go +++ b/options.go @@ -204,9 +204,9 @@ func WithSunset(sunsetDate, replacement string) Option { // api.New(api.WithSwagger("Service", "Public API", "1.0.0")) func WithSwagger(title, description, version string) Option { return func(e *Engine) { - e.swaggerTitle = title - e.swaggerDesc = description - e.swaggerVersion = version + e.swaggerTitle = strings.TrimSpace(title) + e.swaggerDesc = strings.TrimSpace(description) + e.swaggerVersion = strings.TrimSpace(version) e.swaggerEnabled = true } } @@ -218,7 +218,7 @@ func WithSwagger(title, description, version string) Option { // api.WithSwaggerSummary("Service overview") func WithSwaggerSummary(summary string) Option { return func(e *Engine) { - if summary != "" { + if summary = strings.TrimSpace(summary); summary != "" { e.swaggerSummary = summary } } @@ -244,7 +244,7 @@ func WithSwaggerPath(path string) Option { // api.WithSwaggerTermsOfService("https://example.com/terms") func WithSwaggerTermsOfService(url string) Option { return func(e *Engine) { - if url != "" { + if url = strings.TrimSpace(url); url != "" { e.swaggerTermsOfService = url } } @@ -258,13 +258,13 @@ func WithSwaggerTermsOfService(url string) Option { // api.WithSwaggerContact("API Support", "https://example.com/support", "support@example.com") func WithSwaggerContact(name, url, email string) Option { return func(e *Engine) { - if name != "" { + if name = strings.TrimSpace(name); name != "" { e.swaggerContactName = name } - if url != "" { + if url = strings.TrimSpace(url); url != "" { e.swaggerContactURL = url } - if email != "" { + if email = strings.TrimSpace(email); email != "" { e.swaggerContactEmail = email } } @@ -291,10 +291,10 @@ func WithSwaggerServers(servers ...string) Option { // api.WithSwaggerLicense("EUPL-1.2", "https://eupl.eu/1.2/en/") func WithSwaggerLicense(name, url string) Option { return func(e *Engine) { - if name != "" { + if name = strings.TrimSpace(name); name != "" { e.swaggerLicenseName = name } - if url != "" { + if url = strings.TrimSpace(url); url != "" { e.swaggerLicenseURL = url } } @@ -340,10 +340,10 @@ func WithSwaggerSecuritySchemes(schemes map[string]any) Option { // api.WithSwaggerExternalDocs("Developer guide", "https://example.com/docs") func WithSwaggerExternalDocs(description, url string) Option { return func(e *Engine) { - if description != "" { + if description = strings.TrimSpace(description); description != "" { e.swaggerExternalDocsDescription = description } - if url != "" { + if url = strings.TrimSpace(url); url != "" { e.swaggerExternalDocsURL = url } } diff --git a/spec_builder_helper_test.go b/spec_builder_helper_test.go index 6e78b4a..3754d25 100644 --- a/spec_builder_helper_test.go +++ b/spec_builder_helper_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/gin-gonic/gin" + "slices" api "dappco.re/go/core/api" ) @@ -340,6 +341,87 @@ func TestEngine_Good_SwaggerConfigCarriesEngineMetadata(t *testing.T) { } } +func TestEngine_Good_SwaggerConfigTrimsRuntimeMetadata(t *testing.T) { + gin.SetMode(gin.TestMode) + + e, err := api.New( + api.WithSwagger(" Engine API ", " Engine metadata ", " 2.0.0 "), + api.WithSwaggerSummary(" Engine overview "), + api.WithSwaggerTermsOfService(" https://example.com/terms "), + api.WithSwaggerContact(" API Support ", " https://example.com/support ", " support@example.com "), + api.WithSwaggerLicense(" EUPL-1.2 ", " https://eupl.eu/1.2/en/ "), + api.WithSwaggerExternalDocs(" Developer guide ", " https://example.com/docs "), + api.WithAuthentik(api.AuthentikConfig{ + Issuer: " https://auth.example.com ", + ClientID: " core-client ", + TrustedProxy: true, + PublicPaths: []string{" /public/ ", " docs ", "/public"}, + }), + ) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + swagger := e.SwaggerConfig() + if swagger.Title != "Engine API" { + t.Fatalf("expected trimmed title Engine API, got %q", swagger.Title) + } + if swagger.Description != "Engine metadata" { + t.Fatalf("expected trimmed description Engine metadata, got %q", swagger.Description) + } + if swagger.Version != "2.0.0" { + t.Fatalf("expected trimmed version 2.0.0, got %q", swagger.Version) + } + if swagger.Summary != "Engine overview" { + t.Fatalf("expected trimmed summary Engine overview, got %q", swagger.Summary) + } + if swagger.TermsOfService != "https://example.com/terms" { + t.Fatalf("expected trimmed termsOfService, got %q", swagger.TermsOfService) + } + if swagger.ContactName != "API Support" || swagger.ContactURL != "https://example.com/support" || swagger.ContactEmail != "support@example.com" { + t.Fatalf("expected trimmed contact metadata, got %+v", swagger) + } + if swagger.LicenseName != "EUPL-1.2" || swagger.LicenseURL != "https://eupl.eu/1.2/en/" { + t.Fatalf("expected trimmed licence metadata, got %+v", swagger) + } + if swagger.ExternalDocsDescription != "Developer guide" || swagger.ExternalDocsURL != "https://example.com/docs" { + t.Fatalf("expected trimmed external docs metadata, got %+v", swagger) + } + + auth := e.AuthentikConfig() + if auth.Issuer != "https://auth.example.com" { + t.Fatalf("expected trimmed issuer, got %q", auth.Issuer) + } + if auth.ClientID != "core-client" { + t.Fatalf("expected trimmed client ID, got %q", auth.ClientID) + } + if want := []string{"/public", "/docs"}; !slices.Equal(auth.PublicPaths, want) { + t.Fatalf("expected trimmed public paths %v, got %v", want, auth.PublicPaths) + } + + builder := e.OpenAPISpecBuilder() + data, err := builder.Build(nil) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + var spec map[string]any + if err := json.Unmarshal(data, &spec); err != nil { + t.Fatalf("invalid JSON: %v", err) + } + + info, ok := spec["info"].(map[string]any) + if !ok { + t.Fatal("expected info object in generated spec") + } + if info["title"] != "Engine API" || info["description"] != "Engine metadata" || info["version"] != "2.0.0" || info["summary"] != "Engine overview" { + t.Fatalf("expected trimmed OpenAPI info block, got %+v", info) + } + if info["termsOfService"] != "https://example.com/terms" { + t.Fatalf("expected trimmed termsOfService in spec, got %v", info["termsOfService"]) + } +} + func TestEngine_Good_TransportConfigCarriesEngineMetadata(t *testing.T) { gin.SetMode(gin.TestMode)