2026-06-22 16:06:57 +02:00
|
|
|
// Package openapitest holds a cross-module guard: it registers every module
|
|
|
|
|
// into one Huma API and generates the spec. Huma names OpenAPI schemas by Go
|
|
|
|
|
// type name alone (not package-qualified), so two modules declaring an
|
|
|
|
|
// identically named response type (e.g. two "ListOutput"s) collide only when
|
|
|
|
|
// registered together - a failure invisible to per-package `go build`/`go test`.
|
|
|
|
|
package openapitest
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"net/http"
|
|
|
|
|
"path/filepath"
|
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
|
|
"nadir/internal/auditlog"
|
|
|
|
|
"nadir/internal/auth"
|
|
|
|
|
"nadir/internal/meta"
|
|
|
|
|
"nadir/internal/module"
|
|
|
|
|
"nadir/internal/modules/groups"
|
|
|
|
|
"nadir/internal/modules/networking"
|
|
|
|
|
"nadir/internal/modules/packages"
|
|
|
|
|
"nadir/internal/modules/services"
|
|
|
|
|
"nadir/internal/modules/storage"
|
|
|
|
|
"nadir/internal/modules/system"
|
|
|
|
|
"nadir/internal/modules/users"
|
|
|
|
|
"nadir/internal/rbac"
|
|
|
|
|
|
|
|
|
|
"github.com/danielgtaylor/huma/v2"
|
|
|
|
|
"github.com/danielgtaylor/huma/v2/adapters/humago"
|
|
|
|
|
)
|
|
|
|
|
|
2026-06-25 14:44:47 +02:00
|
|
|
type auditModule struct{}
|
|
|
|
|
|
|
|
|
|
func (auditModule) ID() string { return "audit" }
|
|
|
|
|
func (auditModule) Permissions() []rbac.Permission { return []rbac.Permission{rbac.Read} }
|
|
|
|
|
func (auditModule) Register(huma.API) {}
|
|
|
|
|
|
2026-06-22 16:06:57 +02:00
|
|
|
func TestOpenAPISchemaNoCollisions(t *testing.T) {
|
|
|
|
|
auditStore, err := auditlog.New(filepath.Join(t.TempDir(), "audit.db"))
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
sessions, err := auth.NewSessionStore(filepath.Join(t.TempDir(), "sessions.db"))
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
roles := rbac.New()
|
|
|
|
|
|
|
|
|
|
// Mirror cmd/server.go's registration so this catches real collisions.
|
|
|
|
|
mods := []module.Module{
|
|
|
|
|
system.New(),
|
|
|
|
|
services.New(nil),
|
2026-06-24 17:29:45 +02:00
|
|
|
users.New(nil),
|
2026-06-22 16:06:57 +02:00
|
|
|
groups.New(),
|
|
|
|
|
packages.New(),
|
|
|
|
|
networking.New(),
|
|
|
|
|
storage.New(),
|
2026-06-25 14:44:47 +02:00
|
|
|
auditModule{},
|
2026-06-22 16:06:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mux := http.NewServeMux()
|
|
|
|
|
api := humago.New(mux, huma.DefaultConfig("test", "1.0.0"))
|
|
|
|
|
for _, m := range mods {
|
|
|
|
|
m.Register(api) // huma panics here on a duplicate schema name
|
|
|
|
|
}
|
|
|
|
|
meta.Register(api, mods)
|
|
|
|
|
meta.RegisterHealth(api, sessions)
|
2026-06-23 18:02:52 +02:00
|
|
|
meta.RegisterWhoami(api, sessions, nil, roles, mods)
|
2026-06-25 14:44:47 +02:00
|
|
|
meta.RegisterAudit(api, auditStore)
|
2026-06-22 16:06:57 +02:00
|
|
|
auth.RegisterLogin(api, sessions, auditStore, true)
|
|
|
|
|
auth.RegisterLogout(api, sessions, true)
|
|
|
|
|
|
|
|
|
|
// Force full schema resolution.
|
|
|
|
|
if _, err := api.OpenAPI().YAML(); err != nil {
|
|
|
|
|
t.Fatalf("OpenAPI generation failed: %v", err)
|
|
|
|
|
}
|
|
|
|
|
}
|