package app import ( "fmt" "net/http" "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{}, // Renamed from App &models.App{}, // Renamed from Template &models.Deployment{}, &models.DeployedApp{}, &models.DeployedAppResource{}, // 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 (formerly AppModule) componentStore := dbstore.NewComponentStore(a.dbManager) componentService := services.NewComponentService(componentStore) componentHandler := handlers.NewComponentHandler(componentService) a.componentModule = &ComponentModule{ Store: componentStore, Service: componentService, Handler: componentHandler, } // Initialize AppModule (formerly TemplateModule) appStore := dbstore.NewAppStore(a.dbManager) appService := services.NewAppService(appStore) appsHandler := handlers.NewAppsHandler(appService) a.appModule = &AppModule{ Store: appStore, Service: appService, Handler: appsHandler, } // Initialize DeploymentModule deploymentStore := dbstore.NewDeploymentStore(a.dbManager) deploymentService := services.NewDeploymentService( deploymentStore, componentStore, appStore, 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 } func (a *App) loadProviders() error { for name, config := range a.cnf.Providers { provider, ok := cloud.GetProvider(name) if !ok { return fmt.Errorf("provider %s not found", name) } err := provider.Initialize(config) 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() { // Add CORS middleware to handle all cross-origin requests a.rtr.Use(func(c *gin.Context) { c.Writer.Header().Set("Access-Control-Allow-Origin", "*") c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS") c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With") c.Writer.Header().Set("Access-Control-Allow-Credentials", "true") // Allow redirects c.Writer.Header().Set("Access-Control-Expose-Headers", "Location") c.Writer.Header().Set("Access-Control-Max-Age", "86400") // Cache preflight response for 24 hours c.Writer.Header().Set("Content-Type", "application/json; charset=utf-8") // Handle preflight OPTIONS requests if c.Request.Method == http.MethodOptions { c.AbortWithStatus(http.StatusNoContent) return } c.Next() }) // 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 clients := protected.Group("/clients") clients.GET("", a.clientModule.Handler.ListClients) clients.POST("", a.clientModule.Handler.CreateClient) 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 users := protected.Group("/users") users.GET("", a.userModule.Handler.ListUsers) 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 (formerly Apps) components := protected.Group("/components") components.GET("", a.componentModule.Handler.ListComponents) components.POST("", a.componentModule.Handler.CreateComponent) 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) // App routes (formerly Templates) apps := protected.Group("/apps") apps.GET("", a.appModule.Handler.ListApps) apps.POST("", a.appModule.Handler.CreateApp) apps.GET("/:id", a.appModule.Handler.GetApp) apps.PUT("/:id", a.appModule.Handler.UpdateApp) apps.DELETE("/:id", a.appModule.Handler.DeleteApp) apps.GET("/:id/deployments", a.appModule.Handler.GetAppDeployments) // Deployment routes deployments := protected.Group("/deployments") 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-app/:appId", a.deploymentModule.Handler.GetDeploymentsByTemplate) // Was by-template // deployments.GET("/by-user/:userId", a.deploymentModule.Handler.GetDeploymentsByUser) // // Add other resource routes as needed a.entry.Info("Routes configured successfully") }