123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- package main
- import (
- "context"
- "fmt"
- "log"
- "net/http"
- "os"
- "os/signal"
- "strings"
- "syscall"
- "time"
- "github.com/alecthomas/kong"
- "github.com/gin-contrib/cors"
- "github.com/gin-gonic/gin"
- "git.linuxforward.com/byom/byom-onboard/internal/common/jwt"
- "git.linuxforward.com/byom/byom-onboard/internal/domain/register"
- "git.linuxforward.com/byom/byom-onboard/internal/platform/config"
- "git.linuxforward.com/byom/byom-onboard/internal/platform/database"
- "git.linuxforward.com/byom/byom-onboard/internal/platform/mailer"
- "git.linuxforward.com/byom/byom-onboard/internal/platform/payment"
- "git.linuxforward.com/byom/byom-onboard/internal/platform/stripe"
- )
- var (
- // Build information - values will be set during build
- version = "dev"
- commit = "none"
- buildDate = "unknown"
- )
- type CLI struct {
- Config string `help:"Config file path" default:"config.yaml" type:"path"`
- Debug bool `help:"Enable debug mode"`
- Version VersionCmd `cmd:"" help:"Show version information"`
- Serve ServeCmd `cmd:"" help:"Start the HTTP server"`
- }
- type VersionCmd struct{}
- func (v VersionCmd) Run() error {
- fmt.Printf("Version:\t%s\n", version)
- fmt.Printf("Commit:\t\t%s\n", commit)
- fmt.Printf("Built:\t\t%s\n", buildDate)
- return nil
- }
- // ServeCmd handles the serve command
- type ServeCmd struct {
- Port int `help:"Port to listen on" default:"8080"`
- Host string `help:"Host to bind to" default:"0.0.0.0"`
- }
- func (s *ServeCmd) Run(cli *CLI) error {
- // Load configuration
- cfg, err := config.Load()
- if err != nil {
- return fmt.Errorf("failed to load configuration: %w", err)
- }
- // Initialize Stripe
- if err := stripe.Initialize(); err != nil {
- log.Fatalf("Failed to initialize Stripe: %v", err)
- }
- // Initialize Gin
- gin.SetMode(gin.ReleaseMode)
- r := gin.New()
- r.Use(gin.Logger())
- r.Use(gin.Recovery())
- //read cors from env
- corsUrl := os.Getenv("CORS_ALLOWED_ORIGIN")
- // Split the CORS URL by comma to handle multiple origins
- corsOrigins := strings.Split(corsUrl, ",")
- corsConfig := cors.DefaultConfig()
- corsConfig.AllowOrigins = corsOrigins
- corsConfig.AllowCredentials = true
- corsConfig.AllowHeaders = []string{"Content-Type", "Authorization"}
- corsConfig.AllowMethods = []string{"*"}
- r.Use(cors.New(corsConfig))
- if cli.Debug {
- log.Printf("Debug mode enabled")
- gin.SetMode(gin.DebugMode)
- log.Printf("Using config file: %s", cli.Config)
- }
- // Initialize database
- db, err := database.NewDatabase(cfg.Database.DSN)
- if err != nil {
- return fmt.Errorf("failed to initialize database: %w", err)
- }
- jwtClient := jwt.NewJWTClient([]byte(cfg.JWT.Secret))
- //stripeClient := billing.NewStripeClient(cfg.Stripe.APIKey, cfg.Stripe.EndpointSecret)
- mailerClient := mailer.NewMailer(&cfg.Mailer)
- // Initialize Stripe handler
- stripeHandler, err := payment.NewStripeHandler(
- "https://byom.moooffle.com",
- mailerClient,
- )
- if err != nil {
- return fmt.Errorf("failed to initialize Stripe: %w", err)
- }
- // Initialize services
- //ovhClient := provisioning.NewOvhClient(cfg.OVH.Endpoint, cfg.OVH.AppKey, cfg.OVH.AppSecret)
- //provisioningHandler := provisioning.NewHandler(ovhClient, db)
- registerHandler := register.NewHandler(mailerClient, db, jwtClient)
- // Setup server
- server := setupServer(r, registerHandler, cfg, stripeHandler)
- server.Addr = fmt.Sprintf(":%d", s.Port)
- // Start server in a goroutine
- go func() {
- log.Printf("Starting server on port %d", s.Port)
- if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
- log.Fatalf("Failed to start server: %v", err)
- }
- }()
- // Setup graceful shutdown
- quit := make(chan os.Signal, 1)
- signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
- <-quit
- log.Println("Shutting down server...")
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
- defer cancel()
- if err := server.Shutdown(ctx); err != nil {
- return fmt.Errorf("server forced to shutdown: %w", err)
- }
- log.Println("Server exited properly")
- return nil
- }
- func setupServer(
- r *gin.Engine,
- registerHandler *register.Handler,
- config *config.Config,
- stripeHandler *payment.StripeHandler,
- ) *http.Server {
- api := r.Group("/api/v1/onboard")
- {
- // Public routes
- api.POST("/check-email", registerHandler.CheckEmail)
- api.POST("/register", registerHandler.Register)
- api.GET("/validate-email", registerHandler.ValidateEmail)
- // Stripe routes
- api.POST("/create-checkout-session", stripeHandler.CreateCheckoutSession)
- api.POST("/create-portal-session", stripeHandler.CreatePortalSession)
- api.POST("/webhook", stripeHandler.HandleWebhook)
- // Add the new products endpoint
- api.GET("/products", stripeHandler.GetProducts)
- }
- return &http.Server{
- Addr: config.Server.Address,
- Handler: r,
- }
- }
- func main() {
- cli := CLI{}
- ctx := kong.Parse(&cli,
- kong.Name("byom"),
- kong.Description("BYOM - Onboarding service"),
- kong.UsageOnError(),
- kong.ConfigureHelp(kong.HelpOptions{
- Compact: true,
- Summary: true,
- }),
- )
- err := ctx.Run(&cli)
- ctx.FatalIfErrorf(err)
- }
|