package main import ( "os" "strings" "git.devices.local/mawas/golang-api-skeleton/cmd" log "github.com/sirupsen/logrus" ) const defaultHost = "unknown" // https://towardsdatascience.com/building-restful-apis-in-golang-e3fe6e3f8f95 // https://www.voile.com/voile-straps.html // https://yusufs.medium.com/creating-distributed-kv-database-by-implementing-raft-consensus-using-golang-d0884eef2e28 RAFT to create badgerdb sync? dragonboat? // FIXME how to set unique index for username to make soft deletes possible but disallow duplicates... also how to cache a username which got delete and recerated... user ID would get overwritten, maybe pre/suffix deleted username? // TODO add command for db migrate? no auto migrate? // TODO use badgerdb for permissions? path:[token1, token2...] // TODO add database loadbalancing feature... so allow more hosts use first as default and other ones as fallback // TODO get-stats cli command... which means unix socket support to communicate with server // TODO data versioning which will be used as reference from the log, also with predictive analytics for restore which means versioning of reference objects needs to be considered // TODO request body store as reference for log // TODO because there is a badgerdb cache which tokens are existing or which userids are existing make an existence check at uuid generation just do be sure // TODO add logger to gin // TODO make explicit getDBConnection function // TODO restructure flags e.g. listenaddress and port to server // FIXME https://medium.com/telnet/why-should-you-start-reading-documentation-from-limitations-section-6690c08e5d1a#.em5kfkezd - too many SQL variables var ( Version string // allows to set version on build APPName string // allows to overwrite app name on build APPDescription string // allows to overwrite app description on build ) func main() { log.SetFormatter(&log.JSONFormatter{}) log.SetOutput(os.Stdout) hostname, err := os.Hostname() if err != nil { hostname = defaultHost } contextLogger := log.WithFields(log.Fields{ "host": hostname, "version": Version, "app": APPName, }) // cobra sets env if flag is given so that viper can pick it up // config priority: flags > env > config file command := cmd.NewRootCmd(Version, APPName, APPDescription) if err := command.Execute(); err != nil { msg := strings.SplitN(err.Error(), ":", 1) if len(msg) == 2 { contextLogger.WithFields(log.Fields{ "module": msg[0], }).Fatal(msg[1]) } } // asd := flagCfg["application.environment"].(*string) // fmt.Printf("SUPI %s\n", *asd) // cfgFile, flagCfg, err := cmd.Initialize(Version, APPName, APPDescription) // if err != nil { // os.Exit(1) // } // config priority: flags > env > config file // rootCMD.Execute() // asd := flagCfg["application.environment"].(*string) // fmt.Printf("SUPI1 %s\n", *asd) // fmt.Println("SUPI2", cfgFile, flagCfg) // if err := config.Initialize(APPName, cfgFile, flagCfg); err != nil { // contextLogger.WithFields(log.Fields{ // "module": "config", // }).Fatal(err) // } // // // bootstrap cache // c, err := cache.Bootstrap() // if err != nil { // contextLogger.WithFields(log.Fields{ // "module": "cache", // }).Fatal(err) // } // defer c.Close() // 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 { // contextLogger.WithFields(log.Fields{ // "module": "database", // }).Fatal(err) // } // // // add cli user to cache // if err := c.Set("user:"+CLIUserID, CLIUsername); err != nil { // userID -> username mapping // contextLogger.WithFields(log.Fields{ // "module": "cache", // }).Fatal(err) // } // if err := c.Set("user:"+CLIUsername, CLIUserID); err != nil { // username -> userID mapping // contextLogger.WithFields(log.Fields{ // "module": "cache", // }).Fatal(err) // } // // db.AutoMigrate(&models.User{}) // db.AutoMigrate(&models.Token{}) // userRepo := repositories.NewUserRepository(db, CLIUserID, CLIUsername, nil) // userService := services.NewUserService(userRepo) // // // Prefill cache // // TODO also add deleted users to cache for old references // if userData, err := userService.ReadAll(); err != nil { // contextLogger.WithFields(log.Fields{ // "module": "userService", // }).Fatal(err) // } else { // // for i := range userData { // if err := c.Set("user:"+userData[i].ID.String(), userData[i].Username); err != nil { // userID -> username mapping // contextLogger.WithFields(log.Fields{ // "module": "cache", // }).Fatal(err) // } // if err := c.Set("user:"+userData[i].Username, userData[i].ID.String()); err != nil { // username -> userID mapping // contextLogger.WithFields(log.Fields{ // "module": "cache", // }).Fatal(err) // } // } // } // // var userID common.GUID // firstname := strings.ToLower(utils.RandString(utils.RandInt(5, 10))) // lastname := strings.ToLower(utils.RandString(utils.RandInt(6, 14))) // username := string([]byte(firstname)[0]) + lastname // user1 := &models.User{ // Username: username, // Firstname: strings.ToUpper(string([]byte(firstname)[0])) + string([]byte(firstname)[1:]), // Lastname: strings.ToUpper(string([]byte(lastname)[0])) + string([]byte(lastname)[1:]), // Email: username + "@acme.inc", // } // if result, err := userService.Create(user1); err != nil { // panic(err) // } else { // utils.PrettyPrintJSON(result) // if err := c.Set("user:"+result.ID.String(), result.Username); err != nil { // userID -> username mapping // contextLogger.WithFields(log.Fields{ // "module": "cache", // }).Fatal(err) // } // if err := c.Set("user:"+result.Username, result.ID.String()); err != nil { // username -> userID mapping // contextLogger.WithFields(log.Fields{ // "module": "cache", // }).Fatal(err) // } // userID = result.ID // } // // userRepo = repositories.NewUserRepository(db, userID.String(), username, c) // userService = services.NewUserService(userRepo) // // userID db context? // // k := common.UsernameContextKey("username") // // ctx := context.WithValue(context.Background(), "username", username) // // db = db.WithContext(ctx) // // db = db.Set("username", username) // // fmt.Println(db.Get("username")) // // // create example token // tokenRepo := repositories.NewTokenRepository(db, userID.String(), username, c) // tokenService := services.NewTokenService(tokenRepo) // token1 := &models.Token{ // ExpiresAt: time.Now().Add(24 * time.Hour), // UserID: userID, // Active: true, // } // if result1, err := tokenService.Create(token1); err != nil { // panic(err) // } else { // utils.PrettyPrintJSON(result1) // } // // result1, err := tokenService.ReadAll() // if err != nil { // panic(err) // } // utils.PrettyPrintJSON(result1) // // result, err := userService.ReadAll() // if err != nil { // panic(err) // } // utils.PrettyPrintJSON(result) // // firstname2 := strings.ToLower(utils.RandString(utils.RandInt(5, 10))) // lastname2 := strings.ToLower(utils.RandString(utils.RandInt(6, 14))) // username2 := string([]byte(firstname2)[0]) + lastname2 // user2 := &models.User{ // Username: username2, // Firstname: strings.ToUpper(string([]byte(firstname2)[0])) + string([]byte(firstname2)[1:]), // Lastname: strings.ToUpper(string([]byte(lastname2)[0])) + string([]byte(lastname2)[1:]), // Email: username2 + "@acme.inc", // } // if result, err := userService.Create(user2); err != nil { // panic(err) // } else { // utils.PrettyPrintJSON(result) // result3, err := userService.ReadByID(result.Username) // if err != nil { // panic(err) // } // utils.PrettyPrintJSON(result3) // } // // // db, _ := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{}) // // userRepo := user.NewRepository(db) // // userService := user.NewService(userRepo) // // user1 := &user.User{ // // Username: "jdoe", // // Firstname: "Joe", // // Lastname: "Doe", // // Email: "jdoe@acme.inc", // // } // // result, err := userService.Create(user1) // // if err != nil { // // panic(err) // // } // // fmt.Println(result) // // // fmt.Println("main.go --> Environment:", viper.GetString("application.environment")) // // fmt.Println("main.go --> Listen:", viper.GetString("application.listenaddress")) // // fmt.Println("main.go --> Database Port: ", viper.GetInt("database.port")) // // fmt.Println("main.go --> Application Port:", viper.GetInt("application.port")) // // contextLogger.WithFields(log.Fields{ // // "module": "config", // // }).Fatal("ADSADSASd") // }