package main import ( "context" "crypto/subtle" "fmt" "html/template" "log" "os" "github.com/jackc/pgx/v5/pgxpool" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" "github.com/spf13/cobra" "github.com/spf13/viper" ) // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ Use: "bottin", Short: "Bottin étudiant de l'AGECEM", } // execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. func execute() { err := rootCmd.Execute() if err != nil { os.Exit(1) } } // apiCmd represents the api command var apiCmd = &cobra.Command{ Use: "api", Short: "Démarrer le serveur API", Args: cobra.ExactArgs(0), Run: func(cmd *cobra.Command, args []string) { var cfg Config if err := viper.Unmarshal(&cfg); err != nil { log.Fatal("parse config:", err) } e := echo.New() // Middlewares e.Pre(middleware.AddTrailingSlash()) if cfg.API.Key != "" { e.Use(middleware.KeyAuth(func(key string, c echo.Context) (bool, error) { return subtle.ConstantTimeCompare([]byte(key), []byte(cfg.API.Key)) == 1, nil })) } // DataClient ctx := context.Background() //prep pool, err := pgxpool.New( ctx, fmt.Sprintf( "user=%s password=%s database=%s host=%s port=%d sslmode=%s ", cfg.DB.User, cfg.DB.Password, cfg.DB.Database, cfg.DB.Host, cfg.DB.Port, cfg.DB.SSLMode, )) if err != nil { log.Fatal("init pgx pool:", err) } defer pool.Close() db := &PostgresClient{ Ctx: ctx, Pool: pool, } if err := db.Pool.Ping(ctx); err != nil { log.Fatal("ping db:", err) } if err := db.CreateOrReplaceSchema(); err != nil { log.Fatal("create or replace schema:", err) } if err := db.CreateOrReplaceViews(); err != nil { log.Fatal("create or replace views:", err) } // Routes if err := addRoutes(e, db); err != nil { log.Fatal("add routes:", err) } /* h := handlers.New(client) e.GET("/v7/health/", h.GetHealth) e.POST("/v7/membres/", h.PostMembres) e.GET("/v7/membres/", h.ListMembres) e.GET("/v7/membres/:membre_id/", h.ReadMembre) e.PUT("/v7/membres/:membre_id/prefered_name/", h.PutMembrePreferedName) e.POST("/v7/programmes/", h.PostProgrammes) e.POST("/v7/seed/", h.PostSeed) */ // Execution e.Logger.Fatal(e.Start(fmt.Sprintf(":%d", cfg.API.Port))) }, } // webCmd represents the web command var webCmd = &cobra.Command{ Use: "web", Short: "Démarrer le client web", Args: cobra.ExactArgs(0), Run: func(cmd *cobra.Command, args []string) { var cfg Config if err := viper.Unmarshal(&cfg); err != nil { log.Fatal("init config:", err) } // Ping API server /* client := http.DefaultClient defer client.CloseIdleConnections() apiClient := data.NewApiClient(client, webApiKey, webApiHost, webApiProtocol, webApiPort) pingResult, err := apiClient.GetHealth() if err != nil { log.Fatal(err) } log.Println(pingResult) */ e := echo.New() // Middlewares e.Pre(middleware.AddTrailingSlash()) e.Use(middleware.BasicAuth(func(user, password string, c echo.Context) (bool, error) { usersMatch := subtle.ConstantTimeCompare([]byte(user), []byte(cfg.Web.User)) == 1 passwordsMatch := subtle.ConstantTimeCompare([]byte(password), []byte(cfg.Web.Password)) == 1 return usersMatch && passwordsMatch, nil })) // Template t := &Template{ templates: template.Must(template.ParseFS(templatesFS, "templates/*.html")), } e.Renderer = t // Routes /* handler := webhandlers.Handler{APIClient: apiClient} e.GET("/", handler.GetIndex) e.GET("/membre/", handler.GetMembre) */ // Execution e.Logger.Fatal(e.Start( fmt.Sprintf(":%d", cfg.Web.Port))) }, }