diff --git a/.gitignore b/.gitignore index 2aba0ec56ca..f73edf4fd49 100644 --- a/.gitignore +++ b/.gitignore @@ -27,5 +27,5 @@ bin/* public/*.html public/assets/ public/public/ -data/ +/data log/ \ No newline at end of file diff --git a/cmd/alist.go b/cmd/alist.go index aa464084cf0..45f186b1f12 100644 --- a/cmd/alist.go +++ b/cmd/alist.go @@ -3,11 +3,12 @@ package main import ( "flag" "fmt" + bootstrap2 "github.com/alist-org/alist/v3/internal/bootstrap" + "github.com/alist-org/alist/v3/internal/bootstrap/data" "github.com/alist-org/alist/v3/internal/conf" "github.com/alist-org/alist/v3/server" "os" - "github.com/alist-org/alist/v3/bootstrap" "github.com/alist-org/alist/v3/cmd/args" _ "github.com/alist-org/alist/v3/drivers" "github.com/gin-gonic/gin" @@ -30,10 +31,10 @@ func Init() { conf.BuiltAt, conf.GoVersion, conf.GitAuthor, conf.GitCommit, conf.Version, conf.WebVersion) os.Exit(0) } - bootstrap.InitConfig() - bootstrap.Log() - bootstrap.InitDB() - bootstrap.InitData() + bootstrap2.InitConfig() + bootstrap2.Log() + bootstrap2.InitDB() + data.InitData() } func main() { Init() diff --git a/bootstrap/config.go b/internal/bootstrap/config.go similarity index 100% rename from bootstrap/config.go rename to internal/bootstrap/config.go diff --git a/internal/bootstrap/data/data.go b/internal/bootstrap/data/data.go new file mode 100644 index 00000000000..207e40f125f --- /dev/null +++ b/internal/bootstrap/data/data.go @@ -0,0 +1,6 @@ +package data + +func InitData() { + initUser() + initSettings() +} diff --git a/internal/bootstrap/data/setting.go b/internal/bootstrap/data/setting.go new file mode 100644 index 00000000000..a68bb5bb3aa --- /dev/null +++ b/internal/bootstrap/data/setting.go @@ -0,0 +1,78 @@ +package data + +import ( + "github.com/alist-org/alist/v3/internal/conf" + "github.com/alist-org/alist/v3/internal/db" + "github.com/alist-org/alist/v3/internal/model" + "github.com/pkg/errors" + log "github.com/sirupsen/logrus" + "gorm.io/gorm" +) + +var initialSettingItems = []model.SettingItem{ + // site settings + {Key: "version", Value: conf.Version, Type: conf.TypeString, Group: model.SITE, Flag: model.READONLY}, + {Key: "site_title", Value: "AList", Type: conf.TypeString, Group: model.SITE}, + {Key: "site_logo", Value: "https://cdn.jsdelivr.net/gh/alist-org/logo@main/logo.svg", Type: conf.TypeString, Group: model.SITE}, + {Key: "favicon", Value: "https://cdn.jsdelivr.net/gh/alist-org/logo@main/logo.svg", Type: conf.TypeString, Group: model.SITE}, + {Key: "announcement", Value: "https://github.com/alist-org/alist", Type: conf.TypeString, Group: model.SITE}, + // style settings + {Key: "icon_color", Value: "#1890ff", Type: conf.TypeString, Group: model.STYLE}, + // preview settings + {Key: "text_types", Value: "txt,htm,html,xml,java,properties,sql,js,md,json,conf,ini,vue,php,py,bat,gitignore,yml,go,sh,c,cpp,h,hpp,tsx,vtt,srt,ass,rs,lrc", Type: conf.TypeText, Group: model.PREVIEW, Flag: model.PRIVATE}, + {Key: "audio_types", Value: "mp3,flac,ogg,m4a,wav,opus", Type: conf.TypeText, Group: model.PREVIEW, Flag: model.PRIVATE}, + {Key: "video_types", Value: "mp4,mkv,avi,mov,rmvb,webm,flv", Type: conf.TypeText, Group: model.PREVIEW, Flag: model.PRIVATE}, + {Key: "proxy_types", Value: "m3u8", Type: conf.TypeText, Group: model.PREVIEW, Flag: model.PRIVATE}, + {Key: "pdf_viewer_url", Value: "https://alist-org.github.io/pdf.js/web/viewer.html?file=$url", Type: conf.TypeString, Group: model.PREVIEW}, + {Key: "audio_autoplay", Value: "true", Type: conf.TypeBool, Group: model.PREVIEW}, + {Key: "video_autoplay", Value: "true", Type: conf.TypeBool, Group: model.PREVIEW}, + // global settings + {Key: "hide_files", Value: "/\\/README.md/i", Type: conf.TypeText, Group: model.GLOBAL}, + {Key: "global_readme", Value: "This is global readme", Type: conf.TypeText, Group: model.GLOBAL}, + {Key: "customize_head", Type: conf.TypeText, Group: model.GLOBAL, Flag: model.PRIVATE}, + {Key: "customize_body", Type: conf.TypeText, Group: model.GLOBAL, Flag: model.PRIVATE}, +} + +func initSettings() { + // check deprecated + settings, err := db.GetSettings() + if err != nil { + log.Fatalf("failed get settings: %+v", err) + } + for i := range settings { + if !isActive(settings[i].Key) { + settings[i].Flag = model.DEPRECATED + } + } + if settings != nil && len(settings) > 0 { + err = db.SaveSettings(settings) + if err != nil { + log.Fatalf("failed save settings: %+v", err) + } + } + // insert new items + for i, _ := range initialSettingItems { + v := initialSettingItems[i] + _, err := db.GetSettingByKey(v.Key) + if err == nil { + continue + } + if errors.Is(err, gorm.ErrRecordNotFound) { + err = db.SaveSetting(v) + if err != nil { + log.Fatalf("failed create setting: %+v", err) + } + } else { + log.Fatalf("failed get setting: %+v", err) + } + } +} + +func isActive(key string) bool { + for _, item := range initialSettingItems { + if item.Key == key { + return true + } + } + return false +} diff --git a/bootstrap/data.go b/internal/bootstrap/data/user.go similarity index 95% rename from bootstrap/data.go rename to internal/bootstrap/data/user.go index c2a6cb43932..b3f7a7bd51f 100644 --- a/bootstrap/data.go +++ b/internal/bootstrap/data/user.go @@ -1,4 +1,4 @@ -package bootstrap +package data import ( "github.com/alist-org/alist/v3/cmd/args" @@ -10,10 +10,6 @@ import ( "gorm.io/gorm" ) -func InitData() { - initUser() -} - func initUser() { admin, err := db.GetAdmin() adminPassword := random.String(8) diff --git a/bootstrap/db.go b/internal/bootstrap/db.go similarity index 100% rename from bootstrap/db.go rename to internal/bootstrap/db.go diff --git a/bootstrap/log.go b/internal/bootstrap/log.go similarity index 100% rename from bootstrap/log.go rename to internal/bootstrap/log.go diff --git a/internal/db/store.go b/internal/db/db.go similarity index 88% rename from internal/db/store.go rename to internal/db/db.go index 6ea5645fb33..6e24a3f5788 100644 --- a/internal/db/store.go +++ b/internal/db/db.go @@ -10,7 +10,7 @@ var db gorm.DB func Init(d *gorm.DB) { db = *d - err := db.AutoMigrate(new(model.Account), new(model.User), new(model.Meta)) + err := db.AutoMigrate(new(model.Account), new(model.User), new(model.Meta), new(model.SettingItem)) if err != nil { log.Fatalf("failed migrate database: %s", err.Error()) } diff --git a/internal/db/setting.go b/internal/db/setting.go index 486ed72b0cf..a39c7095bb3 100644 --- a/internal/db/setting.go +++ b/internal/db/setting.go @@ -6,12 +6,28 @@ import ( "github.com/pkg/errors" ) -func SaveSettings(items []model.SettingItem) error { - return errors.WithStack(db.Save(items).Error) +func GetSettings() ([]model.SettingItem, error) { + var items []model.SettingItem + if err := db.Find(&items).Error; err != nil { + return nil, errors.WithStack(err) + } + return items, nil } -func SaveSetting(item model.SettingItem) error { - return errors.WithStack(db.Save(item).Error) +func GetSettingByKey(key string) (*model.SettingItem, error) { + var item model.SettingItem + if err := db.Where(fmt.Sprintf("%s = ?", columnName("key")), key).First(&item).Error; err != nil { + return nil, errors.WithStack(err) + } + return &item, nil +} + +func GetPublicSettings() ([]model.SettingItem, error) { + var items []model.SettingItem + if err := db.Where(fmt.Sprintf("%s in ?", columnName("flag")), []int{0, 2}).Find(&items).Error; err != nil { + return nil, err + } + return items, nil } func GetSettingsByGroup(group int) ([]model.SettingItem, error) { @@ -22,6 +38,14 @@ func GetSettingsByGroup(group int) ([]model.SettingItem, error) { return items, nil } +func SaveSettings(items []model.SettingItem) error { + return errors.WithStack(db.Save(items).Error) +} + +func SaveSetting(item model.SettingItem) error { + return errors.WithStack(db.Save(item).Error) +} + func DeleteSettingByKey(key string) error { setting := model.SettingItem{ Key: key, diff --git a/internal/model/setting.go b/internal/model/setting.go index 6865113f26a..b619e1109cd 100644 --- a/internal/model/setting.go +++ b/internal/model/setting.go @@ -1,5 +1,19 @@ package model +const ( + SITE = iota + STYLE + PREVIEW + GLOBAL +) + +const ( + PUBLIC = iota + PRIVATE + READONLY + DEPRECATED +) + type SettingItem struct { Key string `json:"key" gorm:"primaryKey" binding:"required"` // unique key Value string `json:"value"` // value @@ -7,5 +21,5 @@ type SettingItem struct { Type string `json:"type"` // string, number, bool, select Values string `json:"values"` // values for select Group int `json:"group"` // use to group setting in frontend - Access int `json:"access"` // admin/guest/general + Flag int `json:"flag"` // 0 = public, 1 = private, 2 = deprecated, etc. }