From 1763a8a49ef114e400d8cae5636f4af1b63c6986 Mon Sep 17 00:00:00 2001 From: Michael Freeman Date: Sun, 6 Oct 2024 11:02:24 -0500 Subject: [PATCH] wip --- cmd/api/main.go | 37 ++++++++++++++++--- .../20240226153000_create_collections.go | 3 +- .../20240226153100_create_indexes.go | 34 +++++++++-------- pkg/api/middleware/rbac.go | 8 +--- 4 files changed, 53 insertions(+), 29 deletions(-) diff --git a/cmd/api/main.go b/cmd/api/main.go index 0d42134..2f21080 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -3,7 +3,7 @@ package main import ( "github.com/carverauto/eventrunner/cmd/api/migrations" "github.com/carverauto/eventrunner/pkg/api/handlers" - "github.com/carverauto/eventrunner/pkg/api/middleware" + middlewarePkg "github.com/carverauto/eventrunner/pkg/api/middleware" "gofr.dev/pkg/gofr" "gofr.dev/pkg/gofr/datasource/mongo" ) @@ -23,13 +23,40 @@ func main() { userHandler := &handlers.UserHandler{} // Tenant routes (protected by API key) - app.POST("/tenants", tenantHandler.Create, middleware.AuthenticateAPIKey) - app.GET("/tenants", tenantHandler.GetAll, middleware.AuthenticateAPIKey) + app.POST("/tenants", adapt(tenantHandler.Create, middlewarePkg.AuthenticateAPIKey)) + app.GET("/tenants", adapt(tenantHandler.GetAll, middlewarePkg.AuthenticateAPIKey)) // User routes (protected by API key and role-based access) - app.POST("/tenants/{tenant_id}/users", userHandler.Create, middleware.AuthenticateAPIKey, middleware.RequireRole("admin")) - app.GET("/tenants/{tenant_id}/users", userHandler.GetAll, middleware.AuthenticateAPIKey, middleware.RequireRole("admin", "user")) + app.POST("/tenants/{tenant_id}/users", adapt(userHandler.Create, + middlewarePkg.AuthenticateAPIKey, + middlewarePkg.RequireRole("admin"))) + app.GET("/tenants/{tenant_id}/users", adapt(userHandler.GetAll, + middlewarePkg.AuthenticateAPIKey, + middlewarePkg.RequireRole("admin", "user"))) // Run the application app.Run() } + +// adapt converts a handler func and middlewares into a gofr.Handler +func adapt(h interface{}, middlewares ...handlers.Middleware) gofr.Handler { + return func(c *gofr.Context) (interface{}, error) { + var handler handlers.Handler + switch h := h.(type) { + case func(*gofr.Context) (interface{}, error): + handler = handlers.HandlerFunc(h) + default: + if h, ok := h.(handlers.Handler); ok { + handler = h + } else { + panic("unsupported handler type") + } + } + + for i := len(middlewares) - 1; i >= 0; i-- { + handler = middlewares[i](handler) + } + + return handler.Handle(c) + } +} diff --git a/cmd/api/migrations/20240226153000_create_collections.go b/cmd/api/migrations/20240226153000_create_collections.go index 666cde4..3d7850b 100644 --- a/cmd/api/migrations/20240226153000_create_collections.go +++ b/cmd/api/migrations/20240226153000_create_collections.go @@ -11,7 +11,8 @@ func createCollections() migration.Migrate { UP: func(d migration.Datasource) error { collections := []string{"tenants", "users", "api_keys"} for _, coll := range collections { - if err := d.Mongo.CreateCollection(d.Context, coll); err != nil { + _, err := d.SQL.Exec("db.createCollection(\"" + coll + "\")") + if err != nil { return err } } diff --git a/cmd/api/migrations/20240226153100_create_indexes.go b/cmd/api/migrations/20240226153100_create_indexes.go index f9e92b6..98ca6fa 100644 --- a/cmd/api/migrations/20240226153100_create_indexes.go +++ b/cmd/api/migrations/20240226153100_create_indexes.go @@ -9,24 +9,26 @@ import ( func createIndexes() migration.Migrate { return migration.Migrate{ UP: func(d migration.Datasource) error { - // Create unique index on tenant name - if err := d.Mongo.CreateIndex(d.Context, "tenants", map[string]interface{}{"name": 1}, true); err != nil { - return err + indexes := []struct { + collection string + keys string + unique bool + }{ + {collection: "tenants", keys: "name", unique: true}, + {collection: "users", keys: "email", unique: true}, + {collection: "users", keys: "tenant_id", unique: false}, + {collection: "api_keys", keys: "key", unique: true}, } - // Create unique index on user email - if err := d.Mongo.CreateIndex(d.Context, "users", map[string]interface{}{"email": 1}, true); err != nil { - return err - } - - // Create index on user's tenant_id for faster queries - if err := d.Mongo.CreateIndex(d.Context, "users", map[string]interface{}{"tenant_id": 1}, false); err != nil { - return err - } - - // Create unique index on API key - if err := d.Mongo.CreateIndex(d.Context, "api_keys", map[string]interface{}{"key": 1}, true); err != nil { - return err + for _, idx := range indexes { + uniqueStr := "false" + if idx.unique { + uniqueStr = "true" + } + _, err := d.SQL.Exec("db." + idx.collection + ".createIndex({" + idx.keys + ": 1}, {unique: " + uniqueStr + "})") + if err != nil { + return err + } } return nil diff --git a/pkg/api/middleware/rbac.go b/pkg/api/middleware/rbac.go index 6d59d12..50f1c89 100644 --- a/pkg/api/middleware/rbac.go +++ b/pkg/api/middleware/rbac.go @@ -5,7 +5,6 @@ import ( "github.com/carverauto/eventrunner/pkg/eventingest" ) -// AuthenticateAPIKey checks if the API key is valid and active, otherwise returns an error. // AuthenticateAPIKey checks if the API key is valid and active, otherwise returns an error. func AuthenticateAPIKey(next func(customctx.Context) (interface{}, error)) func(customctx.Context) (interface{}, error) { return func(cc customctx.Context) (interface{}, error) { @@ -14,16 +13,11 @@ func AuthenticateAPIKey(next func(customctx.Context) (interface{}, error)) func( return nil, eventingest.NewAuthError("Missing API Key") } - /* - tenantID, customerID, err := cc.GetAPIKey(apiKey) - if err != nil { - return nil, eventingest.NewAuthError("Invalid API Key") - } - */ tenantID, ok := cc.GetUUIDClaim("tenant_id") if !ok { return nil, eventingest.NewAuthError("Missing tenant ID") } + customerID, ok := cc.GetUUIDClaim("customer_id") if !ok { return nil, eventingest.NewAuthError("Missing customer ID")