From 721f18a7f465a9688750767f2691cff68a58731d Mon Sep 17 00:00:00 2001 From: Noah Hsu Date: Wed, 3 Aug 2022 14:14:37 +0800 Subject: [PATCH] feat: fs other api --- drivers/local/driver.go | 5 +++-- drivers/virtual/driver.go | 7 +++--- internal/driver/driver.go | 2 +- internal/fs/fs.go | 9 ++++++++ internal/fs/{write.go => other.go} | 11 ++++++++++ internal/model/{link.go => args.go} | 12 +++++++++++ internal/operations/fs.go | 13 ++++++++++++ server/handles/fsread.go | 33 +++++++++++++++++++++++++++++ 8 files changed, 86 insertions(+), 6 deletions(-) rename internal/fs/{write.go => other.go} (81%) rename internal/model/{link.go => args.go} (65%) diff --git a/drivers/local/driver.go b/drivers/local/driver.go index fc1747cb99b..f3079b91b9a 100644 --- a/drivers/local/driver.go +++ b/drivers/local/driver.go @@ -2,12 +2,13 @@ package local import ( "context" - "github.com/alist-org/alist/v3/internal/errs" "io/ioutil" "os" "path/filepath" "strings" + "github.com/alist-org/alist/v3/internal/errs" + "github.com/alist-org/alist/v3/internal/driver" "github.com/alist-org/alist/v3/internal/model" "github.com/alist-org/alist/v3/internal/operations" @@ -175,7 +176,7 @@ func (d *Local) Put(ctx context.Context, dstDir model.Obj, stream model.FileStre return nil } -func (d *Local) Other(ctx context.Context, data interface{}) (interface{}, error) { +func (d *Local) Other(ctx context.Context, args model.OtherArgs) (interface{}, error) { return nil, errs.NotSupport } diff --git a/drivers/virtual/driver.go b/drivers/virtual/driver.go index e6fe30e9dce..88cfc413f13 100644 --- a/drivers/virtual/driver.go +++ b/drivers/virtual/driver.go @@ -2,14 +2,15 @@ package virtual import ( "context" + "io" + "time" + "github.com/alist-org/alist/v3/internal/driver" "github.com/alist-org/alist/v3/internal/errs" "github.com/alist-org/alist/v3/internal/model" "github.com/alist-org/alist/v3/pkg/utils" "github.com/alist-org/alist/v3/pkg/utils/random" "github.com/pkg/errors" - "io" - "time" ) type Virtual struct { @@ -93,7 +94,7 @@ func (d *Virtual) Put(ctx context.Context, dstDir model.Obj, stream model.FileSt return nil } -func (d *Virtual) Other(ctx context.Context, data interface{}) (interface{}, error) { +func (d *Virtual) Other(ctx context.Context, args model.OtherArgs) (interface{}, error) { return nil, errs.NotSupport } diff --git a/internal/driver/driver.go b/internal/driver/driver.go index 2e1ce82f7af..42cedd94c09 100644 --- a/internal/driver/driver.go +++ b/internal/driver/driver.go @@ -25,7 +25,7 @@ type Meta interface { } type Other interface { - Other(ctx context.Context, data interface{}) (interface{}, error) + Other(ctx context.Context, args model.OtherArgs) (interface{}, error) } type Reader interface { diff --git a/internal/fs/fs.go b/internal/fs/fs.go index b811e9be9fb..7c63e916813 100644 --- a/internal/fs/fs.go +++ b/internal/fs/fs.go @@ -2,6 +2,7 @@ package fs import ( "context" + "github.com/alist-org/alist/v3/internal/driver" "github.com/alist-org/alist/v3/internal/model" "github.com/alist-org/alist/v3/internal/operations" @@ -102,3 +103,11 @@ func GetStorage(path string) (driver.Driver, error) { } return storageDriver, nil } + +func Other(ctx context.Context, args model.FsOtherArgs) (interface{}, error) { + res, err := other(ctx, args) + if err != nil { + log.Errorf("failed remove %s: %+v", args.Path, err) + } + return res, err +} diff --git a/internal/fs/write.go b/internal/fs/other.go similarity index 81% rename from internal/fs/write.go rename to internal/fs/other.go index 624414aa85a..107d49a04cd 100644 --- a/internal/fs/write.go +++ b/internal/fs/other.go @@ -2,7 +2,9 @@ package fs import ( "context" + "github.com/alist-org/alist/v3/internal/errs" + "github.com/alist-org/alist/v3/internal/model" "github.com/alist-org/alist/v3/internal/operations" "github.com/pkg/errors" ) @@ -45,3 +47,12 @@ func remove(ctx context.Context, path string) error { } return operations.Remove(ctx, storage, actualPath) } + +func other(ctx context.Context, args model.FsOtherArgs) (interface{}, error) { + storage, actualPath, err := operations.GetStorageAndActualPath(args.Path) + if err != nil { + return nil, errors.WithMessage(err, "failed get storage") + } + args.Path = actualPath + return operations.Other(ctx, storage, args) +} diff --git a/internal/model/link.go b/internal/model/args.go similarity index 65% rename from internal/model/link.go rename to internal/model/args.go index 389532858b8..1f027334255 100644 --- a/internal/model/link.go +++ b/internal/model/args.go @@ -19,3 +19,15 @@ type Link struct { FilePath *string // local file, return the filepath Expiration *time.Duration // url expiration time } + +type OtherArgs struct { + Obj Obj + Method string + Data interface{} +} + +type FsOtherArgs struct { + Path string `json:"path" form:"path"` + Method string `json:"method" form:"method"` + Data interface{} `json:"data" form:"data"` +} diff --git a/internal/operations/fs.go b/internal/operations/fs.go index eba1f8487db..32541c19549 100644 --- a/internal/operations/fs.go +++ b/internal/operations/fs.go @@ -150,6 +150,19 @@ func Link(ctx context.Context, storage driver.Driver, path string, args model.Li return link, file, err } +// other api +func Other(ctx context.Context, storage driver.Driver, args model.FsOtherArgs) (interface{}, error) { + obj, err := Get(ctx, storage, args.Path) + if err != nil { + return nil, errors.WithMessagef(err, "failed to get obj") + } + return storage.Other(ctx, model.OtherArgs{ + Obj: obj, + Method: args.Method, + Data: args.Data, + }) +} + func MakeDir(ctx context.Context, storage driver.Driver, path string) error { // check if dir exists f, err := Get(ctx, storage, path) diff --git a/server/handles/fsread.go b/server/handles/fsread.go index 61000deb5d1..d8bb74424a1 100644 --- a/server/handles/fsread.go +++ b/server/handles/fsread.go @@ -253,3 +253,36 @@ func FsGet(c *gin.Context) { RawURL: rawURL, }) } + +type FsOtherReq struct { + model.FsOtherArgs + Password string `json:"password" form:"password"` +} + +func FsOther(c *gin.Context) { + var req FsOtherReq + if err := c.ShouldBind(&req); err != nil { + common.ErrorResp(c, err, 400) + return + } + user := c.MustGet("user").(*model.User) + req.Path = stdpath.Join(user.BasePath, req.Path) + meta, err := db.GetNearestMeta(req.Path) + if err != nil { + if !errors.Is(errors.Cause(err), errs.MetaNotFound) { + common.ErrorResp(c, err, 500) + return + } + } + c.Set("meta", meta) + if !canAccess(user, meta, req.Path, req.Password) { + common.ErrorStrResp(c, "password is incorrect", 403) + return + } + res, err := fs.Other(c, req.FsOtherArgs) + if err != nil { + common.ErrorResp(c, err, 500) + return + } + common.SuccessResp(c, res) +}