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