diff --git a/app/delivery/web/api/restricted/storage.go b/app/delivery/web/api/restricted/storage.go index b851f9a..f337547 100644 --- a/app/delivery/web/api/restricted/storage.go +++ b/app/delivery/web/api/restricted/storage.go @@ -30,6 +30,8 @@ func StorageHandlerRoutes(r fiber.Router) fiber.Router { r.Get("/list-content/*", handler.ListContent) r.Get("/download-file/*", handler.DownloadFile) + r.Get("/move/*", handler.Move) + r.Get("/copy/*", handler.Copy) r.Post("/upload-file/*", handler.UploadFile) r.Get("/create-folder/*", handler.CreateFolder) r.Delete("/delete-file/*", handler.DeleteFile) @@ -38,6 +40,50 @@ func StorageHandlerRoutes(r fiber.Router) fiber.Router { return r } +func (h *StorageHandler) Move(c fiber.Ctx) error { + src_abs_path, err := h.storageService.AbsPath(h.config.Storage.RootFolder, c.Params("*")) + if err != nil { + return c.Status(responseErrors.GetErrorStatus(err)). + JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err))) + } + + dest_abs_path, err := h.storageService.AbsPath(h.config.Storage.RootFolder, c.Query("dest_path")) + if err != nil { + return c.Status(responseErrors.GetErrorStatus(err)). + JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err))) + } + + err = h.storageService.Move(src_abs_path, dest_abs_path) + if err != nil { + return c.Status(responseErrors.GetErrorStatus(err)). + JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err))) + } + + return c.JSON(response.Make(nullable.GetNil(""), 0, i18n.T_(c, response.Message_OK))) +} + +func (h *StorageHandler) Copy(c fiber.Ctx) error { + src_abs_path, err := h.storageService.AbsPath(h.config.Storage.RootFolder, c.Params("*")) + if err != nil { + return c.Status(responseErrors.GetErrorStatus(err)). + JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err))) + } + + dest_abs_path, err := h.storageService.AbsPath(h.config.Storage.RootFolder, c.Query("dest_path")) + if err != nil { + return c.Status(responseErrors.GetErrorStatus(err)). + JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err))) + } + + err = h.storageService.Copy(src_abs_path, dest_abs_path) + if err != nil { + return c.Status(responseErrors.GetErrorStatus(err)). + JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err))) + } + + return c.JSON(response.Make(nullable.GetNil(""), 0, i18n.T_(c, response.Message_OK))) +} + // accepted path looks like e.g. "/folder1/" or "folder1" func (h *StorageHandler) ListContent(c fiber.Ctx) error { // relative path defaults to root directory diff --git a/app/repos/storageRepo/storageRepo.go b/app/repos/storageRepo/storageRepo.go index e6c1461..08441a6 100644 --- a/app/repos/storageRepo/storageRepo.go +++ b/app/repos/storageRepo/storageRepo.go @@ -1,6 +1,7 @@ package storageRepo import ( + "io" "mime/multipart" "os" @@ -11,6 +12,8 @@ import ( type UIStorageRepo interface { EntryInfo(abs_path string) (os.FileInfo, error) ListContent(abs_path string) (*[]model.EntryInList, error) + Move(src_abs_path string, dest_abs_path string) error + Copy(src_abs_path string, dest_abs_path string) error OpenFile(abs_path string) (*os.File, error) UploadFile(c fiber.Ctx, abs_path string, f *multipart.FileHeader) error CreateFolder(abs_path string) error @@ -47,6 +50,35 @@ func (r *StorageRepo) ListContent(abs_path string) (*[]model.EntryInList, error) return &entries_in_list, nil } +func (r *StorageRepo) Move(src_abs_path string, dest_abs_path string) error { + return os.Rename(src_abs_path, dest_abs_path) +} + +func (r *StorageRepo) Copy(src_abs_path string, dest_abs_path string) error { + in, err := os.Open(src_abs_path) + if err != nil { + return err + } + defer in.Close() + + info, err := in.Stat() + if err != nil { + return err + } + + out, err := os.OpenFile(dest_abs_path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, info.Mode()) + if err != nil { + return err + } + defer out.Close() + + if _, err := io.Copy(out, in); err != nil { + return err + } + + return out.Sync() +} + func (r *StorageRepo) OpenFile(abs_path string) (*os.File, error) { return os.Open(abs_path) } diff --git a/app/service/storageService/storageService.go b/app/service/storageService/storageService.go index 3e01c61..28b78ed 100644 --- a/app/service/storageService/storageService.go +++ b/app/service/storageService/storageService.go @@ -46,6 +46,35 @@ func (s *StorageService) DownloadFilePrep(abs_path string) (*os.File, string, in return f, filepath.Base(abs_path), info.Size(), nil } +func (s *StorageService) Move(src_abs_path string, dest_abs_path string) error { + _, err := s.storageRepo.EntryInfo(src_abs_path) + if err != nil { + return responseErrors.ErrFileDoesNotExist + } + + if err == nil { + return responseErrors.ErrNameTaken + } else if os.IsNotExist(err) { + return s.storageRepo.Move(src_abs_path, dest_abs_path) + } else { + return err + } +} +func (s *StorageService) Copy(src_abs_path string, dest_abs_path string) error { + _, err := s.storageRepo.EntryInfo(src_abs_path) + if err != nil { + return responseErrors.ErrFileDoesNotExist + } + + if err == nil { + return responseErrors.ErrNameTaken + } else if os.IsNotExist(err) { + return s.storageRepo.Copy(src_abs_path, dest_abs_path) + } else { + return err + } +} + func (s *StorageService) UploadFile(c fiber.Ctx, abs_path string, f *multipart.FileHeader) error { info, err := s.storageRepo.EntryInfo(abs_path) if err != nil || !info.IsDir() { diff --git a/bruno/b2b-daniel/save-product-description.yml b/bruno/b2b-daniel/save-product-description.yml new file mode 100644 index 0000000..3ea103c --- /dev/null +++ b/bruno/b2b-daniel/save-product-description.yml @@ -0,0 +1,28 @@ +info: + name: save-product-description + type: http + seq: 19 + +http: + method: POST + url: http://localhost:3000/api/v1/restricted/product-translation/save-product-description?productID=1&productLangID=3 + params: + - name: productID + value: "1" + type: query + - name: productLangID + value: "3" + type: query + body: + type: json + data: |- + { + "description": "

Der Einsatz von Rehabilitationsrollen in verschiedenen Übungen und Behandlungen wirkt sich positiv auf die Reduzierung von Verletzungen und die Genesungschancen aus. Sie werden in der Rehabilitation, bei Korrekturgymnastik sowie in der traditionellen und Sportmassage eingesetzt, da sie ideal zum Anheben und Spreizen von Gliedmaßen geeignet sind. Zudem können sie zur Unterstützung von Knien, Füßen, Armen und Schultern verwendet werden. Auch für Kinder sind Rehabilitationsrollen empfehlenswert; ihre spielerische Anwendung fördert die Entwicklung der Grobmotorik.

Dank der großen Auswahl an Farben und Größen lässt sich ein Übungsset zusammenstellen, das in jeder Physiotherapiepraxis, jedem Massageraum, jeder Schule oder jedem Kindergarten benötigt wird.

Die Rehabilitationsrolle ist ein Medizinprodukt, das den grundlegenden Anforderungen an Medizinprodukte und den Bestimmungen des Medizinproduktegesetzes entspricht, im Register für Medizinprodukte des Amtes für die Registrierung von Arzneimitteln, Medizinprodukten und Biozidprodukten eingetragen ist, mit der Konformitätserklärung des Herstellers versehen ist und das CE-Zeichen trägt.

\"Medizinprodukt\"

Empfohlene Verwendung:

Materialspezifikationen:

Abdeckung: PVC-beschichtetes Material, das für medizinische Geräte vorgesehen ist und daher sehr leicht zu reinigen und zu desinfizieren ist:

\"ERREICHEN\"\"Öko-Tex\"Enthält\"Feuerfest\"\"Alkoholbeständig\"\"UV-beständig\"\"Für\"Kratzfest\"\"Ölbeständig\"

Füllung: mittelharter Polyurethanschaum mit erhöhter Verformungsbeständigkeit:

\"Öko-Tex\"Hygienezertifikat\"\"Hygienezertifikat\"

" + } + auth: inherit + +settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 diff --git a/bruno/b2b-daniel/translate-product-description.yml b/bruno/b2b-daniel/translate-product-description.yml new file mode 100644 index 0000000..5f3a787 --- /dev/null +++ b/bruno/b2b-daniel/translate-product-description.yml @@ -0,0 +1,28 @@ +info: + name: translate-product-description + type: http + seq: 21 + +http: + method: GET + url: http://localhost:3000/api/v1/restricted/product-translation/translate-product-description?productID=51&productFromLangID=1&productToLangID=3&model=Google + params: + - name: productID + value: "51" + type: query + - name: productFromLangID + value: "1" + type: query + - name: productToLangID + value: "3" + type: query + - name: model + value: Google + type: query + auth: inherit + +settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 diff --git a/bruno/b2b_daniel/storage/copy.yml b/bruno/b2b_daniel/storage/copy.yml new file mode 100644 index 0000000..8161fc0 --- /dev/null +++ b/bruno/b2b_daniel/storage/copy.yml @@ -0,0 +1,19 @@ +info: + name: copy + type: http + seq: 7 + +http: + method: GET + url: http://localhost:3000/api/v1/restricted/storage/copy/folder1/test.txt?dest_path=/folder/a.txt + params: + - name: dest_path + value: /folder/a.txt + type: query + auth: inherit + +settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5 diff --git a/bruno/b2b_daniel/storage/move.yml b/bruno/b2b_daniel/storage/move.yml new file mode 100644 index 0000000..7fb51e5 --- /dev/null +++ b/bruno/b2b_daniel/storage/move.yml @@ -0,0 +1,19 @@ +info: + name: move + type: http + seq: 8 + +http: + method: GET + url: http://localhost:3000/api/v1/restricted/storage/move/folder?dest_path=/folder1/test.txt + params: + - name: dest_path + value: /folder1/test.txt + type: query + auth: inherit + +settings: + encodeUrl: true + timeout: 0 + followRedirects: true + maxRedirects: 5