package service import ( "errors" "github.com/gofiber/fiber/v2" "io" quizdal "penahub.gitlab.yandexcloud.net/backend/quiz/common.git/dal" mw "penahub.gitlab.yandexcloud.net/backend/quiz/common.git/middleware" "penahub.gitlab.yandexcloud.net/backend/quiz/storer.git/dal" "strconv" "sync" "github.com/rs/xid" ) type Service struct { store *dal.Storer dal *quizdal.DAL } func New(s *dal.Storer, q *quizdal.DAL) *Service { return &Service{ store: s, dal: q, } } func (s *Service) Register(app *fiber.App) { app.Put("/quiz/customization", s.UploadCustom) app.Put("/quiz/putImages", s.UploadImages) } // MB Size constants const ( MB = 1 << 20 ) func (s *Service) UploadCustom(c *fiber.Ctx) error { accountId, ok := mw.GetAccountId(c) if !ok { return nil } // Check valid file form, err := c.MultipartForm() if err != nil || form == nil || form.File == nil { return c.Status(fiber.StatusBadRequest).SendString("expecting multipart form file") } squizIdStr := form.Value["quiz"] if len(squizIdStr) == 0 { return c.Status(fiber.StatusFailedDependency).SendString("no quiz id provided") } squizId, err := strconv.ParseInt(squizIdStr[0], 10, 64) if err != nil { return c.Status(fiber.StatusBadRequest).SendString("not valid quiz id provided " + err.Error()) } quiz, err := s.dal.QuizRepo.GetQuizById(c.Context(), accountId, uint64(squizId)) if err != nil { return c.Status(fiber.StatusNotAcceptable).SendString("not exists quiz id provided " + err.Error()) } var ( wg sync.WaitGroup errm sync.Mutex errs []error ) if len(form.File["script"]) >= 1 { wg.Add(1) go func() { defer wg.Done() fileHeader := form.File["script"][0] file, err := fileHeader.Open() if err != nil { errm.Lock() defer errm.Unlock() errs = append(errs, errors.New(err.Error()+" => script read")) return } defer file.Close() if err := s.store.UploadScript(c.Context(), quiz.Qid, file, fileHeader.Size); err != nil { errm.Lock() defer errm.Unlock() errs = append(errs, errors.New(err.Error()+" => script upload")) } }() } if len(form.File["style"]) >= 1 { wg.Add(1) go func() { defer wg.Done() fileHeader := form.File["style"][0] file, err := fileHeader.Open() if err != nil { errm.Lock() defer errm.Unlock() errs = append(errs, errors.New(err.Error()+" => style read")) return } defer file.Close() if err := s.store.UploadStyle(c.Context(), quiz.Qid, file, fileHeader.Size); err != nil { errm.Lock() defer errm.Unlock() errs = append(errs, errors.New(err.Error()+" => style upload")) } }() } if len(form.File["fonts"]) >= 1 { files, sizes := map[string]io.Reader{}, map[string]int64{} for _, fileHeader := range form.File["fonts"] { file, err := fileHeader.Open() if err != nil { errm.Lock() errs = append(errs, errors.New(err.Error()+" => fonts read")) errm.Unlock() } files[fileHeader.Filename] = file sizes[fileHeader.Filename] = fileHeader.Size } wg.Add(1) go func() { defer wg.Done() if errorsFontUploading := s.store.UploadFonts(c.Context(), quiz.Qid, files, sizes); err != nil { errm.Lock() defer errm.Unlock() errs = append(errs, errorsFontUploading...) } }() } wg.Wait() if len(errs) > 0 { return c.Status(fiber.StatusInternalServerError).JSON(errs) } return c.SendStatus(fiber.StatusOK) } func (s *Service) UploadImages(c *fiber.Ctx) error { accountId, ok := mw.GetAccountId(c) if !ok { return nil } // Check valid file form, err := c.MultipartForm() if err != nil || form == nil || form.File == nil { return c.Status(fiber.StatusBadRequest).SendString("expecting multipart form file") } squizIdStr := form.Value["quiz"] if len(squizIdStr) == 0 { return c.Status(fiber.StatusFailedDependency).SendString("no quiz id provided") } squizId, err := strconv.ParseInt(squizIdStr[0], 10, 64) if err != nil { return c.Status(fiber.StatusBadRequest).SendString("not valid quiz id provided " + err.Error()) } quiz, err := s.dal.QuizRepo.GetQuizById(c.Context(), accountId, uint64(squizId)) if err != nil { return c.Status(fiber.StatusNotAcceptable).SendString("not exists quiz id provided " + err.Error()) } var errs []error imgids := make(map[string]string) if len(form.File["image"]) >= 1 { files, sizes := make(map[string]io.Reader), make(map[string]int64) for _, imgFile := range form.File["image"] { f, err := imgFile.Open() if err != nil { errs = append(errs, errors.New(err.Error()+" => imgs read")) continue } fname := xid.New().String() files[fname] = f sizes[fname] = imgFile.Size imgids[imgFile.Filename] = fname defer f.Close() } if err := s.store.UploadImages(c.Context(), quiz.Qid, files, sizes); err != nil { errs = append(errs, err...) } } if len(errs) > 0 { return c.Status(fiber.StatusInternalServerError).JSON(errs) } return c.Status(fiber.StatusOK).JSON(imgids) }