From f7910d47f909a18b5feef08db71d5823fc50569f Mon Sep 17 00:00:00 2001 From: "face.wsl" Date: Fri, 25 Nov 2022 00:18:05 +0800 Subject: [PATCH] fix: sql.settings db --- cmd/utils.go | 3 +- storage/bolt/config.go | 3 ++ storage/sql/settings.go | 98 +++++++++++++++++++++++++++++++---------- storage/sql/share.go | 5 ++- storage/sql/users.go | 5 ++- storage/sql/utils.go | 14 ++++++ 6 files changed, 101 insertions(+), 27 deletions(-) diff --git a/cmd/utils.go b/cmd/utils.go index 961e49e4..650b162f 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -109,7 +109,7 @@ func openBoltDB(path string, cfg pythonConfig) (pythonData, Closeable) { func openDB(path string, cfg pythonConfig) (pythonData, Closeable) { if sql.IsDBPath(path) { - data := pythonData{hadDB: true} + data := pythonData{hadDB: false} db, err := sql.OpenDB(path) if err != nil { log.Fatal("Fail to open database " + path) @@ -118,6 +118,7 @@ func openDB(path string, cfg pythonConfig) (pythonData, Closeable) { if err != nil { log.Fatal("Fail to create database storage for " + path) } + data.hadDB = sql.HadSetting(db) return data, db } return openBoltDB(path, cfg) diff --git a/storage/bolt/config.go b/storage/bolt/config.go index a4d40064..25e0e1a5 100644 --- a/storage/bolt/config.go +++ b/storage/bolt/config.go @@ -4,6 +4,7 @@ import ( "github.com/asdine/storm/v3" "github.com/filebrowser/filebrowser/v2/settings" + "github.com/filebrowser/filebrowser/v2/storage/sql" ) type settingsBackend struct { @@ -16,6 +17,7 @@ func (s settingsBackend) Get() (*settings.Settings, error) { } func (s settingsBackend) Save(set *settings.Settings) error { + sql.LogBacktrace() return save(s.db, "settings", set) } @@ -25,5 +27,6 @@ func (s settingsBackend) GetServer() (*settings.Server, error) { } func (s settingsBackend) SaveServer(server *settings.Server) error { + sql.LogBacktrace() return save(s.db, "server", server) } diff --git a/storage/sql/settings.go b/storage/sql/settings.go index 105b443e..076ada86 100644 --- a/storage/sql/settings.go +++ b/storage/sql/settings.go @@ -3,8 +3,6 @@ package sql import ( "database/sql" "encoding/json" - "fmt" - "strings" "github.com/filebrowser/filebrowser/v2/auth" "github.com/filebrowser/filebrowser/v2/files" @@ -128,6 +126,7 @@ func boolToString(b bool) string { } func (s settingsBackend) Get() (*settings.Settings, error) { + logBacktrace() sql := "select key, value from settings" rows, err := s.db.Query(sql) if checkError(err, "Fail to Query settings.Settings") { @@ -159,28 +158,50 @@ func (s settingsBackend) Get() (*settings.Settings, error) { settings1.Rules = rulesFromString(value) } } + if len(settings1.Key) == 0 { + return nil, nil + } return &settings1, nil } func (s settingsBackend) Save(ss *settings.Settings) error { - columns := []string{"Key", "Signup", "CreateUserDir", "UserHomeBasePath", "Defaults", "AuthMethod", "Branding", "Commands", "Shell", "Rules"} + logBacktrace() + fields := []string{"Key", "Signup", "CreateUserDir", "UserHomeBasePath", "Defaults", "AuthMethod", "Branding", "Commands", "Shell", "Rules"} values := []string{ - "'" + string(ss.Key) + "'", + string(ss.Key), boolToString(ss.Signup), boolToString(ss.CreateUserDir), - "'" + string(ss.UserHomeBasePath) + "'", + string(ss.UserHomeBasePath), userDefaultsToString(ss.Defaults), string(ss.AuthMethod), brandingToString(ss.Branding), commandsToString(ss.Commands), stringsToString(ss.Shell), - RulesToString(ss.Rules)} - sql := fmt.Sprintf("INSERT INTO settings (%s) VALUES(%s)", strings.Join(columns, ","), strings.Join(values, ",")) - _, err := s.db.Exec(sql) - if checkError(err, "Fail to insert settings.Settings") { + RulesToString(ss.Rules), + } + tx, err := s.db.Begin() + if checkError(err, "Fail to begin db transaction") { return err } - return nil + for i, field := range fields { + stmt, err := s.db.Prepare("INSERT INTO settings (key, value) VALUES(?,?)") + defer stmt.Close() + if checkError(err, "Fail to prepare statement") { + tx.Rollback() + break + } + _, err = stmt.Exec(field, values[i]) + if checkError(err, "Fail to insert field "+field+" of settings") { + tx.Rollback() + break + } + } + err = tx.Commit() + if checkError(err, "Fail to commit") { + tx.Rollback() + return err + } + return err } var defaultServer = settings.Server{ @@ -255,6 +276,7 @@ func cloneSettings(s settings.Settings) settings.Settings { } func (s settingsBackend) GetServer() (*settings.Server, error) { + logBacktrace() sql := "select key, value from settings" rows, err := s.db.Query(sql) if checkError(err, "Fail to Query for GetServer") { @@ -301,27 +323,45 @@ func (s settingsBackend) GetServer() (*settings.Server, error) { } func (s settingsBackend) SaveServer(ss *settings.Server) error { - columns := []string{"Root", "BaseURL", "Socket", "TLSKey", "TLSCert", "Port", "Address", "Log", "EnableThumbnails", "ResizePreview", "EnableExec", "TypeDetectionByHeader", "AuthHook"} + logBacktrace() + fields := []string{"Root", "BaseURL", "Socket", "TLSKey", "TLSCert", "Port", "Address", "Log", "EnableThumbnails", "ResizePreview", "EnableExec", "TypeDetectionByHeader", "AuthHook"} values := []string{ - "'" + ss.Root + "'", - "'" + ss.BaseURL + "'", - "'" + ss.Socket + "'", - "'" + ss.TLSKey + "'", - "'" + ss.TLSCert + "'", - "'" + ss.Port + "'", - "'" + ss.Address + "'", - "'" + ss.Log + "'", + ss.Root, + ss.BaseURL, + ss.Socket, + ss.TLSKey, + ss.TLSCert, + ss.Port, + ss.Address, + ss.Log, boolToString(ss.EnableThumbnails), boolToString(ss.ResizePreview), boolToString(ss.EnableExec), boolToString(ss.TypeDetectionByHeader), - "'" + ss.AuthHook + "'"} - sql := fmt.Sprintf("INSERT INTO settings (%s) VALUES(%s)", strings.Join(columns, ","), strings.Join(values, ",")) - _, err := s.db.Exec(sql) - if checkError(err, "Fail to insert for settings.Settings") { + ss.AuthHook} + tx, err := s.db.Begin() + if checkError(err, "Fail to begin db transaction") { return err } - return nil + for i, field := range fields { + stmt, err := s.db.Prepare("INSERT INTO settings (key, value) VALUES(?,?)") + defer stmt.Close() + if checkError(err, "Fail to prepare statement") { + tx.Rollback() + break + } + _, err = stmt.Exec(field, values[i]) + if checkError(err, "Fail to insert field "+field+" of settings") { + tx.Rollback() + break + } + } + err = tx.Commit() + if checkError(err, "Fail to commit") { + tx.Rollback() + return err + } + return err } func SetSetting(db *sql.DB, key string, value string) error { @@ -350,11 +390,21 @@ func GetSetting(db *sql.DB, key string) string { func addSetting(db *sql.DB, key string, value string) error { sql := "insert into settings(key, value) values('" + key + "', '" + value + "')" _, err := db.Exec(sql) + checkError(err, "Fail to addSetting") return err } func updateSetting(db *sql.DB, key string, value string) error { sql := "update settings set value = '" + value + "' where key = '" + key + "'" _, err := db.Exec(sql) + checkError(err, "Fail to updateSetting") return err } + +func HadSetting(db *sql.DB) bool { + key := GetSetting(db, "Key") + if key == "" { + return false + } + return true +} diff --git a/storage/sql/share.go b/storage/sql/share.go index 0ab865b9..21e3182e 100644 --- a/storage/sql/share.go +++ b/storage/sql/share.go @@ -16,8 +16,9 @@ type linkRecord interface { } func InitShareTable(db *sql.DB) error { - sql := "create table if not exists share_links (path string, userid integer, expire integer, passwordhash string, token string)" + sql := "create table if not exists share_links (hash string, path string, userid integer, expire integer, passwordhash string, token string)" _, err := db.Exec(sql) + checkError(err, "Fail to InitShareTable") return err } @@ -88,10 +89,12 @@ func (s shareBackend) Gets(path string, id uint) ([]*share.Link, error) { func (s shareBackend) Save(l *share.Link) error { sql := fmt.Sprintf("insert into share_links (hash, path, userid, expire, passwordhash, token) values('%s', '%s', %d, %d, '%s', '%s')", l.Hash, l.Path, l.UserID, l.Expire, l.PasswordHash, l.Token) _, err := s.db.Exec(sql) + checkError(err, "Fail to Save share") return err } func (s shareBackend) Delete(hash string) error { sql := fmt.Sprintf("DELETE FROM share_links WHERE hash='%s'", hash) _, err := s.db.Exec(sql) + checkError(err, "Fail to Delete share") return err } diff --git a/storage/sql/users.go b/storage/sql/users.go index f5bb2742..b7827069 100644 --- a/storage/sql/users.go +++ b/storage/sql/users.go @@ -124,6 +124,7 @@ func InitUserTable(db *sql.DB) error { return err } user, err := usersBackend{db}.Get("admin") + checkError(err, "Fail to query admin user") if user == nil { log.Println("No admin exists") err := usersBackend{db}.Save(&adminUser) @@ -276,7 +277,7 @@ func (s usersBackend) insertUser(user *users.User) error { } columns := []string{} specs := []string{} - for _,c := range columnSpec { + for _, c := range columnSpec { columns = append(columns, c[0]) specs = append(specs, c[1]) } @@ -318,6 +319,7 @@ func (s usersBackend) DeleteByID(id uint) error { logBacktrace() sql := "delete from users where id=" + strconv.Itoa(int(id)) _, err := s.db.Exec(sql) + checkError(err, "Fail to delete User by id") return err } @@ -325,6 +327,7 @@ func (s usersBackend) DeleteByUsername(username string) error { logBacktrace() sql := "delete from users where username='" + username + "'" _, err := s.db.Exec(sql) + checkError(err, "Fail to delete user by username") return err } diff --git a/storage/sql/utils.go b/storage/sql/utils.go index 202155a9..db6f104e 100644 --- a/storage/sql/utils.go +++ b/storage/sql/utils.go @@ -55,3 +55,17 @@ func logBacktrace() { funcs = reverse(funcs) log.Printf("%s\n", strings.Join(funcs, " -> ")) } + +func LogBacktrace() { + funcs := make([]string, 0) + for _, i := range []int{1, 2, 3} { + p := filepath.Base(getRuntimeFunctionName(uint(i))) + if len(p) > 0 { + funcs = append(funcs, p) + } else { + break + } + } + funcs = reverse(funcs) + log.Printf("%s\n", strings.Join(funcs, " -> ")) +}