package server import ( "database/sql" "fmt" "net/http" "os" "github.com/a-h/templ/examples/integration-gin/gintemplrenderer" "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" "github.com/haydenhargreaves/Potion/internal/app/handlers" "github.com/haydenhargreaves/Potion/internal/app/service" domain "github.com/haydenhargreaves/Potion/internal/domain/server" "github.com/haydenhargreaves/Potion/internal/infrastructure/auth" "github.com/haydenhargreaves/Potion/internal/infrastructure/database/repository" "github.com/joho/godotenv" _ "github.com/lib/pq" ) type Server struct { port int Router *gin.Engine config cors.Config DB *sql.DB } // Init initializes the server with the provided port. CORS settings are defined here. // A pointer to a server object is returned which allows for method chaining. func Init(port int) *Server { // TODO: Set this to release in prod gin.SetMode(gin.DebugMode) server := &Server{ Router: gin.Default(), port: port, config: cors.DefaultConfig(), } // Some stuff for templ rendering htmlRenderer := server.Router.HTMLRender server.Router.HTMLRender = &gintemplrenderer.HTMLTemplRenderer{FallbackHtmlRenderer: htmlRenderer} // Disable proxy warnings server.Router.SetTrustedProxies(nil) // Setup the CORS settings and active them server.config.AllowAllOrigins = true server.Router.Use(cors.New(server.config)) return server } func (s *Server) ConfigureAuth() *Server { err := godotenv.Load(".env") if err != nil { panic("Could not load env file") } redirect_domain := os.Getenv("DOMAIN") var ( redirectUrl string = fmt.Sprintf("%s%s", redirect_domain, domain.API_AUTH_CALLBACK) clientId string = os.Getenv("GOOGLE_CLIENT_ID") clientSecret string = os.Getenv("GOOGLE_CLIENT_SECRET") scope []string = []string{ "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile", } ) // Setup Google OAuth auth.NewGoogleConfig(redirectUrl, clientId, clientSecret, scope) return s } func (s *Server) ConnectDatabase() *Server { err := godotenv.Load(".env") if err != nil { panic("Could not load env file") } var connUrl string = os.Getenv("DATABASE_URL") db, err := sql.Open("postgres", connUrl) if err != nil { panic("Could not connect to database: " + err.Error()) } if err = db.Ping(); err != nil { panic("Error pinging database: " + err.Error()) } s.DB = db return s } // Start starts the server on the port provided when the server was initialized func (s *Server) Start() { s.Router.Run(fmt.Sprintf(":%d", s.port)) } func (s *Server) Setup() *Server { err := godotenv.Load(".env") if err != nil { panic("Could not load env file") } jwtSecret := []byte(os.Getenv("JWT_SECRET")) // Initialize and inject dependencies userRepo := repository.NewUserRepository(s.DB) userService := service.NewUserService(userRepo) authService := service.NewAuthService(userRepo, jwtSecret) deps := &domain.InjectedDependencies{ UserService: userService, AuthService: authService, } // Apply middleware s.Router.Use(DepedencyInjectionMiddleware(deps)) s.Router.Use(JwtAuthMiddleWare(jwtSecret)) // Redirect index to home page: Update this as needed s.Router.GET("/", func(ctx *gin.Context) { ctx.Redirect(http.StatusSeeOther, domain.WEB_HOME) }) // Wrap all routes with a version router_v1 := s.Router.Group(domain.VERSION) // Domain specific routers router_web := router_v1.Group(domain.WEB) router_api := router_v1.Group(domain.API) // Static routes router_web.Static("/static", "./web/static") // API router endpoints router_api.GET("/", func(ctx *gin.Context) { ctx.JSON(200, gin.H{"message": "Server is active."}) }) router_api.GET("/tmp", func(ctx *gin.Context) { if !domain.IsLoggedIn(ctx) { ctx.JSON(200, gin.H{"error": "User is not logged in. Please login to continue"}) return } userId := ctx.MustGet("userId").(int) userEmail := ctx.MustGet("userEmail").(string) ctx.JSON(200, gin.H{"id": userId, "email": userEmail}) }) // WEB router endpoints router_web.GET("/", func(ctx *gin.Context) { ctx.Redirect(http.StatusSeeOther, domain.WEB_HOME) }) router_web.GET("/login", handlers.LoginPage) router_web.GET("/home", handlers.HomePage) router_web.GET("/favorites", handlers.FavoritesPage) router_web.GET("/create", handlers.CreatePage) router_web.GET("/profile", handlers.ProfilePage) router_web.GET("/list", handlers.ListPage) // Authentication router_api.GET("/auth/login", handlers.GoogleLogin) router_api.GET("/auth/callback", handlers.GoogleCallback) router_api.GET("/auth/logout", handlers.Logout) return s }