package api import ( "errors" "fmt" "net/http" "git.artlef.fr/PersonalLibraryManager/internal/jwtauth" "git.artlef.fr/PersonalLibraryManager/internal/model" "github.com/gin-gonic/gin" "github.com/go-playground/validator/v10" "golang.org/x/crypto/bcrypt" "gorm.io/gorm" ) func GetMyBooksHanderl(c *gin.Context, db *gorm.DB) { var userbooks []model.UserBook user, err := getAuthenticatedUser(c, db) if err != nil { manageDefaultError(c, err) return } db.Preload("Book").Where("user_id = ?", user.ID).Find(&userbooks) var booksDto []bookUserGet for _, userbook := range userbooks { booksDto = append(booksDto, fromUserBookDb(&userbook)) } c.JSON(http.StatusOK, booksDto) } func PostBookHandler(c *gin.Context, db *gorm.DB) { var book bookPostCreate err := c.ShouldBindJSON(&book) if err != nil { manageBindingError(c, err) return } user, fetchUserErr := getAuthenticatedUser(c, db) if fetchUserErr != nil { manageDefaultError(c, err) return } bookDb := book.toBook(&user) err = db.Model(&model.Book{}).Save(&bookDb).Error if err != nil { manageDefaultError(c, err) return } c.String(200, "Success") } func PostSignupHandler(c *gin.Context, db *gorm.DB) { var user userSignup err := c.ShouldBindJSON(&user) if err != nil { manageBindingError(c, err) return } userDb, err := user.toUser() if err != nil { manageDefaultError(c, err) return } err = db.Model(&model.User{}).Save(&userDb).Error if err != nil { manageDefaultError(c, err) return } c.String(200, "Success") } func PostLoginHandler(c *gin.Context, db *gorm.DB) { var user userLogin err := c.ShouldBindJSON(&user) if err != nil { manageBindingError(c, err) return } if !isUserAndPasswordOk(db, user.Username, user.Password) { c.JSON(http.StatusInternalServerError, gin.H{"error": "Invalid credentials."}) return } var jwtToken string jwtToken, err = jwtauth.GenerateJwtToken(user.Username) if err != nil { c.JSON(http.StatusUnauthorized, gin.H{"error": fmt.Errorf("Error when generating JWT token: %w", err)}) return } c.JSON(200, gin.H{"message": "Authentication was a success.", "token": jwtToken}) } func isUserAndPasswordOk(db *gorm.DB, username string, password string) bool { var user model.User db.Where("name = ?", username).First(&user) err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)) return err == nil } func getAuthenticatedUser(c *gin.Context, db *gorm.DB) (model.User, error) { var user model.User username, userIsInContext := c.Get("user") if !userIsInContext { return user, errors.New("User not found in context") } res := db.Where("name = ?", username).First(&user) return user, res.Error } func manageBindingError(c *gin.Context, err error) { var ve validator.ValidationErrors if errors.As(err, &ve) { c.JSON(http.StatusBadRequest, getValidationErrors(&ve)) } else { manageDefaultError(c, err) } } func manageDefaultError(c *gin.Context, err error) { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) }