diff --git a/cmd/admin.go b/cmd/admin.go index 6f61ccab..62ca0f67 100644 --- a/cmd/admin.go +++ b/cmd/admin.go @@ -4,7 +4,7 @@ Copyright © 2022 NAME HERE package cmd import ( - "github.com/alist-org/alist/v3/internal/db" + "github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/pkg/utils" "github.com/spf13/cobra" ) @@ -16,7 +16,7 @@ var passwordCmd = &cobra.Command{ Short: "Show admin user's info", Run: func(cmd *cobra.Command, args []string) { Init() - admin, err := db.GetAdmin() + admin, err := op.GetAdmin() if err != nil { utils.Log.Errorf("failed get admin user: %+v", err) } else { diff --git a/cmd/cancel2FA.go b/cmd/cancel2FA.go index d90a398e..46f7e81d 100644 --- a/cmd/cancel2FA.go +++ b/cmd/cancel2FA.go @@ -4,7 +4,7 @@ Copyright © 2022 NAME HERE package cmd import ( - "github.com/alist-org/alist/v3/internal/db" + "github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/pkg/utils" "github.com/spf13/cobra" ) @@ -15,11 +15,11 @@ var cancel2FACmd = &cobra.Command{ Short: "Delete 2FA of admin user", Run: func(cmd *cobra.Command, args []string) { Init() - admin, err := db.GetAdmin() + admin, err := op.GetAdmin() if err != nil { utils.Log.Errorf("failed to get admin user: %+v", err) } else { - err := db.Cancel2FAByUser(admin) + err := op.Cancel2FAByUser(admin) if err != nil { utils.Log.Errorf("failed to cancel 2FA: %+v", err) } diff --git a/internal/bootstrap/data/setting.go b/internal/bootstrap/data/setting.go index db680f2d..3a136631 100644 --- a/internal/bootstrap/data/setting.go +++ b/internal/bootstrap/data/setting.go @@ -3,8 +3,8 @@ package data import ( "github.com/alist-org/alist/v3/cmd/flags" "github.com/alist-org/alist/v3/internal/conf" - "github.com/alist-org/alist/v3/internal/db" "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/pkg/utils/random" "github.com/pkg/errors" log "github.com/sirupsen/logrus" @@ -16,40 +16,45 @@ var initialSettingItems []model.SettingItem func initSettings() { InitialSettings() // check deprecated - settings, err := db.GetSettingItems() + settings, err := op.GetSettingItems() if err != nil { log.Fatalf("failed get settings: %+v", err) } + for i := range settings { - if !isActive(settings[i].Key) { + if !isActive(settings[i].Key) && settings[i].Flag != model.DEPRECATED { settings[i].Flag = model.DEPRECATED + err = op.SaveSettingItem(&settings[i]) + if err != nil { + log.Fatalf("failed save setting: %+v", err) + } } } - // what's going on here??? - //if settings != nil && len(settings) > 0 { - // err = db.SaveSettingItems(settings) - // if err != nil { - // log.Fatalf("failed save settings: %+v", err) - // } - //} - // insert new items + + // create or save setting for i := range initialSettingItems { - v := initialSettingItems[i] - stored, err := db.GetSettingItemByKey(v.Key) - if errors.Is(err, gorm.ErrRecordNotFound) || v.Key == conf.VERSION { - err = db.SaveSettingItem(v) - if err != nil { - log.Fatalf("failed create setting: %+v", err) - } - } else if err != nil { + item := &initialSettingItems[i] + // err + stored, err := op.GetSettingItemByKey(item.Key) + if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { log.Fatalf("failed get setting: %+v", err) - } else { - v.Value = stored.Value - err = db.SaveSettingItem(v) - if err != nil { - log.Fatalf("failed resave setting: %+v", err) - } + continue } + + // save + if stored != nil { + item.Value = stored.Value + } + if stored == nil || *item != *stored { + err = op.SaveSettingItem(item) + if err != nil { + log.Fatalf("failed save setting: %+v", err) + } + continue + } + + // Not save so needs to execute hook + op.HandleSettingItemHook(item) } } diff --git a/internal/bootstrap/data/user.go b/internal/bootstrap/data/user.go index ac6ca1cd..04018ee0 100644 --- a/internal/bootstrap/data/user.go +++ b/internal/bootstrap/data/user.go @@ -6,6 +6,7 @@ import ( "github.com/alist-org/alist/v3/cmd/flags" "github.com/alist-org/alist/v3/internal/db" "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/pkg/utils" "github.com/alist-org/alist/v3/pkg/utils/random" "github.com/pkg/errors" @@ -13,7 +14,7 @@ import ( ) func initUser() { - admin, err := db.GetAdmin() + admin, err := op.GetAdmin() adminPassword := random.String(8) envpass := os.Getenv("ALIST_ADMIN_PASSWORD") if flags.Dev { @@ -29,7 +30,7 @@ func initUser() { Role: model.ADMIN, BasePath: "/", } - if err := db.CreateUser(admin); err != nil { + if err := op.CreateUser(admin); err != nil { panic(err) } else { utils.Log.Infof("Successfully created the admin user and the initial password is: %s", admin.Password) @@ -38,7 +39,7 @@ func initUser() { panic(err) } } - guest, err := db.GetGuest() + guest, err := op.GetGuest() if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { guest = &model.User{ diff --git a/internal/db/meta.go b/internal/db/meta.go index 8fd54fd3..8b6a605e 100644 --- a/internal/db/meta.go +++ b/internal/db/meta.go @@ -1,52 +1,16 @@ package db import ( - stdpath "path" - "time" - - "github.com/Xhofe/go-cache" - "github.com/alist-org/alist/v3/internal/errs" "github.com/alist-org/alist/v3/internal/model" - "github.com/alist-org/alist/v3/pkg/singleflight" - "github.com/alist-org/alist/v3/pkg/utils" "github.com/pkg/errors" - "gorm.io/gorm" ) -var metaCache = cache.NewMemCache(cache.WithShards[*model.Meta](2)) - -// metaG maybe not needed -var metaG singleflight.Group[*model.Meta] - -func GetNearestMeta(path string) (*model.Meta, error) { - path = utils.FixAndCleanPath(path) - meta, err := GetMetaByPath(path) - if err == nil { - return meta, nil - } - if errors.Cause(err) != gorm.ErrRecordNotFound { - return nil, err - } - if path == "/" { - return nil, errors.WithStack(errs.MetaNotFound) - } - return GetNearestMeta(stdpath.Dir(path)) -} - func GetMetaByPath(path string) (*model.Meta, error) { - meta, ok := metaCache.Get(path) - if ok { - return meta, nil + meta := model.Meta{Path: path} + if err := db.Where(meta).First(&meta).Error; err != nil { + return nil, errors.Wrapf(err, "failed select meta") } - meta, err, _ := metaG.Do(path, func() (*model.Meta, error) { - meta := model.Meta{Path: path} - if err := db.Where(meta).First(&meta).Error; err != nil { - return nil, errors.Wrapf(err, "failed select meta") - } - metaCache.Set(path, &meta, cache.WithEx[*model.Meta](time.Hour)) - return &meta, nil - }) - return meta, err + return &meta, nil } func GetMetaById(id uint) (*model.Meta, error) { @@ -62,32 +26,20 @@ func CreateMeta(u *model.Meta) error { } func UpdateMeta(u *model.Meta) error { - old, err := GetMetaById(u.ID) - if err != nil { - return err - } - metaCache.Del(old.Path) return errors.WithStack(db.Save(u).Error) } -func GetMetas(pageIndex, pageSize int) ([]model.Meta, int64, error) { +func GetMetas(pageIndex, pageSize int) (metas []model.Meta, count int64, err error) { metaDB := db.Model(&model.Meta{}) - var count int64 - if err := metaDB.Count(&count).Error; err != nil { + if err = metaDB.Count(&count).Error; err != nil { return nil, 0, errors.Wrapf(err, "failed get metas count") } - var metas []model.Meta - if err := metaDB.Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&metas).Error; err != nil { + if err = metaDB.Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&metas).Error; err != nil { return nil, 0, errors.Wrapf(err, "failed get find metas") } return metas, count, nil } func DeleteMetaById(id uint) error { - old, err := GetMetaById(id) - if err != nil { - return err - } - metaCache.Del(old.Path) return errors.WithStack(db.Delete(&model.Meta{}, id).Error) } diff --git a/internal/db/meta_test.go b/internal/db/meta_test.go deleted file mode 100644 index c44b85c6..00000000 --- a/internal/db/meta_test.go +++ /dev/null @@ -1,60 +0,0 @@ -package db - -import ( - "testing" - - "github.com/alist-org/alist/v3/internal/errs" - "github.com/alist-org/alist/v3/internal/model" - "github.com/pkg/errors" - "gorm.io/driver/sqlite" - "gorm.io/gorm" -) - -func init() { - db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{}) - if err != nil { - panic("failed to connect database") - } - Init(db) -} - -func TestCreateMeta(t *testing.T) { - metas := []model.Meta{ - {Path: "/"}, - {Path: "/a"}, - {Path: "/a/b"}, - {Path: "/a/b/c"}, - } - for _, meta := range metas { - err := CreateMeta(&meta) - if err != nil { - t.Errorf("failed to create meta: %+v", err) - } - } -} - -func TestUpdateMeta(t *testing.T) { - meta := model.Meta{ID: 1, Path: "/b"} - err := UpdateMeta(&meta) - if err != nil { - t.Errorf("failed to update meta: %+v", err) - } -} - -func TestGetNearestMeta1(t *testing.T) { - meta, err := GetNearestMeta("/b/c/d") - if err != nil { - t.Errorf("failed to get nearest meta: %+v", err) - } - if meta.Path != "/b" { - t.Errorf("unexpected meta: %+v", meta) - } -} - -func TestGetNearestMeta2(t *testing.T) { - meta, err := GetNearestMeta("/c/d/e") - if errors.Cause(err) != errs.MetaNotFound { - t.Errorf("unexpected error: %+v", err) - t.Errorf("unexpected meta: %+v", meta) - } -} diff --git a/internal/db/settinghooks.go b/internal/db/settinghooks.go deleted file mode 100644 index f7d85a07..00000000 --- a/internal/db/settinghooks.go +++ /dev/null @@ -1,79 +0,0 @@ -package db - -import ( - "regexp" - "strings" - - "github.com/alist-org/alist/v3/internal/conf" - "github.com/alist-org/alist/v3/internal/model" - "github.com/alist-org/alist/v3/pkg/utils" - "github.com/pkg/errors" - log "github.com/sirupsen/logrus" -) - -type SettingItemHook func(item *model.SettingItem) error - -var settingItemHooks = map[string]SettingItemHook{ - conf.VideoTypes: func(item *model.SettingItem) error { - conf.TypesMap[conf.VideoTypes] = strings.Split(item.Value, ",") - return nil - }, - conf.AudioTypes: func(item *model.SettingItem) error { - conf.TypesMap[conf.AudioTypes] = strings.Split(item.Value, ",") - return nil - }, - conf.ImageTypes: func(item *model.SettingItem) error { - conf.TypesMap[conf.ImageTypes] = strings.Split(item.Value, ",") - return nil - }, - conf.TextTypes: func(item *model.SettingItem) error { - conf.TypesMap[conf.TextTypes] = strings.Split(item.Value, ",") - return nil - }, - conf.ProxyTypes: func(item *model.SettingItem) error { - conf.TypesMap[conf.ProxyTypes] = strings.Split(item.Value, ",") - return nil - }, - - conf.PrivacyRegs: func(item *model.SettingItem) error { - regStrs := strings.Split(item.Value, "\n") - regs := make([]*regexp.Regexp, 0, len(regStrs)) - for _, regStr := range regStrs { - reg, err := regexp.Compile(regStr) - if err != nil { - return errors.WithStack(err) - } - regs = append(regs, reg) - } - conf.PrivacyReg = regs - return nil - }, - conf.FilenameCharMapping: func(item *model.SettingItem) error { - err := utils.Json.UnmarshalFromString(item.Value, &conf.FilenameCharMap) - if err != nil { - return err - } - log.Debugf("filename char mapping: %+v", conf.FilenameCharMap) - return nil - }, -} - -func HandleSettingItem(item *model.SettingItem) (bool, error) { - if hook, ok := settingItemHooks[item.Key]; ok { - return true, hook(item) - } - return false, nil -} - -func RegisterSettingItemHook(key string, hook SettingItemHook) { - settingItemHooks[key] = hook -} - -// func HandleSettingItems(items []model.SettingItem) error { -// for i := range items { -// if err := HandleSettingItem(&items[i]); err != nil { -// return err -// } -// } -// return nil -// } diff --git a/internal/db/settingitem.go b/internal/db/settingitem.go index 6cb88b40..2ba0c665 100644 --- a/internal/db/settingitem.go +++ b/internal/db/settingitem.go @@ -4,45 +4,9 @@ import ( "fmt" "github.com/alist-org/alist/v3/internal/model" - "github.com/alist-org/alist/v3/pkg/generic_sync" "github.com/pkg/errors" - log "github.com/sirupsen/logrus" ) -var settingsMap generic_sync.MapOf[string, string] -var publicSettingsMap generic_sync.MapOf[string, string] - -func settingsUpdate() { - settingsMap.Clear() - publicSettingsMap.Clear() -} - -func GetPublicSettingsMap() map[string]string { - if publicSettingsMap.Empty() { - settingItems, err := GetPublicSettingItems() - if err != nil { - log.Errorf("failed to get settingItems: %+v", err) - } - for _, settingItem := range settingItems { - publicSettingsMap.Store(settingItem.Key, settingItem.Value) - } - } - return publicSettingsMap.ToMap() -} - -func GetSettingsMap() *generic_sync.MapOf[string, string] { - if settingsMap.Empty() { - settingItems, err := GetSettingItems() - if err != nil { - log.Errorf("failed to get settingItems: %+v", err) - } - for _, settingItem := range settingItems { - settingsMap.Store(settingItem.Key, settingItem.Value) - } - } - return &settingsMap -} - func GetSettingItems() ([]model.SettingItem, error) { var settingItems []model.SettingItem if err := db.Find(&settingItems).Error; err != nil { @@ -59,18 +23,18 @@ func GetSettingItemByKey(key string) (*model.SettingItem, error) { return &settingItem, nil } -func GetSettingItemInKeys(keys []string) ([]model.SettingItem, error) { - var settingItem []model.SettingItem - if err := db.Where(fmt.Sprintf("%s in ?", columnName("key")), keys).Find(&settingItem).Error; err != nil { - return nil, errors.WithStack(err) - } - return settingItem, nil -} +// func GetSettingItemInKeys(keys []string) ([]model.SettingItem, error) { +// var settingItem []model.SettingItem +// if err := db.Where(fmt.Sprintf("%s in ?", columnName("key")), keys).Find(&settingItem).Error; err != nil { +// return nil, errors.WithStack(err) +// } +// return settingItem, nil +// } func GetPublicSettingItems() ([]model.SettingItem, error) { var settingItems []model.SettingItem if err := db.Where(fmt.Sprintf("%s in ?", columnName("flag")), []int{model.PUBLIC, model.READONLY}).Find(&settingItems).Error; err != nil { - return nil, err + return nil, errors.WithStack(err) } return settingItems, nil } @@ -91,58 +55,14 @@ func GetSettingItemsInGroups(groups []int) ([]model.SettingItem, error) { return settingItems, nil } -func SaveSettingItems(items []model.SettingItem) error { - others := make([]model.SettingItem, 0) - for i := range items { - if ok, err := HandleSettingItem(&items[i]); ok { - if err != nil { - return err - } else { - err = db.Save(items[i]).Error - if err != nil { - return errors.WithStack(err) - } - } - } else { - others = append(others, items[i]) - } - } - if len(others) > 0 { - err := db.Save(others).Error - if err != nil { - if len(others) < len(items) { - settingsUpdate() - } - return err - } - } - settingsUpdate() - return nil +func SaveSettingItems(items []model.SettingItem) (err error) { + return errors.WithStack(db.Save(items).Error) } -func SaveSettingItem(item model.SettingItem) error { - _, err := HandleSettingItem(&item) - if err != nil { - return err - } - err = db.Save(item).Error - if err == nil { - settingsUpdate() - } - return errors.WithStack(err) +func SaveSettingItem(item *model.SettingItem) error { + return errors.WithStack(db.Save(item).Error) } func DeleteSettingItemByKey(key string) error { - settingItem := model.SettingItem{ - Key: key, - } - old, err := GetSettingItemByKey(key) - if err != nil { - return errors.WithMessage(err, "failed to get settingItem") - } - if !old.IsDeprecated() { - return errors.Errorf("setting [%s] is not deprecated", key) - } - settingsUpdate() - return errors.WithStack(db.Delete(&settingItem).Error) + return errors.WithStack(db.Delete(&model.SettingItem{Key: key}).Error) } diff --git a/internal/db/user.go b/internal/db/user.go index 04bdfbaf..cc2d817f 100644 --- a/internal/db/user.go +++ b/internal/db/user.go @@ -1,61 +1,24 @@ package db import ( - "time" - - "github.com/Xhofe/go-cache" - "github.com/alist-org/alist/v3/internal/errs" "github.com/alist-org/alist/v3/internal/model" - "github.com/alist-org/alist/v3/pkg/singleflight" "github.com/pkg/errors" ) -var userCache = cache.NewMemCache(cache.WithShards[*model.User](2)) -var userG singleflight.Group[*model.User] -var guest *model.User -var admin *model.User - -func GetAdmin() (*model.User, error) { - if admin != nil { - return admin, nil - } - user := model.User{Role: model.ADMIN} +func GetUserByRole(role int) (*model.User, error) { + user := model.User{Role: role} if err := db.Where(user).Take(&user).Error; err != nil { return nil, err } - admin = &user - return &user, nil -} - -func GetGuest() (*model.User, error) { - if guest != nil { - return guest, nil - } - user := model.User{Role: model.GUEST} - if err := db.Where(user).Take(&user).Error; err != nil { - return nil, err - } - guest = &user return &user, nil } func GetUserByName(username string) (*model.User, error) { - if username == "" { - return nil, errors.WithStack(errs.EmptyUsername) + user := model.User{Username: username} + if err := db.Where(user).First(&user).Error; err != nil { + return nil, errors.Wrapf(err, "failed find user") } - user, ok := userCache.Get(username) - if ok { - return user, nil - } - user, err, _ := userG.Do(username, func() (*model.User, error) { - user := model.User{Username: username} - if err := db.Where(user).First(&user).Error; err != nil { - return nil, errors.Wrapf(err, "failed find user") - } - userCache.Set(username, &user, cache.WithEx[*model.User](time.Hour)) - return &user, nil - }) - return user, err + return &user, nil } func GetUserById(id uint) (*model.User, error) { @@ -71,40 +34,14 @@ func CreateUser(u *model.User) error { } func UpdateUser(u *model.User) error { - old, err := GetUserById(u.ID) - if err != nil { - return err - } - userCache.Del(old.Username) - if u.IsGuest() { - guest = nil - } - if u.IsAdmin() { - admin = nil - } return errors.WithStack(db.Save(u).Error) } -func Cancel2FAByUser(u *model.User) error { - u.OtpSecret = "" - return errors.WithStack(UpdateUser(u)) -} - -func Cancel2FAById(id uint) error { - user, err := GetUserById(id) - if err != nil { - return err - } - return Cancel2FAByUser(user) -} - -func GetUsers(pageIndex, pageSize int) ([]model.User, int64, error) { +func GetUsers(pageIndex, pageSize int) (users []model.User, count int64, err error) { userDB := db.Model(&model.User{}) - var count int64 if err := userDB.Count(&count).Error; err != nil { return nil, 0, errors.Wrapf(err, "failed get users count") } - var users []model.User if err := userDB.Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&users).Error; err != nil { return nil, 0, errors.Wrapf(err, "failed get find users") } @@ -112,13 +49,5 @@ func GetUsers(pageIndex, pageSize int) ([]model.User, int64, error) { } func DeleteUserById(id uint) error { - old, err := GetUserById(id) - if err != nil { - return err - } - if old.IsAdmin() || old.IsGuest() { - return errors.WithStack(errs.DeleteAdminOrGuest) - } - userCache.Del(old.Username) return errors.WithStack(db.Delete(&model.User{}, id).Error) } diff --git a/internal/fs/list.go b/internal/fs/list.go index 04521b92..0cdf0591 100644 --- a/internal/fs/list.go +++ b/internal/fs/list.go @@ -2,8 +2,6 @@ package fs import ( "context" - "regexp" - "strings" "github.com/alist-org/alist/v3/internal/model" "github.com/alist-org/alist/v3/internal/op" @@ -16,15 +14,15 @@ import ( func list(ctx context.Context, path string, refresh ...bool) ([]model.Obj, error) { meta := ctx.Value("meta").(*model.Meta) user := ctx.Value("user").(*model.User) - var objs []model.Obj - storage, actualPath, err := op.GetStorageAndActualPath(path) virtualFiles := op.GetStorageVirtualFilesByPath(path) - if err != nil { - if len(virtualFiles) == 0 { - return nil, errors.WithMessage(err, "failed get storage") - } - } else { - _objs, err := op.List(ctx, storage, actualPath, model.ListArgs{ + storage, actualPath, err := op.GetStorageAndActualPath(path) + if err != nil && len(virtualFiles) == 0 { + return nil, errors.WithMessage(err, "failed get storage") + } + + var _objs []model.Obj + if storage != nil { + _objs, err = op.List(ctx, storage, actualPath, model.ListArgs{ ReqPath: path, }, refresh...) if err != nil { @@ -33,21 +31,13 @@ func list(ctx context.Context, path string, refresh ...bool) ([]model.Obj, error return nil, errors.WithMessage(err, "failed get objs") } } - objs = make([]model.Obj, len(_objs)) - copy(objs, _objs) - } - if objs == nil { - objs = virtualFiles - } else { - for _, storageFile := range virtualFiles { - if !containsByName(objs, storageFile) { - objs = append(objs, storageFile) - } - } } + + om := model.NewObjMerge() if whetherHide(user, meta, path) { - objs = hide(objs, meta) + om.InitHideReg(meta.Hide) } + objs := om.Merge(virtualFiles, _objs...) // sort objs if storage != nil { if storage.Config().LocalSort { @@ -78,26 +68,3 @@ func whetherHide(user *model.User, meta *model.Meta, path string) bool { // if is guest, hide return true } - -func hide(objs []model.Obj, meta *model.Meta) []model.Obj { - var res []model.Obj - deleted := make([]bool, len(objs)) - rs := strings.Split(meta.Hide, "\n") - for _, r := range rs { - re := regexp.MustCompile(r) - for i, obj := range objs { - if deleted[i] { - continue - } - if re.MatchString(obj.GetName()) { - deleted[i] = true - } - } - } - for i, obj := range objs { - if !deleted[i] { - res = append(res, obj) - } - } - return res -} diff --git a/internal/fs/walk.go b/internal/fs/walk.go index 53d1aec0..2069b879 100644 --- a/internal/fs/walk.go +++ b/internal/fs/walk.go @@ -5,8 +5,8 @@ import ( "path" "path/filepath" - "github.com/alist-org/alist/v3/internal/db" "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/internal/op" ) // WalkFS traverses filesystem fs starting at name up to depth levels. @@ -26,7 +26,7 @@ func WalkFS(ctx context.Context, depth int, name string, info model.Obj, walkFn if !info.IsDir() || depth == 0 { return nil } - meta, _ := db.GetNearestMeta(name) + meta, _ := op.GetNearestMeta(name) // Read directory names. objs, err := List(context.WithValue(ctx, "meta", meta), name) if err != nil { diff --git a/internal/model/obj.go b/internal/model/obj.go index 3a069858..a81b318e 100644 --- a/internal/model/obj.go +++ b/internal/model/obj.go @@ -2,9 +2,13 @@ package model import ( "io" + "regexp" "sort" + "strings" "time" + mapset "github.com/deckarep/golang-set/v2" + "github.com/maruel/natural" ) @@ -100,3 +104,50 @@ func WrapObjsName(objs []Obj) { objs[i] = &ObjWrapName{Obj: objs[i]} } } + +func NewObjMerge() *ObjMerge { + return &ObjMerge{ + set: mapset.NewSet[string](), + } +} + +type ObjMerge struct { + regs []*regexp.Regexp + set mapset.Set[string] +} + +func (om *ObjMerge) Merge(objs []Obj, objs_ ...Obj) []Obj { + newObjs := make([]Obj, 0, len(objs)+len(objs_)) + newObjs = om.insertObjs(om.insertObjs(newObjs, objs...), objs_...) + return newObjs +} + +func (om *ObjMerge) insertObjs(objs []Obj, objs_ ...Obj) []Obj { + for _, obj := range objs_ { + if om.clickObj(obj) { + objs = append(objs, obj) + } + } + return objs +} + +func (om *ObjMerge) clickObj(obj Obj) bool { + for _, reg := range om.regs { + if reg.MatchString(obj.GetName()) { + return false + } + } + return om.set.Add(obj.GetName()) +} + +func (om *ObjMerge) InitHideReg(hides string) { + rs := strings.Split(hides, "\n") + om.regs = make([]*regexp.Regexp, 0, len(rs)) + for _, r := range rs { + om.regs = append(om.regs, regexp.MustCompile(r)) + } +} + +func (om *ObjMerge) Reset() { + om.set.Clear() +} diff --git a/internal/op/hook.go b/internal/op/hook.go index 7c624e9e..bf0e0df3 100644 --- a/internal/op/hook.go +++ b/internal/op/hook.go @@ -1,7 +1,17 @@ package op -import "github.com/alist-org/alist/v3/internal/model" +import ( + "regexp" + "strings" + "github.com/alist-org/alist/v3/internal/conf" + "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/pkg/utils" + "github.com/pkg/errors" + log "github.com/sirupsen/logrus" +) + +// Obj type ObjsUpdateHook = func(parent string, objs []model.Obj) var ( @@ -11,3 +21,78 @@ var ( func RegisterObjsUpdateHook(hook ObjsUpdateHook) { objsUpdateHooks = append(objsUpdateHooks, hook) } + +func HandleObjsUpdateHook(parent string, objs []model.Obj) { + for _, hook := range objsUpdateHooks { + hook(parent, objs) + } +} + +// Setting +type SettingItemHook func(item *model.SettingItem) error + +var settingItemHooks = map[string]SettingItemHook{ + conf.VideoTypes: func(item *model.SettingItem) error { + conf.TypesMap[conf.VideoTypes] = strings.Split(item.Value, ",") + return nil + }, + conf.AudioTypes: func(item *model.SettingItem) error { + conf.TypesMap[conf.AudioTypes] = strings.Split(item.Value, ",") + return nil + }, + conf.ImageTypes: func(item *model.SettingItem) error { + conf.TypesMap[conf.ImageTypes] = strings.Split(item.Value, ",") + return nil + }, + conf.TextTypes: func(item *model.SettingItem) error { + conf.TypesMap[conf.TextTypes] = strings.Split(item.Value, ",") + return nil + }, + conf.ProxyTypes: func(item *model.SettingItem) error { + conf.TypesMap[conf.ProxyTypes] = strings.Split(item.Value, ",") + return nil + }, + + conf.PrivacyRegs: func(item *model.SettingItem) error { + regStrs := strings.Split(item.Value, "\n") + regs := make([]*regexp.Regexp, 0, len(regStrs)) + for _, regStr := range regStrs { + reg, err := regexp.Compile(regStr) + if err != nil { + return errors.WithStack(err) + } + regs = append(regs, reg) + } + conf.PrivacyReg = regs + return nil + }, + conf.FilenameCharMapping: func(item *model.SettingItem) error { + err := utils.Json.UnmarshalFromString(item.Value, &conf.FilenameCharMap) + if err != nil { + return err + } + log.Debugf("filename char mapping: %+v", conf.FilenameCharMap) + return nil + }, +} + +func RegisterSettingItemHook(key string, hook SettingItemHook) { + settingItemHooks[key] = hook +} + +func HandleSettingItemHook(item *model.SettingItem) (hasHook bool, err error) { + if hook, ok := settingItemHooks[item.Key]; ok { + return true, hook(item) + } + return false, nil +} + +//func HandleSettingItemsHook(items []model.SettingItem) (err error) { +// for i := 0; i < len(items); i++ { +// _, err = HandleSettingItemHook(&items[i]) +// if err != nil { +// return err +// } +// } +// return nil +//} diff --git a/internal/op/meta.go b/internal/op/meta.go new file mode 100644 index 00000000..af14f395 --- /dev/null +++ b/internal/op/meta.go @@ -0,0 +1,88 @@ +package op + +import ( + stdpath "path" + "time" + + "github.com/Xhofe/go-cache" + "github.com/alist-org/alist/v3/internal/db" + "github.com/alist-org/alist/v3/internal/errs" + "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/pkg/singleflight" + "github.com/alist-org/alist/v3/pkg/utils" + "github.com/pkg/errors" + "gorm.io/gorm" +) + +var metaCache = cache.NewMemCache(cache.WithShards[*model.Meta](2)) + +// metaG maybe not needed +var metaG singleflight.Group[*model.Meta] + +func GetNearestMeta(path string) (*model.Meta, error) { + return getNearestMeta(utils.FixAndCleanPath(path)) +} +func getNearestMeta(path string) (*model.Meta, error) { + meta, err := GetMetaByPath(path) + if err == nil { + return meta, nil + } + if errors.Cause(err) != gorm.ErrRecordNotFound { + return nil, err + } + if path == "/" { + return nil, errs.MetaNotFound + } + return getNearestMeta(stdpath.Dir(path)) +} + +func GetMetaByPath(path string) (*model.Meta, error) { + return getMetaByPath(utils.FixAndCleanPath(path)) +} +func getMetaByPath(path string) (*model.Meta, error) { + meta, ok := metaCache.Get(path) + if ok { + return meta, nil + } + meta, err, _ := metaG.Do(path, func() (*model.Meta, error) { + _meta, err := db.GetMetaByPath(path) + if err != nil { + return nil, err + } + metaCache.Set(path, _meta, cache.WithEx[*model.Meta](time.Hour)) + return _meta, nil + }) + return meta, err +} + +func DeleteMetaById(id uint) error { + old, err := db.GetMetaById(id) + if err != nil { + return err + } + metaCache.Del(old.Path) + return db.DeleteMetaById(id) +} + +func UpdateMeta(u *model.Meta) error { + u.Path = utils.FixAndCleanPath(u.Path) + old, err := db.GetMetaById(u.ID) + if err != nil { + return err + } + metaCache.Del(old.Path) + return db.UpdateMeta(u) +} + +func CreateMeta(u *model.Meta) error { + u.Path = utils.FixAndCleanPath(u.Path) + return db.CreateMeta(u) +} + +func GetMetaById(id uint) (*model.Meta, error) { + return db.GetMetaById(id) +} + +func GetMetas(pageIndex, pageSize int) (metas []model.Meta, count int64, err error) { + return db.GetMetas(pageIndex, pageSize) +} diff --git a/internal/op/path.go b/internal/op/path.go index 9909fbc2..6e3dfdf7 100644 --- a/internal/op/path.go +++ b/internal/op/path.go @@ -19,7 +19,7 @@ func GetStorageAndActualPath(rawPath string) (storage driver.Driver, actualPath return } log.Debugln("use storage: ", storage.GetStorage().MountPath) - virtualPath := utils.GetActualVirtualPath(storage.GetStorage().MountPath) - actualPath = utils.FixAndCleanPath(strings.TrimPrefix(rawPath, virtualPath)) + mountPath := utils.GetActualMountPath(storage.GetStorage().MountPath) + actualPath = utils.FixAndCleanPath(strings.TrimPrefix(rawPath, mountPath)) return } diff --git a/internal/op/setting.go b/internal/op/setting.go new file mode 100644 index 00000000..83d19c12 --- /dev/null +++ b/internal/op/setting.go @@ -0,0 +1,198 @@ +package op + +import ( + "sort" + "strconv" + "strings" + "time" + + "github.com/Xhofe/go-cache" + "github.com/alist-org/alist/v3/internal/db" + "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/pkg/singleflight" + "github.com/alist-org/alist/v3/pkg/utils" + "github.com/pkg/errors" +) + +var settingCache = cache.NewMemCache(cache.WithShards[*model.SettingItem](4)) +var settingG singleflight.Group[*model.SettingItem] +var settingCacheF = func(item *model.SettingItem) { + settingCache.Set(item.Key, item, cache.WithEx[*model.SettingItem](time.Hour)) +} + +var settingGroupCache = cache.NewMemCache(cache.WithShards[[]model.SettingItem](4)) +var settingGroupG singleflight.Group[[]model.SettingItem] +var settingGroupCacheF = func(key string, item []model.SettingItem) { + settingGroupCache.Set(key, item, cache.WithEx[[]model.SettingItem](time.Hour)) +} + +func settingCacheUpdate() { + settingCache.Clear() + settingGroupCache.Clear() +} + +func GetPublicSettingsMap() map[string]string { + items, _ := GetPublicSettingItems() + pSettings := make(map[string]string) + for _, item := range items { + pSettings[item.Key] = item.Value + } + return pSettings +} + +func GetSettingsMap() map[string]string { + items, _ := GetSettingItems() + settings := make(map[string]string) + for _, item := range items { + settings[item.Key] = item.Value + } + return settings +} + +func GetSettingItems() ([]model.SettingItem, error) { + if items, ok := settingGroupCache.Get("ALL_SETTING_ITEMS"); ok { + return items, nil + } + items, err, _ := settingGroupG.Do("ALL_SETTING_ITEMS", func() ([]model.SettingItem, error) { + _items, err := db.GetSettingItems() + if err != nil { + return nil, err + } + settingGroupCacheF("ALL_SETTING_ITEMS", _items) + return _items, nil + }) + return items, err +} + +func GetPublicSettingItems() ([]model.SettingItem, error) { + if items, ok := settingGroupCache.Get("ALL_PUBLIC_SETTING_ITEMS"); ok { + return items, nil + } + items, err, _ := settingGroupG.Do("ALL_PUBLIC_SETTING_ITEMS", func() ([]model.SettingItem, error) { + _items, err := db.GetPublicSettingItems() + if err != nil { + return nil, err + } + settingGroupCacheF("ALL_PUBLIC_SETTING_ITEMS", _items) + return _items, nil + }) + return items, err +} + +func GetSettingItemByKey(key string) (*model.SettingItem, error) { + if item, ok := settingCache.Get(key); ok { + return item, nil + } + + item, err, _ := settingG.Do(key, func() (*model.SettingItem, error) { + _item, err := db.GetSettingItemByKey(key) + if err != nil { + return nil, err + } + settingCacheF(_item) + return _item, nil + }) + return item, err +} + +func GetSettingItemInKeys(keys []string) ([]model.SettingItem, error) { + var items []model.SettingItem + for _, key := range keys { + item, err := GetSettingItemByKey(key) + if err != nil { + return nil, err + } + items = append(items, *item) + } + return items, nil +} + +func GetSettingItemsByGroup(group int) ([]model.SettingItem, error) { + key := strconv.Itoa(group) + if items, ok := settingGroupCache.Get(key); ok { + return items, nil + } + items, err, _ := settingGroupG.Do(key, func() ([]model.SettingItem, error) { + _items, err := db.GetSettingItemsByGroup(group) + if err != nil { + return nil, err + } + settingGroupCacheF(key, _items) + return _items, nil + }) + return items, err +} + +func GetSettingItemsInGroups(groups []int) ([]model.SettingItem, error) { + sort.Ints(groups) + key := strings.Join(utils.MustSliceConvert(groups, func(i int) string { + return strconv.Itoa(i) + }), ",") + + if items, ok := settingGroupCache.Get(key); ok { + return items, nil + } + items, err, _ := settingGroupG.Do(key, func() ([]model.SettingItem, error) { + _items, err := db.GetSettingItemsInGroups(groups) + if err != nil { + return nil, err + } + settingGroupCacheF(key, _items) + return _items, nil + }) + return items, err +} + +func SaveSettingItems(items []model.SettingItem) error { + noHookItems := make([]model.SettingItem, 0) + errs := make([]error, 0) + for i := range items { + if ok, err := HandleSettingItemHook(&items[i]); ok { + if err != nil { + errs = append(errs, err) + } else { + err = db.SaveSettingItem(&items[i]) + if err != nil { + errs = append(errs, err) + } + } + } else { + noHookItems = append(noHookItems, items[i]) + } + } + if len(noHookItems) > 0 { + err := db.SaveSettingItems(noHookItems) + if err != nil { + errs = append(errs, err) + } + } + if len(errs) < len(items)-len(noHookItems)+1 { + settingCacheUpdate() + } + return utils.MergeErrors(errs...) +} + +func SaveSettingItem(item *model.SettingItem) (err error) { + // hook + if _, err := HandleSettingItemHook(item); err != nil { + return err + } + // update + if err = db.SaveSettingItem(item); err != nil { + return err + } + settingCacheUpdate() + return nil +} + +func DeleteSettingItemByKey(key string) error { + old, err := GetSettingItemByKey(key) + if err != nil { + return errors.WithMessage(err, "failed to get settingItem") + } + if !old.IsDeprecated() { + return errors.Errorf("setting [%s] is not deprecated", key) + } + settingCacheUpdate() + return db.DeleteSettingItemByKey(key) +} diff --git a/internal/op/storage.go b/internal/op/storage.go index 20006ca2..fc96490d 100644 --- a/internal/op/storage.go +++ b/internal/op/storage.go @@ -29,7 +29,7 @@ func HasStorage(mountPath string) bool { return storagesMap.Has(utils.FixAndCleanPath(mountPath)) } -func GetStorageByVirtualPath(virtualPath string) (driver.Driver, error) { +func GetStorageByMountPath(virtualPath string) (driver.Driver, error) { virtualPath = utils.FixAndCleanPath(virtualPath) storageDriver, ok := storagesMap.Load(virtualPath) if !ok { @@ -130,7 +130,7 @@ func DisableStorage(ctx context.Context, id uint) error { if storage.Disabled { return errors.Errorf("this storage have disabled") } - storageDriver, err := GetStorageByVirtualPath(storage.MountPath) + storageDriver, err := GetStorageByMountPath(storage.MountPath) if err != nil { return errors.WithMessage(err, "failed get storage driver") } @@ -168,7 +168,7 @@ func UpdateStorage(ctx context.Context, storage model.Storage) error { if storage.Disabled { return nil } - storageDriver, err := GetStorageByVirtualPath(oldStorage.MountPath) + storageDriver, err := GetStorageByMountPath(oldStorage.MountPath) if oldStorage.MountPath != storage.MountPath { // mount path renamed, need to drop the storage storagesMap.Delete(oldStorage.MountPath) @@ -192,7 +192,7 @@ func DeleteStorageById(ctx context.Context, id uint) error { return errors.WithMessage(err, "failed get storage") } if !storage.Disabled { - storageDriver, err := GetStorageByVirtualPath(storage.MountPath) + storageDriver, err := GetStorageByMountPath(storage.MountPath) if err != nil { return errors.WithMessage(err, "failed get storage driver") } @@ -221,11 +221,11 @@ func MustSaveDriverStorage(driver driver.Driver) { func saveDriverStorage(driver driver.Driver) error { storage := driver.GetStorage() addition := driver.GetAddition() - strs, err := utils.Json.MarshalToString(addition) + str, err := utils.Json.MarshalToString(addition) if err != nil { return errors.Wrap(err, "error while marshal addition") } - storage.Addition = strs + storage.Addition = str err = db.UpdateStorage(storage) if err != nil { return errors.WithMessage(err, "failed update storage in database") @@ -240,10 +240,10 @@ func getStoragesByPath(path string) []driver.Driver { storages := make([]driver.Driver, 0) curSlashCount := 0 storagesMap.Range(func(mountPath string, value driver.Driver) bool { - virtualPath := utils.GetActualVirtualPath(mountPath) + mountPath = utils.GetActualMountPath(mountPath) // is this path - if strings.HasPrefix(path, virtualPath) { - slashCount := strings.Count(utils.PathAddSeparatorSuffix(virtualPath), "/") + if utils.IsSubPath(path, mountPath) { + slashCount := strings.Count(utils.PathAddSeparatorSuffix(mountPath), "/") // not the longest match if slashCount > curSlashCount { storages = storages[:0] @@ -278,13 +278,12 @@ func GetStorageVirtualFilesByPath(prefix string) []model.Obj { prefix = utils.FixAndCleanPath(prefix) set := mapset.NewSet[string]() for _, v := range storages { - virtualPath := utils.GetActualVirtualPath(v.GetStorage().MountPath) + mountPath := utils.GetActualMountPath(v.GetStorage().MountPath) // Exclude prefix itself and non prefix - if len(prefix) >= len(virtualPath) || !strings.HasPrefix(virtualPath, prefix) { + if len(prefix) >= len(mountPath) || !utils.IsSubPath(mountPath, prefix) { continue } - - name := strings.SplitN(strings.TrimPrefix(virtualPath[len(prefix):], "/"), "/", 1)[0] + name := strings.SplitN(strings.TrimPrefix(mountPath[len(prefix):], "/"), "/", 2)[0] if set.Add(name) { files = append(files, &model.Object{ Name: name, @@ -310,7 +309,7 @@ func GetBalancedStorage(path string) driver.Driver { case 1: return storages[0] default: - virtualPath := utils.GetActualVirtualPath(storages[0].GetStorage().MountPath) + virtualPath := utils.GetActualMountPath(storages[0].GetStorage().MountPath) i, _ := balanceMap.LoadOrStore(virtualPath, 0) i = (i + 1) % storageNum balanceMap.Store(virtualPath, i) diff --git a/internal/op/storage_test.go b/internal/op/storage_test.go index 390fb0d0..f3d0b4e6 100644 --- a/internal/op/storage_test.go +++ b/internal/op/storage_test.go @@ -4,10 +4,12 @@ import ( "context" "testing" + "github.com/alist-org/alist/v3/internal/conf" "github.com/alist-org/alist/v3/internal/db" "github.com/alist-org/alist/v3/internal/model" "github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/pkg/utils" + mapset "github.com/deckarep/golang-set/v2" "gorm.io/driver/sqlite" "gorm.io/gorm" ) @@ -17,6 +19,7 @@ func init() { if err != nil { panic("failed to connect database") } + conf.Conf = conf.DefaultConfig() db.Init(dB) } @@ -25,9 +28,9 @@ func TestCreateStorage(t *testing.T) { storage model.Storage isErr bool }{ - {storage: model.Storage{Driver: "Local", MountPath: "/local", Addition: `{"root_folder":"."}`}, isErr: false}, - {storage: model.Storage{Driver: "Local", MountPath: "/local", Addition: `{"root_folder":"."}`}, isErr: true}, - {storage: model.Storage{Driver: "None", MountPath: "/none", Addition: `{"root_folder":"."}`}, isErr: true}, + {storage: model.Storage{Driver: "Local", MountPath: "/local", Addition: `{"root_folder_path":"."}`}, isErr: false}, + {storage: model.Storage{Driver: "Local", MountPath: "/local", Addition: `{"root_folder_path":"."}`}, isErr: true}, + {storage: model.Storage{Driver: "None", MountPath: "/none", Addition: `{"root_folder_path":"."}`}, isErr: true}, } for _, storage := range storages { _, err := op.CreateStorage(context.Background(), storage.storage) @@ -58,23 +61,26 @@ func TestGetStorageVirtualFilesByPath(t *testing.T) { func TestGetBalancedStorage(t *testing.T) { setupStorages(t) - storage := op.GetBalancedStorage("/a/d/e") - if storage.GetStorage().MountPath != "/a/d/e" { - t.Errorf("expected: /a/d/e, got: %+v", storage.GetStorage().MountPath) + set := mapset.NewSet[string]() + for i := 0; i < 5; i++ { + storage := op.GetBalancedStorage("/a/d/e1") + set.Add(storage.GetStorage().MountPath) } - storage = op.GetBalancedStorage("/a/d/e") - if storage.GetStorage().MountPath != "/a/d/e.balance" { - t.Errorf("expected: /a/d/e.balance, got: %+v", storage.GetStorage().MountPath) + expected := mapset.NewSet([]string{"/a/d/e1", "/a/d/e1.balance"}...) + if !expected.Equal(set) { + t.Errorf("expected: %+v, got: %+v", expected, set) } } func setupStorages(t *testing.T) { var storages = []model.Storage{ - {Driver: "Local", MountPath: "/a/b", Order: 0, Addition: `{"root_folder":"."}`}, - {Driver: "Local", MountPath: "/a/c", Order: 1, Addition: `{"root_folder":"."}`}, - {Driver: "Local", MountPath: "/a/d", Order: 2, Addition: `{"root_folder":"."}`}, - {Driver: "Local", MountPath: "/a/d/e", Order: 3, Addition: `{"root_folder":"."}`}, - {Driver: "Local", MountPath: "/a/d/e.balance", Order: 4, Addition: `{"root_folder":"."}`}, + {Driver: "Local", MountPath: "/a/b", Order: 0, Addition: `{"root_folder_path":"."}`}, + {Driver: "Local", MountPath: "/adc", Order: 0, Addition: `{"root_folder_path":"."}`}, + {Driver: "Local", MountPath: "/a/c", Order: 1, Addition: `{"root_folder_path":"."}`}, + {Driver: "Local", MountPath: "/a/d", Order: 2, Addition: `{"root_folder_path":"."}`}, + {Driver: "Local", MountPath: "/a/d/e1", Order: 3, Addition: `{"root_folder_path":"."}`}, + {Driver: "Local", MountPath: "/a/d/e", Order: 4, Addition: `{"root_folder_path":"."}`}, + {Driver: "Local", MountPath: "/a/d/e1.balance", Order: 4, Addition: `{"root_folder_path":"."}`}, } for _, storage := range storages { _, err := op.CreateStorage(context.Background(), storage) diff --git a/internal/op/user.go b/internal/op/user.go new file mode 100644 index 00000000..a0bbc3ed --- /dev/null +++ b/internal/op/user.go @@ -0,0 +1,115 @@ +package op + +import ( + "time" + + "github.com/Xhofe/go-cache" + "github.com/alist-org/alist/v3/internal/db" + "github.com/alist-org/alist/v3/internal/errs" + "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/pkg/singleflight" + "github.com/alist-org/alist/v3/pkg/utils" +) + +var userCache = cache.NewMemCache(cache.WithShards[*model.User](2)) +var userG singleflight.Group[*model.User] +var guestUser *model.User +var adminUser *model.User + +func GetAdmin() (*model.User, error) { + if adminUser == nil { + user, err := db.GetUserByRole(model.ADMIN) + if err != nil { + return nil, err + } + adminUser = user + } + return adminUser, nil +} + +func GetGuest() (*model.User, error) { + if guestUser == nil { + user, err := db.GetUserByRole(model.GUEST) + if err != nil { + return nil, err + } + guestUser = user + } + return guestUser, nil +} + +func GetUserByRole(role int) (*model.User, error) { + return db.GetUserByRole(role) +} + +func GetUserByName(username string) (*model.User, error) { + if username == "" { + return nil, errs.EmptyUsername + } + if user, ok := userCache.Get(username); ok { + return user, nil + } + user, err, _ := userG.Do(username, func() (*model.User, error) { + _user, err := db.GetUserByName(username) + if err != nil { + return nil, err + } + userCache.Set(username, _user, cache.WithEx[*model.User](time.Hour)) + return _user, nil + }) + return user, err +} + +func GetUserById(id uint) (*model.User, error) { + return db.GetUserById(id) +} + +func GetUsers(pageIndex, pageSize int) (users []model.User, count int64, err error) { + return db.GetUsers(pageIndex, pageSize) +} + +func CreateUser(u *model.User) error { + u.BasePath = utils.FixAndCleanPath(u.BasePath) + return db.CreateUser(u) +} + +func DeleteUserById(id uint) error { + old, err := db.GetUserById(id) + if err != nil { + return err + } + if old.IsAdmin() || old.IsGuest() { + return errs.DeleteAdminOrGuest + } + userCache.Del(old.Username) + return db.DeleteUserById(id) +} + +func UpdateUser(u *model.User) error { + old, err := db.GetUserById(u.ID) + if err != nil { + return err + } + if u.IsAdmin() { + adminUser = nil + } + if u.IsGuest() { + guestUser = nil + } + userCache.Del(old.Username) + u.BasePath = utils.FixAndCleanPath(u.BasePath) + return db.UpdateUser(u) +} + +func Cancel2FAByUser(u *model.User) error { + u.OtpSecret = "" + return UpdateUser(u) +} + +func Cancel2FAById(id uint) error { + user, err := db.GetUserById(id) + if err != nil { + return err + } + return Cancel2FAByUser(user) +} diff --git a/internal/search/build.go b/internal/search/build.go index 19c4a806..53b944f7 100644 --- a/internal/search/build.go +++ b/internal/search/build.go @@ -8,7 +8,6 @@ import ( "sync/atomic" "time" - "github.com/alist-org/alist/v3/internal/db" "github.com/alist-org/alist/v3/internal/fs" "github.com/alist-org/alist/v3/internal/model" "github.com/alist-org/alist/v3/internal/op" @@ -105,7 +104,7 @@ func BuildIndex(ctx context.Context, indexPaths, ignorePaths []string, maxDepth Quit <- struct{}{} } }() - admin, err := db.GetAdmin() + admin, err := op.GetAdmin() if err != nil { return err } diff --git a/internal/search/search.go b/internal/search/search.go index d9c208d0..c1a23b85 100644 --- a/internal/search/search.go +++ b/internal/search/search.go @@ -5,9 +5,9 @@ import ( "fmt" "github.com/alist-org/alist/v3/internal/conf" - "github.com/alist-org/alist/v3/internal/db" "github.com/alist-org/alist/v3/internal/errs" "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/internal/search/searcher" log "github.com/sirupsen/logrus" ) @@ -88,7 +88,7 @@ func BatchIndex(ctx context.Context, objs []ObjWithParent) error { } func init() { - db.RegisterSettingItemHook(conf.SearchIndex, func(item *model.SettingItem) error { + op.RegisterSettingItemHook(conf.SearchIndex, func(item *model.SettingItem) error { log.Debugf("searcher init, mode: %s", item.Value) return Init(item.Value) }) diff --git a/internal/search/util.go b/internal/search/util.go index 709dab29..cfb98c45 100644 --- a/internal/search/util.go +++ b/internal/search/util.go @@ -6,7 +6,6 @@ import ( "github.com/alist-org/alist/v3/drivers/alist_v3" "github.com/alist-org/alist/v3/drivers/base" "github.com/alist-org/alist/v3/internal/conf" - "github.com/alist-org/alist/v3/internal/db" "github.com/alist-org/alist/v3/internal/model" "github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/internal/setting" @@ -26,7 +25,7 @@ func WriteProgress(progress *model.IndexProgress) { if err != nil { log.Errorf("marshal progress error: %+v", err) } - err = db.SaveSettingItem(model.SettingItem{ + err = op.SaveSettingItem(&model.SettingItem{ Key: conf.IndexProgress, Value: p, Type: conf.TypeText, diff --git a/internal/setting/setting.go b/internal/setting/setting.go index 2861380a..cd77874b 100644 --- a/internal/setting/setting.go +++ b/internal/setting/setting.go @@ -3,18 +3,18 @@ package setting import ( "strconv" - "github.com/alist-org/alist/v3/internal/db" + "github.com/alist-org/alist/v3/internal/op" ) func GetStr(key string, defaultValue ...string) string { - val, ok := db.GetSettingsMap().Load(key) - if !ok { + val, _ := op.GetSettingItemByKey(key) + if val == nil { if len(defaultValue) > 0 { return defaultValue[0] } return "" } - return val + return val.Value } func GetInt(key string, defaultVal int) int { diff --git a/pkg/utils/balance.go b/pkg/utils/balance.go index 265c45f0..e6df65c9 100644 --- a/pkg/utils/balance.go +++ b/pkg/utils/balance.go @@ -8,8 +8,8 @@ func IsBalance(str string) bool { return strings.Contains(str, balance) } -// GetActualVirtualPath remove balance suffix -func GetActualVirtualPath(virtualPath string) string { +// GetActualMountPath remove balance suffix +func GetActualMountPath(virtualPath string) string { bIndex := strings.LastIndex(virtualPath, ".balance") if bIndex != -1 { virtualPath = virtualPath[:bIndex] diff --git a/pkg/utils/path.go b/pkg/utils/path.go index 27328fbb..45fe200e 100644 --- a/pkg/utils/path.go +++ b/pkg/utils/path.go @@ -4,6 +4,8 @@ import ( "net/url" stdpath "path" "strings" + + "github.com/alist-org/alist/v3/internal/errs" ) // FixAndCleanPath @@ -36,6 +38,11 @@ func PathEqual(path1, path2 string) bool { return FixAndCleanPath(path1) == FixAndCleanPath(path2) } +func IsSubPath(path string, subPath string) bool { + path, subPath = FixAndCleanPath(path), FixAndCleanPath(subPath) + return path == subPath || strings.HasPrefix(path, subPath+"/") +} + func Ext(path string) string { ext := stdpath.Ext(path) if strings.HasPrefix(ext, ".") { @@ -68,5 +75,8 @@ func EncodePath(path string, all ...bool) string { } func JoinBasePath(basePath, reqPath string) (string, error) { + if strings.HasSuffix(reqPath, "..") || strings.Contains(reqPath, "../") { + return "", errs.RelativePath + } return stdpath.Join(FixAndCleanPath(basePath), FixAndCleanPath(reqPath)), nil } diff --git a/pkg/utils/slice.go b/pkg/utils/slice.go index c1d1584c..a9733eb2 100644 --- a/pkg/utils/slice.go +++ b/pkg/utils/slice.go @@ -1,5 +1,11 @@ package utils +import ( + "strings" + + "github.com/pkg/errors" +) + // SliceEqual check if two slices are equal func SliceEqual[T comparable](a, b []T) bool { if len(a) != len(b) { @@ -44,3 +50,13 @@ func MustSliceConvert[S any, D any](srcS []S, convert func(src S) D) []D { } return res } + +func MergeErrors(errs ...error) error { + errStr := strings.Join(MustSliceConvert(errs, func(err error) string { + return err.Error() + }), "\n") + if errStr != "" { + return errors.New(errStr) + } + return nil +} diff --git a/server/handles/aria2.go b/server/handles/aria2.go index 9948a90a..f127bf04 100644 --- a/server/handles/aria2.go +++ b/server/handles/aria2.go @@ -3,8 +3,8 @@ package handles import ( "github.com/alist-org/alist/v3/internal/aria2" "github.com/alist-org/alist/v3/internal/conf" - "github.com/alist-org/alist/v3/internal/db" "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/server/common" "github.com/gin-gonic/gin" ) @@ -24,7 +24,7 @@ func SetAria2(c *gin.Context) { {Key: conf.Aria2Uri, Value: req.Uri, Type: conf.TypeString, Group: model.ARIA2, Flag: model.PRIVATE}, {Key: conf.Aria2Secret, Value: req.Secret, Type: conf.TypeString, Group: model.ARIA2, Flag: model.PRIVATE}, } - if err := db.SaveSettingItems(items); err != nil { + if err := op.SaveSettingItems(items); err != nil { common.ErrorResp(c, err, 500) return } diff --git a/server/handles/auth.go b/server/handles/auth.go index 0ecd52d8..920b7d75 100644 --- a/server/handles/auth.go +++ b/server/handles/auth.go @@ -7,8 +7,8 @@ import ( "time" "github.com/Xhofe/go-cache" - "github.com/alist-org/alist/v3/internal/db" "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/server/common" "github.com/gin-gonic/gin" "github.com/pquerna/otp/totp" @@ -41,7 +41,7 @@ func Login(c *gin.Context) { common.ErrorResp(c, err, 400) return } - user, err := db.GetUserByName(req.Username) + user, err := op.GetUserByName(req.Username) if err != nil { common.ErrorResp(c, err, 400) loginCache.Set(ip, count+1) @@ -101,7 +101,7 @@ func UpdateCurrent(c *gin.Context) { if req.Password != "" { user.Password = req.Password } - if err := db.UpdateUser(user); err != nil { + if err := op.UpdateUser(user); err != nil { common.ErrorResp(c, err, 500) } else { common.SuccessResp(c) @@ -158,7 +158,7 @@ func Verify2FA(c *gin.Context) { return } user.OtpSecret = req.Secret - if err := db.UpdateUser(user); err != nil { + if err := op.UpdateUser(user); err != nil { common.ErrorResp(c, err, 500) } else { common.SuccessResp(c) diff --git a/server/handles/fsmanage.go b/server/handles/fsmanage.go index 1cfa44e9..7b95af5b 100644 --- a/server/handles/fsmanage.go +++ b/server/handles/fsmanage.go @@ -4,10 +4,10 @@ import ( "fmt" stdpath "path" - "github.com/alist-org/alist/v3/internal/db" "github.com/alist-org/alist/v3/internal/errs" "github.com/alist-org/alist/v3/internal/fs" "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/internal/sign" "github.com/alist-org/alist/v3/pkg/utils" "github.com/alist-org/alist/v3/server/common" @@ -32,7 +32,7 @@ func FsMkdir(c *gin.Context) { return } if !user.CanWrite() { - meta, err := db.GetNearestMeta(stdpath.Dir(reqPath)) + meta, err := op.GetNearestMeta(stdpath.Dir(reqPath)) if err != nil { if !errors.Is(errors.Cause(err), errs.MetaNotFound) { common.ErrorResp(c, err, 500, true) diff --git a/server/handles/fsread.go b/server/handles/fsread.go index aaa90e81..4d4d617a 100644 --- a/server/handles/fsread.go +++ b/server/handles/fsread.go @@ -6,10 +6,10 @@ import ( "strings" "time" - "github.com/alist-org/alist/v3/internal/db" "github.com/alist-org/alist/v3/internal/errs" "github.com/alist-org/alist/v3/internal/fs" "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/internal/sign" "github.com/alist-org/alist/v3/pkg/utils" "github.com/alist-org/alist/v3/server/common" @@ -61,7 +61,7 @@ func FsList(c *gin.Context) { common.ErrorResp(c, err, 403) return } - meta, err := db.GetNearestMeta(reqPath) + meta, err := op.GetNearestMeta(reqPath) if err != nil { if !errors.Is(errors.Cause(err), errs.MetaNotFound) { common.ErrorResp(c, err, 500, true) @@ -118,7 +118,7 @@ func FsDirs(c *gin.Context) { } reqPath = tmp } - meta, err := db.GetNearestMeta(reqPath) + meta, err := op.GetNearestMeta(reqPath) if err != nil { if !errors.Is(errors.Cause(err), errs.MetaNotFound) { common.ErrorResp(c, err, 500, true) @@ -233,7 +233,7 @@ func FsGet(c *gin.Context) { common.ErrorResp(c, err, 403) return } - meta, err := db.GetNearestMeta(reqPath) + meta, err := op.GetNearestMeta(reqPath) if err != nil { if !errors.Is(errors.Cause(err), errs.MetaNotFound) { common.ErrorResp(c, err, 500) @@ -295,7 +295,7 @@ func FsGet(c *gin.Context) { if err == nil { related = filterRelated(sameLevelFiles, obj) } - parentMeta, _ := db.GetNearestMeta(parentPath) + parentMeta, _ := op.GetNearestMeta(parentPath) common.SuccessResp(c, FsGetResp{ ObjResp: ObjResp{ Name: obj.GetName(), @@ -344,7 +344,7 @@ func FsOther(c *gin.Context) { common.ErrorResp(c, err, 403) return } - meta, err := db.GetNearestMeta(req.Path) + meta, err := op.GetNearestMeta(req.Path) if err != nil { if !errors.Is(errors.Cause(err), errs.MetaNotFound) { common.ErrorResp(c, err, 500) diff --git a/server/handles/meta.go b/server/handles/meta.go index 34825907..e7454d9d 100644 --- a/server/handles/meta.go +++ b/server/handles/meta.go @@ -6,9 +6,8 @@ import ( "strconv" "strings" - "github.com/alist-org/alist/v3/internal/db" "github.com/alist-org/alist/v3/internal/model" - "github.com/alist-org/alist/v3/pkg/utils" + "github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/server/common" "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" @@ -22,7 +21,7 @@ func ListMetas(c *gin.Context) { } req.Validate() log.Debugf("%+v", req) - metas, total, err := db.GetMetas(req.Page, req.PerPage) + metas, total, err := op.GetMetas(req.Page, req.PerPage) if err != nil { common.ErrorResp(c, err, 500, true) return @@ -44,8 +43,7 @@ func CreateMeta(c *gin.Context) { common.ErrorStrResp(c, fmt.Sprintf("%s is illegal: %s", r, err.Error()), 400) return } - req.Path = utils.FixAndCleanPath(req.Path) - if err := db.CreateMeta(&req); err != nil { + if err := op.CreateMeta(&req); err != nil { common.ErrorResp(c, err, 500, true) } else { common.SuccessResp(c) @@ -63,8 +61,7 @@ func UpdateMeta(c *gin.Context) { common.ErrorStrResp(c, fmt.Sprintf("%s is illegal: %s", r, err.Error()), 400) return } - req.Path = utils.FixAndCleanPath(req.Path) - if err := db.UpdateMeta(&req); err != nil { + if err := op.UpdateMeta(&req); err != nil { common.ErrorResp(c, err, 500, true) } else { common.SuccessResp(c) @@ -89,7 +86,7 @@ func DeleteMeta(c *gin.Context) { common.ErrorResp(c, err, 400) return } - if err := db.DeleteMetaById(uint(id)); err != nil { + if err := op.DeleteMetaById(uint(id)); err != nil { common.ErrorResp(c, err, 500, true) return } @@ -103,7 +100,7 @@ func GetMeta(c *gin.Context) { common.ErrorResp(c, err, 400) return } - meta, err := db.GetMetaById(uint(id)) + meta, err := op.GetMetaById(uint(id)) if err != nil { common.ErrorResp(c, err, 500, true) return diff --git a/server/handles/search.go b/server/handles/search.go index 8b4d72d6..8881731b 100644 --- a/server/handles/search.go +++ b/server/handles/search.go @@ -4,9 +4,9 @@ import ( "path" "strings" - "github.com/alist-org/alist/v3/internal/db" "github.com/alist-org/alist/v3/internal/errs" "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/internal/search" "github.com/alist-org/alist/v3/pkg/utils" "github.com/alist-org/alist/v3/server/common" @@ -53,7 +53,7 @@ func Search(c *gin.Context) { if !strings.HasPrefix(node.Parent, user.BasePath) { continue } - meta, err := db.GetNearestMeta(node.Parent) + meta, err := op.GetNearestMeta(node.Parent) if err != nil && !errors.Is(errors.Cause(err), errs.MetaNotFound) { continue } diff --git a/server/handles/setting.go b/server/handles/setting.go index 00430302..f778b180 100644 --- a/server/handles/setting.go +++ b/server/handles/setting.go @@ -5,8 +5,8 @@ import ( "strings" "github.com/alist-org/alist/v3/internal/conf" - "github.com/alist-org/alist/v3/internal/db" "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/internal/sign" "github.com/alist-org/alist/v3/pkg/utils/random" "github.com/alist-org/alist/v3/server/common" @@ -17,7 +17,7 @@ import ( func ResetToken(c *gin.Context) { token := random.Token() item := model.SettingItem{Key: "token", Value: token, Type: conf.TypeString, Group: model.SINGLE, Flag: model.PRIVATE} - if err := db.SaveSettingItem(item); err != nil { + if err := op.SaveSettingItem(&item); err != nil { common.ErrorResp(c, err, 500) return } @@ -29,14 +29,14 @@ func GetSetting(c *gin.Context) { key := c.Query("key") keys := c.Query("keys") if key != "" { - item, err := db.GetSettingItemByKey(key) + item, err := op.GetSettingItemByKey(key) if err != nil { common.ErrorResp(c, err, 400) return } common.SuccessResp(c, item) } else { - items, err := db.GetSettingItemInKeys(strings.Split(keys, ",")) + items, err := op.GetSettingItemInKeys(strings.Split(keys, ",")) if err != nil { common.ErrorResp(c, err, 400) return @@ -51,7 +51,7 @@ func SaveSettings(c *gin.Context) { common.ErrorResp(c, err, 400) return } - if err := db.SaveSettingItems(req); err != nil { + if err := op.SaveSettingItems(req); err != nil { common.ErrorResp(c, err, 500) } else { common.SuccessResp(c) @@ -65,7 +65,7 @@ func ListSettings(c *gin.Context) { var settings []model.SettingItem var err error if groupsStr == "" && groupStr == "" { - settings, err = db.GetSettingItems() + settings, err = op.GetSettingItems() } else { var groupStrings []string if groupsStr != "" { @@ -82,7 +82,7 @@ func ListSettings(c *gin.Context) { } groups = append(groups, group) } - settings, err = db.GetSettingItemsInGroups(groups) + settings, err = op.GetSettingItemsInGroups(groups) } if err != nil { common.ErrorResp(c, err, 400) @@ -93,7 +93,7 @@ func ListSettings(c *gin.Context) { func DeleteSetting(c *gin.Context) { key := c.Query("key") - if err := db.DeleteSettingItemByKey(key); err != nil { + if err := op.DeleteSettingItemByKey(key); err != nil { common.ErrorResp(c, err, 500) return } @@ -101,5 +101,5 @@ func DeleteSetting(c *gin.Context) { } func PublicSettings(c *gin.Context) { - common.SuccessResp(c, db.GetPublicSettingsMap()) + common.SuccessResp(c, op.GetPublicSettingsMap()) } diff --git a/server/handles/user.go b/server/handles/user.go index cbee8f33..22d4e87f 100644 --- a/server/handles/user.go +++ b/server/handles/user.go @@ -3,8 +3,8 @@ package handles import ( "strconv" - "github.com/alist-org/alist/v3/internal/db" "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/server/common" "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" @@ -18,7 +18,7 @@ func ListUsers(c *gin.Context) { } req.Validate() log.Debugf("%+v", req) - users, total, err := db.GetUsers(req.Page, req.PerPage) + users, total, err := op.GetUsers(req.Page, req.PerPage) if err != nil { common.ErrorResp(c, err, 500, true) return @@ -39,7 +39,7 @@ func CreateUser(c *gin.Context) { common.ErrorStrResp(c, "admin or guest user can not be created", 400, true) return } - if err := db.CreateUser(&req); err != nil { + if err := op.CreateUser(&req); err != nil { common.ErrorResp(c, err, 500, true) } else { common.SuccessResp(c) @@ -52,7 +52,7 @@ func UpdateUser(c *gin.Context) { common.ErrorResp(c, err, 400) return } - user, err := db.GetUserById(req.ID) + user, err := op.GetUserById(req.ID) if err != nil { common.ErrorResp(c, err, 500) return @@ -67,7 +67,7 @@ func UpdateUser(c *gin.Context) { if req.OtpSecret == "" { req.OtpSecret = user.OtpSecret } - if err := db.UpdateUser(&req); err != nil { + if err := op.UpdateUser(&req); err != nil { common.ErrorResp(c, err, 500) } else { common.SuccessResp(c) @@ -81,7 +81,7 @@ func DeleteUser(c *gin.Context) { common.ErrorResp(c, err, 400) return } - if err := db.DeleteUserById(uint(id)); err != nil { + if err := op.DeleteUserById(uint(id)); err != nil { common.ErrorResp(c, err, 500) return } @@ -95,7 +95,7 @@ func GetUser(c *gin.Context) { common.ErrorResp(c, err, 400) return } - user, err := db.GetUserById(uint(id)) + user, err := op.GetUserById(uint(id)) if err != nil { common.ErrorResp(c, err, 500, true) return @@ -110,7 +110,7 @@ func Cancel2FAById(c *gin.Context) { common.ErrorResp(c, err, 400) return } - if err := db.Cancel2FAById(uint(id)); err != nil { + if err := op.Cancel2FAById(uint(id)); err != nil { common.ErrorResp(c, err, 500) return } diff --git a/server/middlewares/auth.go b/server/middlewares/auth.go index c22f2825..7ad40425 100644 --- a/server/middlewares/auth.go +++ b/server/middlewares/auth.go @@ -2,8 +2,8 @@ package middlewares import ( "github.com/alist-org/alist/v3/internal/conf" - "github.com/alist-org/alist/v3/internal/db" "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/internal/setting" "github.com/alist-org/alist/v3/server/common" "github.com/gin-gonic/gin" @@ -15,7 +15,7 @@ import ( func Auth(c *gin.Context) { token := c.GetHeader("Authorization") if token == setting.GetStr(conf.Token) { - admin, err := db.GetAdmin() + admin, err := op.GetAdmin() if err != nil { common.ErrorResp(c, err, 500) c.Abort() @@ -27,7 +27,7 @@ func Auth(c *gin.Context) { return } if token == "" { - guest, err := db.GetGuest() + guest, err := op.GetGuest() if err != nil { common.ErrorResp(c, err, 500) c.Abort() @@ -44,7 +44,7 @@ func Auth(c *gin.Context) { c.Abort() return } - user, err := db.GetUserByName(userClaims.Username) + user, err := op.GetUserByName(userClaims.Username) if err != nil { common.ErrorResp(c, err, 401) c.Abort() diff --git a/server/middlewares/down.go b/server/middlewares/down.go index 411d053c..48e9ea72 100644 --- a/server/middlewares/down.go +++ b/server/middlewares/down.go @@ -4,9 +4,9 @@ import ( "strings" "github.com/alist-org/alist/v3/internal/conf" - "github.com/alist-org/alist/v3/internal/db" "github.com/alist-org/alist/v3/internal/errs" "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/internal/setting" "github.com/alist-org/alist/v3/internal/sign" "github.com/alist-org/alist/v3/pkg/utils" @@ -18,7 +18,7 @@ import ( func Down(c *gin.Context) { rawPath := parsePath(c.Param("path")) c.Set("path", rawPath) - meta, err := db.GetNearestMeta(rawPath) + meta, err := op.GetNearestMeta(rawPath) if err != nil { if !errors.Is(errors.Cause(err), errs.MetaNotFound) { common.ErrorResp(c, err, 500, true) diff --git a/server/middlewares/fsup.go b/server/middlewares/fsup.go index 3e503cc6..809e8f29 100644 --- a/server/middlewares/fsup.go +++ b/server/middlewares/fsup.go @@ -4,9 +4,9 @@ import ( "net/url" stdpath "path" - "github.com/alist-org/alist/v3/internal/db" "github.com/alist-org/alist/v3/internal/errs" "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/server/common" "github.com/gin-gonic/gin" "github.com/pkg/errors" @@ -27,7 +27,7 @@ func FsUp(c *gin.Context) { common.ErrorResp(c, err, 403) return } - meta, err := db.GetNearestMeta(stdpath.Dir(path)) + meta, err := op.GetNearestMeta(stdpath.Dir(path)) if err != nil { if !errors.Is(errors.Cause(err), errs.MetaNotFound) { common.ErrorResp(c, err, 500, true) diff --git a/server/webdav.go b/server/webdav.go index ddd95028..6c97266e 100644 --- a/server/webdav.go +++ b/server/webdav.go @@ -4,8 +4,8 @@ import ( "context" "net/http" - "github.com/alist-org/alist/v3/internal/db" "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/internal/op" "github.com/alist-org/alist/v3/pkg/utils" "github.com/alist-org/alist/v3/server/webdav" "github.com/gin-gonic/gin" @@ -45,7 +45,7 @@ func ServeWebDAV(c *gin.Context) { } func WebDAVAuth(c *gin.Context) { - guest, _ := db.GetGuest() + guest, _ := op.GetGuest() username, password, ok := c.Request.BasicAuth() if !ok { if c.Request.Method == "OPTIONS" { @@ -58,7 +58,7 @@ func WebDAVAuth(c *gin.Context) { c.Abort() return } - user, err := db.GetUserByName(username) + user, err := op.GetUserByName(username) if err != nil || user.ValidatePassword(password) != nil { if c.Request.Method == "OPTIONS" { c.Set("user", guest) diff --git a/server/webdav/file.go b/server/webdav/file.go index 4840f126..c053a4cb 100644 --- a/server/webdav/file.go +++ b/server/webdav/file.go @@ -10,9 +10,9 @@ import ( "path" "path/filepath" - "github.com/alist-org/alist/v3/internal/db" "github.com/alist-org/alist/v3/internal/fs" "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/internal/op" ) // slashClean is equivalent to but slightly more efficient than @@ -85,7 +85,7 @@ func walkFS(ctx context.Context, depth int, name string, info model.Obj, walkFn if depth == 1 { depth = 0 } - meta, _ := db.GetNearestMeta(name) + meta, _ := op.GetNearestMeta(name) // Read directory names. objs, err := fs.List(context.WithValue(ctx, "meta", meta), name) //f, err := fs.OpenFile(ctx, name, os.O_RDONLY, 0)