mirror of https://github.com/Xhofe/alist
refactor: split the db package hook and cache to the op package (#2747)
* refactor:separate the setting method from the db package to the op package and add the cache
* refactor:separate the meta method from the db package to the op package
* fix:setting not load database data
* refactor:separate the user method from the db package to the op package
* refactor:remove user JoinPath error
* fix:op package user cache
* refactor:fs package list method
* fix:tile virtual paths (close #2743)
* Revert "refactor:remove user JoinPath error"
This reverts commit 4e20daaf9e
.
* clean path directly may lead to unknown behavior
* fix: The path of the meta passed in must be prefix of reqPath
* chore: rename all virtualPath to mountPath
* fix: `getStoragesByPath` and `GetStorageVirtualFilesByPath`
is_sub_path:
/a/b isn't subpath of /a/bc
* fix: don't save setting if hook error
Co-authored-by: Noah Hsu <i@nn.ci>
pull/2757/head
parent
f38f4f401b
commit
6024e8d832
|
@ -4,7 +4,7 @@ Copyright © 2022 NAME HERE <EMAIL ADDRESS>
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
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/alist-org/alist/v3/pkg/utils"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
@ -16,7 +16,7 @@ var passwordCmd = &cobra.Command{
|
||||||
Short: "Show admin user's info",
|
Short: "Show admin user's info",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
Init()
|
Init()
|
||||||
admin, err := db.GetAdmin()
|
admin, err := op.GetAdmin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Log.Errorf("failed get admin user: %+v", err)
|
utils.Log.Errorf("failed get admin user: %+v", err)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -4,7 +4,7 @@ Copyright © 2022 NAME HERE <EMAIL ADDRESS>
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
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/alist-org/alist/v3/pkg/utils"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
@ -15,11 +15,11 @@ var cancel2FACmd = &cobra.Command{
|
||||||
Short: "Delete 2FA of admin user",
|
Short: "Delete 2FA of admin user",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
Init()
|
Init()
|
||||||
admin, err := db.GetAdmin()
|
admin, err := op.GetAdmin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Log.Errorf("failed to get admin user: %+v", err)
|
utils.Log.Errorf("failed to get admin user: %+v", err)
|
||||||
} else {
|
} else {
|
||||||
err := db.Cancel2FAByUser(admin)
|
err := op.Cancel2FAByUser(admin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Log.Errorf("failed to cancel 2FA: %+v", err)
|
utils.Log.Errorf("failed to cancel 2FA: %+v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ package data
|
||||||
import (
|
import (
|
||||||
"github.com/alist-org/alist/v3/cmd/flags"
|
"github.com/alist-org/alist/v3/cmd/flags"
|
||||||
"github.com/alist-org/alist/v3/internal/conf"
|
"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/model"
|
||||||
|
"github.com/alist-org/alist/v3/internal/op"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils/random"
|
"github.com/alist-org/alist/v3/pkg/utils/random"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
@ -16,40 +16,45 @@ var initialSettingItems []model.SettingItem
|
||||||
func initSettings() {
|
func initSettings() {
|
||||||
InitialSettings()
|
InitialSettings()
|
||||||
// check deprecated
|
// check deprecated
|
||||||
settings, err := db.GetSettingItems()
|
settings, err := op.GetSettingItems()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed get settings: %+v", err)
|
log.Fatalf("failed get settings: %+v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range settings {
|
for i := range settings {
|
||||||
if !isActive(settings[i].Key) {
|
if !isActive(settings[i].Key) && settings[i].Flag != model.DEPRECATED {
|
||||||
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 {
|
// create or save setting
|
||||||
// err = db.SaveSettingItems(settings)
|
|
||||||
// if err != nil {
|
|
||||||
// log.Fatalf("failed save settings: %+v", err)
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
// insert new items
|
|
||||||
for i := range initialSettingItems {
|
for i := range initialSettingItems {
|
||||||
v := initialSettingItems[i]
|
item := &initialSettingItems[i]
|
||||||
stored, err := db.GetSettingItemByKey(v.Key)
|
// err
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) || v.Key == conf.VERSION {
|
stored, err := op.GetSettingItemByKey(item.Key)
|
||||||
err = db.SaveSettingItem(v)
|
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("failed create setting: %+v", err)
|
|
||||||
}
|
|
||||||
} else if err != nil {
|
|
||||||
log.Fatalf("failed get setting: %+v", err)
|
log.Fatalf("failed get setting: %+v", err)
|
||||||
} else {
|
continue
|
||||||
v.Value = stored.Value
|
|
||||||
err = db.SaveSettingItem(v)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("failed resave setting: %+v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"github.com/alist-org/alist/v3/cmd/flags"
|
"github.com/alist-org/alist/v3/cmd/flags"
|
||||||
"github.com/alist-org/alist/v3/internal/db"
|
"github.com/alist-org/alist/v3/internal/db"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"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"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils/random"
|
"github.com/alist-org/alist/v3/pkg/utils/random"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -13,7 +14,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func initUser() {
|
func initUser() {
|
||||||
admin, err := db.GetAdmin()
|
admin, err := op.GetAdmin()
|
||||||
adminPassword := random.String(8)
|
adminPassword := random.String(8)
|
||||||
envpass := os.Getenv("ALIST_ADMIN_PASSWORD")
|
envpass := os.Getenv("ALIST_ADMIN_PASSWORD")
|
||||||
if flags.Dev {
|
if flags.Dev {
|
||||||
|
@ -29,7 +30,7 @@ func initUser() {
|
||||||
Role: model.ADMIN,
|
Role: model.ADMIN,
|
||||||
BasePath: "/",
|
BasePath: "/",
|
||||||
}
|
}
|
||||||
if err := db.CreateUser(admin); err != nil {
|
if err := op.CreateUser(admin); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
} else {
|
} else {
|
||||||
utils.Log.Infof("Successfully created the admin user and the initial password is: %s", admin.Password)
|
utils.Log.Infof("Successfully created the admin user and the initial password is: %s", admin.Password)
|
||||||
|
@ -38,7 +39,7 @@ func initUser() {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
guest, err := db.GetGuest()
|
guest, err := op.GetGuest()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
guest = &model.User{
|
guest = &model.User{
|
||||||
|
|
|
@ -1,52 +1,16 @@
|
||||||
package db
|
package db
|
||||||
|
|
||||||
import (
|
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/internal/model"
|
||||||
"github.com/alist-org/alist/v3/pkg/singleflight"
|
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
|
||||||
"github.com/pkg/errors"
|
"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) {
|
func GetMetaByPath(path string) (*model.Meta, error) {
|
||||||
meta, ok := metaCache.Get(path)
|
meta := model.Meta{Path: path}
|
||||||
if ok {
|
if err := db.Where(meta).First(&meta).Error; err != nil {
|
||||||
return meta, nil
|
return nil, errors.Wrapf(err, "failed select meta")
|
||||||
}
|
}
|
||||||
meta, err, _ := metaG.Do(path, func() (*model.Meta, error) {
|
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")
|
|
||||||
}
|
|
||||||
metaCache.Set(path, &meta, cache.WithEx[*model.Meta](time.Hour))
|
|
||||||
return &meta, nil
|
|
||||||
})
|
|
||||||
return meta, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMetaById(id uint) (*model.Meta, error) {
|
func GetMetaById(id uint) (*model.Meta, error) {
|
||||||
|
@ -62,32 +26,20 @@ func CreateMeta(u *model.Meta) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateMeta(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)
|
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{})
|
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")
|
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 nil, 0, errors.Wrapf(err, "failed get find metas")
|
||||||
}
|
}
|
||||||
return metas, count, nil
|
return metas, count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteMetaById(id uint) error {
|
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)
|
return errors.WithStack(db.Delete(&model.Meta{}, id).Error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
// }
|
|
|
@ -4,45 +4,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/alist-org/alist/v3/pkg/generic_sync"
|
|
||||||
"github.com/pkg/errors"
|
"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) {
|
func GetSettingItems() ([]model.SettingItem, error) {
|
||||||
var settingItems []model.SettingItem
|
var settingItems []model.SettingItem
|
||||||
if err := db.Find(&settingItems).Error; err != nil {
|
if err := db.Find(&settingItems).Error; err != nil {
|
||||||
|
@ -59,18 +23,18 @@ func GetSettingItemByKey(key string) (*model.SettingItem, error) {
|
||||||
return &settingItem, nil
|
return &settingItem, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSettingItemInKeys(keys []string) ([]model.SettingItem, error) {
|
// func GetSettingItemInKeys(keys []string) ([]model.SettingItem, error) {
|
||||||
var settingItem []model.SettingItem
|
// var settingItem []model.SettingItem
|
||||||
if err := db.Where(fmt.Sprintf("%s in ?", columnName("key")), keys).Find(&settingItem).Error; err != nil {
|
// if err := db.Where(fmt.Sprintf("%s in ?", columnName("key")), keys).Find(&settingItem).Error; err != nil {
|
||||||
return nil, errors.WithStack(err)
|
// return nil, errors.WithStack(err)
|
||||||
}
|
// }
|
||||||
return settingItem, nil
|
// return settingItem, nil
|
||||||
}
|
// }
|
||||||
|
|
||||||
func GetPublicSettingItems() ([]model.SettingItem, error) {
|
func GetPublicSettingItems() ([]model.SettingItem, error) {
|
||||||
var settingItems []model.SettingItem
|
var settingItems []model.SettingItem
|
||||||
if err := db.Where(fmt.Sprintf("%s in ?", columnName("flag")), []int{model.PUBLIC, model.READONLY}).Find(&settingItems).Error; err != nil {
|
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
|
return settingItems, nil
|
||||||
}
|
}
|
||||||
|
@ -91,58 +55,14 @@ func GetSettingItemsInGroups(groups []int) ([]model.SettingItem, error) {
|
||||||
return settingItems, nil
|
return settingItems, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func SaveSettingItems(items []model.SettingItem) error {
|
func SaveSettingItems(items []model.SettingItem) (err error) {
|
||||||
others := make([]model.SettingItem, 0)
|
return errors.WithStack(db.Save(items).Error)
|
||||||
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 SaveSettingItem(item model.SettingItem) error {
|
func SaveSettingItem(item *model.SettingItem) error {
|
||||||
_, err := HandleSettingItem(&item)
|
return errors.WithStack(db.Save(item).Error)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = db.Save(item).Error
|
|
||||||
if err == nil {
|
|
||||||
settingsUpdate()
|
|
||||||
}
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteSettingItemByKey(key string) error {
|
func DeleteSettingItemByKey(key string) error {
|
||||||
settingItem := model.SettingItem{
|
return errors.WithStack(db.Delete(&model.SettingItem{Key: key}).Error)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,61 +1,24 @@
|
||||||
package db
|
package db
|
||||||
|
|
||||||
import (
|
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/internal/model"
|
||||||
"github.com/alist-org/alist/v3/pkg/singleflight"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
var userCache = cache.NewMemCache(cache.WithShards[*model.User](2))
|
func GetUserByRole(role int) (*model.User, error) {
|
||||||
var userG singleflight.Group[*model.User]
|
user := model.User{Role: role}
|
||||||
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}
|
|
||||||
if err := db.Where(user).Take(&user).Error; err != nil {
|
if err := db.Where(user).Take(&user).Error; err != nil {
|
||||||
return nil, err
|
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
|
return &user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetUserByName(username string) (*model.User, error) {
|
func GetUserByName(username string) (*model.User, error) {
|
||||||
if username == "" {
|
user := model.User{Username: username}
|
||||||
return nil, errors.WithStack(errs.EmptyUsername)
|
if err := db.Where(user).First(&user).Error; err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "failed find user")
|
||||||
}
|
}
|
||||||
user, ok := userCache.Get(username)
|
return &user, nil
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetUserById(id uint) (*model.User, error) {
|
func GetUserById(id uint) (*model.User, error) {
|
||||||
|
@ -71,40 +34,14 @@ func CreateUser(u *model.User) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateUser(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)
|
return errors.WithStack(db.Save(u).Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Cancel2FAByUser(u *model.User) error {
|
func GetUsers(pageIndex, pageSize int) (users []model.User, count int64, err 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) {
|
|
||||||
userDB := db.Model(&model.User{})
|
userDB := db.Model(&model.User{})
|
||||||
var count int64
|
|
||||||
if err := userDB.Count(&count).Error; err != nil {
|
if err := userDB.Count(&count).Error; err != nil {
|
||||||
return nil, 0, errors.Wrapf(err, "failed get users count")
|
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 {
|
if err := userDB.Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&users).Error; err != nil {
|
||||||
return nil, 0, errors.Wrapf(err, "failed get find users")
|
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 {
|
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)
|
return errors.WithStack(db.Delete(&model.User{}, id).Error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,6 @@ package fs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/alist-org/alist/v3/internal/op"
|
"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) {
|
func list(ctx context.Context, path string, refresh ...bool) ([]model.Obj, error) {
|
||||||
meta := ctx.Value("meta").(*model.Meta)
|
meta := ctx.Value("meta").(*model.Meta)
|
||||||
user := ctx.Value("user").(*model.User)
|
user := ctx.Value("user").(*model.User)
|
||||||
var objs []model.Obj
|
|
||||||
storage, actualPath, err := op.GetStorageAndActualPath(path)
|
|
||||||
virtualFiles := op.GetStorageVirtualFilesByPath(path)
|
virtualFiles := op.GetStorageVirtualFilesByPath(path)
|
||||||
if err != nil {
|
storage, actualPath, err := op.GetStorageAndActualPath(path)
|
||||||
if len(virtualFiles) == 0 {
|
if err != nil && len(virtualFiles) == 0 {
|
||||||
return nil, errors.WithMessage(err, "failed get storage")
|
return nil, errors.WithMessage(err, "failed get storage")
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
_objs, err := op.List(ctx, storage, actualPath, model.ListArgs{
|
var _objs []model.Obj
|
||||||
|
if storage != nil {
|
||||||
|
_objs, err = op.List(ctx, storage, actualPath, model.ListArgs{
|
||||||
ReqPath: path,
|
ReqPath: path,
|
||||||
}, refresh...)
|
}, refresh...)
|
||||||
if err != nil {
|
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")
|
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) {
|
if whetherHide(user, meta, path) {
|
||||||
objs = hide(objs, meta)
|
om.InitHideReg(meta.Hide)
|
||||||
}
|
}
|
||||||
|
objs := om.Merge(virtualFiles, _objs...)
|
||||||
// sort objs
|
// sort objs
|
||||||
if storage != nil {
|
if storage != nil {
|
||||||
if storage.Config().LocalSort {
|
if storage.Config().LocalSort {
|
||||||
|
@ -78,26 +68,3 @@ func whetherHide(user *model.User, meta *model.Meta, path string) bool {
|
||||||
// if is guest, hide
|
// if is guest, hide
|
||||||
return true
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,8 +5,8 @@ import (
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"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/model"
|
||||||
|
"github.com/alist-org/alist/v3/internal/op"
|
||||||
)
|
)
|
||||||
|
|
||||||
// WalkFS traverses filesystem fs starting at name up to depth levels.
|
// 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 {
|
if !info.IsDir() || depth == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
meta, _ := db.GetNearestMeta(name)
|
meta, _ := op.GetNearestMeta(name)
|
||||||
// Read directory names.
|
// Read directory names.
|
||||||
objs, err := List(context.WithValue(ctx, "meta", meta), name)
|
objs, err := List(context.WithValue(ctx, "meta", meta), name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -2,9 +2,13 @@ package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
mapset "github.com/deckarep/golang-set/v2"
|
||||||
|
|
||||||
"github.com/maruel/natural"
|
"github.com/maruel/natural"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -100,3 +104,50 @@ func WrapObjsName(objs []Obj) {
|
||||||
objs[i] = &ObjWrapName{Obj: objs[i]}
|
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()
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,17 @@
|
||||||
package op
|
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)
|
type ObjsUpdateHook = func(parent string, objs []model.Obj)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -11,3 +21,78 @@ var (
|
||||||
func RegisterObjsUpdateHook(hook ObjsUpdateHook) {
|
func RegisterObjsUpdateHook(hook ObjsUpdateHook) {
|
||||||
objsUpdateHooks = append(objsUpdateHooks, hook)
|
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
|
||||||
|
//}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -19,7 +19,7 @@ func GetStorageAndActualPath(rawPath string) (storage driver.Driver, actualPath
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Debugln("use storage: ", storage.GetStorage().MountPath)
|
log.Debugln("use storage: ", storage.GetStorage().MountPath)
|
||||||
virtualPath := utils.GetActualVirtualPath(storage.GetStorage().MountPath)
|
mountPath := utils.GetActualMountPath(storage.GetStorage().MountPath)
|
||||||
actualPath = utils.FixAndCleanPath(strings.TrimPrefix(rawPath, virtualPath))
|
actualPath = utils.FixAndCleanPath(strings.TrimPrefix(rawPath, mountPath))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -29,7 +29,7 @@ func HasStorage(mountPath string) bool {
|
||||||
return storagesMap.Has(utils.FixAndCleanPath(mountPath))
|
return storagesMap.Has(utils.FixAndCleanPath(mountPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetStorageByVirtualPath(virtualPath string) (driver.Driver, error) {
|
func GetStorageByMountPath(virtualPath string) (driver.Driver, error) {
|
||||||
virtualPath = utils.FixAndCleanPath(virtualPath)
|
virtualPath = utils.FixAndCleanPath(virtualPath)
|
||||||
storageDriver, ok := storagesMap.Load(virtualPath)
|
storageDriver, ok := storagesMap.Load(virtualPath)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -130,7 +130,7 @@ func DisableStorage(ctx context.Context, id uint) error {
|
||||||
if storage.Disabled {
|
if storage.Disabled {
|
||||||
return errors.Errorf("this storage have disabled")
|
return errors.Errorf("this storage have disabled")
|
||||||
}
|
}
|
||||||
storageDriver, err := GetStorageByVirtualPath(storage.MountPath)
|
storageDriver, err := GetStorageByMountPath(storage.MountPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithMessage(err, "failed get storage driver")
|
return errors.WithMessage(err, "failed get storage driver")
|
||||||
}
|
}
|
||||||
|
@ -168,7 +168,7 @@ func UpdateStorage(ctx context.Context, storage model.Storage) error {
|
||||||
if storage.Disabled {
|
if storage.Disabled {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
storageDriver, err := GetStorageByVirtualPath(oldStorage.MountPath)
|
storageDriver, err := GetStorageByMountPath(oldStorage.MountPath)
|
||||||
if oldStorage.MountPath != storage.MountPath {
|
if oldStorage.MountPath != storage.MountPath {
|
||||||
// mount path renamed, need to drop the storage
|
// mount path renamed, need to drop the storage
|
||||||
storagesMap.Delete(oldStorage.MountPath)
|
storagesMap.Delete(oldStorage.MountPath)
|
||||||
|
@ -192,7 +192,7 @@ func DeleteStorageById(ctx context.Context, id uint) error {
|
||||||
return errors.WithMessage(err, "failed get storage")
|
return errors.WithMessage(err, "failed get storage")
|
||||||
}
|
}
|
||||||
if !storage.Disabled {
|
if !storage.Disabled {
|
||||||
storageDriver, err := GetStorageByVirtualPath(storage.MountPath)
|
storageDriver, err := GetStorageByMountPath(storage.MountPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithMessage(err, "failed get storage driver")
|
return errors.WithMessage(err, "failed get storage driver")
|
||||||
}
|
}
|
||||||
|
@ -221,11 +221,11 @@ func MustSaveDriverStorage(driver driver.Driver) {
|
||||||
func saveDriverStorage(driver driver.Driver) error {
|
func saveDriverStorage(driver driver.Driver) error {
|
||||||
storage := driver.GetStorage()
|
storage := driver.GetStorage()
|
||||||
addition := driver.GetAddition()
|
addition := driver.GetAddition()
|
||||||
strs, err := utils.Json.MarshalToString(addition)
|
str, err := utils.Json.MarshalToString(addition)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error while marshal addition")
|
return errors.Wrap(err, "error while marshal addition")
|
||||||
}
|
}
|
||||||
storage.Addition = strs
|
storage.Addition = str
|
||||||
err = db.UpdateStorage(storage)
|
err = db.UpdateStorage(storage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithMessage(err, "failed update storage in database")
|
return errors.WithMessage(err, "failed update storage in database")
|
||||||
|
@ -240,10 +240,10 @@ func getStoragesByPath(path string) []driver.Driver {
|
||||||
storages := make([]driver.Driver, 0)
|
storages := make([]driver.Driver, 0)
|
||||||
curSlashCount := 0
|
curSlashCount := 0
|
||||||
storagesMap.Range(func(mountPath string, value driver.Driver) bool {
|
storagesMap.Range(func(mountPath string, value driver.Driver) bool {
|
||||||
virtualPath := utils.GetActualVirtualPath(mountPath)
|
mountPath = utils.GetActualMountPath(mountPath)
|
||||||
// is this path
|
// is this path
|
||||||
if strings.HasPrefix(path, virtualPath) {
|
if utils.IsSubPath(path, mountPath) {
|
||||||
slashCount := strings.Count(utils.PathAddSeparatorSuffix(virtualPath), "/")
|
slashCount := strings.Count(utils.PathAddSeparatorSuffix(mountPath), "/")
|
||||||
// not the longest match
|
// not the longest match
|
||||||
if slashCount > curSlashCount {
|
if slashCount > curSlashCount {
|
||||||
storages = storages[:0]
|
storages = storages[:0]
|
||||||
|
@ -278,13 +278,12 @@ func GetStorageVirtualFilesByPath(prefix string) []model.Obj {
|
||||||
prefix = utils.FixAndCleanPath(prefix)
|
prefix = utils.FixAndCleanPath(prefix)
|
||||||
set := mapset.NewSet[string]()
|
set := mapset.NewSet[string]()
|
||||||
for _, v := range storages {
|
for _, v := range storages {
|
||||||
virtualPath := utils.GetActualVirtualPath(v.GetStorage().MountPath)
|
mountPath := utils.GetActualMountPath(v.GetStorage().MountPath)
|
||||||
// Exclude prefix itself and non prefix
|
// 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
|
continue
|
||||||
}
|
}
|
||||||
|
name := strings.SplitN(strings.TrimPrefix(mountPath[len(prefix):], "/"), "/", 2)[0]
|
||||||
name := strings.SplitN(strings.TrimPrefix(virtualPath[len(prefix):], "/"), "/", 1)[0]
|
|
||||||
if set.Add(name) {
|
if set.Add(name) {
|
||||||
files = append(files, &model.Object{
|
files = append(files, &model.Object{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
@ -310,7 +309,7 @@ func GetBalancedStorage(path string) driver.Driver {
|
||||||
case 1:
|
case 1:
|
||||||
return storages[0]
|
return storages[0]
|
||||||
default:
|
default:
|
||||||
virtualPath := utils.GetActualVirtualPath(storages[0].GetStorage().MountPath)
|
virtualPath := utils.GetActualMountPath(storages[0].GetStorage().MountPath)
|
||||||
i, _ := balanceMap.LoadOrStore(virtualPath, 0)
|
i, _ := balanceMap.LoadOrStore(virtualPath, 0)
|
||||||
i = (i + 1) % storageNum
|
i = (i + 1) % storageNum
|
||||||
balanceMap.Store(virtualPath, i)
|
balanceMap.Store(virtualPath, i)
|
||||||
|
|
|
@ -4,10 +4,12 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/alist-org/alist/v3/internal/conf"
|
||||||
"github.com/alist-org/alist/v3/internal/db"
|
"github.com/alist-org/alist/v3/internal/db"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/alist-org/alist/v3/internal/op"
|
"github.com/alist-org/alist/v3/internal/op"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
|
mapset "github.com/deckarep/golang-set/v2"
|
||||||
"gorm.io/driver/sqlite"
|
"gorm.io/driver/sqlite"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
@ -17,6 +19,7 @@ func init() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("failed to connect database")
|
panic("failed to connect database")
|
||||||
}
|
}
|
||||||
|
conf.Conf = conf.DefaultConfig()
|
||||||
db.Init(dB)
|
db.Init(dB)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,9 +28,9 @@ func TestCreateStorage(t *testing.T) {
|
||||||
storage model.Storage
|
storage model.Storage
|
||||||
isErr bool
|
isErr bool
|
||||||
}{
|
}{
|
||||||
{storage: model.Storage{Driver: "Local", MountPath: "/local", Addition: `{"root_folder":"."}`}, isErr: false},
|
{storage: model.Storage{Driver: "Local", MountPath: "/local", Addition: `{"root_folder_path":"."}`}, isErr: false},
|
||||||
{storage: model.Storage{Driver: "Local", MountPath: "/local", Addition: `{"root_folder":"."}`}, isErr: true},
|
{storage: model.Storage{Driver: "Local", MountPath: "/local", Addition: `{"root_folder_path":"."}`}, isErr: true},
|
||||||
{storage: model.Storage{Driver: "None", MountPath: "/none", Addition: `{"root_folder":"."}`}, isErr: true},
|
{storage: model.Storage{Driver: "None", MountPath: "/none", Addition: `{"root_folder_path":"."}`}, isErr: true},
|
||||||
}
|
}
|
||||||
for _, storage := range storages {
|
for _, storage := range storages {
|
||||||
_, err := op.CreateStorage(context.Background(), storage.storage)
|
_, err := op.CreateStorage(context.Background(), storage.storage)
|
||||||
|
@ -58,23 +61,26 @@ func TestGetStorageVirtualFilesByPath(t *testing.T) {
|
||||||
|
|
||||||
func TestGetBalancedStorage(t *testing.T) {
|
func TestGetBalancedStorage(t *testing.T) {
|
||||||
setupStorages(t)
|
setupStorages(t)
|
||||||
storage := op.GetBalancedStorage("/a/d/e")
|
set := mapset.NewSet[string]()
|
||||||
if storage.GetStorage().MountPath != "/a/d/e" {
|
for i := 0; i < 5; i++ {
|
||||||
t.Errorf("expected: /a/d/e, got: %+v", storage.GetStorage().MountPath)
|
storage := op.GetBalancedStorage("/a/d/e1")
|
||||||
|
set.Add(storage.GetStorage().MountPath)
|
||||||
}
|
}
|
||||||
storage = op.GetBalancedStorage("/a/d/e")
|
expected := mapset.NewSet([]string{"/a/d/e1", "/a/d/e1.balance"}...)
|
||||||
if storage.GetStorage().MountPath != "/a/d/e.balance" {
|
if !expected.Equal(set) {
|
||||||
t.Errorf("expected: /a/d/e.balance, got: %+v", storage.GetStorage().MountPath)
|
t.Errorf("expected: %+v, got: %+v", expected, set)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupStorages(t *testing.T) {
|
func setupStorages(t *testing.T) {
|
||||||
var storages = []model.Storage{
|
var storages = []model.Storage{
|
||||||
{Driver: "Local", MountPath: "/a/b", Order: 0, Addition: `{"root_folder":"."}`},
|
{Driver: "Local", MountPath: "/a/b", Order: 0, Addition: `{"root_folder_path":"."}`},
|
||||||
{Driver: "Local", MountPath: "/a/c", Order: 1, Addition: `{"root_folder":"."}`},
|
{Driver: "Local", MountPath: "/adc", Order: 0, Addition: `{"root_folder_path":"."}`},
|
||||||
{Driver: "Local", MountPath: "/a/d", Order: 2, Addition: `{"root_folder":"."}`},
|
{Driver: "Local", MountPath: "/a/c", Order: 1, Addition: `{"root_folder_path":"."}`},
|
||||||
{Driver: "Local", MountPath: "/a/d/e", Order: 3, Addition: `{"root_folder":"."}`},
|
{Driver: "Local", MountPath: "/a/d", Order: 2, Addition: `{"root_folder_path":"."}`},
|
||||||
{Driver: "Local", MountPath: "/a/d/e.balance", Order: 4, Addition: `{"root_folder":"."}`},
|
{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 {
|
for _, storage := range storages {
|
||||||
_, err := op.CreateStorage(context.Background(), storage)
|
_, err := op.CreateStorage(context.Background(), storage)
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/db"
|
|
||||||
"github.com/alist-org/alist/v3/internal/fs"
|
"github.com/alist-org/alist/v3/internal/fs"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/alist-org/alist/v3/internal/op"
|
"github.com/alist-org/alist/v3/internal/op"
|
||||||
|
@ -105,7 +104,7 @@ func BuildIndex(ctx context.Context, indexPaths, ignorePaths []string, maxDepth
|
||||||
Quit <- struct{}{}
|
Quit <- struct{}{}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
admin, err := db.GetAdmin()
|
admin, err := op.GetAdmin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/conf"
|
"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/errs"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"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"
|
"github.com/alist-org/alist/v3/internal/search/searcher"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
@ -88,7 +88,7 @@ func BatchIndex(ctx context.Context, objs []ObjWithParent) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
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)
|
log.Debugf("searcher init, mode: %s", item.Value)
|
||||||
return Init(item.Value)
|
return Init(item.Value)
|
||||||
})
|
})
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"github.com/alist-org/alist/v3/drivers/alist_v3"
|
"github.com/alist-org/alist/v3/drivers/alist_v3"
|
||||||
"github.com/alist-org/alist/v3/drivers/base"
|
"github.com/alist-org/alist/v3/drivers/base"
|
||||||
"github.com/alist-org/alist/v3/internal/conf"
|
"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/model"
|
||||||
"github.com/alist-org/alist/v3/internal/op"
|
"github.com/alist-org/alist/v3/internal/op"
|
||||||
"github.com/alist-org/alist/v3/internal/setting"
|
"github.com/alist-org/alist/v3/internal/setting"
|
||||||
|
@ -26,7 +25,7 @@ func WriteProgress(progress *model.IndexProgress) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("marshal progress error: %+v", err)
|
log.Errorf("marshal progress error: %+v", err)
|
||||||
}
|
}
|
||||||
err = db.SaveSettingItem(model.SettingItem{
|
err = op.SaveSettingItem(&model.SettingItem{
|
||||||
Key: conf.IndexProgress,
|
Key: conf.IndexProgress,
|
||||||
Value: p,
|
Value: p,
|
||||||
Type: conf.TypeText,
|
Type: conf.TypeText,
|
||||||
|
|
|
@ -3,18 +3,18 @@ package setting
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/db"
|
"github.com/alist-org/alist/v3/internal/op"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetStr(key string, defaultValue ...string) string {
|
func GetStr(key string, defaultValue ...string) string {
|
||||||
val, ok := db.GetSettingsMap().Load(key)
|
val, _ := op.GetSettingItemByKey(key)
|
||||||
if !ok {
|
if val == nil {
|
||||||
if len(defaultValue) > 0 {
|
if len(defaultValue) > 0 {
|
||||||
return defaultValue[0]
|
return defaultValue[0]
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return val
|
return val.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetInt(key string, defaultVal int) int {
|
func GetInt(key string, defaultVal int) int {
|
||||||
|
|
|
@ -8,8 +8,8 @@ func IsBalance(str string) bool {
|
||||||
return strings.Contains(str, balance)
|
return strings.Contains(str, balance)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetActualVirtualPath remove balance suffix
|
// GetActualMountPath remove balance suffix
|
||||||
func GetActualVirtualPath(virtualPath string) string {
|
func GetActualMountPath(virtualPath string) string {
|
||||||
bIndex := strings.LastIndex(virtualPath, ".balance")
|
bIndex := strings.LastIndex(virtualPath, ".balance")
|
||||||
if bIndex != -1 {
|
if bIndex != -1 {
|
||||||
virtualPath = virtualPath[:bIndex]
|
virtualPath = virtualPath[:bIndex]
|
||||||
|
|
|
@ -4,6 +4,8 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
stdpath "path"
|
stdpath "path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/alist-org/alist/v3/internal/errs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FixAndCleanPath
|
// FixAndCleanPath
|
||||||
|
@ -36,6 +38,11 @@ func PathEqual(path1, path2 string) bool {
|
||||||
return FixAndCleanPath(path1) == FixAndCleanPath(path2)
|
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 {
|
func Ext(path string) string {
|
||||||
ext := stdpath.Ext(path)
|
ext := stdpath.Ext(path)
|
||||||
if strings.HasPrefix(ext, ".") {
|
if strings.HasPrefix(ext, ".") {
|
||||||
|
@ -68,5 +75,8 @@ func EncodePath(path string, all ...bool) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func JoinBasePath(basePath, reqPath string) (string, error) {
|
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
|
return stdpath.Join(FixAndCleanPath(basePath), FixAndCleanPath(reqPath)), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
package utils
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
// SliceEqual check if two slices are equal
|
// SliceEqual check if two slices are equal
|
||||||
func SliceEqual[T comparable](a, b []T) bool {
|
func SliceEqual[T comparable](a, b []T) bool {
|
||||||
if len(a) != len(b) {
|
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
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ package handles
|
||||||
import (
|
import (
|
||||||
"github.com/alist-org/alist/v3/internal/aria2"
|
"github.com/alist-org/alist/v3/internal/aria2"
|
||||||
"github.com/alist-org/alist/v3/internal/conf"
|
"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/model"
|
||||||
|
"github.com/alist-org/alist/v3/internal/op"
|
||||||
"github.com/alist-org/alist/v3/server/common"
|
"github.com/alist-org/alist/v3/server/common"
|
||||||
"github.com/gin-gonic/gin"
|
"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.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},
|
{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)
|
common.ErrorResp(c, err, 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Xhofe/go-cache"
|
"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/model"
|
||||||
|
"github.com/alist-org/alist/v3/internal/op"
|
||||||
"github.com/alist-org/alist/v3/server/common"
|
"github.com/alist-org/alist/v3/server/common"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/pquerna/otp/totp"
|
"github.com/pquerna/otp/totp"
|
||||||
|
@ -41,7 +41,7 @@ func Login(c *gin.Context) {
|
||||||
common.ErrorResp(c, err, 400)
|
common.ErrorResp(c, err, 400)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user, err := db.GetUserByName(req.Username)
|
user, err := op.GetUserByName(req.Username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.ErrorResp(c, err, 400)
|
common.ErrorResp(c, err, 400)
|
||||||
loginCache.Set(ip, count+1)
|
loginCache.Set(ip, count+1)
|
||||||
|
@ -101,7 +101,7 @@ func UpdateCurrent(c *gin.Context) {
|
||||||
if req.Password != "" {
|
if req.Password != "" {
|
||||||
user.Password = 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)
|
common.ErrorResp(c, err, 500)
|
||||||
} else {
|
} else {
|
||||||
common.SuccessResp(c)
|
common.SuccessResp(c)
|
||||||
|
@ -158,7 +158,7 @@ func Verify2FA(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user.OtpSecret = req.Secret
|
user.OtpSecret = req.Secret
|
||||||
if err := db.UpdateUser(user); err != nil {
|
if err := op.UpdateUser(user); err != nil {
|
||||||
common.ErrorResp(c, err, 500)
|
common.ErrorResp(c, err, 500)
|
||||||
} else {
|
} else {
|
||||||
common.SuccessResp(c)
|
common.SuccessResp(c)
|
||||||
|
|
|
@ -4,10 +4,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
stdpath "path"
|
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/errs"
|
||||||
"github.com/alist-org/alist/v3/internal/fs"
|
"github.com/alist-org/alist/v3/internal/fs"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"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/internal/sign"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
"github.com/alist-org/alist/v3/server/common"
|
"github.com/alist-org/alist/v3/server/common"
|
||||||
|
@ -32,7 +32,7 @@ func FsMkdir(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !user.CanWrite() {
|
if !user.CanWrite() {
|
||||||
meta, err := db.GetNearestMeta(stdpath.Dir(reqPath))
|
meta, err := op.GetNearestMeta(stdpath.Dir(reqPath))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
|
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
|
||||||
common.ErrorResp(c, err, 500, true)
|
common.ErrorResp(c, err, 500, true)
|
||||||
|
|
|
@ -6,10 +6,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/db"
|
|
||||||
"github.com/alist-org/alist/v3/internal/errs"
|
"github.com/alist-org/alist/v3/internal/errs"
|
||||||
"github.com/alist-org/alist/v3/internal/fs"
|
"github.com/alist-org/alist/v3/internal/fs"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"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/internal/sign"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
"github.com/alist-org/alist/v3/server/common"
|
"github.com/alist-org/alist/v3/server/common"
|
||||||
|
@ -61,7 +61,7 @@ func FsList(c *gin.Context) {
|
||||||
common.ErrorResp(c, err, 403)
|
common.ErrorResp(c, err, 403)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
meta, err := db.GetNearestMeta(reqPath)
|
meta, err := op.GetNearestMeta(reqPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
|
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
|
||||||
common.ErrorResp(c, err, 500, true)
|
common.ErrorResp(c, err, 500, true)
|
||||||
|
@ -118,7 +118,7 @@ func FsDirs(c *gin.Context) {
|
||||||
}
|
}
|
||||||
reqPath = tmp
|
reqPath = tmp
|
||||||
}
|
}
|
||||||
meta, err := db.GetNearestMeta(reqPath)
|
meta, err := op.GetNearestMeta(reqPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
|
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
|
||||||
common.ErrorResp(c, err, 500, true)
|
common.ErrorResp(c, err, 500, true)
|
||||||
|
@ -233,7 +233,7 @@ func FsGet(c *gin.Context) {
|
||||||
common.ErrorResp(c, err, 403)
|
common.ErrorResp(c, err, 403)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
meta, err := db.GetNearestMeta(reqPath)
|
meta, err := op.GetNearestMeta(reqPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
|
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
|
||||||
common.ErrorResp(c, err, 500)
|
common.ErrorResp(c, err, 500)
|
||||||
|
@ -295,7 +295,7 @@ func FsGet(c *gin.Context) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
related = filterRelated(sameLevelFiles, obj)
|
related = filterRelated(sameLevelFiles, obj)
|
||||||
}
|
}
|
||||||
parentMeta, _ := db.GetNearestMeta(parentPath)
|
parentMeta, _ := op.GetNearestMeta(parentPath)
|
||||||
common.SuccessResp(c, FsGetResp{
|
common.SuccessResp(c, FsGetResp{
|
||||||
ObjResp: ObjResp{
|
ObjResp: ObjResp{
|
||||||
Name: obj.GetName(),
|
Name: obj.GetName(),
|
||||||
|
@ -344,7 +344,7 @@ func FsOther(c *gin.Context) {
|
||||||
common.ErrorResp(c, err, 403)
|
common.ErrorResp(c, err, 403)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
meta, err := db.GetNearestMeta(req.Path)
|
meta, err := op.GetNearestMeta(req.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
|
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
|
||||||
common.ErrorResp(c, err, 500)
|
common.ErrorResp(c, err, 500)
|
||||||
|
|
|
@ -6,9 +6,8 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/db"
|
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"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/alist-org/alist/v3/server/common"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
@ -22,7 +21,7 @@ func ListMetas(c *gin.Context) {
|
||||||
}
|
}
|
||||||
req.Validate()
|
req.Validate()
|
||||||
log.Debugf("%+v", req)
|
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 {
|
if err != nil {
|
||||||
common.ErrorResp(c, err, 500, true)
|
common.ErrorResp(c, err, 500, true)
|
||||||
return
|
return
|
||||||
|
@ -44,8 +43,7 @@ func CreateMeta(c *gin.Context) {
|
||||||
common.ErrorStrResp(c, fmt.Sprintf("%s is illegal: %s", r, err.Error()), 400)
|
common.ErrorStrResp(c, fmt.Sprintf("%s is illegal: %s", r, err.Error()), 400)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
req.Path = utils.FixAndCleanPath(req.Path)
|
if err := op.CreateMeta(&req); err != nil {
|
||||||
if err := db.CreateMeta(&req); err != nil {
|
|
||||||
common.ErrorResp(c, err, 500, true)
|
common.ErrorResp(c, err, 500, true)
|
||||||
} else {
|
} else {
|
||||||
common.SuccessResp(c)
|
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)
|
common.ErrorStrResp(c, fmt.Sprintf("%s is illegal: %s", r, err.Error()), 400)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
req.Path = utils.FixAndCleanPath(req.Path)
|
if err := op.UpdateMeta(&req); err != nil {
|
||||||
if err := db.UpdateMeta(&req); err != nil {
|
|
||||||
common.ErrorResp(c, err, 500, true)
|
common.ErrorResp(c, err, 500, true)
|
||||||
} else {
|
} else {
|
||||||
common.SuccessResp(c)
|
common.SuccessResp(c)
|
||||||
|
@ -89,7 +86,7 @@ func DeleteMeta(c *gin.Context) {
|
||||||
common.ErrorResp(c, err, 400)
|
common.ErrorResp(c, err, 400)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := db.DeleteMetaById(uint(id)); err != nil {
|
if err := op.DeleteMetaById(uint(id)); err != nil {
|
||||||
common.ErrorResp(c, err, 500, true)
|
common.ErrorResp(c, err, 500, true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -103,7 +100,7 @@ func GetMeta(c *gin.Context) {
|
||||||
common.ErrorResp(c, err, 400)
|
common.ErrorResp(c, err, 400)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
meta, err := db.GetMetaById(uint(id))
|
meta, err := op.GetMetaById(uint(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.ErrorResp(c, err, 500, true)
|
common.ErrorResp(c, err, 500, true)
|
||||||
return
|
return
|
||||||
|
|
|
@ -4,9 +4,9 @@ import (
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/db"
|
|
||||||
"github.com/alist-org/alist/v3/internal/errs"
|
"github.com/alist-org/alist/v3/internal/errs"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"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/internal/search"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
"github.com/alist-org/alist/v3/server/common"
|
"github.com/alist-org/alist/v3/server/common"
|
||||||
|
@ -53,7 +53,7 @@ func Search(c *gin.Context) {
|
||||||
if !strings.HasPrefix(node.Parent, user.BasePath) {
|
if !strings.HasPrefix(node.Parent, user.BasePath) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
meta, err := db.GetNearestMeta(node.Parent)
|
meta, err := op.GetNearestMeta(node.Parent)
|
||||||
if err != nil && !errors.Is(errors.Cause(err), errs.MetaNotFound) {
|
if err != nil && !errors.Is(errors.Cause(err), errs.MetaNotFound) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/conf"
|
"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/model"
|
||||||
|
"github.com/alist-org/alist/v3/internal/op"
|
||||||
"github.com/alist-org/alist/v3/internal/sign"
|
"github.com/alist-org/alist/v3/internal/sign"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils/random"
|
"github.com/alist-org/alist/v3/pkg/utils/random"
|
||||||
"github.com/alist-org/alist/v3/server/common"
|
"github.com/alist-org/alist/v3/server/common"
|
||||||
|
@ -17,7 +17,7 @@ import (
|
||||||
func ResetToken(c *gin.Context) {
|
func ResetToken(c *gin.Context) {
|
||||||
token := random.Token()
|
token := random.Token()
|
||||||
item := model.SettingItem{Key: "token", Value: token, Type: conf.TypeString, Group: model.SINGLE, Flag: model.PRIVATE}
|
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)
|
common.ErrorResp(c, err, 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -29,14 +29,14 @@ func GetSetting(c *gin.Context) {
|
||||||
key := c.Query("key")
|
key := c.Query("key")
|
||||||
keys := c.Query("keys")
|
keys := c.Query("keys")
|
||||||
if key != "" {
|
if key != "" {
|
||||||
item, err := db.GetSettingItemByKey(key)
|
item, err := op.GetSettingItemByKey(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.ErrorResp(c, err, 400)
|
common.ErrorResp(c, err, 400)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
common.SuccessResp(c, item)
|
common.SuccessResp(c, item)
|
||||||
} else {
|
} else {
|
||||||
items, err := db.GetSettingItemInKeys(strings.Split(keys, ","))
|
items, err := op.GetSettingItemInKeys(strings.Split(keys, ","))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.ErrorResp(c, err, 400)
|
common.ErrorResp(c, err, 400)
|
||||||
return
|
return
|
||||||
|
@ -51,7 +51,7 @@ func SaveSettings(c *gin.Context) {
|
||||||
common.ErrorResp(c, err, 400)
|
common.ErrorResp(c, err, 400)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := db.SaveSettingItems(req); err != nil {
|
if err := op.SaveSettingItems(req); err != nil {
|
||||||
common.ErrorResp(c, err, 500)
|
common.ErrorResp(c, err, 500)
|
||||||
} else {
|
} else {
|
||||||
common.SuccessResp(c)
|
common.SuccessResp(c)
|
||||||
|
@ -65,7 +65,7 @@ func ListSettings(c *gin.Context) {
|
||||||
var settings []model.SettingItem
|
var settings []model.SettingItem
|
||||||
var err error
|
var err error
|
||||||
if groupsStr == "" && groupStr == "" {
|
if groupsStr == "" && groupStr == "" {
|
||||||
settings, err = db.GetSettingItems()
|
settings, err = op.GetSettingItems()
|
||||||
} else {
|
} else {
|
||||||
var groupStrings []string
|
var groupStrings []string
|
||||||
if groupsStr != "" {
|
if groupsStr != "" {
|
||||||
|
@ -82,7 +82,7 @@ func ListSettings(c *gin.Context) {
|
||||||
}
|
}
|
||||||
groups = append(groups, group)
|
groups = append(groups, group)
|
||||||
}
|
}
|
||||||
settings, err = db.GetSettingItemsInGroups(groups)
|
settings, err = op.GetSettingItemsInGroups(groups)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.ErrorResp(c, err, 400)
|
common.ErrorResp(c, err, 400)
|
||||||
|
@ -93,7 +93,7 @@ func ListSettings(c *gin.Context) {
|
||||||
|
|
||||||
func DeleteSetting(c *gin.Context) {
|
func DeleteSetting(c *gin.Context) {
|
||||||
key := c.Query("key")
|
key := c.Query("key")
|
||||||
if err := db.DeleteSettingItemByKey(key); err != nil {
|
if err := op.DeleteSettingItemByKey(key); err != nil {
|
||||||
common.ErrorResp(c, err, 500)
|
common.ErrorResp(c, err, 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -101,5 +101,5 @@ func DeleteSetting(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func PublicSettings(c *gin.Context) {
|
func PublicSettings(c *gin.Context) {
|
||||||
common.SuccessResp(c, db.GetPublicSettingsMap())
|
common.SuccessResp(c, op.GetPublicSettingsMap())
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ package handles
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/db"
|
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"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/alist-org/alist/v3/server/common"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
@ -18,7 +18,7 @@ func ListUsers(c *gin.Context) {
|
||||||
}
|
}
|
||||||
req.Validate()
|
req.Validate()
|
||||||
log.Debugf("%+v", req)
|
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 {
|
if err != nil {
|
||||||
common.ErrorResp(c, err, 500, true)
|
common.ErrorResp(c, err, 500, true)
|
||||||
return
|
return
|
||||||
|
@ -39,7 +39,7 @@ func CreateUser(c *gin.Context) {
|
||||||
common.ErrorStrResp(c, "admin or guest user can not be created", 400, true)
|
common.ErrorStrResp(c, "admin or guest user can not be created", 400, true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := db.CreateUser(&req); err != nil {
|
if err := op.CreateUser(&req); err != nil {
|
||||||
common.ErrorResp(c, err, 500, true)
|
common.ErrorResp(c, err, 500, true)
|
||||||
} else {
|
} else {
|
||||||
common.SuccessResp(c)
|
common.SuccessResp(c)
|
||||||
|
@ -52,7 +52,7 @@ func UpdateUser(c *gin.Context) {
|
||||||
common.ErrorResp(c, err, 400)
|
common.ErrorResp(c, err, 400)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user, err := db.GetUserById(req.ID)
|
user, err := op.GetUserById(req.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.ErrorResp(c, err, 500)
|
common.ErrorResp(c, err, 500)
|
||||||
return
|
return
|
||||||
|
@ -67,7 +67,7 @@ func UpdateUser(c *gin.Context) {
|
||||||
if req.OtpSecret == "" {
|
if req.OtpSecret == "" {
|
||||||
req.OtpSecret = user.OtpSecret
|
req.OtpSecret = user.OtpSecret
|
||||||
}
|
}
|
||||||
if err := db.UpdateUser(&req); err != nil {
|
if err := op.UpdateUser(&req); err != nil {
|
||||||
common.ErrorResp(c, err, 500)
|
common.ErrorResp(c, err, 500)
|
||||||
} else {
|
} else {
|
||||||
common.SuccessResp(c)
|
common.SuccessResp(c)
|
||||||
|
@ -81,7 +81,7 @@ func DeleteUser(c *gin.Context) {
|
||||||
common.ErrorResp(c, err, 400)
|
common.ErrorResp(c, err, 400)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := db.DeleteUserById(uint(id)); err != nil {
|
if err := op.DeleteUserById(uint(id)); err != nil {
|
||||||
common.ErrorResp(c, err, 500)
|
common.ErrorResp(c, err, 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ func GetUser(c *gin.Context) {
|
||||||
common.ErrorResp(c, err, 400)
|
common.ErrorResp(c, err, 400)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user, err := db.GetUserById(uint(id))
|
user, err := op.GetUserById(uint(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.ErrorResp(c, err, 500, true)
|
common.ErrorResp(c, err, 500, true)
|
||||||
return
|
return
|
||||||
|
@ -110,7 +110,7 @@ func Cancel2FAById(c *gin.Context) {
|
||||||
common.ErrorResp(c, err, 400)
|
common.ErrorResp(c, err, 400)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := db.Cancel2FAById(uint(id)); err != nil {
|
if err := op.Cancel2FAById(uint(id)); err != nil {
|
||||||
common.ErrorResp(c, err, 500)
|
common.ErrorResp(c, err, 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ package middlewares
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/alist-org/alist/v3/internal/conf"
|
"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/model"
|
||||||
|
"github.com/alist-org/alist/v3/internal/op"
|
||||||
"github.com/alist-org/alist/v3/internal/setting"
|
"github.com/alist-org/alist/v3/internal/setting"
|
||||||
"github.com/alist-org/alist/v3/server/common"
|
"github.com/alist-org/alist/v3/server/common"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
@ -15,7 +15,7 @@ import (
|
||||||
func Auth(c *gin.Context) {
|
func Auth(c *gin.Context) {
|
||||||
token := c.GetHeader("Authorization")
|
token := c.GetHeader("Authorization")
|
||||||
if token == setting.GetStr(conf.Token) {
|
if token == setting.GetStr(conf.Token) {
|
||||||
admin, err := db.GetAdmin()
|
admin, err := op.GetAdmin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.ErrorResp(c, err, 500)
|
common.ErrorResp(c, err, 500)
|
||||||
c.Abort()
|
c.Abort()
|
||||||
|
@ -27,7 +27,7 @@ func Auth(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if token == "" {
|
if token == "" {
|
||||||
guest, err := db.GetGuest()
|
guest, err := op.GetGuest()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.ErrorResp(c, err, 500)
|
common.ErrorResp(c, err, 500)
|
||||||
c.Abort()
|
c.Abort()
|
||||||
|
@ -44,7 +44,7 @@ func Auth(c *gin.Context) {
|
||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user, err := db.GetUserByName(userClaims.Username)
|
user, err := op.GetUserByName(userClaims.Username)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.ErrorResp(c, err, 401)
|
common.ErrorResp(c, err, 401)
|
||||||
c.Abort()
|
c.Abort()
|
||||||
|
|
|
@ -4,9 +4,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/conf"
|
"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/errs"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"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/setting"
|
||||||
"github.com/alist-org/alist/v3/internal/sign"
|
"github.com/alist-org/alist/v3/internal/sign"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
|
@ -18,7 +18,7 @@ import (
|
||||||
func Down(c *gin.Context) {
|
func Down(c *gin.Context) {
|
||||||
rawPath := parsePath(c.Param("path"))
|
rawPath := parsePath(c.Param("path"))
|
||||||
c.Set("path", rawPath)
|
c.Set("path", rawPath)
|
||||||
meta, err := db.GetNearestMeta(rawPath)
|
meta, err := op.GetNearestMeta(rawPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
|
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
|
||||||
common.ErrorResp(c, err, 500, true)
|
common.ErrorResp(c, err, 500, true)
|
||||||
|
|
|
@ -4,9 +4,9 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
stdpath "path"
|
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/errs"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"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/alist-org/alist/v3/server/common"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -27,7 +27,7 @@ func FsUp(c *gin.Context) {
|
||||||
common.ErrorResp(c, err, 403)
|
common.ErrorResp(c, err, 403)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
meta, err := db.GetNearestMeta(stdpath.Dir(path))
|
meta, err := op.GetNearestMeta(stdpath.Dir(path))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
|
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
|
||||||
common.ErrorResp(c, err, 500, true)
|
common.ErrorResp(c, err, 500, true)
|
||||||
|
|
|
@ -4,8 +4,8 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"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/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"
|
||||||
"github.com/alist-org/alist/v3/server/webdav"
|
"github.com/alist-org/alist/v3/server/webdav"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
@ -45,7 +45,7 @@ func ServeWebDAV(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func WebDAVAuth(c *gin.Context) {
|
func WebDAVAuth(c *gin.Context) {
|
||||||
guest, _ := db.GetGuest()
|
guest, _ := op.GetGuest()
|
||||||
username, password, ok := c.Request.BasicAuth()
|
username, password, ok := c.Request.BasicAuth()
|
||||||
if !ok {
|
if !ok {
|
||||||
if c.Request.Method == "OPTIONS" {
|
if c.Request.Method == "OPTIONS" {
|
||||||
|
@ -58,7 +58,7 @@ func WebDAVAuth(c *gin.Context) {
|
||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user, err := db.GetUserByName(username)
|
user, err := op.GetUserByName(username)
|
||||||
if err != nil || user.ValidatePassword(password) != nil {
|
if err != nil || user.ValidatePassword(password) != nil {
|
||||||
if c.Request.Method == "OPTIONS" {
|
if c.Request.Method == "OPTIONS" {
|
||||||
c.Set("user", guest)
|
c.Set("user", guest)
|
||||||
|
|
|
@ -10,9 +10,9 @@ import (
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"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/fs"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"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
|
// 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 {
|
if depth == 1 {
|
||||||
depth = 0
|
depth = 0
|
||||||
}
|
}
|
||||||
meta, _ := db.GetNearestMeta(name)
|
meta, _ := op.GetNearestMeta(name)
|
||||||
// Read directory names.
|
// Read directory names.
|
||||||
objs, err := fs.List(context.WithValue(ctx, "meta", meta), name)
|
objs, err := fs.List(context.WithValue(ctx, "meta", meta), name)
|
||||||
//f, err := fs.OpenFile(ctx, name, os.O_RDONLY, 0)
|
//f, err := fs.OpenFile(ctx, name, os.O_RDONLY, 0)
|
||||||
|
|
Loading…
Reference in New Issue