Skip to content

Commit a2573fb

Browse files
Khorayljjlgj2rong4cn
authored
fix(drivers/seafile): object not found when RootFolderPath != "/" (OpenListTeam#2010)
* fix(driver/seafile): object not found when RootFolderPath != "/" * refactor(seafile): restructure Seafile driver for improved library handling and error management * add IsDir method to LibraryInfo type * improve initialization * add repoID to RepoItemResp and update List method to set repoID --------- Co-authored-by: Khoray <[email protected]> Co-authored-by: j2rong4cn <[email protected]>
1 parent 031b719 commit a2573fb

File tree

3 files changed

+160
-168
lines changed

3 files changed

+160
-168
lines changed

drivers/seafile/driver.go

Lines changed: 109 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import (
66
"net/http"
77
stdpath "path"
88
"strings"
9-
"time"
109

1110
"github.com/OpenListTeam/OpenList/v4/internal/driver"
11+
"github.com/OpenListTeam/OpenList/v4/internal/errs"
1212
"github.com/OpenListTeam/OpenList/v4/internal/model"
1313
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
1414
"github.com/go-resty/resty/v2"
@@ -19,7 +19,7 @@ type Seafile struct {
1919
Addition
2020

2121
authorization string
22-
libraryMap map[string]*LibraryInfo
22+
root model.Obj
2323
}
2424

2525
func (d *Seafile) Config() driver.Config {
@@ -32,71 +32,121 @@ func (d *Seafile) GetAddition() driver.Additional {
3232

3333
func (d *Seafile) Init(ctx context.Context) error {
3434
d.Address = strings.TrimSuffix(d.Address, "/")
35+
err := d.getToken()
36+
if err != nil {
37+
return err
38+
}
3539
d.RootFolderPath = utils.FixAndCleanPath(d.RootFolderPath)
36-
d.libraryMap = make(map[string]*LibraryInfo)
37-
return d.getToken()
40+
if d.RepoId != "" {
41+
library, err := d.getLibraryInfo(d.RepoId)
42+
if err != nil {
43+
return err
44+
}
45+
library.path = d.RootFolderPath
46+
library.ObjMask = model.Locked
47+
d.root = &LibraryInfo{
48+
LibraryItemResp: library,
49+
}
50+
return nil
51+
}
52+
if len(d.RootFolderPath) <= 1 {
53+
d.root = &model.Object{
54+
Name: "root",
55+
Path: d.RootFolderPath,
56+
IsFolder: true,
57+
Modified: d.Modified,
58+
Mask: model.Locked,
59+
}
60+
return nil
61+
}
62+
63+
var resp []LibraryItemResp
64+
_, err = d.request(http.MethodGet, "/api2/repos/", func(req *resty.Request) {
65+
req.SetResult(&resp)
66+
})
67+
if err != nil {
68+
return err
69+
}
70+
for _, library := range resp {
71+
p, found := strings.CutPrefix(d.RootFolderPath[1:], library.Name)
72+
if !found {
73+
continue
74+
}
75+
if p == "" {
76+
p = "/"
77+
} else if p[0] != '/' {
78+
continue
79+
}
80+
// d.RepoId = library.Id
81+
// d.RootFolderPath = p
82+
83+
library.path = p
84+
library.ObjMask = model.Locked
85+
d.root = &LibraryInfo{
86+
LibraryItemResp: library,
87+
}
88+
return nil
89+
}
90+
return fmt.Errorf("Library for root folder path %q not found", d.RootFolderPath)
3891
}
3992

4093
func (d *Seafile) Drop(ctx context.Context) error {
94+
d.root = nil
4195
return nil
4296
}
4397

98+
func (d *Seafile) GetRoot(ctx context.Context) (model.Obj, error) {
99+
if d.root == nil {
100+
return nil, errs.StorageNotInit
101+
}
102+
return d.root, nil
103+
}
104+
44105
func (d *Seafile) List(ctx context.Context, dir model.Obj, args model.ListArgs) (result []model.Obj, err error) {
45106
path := dir.GetPath()
46-
if path == "/" && d.RepoId == "" {
47-
libraries, err := d.listLibraries()
48-
if err != nil {
49-
return nil, err
50-
}
51-
return utils.SliceConvert(libraries, func(f LibraryItemResp) (model.Obj, error) {
52-
return &model.Object{
53-
Path: stdpath.Join(path, f.Name),
54-
Name: f.Name,
55-
Modified: time.Unix(f.Modified, 0),
56-
Size: f.Size,
57-
IsFolder: true,
107+
switch o := dir.(type) {
108+
default:
109+
var resp []LibraryItemResp
110+
_, err = d.request(http.MethodGet, "/api2/repos/", func(req *resty.Request) {
111+
req.SetResult(&resp)
112+
})
113+
return utils.SliceConvert(resp, func(f LibraryItemResp) (model.Obj, error) {
114+
f.path = path
115+
return &LibraryInfo{
116+
LibraryItemResp: f,
58117
}, nil
59118
})
60-
}
61-
var repo *LibraryInfo
62-
repo, path, err = d.getRepoAndPath(path)
63-
if err != nil {
64-
return nil, err
65-
}
66-
if repo.Encrypted {
67-
err = d.decryptLibrary(repo)
68-
if err != nil {
69-
return nil, err
119+
case *LibraryInfo:
120+
if o.Encrypted {
121+
err = d.decryptLibrary(o)
122+
if err != nil {
123+
return nil, err
124+
}
70125
}
126+
case *RepoItemResp:
127+
// do nothing
71128
}
72-
var resp []RepoDirItemResp
73-
_, err = d.request(http.MethodGet, fmt.Sprintf("/api2/repos/%s/dir/", repo.Id), func(req *resty.Request) {
129+
130+
var resp []RepoItemResp
131+
_, err = d.request(http.MethodGet, fmt.Sprintf("/api2/repos/%s/dir/", dir.GetID()), func(req *resty.Request) {
74132
req.SetResult(&resp).SetQueryParams(map[string]string{
75133
"p": path,
76134
})
77135
})
78136
if err != nil {
79137
return nil, err
80138
}
81-
return utils.SliceConvert(resp, func(f RepoDirItemResp) (model.Obj, error) {
82-
return &model.Object{
83-
Path: stdpath.Join(dir.GetPath(), f.Name),
84-
Name: f.Name,
85-
Modified: time.Unix(f.Modified, 0),
86-
Size: f.Size,
87-
IsFolder: f.Type == "dir",
88-
}, nil
139+
return utils.SliceConvert(resp, func(f RepoItemResp) (model.Obj, error) {
140+
f.path = stdpath.Join(path, f.Name)
141+
f.repoID = dir.GetID()
142+
return &f, nil
89143
})
90144
}
91145

92146
func (d *Seafile) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
93-
repo, path, err := d.getRepoAndPath(file.GetPath())
94-
if err != nil {
95-
return nil, err
96-
}
97-
res, err := d.request(http.MethodGet, fmt.Sprintf("/api2/repos/%s/file/", repo.Id), func(req *resty.Request) {
147+
res, err := d.request(http.MethodGet, fmt.Sprintf("/api2/repos/%s/file/", file.GetID()), func(req *resty.Request) {
98148
req.SetQueryParams(map[string]string{
99-
"p": path,
149+
"p": file.GetPath(),
100150
"reuse": "1",
101151
})
102152
})
@@ -109,14 +159,9 @@ func (d *Seafile) Link(ctx context.Context, file model.Obj, args model.LinkArgs)
109159
}
110160

111161
func (d *Seafile) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
112-
repo, path, err := d.getRepoAndPath(parentDir.GetPath())
113-
if err != nil {
114-
return err
115-
}
116-
path, _ = utils.JoinBasePath(path, dirName)
117-
_, err = d.request(http.MethodPost, fmt.Sprintf("/api2/repos/%s/dir/", repo.Id), func(req *resty.Request) {
162+
_, err := d.request(http.MethodPost, fmt.Sprintf("/api2/repos/%s/dir/", parentDir.GetID()), func(req *resty.Request) {
118163
req.SetQueryParams(map[string]string{
119-
"p": path,
164+
"p": stdpath.Join(parentDir.GetPath(), dirName),
120165
}).SetFormData(map[string]string{
121166
"operation": "mkdir",
122167
})
@@ -125,34 +170,22 @@ func (d *Seafile) MakeDir(ctx context.Context, parentDir model.Obj, dirName stri
125170
}
126171

127172
func (d *Seafile) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
128-
repo, path, err := d.getRepoAndPath(srcObj.GetPath())
129-
if err != nil {
130-
return err
131-
}
132-
dstRepo, dstPath, err := d.getRepoAndPath(dstDir.GetPath())
133-
if err != nil {
134-
return err
135-
}
136-
_, err = d.request(http.MethodPost, fmt.Sprintf("/api2/repos/%s/file/", repo.Id), func(req *resty.Request) {
173+
_, err := d.request(http.MethodPost, fmt.Sprintf("/api2/repos/%s/file/", srcObj.GetID()), func(req *resty.Request) {
137174
req.SetQueryParams(map[string]string{
138-
"p": path,
175+
"p": srcObj.GetPath(),
139176
}).SetFormData(map[string]string{
140177
"operation": "move",
141-
"dst_repo": dstRepo.Id,
142-
"dst_dir": dstPath,
178+
"dst_repo": dstDir.GetID(),
179+
"dst_dir": dstDir.GetPath(),
143180
})
144181
}, true)
145182
return err
146183
}
147184

148185
func (d *Seafile) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
149-
repo, path, err := d.getRepoAndPath(srcObj.GetPath())
150-
if err != nil {
151-
return err
152-
}
153-
_, err = d.request(http.MethodPost, fmt.Sprintf("/api2/repos/%s/file/", repo.Id), func(req *resty.Request) {
186+
_, err := d.request(http.MethodPost, fmt.Sprintf("/api2/repos/%s/file/", srcObj.GetID()), func(req *resty.Request) {
154187
req.SetQueryParams(map[string]string{
155-
"p": path,
188+
"p": srcObj.GetPath(),
156189
}).SetFormData(map[string]string{
157190
"operation": "rename",
158191
"newname": newName,
@@ -162,47 +195,31 @@ func (d *Seafile) Rename(ctx context.Context, srcObj model.Obj, newName string)
162195
}
163196

164197
func (d *Seafile) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
165-
repo, path, err := d.getRepoAndPath(srcObj.GetPath())
166-
if err != nil {
167-
return err
168-
}
169-
dstRepo, dstPath, err := d.getRepoAndPath(dstDir.GetPath())
170-
if err != nil {
171-
return err
172-
}
173-
_, err = d.request(http.MethodPost, fmt.Sprintf("/api2/repos/%s/file/", repo.Id), func(req *resty.Request) {
198+
_, err := d.request(http.MethodPost, fmt.Sprintf("/api2/repos/%s/file/", srcObj.GetID()), func(req *resty.Request) {
174199
req.SetQueryParams(map[string]string{
175-
"p": path,
200+
"p": srcObj.GetPath(),
176201
}).SetFormData(map[string]string{
177202
"operation": "copy",
178-
"dst_repo": dstRepo.Id,
179-
"dst_dir": dstPath,
203+
"dst_repo": dstDir.GetID(),
204+
"dst_dir": dstDir.GetPath(),
180205
})
181206
})
182207
return err
183208
}
184209

185210
func (d *Seafile) Remove(ctx context.Context, obj model.Obj) error {
186-
repo, path, err := d.getRepoAndPath(obj.GetPath())
187-
if err != nil {
188-
return err
189-
}
190-
_, err = d.request(http.MethodDelete, fmt.Sprintf("/api2/repos/%s/file/", repo.Id), func(req *resty.Request) {
211+
_, err := d.request(http.MethodDelete, fmt.Sprintf("/api2/repos/%s/file/", obj.GetID()), func(req *resty.Request) {
191212
req.SetQueryParams(map[string]string{
192-
"p": path,
213+
"p": obj.GetPath(),
193214
})
194215
})
195216
return err
196217
}
197218

198219
func (d *Seafile) Put(ctx context.Context, dstDir model.Obj, s model.FileStreamer, up driver.UpdateProgress) error {
199-
repo, path, err := d.getRepoAndPath(dstDir.GetPath())
200-
if err != nil {
201-
return err
202-
}
203-
res, err := d.request(http.MethodGet, fmt.Sprintf("/api2/repos/%s/upload-link/", repo.Id), func(req *resty.Request) {
220+
res, err := d.request(http.MethodGet, fmt.Sprintf("/api2/repos/%s/upload-link/", dstDir.GetID()), func(req *resty.Request) {
204221
req.SetQueryParams(map[string]string{
205-
"p": path,
222+
"p": dstDir.GetPath(),
206223
})
207224
})
208225
if err != nil {
@@ -218,7 +235,7 @@ func (d *Seafile) Put(ctx context.Context, dstDir model.Obj, s model.FileStreame
218235
})
219236
req.SetFileReader("file", s.GetName(), r).
220237
SetFormData(map[string]string{
221-
"parent_dir": path,
238+
"parent_dir": dstDir.GetPath(),
222239
"replace": "1",
223240
}).
224241
SetContext(ctx)

drivers/seafile/types.go

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
package seafile
22

3-
import "time"
3+
import (
4+
"time"
5+
6+
"github.com/OpenListTeam/OpenList/v4/internal/model"
7+
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
8+
)
49

510
type AuthTokenResp struct {
611
Token string `json:"token"`
@@ -13,7 +18,41 @@ type RepoItemResp struct {
1318
Size int64 `json:"size"`
1419
Modified int64 `json:"mtime"`
1520
Permission string `json:"permission"`
21+
22+
path string
23+
model.ObjMask
24+
repoID string
25+
}
26+
27+
func (l *RepoItemResp) IsDir() bool {
28+
return l.Type == "dir"
29+
}
30+
func (l *RepoItemResp) GetPath() string {
31+
return l.path
32+
}
33+
func (l *RepoItemResp) GetName() string {
34+
return l.Name
35+
}
36+
func (l *RepoItemResp) ModTime() time.Time {
37+
return time.Unix(l.Modified, 0)
38+
}
39+
func (l *RepoItemResp) CreateTime() time.Time {
40+
return l.ModTime()
41+
}
42+
func (l *RepoItemResp) GetSize() int64 {
43+
return l.Size
1644
}
45+
func (l *RepoItemResp) GetID() string {
46+
if l.repoID != "" {
47+
return l.repoID
48+
}
49+
return l.Id
50+
}
51+
func (l *RepoItemResp) GetHash() utils.HashInfo {
52+
return utils.HashInfo{}
53+
}
54+
55+
var _ model.Obj = (*RepoItemResp)(nil)
1756

1857
type LibraryItemResp struct {
1958
RepoItemResp
@@ -33,12 +72,12 @@ type LibraryItemResp struct {
3372
SizeFormatted string `json:"size_formatted"`
3473
}
3574

36-
type RepoDirItemResp struct {
37-
RepoItemResp
38-
}
39-
4075
type LibraryInfo struct {
4176
LibraryItemResp
4277
decryptedTime time.Time
4378
decryptedSuccess bool
44-
}
79+
}
80+
81+
func (l *LibraryInfo) IsDir() bool {
82+
return true
83+
}

0 commit comments

Comments
 (0)