From 3716dc654dd896e1042940e674552cf0f5218389 Mon Sep 17 00:00:00 2001 From: ajikamaludin Date: Sat, 23 Jul 2022 09:47:49 +0700 Subject: [PATCH] add converter, req and res need to make model for it self --- app/controllers/auth/auth.controller.go | 17 +++--- app/controllers/note/note.controller.go | 71 ++++++------------------- app/controllers/user/user.controller.go | 9 ++-- app/models/note.go | 46 ++++++++++++++-- app/models/user.go | 25 ++++++++- app/repository/note/note.repository.go | 60 ++++++++++++++++++++- pkg/gorm.db/gorm.db.go | 2 +- pkg/jwtmanager/jwtmanager.go | 10 ++++ pkg/utils/constants/constants.go | 2 +- pkg/utils/converter/converter.go | 17 ++++++ 10 files changed, 184 insertions(+), 75 deletions(-) create mode 100644 pkg/utils/converter/converter.go diff --git a/app/controllers/auth/auth.controller.go b/app/controllers/auth/auth.controller.go index 48a5744..a5c0644 100644 --- a/app/controllers/auth/auth.controller.go +++ b/app/controllers/auth/auth.controller.go @@ -11,7 +11,7 @@ import ( ) func Login(c *fiber.Ctx) error { - userRequest := new(models.User) + userRequest := new(models.UserReq) _ = c.BodyParser(&userRequest) @@ -19,7 +19,7 @@ func Login(c *fiber.Ctx) error { if errors != nil { return c.Status(fiber.StatusUnprocessableEntity).JSON(fiber.Map{ "status": constants.STATUS_FAIL, - "message": "request body mismatch", + "message": "request body invalid", "error": errors, }) } @@ -32,7 +32,7 @@ func Login(c *fiber.Ctx) error { if err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "status": constants.STATUS_FAIL, - "message": "credentials mismatch", + "message": "credentials invalid", "error": err.Error(), }) } @@ -40,14 +40,14 @@ func Login(c *fiber.Ctx) error { accessToken := jwtmanager.CreateToken(user) return c.Status(fiber.StatusOK).JSON(fiber.Map{ - "user": user, + "user": user.ToUserRes(), "accessToken": accessToken, "refreshToken": "", }) } func Register(c *fiber.Ctx) error { - userRequest := new(models.User) + userRequest := new(models.UserReq) _ = c.BodyParser(&userRequest) @@ -55,14 +55,15 @@ func Register(c *fiber.Ctx) error { if errors != nil { return c.Status(fiber.StatusUnprocessableEntity).JSON(fiber.Map{ "status": constants.STATUS_FAIL, - "message": "request body mismatch", + "message": "request body invalid", "error": errors, }) } + hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(userRequest.Password), bcrypt.DefaultCost) user := &models.User{ Email: userRequest.Email, - Password: userRequest.Password, + Password: string(hashedPassword), } err := userRepository.GetUserByEmail(userRequest.Email, user) if err == nil { @@ -78,7 +79,7 @@ func Register(c *fiber.Ctx) error { accessToken := jwtmanager.CreateToken(user) return c.Status(fiber.StatusOK).JSON(fiber.Map{ - "user": user, + "user": user.ToUserRes(), "accessToken": accessToken, "refreshToken": "", }) diff --git a/app/controllers/note/note.controller.go b/app/controllers/note/note.controller.go index 82415ff..edcecf8 100644 --- a/app/controllers/note/note.controller.go +++ b/app/controllers/note/note.controller.go @@ -3,9 +3,8 @@ package note import ( "github.com/ajikamaludin/go-fiber-rest/app/models" noteRepository "github.com/ajikamaludin/go-fiber-rest/app/repository/note" - gormdb "github.com/ajikamaludin/go-fiber-rest/pkg/gorm.db" - redisclient "github.com/ajikamaludin/go-fiber-rest/pkg/redis.client" "github.com/ajikamaludin/go-fiber-rest/pkg/utils/constants" + "github.com/ajikamaludin/go-fiber-rest/pkg/utils/converter" "github.com/ajikamaludin/go-fiber-rest/pkg/utils/validator" "github.com/gofiber/fiber/v2" ) @@ -13,7 +12,7 @@ import ( func GetAllNotes(c *fiber.Ctx) error { var notes []models.Note - err := noteRepository.GetAllNotes(¬es) + err := noteRepository.GetAllNotes(c, ¬es) if err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "status": constants.STATUS_FAIL, @@ -22,10 +21,12 @@ func GetAllNotes(c *fiber.Ctx) error { }) } + notesRes := converter.MapNoteToNoteRes(notes) + return c.Status(fiber.StatusOK).JSON(fiber.Map{ "status": constants.STATUS_SUCCESS, "message": "Ok", - "data": notes, + "data": notesRes, }) } @@ -45,53 +46,33 @@ func GetNoteById(c *fiber.Ctx) error { return c.Status(fiber.StatusOK).JSON(fiber.Map{ "status": constants.STATUS_SUCCESS, "message": "note found", - "data": note, + "data": note.ToNoteRes(), }) } func CreateNote(c *fiber.Ctx) error { - noteRequest := new(models.Note) + noteRequest := new(models.NoteReq) - if err := c.BodyParser(¬eRequest); err != nil { - return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ - "message": err.Error(), - }) - } + c.BodyParser(¬eRequest) errors := validator.ValidateRequest(noteRequest) if errors != nil { return c.Status(fiber.StatusUnprocessableEntity).JSON(errors) } - db, err := gormdb.GetInstance() - if err != nil { - return err - } - - var note = models.Note{ - Title: noteRequest.Note, - Note: noteRequest.Title, - } - - db.Create(¬e) + note, _ := noteRepository.CreateNote(c, noteRequest) return c.Status(fiber.StatusCreated).JSON(fiber.Map{ "status": constants.STATUS_SUCCESS, "message": "note created", - "data": note, + "data": note.ToNoteRes(), }) } func UpdateNote(c *fiber.Ctx) error { - // validate request first - noteRequest := new(models.Note) + noteRequest := new(models.NoteReq) - if err := c.BodyParser(¬eRequest); err != nil { - return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ - "status": constants.STATUS_FAIL, - "message": err.Error(), - }) - } + c.BodyParser(¬eRequest) errors := validator.ValidateRequest(noteRequest) if errors != nil { @@ -102,16 +83,9 @@ func UpdateNote(c *fiber.Ctx) error { }) } - // find records id := c.Params("id") - - db, err := gormdb.GetInstance() - if err != nil { - return err - } - note := models.Note{} - err = db.First(¬e, id).Error + err := noteRepository.GetNoteById(id, ¬e) if err != nil { return c.Status(fiber.StatusNotFound).JSON(fiber.Map{ @@ -120,29 +94,20 @@ func UpdateNote(c *fiber.Ctx) error { }) } - // Update - db.Model(¬e).Updates(noteRequest) - key := "note+" + id - redisclient.Remove(key) + noteRepository.UpdateNote(¬e, noteRequest) return c.Status(fiber.StatusCreated).JSON(fiber.Map{ "status": constants.STATUS_SUCCESS, "message": "note updated", - "data": note, + "data": note.ToNoteRes(), }) } func DeleteNote(c *fiber.Ctx) error { - // find records id := c.Params("id") - db, err := gormdb.GetInstance() - if err != nil { - return err - } - note := models.Note{} - err = db.First(¬e, id).Error + err := noteRepository.GetNoteById(id, ¬e) if err != nil { return c.Status(fiber.StatusNotFound).JSON(fiber.Map{ @@ -151,9 +116,7 @@ func DeleteNote(c *fiber.Ctx) error { }) } - db.Delete(¬e) - key := "note+" + id - redisclient.Remove(key) + noteRepository.DeleteNote(¬e) return c.SendStatus(fiber.StatusNoContent) } diff --git a/app/controllers/user/user.controller.go b/app/controllers/user/user.controller.go index 70b3098..b442e29 100644 --- a/app/controllers/user/user.controller.go +++ b/app/controllers/user/user.controller.go @@ -4,13 +4,14 @@ import ( "github.com/ajikamaludin/go-fiber-rest/app/models" gormdb "github.com/ajikamaludin/go-fiber-rest/pkg/gorm.db" "github.com/ajikamaludin/go-fiber-rest/pkg/utils/constants" + "github.com/ajikamaludin/go-fiber-rest/pkg/utils/converter" "github.com/ajikamaludin/go-fiber-rest/pkg/utils/validator" "github.com/gofiber/fiber/v2" "golang.org/x/crypto/bcrypt" ) func CreateUser(c *fiber.Ctx) error { - userRequest := new(models.User) + userRequest := new(models.UserReq) if err := c.BodyParser(&userRequest); err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ @@ -48,7 +49,7 @@ func CreateUser(c *fiber.Ctx) error { return c.Status(fiber.StatusCreated).JSON(fiber.Map{ "status": constants.STATUS_SUCCESS, "message": "user created", - "data": user, + "data": user.ToUserRes(), }) } @@ -58,12 +59,12 @@ func GetAllUsers(c *fiber.Ctx) error { return err } - users := &models.User{} + users := []models.User{} db.Find(&users) return c.Status(fiber.StatusOK).JSON(fiber.Map{ "status": constants.STATUS_SUCCESS, "message": "Ok", - "data": users, + "data": converter.MapUserToUserRes(users), }) } diff --git a/app/models/note.go b/app/models/note.go index 45e1d5b..e0ac7cf 100644 --- a/app/models/note.go +++ b/app/models/note.go @@ -7,8 +7,48 @@ import ( type Note struct { gorm.Model - UserId uuid.UUID - Title string `validate:"required,min=3"` - Note string `validate:"required,min=3"` + UserId uuid.UUID `gorm:"type:uuid"` + Title string + Note string Tag string + User User `json:",omitempty"` +} + +func (n Note) ToNoteRes() *NoteRes { + return &NoteRes{ + UserId: n.UserId, + ID: n.ID, + Title: n.Title, + Note: n.Note, + } +} + +func (n Note) ToNoteWithUserRes() *NoteWithUserRes { + return &NoteWithUserRes{ + UserId: n.UserId, + ID: n.ID, + Title: n.Title, + Note: n.Note, + User: n.User, + } +} + +type NoteRes struct { + UserId uuid.UUID + ID uint + Title string + Note string +} + +type NoteWithUserRes struct { + UserId uuid.UUID + ID uint + Title string + Note string + User User +} + +type NoteReq struct { + Title string `validate:"required,min=3"` + Note string `validate:"required,min=3"` } diff --git a/app/models/user.go b/app/models/user.go index 6415b8a..a5faa76 100644 --- a/app/models/user.go +++ b/app/models/user.go @@ -12,8 +12,8 @@ type User struct { CreatedAt time.Time UpdatedAt time.Time DeletedAt gorm.DeletedAt `gorm:"index"` - Email string `validate:"required,min=3,email"` - Password string `validate:"required,min=3"` + Email string + Password string Notes []Note } @@ -22,3 +22,24 @@ func (user *User) BeforeCreate(tx *gorm.DB) (err error) { return } + +func (user User) ToUserRes() *UserRes { + return &UserRes{ + ID: user.ID, + Email: user.Email, + Password: user.Password, + CreatedAt: user.CreatedAt, + } +} + +type UserRes struct { + ID uuid.UUID + Email string + Password string + CreatedAt time.Time +} + +type UserReq struct { + Email string `validate:"required,min=3,email"` + Password string `validate:"required,min=3"` +} diff --git a/app/repository/note/note.repository.go b/app/repository/note/note.repository.go index dbb6846..fa0acc7 100644 --- a/app/repository/note/note.repository.go +++ b/app/repository/note/note.repository.go @@ -1,21 +1,26 @@ package note import ( + "strconv" "time" "github.com/ajikamaludin/go-fiber-rest/app/models" gormdb "github.com/ajikamaludin/go-fiber-rest/pkg/gorm.db" + "github.com/ajikamaludin/go-fiber-rest/pkg/jwtmanager" redisclient "github.com/ajikamaludin/go-fiber-rest/pkg/redis.client" + "github.com/gofiber/fiber/v2" ) -func GetAllNotes(notes *[]models.Note) error { +func GetAllNotes(c *fiber.Ctx, notes *[]models.Note) error { err := redisclient.Get("allnotes", ¬es) if err != nil { db, err := gormdb.GetInstance() if err != nil { return err } - db.Find(¬es) + + userId := jwtmanager.GetUserId(c) + db.Where("user_id = ?", userId).Find(¬es) redisclient.Set("allnotes", ¬es, 30*time.Second) } @@ -42,3 +47,54 @@ func GetNoteById(id string, note *models.Note) error { } return nil } + +func CreateNote(c *fiber.Ctx, noteRequest *models.NoteReq) (*models.Note, error) { + db, err := gormdb.GetInstance() + if err != nil { + return nil, err + } + + userId := jwtmanager.GetUserId(c) + + note := &models.Note{ + UserId: userId, + Title: noteRequest.Note, + Note: noteRequest.Title, + } + + db.Create(¬e) + return note, nil +} + +func UpdateNote(note *models.Note, noteRequest *models.NoteReq) (*models.NoteRes, error) { + db, err := gormdb.GetInstance() + if err != nil { + return nil, err + } + + db.Model(¬e).Updates(&models.Note{ + Title: noteRequest.Title, + Note: noteRequest.Note, + }) + key := "note+" + strconv.Itoa(int(note.ID)) + redisclient.Remove(key) + + return &models.NoteRes{ + UserId: note.UserId, + Title: note.Title, + Note: note.Note, + }, err +} + +func DeleteNote(note *models.Note) error { + db, err := gormdb.GetInstance() + if err != nil { + return err + } + + db.Delete(¬e) + key := "note+" + strconv.Itoa(int(note.ID)) + redisclient.Remove(key) + + return nil +} diff --git a/pkg/gorm.db/gorm.db.go b/pkg/gorm.db/gorm.db.go index 64af506..8ed3674 100644 --- a/pkg/gorm.db/gorm.db.go +++ b/pkg/gorm.db/gorm.db.go @@ -14,7 +14,6 @@ var lock = &sync.Mutex{} var db *gorm.DB func GetInstance() (*gorm.DB, error) { - // fmt.Println("[DATABASE] : ", db) if db == nil { configs := configs.GetInstance() @@ -41,5 +40,6 @@ func GetInstance() (*gorm.DB, error) { } return db, nil } + // fmt.Println("[DATABASE] : ", db) return db, nil } diff --git a/pkg/jwtmanager/jwtmanager.go b/pkg/jwtmanager/jwtmanager.go index d802bbf..f054323 100644 --- a/pkg/jwtmanager/jwtmanager.go +++ b/pkg/jwtmanager/jwtmanager.go @@ -5,6 +5,9 @@ import ( "github.com/ajikamaludin/go-fiber-rest/app/configs" "github.com/ajikamaludin/go-fiber-rest/app/models" + "github.com/gofiber/fiber/v2" + "github.com/google/uuid" + "github.com/golang-jwt/jwt/v4" ) @@ -22,3 +25,10 @@ func CreateToken(user *models.User) string { return token } + +func GetUserId(c *fiber.Ctx) (UserId uuid.UUID) { + user := c.Locals("user").(*jwt.Token) + claims := user.Claims.(jwt.MapClaims) + UserId, _ = uuid.Parse(claims["user_id"].(string)) + return +} diff --git a/pkg/utils/constants/constants.go b/pkg/utils/constants/constants.go index 9c97b9c..b449899 100644 --- a/pkg/utils/constants/constants.go +++ b/pkg/utils/constants/constants.go @@ -1,4 +1,4 @@ package constants -const STATUS_SUCCESS = "succes" +const STATUS_SUCCESS = "success" const STATUS_FAIL = "fail" diff --git a/pkg/utils/converter/converter.go b/pkg/utils/converter/converter.go new file mode 100644 index 0000000..86f98ec --- /dev/null +++ b/pkg/utils/converter/converter.go @@ -0,0 +1,17 @@ +package converter + +import "github.com/ajikamaludin/go-fiber-rest/app/models" + +func MapNoteToNoteRes(notes []models.Note) (noteRes []models.NoteRes) { + for _, v := range notes { + noteRes = append(noteRes, *v.ToNoteRes()) + } + return +} + +func MapUserToUserRes(users []models.User) (userRes []models.UserRes) { + for _, v := range users { + userRes = append(userRes, *v.ToUserRes()) + } + return +}