package storageService import ( "mime/multipart" "os" "path/filepath" "strings" "git.ma-al.com/goc_daniel/b2b/app/model" "git.ma-al.com/goc_daniel/b2b/app/repos/storageRepo" "git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors" "github.com/gofiber/fiber/v3" ) type StorageService struct { storageRepo storageRepo.UIStorageRepo } func New() *StorageService { return &StorageService{ storageRepo: storageRepo.New(), } } func (s *StorageService) ListContent(abs_path string) (*[]model.EntryInList, error) { info, err := s.storageRepo.EntryInfo(abs_path) if err != nil || !info.IsDir() { return nil, responseErrors.ErrFolderDoesNotExist } entries_in_list, err := s.storageRepo.ListContent(abs_path) return entries_in_list, err } func (s *StorageService) DownloadFilePrep(abs_path string) (*os.File, string, int64, error) { info, err := s.storageRepo.EntryInfo(abs_path) if err != nil || info.IsDir() { return nil, "", 0, responseErrors.ErrFileDoesNotExist } f, err := s.storageRepo.OpenFile(abs_path) if err != nil { return nil, "", 0, err } return f, filepath.Base(abs_path), info.Size(), nil } 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() { return responseErrors.ErrFolderDoesNotExist } name := f.Filename if name == "" || name == "." || name == ".." || filepath.Base(name) != name { return responseErrors.ErrBadAttribute } abs_file_path, err := s.AbsPath(abs_path, name) if err != nil { return err } if abs_file_path == abs_path { return responseErrors.ErrBadAttribute } info, err = s.storageRepo.EntryInfo(abs_file_path) if err == nil { return responseErrors.ErrNameTaken } else if os.IsNotExist(err) { return s.storageRepo.UploadFile(c, abs_file_path, f) } else { return err } } func (s *StorageService) CreateFolder(abs_path string, name string) error { info, err := s.storageRepo.EntryInfo(abs_path) if err != nil || !info.IsDir() { return responseErrors.ErrFolderDoesNotExist } if name == "" || name == "." || name == ".." || filepath.Base(name) != name { return responseErrors.ErrBadAttribute } abs_folder_path, err := s.AbsPath(abs_path, name) if err != nil { return err } if abs_folder_path == abs_path { return responseErrors.ErrBadAttribute } info, err = s.storageRepo.EntryInfo(abs_folder_path) if err == nil { return responseErrors.ErrNameTaken } else if os.IsNotExist(err) { return s.storageRepo.CreateFolder(abs_folder_path) } else { return err } } func (s *StorageService) DeleteFile(abs_path string) error { info, err := s.storageRepo.EntryInfo(abs_path) if err != nil || info.IsDir() { return responseErrors.ErrFileDoesNotExist } return s.storageRepo.DeleteFile(abs_path) } func (s *StorageService) DeleteFolder(abs_path string) error { info, err := s.storageRepo.EntryInfo(abs_path) if err != nil || !info.IsDir() { return responseErrors.ErrFolderDoesNotExist } return s.storageRepo.DeleteFolder(abs_path) } // AbsPath extracts an absolute path and validates it func (s *StorageService) AbsPath(root string, relativePath string) (string, error) { clean_name := filepath.Clean(relativePath) full_path := filepath.Join(root, clean_name) if full_path != root && !strings.HasPrefix(full_path, root+string(os.PathSeparator)) { return "", responseErrors.ErrAccessDenied } return full_path, nil }