Browse Source

Pengen upload lagi

user
Seyora24 1 year ago
parent
commit
95ed97d1ba
  1. 178
      controllers/postController.go
  2. 4
      go.mod
  3. 9
      go.sum
  4. 2
      main.go

178
controllers/postController.go

@ -1,8 +1,11 @@
package controllers package controllers
import ( import (
"fmt"
"net/http" "net/http"
"os" "os"
"strconv"
"strings"
"time" "time"
"tugas1/initializers" "tugas1/initializers"
"tugas1/models" "tugas1/models"
@ -10,6 +13,7 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v4" "github.com/golang-jwt/jwt/v4"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
) )
func PostsCreate(c *gin.Context) { func PostsCreate(c *gin.Context) {
@ -116,124 +120,190 @@ func PostsDelete(c *gin.Context) {
// Respond // Respond
c.Status(200) c.Status(200)
} }
func SignUp(c *gin.Context) { func SignUp(c *gin.Context) {
// Get the email/pass of req body
var body struct { var body struct {
Name string
Email string Email string
Password string Password string
Gender string Nik string
Address string Name string
Tempat string Photo string
TLahir string Birthdate time.Time
JobTitle string
CreatedBy string
UpdatedBy string
DeletedBy string
} }
if err := c.ShouldBindJSON(&body); err != nil {
if c.Bind(&body) != nil {
c.JSON(http.StatusBadRequest, gin.H{ c.JSON(http.StatusBadRequest, gin.H{
"error": "Failed to read body", "error": "Failed to read body",
}) })
return return
} }
// Hash the password
hash, err := bcrypt.GenerateFromPassword([]byte(body.Password), 10) hash, err := bcrypt.GenerateFromPassword([]byte(body.Password), 10)
if err != nil { if err != nil {
c.JSON(http.StatusBadRequest, gin.H{ c.JSON(http.StatusBadRequest, gin.H{
"error": "Failed to hash password", "error": "Failed to generate password hash",
}) })
return return
} }
user := models.Post{
// Create the user Email: body.Email,
user := models.Post{Name: body.Name, Email: body.Email, Password: string(hash), Gender: body.Gender, Password: string(hash),
Address: body.Address, Tempat: body.Tempat, TLahir: body.TLahir} 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) result := initializers.DB.Create(&user)
if result.Error != nil { if result.Error != nil {
c.JSON(http.StatusBadRequest, gin.H{ c.JSON(http.StatusBadRequest, gin.H{
"error": "Failed to create user", "error": "Failed to create user",
}) })
return return
} }
updateLoginRecord(c, user.ID, time.Now())
// Respond
c.JSON(http.StatusOK, gin.H{}) c.JSON(http.StatusOK, gin.H{})
} }
func LogIn(c *gin.Context) {
func Login(c *gin.Context) {
// Get the email and password for req body
var body struct { var body struct {
Name string
Email string Email string
Password string Password string
Gender string
Address string
Tempat string
TLahir string
} }
if err := c.ShouldBindJSON(&body); err != nil {
if c.Bind(&body) != nil {
c.JSON(http.StatusBadRequest, gin.H{ c.JSON(http.StatusBadRequest, gin.H{
"error": "Failed to read body", "error": "Failed to read body",
}) })
return return
} }
// Look up requested user
var user models.Post var user models.Post
initializers.DB.First(&user, "email = ?", body.Email) initializers.DB.First(&user, "email = ?", body.Email)
if user.ID == 0 { if user.ID == 0 {
c.JSON(http.StatusBadRequest, gin.H{ c.JSON(http.StatusBadRequest, gin.H{
"error": "Invalid email", "error": "Invalid email or password",
}) })
return return
} }
// Compare sent in password with saved user password hash
err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(body.Password)) err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(body.Password))
if err != nil { if err != nil {
c.JSON(http.StatusBadRequest, gin.H{ c.JSON(http.StatusBadRequest, gin.H{
"error": "Invalid password", "error": "Invalid email or password",
}) })
return return
} }
user.LastLoginAt = time.Now()
// Generate a jwt token initializers.DB.Save(&user)
updateLoginRecord(c, user.ID, time.Now())
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"sub": user.ID, "sub": user.ID,
"exp": time.Now().Add(time.Hour * 24 * 30).Unix(), "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"))) tokenString, err := token.SignedString([]byte(os.Getenv("SECRET")))
if err != nil { if err != nil {
c.JSON(http.StatusBadRequest, gin.H{ c.JSON(http.StatusBadRequest, gin.H{
"error": "Failed to create token", "error": "Failed to create token",
}) })
return return
} }
// Send it back
c.SetSameSite(http.SameSiteLaxMode) c.SetSameSite(http.SameSiteLaxMode)
c.SetCookie("Authorization", tokenString, 3600*24*30, "", "", false, true) 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) { func Validate(c *gin.Context) {
user, _ := c.Get("user") user, _ := c.Get("user")
c.JSON(http.StatusOK, gin.H{ c.JSON(http.StatusOK, gin.H{
"message": user, "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)
}

4
go.mod

@ -31,8 +31,12 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/radovskyb/watcher v1.0.7 // 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/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // 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/arch v0.4.0 // indirect
golang.org/x/crypto v0.10.0 // indirect golang.org/x/crypto v0.10.0 // indirect
golang.org/x/net v0.11.0 // indirect golang.org/x/net v0.11.0 // indirect

9
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/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 h1:AYePLih6dpmS32vlHfhCeli8127LzkIgwJGcwwe8tUE=
github.com/radovskyb/watcher v1.0.7/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm+ZuvsUYIg= 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.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.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 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/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 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= 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.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 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= 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-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 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.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= golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=

2
main.go

@ -23,7 +23,7 @@ func main() {
r.GET("/posts/:id", controllers.PostsShow) r.GET("/posts/:id", controllers.PostsShow)
r.DELETE("/posts/:id", controllers.PostsDelete) r.DELETE("/posts/:id", controllers.PostsDelete)
r.POST("/signup", controllers.SignUp) r.POST("/signup", controllers.SignUp)
r.POST("/login", controllers.Login) r.POST("/login", controllers.LogIn)
r.GET("/validate", middleware.RequireAuth, controllers.Validate) r.GET("/validate", middleware.RequireAuth, controllers.Validate)
r.Run() r.Run()
} }

Loading…
Cancel
Save