package controllers import ( "crypto/rand" "encoding/base64" "golang-test/database" "golang-test/libs" "golang-test/types" "golang-test/validators" "log" "net/http" "strconv" "github.com/gin-gonic/gin" "github.com/go-playground/validator/v10" "golang.org/x/crypto/bcrypt" ) type TokenStruct struct { UserID uint token string } func RegisterUser(c *gin.Context, register types.RegisterRequest) { db := database.Connector() validate := validators.Validate var token database.Token var user database.User // Валидация входных данных if err := validate.Struct(register); err != nil { c.JSON(http.StatusBadRequest, libs.GetValidationErrors(err.(validator.ValidationErrors))) return } // Проверка, существует ли уже пользователь с таким email if userExists(register.Email) { c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: "User already exists"}) return } // Генерация хэшированного пароля hashedPassword, err := bcrypt.GenerateFromPassword([]byte(register.Password), 12) if err != nil { log.Println(err.Error()) c.JSON(http.StatusInternalServerError, types.ErrorResponse{Message: err.Error()}) return } // Создание нового пользователя user = database.User{ Name: register.Name, Email: register.Email, Password: string(hashedPassword), } // Генерация токена для пользователя token.Token = generateToken() token.UserID = user.ID user.Tokens = append(user.Tokens, token) // Сохранение пользователя в базе данных if err := db.Create(&user).Error; err != nil { c.JSON(http.StatusInternalServerError, types.ErrorResponse{Message: err.Error()}) return } // Отправка ответа с токеном c.JSON(http.StatusCreated, types.TokenResponse{Token: token.Token}) } // userExists проверяет, существует ли пользователь с данным email func userExists(email string) bool { db := database.Connector() var user database.User err := db.Where("email = ?", email).First(&user).Error return err == nil } func LoginUser(c *gin.Context, login types.LoginRequest) { var user database.User db := database.Connector() validate := validators.Validate var token database.Token if err := validate.Struct(login); err != nil { c.JSON(http.StatusBadRequest, libs.GetValidationErrors(err.(validator.ValidationErrors))) return } if err := db.Where("email = ?", login.Email).First(&user).Error; err != nil { c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: "Invalid email or password"}) return } if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(login.Password)); err != nil { c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: "Invalid email or password"}) return } token.Token = generateToken() token.UserID = user.ID user.Tokens = append(user.Tokens, token) db.Save(&user) c.JSON(http.StatusOK, types.TokenResponse{Token: token.Token}) } func generateToken() string { b := make([]byte, 25) if _, err := rand.Read(b); err != nil { return "" } return base64.StdEncoding.EncodeToString(b) } func GetUser(c *gin.Context) { var products []types.ProductResponse user, err := libs.GetUserFromHeaders(c) if err != nil { c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: err.Error()}) return } for _, product := range user.Products { products = append(products, types.ProductResponse{ ID: product.ID, Name: product.Name, Price: product.Price, }) } userResponse := types.UserResponse{ ID: user.ID, Name: user.Name, Email: user.Email, Products: products, Money: user.Money, } c.JSON(http.StatusOK, userResponse) } func EditUserName(c *gin.Context, userName types.EditUserNameRequest) { db := database.Connector() validate := validators.Validate if err := validate.Struct(userName); err != nil { c.JSON(http.StatusBadRequest, libs.GetValidationErrors(err.(validator.ValidationErrors))) return } user, err := libs.GetUserFromHeaders(c) if err != nil { c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: err.Error()}) return } user.Name = userName.Name if err := db.Save(user).Error; err != nil { c.JSON(http.StatusInternalServerError, types.ErrorResponse{Message: err.Error()}) return } c.JSON(http.StatusOK, types.MessageResponse{Message: "User name successfully updated"}) } func AddMoneyToUser(c *gin.Context, moneyRequest types.AddMoneyRequest) { db := database.Connector() user, err := libs.GetUserFromHeaders(c) if err != nil { c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: err.Error()}) return } user.Money += moneyRequest.Money if err := db.Save(&user).Error; err != nil { c.JSON(http.StatusInternalServerError, types.ErrorResponse{Message: err.Error()}) } c.JSON(http.StatusOK, types.MessageResponse{Message: "Money successfully added"}) } func BuyProduct(c *gin.Context) { var product database.Product db := database.Connector() id, err := strconv.Atoi(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()}) return } if err := db.First(&product, id).Error; err != nil { c.JSON(http.StatusBadRequest, types.NotFoundError("Product", id)) return } user, err := libs.GetUserFromHeaders(c) if err != nil { c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: err.Error()}) return } if user.Money-product.Price < 0 { c.JSON(http.StatusOK, types.MessageResponse{Message: "Not enough money"}) return } user.Money -= product.Price user.Products = append(user.Products, product) db.Save(&user) c.JSON(http.StatusOK, types.MessageResponse{Message: "Product successful buyed"}) } func GetBuyedProducts(c *gin.Context) { var response []types.ProductResponse user, err := libs.GetUserFromHeaders(c) if err != nil { c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: err.Error()}) return } for _, product := range user.Products { manufacturer := types.ManufacturerResponse{ ID: product.ManufacturerID, Name: product.Manufacturer.Name, } response = append(response, types.ProductResponse{ ID: product.ID, Name: product.Manufacturer.Name, Price: product.Price, ManufacturerID: manufacturer.ID, Manufacturer: manufacturer, }) } c.JSON(http.StatusOK, response) }