feat(driver): Added support for safe unlocking logic

- Added safe file unlocking logic in `driver.go`, returning an error if unlocking fails.
- Introduced the `safeBoxUnlocked` variable of type `sync.Map` to record the IDs of unlocked files.
- Enhanced error handling logic to automatically attempt to unlock safe files and re-retrieve the file list.
- Added the `IsLock` field to file types in `types.go` to identify whether they are safe files.
- Added a constant definition for the `SafeBoxUnlock` interface address in `util.go`.
- Added the `unlockSafeBox` method to unlock a safe with a specified file ID via the API.
- Optimized the file retrieval logic to automatically call the unlock method when the safe is locked.
pull/9311/head
okatu-loli 2025-09-05 19:17:00 +08:00
parent 42f6c61503
commit d6f002a133
3 changed files with 49 additions and 2 deletions

View File

@ -6,6 +6,8 @@ import (
"fmt"
"net/http"
"net/url"
"strconv"
"strings"
"sync"
"time"
@ -29,6 +31,7 @@ type Pan123 struct {
model.Storage
Addition
apiRateLimit sync.Map
safeBoxUnlocked sync.Map
}
func (d *Pan123) Config() driver.Config {
@ -52,10 +55,27 @@ func (d *Pan123) Drop(ctx context.Context) error {
}
func (d *Pan123) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
if f, ok := dir.(File); ok && f.IsLock == 1 {
if err := d.unlockSafeBox(f.FileId); err != nil {
return nil, err
}
}
files, err := d.getFiles(ctx, dir.GetID(), dir.GetName())
if err != nil {
msg := strings.ToLower(err.Error())
if strings.Contains(msg, "safe box") || strings.Contains(err.Error(), "保险箱") {
if id, e := strconv.ParseInt(dir.GetID(), 10, 64); e == nil {
if e = d.unlockSafeBox(id); e == nil {
files, err = d.getFiles(ctx, dir.GetID(), dir.GetName())
} else {
return nil, e
}
}
}
if err != nil {
return nil, err
}
}
return utils.SliceConvert(files, func(src File) (model.Obj, error) {
return src, nil
})

View File

@ -20,6 +20,7 @@ type File struct {
Etag string `json:"Etag"`
S3KeyFlag string `json:"S3KeyFlag"`
DownloadUrl string `json:"DownloadUrl"`
IsLock int `json:"IsLock"`
}
func (f File) CreateTime() time.Time {

View File

@ -43,6 +43,7 @@ const (
S3Auth = MainApi + "/file/s3_upload_object/auth"
UploadCompleteV2 = MainApi + "/file/upload_complete/v2"
S3Complete = MainApi + "/file/s3_complete_multipart_upload"
SafeBoxUnlock = MainApi + "/restful/goapi/v1/file/safe_box/auth/unlockbox"
//AuthKeySalt = "8-8D$sL8gPjom7bk#cY"
)
@ -238,6 +239,22 @@ do:
return body, nil
}
func (d *Pan123) unlockSafeBox(fileId int64) error {
if _, ok := d.safeBoxUnlocked.Load(fileId); ok {
return nil
}
data := base.Json{"password": d.SafePassword}
url := fmt.Sprintf("%s?fileId=%d", SafeBoxUnlock, fileId)
_, err := d.Request(url, http.MethodPost, func(req *resty.Request) {
req.SetBody(data)
}, nil)
if err != nil {
return err
}
d.safeBoxUnlocked.Store(fileId, true)
return nil
}
func (d *Pan123) getFiles(ctx context.Context, parentId string, name string) ([]File, error) {
page := 1
total := 0
@ -267,6 +284,15 @@ func (d *Pan123) getFiles(ctx context.Context, parentId string, name string) ([]
req.SetQueryParams(query)
}, &resp)
if err != nil {
msg := strings.ToLower(err.Error())
if strings.Contains(msg, "safe box") || strings.Contains(err.Error(), "保险箱") {
if fid, e := strconv.ParseInt(parentId, 10, 64); e == nil {
if e = d.unlockSafeBox(fid); e == nil {
return d.getFiles(ctx, parentId, name)
}
return nil, e
}
}
return nil, err
}
log.Debug(string(_res))