diff --git a/cmd/testserver/main.go b/cmd/testserver/main.go index 2309fa9..c753c91 100644 --- a/cmd/testserver/main.go +++ b/cmd/testserver/main.go @@ -47,8 +47,8 @@ func main() { handler.RegisterModel("public", modelNames[i], model) } - // Setup routes using new SetupMuxRoutes function - resolvespec.SetupMuxRoutes(r, handler) + // Setup routes using new SetupMuxRoutes function (without authentication) + resolvespec.SetupMuxRoutes(r, handler, nil) // Start server logger.Info("Starting server on :8080") diff --git a/pkg/common/handler_example.go b/pkg/common/handler_example.go new file mode 100644 index 0000000..9b4f661 --- /dev/null +++ b/pkg/common/handler_example.go @@ -0,0 +1,97 @@ +package common + +// Example showing how to use the common handler interfaces +// This file demonstrates the handler interface hierarchy and usage patterns + +// ProcessWithAnyHandler demonstrates using the base SpecHandler interface +// which works with any handler type (resolvespec, restheadspec, or funcspec) +func ProcessWithAnyHandler(handler SpecHandler) Database { + // All handlers expose GetDatabase() through the SpecHandler interface + return handler.GetDatabase() +} + +// ProcessCRUDRequest demonstrates using the CRUDHandler interface +// which works with resolvespec.Handler and restheadspec.Handler +func ProcessCRUDRequest(handler CRUDHandler, w ResponseWriter, r Request, params map[string]string) { + // Both resolvespec and restheadspec handlers implement Handle() + handler.Handle(w, r, params) +} + +// ProcessMetadataRequest demonstrates getting metadata from CRUD handlers +func ProcessMetadataRequest(handler CRUDHandler, w ResponseWriter, r Request, params map[string]string) { + // Both resolvespec and restheadspec handlers implement HandleGet() + handler.HandleGet(w, r, params) +} + +// Example usage patterns (not executable, just for documentation): +/* +// Example 1: Using with resolvespec.Handler +func ExampleResolveSpec() { + db := // ... get database + registry := // ... get registry + + handler := resolvespec.NewHandler(db, registry) + + // Can be used as SpecHandler + var specHandler SpecHandler = handler + database := specHandler.GetDatabase() + + // Can be used as CRUDHandler + var crudHandler CRUDHandler = handler + crudHandler.Handle(w, r, params) + crudHandler.HandleGet(w, r, params) +} + +// Example 2: Using with restheadspec.Handler +func ExampleRestHeadSpec() { + db := // ... get database + registry := // ... get registry + + handler := restheadspec.NewHandler(db, registry) + + // Can be used as SpecHandler + var specHandler SpecHandler = handler + database := specHandler.GetDatabase() + + // Can be used as CRUDHandler + var crudHandler CRUDHandler = handler + crudHandler.Handle(w, r, params) + crudHandler.HandleGet(w, r, params) +} + +// Example 3: Using with funcspec.Handler +func ExampleFuncSpec() { + db := // ... get database + + handler := funcspec.NewHandler(db) + + // Can be used as SpecHandler + var specHandler SpecHandler = handler + database := specHandler.GetDatabase() + + // Can be used as QueryHandler + var queryHandler QueryHandler = handler + // funcspec has different methods: SqlQueryList() and SqlQuery() + // which return HTTP handler functions +} + +// Example 4: Polymorphic handler processing +func ProcessHandlers(handlers []SpecHandler) { + for _, handler := range handlers { + // All handlers expose the database + db := handler.GetDatabase() + + // Type switch for specific handler types + switch h := handler.(type) { + case CRUDHandler: + // This is resolvespec or restheadspec + // Can call Handle() and HandleGet() + _ = h + case QueryHandler: + // This is funcspec + // Can call SqlQueryList() and SqlQuery() + _ = h + } + } +} +*/ diff --git a/pkg/common/interfaces.go b/pkg/common/interfaces.go index 2ce5e17..f4fdecf 100644 --- a/pkg/common/interfaces.go +++ b/pkg/common/interfaces.go @@ -246,3 +246,39 @@ type PrimaryKeyNameProvider interface { type SchemaProvider interface { SchemaName() string } + +// SpecHandler interface represents common functionality across all spec handlers +// This is the base interface implemented by: +// - resolvespec.Handler: Handles CRUD operations via request body with explicit operation field +// - restheadspec.Handler: Handles CRUD operations via HTTP methods (GET/POST/PUT/DELETE) +// - funcspec.Handler: Handles custom SQL query execution with dynamic parameters +// +// The interface hierarchy is: +// +// SpecHandler (base) +// ├── CRUDHandler (resolvespec, restheadspec) +// └── QueryHandler (funcspec) +type SpecHandler interface { + // GetDatabase returns the underlying database connection + GetDatabase() Database +} + +// CRUDHandler interface for handlers that support CRUD operations +// This is implemented by resolvespec.Handler and restheadspec.Handler +type CRUDHandler interface { + SpecHandler + + // Handle processes API requests through router-agnostic interface + Handle(w ResponseWriter, r Request, params map[string]string) + + // HandleGet processes GET requests for metadata + HandleGet(w ResponseWriter, r Request, params map[string]string) +} + +// QueryHandler interface for handlers that execute SQL queries +// This is implemented by funcspec.Handler +// Note: funcspec uses standard http.ResponseWriter and *http.Request instead of common interfaces +type QueryHandler interface { + SpecHandler + // Methods are defined in funcspec package due to different function signature requirements +} diff --git a/pkg/funcspec/function_api.go b/pkg/funcspec/function_api.go index f28e5b1..8826914 100644 --- a/pkg/funcspec/function_api.go +++ b/pkg/funcspec/function_api.go @@ -32,6 +32,12 @@ func NewHandler(db common.Database) *Handler { } } +// GetDatabase returns the underlying database connection +// Implements common.SpecHandler interface +func (h *Handler) GetDatabase() common.Database { + return h.db +} + // Hooks returns the hook registry for this handler // Use this to register custom hooks for operations func (h *Handler) Hooks() *HookRegistry { diff --git a/pkg/resolvespec/handler.go b/pkg/resolvespec/handler.go index 3cd7b89..847d0e3 100644 --- a/pkg/resolvespec/handler.go +++ b/pkg/resolvespec/handler.go @@ -34,6 +34,12 @@ func NewHandler(db common.Database, registry common.ModelRegistry) *Handler { return handler } +// GetDatabase returns the underlying database connection +// Implements common.SpecHandler interface +func (h *Handler) GetDatabase() common.Database { + return h.db +} + // handlePanic is a helper function to handle panics with stack traces func (h *Handler) handlePanic(w common.ResponseWriter, method string, err interface{}) { stack := debug.Stack() diff --git a/pkg/resolvespec/resolvespec.go b/pkg/resolvespec/resolvespec.go index dbbd11c..715d88d 100644 --- a/pkg/resolvespec/resolvespec.go +++ b/pkg/resolvespec/resolvespec.go @@ -37,28 +37,46 @@ func NewStandardBunRouter() *router.StandardBunRouterAdapter { return router.NewStandardBunRouterAdapter() } +// MiddlewareFunc is a function that wraps an http.Handler with additional functionality +type MiddlewareFunc func(http.Handler) http.Handler + // SetupMuxRoutes sets up routes for the ResolveSpec API with Mux -func SetupMuxRoutes(muxRouter *mux.Router, handler *Handler) { - muxRouter.HandleFunc("/{schema}/{entity}", func(w http.ResponseWriter, r *http.Request) { +// authMiddleware is optional - if provided, routes will be protected with the middleware +// Example: SetupMuxRoutes(router, handler, func(h http.Handler) http.Handler { return security.NewAuthHandler(securityList, h) }) +func SetupMuxRoutes(muxRouter *mux.Router, handler *Handler, authMiddleware MiddlewareFunc) { + // Create handler functions + postEntityHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) reqAdapter := router.NewHTTPRequest(r) respAdapter := router.NewHTTPResponseWriter(w) handler.Handle(respAdapter, reqAdapter, vars) - }).Methods("POST") + }) - muxRouter.HandleFunc("/{schema}/{entity}/{id}", func(w http.ResponseWriter, r *http.Request) { + postEntityWithIDHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) reqAdapter := router.NewHTTPRequest(r) respAdapter := router.NewHTTPResponseWriter(w) handler.Handle(respAdapter, reqAdapter, vars) - }).Methods("POST") + }) - muxRouter.HandleFunc("/{schema}/{entity}", func(w http.ResponseWriter, r *http.Request) { + getEntityHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) reqAdapter := router.NewHTTPRequest(r) respAdapter := router.NewHTTPResponseWriter(w) handler.HandleGet(respAdapter, reqAdapter, vars) - }).Methods("GET") + }) + + // Apply authentication middleware if provided + if authMiddleware != nil { + postEntityHandler = authMiddleware(postEntityHandler).(http.HandlerFunc) + postEntityWithIDHandler = authMiddleware(postEntityWithIDHandler).(http.HandlerFunc) + getEntityHandler = authMiddleware(getEntityHandler).(http.HandlerFunc) + } + + // Register routes + muxRouter.Handle("/{schema}/{entity}", postEntityHandler).Methods("POST") + muxRouter.Handle("/{schema}/{entity}/{id}", postEntityWithIDHandler).Methods("POST") + muxRouter.Handle("/{schema}/{entity}", getEntityHandler).Methods("GET") } // Example usage functions for documentation: @@ -68,12 +86,20 @@ func ExampleWithGORM(db *gorm.DB) { // Create handler using GORM handler := NewHandlerWithGORM(db) - // Setup router + // Setup router without authentication muxRouter := mux.NewRouter() - SetupMuxRoutes(muxRouter, handler) + SetupMuxRoutes(muxRouter, handler, nil) // Register models // handler.RegisterModel("public", "users", &User{}) + + // To add authentication, pass a middleware function: + // import "github.com/bitechdev/ResolveSpec/pkg/security" + // secList := security.NewSecurityList(myProvider) + // authMiddleware := func(h http.Handler) http.Handler { + // return security.NewAuthHandler(secList, h) + // } + // SetupMuxRoutes(muxRouter, handler, authMiddleware) } // ExampleWithBun shows how to switch to Bun ORM @@ -88,9 +114,9 @@ func ExampleWithBun(bunDB *bun.DB) { // Create handler handler := NewHandler(dbAdapter, registry) - // Setup routes + // Setup routes without authentication muxRouter := mux.NewRouter() - SetupMuxRoutes(muxRouter, handler) + SetupMuxRoutes(muxRouter, handler, nil) } // SetupBunRouterRoutes sets up bunrouter routes for the ResolveSpec API diff --git a/pkg/restheadspec/handler.go b/pkg/restheadspec/handler.go index a58dcc5..329e468 100644 --- a/pkg/restheadspec/handler.go +++ b/pkg/restheadspec/handler.go @@ -38,6 +38,12 @@ func NewHandler(db common.Database, registry common.ModelRegistry) *Handler { return handler } +// GetDatabase returns the underlying database connection +// Implements common.SpecHandler interface +func (h *Handler) GetDatabase() common.Database { + return h.db +} + // Hooks returns the hook registry for this handler // Use this to register custom hooks for operations func (h *Handler) Hooks() *HookRegistry { diff --git a/pkg/restheadspec/restheadspec.go b/pkg/restheadspec/restheadspec.go index d51effe..7a19460 100644 --- a/pkg/restheadspec/restheadspec.go +++ b/pkg/restheadspec/restheadspec.go @@ -90,31 +90,51 @@ func NewStandardBunRouter() *router.StandardBunRouterAdapter { return router.NewStandardBunRouterAdapter() } +// MiddlewareFunc is a function that wraps an http.Handler with additional functionality +type MiddlewareFunc func(http.Handler) http.Handler + // SetupMuxRoutes sets up routes for the RestHeadSpec API with Mux -func SetupMuxRoutes(muxRouter *mux.Router, handler *Handler) { - // GET, POST, PUT, PATCH, DELETE for /{schema}/{entity} - muxRouter.HandleFunc("/{schema}/{entity}", func(w http.ResponseWriter, r *http.Request) { +// authMiddleware is optional - if provided, routes will be protected with the middleware +// Example: SetupMuxRoutes(router, handler, func(h http.Handler) http.Handler { return security.NewAuthHandler(securityList, h) }) +func SetupMuxRoutes(muxRouter *mux.Router, handler *Handler, authMiddleware MiddlewareFunc) { + // Create handler functions + entityHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) reqAdapter := router.NewHTTPRequest(r) respAdapter := router.NewHTTPResponseWriter(w) handler.Handle(respAdapter, reqAdapter, vars) - }).Methods("GET", "POST") + }) - // GET, PUT, PATCH, DELETE for /{schema}/{entity}/{id} - muxRouter.HandleFunc("/{schema}/{entity}/{id}", func(w http.ResponseWriter, r *http.Request) { + entityWithIDHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) reqAdapter := router.NewHTTPRequest(r) respAdapter := router.NewHTTPResponseWriter(w) handler.Handle(respAdapter, reqAdapter, vars) - }).Methods("GET", "PUT", "PATCH", "DELETE", "POST") + }) - // GET for metadata (using HandleGet) - muxRouter.HandleFunc("/{schema}/{entity}/metadata", func(w http.ResponseWriter, r *http.Request) { + metadataHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) reqAdapter := router.NewHTTPRequest(r) respAdapter := router.NewHTTPResponseWriter(w) handler.HandleGet(respAdapter, reqAdapter, vars) - }).Methods("GET") + }) + + // Apply authentication middleware if provided + if authMiddleware != nil { + entityHandler = authMiddleware(entityHandler).(http.HandlerFunc) + entityWithIDHandler = authMiddleware(entityWithIDHandler).(http.HandlerFunc) + metadataHandler = authMiddleware(metadataHandler).(http.HandlerFunc) + } + + // Register routes + // GET, POST for /{schema}/{entity} + muxRouter.Handle("/{schema}/{entity}", entityHandler).Methods("GET", "POST") + + // GET, PUT, PATCH, DELETE, POST for /{schema}/{entity}/{id} + muxRouter.Handle("/{schema}/{entity}/{id}", entityWithIDHandler).Methods("GET", "PUT", "PATCH", "DELETE", "POST") + + // GET for metadata (using HandleGet) + muxRouter.Handle("/{schema}/{entity}/metadata", metadataHandler).Methods("GET") } // Example usage functions for documentation: @@ -124,12 +144,20 @@ func ExampleWithGORM(db *gorm.DB) { // Create handler using GORM handler := NewHandlerWithGORM(db) - // Setup router + // Setup router without authentication muxRouter := mux.NewRouter() - SetupMuxRoutes(muxRouter, handler) + SetupMuxRoutes(muxRouter, handler, nil) // Register models // handler.registry.RegisterModel("public.users", &User{}) + + // To add authentication, pass a middleware function: + // import "github.com/bitechdev/ResolveSpec/pkg/security" + // secList := security.NewSecurityList(myProvider) + // authMiddleware := func(h http.Handler) http.Handler { + // return security.NewAuthHandler(secList, h) + // } + // SetupMuxRoutes(muxRouter, handler, authMiddleware) } // ExampleWithBun shows how to switch to Bun ORM @@ -144,9 +172,9 @@ func ExampleWithBun(bunDB *bun.DB) { // Create handler handler := NewHandler(dbAdapter, registry) - // Setup routes + // Setup routes without authentication muxRouter := mux.NewRouter() - SetupMuxRoutes(muxRouter, handler) + SetupMuxRoutes(muxRouter, handler, nil) } // SetupBunRouterRoutes sets up bunrouter routes for the RestHeadSpec API diff --git a/pkg/security/middleware.go b/pkg/security/middleware.go index 2f73683..2540a7d 100644 --- a/pkg/security/middleware.go +++ b/pkg/security/middleware.go @@ -243,3 +243,158 @@ func GetUserMeta(ctx context.Context) (map[string]any, bool) { meta, ok := ctx.Value(UserMetaKey).(map[string]any) return meta, ok } + +// // Handler adapters for resolvespec/restheadspec compatibility +// // These functions allow using NewAuthHandler and NewOptionalAuthHandler with custom handler abstractions + +// // SpecHandlerAdapter is an interface for handler adapters that need authentication +// // Implement this interface to create adapters for custom handler types +// type SpecHandlerAdapter interface { +// // AdaptToHTTPHandler converts the custom handler to a standard http.Handler +// AdaptToHTTPHandler() http.Handler +// } + +// // ResolveSpecHandlerAdapter adapts a resolvespec/restheadspec handler method to http.Handler +// type ResolveSpecHandlerAdapter struct { +// // HandlerMethod is the method to call (e.g., handler.Handle, handler.HandleGet) +// HandlerMethod func(w any, r any, params map[string]string) +// // Params are the route parameters (e.g., {"schema": "public", "entity": "users"}) +// Params map[string]string +// // RequestAdapter converts *http.Request to the custom Request interface +// // Use router.NewHTTPRequest from pkg/common/adapters/router +// RequestAdapter func(*http.Request) any +// // ResponseAdapter converts http.ResponseWriter to the custom ResponseWriter interface +// // Use router.NewHTTPResponseWriter from pkg/common/adapters/router +// ResponseAdapter func(http.ResponseWriter) any +// } + +// // AdaptToHTTPHandler implements SpecHandlerAdapter +// func (a *ResolveSpecHandlerAdapter) AdaptToHTTPHandler() http.Handler { +// return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { +// req := a.RequestAdapter(r) +// resp := a.ResponseAdapter(w) +// a.HandlerMethod(resp, req, a.Params) +// }) +// } + +// // WrapSpecHandler wraps a spec handler adapter with authentication +// // Use this to apply NewAuthHandler or NewOptionalAuthHandler to resolvespec/restheadspec handlers +// // +// // Example with required auth: +// // +// // adapter := &security.ResolveSpecHandlerAdapter{ +// // HandlerMethod: handler.Handle, +// // Params: map[string]string{"schema": "public", "entity": "users"}, +// // RequestAdapter: func(r *http.Request) any { return router.NewHTTPRequest(r) }, +// // ResponseAdapter: func(w http.ResponseWriter) any { return router.NewHTTPResponseWriter(w) }, +// // } +// // authHandler := security.WrapSpecHandler(securityList, adapter, false) +// // muxRouter.Handle("/api/users", authHandler) +// func WrapSpecHandler(securityList *SecurityList, adapter SpecHandlerAdapter, optional bool) http.Handler { +// httpHandler := adapter.AdaptToHTTPHandler() +// if optional { +// return NewOptionalAuthHandler(securityList, httpHandler) +// } +// return NewAuthHandler(securityList, httpHandler) +// } + +// // MuxRouteBuilder helps build authenticated routes with Gorilla Mux +// type MuxRouteBuilder struct { +// securityList *SecurityList +// requestAdapter func(*http.Request) any +// responseAdapter func(http.ResponseWriter) any +// paramExtractor func(*http.Request) map[string]string +// } + +// // NewMuxRouteBuilder creates a route builder for Gorilla Mux with standard router adapters +// // Usage: +// // +// // builder := security.NewMuxRouteBuilder(securityList, router.NewHTTPRequest, router.NewHTTPResponseWriter) +// func NewMuxRouteBuilder( +// securityList *SecurityList, +// requestAdapter func(*http.Request) any, +// responseAdapter func(http.ResponseWriter) any, +// ) *MuxRouteBuilder { +// return &MuxRouteBuilder{ +// securityList: securityList, +// requestAdapter: requestAdapter, +// responseAdapter: responseAdapter, +// paramExtractor: nil, // Will be set per route using mux.Vars +// } +// } + +// // HandleAuth creates an authenticated route handler +// // pattern: the route pattern (e.g., "/{schema}/{entity}") +// // handler: the handler method to call (e.g., handler.Handle) +// // optional: true for optional auth (guest fallback), false for required auth (401 on failure) +// // methods: HTTP methods (e.g., "GET", "POST") +// // +// // Usage: +// // +// // builder.HandleAuth(router, "/{schema}/{entity}", handler.Handle, false, "POST") +// func (b *MuxRouteBuilder) HandleAuth( +// router interface { +// HandleFunc(pattern string, f func(http.ResponseWriter, *http.Request)) interface{ Methods(...string) interface{} } +// }, +// pattern string, +// handlerMethod func(w any, r any, params map[string]string), +// optional bool, +// methods ...string, +// ) { +// router.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) { +// // Extract params using the registered extractor or default to empty map +// var params map[string]string +// if b.paramExtractor != nil { +// params = b.paramExtractor(r) +// } else { +// params = make(map[string]string) +// } + +// adapter := &ResolveSpecHandlerAdapter{ +// HandlerMethod: handlerMethod, +// Params: params, +// RequestAdapter: b.requestAdapter, +// ResponseAdapter: b.responseAdapter, +// } +// authHandler := WrapSpecHandler(b.securityList, adapter, optional) +// authHandler.ServeHTTP(w, r) +// }).Methods(methods...) +// } + +// // SetParamExtractor sets a custom parameter extractor function +// // For Gorilla Mux, you would use: builder.SetParamExtractor(mux.Vars) +// func (b *MuxRouteBuilder) SetParamExtractor(extractor func(*http.Request) map[string]string) { +// b.paramExtractor = extractor +// } + +// // SetupAuthenticatedSpecRoutes sets up all standard resolvespec/restheadspec routes with authentication +// // This is a convenience function that sets up the common route patterns +// // +// // Usage: +// // +// // security.SetupAuthenticatedSpecRoutes(router, handler, securityList, router.NewHTTPRequest, router.NewHTTPResponseWriter, mux.Vars) +// func SetupAuthenticatedSpecRoutes( +// router interface { +// HandleFunc(pattern string, f func(http.ResponseWriter, *http.Request)) interface{ Methods(...string) interface{} } +// }, +// handler interface { +// Handle(w any, r any, params map[string]string) +// HandleGet(w any, r any, params map[string]string) +// }, +// securityList *SecurityList, +// requestAdapter func(*http.Request) any, +// responseAdapter func(http.ResponseWriter) any, +// paramExtractor func(*http.Request) map[string]string, +// ) { +// builder := NewMuxRouteBuilder(securityList, requestAdapter, responseAdapter) +// builder.SetParamExtractor(paramExtractor) + +// // POST /{schema}/{entity} +// builder.HandleAuth(router, "/{schema}/{entity}", handler.Handle, false, "POST") + +// // POST /{schema}/{entity}/{id} +// builder.HandleAuth(router, "/{schema}/{entity}/{id}", handler.Handle, false, "POST") + +// // GET /{schema}/{entity} +// builder.HandleAuth(router, "/{schema}/{entity}", handler.HandleGet, false, "GET") +// } diff --git a/pkg/security/setup_example.go b/pkg/security/setup_example.go index 49e503a..a5ded81 100644 --- a/pkg/security/setup_example.go +++ b/pkg/security/setup_example.go @@ -68,12 +68,14 @@ func ExampleDatabaseSecurity(gormDB interface{}, sqlDB *sql.DB) (http.Handler, e // Step 5: Setup security securityList := SetupSecurityProvider(handler, provider) - // Step 6: Create router and setup routes + // Step 6: Create router and setup routes with authentication router := mux.NewRouter() - restheadspec.SetupMuxRoutes(router, handler) + authMiddleware := func(h http.Handler) http.Handler { + return NewAuthHandler(securityList, h) + } + restheadspec.SetupMuxRoutes(router, handler, authMiddleware) - // Step 7: Apply middleware in correct order - router.Use(NewAuthMiddleware(securityList)) + // Step 7: Apply additional security middleware router.Use(SetSecurityMiddleware(securityList)) return router, nil @@ -95,9 +97,11 @@ func ExampleHeaderAuthentication(gormDB interface{}, sqlDB *sql.DB) (*mux.Router securityList := SetupSecurityProvider(handler, provider) router := mux.NewRouter() - restheadspec.SetupMuxRoutes(router, handler) + authMiddleware := func(h http.Handler) http.Handler { + return NewAuthHandler(securityList, h) + } + restheadspec.SetupMuxRoutes(router, handler, authMiddleware) - router.Use(NewAuthMiddleware(securityList)) router.Use(SetSecurityMiddleware(securityList)) return router, nil @@ -150,9 +154,11 @@ func ExampleConfigSecurity(gormDB interface{}) (*mux.Router, error) { securityList := SetupSecurityProvider(handler, provider) router := mux.NewRouter() - restheadspec.SetupMuxRoutes(router, handler) + authMiddleware := func(h http.Handler) http.Handler { + return NewAuthHandler(securityList, h) + } + restheadspec.SetupMuxRoutes(router, handler, authMiddleware) - router.Use(NewAuthMiddleware(securityList)) router.Use(SetSecurityMiddleware(securityList)) return router, nil @@ -282,10 +288,12 @@ func CompleteServerExample(gormDB interface{}, sqlDB *sql.DB) http.Handler { // Add auth routes (login/logout) SetupAuthRoutes(router, securityList) - // Add API routes with security middleware + // Add API routes with authentication apiRouter := router.PathPrefix("/api").Subrouter() - restheadspec.SetupMuxRoutes(apiRouter, handler) - apiRouter.Use(NewAuthMiddleware(securityList)) + authMiddleware := func(h http.Handler) http.Handler { + return NewAuthHandler(securityList, h) + } + restheadspec.SetupMuxRoutes(apiRouter, handler, authMiddleware) apiRouter.Use(SetSecurityMiddleware(securityList)) return router