Code refactoring, added comments.
This commit is contained in:
parent
434c36a4e0
commit
6f56536781
|
@ -1,74 +1,93 @@
|
||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-playground/validator/v10"
|
|
||||||
"golang-test/database"
|
"golang-test/database"
|
||||||
"golang-test/libs"
|
"golang-test/libs"
|
||||||
"golang-test/types"
|
"golang-test/types"
|
||||||
"golang-test/validators"
|
"golang-test/validators"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/go-playground/validator/v10"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// CreateManufacturer создает нового производителя в базе данных.
|
||||||
func CreateManufacturer(c *gin.Context, manufacturer database.Manufacturer) {
|
func CreateManufacturer(c *gin.Context, manufacturer database.Manufacturer) {
|
||||||
db := database.Connector()
|
db := database.Connector() // Подключение к базе данных
|
||||||
validate := validators.Validate
|
validate := validators.Validate // Валидатор для проверки входных данных
|
||||||
|
|
||||||
|
// Валидация структуры производителя
|
||||||
if err := validate.Struct(manufacturer); err != nil {
|
if err := validate.Struct(manufacturer); err != nil {
|
||||||
c.JSON(http.StatusBadRequest, libs.GetValidationErrors(err.(validator.ValidationErrors)))
|
c.JSON(http.StatusBadRequest, libs.GetValidationErrors(err.(validator.ValidationErrors)))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Добавление производителя в базу данных
|
||||||
if err := db.Create(&manufacturer).Error; err != nil {
|
if err := db.Create(&manufacturer).Error; err != nil {
|
||||||
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()})
|
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusCreated, types.MessageResponse{Message: "Manufacturer created successfully"})
|
c.JSON(http.StatusCreated, types.MessageResponse{Message: "Manufacturer created successfully"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteManufacturer удаляет производителя из базы данных по ID.
|
||||||
func DeleteManufacturer(c *gin.Context) {
|
func DeleteManufacturer(c *gin.Context) {
|
||||||
db := database.Connector()
|
db := database.Connector() // Подключение к базе данных
|
||||||
|
|
||||||
id := c.Param("id")
|
id := c.Param("id") // Получение ID из параметров запроса
|
||||||
|
|
||||||
var manufacturer database.Manufacturer
|
var manufacturer database.Manufacturer
|
||||||
|
|
||||||
|
// Поиск производителя по ID
|
||||||
if db.First(&manufacturer, id).Error != nil {
|
if db.First(&manufacturer, id).Error != nil {
|
||||||
c.JSON(http.StatusNotFound, types.NotFoundError("Manufacturer", id))
|
c.JSON(http.StatusNotFound, types.NotFoundError("Manufacturer", id))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Удаление производителя
|
||||||
if err := db.Delete(&manufacturer, id).Error; err != nil {
|
if err := db.Delete(&manufacturer, id).Error; err != nil {
|
||||||
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()})
|
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, types.MessageResponse{Message: "Manufacturer deleted successfully"})
|
c.JSON(http.StatusOK, types.MessageResponse{Message: "Manufacturer deleted successfully"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetManufacturers возвращает список всех производителей.
|
||||||
func GetManufacturers(c *gin.Context) {
|
func GetManufacturers(c *gin.Context) {
|
||||||
db := database.Connector()
|
db := database.Connector() // Подключение к базе данных
|
||||||
var manufacturers []types.ManufacturerResponse
|
var manufacturers []types.ManufacturerResponse
|
||||||
|
|
||||||
|
// Получение списка производителей
|
||||||
if err := db.Model(&database.Manufacturer{}).Select("ID", "Name").Scan(&manufacturers).Error; err != nil {
|
if err := db.Model(&database.Manufacturer{}).Select("ID", "Name").Scan(&manufacturers).Error; err != nil {
|
||||||
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()})
|
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, manufacturers)
|
c.JSON(http.StatusOK, manufacturers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EditManufacture редактирует информацию о производителе.
|
||||||
func EditManufacture(c *gin.Context, editedManufacturer types.ManufacturerPatchRequest) {
|
func EditManufacture(c *gin.Context, editedManufacturer types.ManufacturerPatchRequest) {
|
||||||
db := database.Connector()
|
db := database.Connector() // Подключение к базе данных
|
||||||
id := c.Param("id")
|
id := c.Param("id") // Получение ID из параметров запроса
|
||||||
var manufacturer database.Manufacturer
|
var manufacturer database.Manufacturer
|
||||||
|
|
||||||
validate := validators.Validate
|
validate := validators.Validate // Валидатор для проверки входных данных
|
||||||
|
|
||||||
|
// Валидация измененных данных
|
||||||
if err := validate.Struct(editedManufacturer); err != nil {
|
if err := validate.Struct(editedManufacturer); err != nil {
|
||||||
c.JSON(http.StatusBadRequest, libs.GetValidationErrors(err.(validator.ValidationErrors)))
|
c.JSON(http.StatusBadRequest, libs.GetValidationErrors(err.(validator.ValidationErrors)))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Поиск и обновление данных производителя
|
||||||
if db.First(&manufacturer, id).Error != nil {
|
if db.First(&manufacturer, id).Error != nil {
|
||||||
c.JSON(http.StatusNotFound, types.NotFoundError("Manufacturer", id))
|
c.JSON(http.StatusNotFound, types.NotFoundError("Manufacturer", id))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
db.First(&manufacturer, id)
|
|
||||||
manufacturer.Name = editedManufacturer.Name
|
manufacturer.Name = editedManufacturer.Name
|
||||||
db.Save(&manufacturer)
|
db.Save(&manufacturer)
|
||||||
|
|
||||||
|
|
|
@ -1,169 +1,115 @@
|
||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-playground/validator/v10"
|
|
||||||
"golang-test/database"
|
"golang-test/database"
|
||||||
"golang-test/libs"
|
"golang-test/libs"
|
||||||
"golang-test/types"
|
"golang-test/types"
|
||||||
"golang-test/validators"
|
"golang-test/validators"
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
//"golang-test/migrations"
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/go-playground/validator/v10"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// CreateProduct создает новый продукт в базе данных.
|
||||||
func CreateProduct(c *gin.Context, product database.Product) {
|
func CreateProduct(c *gin.Context, product database.Product) {
|
||||||
db := database.Connector()
|
db := database.Connector()
|
||||||
validate := validators.Validate
|
validate := validators.Validate
|
||||||
//response := types.MessageResponse{Message: "Product Created"}
|
|
||||||
var manufacturer *database.Manufacturer
|
|
||||||
|
|
||||||
|
// Проверка данных продукта.
|
||||||
if err := validate.Struct(&product); err != nil {
|
if err := validate.Struct(&product); err != nil {
|
||||||
c.JSON(http.StatusBadRequest, libs.GetValidationErrors(err.(validator.ValidationErrors)))
|
c.JSON(http.StatusBadRequest, libs.GetValidationErrors(err.(validator.ValidationErrors)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Проверка существования производителя.
|
||||||
|
var manufacturer *database.Manufacturer
|
||||||
if err := db.First(&manufacturer, product.ManufacturerID).Error; err != nil {
|
if err := db.First(&manufacturer, product.ManufacturerID).Error; err != nil {
|
||||||
c.JSON(http.StatusBadRequest, types.NotFoundError("Product", product.ManufacturerID))
|
c.JSON(http.StatusBadRequest, types.NotFoundError("Product", product.ManufacturerID))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
product.Manufacturer = manufacturer
|
// Добавление продукта в базу данных.
|
||||||
|
|
||||||
log.Println(*product.Manufacturer)
|
|
||||||
|
|
||||||
if err := db.Create(&product).Error; err != nil {
|
if err := db.Create(&product).Error; err != nil {
|
||||||
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()})
|
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Отправка ответа о успешном создании продукта.
|
||||||
c.JSON(http.StatusCreated, types.MessageResponse{Message: "Product created"})
|
c.JSON(http.StatusCreated, types.MessageResponse{Message: "Product created"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteProduct удаляет продукт по ID.
|
||||||
func DeleteProduct(c *gin.Context) {
|
func DeleteProduct(c *gin.Context) {
|
||||||
db := database.Connector()
|
db := database.Connector()
|
||||||
id := c.Param("id")
|
id := c.Param("id")
|
||||||
|
|
||||||
var product database.Product
|
var product database.Product
|
||||||
|
|
||||||
response := types.MessageResponse{
|
// Проверка существования продукта перед удалением.
|
||||||
Message: "Product deleted",
|
|
||||||
}
|
|
||||||
|
|
||||||
if db.First(&product, id).Error != nil {
|
if db.First(&product, id).Error != nil {
|
||||||
c.JSON(http.StatusNotFound, types.NotFoundError("Product", id))
|
c.JSON(http.StatusNotFound, types.NotFoundError("Product", id))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
db.Delete(&product, id)
|
// Удаление продукта из базы данных.
|
||||||
|
if err := db.Delete(&product, id).Error; err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, types.ErrorResponse{Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, response)
|
// Отправка ответа о успешном удалении.
|
||||||
|
c.JSON(http.StatusOK, types.MessageResponse{Message: "Product deleted"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetProducts возвращает список всех продуктов.
|
||||||
func GetProducts(c *gin.Context) {
|
func GetProducts(c *gin.Context) {
|
||||||
db := database.Connector()
|
db := database.Connector()
|
||||||
var product []database.Product
|
var products []database.Product
|
||||||
var productResp []types.ProductResponse
|
var productResp []types.ProductResponse
|
||||||
|
|
||||||
db.Find(&product).Scan(&productResp)
|
// Получение продуктов из базы данных.
|
||||||
|
if err := db.Preload("Manufacturer").Find(&products).Scan(&productResp).Error; err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, types.ErrorResponse{Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Добавление информации о производителе к каждому продукту.
|
||||||
for i, element := range productResp {
|
for i, element := range productResp {
|
||||||
var manufacturer types.ManufacturerResponse
|
var manufacturer types.ManufacturerResponse
|
||||||
db.First(&database.Manufacturer{}, element.ManufacturerID).Scan(&manufacturer)
|
db.First(&database.Manufacturer{}, element.ManufacturerID).Scan(&manufacturer)
|
||||||
productResp[i].Manufacturer = manufacturer
|
productResp[i].Manufacturer = manufacturer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Отправка списка продуктов.
|
||||||
c.JSON(http.StatusOK, productResp)
|
c.JSON(http.StatusOK, productResp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetProductInfo возвращает информацию о продукте по ID.
|
||||||
func GetProductInfo(c *gin.Context) {
|
func GetProductInfo(c *gin.Context) {
|
||||||
db := database.Connector()
|
db := database.Connector()
|
||||||
id, err := strconv.Atoi(c.Param("id"))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()})
|
|
||||||
}
|
|
||||||
|
|
||||||
//var productResponse types.ProductResponse
|
|
||||||
var product database.Product
|
var product database.Product
|
||||||
var productResp types.ProductResponse
|
var productResp types.ProductResponse
|
||||||
var manufacturer types.ManufacturerResponse
|
|
||||||
|
|
||||||
if err := db.First(&product, id).Select("ID", "Name", "Price", "ManufacturerID").Scan(&productResp).Error; err != nil {
|
|
||||||
c.JSON(http.StatusBadRequest, types.NotFoundError("Product", id))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := db.First(&product.Manufacturer, product.ManufacturerID).Scan(&manufacturer).Error; err != nil {
|
|
||||||
c.JSON(http.StatusBadRequest, types.NotFoundError("Product", product.ManufacturerID))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
productResp.Manufacturer = manufacturer
|
|
||||||
log.Println(product.Manufacturer)
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, productResp)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BuyProduct(c *gin.Context) {
|
|
||||||
var product database.Product
|
|
||||||
|
|
||||||
db := database.Connector()
|
|
||||||
id, err := strconv.Atoi(c.Param("id"))
|
id, err := strconv.Atoi(c.Param("id"))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()})
|
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := db.First(&product, id).Error; err != nil {
|
// Получение продукта из базы данных.
|
||||||
|
if err := db.Preload("Manufacturer").First(&product, id).Scan(&productResp).Error; err != nil {
|
||||||
c.JSON(http.StatusBadRequest, types.NotFoundError("Product", id))
|
c.JSON(http.StatusBadRequest, types.NotFoundError("Product", id))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
token, err := libs.GetTokenFromHeaders(c)
|
// Добавление информации о производителе в ответ.
|
||||||
|
productResp.Manufacturer = types.ManufacturerResponse{
|
||||||
if err != nil {
|
Name: product.Manufacturer.Name,
|
||||||
c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: "Invalid token. Please login"})
|
ID: product.Manufacturer.ID,
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u, err := GetUserByToken(token)
|
// Отправка информации о продукте.
|
||||||
if err != nil {
|
c.JSON(http.StatusOK, productResp)
|
||||||
c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: "Invalid token. Please login"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if u.Money-product.Price < 0 {
|
|
||||||
c.JSON(http.StatusOK, types.MessageResponse{Message: "Not enough money"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
u.Money -= product.Price
|
|
||||||
|
|
||||||
u.Products = append(u.Products, product)
|
|
||||||
|
|
||||||
db.Save(&u)
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, types.MessageResponse{Message: "Product successful buyed"})
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetBuyedProducts(c *gin.Context) {
|
|
||||||
db := database.Connector()
|
|
||||||
|
|
||||||
token, err := libs.GetTokenFromHeaders(c)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: "Invalid token. Please login"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
u, err := GetUserByToken(token)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: "Invalid token. Please login"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
db.Joins("Products").First(&u)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,15 +3,17 @@ package controllers
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/go-playground/validator/v10"
|
|
||||||
"golang-test/database"
|
"golang-test/database"
|
||||||
"golang-test/libs"
|
"golang-test/libs"
|
||||||
"golang-test/types"
|
"golang-test/types"
|
||||||
"golang-test/validators"
|
"golang-test/validators"
|
||||||
"golang.org/x/crypto/bcrypt"
|
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/go-playground/validator/v10"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TokenStruct struct {
|
type TokenStruct struct {
|
||||||
|
@ -23,16 +25,21 @@ func RegisterUser(c *gin.Context, register types.RegisterRequest) {
|
||||||
db := database.Connector()
|
db := database.Connector()
|
||||||
validate := validators.Validate
|
validate := validators.Validate
|
||||||
var token database.Token
|
var token database.Token
|
||||||
|
var user database.User
|
||||||
|
|
||||||
|
// Валидация входных данных
|
||||||
if err := validate.Struct(register); err != nil {
|
if err := validate.Struct(register); err != nil {
|
||||||
c.JSON(http.StatusBadRequest, libs.GetValidationErrors(err.(validator.ValidationErrors)))
|
c.JSON(http.StatusBadRequest, libs.GetValidationErrors(err.(validator.ValidationErrors)))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := db.Where("email =?", register.Email).Error; err == nil {
|
// Проверка, существует ли уже пользователь с таким email
|
||||||
|
if userExists(register.Email) {
|
||||||
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: "User already exists"})
|
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: "User already exists"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Генерация хэшированного пароля
|
||||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(register.Password), 12)
|
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(register.Password), 12)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err.Error())
|
log.Println(err.Error())
|
||||||
|
@ -40,24 +47,36 @@ func RegisterUser(c *gin.Context, register types.RegisterRequest) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
user := database.User{
|
// Создание нового пользователя
|
||||||
|
user = database.User{
|
||||||
Name: register.Name,
|
Name: register.Name,
|
||||||
Email: register.Email,
|
Email: register.Email,
|
||||||
Password: string(hashedPassword),
|
Password: string(hashedPassword),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Генерация токена для пользователя
|
||||||
|
token.Token = generateToken()
|
||||||
|
token.UserID = user.ID
|
||||||
|
user.Tokens = append(user.Tokens, token)
|
||||||
|
|
||||||
|
// Сохранение пользователя в базе данных
|
||||||
if err := db.Create(&user).Error; err != nil {
|
if err := db.Create(&user).Error; err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, types.ErrorResponse{Message: err.Error()})
|
c.JSON(http.StatusInternalServerError, types.ErrorResponse{Message: err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
token.Token = generateToken()
|
// Отправка ответа с токеном
|
||||||
token.UserID = user.ID
|
|
||||||
user.Tokens = append(user.Tokens, token)
|
|
||||||
|
|
||||||
c.JSON(http.StatusCreated, types.TokenResponse{Token: token.Token})
|
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) {
|
func LoginUser(c *gin.Context, login types.LoginRequest) {
|
||||||
var user database.User
|
var user database.User
|
||||||
db := database.Connector()
|
db := database.Connector()
|
||||||
|
@ -97,44 +116,34 @@ func generateToken() string {
|
||||||
return base64.StdEncoding.EncodeToString(b)
|
return base64.StdEncoding.EncodeToString(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetUserByToken(token string) (database.User, error) {
|
|
||||||
var tokenObject database.Token
|
|
||||||
var err error
|
|
||||||
var user database.User
|
|
||||||
|
|
||||||
db := database.Connector()
|
|
||||||
if err := db.Where("token = ?", token).First(&tokenObject).Error; err != nil {
|
|
||||||
return user, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := db.First(&user, tokenObject.UserID).Error; err != nil {
|
|
||||||
return user, err
|
|
||||||
}
|
|
||||||
return user, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetUser(c *gin.Context) {
|
func GetUser(c *gin.Context) {
|
||||||
token, err := libs.GetTokenFromHeaders(c)
|
var products []types.ProductResponse
|
||||||
|
user, err := libs.GetUserFromHeaders(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: "Invalid token. Please login"})
|
c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: err.Error()})
|
||||||
}
|
|
||||||
|
|
||||||
u, err := GetUserByToken(token)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: "Invalid token. Please login"})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, u)
|
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) {
|
func EditUserName(c *gin.Context, userName types.EditUserNameRequest) {
|
||||||
token, err := libs.GetTokenFromHeaders(c)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: "Invalid token. Please login"})
|
|
||||||
}
|
|
||||||
|
|
||||||
db := database.Connector()
|
db := database.Connector()
|
||||||
validate := validators.Validate
|
validate := validators.Validate
|
||||||
|
|
||||||
|
@ -143,18 +152,98 @@ func EditUserName(c *gin.Context, userName types.EditUserNameRequest) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
u, err := GetUserByToken(token)
|
user, err := libs.GetUserFromHeaders(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: "Invalid token. Please login"})
|
c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
u.Name = userName.Name
|
user.Name = userName.Name
|
||||||
|
|
||||||
if err := db.Save(u).Error; err != nil {
|
if err := db.Save(user).Error; err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, types.ErrorResponse{Message: err.Error()})
|
c.JSON(http.StatusInternalServerError, types.ErrorResponse{Message: err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, types.MessageResponse{Message: "User name successfully updated"})
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -12,7 +12,8 @@ type Product struct {
|
||||||
Name string `validate:"required"`
|
Name string `validate:"required"`
|
||||||
Price uint `validate:"required"`
|
Price uint `validate:"required"`
|
||||||
ManufacturerID uint `validate:"required"`
|
ManufacturerID uint `validate:"required"`
|
||||||
Manufacturer *Manufacturer `gorm:"foreignKey:ManufacturerID;references:ID"`
|
Manufacturer *Manufacturer `gorm:"foreignKey:ManufacturerID"`
|
||||||
|
Users []User `gorm:"many2many:user_products;"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Token struct {
|
type Token struct {
|
||||||
|
@ -28,6 +29,6 @@ type User struct {
|
||||||
Email string `validate:"required"`
|
Email string `validate:"required"`
|
||||||
Password string `validate:"required"`
|
Password string `validate:"required"`
|
||||||
Products []Product `gorm:"many2many:user_products;"`
|
Products []Product `gorm:"many2many:user_products;"`
|
||||||
Tokens []Token `gorm:"many2many:user_token;"`
|
Tokens []Token
|
||||||
Money uint `gorm:"default:0"`
|
Money uint `gorm:"default:0"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
// Package docs Code generated by swaggo/swag. DO NOT EDIT
|
||||||
|
package docs
|
||||||
|
|
||||||
|
import "github.com/swaggo/swag"
|
||||||
|
|
||||||
|
const docTemplate = `{
|
||||||
|
"schemes": {{ marshal .Schemes }},
|
||||||
|
"swagger": "2.0",
|
||||||
|
"info": {
|
||||||
|
"description": "{{escape .Description}}",
|
||||||
|
"title": "{{.Title}}",
|
||||||
|
"contact": {},
|
||||||
|
"version": "{{.Version}}"
|
||||||
|
},
|
||||||
|
"host": "{{.Host}}",
|
||||||
|
"basePath": "{{.BasePath}}",
|
||||||
|
"paths": {}
|
||||||
|
}`
|
||||||
|
|
||||||
|
// SwaggerInfo holds exported Swagger Info so clients can modify it
|
||||||
|
var SwaggerInfo = &swag.Spec{
|
||||||
|
Version: "1.0",
|
||||||
|
Host: "",
|
||||||
|
BasePath: "",
|
||||||
|
Schemes: []string{},
|
||||||
|
Title: "API для тестового задания на Golang",
|
||||||
|
Description: "",
|
||||||
|
InfoInstanceName: "swagger",
|
||||||
|
SwaggerTemplate: docTemplate,
|
||||||
|
LeftDelim: "{{",
|
||||||
|
RightDelim: "}}",
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"swagger": "2.0",
|
||||||
|
"info": {
|
||||||
|
"title": "API для тестового задания на Golang",
|
||||||
|
"contact": {},
|
||||||
|
"version": "1.0"
|
||||||
|
},
|
||||||
|
"paths": {}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
info:
|
||||||
|
contact: {}
|
||||||
|
title: API для тестового задания на Golang
|
||||||
|
version: "1.0"
|
||||||
|
paths: {}
|
||||||
|
swagger: "2.0"
|
17
go.mod
17
go.mod
|
@ -5,17 +5,28 @@ go 1.22.3
|
||||||
require (
|
require (
|
||||||
github.com/gin-gonic/gin v1.10.0
|
github.com/gin-gonic/gin v1.10.0
|
||||||
github.com/go-playground/validator/v10 v10.20.0
|
github.com/go-playground/validator/v10 v10.20.0
|
||||||
|
github.com/swaggo/files v1.0.1
|
||||||
|
github.com/swaggo/gin-swagger v1.6.0
|
||||||
|
github.com/swaggo/swag v1.16.3
|
||||||
|
golang.org/x/crypto v0.23.0
|
||||||
gorm.io/driver/postgres v1.5.7
|
gorm.io/driver/postgres v1.5.7
|
||||||
gorm.io/gorm v1.25.10
|
gorm.io/gorm v1.25.10
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||||
|
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||||
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||||
github.com/bytedance/sonic v1.11.6 // indirect
|
github.com/bytedance/sonic v1.11.6 // indirect
|
||||||
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
|
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||||
|
github.com/go-openapi/jsonreference v0.19.6 // indirect
|
||||||
|
github.com/go-openapi/spec v0.20.4 // indirect
|
||||||
|
github.com/go-openapi/swag v0.19.15 // indirect
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/goccy/go-json v0.10.2 // indirect
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
|
@ -24,10 +35,11 @@ require (
|
||||||
github.com/jackc/pgx/v5 v5.4.3 // indirect
|
github.com/jackc/pgx/v5 v5.4.3 // indirect
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||||
github.com/kr/text v0.2.0 // indirect
|
|
||||||
github.com/leodido/go-urn v1.4.0 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
|
github.com/mailru/easyjson v0.7.6 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
@ -36,10 +48,11 @@ require (
|
||||||
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.12 // indirect
|
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||||
golang.org/x/arch v0.8.0 // indirect
|
golang.org/x/arch v0.8.0 // indirect
|
||||||
golang.org/x/crypto v0.23.0 // indirect
|
|
||||||
golang.org/x/net v0.25.0 // indirect
|
golang.org/x/net v0.25.0 // indirect
|
||||||
golang.org/x/sys v0.20.0 // indirect
|
golang.org/x/sys v0.20.0 // indirect
|
||||||
golang.org/x/text v0.15.0 // indirect
|
golang.org/x/text v0.15.0 // indirect
|
||||||
|
golang.org/x/tools v0.7.0 // indirect
|
||||||
google.golang.org/protobuf v1.34.1 // indirect
|
google.golang.org/protobuf v1.34.1 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
74
go.sum
74
go.sum
|
@ -1,3 +1,9 @@
|
||||||
|
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
||||||
|
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
|
||||||
|
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
|
||||||
|
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||||
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||||
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||||
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
|
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
|
||||||
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
||||||
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
||||||
|
@ -12,10 +18,22 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||||
|
github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4=
|
||||||
|
github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk=
|
||||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||||
|
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||||
|
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
|
||||||
|
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||||
|
github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
|
||||||
|
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
|
||||||
|
github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
|
||||||
|
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
|
||||||
|
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||||
|
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
|
||||||
|
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||||
|
@ -39,18 +57,27 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
|
||||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
|
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||||
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||||
|
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
|
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
|
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
|
||||||
|
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
@ -58,6 +85,7 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
@ -69,6 +97,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
@ -76,31 +105,76 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE=
|
||||||
|
github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg=
|
||||||
|
github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+zy8M=
|
||||||
|
github.com/swaggo/gin-swagger v1.6.0/go.mod h1:BG00cCEy294xtVpyIAHG6+e2Qzj/xKlRdOqDkvq0uzo=
|
||||||
|
github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg=
|
||||||
|
github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk=
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||||
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.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
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.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
||||||
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
|
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
|
||||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
|
||||||
|
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
||||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/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.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
||||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
|
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
|
||||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
|
||||||
|
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
|
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
|
||||||
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM=
|
gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM=
|
||||||
|
|
|
@ -5,7 +5,11 @@ meta {
|
||||||
}
|
}
|
||||||
|
|
||||||
get {
|
get {
|
||||||
url: {{host}}
|
url: {{host}}/product/4/buy
|
||||||
body: none
|
body: none
|
||||||
auth: none
|
auth: bearer
|
||||||
|
}
|
||||||
|
|
||||||
|
auth:bearer {
|
||||||
|
token: {{token}}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ meta {
|
||||||
}
|
}
|
||||||
|
|
||||||
get {
|
get {
|
||||||
url: {{host}}/product/19
|
url: {{host}}/product/4
|
||||||
body: none
|
body: none
|
||||||
auth: none
|
auth: none
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
meta {
|
||||||
|
name: Test
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: {{host}}/test
|
||||||
|
body: none
|
||||||
|
auth: none
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
meta {
|
||||||
|
name: Add Money
|
||||||
|
type: http
|
||||||
|
seq: 6
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
url: {{host}}/user/addmoney
|
||||||
|
body: json
|
||||||
|
auth: bearer
|
||||||
|
}
|
||||||
|
|
||||||
|
auth:bearer {
|
||||||
|
token: {{token}}
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"Money": 100
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,9 +7,9 @@ meta {
|
||||||
get {
|
get {
|
||||||
url: {{host}}/user
|
url: {{host}}/user
|
||||||
body: none
|
body: none
|
||||||
auth: none
|
auth: bearer
|
||||||
}
|
}
|
||||||
|
|
||||||
headers {
|
auth:bearer {
|
||||||
Authorization: Bearer TPqB2mHBjRkvLpH3M6kWSWVMj7O75t665g==
|
token: {{token}}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,5 +2,5 @@ vars {
|
||||||
host: http://localhost:8080
|
host: http://localhost:8080
|
||||||
manufacturerID: 1
|
manufacturerID: 1
|
||||||
productID: 6
|
productID: 6
|
||||||
token: TPqB2mHBjRkvLpH3M6kWSWVMj7O75t665g==
|
token: npG8pIdPaFSBHdM119QpZtm773KKCoVIGw==
|
||||||
}
|
}
|
||||||
|
|
35
libs/libs.go
35
libs/libs.go
|
@ -2,17 +2,19 @@ package libs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"golang-test/database"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
"golang-test/types"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ValidationErrorsType определяет тип для хранения ошибок валидации.
|
||||||
type ValidationErrorsType struct {
|
type ValidationErrorsType struct {
|
||||||
Errors map[string]string `json:"errors"`
|
Errors map[string]string `json:"errors"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetValidationErrors преобразует ошибки валидации в удобный для использования формат.
|
||||||
func GetValidationErrors(errs validator.ValidationErrors) ValidationErrorsType {
|
func GetValidationErrors(errs validator.ValidationErrors) ValidationErrorsType {
|
||||||
errors := make(map[string]string)
|
errors := make(map[string]string)
|
||||||
for _, err := range errs {
|
for _, err := range errs {
|
||||||
|
@ -22,6 +24,7 @@ func GetValidationErrors(errs validator.ValidationErrors) ValidationErrorsType {
|
||||||
return ValidationErrorsType{Errors: errors}
|
return ValidationErrorsType{Errors: errors}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToSnakeCase преобразует строку из CamelCase в snake_case.
|
||||||
func ToSnakeCase(str string) string {
|
func ToSnakeCase(str string) string {
|
||||||
var result []rune
|
var result []rune
|
||||||
for i, r := range str {
|
for i, r := range str {
|
||||||
|
@ -33,16 +36,32 @@ func ToSnakeCase(str string) string {
|
||||||
return strings.ToLower(string(result))
|
return strings.ToLower(string(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetTokenFromHeaders(c *gin.Context) (string, error) {
|
// GetUserFromHeaders извлекает пользователя из заголовков запроса.
|
||||||
|
func GetUserFromHeaders(c *gin.Context) (database.User, error) {
|
||||||
|
var tokenObject database.Token
|
||||||
|
var user database.User
|
||||||
|
db := database.Connector()
|
||||||
|
|
||||||
|
// Проверка наличия заголовка Authorization
|
||||||
if c.Request.Header["Authorization"] == nil {
|
if c.Request.Header["Authorization"] == nil {
|
||||||
return "", errors.New("Authorization required")
|
return user, errors.New("no Authorization header")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(strings.Split(c.Request.Header["Authorization"][0], " ")) < 2 {
|
if len(strings.Split(c.Request.Header["Authorization"][0], " ")) < 2 {
|
||||||
c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: "Invalid token. Please login"})
|
return user, errors.New("invalid Token. Please Login")
|
||||||
return "", errors.New("Authorization required")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
token := strings.Split(c.Request.Header["Authorization"][0], " ")[1]
|
token := strings.Split(c.Request.Header["Authorization"][0], " ")[1]
|
||||||
|
|
||||||
return token, nil
|
// Поиск токена в базе данных
|
||||||
|
if err := db.Where("token = ?", token).First(&tokenObject).Error; err != nil {
|
||||||
|
return user, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Загрузка пользователя с предварительной загрузкой связанных продуктов и производителей
|
||||||
|
if err := db.Preload("Products.Manufacturer").Preload("Products").First(&user, tokenObject.UserID).Error; err != nil {
|
||||||
|
return user, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
177
main.go
177
main.go
|
@ -1,120 +1,140 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// "fmt"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"golang-test/controllers"
|
"golang-test/controllers"
|
||||||
"golang-test/database"
|
"golang-test/database"
|
||||||
"golang-test/types"
|
"golang-test/types"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
swaggerFiles "github.com/swaggo/files"
|
||||||
|
ginSwagger "github.com/swaggo/gin-swagger"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// @title API для тестового задания на Golang
|
||||||
|
// @version 1.0
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
// Создание сервера
|
// Создание сервера
|
||||||
r := gin.Default()
|
r := gin.Default()
|
||||||
|
|
||||||
//View для создание товара
|
// Добавляем Swagger UI
|
||||||
|
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
r.POST("/product", func(c *gin.Context) {
|
r.POST("/product", func(c *gin.Context) {
|
||||||
var product database.Product
|
var product database.Product
|
||||||
if err := c.ShouldBind(&product); err != nil {
|
if err := c.ShouldBind(&product); err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
controllers.CreateProduct(c, product)
|
controllers.CreateProduct(c, product)
|
||||||
})
|
})
|
||||||
|
|
||||||
//View для удаления товара
|
|
||||||
r.DELETE("/product/:id", func(c *gin.Context) {
|
r.DELETE("/product/:id", func(c *gin.Context) {
|
||||||
controllers.DeleteProduct(c)
|
controllers.DeleteProduct(c)
|
||||||
})
|
})
|
||||||
|
|
||||||
//View для просмотра всех продуктов
|
|
||||||
r.GET("/product", func(c *gin.Context) {
|
r.GET("/product", func(c *gin.Context) {
|
||||||
controllers.GetProducts(c)
|
controllers.GetProducts(c)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
r.GET("/product/:id", func(c *gin.Context) {
|
r.GET("/product/:id", func(c *gin.Context) {
|
||||||
controllers.GetProductInfo(c)
|
controllers.GetProductInfo(c)
|
||||||
})
|
})
|
||||||
|
|
||||||
//View для создания производителя
|
|
||||||
r.POST("/manufacturer", func(c *gin.Context) {
|
|
||||||
var manufacturer database.Manufacturer
|
|
||||||
if err := c.ShouldBind(&manufacturer); err != nil {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
||||||
}
|
|
||||||
|
|
||||||
controllers.CreateManufacturer(c, manufacturer)
|
|
||||||
})
|
|
||||||
|
|
||||||
//View для удаления производителя
|
|
||||||
r.DELETE("/manufacturer/:id", func(c *gin.Context) {
|
|
||||||
controllers.DeleteManufacturer(c)
|
|
||||||
})
|
|
||||||
|
|
||||||
//View получения списка всех производителей
|
|
||||||
r.GET("/manufacturer", func(c *gin.Context) {
|
|
||||||
controllers.GetManufacturers(c)
|
|
||||||
})
|
|
||||||
|
|
||||||
//View для редактирования производителя
|
|
||||||
r.PATCH("/manufacturer/:id", func(c *gin.Context) {
|
|
||||||
var manufacturer types.ManufacturerPatchRequest
|
|
||||||
|
|
||||||
if err := c.ShouldBind(&manufacturer); err != nil {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
||||||
}
|
|
||||||
|
|
||||||
controllers.EditManufacture(c, manufacturer)
|
|
||||||
})
|
|
||||||
|
|
||||||
//View для создания пользователя
|
|
||||||
r.POST("/registration", func(c *gin.Context) {
|
|
||||||
var form types.RegisterRequest
|
|
||||||
if err := c.ShouldBind(&form); err != nil {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
controllers.RegisterUser(c, form)
|
|
||||||
})
|
|
||||||
|
|
||||||
//View для аутентификации пользователя
|
|
||||||
r.POST("/login", func(c *gin.Context) {
|
|
||||||
var register types.LoginRequest
|
|
||||||
if err := c.ShouldBind(®ister); err != nil {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
controllers.LoginUser(c, register)
|
|
||||||
})
|
|
||||||
//View для получения пользователя
|
|
||||||
r.GET("/user", func(c *gin.Context) {
|
|
||||||
var user database.User
|
|
||||||
if err := c.ShouldBind(&user); err != nil {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
controllers.GetUser(c)
|
|
||||||
})
|
|
||||||
|
|
||||||
//View для редактированя пользователя
|
|
||||||
r.PATCH("/user", func(c *gin.Context) {
|
|
||||||
var user types.EditUserNameRequest
|
|
||||||
if err := c.ShouldBind(&user); err != nil {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
||||||
}
|
|
||||||
controllers.EditUserName(c, user)
|
|
||||||
})
|
|
||||||
|
|
||||||
//View для покупки товара
|
|
||||||
r.GET("/product/:id/buy", func(c *gin.Context) {
|
r.GET("/product/:id/buy", func(c *gin.Context) {
|
||||||
controllers.BuyProduct(c)
|
controllers.BuyProduct(c)
|
||||||
})
|
})
|
||||||
|
|
||||||
//View для просмотра купленных товаров
|
|
||||||
|
r.POST("/manufacturer", func(c *gin.Context) {
|
||||||
|
var manufacturer database.Manufacturer
|
||||||
|
if err := c.ShouldBind(&manufacturer); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
controllers.CreateManufacturer(c, manufacturer)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
r.DELETE("/manufacturer/:id", func(c *gin.Context) {
|
||||||
|
controllers.DeleteManufacturer(c)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
r.GET("/manufacturer", func(c *gin.Context) {
|
||||||
|
controllers.GetManufacturers(c)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
r.PATCH("/manufacturer/:id", func(c *gin.Context) {
|
||||||
|
var manufacturer types.ManufacturerPatchRequest
|
||||||
|
if err := c.ShouldBind(&manufacturer); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
controllers.EditManufacture(c, manufacturer)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
r.POST("/registration", func(c *gin.Context) {
|
||||||
|
var form types.RegisterRequest
|
||||||
|
if err := c.ShouldBind(&form); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
controllers.RegisterUser(c, form)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
r.POST("/login", func(c *gin.Context) {
|
||||||
|
var register types.LoginRequest
|
||||||
|
if err := c.ShouldBind(®ister); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
controllers.LoginUser(c, register)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
r.GET("/user", func(c *gin.Context) {
|
||||||
|
controllers.GetUser(c)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
r.PATCH("/user", func(c *gin.Context) {
|
||||||
|
var user types.EditUserNameRequest
|
||||||
|
if err := c.ShouldBind(&user); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
controllers.EditUserName(c, user)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
r.POST("/user/addmoney", func(c *gin.Context) {
|
||||||
|
var moneyRequest types.AddMoneyRequest
|
||||||
|
if err := c.ShouldBind(&moneyRequest); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
controllers.AddMoneyToUser(c, moneyRequest)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
r.GET("/user/products", func(c *gin.Context) {
|
r.GET("/user/products", func(c *gin.Context) {
|
||||||
controllers.GetBuyedProducts(c)
|
controllers.GetBuyedProducts(c)
|
||||||
})
|
})
|
||||||
|
@ -138,3 +158,4 @@ func main() {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,3 +18,7 @@ type RegisterRequest struct {
|
||||||
type EditUserNameRequest struct {
|
type EditUserNameRequest struct {
|
||||||
Name string `validate:"required"`
|
Name string `validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AddMoneyRequest struct {
|
||||||
|
Money uint `validate:"required"`
|
||||||
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type ManufacturerResponse struct {
|
type ManufacturerResponse struct {
|
||||||
ID string
|
ID uint
|
||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,3 +49,11 @@ func NotFoundError(obj string, id interface{}) ErrorResponse {
|
||||||
type MessageResponse struct {
|
type MessageResponse struct {
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UserResponse struct {
|
||||||
|
ID uint
|
||||||
|
Name string
|
||||||
|
Email string
|
||||||
|
Money uint
|
||||||
|
Products []ProductResponse
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue