package storageRepo import ( "io" "os" "path/filepath" "time" "git.ma-al.com/goc_daniel/b2b/app/db" "git.ma-al.com/goc_daniel/b2b/app/model" ) type UIStorageRepo interface { SaveWebdavToken(user_id uint, hash_token string, expires_at *time.Time) error EntryInfo(abs_path string) (os.FileInfo, error) ListContent(abs_path string) (*[]model.EntryInList, error) OpenFile(abs_path string) (*os.File, error) Put(abs_path string, src io.Reader) error Delete(abs_path string) error Mkcol(abs_path string) error Move(src_abs_path string, dest_abs_path string) error Copy(src_abs_path string, dest_abs_path string) error } type StorageRepo struct{} func New() UIStorageRepo { return &StorageRepo{} } func (r *StorageRepo) SaveWebdavToken(user_id uint, hash_token string, expires_at *time.Time) error { return db.DB. Table("b2b_customers"). Where("id = ?", user_id). Updates(map[string]interface{}{ "webdav_token": hash_token, "webdav_expires": expires_at, }). Error } func (r *StorageRepo) EntryInfo(abs_path string) (os.FileInfo, error) { return os.Stat(abs_path) } func (r *StorageRepo) ListContent(abs_path string) (*[]model.EntryInList, error) { entries, err := os.ReadDir(abs_path) if err != nil { return nil, err } var entries_in_list []model.EntryInList for _, entry := range entries { var next_entry_in_list model.EntryInList next_entry_in_list.Name = entry.Name() next_entry_in_list.IsFolder = entry.IsDir() entries_in_list = append(entries_in_list, next_entry_in_list) } return &entries_in_list, nil } func (r *StorageRepo) OpenFile(abs_path string) (*os.File, error) { return os.Open(abs_path) } func (r *StorageRepo) Put(abs_path string, src io.Reader) error { // Write to a temp file in the same directory, then atomically rename. tmp, err := os.CreateTemp(filepath.Dir(abs_path), ".put-*") if err != nil { return err } tmp_name := tmp.Name() cleanup_tmp := true defer func() { _ = tmp.Close() if cleanup_tmp { _ = os.Remove(tmp_name) } }() _, err = io.Copy(tmp, src) if err != nil { return err } err = tmp.Sync() if err != nil { return err } err = tmp.Close() if err != nil { return err } err = os.Chmod(tmp_name, 0o644) if err != nil { return err } err = os.Rename(tmp_name, abs_path) if err != nil { return err } cleanup_tmp = false return nil } func (r *StorageRepo) Delete(abs_path string) error { return os.RemoveAll(abs_path) } func (r *StorageRepo) Mkcol(abs_path string) error { return os.Mkdir(abs_path, 0755) } 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 { info, err := os.Stat(src_abs_path) if err != nil { return err } if info.IsDir() { return r.copyDir(src_abs_path, dest_abs_path) } else { return r.copyFile(src_abs_path, dest_abs_path) } } func (r *StorageRepo) copyFile(src_abs_path string, dest_abs_path string) error { f, err := os.Open(src_abs_path) if err != nil { return err } defer f.Close() err = r.Put(dest_abs_path, f) return err } func (r *StorageRepo) copyDir(src_abs_path string, dest_abs_path string) error { if err := os.Mkdir(dest_abs_path, 0755); err != nil { return err } entries, err := os.ReadDir(src_abs_path) if err != nil { return err } for _, entry := range entries { entity_src_path := filepath.Join(src_abs_path, entry.Name()) entity_dst_Path := filepath.Join(dest_abs_path, entry.Name()) if entry.IsDir() { err = r.copyDir(entity_src_path, entity_dst_Path) if err != nil { return err } } else { err = r.copyFile(entity_src_path, entity_dst_Path) if err != nil { return err } } } return nil }