From 95ed97d1bac0a5c32881fc09550c02ede34fd29b Mon Sep 17 00:00:00 2001 From: Seyora24 Date: Thu, 13 Jul 2023 10:15:18 +0700 Subject: [PATCH] Pengen upload lagi --- controllers/postController.go | 182 +++++++++++++++++++++++----------- go.mod | 4 + go.sum | 9 ++ main.go | 2 +- 4 files changed, 140 insertions(+), 57 deletions(-) diff --git a/controllers/postController.go b/controllers/postController.go index fd904cc..4f66ff5 100644 --- a/controllers/postController.go +++ b/controllers/postController.go @@ -1,8 +1,11 @@ package controllers import ( + "fmt" "net/http" "os" + "strconv" + "strings" "time" "tugas1/initializers" "tugas1/models" @@ -10,6 +13,7 @@ import ( "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v4" "golang.org/x/crypto/bcrypt" + "gorm.io/gorm" ) func PostsCreate(c *gin.Context) { @@ -116,124 +120,190 @@ func PostsDelete(c *gin.Context) { // Respond c.Status(200) } - func SignUp(c *gin.Context) { - // Get the email/pass of req body var body struct { - Name string - Email string - Password string - Gender string - Address string - Tempat string - TLahir string + Email string + Password string + Nik string + Name string + Photo string + Birthdate time.Time + JobTitle string + CreatedBy string + UpdatedBy string + DeletedBy string } - - if c.Bind(&body) != nil { + if err := c.ShouldBindJSON(&body); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": "Failed to read body", }) - return } - - // Hash the password hash, err := bcrypt.GenerateFromPassword([]byte(body.Password), 10) - if err != nil { c.JSON(http.StatusBadRequest, gin.H{ - "error": "Failed to hash password", + "error": "Failed to generate password hash", }) - return } - - // Create the user - user := models.Post{Name: body.Name, Email: body.Email, Password: string(hash), Gender: body.Gender, - Address: body.Address, Tempat: body.Tempat, TLahir: body.TLahir} + user := models.Post{ + Email: body.Email, + Password: string(hash), + Nik: body.Nik, + Name: body.Name, + Photo: body.Photo, + Birthdate: body.Birthdate, + JobTitle: body.JobTitle, + LastLoginAt: time.Now(), + CreatedBy: body.Nik, + UpdatedBy: body.Nik, + DeletedBy: body.Nik, + Token: "", + } result := initializers.DB.Create(&user) - if result.Error != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": "Failed to create user", }) - return } - - // Respond + updateLoginRecord(c, user.ID, time.Now()) c.JSON(http.StatusOK, gin.H{}) } - -func Login(c *gin.Context) { - // Get the email and password for req body +func LogIn(c *gin.Context) { var body struct { - Name string Email string Password string - Gender string - Address string - Tempat string - TLahir string } - - if c.Bind(&body) != nil { + if err := c.ShouldBindJSON(&body); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": "Failed to read body", }) - return } - // Look up requested user var user models.Post initializers.DB.First(&user, "email = ?", body.Email) - if user.ID == 0 { c.JSON(http.StatusBadRequest, gin.H{ - "error": "Invalid email", + "error": "Invalid email or password", }) - return } - // Compare sent in password with saved user password hash err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(body.Password)) - if err != nil { c.JSON(http.StatusBadRequest, gin.H{ - "error": "Invalid password", + "error": "Invalid email or password", }) - return } - - // Generate a jwt token + user.LastLoginAt = time.Now() + initializers.DB.Save(&user) + updateLoginRecord(c, user.ID, time.Now()) token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ "sub": user.ID, "exp": time.Now().Add(time.Hour * 24 * 30).Unix(), }) - - // Sign and get the complete encoded token as a string using the secret tokenString, err := token.SignedString([]byte(os.Getenv("SECRET"))) - if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": "Failed to create token", }) - return } - - // Send it back c.SetSameSite(http.SameSiteLaxMode) c.SetCookie("Authorization", tokenString, 3600*24*30, "", "", false, true) - - c.JSON(http.StatusOK, gin.H{}) + c.JSON(http.StatusOK, gin.H{ + "token": tokenString, + }) +} +func LogOut(c *gin.Context) { + c.SetCookie("Authorization", "", -1, "/", "", false, true) + c.JSON(http.StatusOK, gin.H{ + "message": "Logout successful", + }) } - func Validate(c *gin.Context) { user, _ := c.Get("user") - c.JSON(http.StatusOK, gin.H{ "message": user, }) } +func updateLoginRecord(c *gin.Context, userID uint, date time.Time) { + // Cari data rekap login berdasarkan tanggal + var loginRecord models.LoginRecord + result := initializers.DB.Where("login_date = ?", date.Format("2006-01-02")).First(&loginRecord) + if result.Error != nil && result.Error != gorm.ErrRecordNotFound { + return + } + if result.Error == gorm.ErrRecordNotFound { + // Jika belum ada data rekap untuk hari ini, buat data baru + loginRecord = models.LoginRecord{ + LoginDate: date, + UserIDs: fmt.Sprintf("%d", userID), + } + initializers.DB.Create(&loginRecord) + } else { + // Jika sudah ada data rekap, cek apakah user sudah login pada hari ini + if !containsInt(loginRecord.UserIDs, userID) { + // Jika user belum login hari ini, tambahkan ID pengguna ke dalam array user_ids + + loginRecord.UserIDs = fmt.Sprintf("%s,%d", loginRecord.UserIDs, userID) + initializers.DB.Save(&loginRecord) + } + } + // Ambil data pengguna yang login pada hari ini + var users []models.Post + initializers.DB.Find(&users, "id IN (?)", parseUserIDs(loginRecord.UserIDs)) + // Update login record dengan pengguna yang login pada hari ini + loginRecord.Users = users + // Update jumlah pengguna (TotalUsers) saat pengguna baru melakukan login + + initializers.DB.Save(&loginRecord) +} + +// Helper function to check if an int is present in a slice +func containsInt(slice string, val uint) bool { + ids := parseUserIDs(slice) + for _, item := range ids { + if item == val { + return true + } + } + return false +} + +// Helper function to parse user IDs from a string +func parseUserIDs(idsStr string) []uint { + ids := strings.Split(idsStr, ",") + var userIDs []uint + for _, idStr := range ids { + id, err := strconv.ParseUint(idStr, 10, 32) + if err != nil { + continue + } + userIDs = append(userIDs, uint(id)) + } + return userIDs +} +func GetLoginRecords(c *gin.Context) { + var loginRecords []models.LoginRecord + result := initializers.DB.Find(&loginRecords) + if result.Error != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "Failed to fetch login records", + }) + return + } + // Retrieve user details for each login record + for i := range loginRecords { + var users []models.Post + initializers.DB.Find(&users, "id IN (?)", parseUserIDs(loginRecords[i].UserIDs)) + loginRecords[i].Users = users + } + // Create JSON response + var response struct { + Records []models.LoginRecord `json:"records"` + } + response.Records = loginRecords + c.JSON(http.StatusOK, response) +} diff --git a/go.mod b/go.mod index af666fa..9c72239 100644 --- a/go.mod +++ b/go.mod @@ -31,8 +31,12 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/radovskyb/watcher v1.0.7 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.11 // indirect + go.uber.org/atomic v1.7.0 // indirect + go.uber.org/multierr v1.6.0 // indirect + go.uber.org/zap v1.24.0 // indirect golang.org/x/arch v0.4.0 // indirect golang.org/x/crypto v0.10.0 // indirect golang.org/x/net v0.11.0 // indirect diff --git a/go.sum b/go.sum index 3b54256..2001f32 100644 --- a/go.sum +++ b/go.sum @@ -67,6 +67,8 @@ github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNc github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/radovskyb/watcher v1.0.7 h1:AYePLih6dpmS32vlHfhCeli8127LzkIgwJGcwwe8tUE= github.com/radovskyb/watcher v1.0.7/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm+ZuvsUYIg= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -81,6 +83,12 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= @@ -94,6 +102,7 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= diff --git a/main.go b/main.go index a03e027..21d4252 100644 --- a/main.go +++ b/main.go @@ -23,7 +23,7 @@ func main() { r.GET("/posts/:id", controllers.PostsShow) r.DELETE("/posts/:id", controllers.PostsDelete) r.POST("/signup", controllers.SignUp) - r.POST("/login", controllers.Login) + r.POST("/login", controllers.LogIn) r.GET("/validate", middleware.RequireAuth, controllers.Validate) r.Run() }