backend/api/ajoutProduit.go

Summary

Maintainability
A
1 hr
Test Coverage
package api

import (
    "bar/autogen"
    "bar/internal/models"
    "bar/internal/storage"
    "encoding/base64"
    "net/http"
    "strings"

    "github.com/google/uuid"
    "github.com/labstack/echo/v4"
    "github.com/sirupsen/logrus"
    "go.mongodb.org/mongo-driver/mongo"
)

func PostItem403(c echo.Context, message string) error {
    r := autogen.PostItem403JSONResponse{
        ErrorCode: autogen.ErrForbidden,
        Message:   autogen.Messages(message),
    }
    return r.VisitPostItemResponse(c.Response())
}
func PostItem400(c echo.Context, message string) error {
    r := autogen.PostItem400JSONResponse{
        ErrorCode: autogen.ErrBadRequest,
        Message:   autogen.Messages(message),
    }
    return r.VisitPostItemResponse(c.Response())
}

func PostItem500(c echo.Context, message string) error {
    r := autogen.PostItem500JSONResponse{
        ErrorCode: autogen.ErrInternalServerError,
        Message:   autogen.Messages(message),
    }
    return r.VisitPostItemResponse(c.Response())
}

// (POST /categories/{category_id}/items)
func (s *Server) PostItem(c echo.Context, categoryId autogen.UUID) error {
    usr, err := MustGetUser(c)
    if err != nil {
        return nil
    }

    // Make sure the correct people have access
    switch usr.Role {
    default:
        return PostItem403(c, "You are not allowed to do this")
    case autogen.AccountMember:
    case autogen.AccountAdmin:
    case autogen.AccountSuperAdmin:
    }

    var p autogen.NewItem
    if err := c.Bind(&p); err != nil {
        logrus.Error(err)
        return PostItem400(c, "Incomprehensible body")
    }

    isMenu := false
    if p.IsMenu != nil {
        isMenu = *p.IsMenu
    }

    if !isMenu && p.MenuItems != nil && len(*p.MenuItems) > 0 {
        isMenu = true
        p.IsMenu = &isMenu
    }

    if isMenu {
        // Verify that the menu is correct
        if (p.MenuItems == nil || len(*p.MenuItems) == 0) && (p.MenuCategories == nil || len(*p.MenuCategories) == 0) {
            return PostItem400(c, "Menu must contain at least one item / category")
        }

        // Verify that all items exists
        for i, menuItem := range *p.MenuItems {
            item, err := s.DBackend.GetItem(c.Request().Context(), menuItem.Id.String())
            if err != nil {
                if err == mongo.ErrNoDocuments {
                    return PostItem400(c, "Item in menu does not exist")
                }
                logrus.Error(err)
                return PostItem500(c, "Unknown error while verifying menu")
            }
            if item.IsMenu {
                return PostItem400(c, "Menu cannot contain other menus")
            }
            menuItem.Name = item.Name
            menuItem.PictureUri = item.PictureUri
            (*p.MenuItems)[i] = menuItem
        }

        // Verify that all categories exists
        for i, menuCategory := range *p.MenuCategories {
            cat, err := s.DBackend.GetCategory(c.Request().Context(), menuCategory.Id.String())
            if err != nil {
                if err == mongo.ErrNoDocuments {
                    return PostItem400(c, "Category in menu does not exist")
                }
                logrus.Error(err)
                return PostItem500(c, "Unknown error while verifying menu")
            }
            menuCategory.Name = cat.Name
            menuCategory.PictureUri = cat.PictureUri
            (*p.MenuCategories)[i] = menuCategory
        }
    }

    d, err := base64.StdEncoding.DecodeString(p.Picture)
    if err != nil {
        logrus.Error(err)
        return PostItem400(c, "Could not decode picture")
    }

    // Check MIME type
    if !strings.Contains(http.DetectContentType(d), "image") {
        logrus.Error(err)
        return PostItem400(c, "Picture is not an image")
    }

    uid := uuid.New()

    // Save image to storage
    err = storage.SaveFile("items/"+uid.String(), d)
    if err != nil {
        logrus.Error(err)
        return PostItem500(c, "Could not save picture")
    }

    item := &models.Item{
        Item: autogen.Item{
            Id:              uid,
            CategoryId:      categoryId,
            Name:            p.Name,
            Prices:          p.Prices,
            PictureUri:      "/categories/" + categoryId.String() + "/items/" + uid.String() + "/picture",
            Promotion:       p.Promotion,
            PromotionEndsAt: p.PromotionEndsAt,
            State:           p.State,
            AmountLeft:      p.AmountLeft,
            BuyLimit:        p.BuyLimit,
            OptimalAmount:   p.OptimalAmount,
            AvailableFrom:   p.AvailableFrom,
            AvailableUntil:  p.AvailableUntil,
            IsMenu:          isMenu,
            MenuItems:       p.MenuItems,
            MenuCategories:  p.MenuCategories,
        },
    }

    // Save item to database
    err = s.DBackend.CreateItem(c.Request().Context(), item)
    if err != nil {
        logrus.Error(err)
        return PostItem500(c, "Could not save item")
    }

    logrus.WithField("item", item.Name).WithField("by", usr.Name()).Info("Item created")
    autogen.PostItem201JSONResponse(item.Item).VisitPostItemResponse(c.Response())
    return nil
}