package controllers import ( "fmt" "net/http" "os" "strconv" "strings" "time" "tugas1/initializers" "tugas1/models" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v4" "golang.org/x/crypto/bcrypt" "gorm.io/gorm" ) func PostsCreate(c *gin.Context) { // Get dataoff req body var body struct { Name string Email string Password string Gender string Address string Tempat string TLahir string } c.Bind((&body)) // Create a post post := models.Post{Name: body.Name, Email: body.Email, Password: body.Password, Gender: body.Gender, Address: body.Address, Tempat: body.Tempat, TLahir: body.TLahir} result := initializers.DB.Create(&post) if result.Error != nil { c.Status(400) return } // Return it c.JSON(200, gin.H{ "post": post, }) } func PostsIndex(c *gin.Context) { // Get the posts var posts []models.Post initializers.DB.Find(&posts) // Respond with them c.JSON(200, gin.H{ "posts": posts, }) } func PostsShow(c *gin.Context) { // Get id off url id := c.Param("id") // Get the posts var post models.Post initializers.DB.First(&post, id) // Respond with them c.JSON(200, gin.H{ "post": post, }) } func PostsUpdate(c *gin.Context) { // Get the id off the url id := c.Param("id") // Get the data off req body var body struct { Name string Email string Password string Gender string Address string Tempat string TLahir string } c.Bind(&body) // Find the post were updating var post models.Post initializers.DB.First(&post, id) // Updated it initializers.DB.Model(&post).Updates(models.Post{ Name: body.Name, Email: body.Email, Password: body.Password, Gender: body.Gender, Address: body.Address, Tempat: body.Tempat, TLahir: body.TLahir, }) // Respond with it c.JSON(200, gin.H{ "post": post, }) } func PostsDelete(c *gin.Context) { // Get the id off the url id := c.Param("id") // Delete the posts initializers.DB.Delete(&models.Post{}, id) // Respond c.Status(200) } func SignUp(c *gin.Context) { var body struct { Email string Password string Nik string Name string Photo string Birthdate time.Time JobTitle string CreatedBy string UpdatedBy string DeletedBy string } if err := c.ShouldBindJSON(&body); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": "Failed to read body", }) return } hash, err := bcrypt.GenerateFromPassword([]byte(body.Password), 10) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": "Failed to generate password hash", }) return } 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 } updateLoginRecord(c, user.ID, time.Now()) c.JSON(http.StatusOK, gin.H{}) } var totalRecord int64 // variabel global untuk menyimpan total record func LogIn(c *gin.Context) { var body struct { Email string Password string } if err := c.ShouldBindJSON(&body); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "data": nil, "message": "Failed to read body", "status": false, }) return } var user models.Post result := initializers.DB.First(&user, "email = ?", body.Email) if result.Error != nil { c.JSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "data": nil, "message": "Invalid email or password", "status": false, }) return } err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(body.Password)) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "data": nil, "message": "Invalid email or password", "status": false, }) return } user.LastLoginAt = time.Now() result = initializers.DB.Save(&user) if result.Error != nil { c.JSON(http.StatusInternalServerError, gin.H{ "code": http.StatusInternalServerError, "data": nil, "message": "Failed to update user data", "status": false, }) return } 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(), }) tokenString, err := token.SignedString([]byte(os.Getenv("SECRET"))) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "data": nil, "message": "Failed to create token", "status": false, }) return } c.SetSameSite(http.SameSiteLaxMode) c.SetCookie("Authorization", tokenString, 3600*24*30, "", "", false, true) // Menghitung total record setelah operasi save totalRecord++ c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "data": user, "message": "OK", "status": true, "totalRecord": totalRecord, }) } 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) }