package app import ( "fmt" "time" "git.linuxforward.com/byop/byop-engine/auth" "git.linuxforward.com/byop/byop-engine/cloud" "git.linuxforward.com/byop/byop-engine/dbmanager" "git.linuxforward.com/byop/byop-engine/dbstore" "git.linuxforward.com/byop/byop-engine/handlers" mw "git.linuxforward.com/byop/byop-engine/middleware" "git.linuxforward.com/byop/byop-engine/models" "git.linuxforward.com/byop/byop-engine/services" "github.com/pkg/errors" "github.com/gin-gonic/gin" ) func (a *App) initCommonServices() error { // Initialize token store a.tokenStore = auth.NewMemoryTokenStore(time.Duration(a.cnf.Auth.CleanupInterval)) // Initialize authentication service a.authService = auth.NewJWTService( []byte(a.cnf.Auth.PrivateKey), time.Duration(a.cnf.Auth.TokenDuration), a.tokenStore, ) // Initialize providers if err := a.loadProviders(); err != nil { return errors.Wrap(err, "load providers") } // Initialize database manager switch a.cnf.Database.Type { case "sqlite": var err error a.dbManager, err = dbmanager.NewSQLiteManager(a.cnf.Database.Sqlite.File) if err != nil { return fmt.Errorf("create sqlite manager: %w", err) } // case "postgres": // a.dbManager = dbmanager.NewPostgresDbManager(a.cnf.Db.Host, a.cnf.Db.Port, a.cnf.Db.User, a.cnf.Db.Password, a.cnf.Db.Name) // case "mysql": // a.dbManager = dbmanager.NewMySQLDbManager(a.cnf.Db.Host, a.cnf.Db.Port, a.cnf.Db.User, a.cnf.Db.Password, a.cnf.Db.Name) default: return fmt.Errorf("unsupported database type: %s", a.cnf.Database.Type) } if err := a.dbManager.Connect(); err != nil { return fmt.Errorf("connect to database: %w", err) } // Auto migrate database schema if err := a.dbManager.Migrate( &models.User{}, &models.Client{}, &models.Component{}, &models.Blueprint{}, &models.Deployment{}, &models.DeployedComponent{}, &models.DeployedComponentResource{}, // Add other models here ); err != nil { return fmt.Errorf("migrate database: %w", err) } a.entry.Info("Services initialized successfully, including authentication and database manager") return nil } func (a *App) initHandlers() error { // Initialize UserModule userStore := dbstore.NewUserStore(a.dbManager) userService := services.NewUserService(userStore) userHandler := handlers.NewUserHandler(userService) a.userModule = &UserModule{ Store: userStore, Service: userService, Handler: userHandler, } // Initialize ClientModule clientStore := dbstore.NewClientStore(a.dbManager) clientService := services.NewClientService(clientStore) clientHandler := handlers.NewClientHandler(clientService) a.clientModule = &ClientModule{ Store: clientStore, Service: clientService, Handler: clientHandler, } // Initialize ComponentModule componentStore := dbstore.NewComponentStore(a.dbManager) componentService := services.NewComponentService(componentStore) componentHandler := handlers.NewComponentHandler(componentService) a.componentModule = &ComponentModule{ Store: componentStore, Service: componentService, Handler: componentHandler, } // Initialize BlueprintModule blueprintStore := dbstore.NewBlueprintStore(a.dbManager) blueprintService := services.NewBlueprintService(blueprintStore) blueprintHandler := handlers.NewBlueprintHandler(blueprintService) a.blueprintModule = &BlueprintModule{ Store: blueprintStore, Service: blueprintService, Handler: blueprintHandler, } // Initialize DeploymentModule deploymentStore := dbstore.NewDeploymentStore(a.dbManager) deploymentService := services.NewDeploymentService( deploymentStore, componentStore, blueprintStore, clientStore, ) deploymentHandler := handlers.NewDeploymentHandler(deploymentService) a.deploymentModule = &DeploymentModule{ Store: deploymentStore, Service: deploymentService, Handler: deploymentHandler, } // Initialize authentication handler a.authHandler = handlers.NewAuthHandler(a.authService, a.userModule.Store) // Initialize resource handlers a.providerHandler = handlers.NewProviderHandler() // Initialize other handlers... a.entry.Info("Handlers initialized successfully") return nil } // Updated loadProviders method func (a *App) loadProviders() error { for name, cnf := range a.cnf.Providers { // Use the new InitializeProvider function instead of GetProvider + Initialize err := cloud.InitializeProvider(name, cnf) if err != nil { return fmt.Errorf("initialize provider %s: %w", name, err) } a.entry.WithField("provider", name).Info("Provider initialized") } a.entry.Info("All providers loaded successfully") return nil } func (a *App) setupRoutes() { // API version group v1 := a.rtr.Group("/api/v1") // Auth routes - no middleware required // Public routes (no authentication required) public := v1.Group("/") public.POST("/users", a.userModule.Handler.CreateUser) // Allow user registration without authentication // Auth routes - no middleware required public.POST("/login", a.authHandler.Login) // Allow login without authentication public.POST("/refresh-token", a.authHandler.RefreshToken) // Allow token refresh without authentication public.POST("/logout", a.authHandler.Logout) // Allow logout without authentication public.GET("/health", func(c *gin.Context) { c.JSON(200, gin.H{"status": "ok"}) }) // Protected routes - require authentication protected := v1.Group("/") protected.Use(mw.Auth(a.authService)) // Auth middleware with service dependency // Register resource routes providers := protected.Group("/providers") a.providerHandler.RegisterRoutes(providers) // Client routes - registering both with and without trailing slash clients := protected.Group("/clients") clients.GET("", a.clientModule.Handler.ListClients) // Without trailing slash clients.GET("/", a.clientModule.Handler.ListClients) // With trailing slash clients.POST("", a.clientModule.Handler.CreateClient) // Without trailing slash clients.POST("/", a.clientModule.Handler.CreateClient) // With trailing slash clients.GET("/:id", a.clientModule.Handler.GetClient) clients.PUT("/:id", a.clientModule.Handler.UpdateClient) clients.DELETE("/:id", a.clientModule.Handler.DeleteClient) clients.GET("/:id/deployments", a.clientModule.Handler.GetClientDeployments) // User routes - registering both with and without trailing slash users := protected.Group("/users") users.GET("", a.userModule.Handler.ListUsers) // Without trailing slash users.GET("/", a.userModule.Handler.ListUsers) // With trailing slash users.GET("/:id", a.userModule.Handler.GetUser) users.PUT("/:id", a.userModule.Handler.UpdateUser) users.DELETE("/:id", a.userModule.Handler.DeleteUser) users.GET("/:id/deployments", a.userModule.Handler.GetUserDeployments) // Component routes - registering both with and without trailing slash components := protected.Group("/components") components.GET("", a.componentModule.Handler.ListComponents) // Without trailing slash components.GET("/", a.componentModule.Handler.ListComponents) // With trailing slash components.POST("", a.componentModule.Handler.CreateComponent) // Without trailing slash components.POST("/", a.componentModule.Handler.CreateComponent) // With trailing slash components.GET("/:id", a.componentModule.Handler.GetComponent) components.PUT("/:id", a.componentModule.Handler.UpdateComponent) components.DELETE("/:id", a.componentModule.Handler.DeleteComponent) components.GET("/:id/deployments", a.componentModule.Handler.GetComponentDeployments) // Blueprint routes - registering both with and without trailing slash blueprints := protected.Group("/blueprints") blueprints.GET("", a.blueprintModule.Handler.ListBlueprints) // Without trailing slash blueprints.GET("/", a.blueprintModule.Handler.ListBlueprints) // With trailing slash blueprints.POST("", a.blueprintModule.Handler.CreateBlueprint) // Without trailing slash blueprints.POST("/", a.blueprintModule.Handler.CreateBlueprint) // With trailing slash blueprints.GET("/:id", a.blueprintModule.Handler.GetBlueprint) blueprints.PUT("/:id", a.blueprintModule.Handler.UpdateBlueprint) blueprints.DELETE("/:id", a.blueprintModule.Handler.DeleteBlueprint) blueprints.GET("/:id/deployments", a.blueprintModule.Handler.GetBlueprintDeployments) // Deployment routes - need to handle both versions deployments := protected.Group("/deployments") deployments.GET("", a.deploymentModule.Handler.ListDeployments) deployments.GET("/", a.deploymentModule.Handler.ListDeployments) deployments.POST("", a.deploymentModule.Handler.CreateDeployment) deployments.GET("/:id", a.deploymentModule.Handler.GetDeployment) deployments.PUT("/:id", a.deploymentModule.Handler.UpdateDeployment) deployments.DELETE("/:id", a.deploymentModule.Handler.DeleteDeployment) deployments.PUT("/:id/status", a.deploymentModule.Handler.UpdateDeploymentStatus) deployments.GET("/by-client/:clientId", a.deploymentModule.Handler.GetDeploymentsByClient) deployments.GET("/by-blueprint/:blueprintId", a.deploymentModule.Handler.GetDeploymentsByBlueprint) deployments.GET("/by-user/:userId", a.deploymentModule.Handler.GetDeploymentsByUser) a.entry.Info("Routes configured successfully") }