package server import ( "fmt" "git.devices.local/mawas/golang-api-skeleton/api" "git.devices.local/mawas/golang-api-skeleton/indexes" "git.devices.local/mawas/golang-api-skeleton/lib/cache" "git.devices.local/mawas/golang-api-skeleton/lib/common" "git.devices.local/mawas/golang-api-skeleton/lib/config" "git.devices.local/mawas/golang-api-skeleton/lib/database" "git.devices.local/mawas/golang-api-skeleton/lib/middlewares" "git.devices.local/mawas/golang-api-skeleton/models" "git.devices.local/mawas/golang-api-skeleton/repositories" "git.devices.local/mawas/golang-api-skeleton/services" "github.com/gin-gonic/gin" "github.com/spf13/cobra" "github.com/spf13/viper" ) func Command(version string, appName string, cfgFile string, flagCfg map[string]interface{}) *cobra.Command { return &cobra.Command{ Use: "server", Short: "Starts application", Long: "Starts application", // SilenceUsage: true, // SilenceErrors: true, DisableAutoGenTag: true, RunE: func(cmd *cobra.Command, args []string) error { return startServer(version, appName, cfgFile, flagCfg) }, } } func startServer(version string, appName string, cfgFile string, flagCfg map[string]interface{}) error { if err := config.Initialize(appName, cfgFile, flagCfg); err != nil { return fmt.Errorf("config:" + err.Error()) } db, err := database.Connect(database.Credentials{ Host: viper.GetString("database.host"), Port: viper.GetInt("database.port"), Dialect: viper.GetString("database.dialect"), Database: viper.GetString("database.database"), User: viper.GetString("database.user"), Password: viper.GetString("database.password"), MaxOpenConn: viper.GetInt("database.port"), MaxIdleConn: viper.GetInt("database.port"), MaxLifeTime: viper.GetInt("database.port"), Debug: true, }) if err != nil { return fmt.Errorf("database:%v", err) } app := gin.New() app.Use(gin.Recovery()) c, err := cache.Bootstrap() if err != nil { return fmt.Errorf("cache:%v", err) } defer c.Close() if err := c.Set("user:"+common.CLIUserID, common.CLIUsername); err != nil { // userID -> username mapping return fmt.Errorf("cache:%v", err) } if err := c.Set("user:"+common.CLIUsername, common.CLIUserID); err != nil { // username -> userID mapping return fmt.Errorf("api:%v", err) } if err := c.Set("user:01F5FSJXDHWT4HK93B9NB8V5G4", "test"); err != nil { // userID -> username mapping return fmt.Errorf("cache:%v", err) } if err := c.Set("user:test", "01F5FSJXDHWT4HK93B9NB8V5G4"); err != nil { // username -> userID mapping return fmt.Errorf("cache:%v", err) } // FIXME find out where todo database migration if err := db.AutoMigrate(&models.Token{}); err != nil { return fmt.Errorf("database:%v", err) } if err := db.AutoMigrate(&models.User{}); err != nil { return fmt.Errorf("database:%v", err) } // Prefill cache // TODO also add deleted users to cache for old references // users userRepo := repositories.NewUserRepository(db, common.CLIUserID, common.CLIUsername, nil) userService := services.NewUserService(userRepo) userData, err := userService.ReadAll() if err != nil { return fmt.Errorf("cache:%v", err.Error()) } for i := range userData { if err := c.Set("user:"+userData[i].ID.String(), userData[i].Username); err != nil { // userID -> username mapping return fmt.Errorf("cache:%v", err) } if err := c.Set("user:"+userData[i].Username, userData[i].ID.String()); err != nil { // username -> userID mapping return fmt.Errorf("cache:%v", err) } } // tokens tokenRepo := repositories.NewTokenRepository(db, common.CLIUserID, common.CLIUsername, nil) tokenService := services.NewTokenService(tokenRepo) tokenData, err := tokenService.ReadAll() if err != nil { return fmt.Errorf("cache:%v", err) } for i := range tokenData { if err := c.Set("token:"+tokenData[i].Token.String(), tokenData[i].UserID.String()); err != nil { // token -> userID mapping return fmt.Errorf("cache:%v", err) } } index, err := indexes.Init(db) if err != nil { return fmt.Errorf("index:%v", err) } app.Use(inject("index", index)) app.Use(inject("cache", c)) app.Use(inject("db", db)) app.Use(middlewares.RequestID()) app.Use(middlewares.Authentication()) app.Use(middlewares.VersionHeader(version)) api.ApplyRoutes(app) if err := app.Run(fmt.Sprintf("%s:%s", viper.GetString("application.listenaddress"), viper.GetString("application.port"))); err != nil { return fmt.Errorf("api:%v", err) } return nil } // Inject injects database to gin context func inject(key string, value interface{}) gin.HandlerFunc { return func(c *gin.Context) { c.Set(key, value) c.Next() } }