Code Refactoring and Added Buy Product
This commit is contained in:
parent
6790a0ba81
commit
6705d08a16
|
@ -5,120 +5,72 @@ import (
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
"golang-test/database"
|
"golang-test/database"
|
||||||
"golang-test/libs"
|
"golang-test/libs"
|
||||||
"golang-test/message"
|
|
||||||
"golang-test/types"
|
"golang-test/types"
|
||||||
"golang-test/validators"
|
"golang-test/validators"
|
||||||
"log"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
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
|
||||||
response := message.Response{Status: 200}
|
|
||||||
|
|
||||||
if err := validate.Struct(manufacturer); err != nil {
|
if err := validate.Struct(manufacturer); err != nil {
|
||||||
response.Error = libs.GetValidationErrors(err.(validator.ValidationErrors))
|
c.JSON(http.StatusBadRequest, libs.GetValidationErrors(err.(validator.ValidationErrors)))
|
||||||
response.Status = 400
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := db.Create(&manufacturer).Error; err != nil {
|
if err := db.Create(&manufacturer).Error; err != nil {
|
||||||
log.Println(err.Error())
|
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()})
|
||||||
response.Error = gin.H{
|
|
||||||
"error": err.Error(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
response.Status = 500
|
c.JSON(http.StatusCreated, types.MessageResponse{Message: "Manufacturer created successfully"})
|
||||||
message.SendResponse(c, response)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.Message = gin.H{
|
|
||||||
"message": "Manufacturer created",
|
|
||||||
}
|
|
||||||
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteManufacturer(c *gin.Context) {
|
func DeleteManufacturer(c *gin.Context) {
|
||||||
db := database.Connector()
|
db := database.Connector()
|
||||||
response := message.Response{Status: 200}
|
|
||||||
|
|
||||||
id := c.Param("id")
|
id := c.Param("id")
|
||||||
|
|
||||||
var manufacturer database.Manufacturer
|
var manufacturer database.Manufacturer
|
||||||
|
|
||||||
if db.First(&manufacturer, id).Error != nil {
|
if db.First(&manufacturer, id).Error != nil {
|
||||||
response.Error = gin.H{
|
c.JSON(http.StatusNotFound, types.NotFoundError("Manufacturer", id))
|
||||||
"error": "Manufacturer with id '" + id + "' not found",
|
|
||||||
}
|
|
||||||
response.Status = 404
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
db.Delete(&manufacturer, id)
|
if err := db.Delete(&manufacturer, id).Error; err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()})
|
||||||
response.Message = gin.H{
|
|
||||||
"message": "Manufacturer deleted",
|
|
||||||
}
|
}
|
||||||
message.SendResponse(c, response)
|
|
||||||
|
c.JSON(http.StatusOK, types.MessageResponse{Message: "Manufacturer deleted successfully"})
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetManufacturers(c *gin.Context) {
|
func GetManufacturers(c *gin.Context) {
|
||||||
|
|
||||||
type ManufacturerResponse struct {
|
|
||||||
ID uint
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
db := database.Connector()
|
db := database.Connector()
|
||||||
response := message.Response{Status: 200}
|
var manufacturers []types.ManufacturerResponse
|
||||||
var manufacturers []ManufacturerResponse
|
|
||||||
|
|
||||||
db.Model(&database.Manufacturer{}).Select("ID", "Name").Scan(&manufacturers)
|
if err := db.Model(&database.Manufacturer{}).Select("ID", "Name").Scan(&manufacturers).Error; err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()})
|
||||||
response.Message = gin.H{
|
|
||||||
"manufacturers": manufacturers,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message.SendResponse(c, response)
|
c.JSON(http.StatusOK, manufacturers)
|
||||||
}
|
}
|
||||||
|
|
||||||
func EditManufacture(c *gin.Context, editedManufacturer types.ManufacturerPatchRequest) {
|
func EditManufacture(c *gin.Context, editedManufacturer types.ManufacturerPatchRequest) {
|
||||||
db := database.Connector()
|
db := database.Connector()
|
||||||
response := message.Response{Status: 200}
|
|
||||||
id := c.Param("id")
|
id := c.Param("id")
|
||||||
|
|
||||||
validate := validators.Validate
|
|
||||||
err := validate.Struct(editedManufacturer)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
response.Error = libs.GetValidationErrors(err.(validator.ValidationErrors))
|
|
||||||
response.Status = 400
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var manufacturer database.Manufacturer
|
var manufacturer database.Manufacturer
|
||||||
|
|
||||||
if db.First(&manufacturer, id).Error != nil {
|
validate := validators.Validate
|
||||||
response.Error = gin.H{
|
if err := validate.Struct(editedManufacturer); err != nil {
|
||||||
"error": "Manufacturer with id '" + id + "' not found",
|
c.JSON(http.StatusBadRequest, libs.GetValidationErrors(err.(validator.ValidationErrors)))
|
||||||
}
|
}
|
||||||
response.Status = 404
|
|
||||||
message.SendResponse(c, response)
|
if db.First(&manufacturer, id).Error != nil {
|
||||||
return
|
c.JSON(http.StatusNotFound, types.NotFoundError("Manufacturer", id))
|
||||||
}
|
}
|
||||||
|
|
||||||
db.First(&manufacturer, id)
|
db.First(&manufacturer, id)
|
||||||
manufacturer.Name = editedManufacturer.Name
|
manufacturer.Name = editedManufacturer.Name
|
||||||
db.Save(&manufacturer)
|
db.Save(&manufacturer)
|
||||||
|
|
||||||
response.Message = gin.H{
|
c.JSON(http.StatusOK, types.MessageResponse{Message: "Manufacturer edited successfully"})
|
||||||
"message": "Manufacturer edited",
|
|
||||||
}
|
|
||||||
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,10 @@ import (
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
"golang-test/database"
|
"golang-test/database"
|
||||||
"golang-test/libs"
|
"golang-test/libs"
|
||||||
"golang-test/message"
|
"golang-test/types"
|
||||||
"golang-test/validators"
|
"golang-test/validators"
|
||||||
"log"
|
"log"
|
||||||
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
//"golang-test/migrations"
|
//"golang-test/migrations"
|
||||||
)
|
)
|
||||||
|
@ -15,120 +16,154 @@ import (
|
||||||
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 := message.Response{Status: 200}
|
//response := types.MessageResponse{Message: "Product Created"}
|
||||||
|
var manufacturer *database.Manufacturer
|
||||||
|
|
||||||
err := validate.Struct(product)
|
if err := validate.Struct(&product); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, libs.GetValidationErrors(err.(validator.ValidationErrors)))
|
||||||
if err != nil {
|
|
||||||
response.Error = libs.GetValidationErrors(err.(validator.ValidationErrors))
|
|
||||||
response.Status = 400
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := db.First(&database.Manufacturer{}, product.ManufacturerID).Error; err != nil {
|
if err := db.First(&manufacturer, product.ManufacturerID).Error; err != nil {
|
||||||
response.Error = gin.H{
|
c.JSON(http.StatusBadRequest, types.NotFoundError("Product", product.ManufacturerID))
|
||||||
"error": "Manufacturer with id '" + strconv.Itoa(int(product.ManufacturerID)) + "' not found",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = db.Create(&product).Error
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err.Error())
|
|
||||||
response.Error = gin.H{
|
|
||||||
"error": err.Error(),
|
|
||||||
}
|
|
||||||
|
|
||||||
response.Status = 500
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
response.Message = gin.H{
|
product.Manufacturer = manufacturer
|
||||||
"message": "Product created",
|
|
||||||
|
log.Println(*product.Manufacturer)
|
||||||
|
|
||||||
|
if err := db.Create(&product).Error; err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
message.SendResponse(c, response)
|
c.JSON(http.StatusCreated, types.MessageResponse{Message: "Product created"})
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteProduct(c *gin.Context) {
|
func DeleteProduct(c *gin.Context) {
|
||||||
db := database.Connector()
|
db := database.Connector()
|
||||||
response := message.Response{Status: 200}
|
|
||||||
id := c.Param("id")
|
id := c.Param("id")
|
||||||
|
|
||||||
var product database.Product
|
var product database.Product
|
||||||
|
|
||||||
if db.First(&product, id).Error != nil {
|
response := types.MessageResponse{
|
||||||
response.Error = gin.H{
|
Message: "Product deleted",
|
||||||
"error": "Product with id '" + id + "' not found",
|
|
||||||
}
|
}
|
||||||
response.Status = 404
|
|
||||||
message.SendResponse(c, response)
|
if db.First(&product, id).Error != nil {
|
||||||
|
c.JSON(http.StatusNotFound, types.NotFoundError("Product", id))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
db.Delete(&product, id)
|
db.Delete(&product, id)
|
||||||
|
|
||||||
response.Message = gin.H{
|
c.JSON(http.StatusOK, response)
|
||||||
"message": "Product deleted",
|
|
||||||
}
|
|
||||||
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//func GetProducts(c *gin.Context) {
|
func GetProducts(c *gin.Context) {
|
||||||
//
|
db := database.Connector()
|
||||||
// db := database.Connector()
|
var product []database.Product
|
||||||
// response := message.Response{Status: 200}
|
var productResp []types.ProductResponse
|
||||||
// var product []database.Product
|
|
||||||
//
|
db.Find(&product).Scan(&productResp)
|
||||||
// resp := []interface{}{}
|
|
||||||
//
|
for i, element := range productResp {
|
||||||
// db.Find(&product)
|
var manufacturer types.ManufacturerResponse
|
||||||
//
|
db.First(&database.Manufacturer{}, element.ManufacturerID).Scan(&manufacturer)
|
||||||
// for _, productItem := range product {
|
productResp[i].Manufacturer = manufacturer
|
||||||
// resp = append(resp, gin.H{
|
}
|
||||||
// "id": productItem.ID,
|
|
||||||
// "name": productItem.Name,
|
c.JSON(http.StatusOK, productResp)
|
||||||
// "price": productItem.Price,
|
}
|
||||||
// "manufacturer_ID": productItem.Manufacturer.ID,
|
|
||||||
// "manufacturer_Name": productItem.Manufacturer.Name,
|
|
||||||
// })
|
|
||||||
// log.Println(productItem.Manufacturer.Name)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// response.Message = gin.H{
|
|
||||||
// "products": resp,
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// message.SendResponse(c, response)
|
|
||||||
//}
|
|
||||||
|
|
||||||
func GetProductInfo(c *gin.Context) {
|
func GetProductInfo(c *gin.Context) {
|
||||||
db := database.Connector()
|
db := database.Connector()
|
||||||
response := message.Response{Status: 200}
|
id, err := strconv.Atoi(c.Param("id"))
|
||||||
id := c.Param("id")
|
|
||||||
|
|
||||||
var product database.Product
|
if err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: err.Error()})
|
||||||
if err := db.First(&product, id).Error; err != nil {
|
|
||||||
response.Error = gin.H{
|
|
||||||
"error": "Product with id '" + id + "' not found",
|
|
||||||
}
|
}
|
||||||
response.Status = 404
|
|
||||||
message.SendResponse(c, response)
|
//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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
response.Message = gin.H{
|
if err := db.First(&product.Manufacturer, product.ManufacturerID).Scan(&manufacturer).Error; err != nil {
|
||||||
"product": gin.H{
|
c.JSON(http.StatusBadRequest, types.NotFoundError("Product", product.ManufacturerID))
|
||||||
"id": product.ID,
|
return
|
||||||
"name": product.Name,
|
|
||||||
"price": product.Price,
|
|
||||||
"manufacturer_ID": product.ManufacturerID,
|
|
||||||
"manufacturer_Name": product.Manufacturer.Name,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
// Пример генератора токена
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
@ -9,93 +7,47 @@ import (
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
"golang-test/database"
|
"golang-test/database"
|
||||||
"golang-test/libs"
|
"golang-test/libs"
|
||||||
"golang-test/message"
|
|
||||||
"golang-test/types"
|
"golang-test/types"
|
||||||
"golang-test/validators"
|
"golang-test/validators"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
"strings"
|
"log"
|
||||||
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
//func tokenGenerator() string {
|
|
||||||
// b := make([]byte, 4)
|
|
||||||
// rand.Read(b)
|
|
||||||
// return fmt.Sprintf("%x", b)
|
|
||||||
//}
|
|
||||||
|
|
||||||
// func main() {
|
|
||||||
// a := tokenGenerator()
|
|
||||||
// fmt.Println(a)
|
|
||||||
// }
|
|
||||||
|
|
||||||
type TokenStruct struct {
|
type TokenStruct struct {
|
||||||
UserID uint
|
UserID uint
|
||||||
token string
|
token string
|
||||||
}
|
}
|
||||||
|
|
||||||
//func RegisterUser(c *gin.Context, user database.User) {
|
func RegisterUser(c *gin.Context, register types.RegisterRequest) {
|
||||||
// db := database.Connector()
|
|
||||||
// validate := validators.Validate
|
|
||||||
// response := message.Response{Status: 200}
|
|
||||||
// if err := validate.Struct(user); err != nil {
|
|
||||||
// response.Error = libs.GetValidationErrors(err.(validator.ValidationErrors))
|
|
||||||
// response.Status = 400
|
|
||||||
// message.SendResponse(c, response)
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// hash, err := bcrypt.GenerateFromPassword([]byte(user.Password), 12)
|
|
||||||
// if err != nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// user.Password = string(hash)
|
|
||||||
// if err := db.Create(user).Error; err != nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
|
|
||||||
func RegisterUser(c *gin.Context, register database.User) {
|
|
||||||
var user database.User
|
|
||||||
db := database.Connector()
|
db := database.Connector()
|
||||||
validate := validators.Validate
|
validate := validators.Validate
|
||||||
response := message.Response{Status: 201}
|
var token database.Token
|
||||||
var token *database.Token
|
|
||||||
|
|
||||||
if err := validate.Struct(register); err != nil {
|
if err := validate.Struct(register); err != nil {
|
||||||
response.Error = libs.GetValidationErrors(err.(validator.ValidationErrors))
|
c.JSON(http.StatusBadRequest, libs.GetValidationErrors(err.(validator.ValidationErrors)))
|
||||||
response.Status = 400
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := db.Where("email =?", register.Email).First(&user).Error; err == nil {
|
if err := db.Where("email =?", register.Email).Error; err == nil {
|
||||||
response.Status = 400
|
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: "User already exists"})
|
||||||
response.Error = gin.H{
|
|
||||||
"error": "User already exists",
|
|
||||||
}
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(register.Password), 12)
|
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(register.Password), 12)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Status = 500
|
log.Println(err.Error())
|
||||||
response.Error = gin.H{
|
c.JSON(http.StatusInternalServerError, types.ErrorResponse{Message: err.Error()})
|
||||||
"error": "Internal Server Error",
|
|
||||||
}
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
user.Email = register.Email
|
user := database.User{
|
||||||
user.Password = string(hashedPassword)
|
Name: register.Name,
|
||||||
user.Name = register.Name
|
Email: register.Email,
|
||||||
|
Password: string(hashedPassword),
|
||||||
|
}
|
||||||
|
|
||||||
if err := db.Create(&user).Error; err != nil {
|
if err := db.Create(&user).Error; err != nil {
|
||||||
response.Status = 500
|
c.JSON(http.StatusInternalServerError, types.ErrorResponse{Message: err.Error()})
|
||||||
response.Error = gin.H{
|
|
||||||
"error": "Internal Server Error",
|
|
||||||
}
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,53 +55,42 @@ func RegisterUser(c *gin.Context, register database.User) {
|
||||||
token.UserID = user.ID
|
token.UserID = user.ID
|
||||||
user.Tokens = append(user.Tokens, token)
|
user.Tokens = append(user.Tokens, token)
|
||||||
|
|
||||||
response.Message = gin.H{
|
c.JSON(http.StatusCreated, types.TokenResponse{Token: token.Token})
|
||||||
"message": "Registration Success",
|
|
||||||
}
|
|
||||||
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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()
|
||||||
validate := validators.Validate
|
validate := validators.Validate
|
||||||
response := message.Response{Status: 200}
|
var token database.Token
|
||||||
var token *database.Token
|
|
||||||
|
|
||||||
if err := validate.Struct(login); err != nil {
|
if err := validate.Struct(login); err != nil {
|
||||||
response.Error = libs.GetValidationErrors(err.(validator.ValidationErrors))
|
c.JSON(http.StatusBadRequest, libs.GetValidationErrors(err.(validator.ValidationErrors)))
|
||||||
response.Status = 400
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := db.Where("email = ?", login.Email).First(&user).Error; err != nil {
|
if err := db.Where("email = ?", login.Email).First(&user).Error; err != nil {
|
||||||
response.Status = 404
|
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: "Invalid email or password"})
|
||||||
response.Error = gin.H{
|
return
|
||||||
"error": "User not found",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(login.Password)); err != nil {
|
if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(login.Password)); err != nil {
|
||||||
response.Status = 404
|
c.JSON(http.StatusBadRequest, types.ErrorResponse{Message: "Invalid email or password"})
|
||||||
response.Error = gin.H{
|
return
|
||||||
"error": "User not found",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
token.Token = generateToken()
|
token.Token = generateToken()
|
||||||
token.UserID = user.ID
|
token.UserID = user.ID
|
||||||
|
|
||||||
user.Tokens = append(user.Tokens, token)
|
user.Tokens = append(user.Tokens, token)
|
||||||
|
|
||||||
response.Message = gin.H{
|
db.Save(&user)
|
||||||
"message": "Login Success",
|
|
||||||
}
|
|
||||||
|
|
||||||
message.SendResponse(c, response)
|
c.JSON(http.StatusOK, types.TokenResponse{Token: token.Token})
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateToken() string {
|
func generateToken() string {
|
||||||
b := make([]byte, 4)
|
b := make([]byte, 25)
|
||||||
if _, err := rand.Read(b); err != nil {
|
if _, err := rand.Read(b); err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -157,7 +98,7 @@ func generateToken() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetUserByToken(token string) (database.User, error) {
|
func GetUserByToken(token string) (database.User, error) {
|
||||||
var tokenObject TokenStruct
|
var tokenObject database.Token
|
||||||
var err error
|
var err error
|
||||||
var user database.User
|
var user database.User
|
||||||
|
|
||||||
|
@ -165,115 +106,55 @@ func GetUserByToken(token string) (database.User, error) {
|
||||||
if err := db.Where("token = ?", token).First(&tokenObject).Error; err != nil {
|
if err := db.Where("token = ?", token).First(&tokenObject).Error; err != nil {
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := db.First(&user, tokenObject.UserID).Error; err != nil {
|
if err := db.First(&user, tokenObject.UserID).Error; err != nil {
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetUser(c *gin.Context, user database.User) {
|
func GetUser(c *gin.Context) {
|
||||||
token := strings.Split(c.Request.Header["Bearer"][0], " ")[1]
|
token, err := libs.GetTokenFromHeaders(c)
|
||||||
validate := validators.Validate
|
|
||||||
response := message.Response{Status: 200}
|
if err != nil {
|
||||||
|
c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: "Invalid token. Please login"})
|
||||||
|
}
|
||||||
|
|
||||||
u, err := GetUserByToken(token)
|
u, err := GetUserByToken(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Status = 401
|
c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: "Invalid token. Please login"})
|
||||||
response.Error = gin.H{
|
|
||||||
"error": "Token is invalid, please login",
|
|
||||||
}
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := validate.Struct(user); err != nil {
|
c.JSON(http.StatusOK, u)
|
||||||
response.Error = libs.GetValidationErrors(err.(validator.ValidationErrors))
|
|
||||||
response.Status = 400
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.Message = gin.H{
|
|
||||||
"message": "User data successfully received",
|
|
||||||
"user": u,
|
|
||||||
}
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func EditUser(c *gin.Context, user database.User) {
|
func EditUserName(c *gin.Context, userName types.EditUserNameRequest) {
|
||||||
token := strings.Split(c.Request.Header["Bearer"][0], " ")[1]
|
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
|
||||||
response := message.Response{Status: 200}
|
|
||||||
|
if err := validate.Struct(userName); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, libs.GetValidationErrors(err.(validator.ValidationErrors)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
u, err := GetUserByToken(token)
|
u, err := GetUserByToken(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Status = 401
|
c.JSON(http.StatusUnauthorized, types.ErrorResponse{Message: "Invalid token. Please login"})
|
||||||
response.Error = gin.H{
|
|
||||||
"error": "Token is invalid, please login",
|
|
||||||
}
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := validate.Struct(user); err != nil {
|
u.Name = userName.Name
|
||||||
response.Error = libs.GetValidationErrors(err.(validator.ValidationErrors))
|
|
||||||
response.Status = 400
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
hash, err := bcrypt.GenerateFromPassword([]byte(user.Password), 12)
|
|
||||||
if err != nil {
|
|
||||||
response.Status = 500
|
|
||||||
response.Error = gin.H{
|
|
||||||
"error": err,
|
|
||||||
}
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
u.Password = string(hash)
|
|
||||||
|
|
||||||
if err := db.Save(u).Error; err != nil {
|
if err := db.Save(u).Error; err != nil {
|
||||||
response.Status = 500
|
c.JSON(http.StatusInternalServerError, types.ErrorResponse{Message: err.Error()})
|
||||||
response.Error = gin.H{
|
|
||||||
"error": err,
|
|
||||||
}
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
response.Message = gin.H{
|
c.JSON(http.StatusOK, types.MessageResponse{Message: "User name successfully updated"})
|
||||||
"message": "User successfully updated",
|
|
||||||
}
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteUser(c *gin.Context) {
|
|
||||||
token := strings.Split(c.Request.Header["Bearer"][0], " ")[1]
|
|
||||||
db := database.Connector()
|
|
||||||
u, err := GetUserByToken(token)
|
|
||||||
response := message.Response{Status: 200}
|
|
||||||
if err != nil {
|
|
||||||
response.Status = 401
|
|
||||||
response.Error = gin.H{
|
|
||||||
"error": "Token is invalid, please login",
|
|
||||||
}
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := db.Delete(u).Error; err != nil {
|
|
||||||
response.Status = 500
|
|
||||||
response.Error = gin.H{
|
|
||||||
"error": err,
|
|
||||||
}
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response.Message = gin.H{
|
|
||||||
"message": "User successfully deleted",
|
|
||||||
}
|
|
||||||
message.SendResponse(c, response)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ type User struct {
|
||||||
Name string `validate:"required"`
|
Name string `validate:"required"`
|
||||||
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 `gorm:"many2many:user_token;"`
|
||||||
|
Money uint `gorm:"default:0"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,6 @@ post {
|
||||||
|
|
||||||
body:json {
|
body:json {
|
||||||
{
|
{
|
||||||
"name": "Тест 1"
|
"name": "Тест 123"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ meta {
|
||||||
}
|
}
|
||||||
|
|
||||||
delete {
|
delete {
|
||||||
url: {{host}}/manufacturer/{{manufacturerID}}
|
url: {{host}}/manufacturer/6
|
||||||
body: none
|
body: none
|
||||||
auth: none
|
auth: none
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,13 @@ meta {
|
||||||
}
|
}
|
||||||
|
|
||||||
patch {
|
patch {
|
||||||
url: {{host}}/manufacturer/{{manufacturerID}}
|
url: {{host}}/manufacturer/5
|
||||||
body: json
|
body: json
|
||||||
auth: none
|
auth: none
|
||||||
}
|
}
|
||||||
|
|
||||||
body:json {
|
body:json {
|
||||||
{
|
{
|
||||||
"name": "Test3"
|
"name": "Sdsad"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ meta {
|
||||||
}
|
}
|
||||||
|
|
||||||
get {
|
get {
|
||||||
url:
|
url: {{host}}/product/19
|
||||||
body: none
|
body: none
|
||||||
auth: none
|
auth: none
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,20 +4,12 @@ meta {
|
||||||
seq: 3
|
seq: 3
|
||||||
}
|
}
|
||||||
|
|
||||||
post {
|
get {
|
||||||
url: {{host}}/product
|
url: {{host}}/product
|
||||||
body: json
|
body: json
|
||||||
auth: none
|
auth: none
|
||||||
}
|
}
|
||||||
|
|
||||||
body:json {
|
|
||||||
{
|
|
||||||
"name": "Яблоко",
|
|
||||||
"price": 5,
|
|
||||||
"manufacturerID": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body:multipart-form {
|
body:multipart-form {
|
||||||
name: Яблоко
|
name: Яблоко
|
||||||
price: 5
|
price: 5
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
vars {
|
vars {
|
||||||
host: http://localhost:8080
|
host: http://localhost:8080
|
||||||
manufacturerID: 1
|
manufacturerID: 1
|
||||||
productID: 2
|
productID: 6
|
||||||
|
token: TPqB2mHBjRkvLpH3M6kWSWVMj7O75t665g==
|
||||||
}
|
}
|
||||||
|
|
29
libs/libs.go
29
libs/libs.go
|
@ -1,20 +1,25 @@
|
||||||
package libs
|
package libs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"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"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetValidationErrors(errs validator.ValidationErrors) gin.H {
|
type ValidationErrorsType struct {
|
||||||
errors := make(map[string]any)
|
Errors map[string]string `json:"errors"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetValidationErrors(errs validator.ValidationErrors) ValidationErrorsType {
|
||||||
|
errors := make(map[string]string)
|
||||||
for _, err := range errs {
|
for _, err := range errs {
|
||||||
errors[err.Field()] = err.Error()
|
errors[err.Field()] = err.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
return gin.H{
|
return ValidationErrorsType{Errors: errors}
|
||||||
"error": errors,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ToSnakeCase(str string) string {
|
func ToSnakeCase(str string) string {
|
||||||
|
@ -27,3 +32,17 @@ func ToSnakeCase(str string) string {
|
||||||
}
|
}
|
||||||
return strings.ToLower(string(result))
|
return strings.ToLower(string(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetTokenFromHeaders(c *gin.Context) (string, error) {
|
||||||
|
if c.Request.Header["Authorization"] == nil {
|
||||||
|
return "", errors.New("Authorization required")
|
||||||
|
}
|
||||||
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
token := strings.Split(c.Request.Header["Authorization"][0], " ")[1]
|
||||||
|
|
||||||
|
return token, nil
|
||||||
|
}
|
||||||
|
|
28
main.go
28
main.go
|
@ -72,9 +72,10 @@ func main() {
|
||||||
|
|
||||||
//View для создания пользователя
|
//View для создания пользователя
|
||||||
r.POST("/registration", func(c *gin.Context) {
|
r.POST("/registration", func(c *gin.Context) {
|
||||||
var form database.User
|
var form types.RegisterRequest
|
||||||
if err := c.ShouldBind(&form); err != nil {
|
if err := c.ShouldBind(&form); err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
controllers.RegisterUser(c, form)
|
controllers.RegisterUser(c, form)
|
||||||
|
@ -85,6 +86,7 @@ func main() {
|
||||||
var register types.LoginRequest
|
var register types.LoginRequest
|
||||||
if err := c.ShouldBind(®ister); err != nil {
|
if err := c.ShouldBind(®ister); err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
controllers.LoginUser(c, register)
|
controllers.LoginUser(c, register)
|
||||||
})
|
})
|
||||||
|
@ -93,26 +95,28 @@ func main() {
|
||||||
var user database.User
|
var user database.User
|
||||||
if err := c.ShouldBind(&user); err != nil {
|
if err := c.ShouldBind(&user); err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
controllers.LoginUser(c, user)
|
controllers.GetUser(c)
|
||||||
})
|
})
|
||||||
|
|
||||||
//View для редактированя пользователя
|
//View для редактированя пользователя
|
||||||
r.PATCH("/user/edit", func(c *gin.Context) {
|
r.PATCH("/user", func(c *gin.Context) {
|
||||||
var user database.User
|
var user types.EditUserNameRequest
|
||||||
if err := c.ShouldBind(&user); err != nil {
|
if err := c.ShouldBind(&user); err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||||
}
|
}
|
||||||
controllers.EditUser(c, user)
|
controllers.EditUserName(c, user)
|
||||||
})
|
})
|
||||||
|
|
||||||
//View для удаления пользователя
|
//View для покупки товара
|
||||||
r.DELETE("/user/delete", func(c *gin.Context) {
|
r.GET("/product/:id/buy", func(c *gin.Context) {
|
||||||
var form types.LoginRequest
|
controllers.BuyProduct(c)
|
||||||
if err := c.ShouldBind(&form); err != nil {
|
})
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
||||||
}
|
//View для просмотра купленных товаров
|
||||||
controllers.DeleteUser(c)
|
r.GET("/user/products", func(c *gin.Context) {
|
||||||
|
controllers.GetBuyedProducts(c)
|
||||||
})
|
})
|
||||||
|
|
||||||
err := r.Run()
|
err := r.Run()
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
package message
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Response struct {
|
|
||||||
Status int
|
|
||||||
Message gin.H
|
|
||||||
Error gin.H
|
|
||||||
}
|
|
||||||
|
|
||||||
func SendResponse(c *gin.Context, response Response) {
|
|
||||||
if len(response.Message) > 0 {
|
|
||||||
c.JSON(response.Status, response.Message)
|
|
||||||
} else if len(response.Error) > 0 {
|
|
||||||
c.JSON(response.Status, response.Error)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
type ManufacturerPatchRequest struct {
|
||||||
|
Name string `validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoginRequest struct {
|
||||||
|
Email string `validate:"required,email"`
|
||||||
|
Password string `validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RegisterRequest struct {
|
||||||
|
Name string `validate:"required"`
|
||||||
|
Email string `validate:"required,email"`
|
||||||
|
Password string `validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type EditUserNameRequest struct {
|
||||||
|
Name string `validate:"required"`
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/go-playground/validator/v10"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ManufacturerResponse struct {
|
||||||
|
ID string
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProductResponse struct {
|
||||||
|
ID uint
|
||||||
|
Name string
|
||||||
|
Price uint
|
||||||
|
ManufacturerID uint
|
||||||
|
Manufacturer ManufacturerResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
type TokenResponse struct {
|
||||||
|
Token string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ErrorResponse struct {
|
||||||
|
Message string `json:"error"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ValidationErrorResponse struct {
|
||||||
|
Errors validator.ValidationErrors `json:"error"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NotFoundError(obj string, id interface{}) ErrorResponse {
|
||||||
|
var idStr string
|
||||||
|
switch reflect.TypeOf(id).Kind() {
|
||||||
|
case reflect.String:
|
||||||
|
idStr = id.(string)
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
idStr = strconv.FormatInt(reflect.ValueOf(id).Int(), 10)
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
|
idStr = strconv.FormatUint(reflect.ValueOf(id).Uint(), 10)
|
||||||
|
default:
|
||||||
|
idStr = ""
|
||||||
|
}
|
||||||
|
return ErrorResponse{Message: obj + " with id " + idStr + " not found"}
|
||||||
|
}
|
||||||
|
|
||||||
|
type MessageResponse struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
|
@ -1,10 +0,0 @@
|
||||||
package types
|
|
||||||
|
|
||||||
type ManufacturerPatchRequest struct {
|
|
||||||
Name string `validate:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type LoginRequest struct {
|
|
||||||
Email string `validate:"required,email"`
|
|
||||||
Password string `validate:"required"`
|
|
||||||
}
|
|
Loading…
Reference in New Issue