package app import ( "context" "fmt" "net/http" "time" "git.linuxforward.com/byop/byop-engine/auth" "git.linuxforward.com/byop/byop-engine/cloud" "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/services" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/gin-gonic/gin" ) func (a *App) initCommonServices() error { // Initialize database db, err := dbstore.NewSQLiteStore(a.cnf.Database.DSN) if err != nil { return errors.Wrap(err, "initialize database") } a.database = db // 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, a.database, // Added database argument ) // Initialize providers if err := a.loadProviders(); err != nil { return errors.Wrap(err, "load providers") } // If debug mode, create default admin user if a.cnf.Debug { db.CreateDefaultAdmin(context.Background()) // Added context argument a.entry.Info("Debug mode enabled, default admin user created") // Output the admin credentials a.entry.WithFields(logrus.Fields{ "email": "admin@byop.local", "password": "admin123", }).Info("Default admin credentials") } // Get Ovh provider ovhProvider, _ := cloud.GetProvider("ovh") a.previewService = services.NewPreviewServiceManager(a.database, ovhProvider, a.cnf.LocalPreview, a.cnf, a.registryClient, a.cnf.ReistryUrl, "", "") a.builderService = services.NewBuilderService(a.database, a.buildkitClient, a.registryClient, 5) a.entry.Info("Services initialized successfully, including authentication and database manager") return nil } func (a *App) initHandlers() error { // Initialize UserModule a.userHandler = handlers.NewUserHandler(a.database) // Initialize ClientModule a.clientHandler = handlers.NewClientHandler(a.database) // Initialize ComponentModule a.componentHandler = handlers.NewComponentHandler(a.database, a.builderService, a.cnf.ReistryUrl) // Initialize AppModule a.appHandler = handlers.NewAppsHandler(a.database, a.previewService) // Initialize DeploymentModule a.deploymentHandler = handlers.NewDeploymentHandler(a.database) // Initialize authentication handler a.authHandler = handlers.NewAuthHandler(a.authService, a.database) // Initialize resource handlers a.providerHandler = handlers.NewProviderHandler() // Initialize PreviewHandler a.previewHandler = handlers.NewPreviewHandler(a.previewService, a.database) 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() { // 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.userHandler.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.clientHandler.ListClients) clients.POST("", a.clientHandler.CreateClient) clients.GET("/:id", a.clientHandler.GetClient) clients.PUT("/:id", a.clientHandler.UpdateClient) clients.DELETE("/:id", a.clientHandler.DeleteClient) clients.GET("/:id/deployments", a.clientHandler.GetClientDeployments) // User routes - registering both with and without trailing slash users := protected.Group("/users") users.GET("", a.userHandler.ListUsers) users.GET("/:id", a.userHandler.GetUser) users.PUT("/:id", a.userHandler.UpdateUser) users.DELETE("/:id", a.userHandler.DeleteUser) users.GET("/:id/deployments", a.userHandler.GetUserDeployments) // Component routes (formerly Apps) components := protected.Group("/components") components.GET("", a.componentHandler.ListComponents) components.POST("", a.componentHandler.CreateComponent) components.GET("/:id", a.componentHandler.GetComponent) components.PUT("/:id", a.componentHandler.UpdateComponent) components.DELETE("/:id", a.componentHandler.DeleteComponent) components.GET("/:id/deployments", a.componentHandler.GetComponentDeployments) // App routes (formerly Templates) apps := protected.Group("/apps") apps.GET("", a.appHandler.ListApps) apps.POST("", a.appHandler.CreateApp) apps.GET("/:id", a.appHandler.GetApp) apps.PUT("/:id", a.appHandler.UpdateApp) apps.DELETE("/:id", a.appHandler.DeleteApp) apps.GET("/:id/deployments", a.appHandler.GetAppDeployments) // App preview route apps.POST("/:id/preview", a.appHandler.CreateAppPreview) apps.GET("/:id/preview", a.appHandler.GetAppPreview) apps.DELETE("/:id/preview", a.appHandler.DeleteAppPreview) // Deployment routes - need to handle both versions deployments := protected.Group("/deployments") deployments.GET("", a.deploymentHandler.ListDeployments) deployments.POST("", a.deploymentHandler.CreateDeployment) deployments.GET("/:id", a.deploymentHandler.GetDeployment) deployments.PUT("/:id", a.deploymentHandler.UpdateDeployment) deployments.DELETE("/:id", a.deploymentHandler.DeleteDeployment) deployments.PUT("/:id/status", a.deploymentHandler.UpdateDeploymentStatus) // deployments.GET("/by-client/:clientId", a.deploymentHandler.GetDeploymentsByClient) // deployments.GET("/by-app/:appId", a.deploymentHandler.GetDeploymentsByTemplate) // Was by-template // deployments.GET("/by-user/:userId", a.deploymentHandler.GetDeploymentsByUser) // // Add other resource routes as needed a.entry.Info("Routes configured successfully") }