diff --git a/controllers/manufacturerController.go b/controllers/manufacturerController.go index 2eb1daa..36b0eda 100644 --- a/controllers/manufacturerController.go +++ b/controllers/manufacturerController.go @@ -1,74 +1,93 @@ package controllers import ( - "github.com/gin-gonic/gin" - "github.com/go-playground/validator/v10" "golang-test/database" "golang-test/libs" "golang-test/types" "golang-test/validators" "net/http" + + "github.com/gin-gonic/gin" + "github.com/go-playground/validator/v10" ) +// CreateManufacturer создает нового производителя в базе данных. func CreateManufacturer(c *gin.Context, manufacturer database.Manufacturer) { - db := database.Connector() - validate := validators.Validate + db := database.Connector() // Подключение к базе данных + validate := validators.Validate // Валидатор для проверки входных данных + // Валидация структуры производителя if err := validate.Struct(manufacturer); err != nil { c.JSON(http.StatusBadRequest, libs.GetValidationErrors(err.(validator.ValidationErrors))) + return } + // Добавление производителя в базу данных if err := db.Create(&manufacturer).Error; err != nil { c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()}) + return } c.JSON(http.StatusCreated, types.MessageResponse{Message: "Manufacturer created successfully"}) } +// DeleteManufacturer удаляет производителя из базы данных по ID. func DeleteManufacturer(c *gin.Context) { - db := database.Connector() + db := database.Connector() // Подключение к базе данных - id := c.Param("id") + id := c.Param("id") // Получение ID из параметров запроса var manufacturer database.Manufacturer + // Поиск производителя по ID if db.First(&manufacturer, id).Error != nil { c.JSON(http.StatusNotFound, types.NotFoundError("Manufacturer", id)) + return } + // Удаление производителя if err := db.Delete(&manufacturer, id).Error; err != nil { c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()}) + return } c.JSON(http.StatusOK, types.MessageResponse{Message: "Manufacturer deleted successfully"}) } +// GetManufacturers возвращает список всех производителей. func GetManufacturers(c *gin.Context) { - db := database.Connector() + db := database.Connector() // Подключение к базе данных var manufacturers []types.ManufacturerResponse + // Получение списка производителей if err := db.Model(&database.Manufacturer{}).Select("ID", "Name").Scan(&manufacturers).Error; err != nil { c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()}) + return } c.JSON(http.StatusOK, manufacturers) } +// EditManufacture редактирует информацию о производителе. func EditManufacture(c *gin.Context, editedManufacturer types.ManufacturerPatchRequest) { - db := database.Connector() - id := c.Param("id") + db := database.Connector() // Подключение к базе данных + id := c.Param("id") // Получение ID из параметров запроса var manufacturer database.Manufacturer - validate := validators.Validate + validate := validators.Validate // Валидатор для проверки входных данных + + // Валидация измененных данных if err := validate.Struct(editedManufacturer); err != nil { c.JSON(http.StatusBadRequest, libs.GetValidationErrors(err.(validator.ValidationErrors))) + return } + // Поиск и обновление данных производителя if db.First(&manufacturer, id).Error != nil { c.JSON(http.StatusNotFound, types.NotFoundError("Manufacturer", id)) + return } - db.First(&manufacturer, id) manufacturer.Name = editedManufacturer.Name db.Save(&manufacturer) diff --git a/controllers/productController.go b/controllers/productController.go index b2fa07c..19f9596 100644 --- a/controllers/productController.go +++ b/controllers/productController.go @@ -1,169 +1,115 @@ package controllers import ( - "github.com/gin-gonic/gin" - "github.com/go-playground/validator/v10" "golang-test/database" "golang-test/libs" "golang-test/types" "golang-test/validators" - "log" "net/http" "strconv" - //"golang-test/migrations" + + "github.com/gin-gonic/gin" + "github.com/go-playground/validator/v10" ) +// CreateProduct создает новый продукт в базе данных. func CreateProduct(c *gin.Context, product database.Product) { db := database.Connector() validate := validators.Validate - //response := types.MessageResponse{Message: "Product Created"} - var manufacturer *database.Manufacturer + // Проверка данных продукта. if err := validate.Struct(&product); err != nil { c.JSON(http.StatusBadRequest, libs.GetValidationErrors(err.(validator.ValidationErrors))) return } + // Проверка существования производителя. + var manufacturer *database.Manufacturer if err := db.First(&manufacturer, product.ManufacturerID).Error; err != nil { c.JSON(http.StatusBadRequest, types.NotFoundError("Product", product.ManufacturerID)) return } - product.Manufacturer = manufacturer - - log.Println(*product.Manufacturer) - + // Добавление продукта в базу данных. if err := db.Create(&product).Error; err != nil { c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()}) return } + // Отправка ответа о успешном создании продукта. c.JSON(http.StatusCreated, types.MessageResponse{Message: "Product created"}) } +// DeleteProduct удаляет продукт по ID. func DeleteProduct(c *gin.Context) { db := database.Connector() id := c.Param("id") var product database.Product - response := types.MessageResponse{ - Message: "Product deleted", - } - + // Проверка существования продукта перед удалением. if db.First(&product, id).Error != nil { c.JSON(http.StatusNotFound, types.NotFoundError("Product", id)) 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) { db := database.Connector() - var product []database.Product + var products []database.Product 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 { var manufacturer types.ManufacturerResponse db.First(&database.Manufacturer{}, element.ManufacturerID).Scan(&manufacturer) productResp[i].Manufacturer = manufacturer } + // Отправка списка продуктов. c.JSON(http.StatusOK, productResp) } +// GetProductInfo возвращает информацию о продукте по ID. func GetProductInfo(c *gin.Context) { 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 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")) - if err != nil { c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()}) 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)) return } - token, err := libs.GetTokenFromHeaders(c) - - if err != nil { - c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: "Invalid token. Please login"}) - return + // Добавление информации о производителе в ответ. + productResp.Manufacturer = types.ManufacturerResponse{ + Name: product.Manufacturer.Name, + ID: product.Manufacturer.ID, } - u, err := GetUserByToken(token) - if err != nil { - 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) + // Отправка информации о продукте. + c.JSON(http.StatusOK, productResp) } diff --git a/controllers/userController.go b/controllers/userController.go index 222d786..f34c53a 100644 --- a/controllers/userController.go +++ b/controllers/userController.go @@ -3,15 +3,17 @@ package controllers import ( "crypto/rand" "encoding/base64" - "github.com/gin-gonic/gin" - "github.com/go-playground/validator/v10" "golang-test/database" "golang-test/libs" "golang-test/types" "golang-test/validators" - "golang.org/x/crypto/bcrypt" "log" "net/http" + "strconv" + + "github.com/gin-gonic/gin" + "github.com/go-playground/validator/v10" + "golang.org/x/crypto/bcrypt" ) type TokenStruct struct { @@ -23,16 +25,21 @@ 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 } - 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"}) return } + // Генерация хэшированного пароля hashedPassword, err := bcrypt.GenerateFromPassword([]byte(register.Password), 12) if err != nil { log.Println(err.Error()) @@ -40,24 +47,36 @@ func RegisterUser(c *gin.Context, register types.RegisterRequest) { return } - user := database.User{ + // Создание нового пользователя + 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 } - token.Token = generateToken() - token.UserID = user.ID - user.Tokens = append(user.Tokens, 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) { var user database.User db := database.Connector() @@ -97,44 +116,34 @@ func generateToken() string { 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) { - token, err := libs.GetTokenFromHeaders(c) - + var products []types.ProductResponse + user, err := libs.GetUserFromHeaders(c) if err != nil { - c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: "Invalid token. Please login"}) - } - - u, err := GetUserByToken(token) - if err != nil { - c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: "Invalid token. Please login"}) + c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: err.Error()}) 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) { - token, err := libs.GetTokenFromHeaders(c) - if err != nil { - c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: "Invalid token. Please login"}) - } - db := database.Connector() validate := validators.Validate @@ -143,18 +152,98 @@ func EditUserName(c *gin.Context, userName types.EditUserNameRequest) { return } - u, err := GetUserByToken(token) + user, err := libs.GetUserFromHeaders(c) if err != nil { - c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: "Invalid token. Please login"}) + c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: err.Error()}) 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()}) 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) +} diff --git a/database/models.go b/database/models.go index 2292076..b858b71 100644 --- a/database/models.go +++ b/database/models.go @@ -12,7 +12,8 @@ type Product struct { Name string `validate:"required"` Price 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 { @@ -28,6 +29,6 @@ type User struct { Email string `validate:"required"` Password string `validate:"required"` Products []Product `gorm:"many2many:user_products;"` - Tokens []Token `gorm:"many2many:user_token;"` - Money uint `gorm:"default:0"` + Tokens []Token + Money uint `gorm:"default:0"` } diff --git a/docs/docs.go b/docs/docs.go new file mode 100644 index 0000000..ffca88c --- /dev/null +++ b/docs/docs.go @@ -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) +} diff --git a/docs/swagger.json b/docs/swagger.json new file mode 100644 index 0000000..792945b --- /dev/null +++ b/docs/swagger.json @@ -0,0 +1,9 @@ +{ + "swagger": "2.0", + "info": { + "title": "API для тестового задания на Golang", + "contact": {}, + "version": "1.0" + }, + "paths": {} +} \ No newline at end of file diff --git a/docs/swagger.yaml b/docs/swagger.yaml new file mode 100644 index 0000000..08de91f --- /dev/null +++ b/docs/swagger.yaml @@ -0,0 +1,6 @@ +info: + contact: {} + title: API для тестового задания на Golang + version: "1.0" +paths: {} +swagger: "2.0" diff --git a/go.mod b/go.mod index 5c02a9f..7975e61 100644 --- a/go.mod +++ b/go.mod @@ -5,17 +5,28 @@ go 1.22.3 require ( github.com/gin-gonic/gin v1.10.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/gorm v1.25.10 ) 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/loader v0.1.1 // indirect github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/iasm v0.2.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // 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/universal-translator v0.18.1 // 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/jinzhu/inflection v1.0.0 // 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/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/mailru/easyjson v0.7.6 // 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/reflect2 v1.0.2 // indirect @@ -36,10 +48,11 @@ require ( github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // 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/sys v0.20.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 + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 9989a7d..796f04c 100644 --- a/go.sum +++ b/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/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= 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/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/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/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/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/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= 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/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= 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/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.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= 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/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/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/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/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/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 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/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= 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/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= 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.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.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.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 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.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= 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/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/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.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= 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/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/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.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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/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/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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= 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 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/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-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/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM= diff --git a/golang-test/Product/Buy Product.bru b/golang-test/Product/Buy Product.bru index a4e9ace..3b201de 100644 --- a/golang-test/Product/Buy Product.bru +++ b/golang-test/Product/Buy Product.bru @@ -5,7 +5,11 @@ meta { } get { - url: {{host}} + url: {{host}}/product/4/buy body: none - auth: none + auth: bearer +} + +auth:bearer { + token: {{token}} } diff --git a/golang-test/Product/Get Product Info.bru b/golang-test/Product/Get Product Info.bru index fa4db10..d1f61db 100644 --- a/golang-test/Product/Get Product Info.bru +++ b/golang-test/Product/Get Product Info.bru @@ -5,7 +5,7 @@ meta { } get { - url: {{host}}/product/19 + url: {{host}}/product/4 body: none auth: none } diff --git a/golang-test/Test.bru b/golang-test/Test.bru new file mode 100644 index 0000000..2bb1c66 --- /dev/null +++ b/golang-test/Test.bru @@ -0,0 +1,11 @@ +meta { + name: Test + type: http + seq: 2 +} + +get { + url: {{host}}/test + body: none + auth: none +} diff --git a/golang-test/User/Add Money.bru b/golang-test/User/Add Money.bru new file mode 100644 index 0000000..bf87227 --- /dev/null +++ b/golang-test/User/Add Money.bru @@ -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 + } +} diff --git a/golang-test/User/Get User Info.bru b/golang-test/User/Get User Info.bru index 79ed40c..57fa792 100644 --- a/golang-test/User/Get User Info.bru +++ b/golang-test/User/Get User Info.bru @@ -7,9 +7,9 @@ meta { get { url: {{host}}/user body: none - auth: none + auth: bearer } -headers { - Authorization: Bearer TPqB2mHBjRkvLpH3M6kWSWVMj7O75t665g== +auth:bearer { + token: {{token}} } diff --git a/golang-test/environments/golang-test.bru b/golang-test/environments/golang-test.bru index b29ff36..24fa341 100644 --- a/golang-test/environments/golang-test.bru +++ b/golang-test/environments/golang-test.bru @@ -2,5 +2,5 @@ vars { host: http://localhost:8080 manufacturerID: 1 productID: 6 - token: TPqB2mHBjRkvLpH3M6kWSWVMj7O75t665g== + token: npG8pIdPaFSBHdM119QpZtm773KKCoVIGw== } diff --git a/libs/libs.go b/libs/libs.go index 09f55b8..29d78cc 100644 --- a/libs/libs.go +++ b/libs/libs.go @@ -2,17 +2,19 @@ package libs import ( "errors" + "golang-test/database" + "strings" + "github.com/gin-gonic/gin" "github.com/go-playground/validator/v10" - "golang-test/types" - "net/http" - "strings" ) +// ValidationErrorsType определяет тип для хранения ошибок валидации. type ValidationErrorsType struct { Errors map[string]string `json:"errors"` } +// GetValidationErrors преобразует ошибки валидации в удобный для использования формат. func GetValidationErrors(errs validator.ValidationErrors) ValidationErrorsType { errors := make(map[string]string) for _, err := range errs { @@ -22,6 +24,7 @@ func GetValidationErrors(errs validator.ValidationErrors) ValidationErrorsType { return ValidationErrorsType{Errors: errors} } +// ToSnakeCase преобразует строку из CamelCase в snake_case. func ToSnakeCase(str string) string { var result []rune for i, r := range str { @@ -33,16 +36,32 @@ func ToSnakeCase(str string) string { 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 { - return "", errors.New("Authorization required") + return user, errors.New("no Authorization header") } if len(strings.Split(c.Request.Header["Authorization"][0], " ")) < 2 { - c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: "Invalid token. Please login"}) - return "", errors.New("Authorization required") + return user, errors.New("invalid Token. Please Login") } + 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 } diff --git a/main.go b/main.go index 2b37539..f6b01fe 100644 --- a/main.go +++ b/main.go @@ -1,120 +1,140 @@ package main import ( - // "fmt" - "github.com/gin-gonic/gin" "golang-test/controllers" "golang-test/database" "golang-test/types" "log" "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() { // Создание сервера r := gin.Default() - //View для создание товара + // Добавляем Swagger UI + r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) + + + r.POST("/product", func(c *gin.Context) { var product database.Product 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) }) - //View для удаления товара + r.DELETE("/product/:id", func(c *gin.Context) { controllers.DeleteProduct(c) }) - //View для просмотра всех продуктов + r.GET("/product", func(c *gin.Context) { controllers.GetProducts(c) }) + r.GET("/product/:id", func(c *gin.Context) { 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) { 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) { controllers.GetBuyedProducts(c) }) @@ -138,3 +158,4 @@ func main() { }() } + diff --git a/types/requests.go b/types/requests.go index 15f091a..81b908b 100644 --- a/types/requests.go +++ b/types/requests.go @@ -18,3 +18,7 @@ type RegisterRequest struct { type EditUserNameRequest struct { Name string `validate:"required"` } + +type AddMoneyRequest struct { + Money uint `validate:"required"` +} diff --git a/types/responses.go b/types/responses.go index c0f6e5a..028ba6a 100644 --- a/types/responses.go +++ b/types/responses.go @@ -7,7 +7,7 @@ import ( ) type ManufacturerResponse struct { - ID string + ID uint Name string } @@ -49,3 +49,11 @@ func NotFoundError(obj string, id interface{}) ErrorResponse { type MessageResponse struct { Message string `json:"message"` } + +type UserResponse struct { + ID uint + Name string + Email string + Money uint + Products []ProductResponse +}