From 0f5d46164adb550466f0804fb60008b926646b90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernd-Ren=C3=A9=20Predota?= Date: Mon, 17 May 2021 10:04:27 +0200 Subject: [PATCH] first rest api endpoints added --- README.md | 2 +- api/v1/tokens/route.go | 24 +++++++++++ api/v1/tokens/tokens.go | 43 +++++++++++++++++++ api/v1/users/route.go | 24 +++++++++++ api/v1/users/users.go | 20 +++++++++ api/v1/v1.go | 8 +++- cmd/add/add.go | 4 +- cmd/add/admin/admin.go | 15 ++++--- cmd/root.go | 57 +++++++++++++------------ cmd/server/server.go | 90 ++++++++++++++++++++++++++++++---------- lib/common/common.go | 2 +- lib/database/database.go | 13 ++++-- lib/utils/utils.go | 17 +++++--- main.go | 2 + models/token.go | 2 +- models/user.go | 6 +-- repositories/token.go | 26 ++++++------ repositories/user.go | 4 +- 18 files changed, 271 insertions(+), 88 deletions(-) create mode 100644 api/v1/tokens/route.go create mode 100644 api/v1/tokens/tokens.go create mode 100644 api/v1/users/route.go create mode 100644 api/v1/users/users.go diff --git a/README.md b/README.md index 3767e80..8b863da 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # golang API Skeleton -[![Build Status](https://drone.devices.local/api/badges/mawas/golang-api-skeleton/status.svg)](https://drone.devices.local/mawas/golang-api-skeleton)![gopherbadger-tag-do-not-edit](https://img.shields.io/badge/Go%20Coverage-67%25-brightgreen.svg?longCache=true&style=flat) +[![Build Status](https://drone.devices.local/api/badges/mawas/golang-api-skeleton/status.svg)](https://drone.devices.local/mawas/golang-api-skeleton)![gopherbadger-tag-do-not-edit](https://img.shields.io/badge/Go%20Coverage-69%25-brightgreen.svg?longCache=true&style=flat) refined skeleton future apis should be based on diff --git a/api/v1/tokens/route.go b/api/v1/tokens/route.go new file mode 100644 index 0000000..61411c7 --- /dev/null +++ b/api/v1/tokens/route.go @@ -0,0 +1,24 @@ +package tokens + +import "github.com/gin-gonic/gin" + +// ApplyRoutes applies router to the gin Engine +func ApplyRoutes(r *gin.RouterGroup) *gin.RouterGroup { + tokens := r.Group("/tokens") + { + tokens.POST("", Create) + // tokens.GET("/:id", middlewares.Authorized, ReadAction) + tokens.GET("/:token", Read) + // tokens.GET("/:id/logs", middlewares.Authorized, actionlogs.ReadActionLogs) + // tokens.PATCH("/:id", middlewares.Authorized, UpdateAction) + // tokens.PATCH("", middlewares.Authorized, UpdateActions) + // tokens.DELETE("/:id", middlewares.Authorized, DeleteAction) + // tokens.DELETE("", middlewares.Authorized, DeleteActions) + // tokens.GET("/:id/properties/*path", middlewares.Authorized, actionproperties.ReadActionProperty) + // tokens.GET("/:id/properties", middlewares.Authorized, actionproperties.ReadActionProperties) + // tokens.PUT("/:id/properties/*path", middlewares.Authorized, actionproperties.UpsertActionProperty) + // tokens.PUT("/:id/properties", middlewares.Authorized, actionproperties.ReplaceActionProperties) + // tokens.DELETE("/:id/properties/*path", middlewares.Authorized, actionproperties.DeleteActionProperty) + } + return r +} diff --git a/api/v1/tokens/tokens.go b/api/v1/tokens/tokens.go new file mode 100644 index 0000000..50cf6be --- /dev/null +++ b/api/v1/tokens/tokens.go @@ -0,0 +1,43 @@ +package tokens + +import ( + "time" + + "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/models" + "git.devices.local/mawas/golang-api-skeleton/repositories" + "git.devices.local/mawas/golang-api-skeleton/services" + "github.com/gin-gonic/gin" + "gorm.io/gorm" +) + +func Create(c *gin.Context) { + // var requestBody models.Token + db := c.MustGet("db").(*gorm.DB) + cc := c.MustGet("cache").(cache.Cache) + // if err := c.ShouldBindBodyWith(&requestBody, binding.JSON); err != nil { + // return + // } + tokenRepo := repositories.NewTokenRepository(db, "01F5FSJXDHWT4HK93B9NB8V5G4", "test", cc) + tokenService := services.NewTokenService(tokenRepo) + userID, _ := common.StringToGUID("01F5G1W6WJCKQ4PPRS36RYGQ08") + t := &models.Token{ + ExpiresAt: time.Now().Add(24 * time.Hour), + UserID: userID, + Active: true, + } + token, _ := tokenService.Create(t) + c.JSON(200, token) +} + +func Read(c *gin.Context) { + db := c.MustGet("db").(*gorm.DB) + cc := c.MustGet("cache").(cache.Cache) + repo := repositories.NewTokenRepository(db, "01F5FSJXDHWT4HK93B9NB8V5G4", "test", cc) + service := services.NewTokenService(repo) + t := c.Param("token") + token, _ := service.ReadByKey(t) + c.JSON(200, token) + +} diff --git a/api/v1/users/route.go b/api/v1/users/route.go new file mode 100644 index 0000000..a902e41 --- /dev/null +++ b/api/v1/users/route.go @@ -0,0 +1,24 @@ +package users + +import "github.com/gin-gonic/gin" + +// ApplyRoutes applies router to the gin Engine +func ApplyRoutes(r *gin.RouterGroup) *gin.RouterGroup { + users := r.Group("/users") + { + // actions.POST("", middlewares.Authorized, CreateActions) + // actions.GET("/:id", middlewares.Authorized, ReadAction) + users.GET("/:username", Read) + // actions.GET("/:id/logs", middlewares.Authorized, actionlogs.ReadActionLogs) + // actions.PATCH("/:id", middlewares.Authorized, UpdateAction) + // actions.PATCH("", middlewares.Authorized, UpdateActions) + // actions.DELETE("/:id", middlewares.Authorized, DeleteAction) + // actions.DELETE("", middlewares.Authorized, DeleteActions) + // actions.GET("/:id/properties/*path", middlewares.Authorized, actionproperties.ReadActionProperty) + // actions.GET("/:id/properties", middlewares.Authorized, actionproperties.ReadActionProperties) + // actions.PUT("/:id/properties/*path", middlewares.Authorized, actionproperties.UpsertActionProperty) + // actions.PUT("/:id/properties", middlewares.Authorized, actionproperties.ReplaceActionProperties) + // actions.DELETE("/:id/properties/*path", middlewares.Authorized, actionproperties.DeleteActionProperty) + } + return r +} diff --git a/api/v1/users/users.go b/api/v1/users/users.go new file mode 100644 index 0000000..1cf2dd1 --- /dev/null +++ b/api/v1/users/users.go @@ -0,0 +1,20 @@ +package users + +import ( + "git.devices.local/mawas/golang-api-skeleton/lib/cache" + "git.devices.local/mawas/golang-api-skeleton/repositories" + "git.devices.local/mawas/golang-api-skeleton/services" + "github.com/gin-gonic/gin" + "gorm.io/gorm" +) + +func Read(c *gin.Context) { + db := c.MustGet("db").(*gorm.DB) + cc := c.MustGet("cache").(cache.Cache) + userRepo := repositories.NewUserRepository(db, "01F5FSJXDHWT4HK93B9NB8V5G4", "test", cc) + userService := services.NewUserService(userRepo) + username := c.Param("username") + user, _ := userService.ReadByID(username) + c.JSON(200, user) + +} diff --git a/api/v1/v1.go b/api/v1/v1.go index c552ff3..66484c7 100644 --- a/api/v1/v1.go +++ b/api/v1/v1.go @@ -1,11 +1,17 @@ package v1 -import "github.com/gin-gonic/gin" +import ( + "git.devices.local/mawas/golang-api-skeleton/api/v1/tokens" + "git.devices.local/mawas/golang-api-skeleton/api/v1/users" + "github.com/gin-gonic/gin" +) func ApplyRoutes(r *gin.RouterGroup) *gin.RouterGroup { v1 := r.Group("/v1") { v1.GET("/ping") + users.ApplyRoutes(v1) + tokens.ApplyRoutes(v1) } return v1 } diff --git a/cmd/add/add.go b/cmd/add/add.go index a325707..3c81aeb 100644 --- a/cmd/add/add.go +++ b/cmd/add/add.go @@ -14,8 +14,8 @@ func Command(appName string, cfgFile string, flagCfg map[string]interface{}) *co // SilenceErrors: true, DisableAutoGenTag: true, RunE: func(cmd *cobra.Command, args []string) error { - cmd.Help() - return nil + err := cmd.Help() + return err }, } cmd.AddCommand(admin.Command(appName, cfgFile, flagCfg)) diff --git a/cmd/add/admin/admin.go b/cmd/add/admin/admin.go index 14428d9..ba47292 100644 --- a/cmd/add/admin/admin.go +++ b/cmd/add/admin/admin.go @@ -29,12 +29,16 @@ func Command(appName string, cfgFile string, flagCfg map[string]interface{}) *co cmd.Flags().StringVarP(&username, "username", "U", "admin", "desired admin user name") cmd.Flags().StringVarP(&firstname, "firstname", "F", "", "admin user fistname") if err := cmd.MarkFlagRequired("firstname"); err != nil { - // cmd.Usage() + panic(err) } cmd.Flags().StringVarP(&lastname, "lastname", "L", "", "admin user lastname") - cmd.MarkFlagRequired("lastname") + if err := cmd.MarkFlagRequired("lastname"); err != nil { + panic(err) + } cmd.Flags().StringVarP(&email, "email", "M", "", "admin user email address") - cmd.MarkFlagRequired("email") + if err := cmd.MarkFlagRequired("email"); err != nil { + panic(err) + } return cmd } @@ -63,6 +67,7 @@ func createAdminUser(appName, cfgFile string, flagCfg map[string]interface{}, us userRepo := repositories.NewUserRepository(db, common.CLIUserID, common.CLIUsername, nil) userService := services.NewUserService(userRepo) adminUser := services.NewUser(username, firstname, lastname, email) - userService.Create(&adminUser) - return nil + adminUser.Active = true + _, err = userService.Create(&adminUser) + return err } diff --git a/cmd/root.go b/cmd/root.go index e04eb5d..80d64bb 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -33,8 +33,8 @@ func NewRootCmd(version string, appName string, appDescription string) *cobra.Co // SilenceErrors: true, DisableAutoGenTag: true, RunE: func(cmd *cobra.Command, args []string) error { - cmd.Usage() - return nil + err := cmd.Usage() + return err }, } // cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) { @@ -77,35 +77,35 @@ func newSampleCfgCmd() *cobra.Command { } } -//func createAdminCmd(userService *services.UserService) *cobra.Command { +// func createAdminCmd(userService *services.UserService) *cobra.Command { +// return &cobra.Command{ +// Use: "admin", +// Short: "Create initial admin user", +// Long: "Create initial admin user", +// RunE: func(cmd *cobra.Command, args []string) error{ +// adminUser := &models.Token{ +// ExpiresAt: time.Now().Add(24 * time.Hour), +// UserID: userID, +// Active: true, +// } +// if result1, err := tokenService.Create(token1); err != nil { +// panic(err) +// } +// }, +// } +// } + +// func newSampleCLICmd() *cobra.Command { // return &cobra.Command{ -// Use: "admin", -// Short: "Create initial admin user", -// Long: "Create initial admin user", -// RunE: func(cmd *cobra.Command, args []string) error{ -// adminUser := &models.Token{ -// ExpiresAt: time.Now().Add(24 * time.Hour), -// UserID: userID, -// Active: true, -// } -// if result1, err := tokenService.Create(token1); err != nil { -// panic(err) -// } +// Use: "cli", +// Short: "Interactive CLI", +// Long: "Interactive CLI maybe", +// Run: func(cmd *cobra.Command, args []string) { +// cmd.Println("here might be an cli") +// os.Exit(0) // }, // } -//} - -func newSampleCLICmd() *cobra.Command { - return &cobra.Command{ - Use: "cli", - Short: "Interactive CLI", - Long: "Interactive CLI maybe", - Run: func(cmd *cobra.Command, args []string) { - cmd.Println("here might be an cli") - os.Exit(0) - }, - } -} +// } func Initialize(version string, appName string, appDescription string) (string, map[string]interface{}, error) { var cfgFile string @@ -118,7 +118,6 @@ func Initialize(version string, appName string, appDescription string) (string, }) rootCmd.AddCommand(newVersionCmd(version, appName)) rootCmd.AddCommand(newSampleCfgCmd()) - rootCmd.AddCommand(newSampleCfgCmd()) // rootCmd.AddCommand(newSampleCLICmd()) rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file") diff --git a/cmd/server/server.go b/cmd/server/server.go index 5b39ffc..6990c94 100644 --- a/cmd/server/server.go +++ b/cmd/server/server.go @@ -4,7 +4,13 @@ import ( "fmt" "git.devices.local/mawas/golang-api-skeleton/api" + "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/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" @@ -28,24 +34,64 @@ func startServer(appName string, cfgFile string, flagCfg map[string]interface{}) 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) - // } + 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()) - // app.Use(inject(db)) + 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) + } + // Prefill cache + // TODO also add deleted users to cache for old references + userRepo := repositories.NewUserRepository(db, common.CLIUserID, common.CLIUsername, nil) + userService := services.NewUserService(userRepo) + if userData, err := userService.ReadAll(); err != nil { + } else { + 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) + } + } + } + app.Use(inject("cache", c)) + app.Use(inject("db", db)) + // 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) + } 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) @@ -60,9 +106,9 @@ func startServer(appName string, cfgFile string, flagCfg map[string]interface{}) // } // Inject injects database to gin context -// func inject(db *gorm.DB) gin.HandlerFunc { -// return func(c *gin.Context) { -// c.Set("db", db) -// c.Next() -// } -// } +func inject(key string, value interface{}) gin.HandlerFunc { + return func(c *gin.Context) { + c.Set(key, value) + c.Next() + } +} diff --git a/lib/common/common.go b/lib/common/common.go index 78a7410..5cc29af 100644 --- a/lib/common/common.go +++ b/lib/common/common.go @@ -47,7 +47,7 @@ func (basicFields *BasicFields) AfterCreate(tx *gorm.DB) error { return nil } -type GUIDPKicPK struct { +type ModelIntegerPK struct { ID uint64 `gorm:"primaryKey;column:id" json:"id"` BasicFields } diff --git a/lib/database/database.go b/lib/database/database.go index 540d1f6..537aa0d 100644 --- a/lib/database/database.go +++ b/lib/database/database.go @@ -63,8 +63,8 @@ func (c *Credentials) getDSN() gorm.Dialector { " sslmode=disable connect_timeout=5" return postgres.Open(dsn) case "sqlite": - // return sqlite.Open("gorm.db") - return sqlite.Open("file::memory:?cache=shared") + return sqlite.Open("gorm.db") + // return sqlite.Open("file::memory:?cache=shared") } return nil } @@ -78,13 +78,18 @@ func Connect(c Credentials) (*gorm.DB, error) { Colorful: true, // Disable color }, ) - db, err := gorm.Open(c.getDSN(), &gorm.Config{Logger: newLogger}) + config := gorm.Config{Logger: newLogger} + if strings.EqualFold(c.Dialect, "sqlite") { + // FIXME HACK for sqlite + config.DisableForeignKeyConstraintWhenMigrating = true + } + db, err := gorm.Open(c.getDSN(), &config) if err != nil { return nil, err } + return db, nil // sqlDB, err := db.DB() // sqlDB.SetMaxOpenConns(config.Configuration.DBMaxOpenConn) // sqlDB.SetMaxIdleConns(config.Configuration.DBMaxIdleConn) // sqlDB.SetConnMaxLifetime(time.Duration(config.Configuration.DBMaxLifeTime) * time.Second) - return db, nil } diff --git a/lib/utils/utils.go b/lib/utils/utils.go index 7cb8e6e..793ae23 100644 --- a/lib/utils/utils.go +++ b/lib/utils/utils.go @@ -46,15 +46,22 @@ func RandInt(s int, e int) int { } func PrettyPrintJSON(s interface{}) { - switch s.(type) { + switch v := s.(type) { case string: var j map[string]interface{} - json.Unmarshal([]byte(s.(string)), &j) - // jsonString, _ := json.MarshalIndent(j, "", " ") - jsonString, _ := json.Marshal(j) + if err := json.Unmarshal([]byte(v), &j); err != nil { + panic(err) + } + jsonString, err := json.Marshal(j) + if err != nil { + panic(err) + } fmt.Println(string(jsonString)) default: - jsonString, _ := json.MarshalIndent(s, "", " ") + jsonString, err := json.MarshalIndent(s, "", " ") + if err != nil { + panic(err) + } fmt.Println(string(jsonString)) } } diff --git a/main.go b/main.go index c06c981..c167847 100644 --- a/main.go +++ b/main.go @@ -23,6 +23,8 @@ const defaultHost = "unknown" // 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 + var ( Version string // allows to set version on build APPName string // allows to overwrite app name on build diff --git a/models/token.go b/models/token.go index 085322a..ce8cbeb 100644 --- a/models/token.go +++ b/models/token.go @@ -16,7 +16,7 @@ type Token struct { LastUsedDB sql.NullTime `gorm:"column:last_used" json:"-"` LastUsedJSON *time.Time `gorm:"-" json:"last_used,omitempty"` ExpiresAt time.Time `json:"expires_at"` - UserID common.GUID `json:"asd"` + UserID common.GUID `json:"-"` Username string `gorm:"-" json:"username"` Active bool `json:"active"` } diff --git a/models/user.go b/models/user.go index 001947d..a142876 100644 --- a/models/user.go +++ b/models/user.go @@ -16,7 +16,7 @@ type User struct { TokensRef []Token `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-"` Tokens []string `gorm:"-" json:"tokens"` PasswordHash string `json:"-"` - Active bool ` json:"active"` + Active bool `json:"active"` } func (user *User) AfterCreate(tx *gorm.DB) error { @@ -34,12 +34,10 @@ func (user *User) AfterFind(tx *gorm.DB) error { if user.DeletedAtDB.Valid { user.DeletedAtJSON = &user.DeletedAtDB.Time } + user.Tokens = []string{} for i := range user.TokensRef { user.Tokens = append(user.Tokens, user.TokensRef[i].Token.String()) } - if len(user.Tokens) == 0 { - user.Tokens = []string{} - } if cc, ok := tx.Get("cache"); ok { if c, ok := cc.(cache.Cache); ok { if username, err := c.Get("user:" + user.CreatedByDB.String()); err != nil { diff --git a/repositories/token.go b/repositories/token.go index fd27541..a0d37f9 100644 --- a/repositories/token.go +++ b/repositories/token.go @@ -3,18 +3,19 @@ package repositories import ( "git.devices.local/mawas/golang-api-skeleton/lib/cache" + "git.devices.local/mawas/golang-api-skeleton/lib/common" model "git.devices.local/mawas/golang-api-skeleton/models" "gorm.io/gorm" ) -type tokenDAO struct { +type TokenDAO struct { repo } // NewTokenRepository create new repository for model token -func NewTokenRepository(db *gorm.DB, userID string, username string, cache cache.Cache) *tokenDAO { +func NewTokenRepository(db *gorm.DB, userID string, username string, cache cache.Cache) *TokenDAO { db = db.Set("username", username).Set("userID", userID).Set("cache", cache) - return &tokenDAO{ + return &TokenDAO{ repo: repo{ db: db, userID: userID, @@ -23,28 +24,29 @@ func NewTokenRepository(db *gorm.DB, userID string, username string, cache cache } } -func (dao *tokenDAO) ReadByKey(key interface{}) (*model.Token, error) { +func (dao *TokenDAO) ReadByKey(key interface{}) (*model.Token, error) { token := model.Token{} - err := dao.db.Joins("User").First(&token, key).Error + t, _ := common.StringToGUID(key.(string)) + err := dao.db.Where(model.Token{Token: t}).First(&token).Error return &token, err } -func (dao *tokenDAO) ReadAll() ([]*model.Token, error) { +func (dao *TokenDAO) ReadAll() ([]*model.Token, error) { var tokens []*model.Token err := dao.db.Find(&tokens).Error return tokens, err } -func (dao *tokenDAO) Create(token *model.Token) (*model.Token, error) { +func (dao *TokenDAO) Create(token *model.Token) (*model.Token, error) { err := dao.db.Create(token).Error if cc, ok := dao.db.Get("cache"); ok { if c, ok := cc.(cache.Cache); ok { - if username, err := c.Get("user:" + token.UserID.String()); err != nil { + username, err := c.Get("user:" + token.UserID.String()) + if err != nil { return nil, err - } else { - if username != nil { - token.Username = *username - } + } + if username != nil { + token.Username = *username } } } diff --git a/repositories/user.go b/repositories/user.go index 8e14218..81b935a 100644 --- a/repositories/user.go +++ b/repositories/user.go @@ -25,7 +25,9 @@ func NewUserRepository(db *gorm.DB, userID string, username string, cache cache. func (dao *UserDAO) ReadByUsername(username string) (*model.User, error) { result := model.User{} - err := dao.db.Where(&model.User{Username: username}).First(&result).Error + // err := dao.db.Joins("TokensRef").Where(&model.User{Username: username}).First(&result).Error + err := dao.db.Preload("TokensRef").Where(&model.User{Username: username}).First(&result).Error + // err := dao.db.Where(&model.User{Username: username}).First(&result).Error return &result, err }