fix: user default

This commit is contained in:
face.wsl 2022-11-23 21:09:35 +08:00
parent 83deb8b143
commit 1ac77024e5
6 changed files with 183 additions and 80 deletions

View File

@ -15,6 +15,7 @@ type authBackend struct {
} }
func (s authBackend) Get(t settings.AuthMethod) (auth.Auther, error) { func (s authBackend) Get(t settings.AuthMethod) (auth.Auther, error) {
logBacktrace()
var auther auth.Auther var auther auth.Auther
switch t { switch t {
@ -30,17 +31,12 @@ func (s authBackend) Get(t settings.AuthMethod) (auth.Auther, error) {
fmt.Println("ERROR: unknown auth method " + t) fmt.Println("ERROR: unknown auth method " + t)
return nil, errors.ErrInvalidAuthMethod return nil, errors.ErrInvalidAuthMethod
} }
return auther, nil
val := GetSetting(s.db, "auther")
if val == "" {
return auther, nil
}
return auther, json.Unmarshal([]byte(val), auther)
} }
func (s authBackend) Save(a auth.Auther) error { func (s authBackend) Save(a auth.Auther) error {
val, err := json.Marshal(a) val, err := json.Marshal(a)
if !checkError(err, "Fail to save auth.Auther") { if checkError(err, "Fail to save auth.Auther") {
return err return err
} }
return SetSetting(s.db, "auther", string(val)) return SetSetting(s.db, "auther", string(val))

View File

@ -6,12 +6,16 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/filebrowser/filebrowser/v2/auth"
"github.com/filebrowser/filebrowser/v2/files" "github.com/filebrowser/filebrowser/v2/files"
"github.com/filebrowser/filebrowser/v2/rules" "github.com/filebrowser/filebrowser/v2/rules"
"github.com/filebrowser/filebrowser/v2/settings" "github.com/filebrowser/filebrowser/v2/settings"
"github.com/filebrowser/filebrowser/v2/users" "github.com/filebrowser/filebrowser/v2/users"
) )
func init() {
}
type settingsBackend struct { type settingsBackend struct {
db *sql.DB db *sql.DB
} }
@ -35,7 +39,7 @@ func userDefaultsFromString(s string) settings.UserDefaults {
func userDefaultsToString(d settings.UserDefaults) string { func userDefaultsToString(d settings.UserDefaults) string {
data, err := json.Marshal(d) data, err := json.Marshal(d)
if !checkError(err, "Fail to stringify settings.UserDefaults") { if checkError(err, "Fail to stringify settings.UserDefaults") {
return "" return ""
} }
return string(data) return string(data)
@ -53,7 +57,7 @@ func brandingFromString(s string) settings.Branding {
func brandingToString(s settings.Branding) string { func brandingToString(s settings.Branding) string {
data, err := json.Marshal(s) data, err := json.Marshal(s)
if !checkError(err, "Fail to jsonify settings.Branding") { if checkError(err, "Fail to jsonify settings.Branding") {
return "" return ""
} }
return string(data) return string(data)
@ -61,27 +65,27 @@ func brandingToString(s settings.Branding) string {
func commandsToString(c map[string][]string) string { func commandsToString(c map[string][]string) string {
data, err := json.Marshal(c) data, err := json.Marshal(c)
if !checkError(err, "Fail to jsonify commands") { if checkError(err, "Fail to jsonify commands") {
return "" return ""
} }
return string(data) return string(data)
} }
func commandsFromString(s string) map[string][]string { func commandsFromString(s string) map[string][]string {
c := make(map[string][]string)
if s == "" { if s == "" {
return map[string][]string{} return c
} }
c := map[string][]string{}
err := json.Unmarshal([]byte(s), &c) err := json.Unmarshal([]byte(s), &c)
checkError(err, "Fail to parse commands") checkError(err, "Fail to parse commands")
return c return c
} }
func stringsFromString(s string) []string { func stringsFromString(s string) []string {
c := make([]string, 0)
if s == "" { if s == "" {
return []string{} return c
} }
c := []string{}
err := json.Unmarshal([]byte(s), &c) err := json.Unmarshal([]byte(s), &c)
checkError(err, "Fail to parse []string") checkError(err, "Fail to parse []string")
return c return c
@ -89,7 +93,7 @@ func stringsFromString(s string) []string {
func stringsToString(c []string) string { func stringsToString(c []string) string {
data, err := json.Marshal(c) data, err := json.Marshal(c)
if !checkError(err, "Fail to jsonify strings") { if checkError(err, "Fail to jsonify strings") {
return "" return ""
} }
return string(data) return string(data)
@ -126,7 +130,7 @@ func boolToString(b bool) string {
func (s settingsBackend) Get() (*settings.Settings, error) { func (s settingsBackend) Get() (*settings.Settings, error) {
sql := "select key, value from settings" sql := "select key, value from settings"
rows, err := s.db.Query(sql) rows, err := s.db.Query(sql)
if !checkError(err, "Fail to Query settings.Settings") { if checkError(err, "Fail to Query settings.Settings") {
return nil, err return nil, err
} }
key := "" key := ""
@ -173,7 +177,7 @@ func (s settingsBackend) Save(ss *settings.Settings) error {
RulesToString(ss.Rules)} RulesToString(ss.Rules)}
sql := fmt.Sprintf("INSERT INTO settings (%s) VALUES(%s)", strings.Join(columns, ","), strings.Join(values, ",")) sql := fmt.Sprintf("INSERT INTO settings (%s) VALUES(%s)", strings.Join(columns, ","), strings.Join(values, ","))
_, err := s.db.Exec(sql) _, err := s.db.Exec(sql)
if !checkError(err, "Fail to insert settings.Settings") { if checkError(err, "Fail to insert settings.Settings") {
return err return err
} }
return nil return nil
@ -212,11 +216,11 @@ var defaultSettings = settings.Settings{
Share: true, Share: true,
Download: true, Download: true,
}, },
Commands: []string{}, Commands: make([]string, 0),
HideDotfiles: false, HideDotfiles: false,
DateFormat: false, DateFormat: false,
}, },
AuthMethod: "json", AuthMethod: auth.MethodJSONAuth,
Branding: settings.Branding{ Branding: settings.Branding{
Name: "", Name: "",
DisableExternal: false, DisableExternal: false,
@ -224,27 +228,28 @@ var defaultSettings = settings.Settings{
Theme: "", Theme: "",
Color: "", Color: "",
}, },
Commands: map[string][]string{}, Commands: make(map[string][]string),
Shell: []string{}, Shell: make([]string, 0),
Rules: []rules.Rule{}, Rules: make([]rules.Rule, 0),
} }
func cloneServer(server settings.Server) settings.Server { func cloneServer(server settings.Server) settings.Server {
data, err := json.Marshal(server) data, err := json.Marshal(server)
if !checkError(err, "Fail to clone settings.Server") {
return settings.Server{}
}
s := settings.Server{} s := settings.Server{}
json.Unmarshal(data, &s) if checkError(err, "Fail to clone settings.Server") {
return s
}
err = json.Unmarshal(data, &s)
checkError(err, "Fail to decode for settings.Server")
return s return s
} }
func cloneSettings(s settings.Settings) settings.Settings { func cloneSettings(s settings.Settings) settings.Settings {
data, err := json.Marshal(s) data, err := json.Marshal(s)
if !checkError(err, "Fail to clone settings.Settings") {
return settings.Settings{}
}
s1 := settings.Settings{} s1 := settings.Settings{}
if checkError(err, "Fail to clone settings.Settings") {
return s1
}
json.Unmarshal(data, &s1) json.Unmarshal(data, &s1)
return s1 return s1
} }
@ -252,7 +257,7 @@ func cloneSettings(s settings.Settings) settings.Settings {
func (s settingsBackend) GetServer() (*settings.Server, error) { func (s settingsBackend) GetServer() (*settings.Server, error) {
sql := "select key, value from settings" sql := "select key, value from settings"
rows, err := s.db.Query(sql) rows, err := s.db.Query(sql)
if !checkError(err, "Fail to Query for GetServer") { if checkError(err, "Fail to Query for GetServer") {
return nil, err return nil, err
} }
server := cloneServer(defaultServer) server := cloneServer(defaultServer)
@ -261,7 +266,7 @@ func (s settingsBackend) GetServer() (*settings.Server, error) {
for rows.Next() { for rows.Next() {
err = rows.Scan(&key, &value) err = rows.Scan(&key, &value)
if !checkError(err, "Fail to query settings.Settings") { if checkError(err, "Fail to query settings.Settings") {
continue continue
} }
if key == "Root" { if key == "Root" {
@ -313,7 +318,7 @@ func (s settingsBackend) SaveServer(ss *settings.Server) error {
"'" + ss.AuthHook + "'"} "'" + ss.AuthHook + "'"}
sql := fmt.Sprintf("INSERT INTO settings (%s) VALUES(%s)", strings.Join(columns, ","), strings.Join(values, ",")) sql := fmt.Sprintf("INSERT INTO settings (%s) VALUES(%s)", strings.Join(columns, ","), strings.Join(values, ","))
_, err := s.db.Exec(sql) _, err := s.db.Exec(sql)
if !checkError(err, "Fail to insert for settings.Settings") { if checkError(err, "Fail to insert for settings.Settings") {
return err return err
} }
return nil return nil
@ -323,7 +328,7 @@ func SetSetting(db *sql.DB, key string, value string) error {
sql := "select count(key) from settings where key = '" + key + "'" sql := "select count(key) from settings where key = '" + key + "'"
count := 0 count := 0
err := db.QueryRow(sql).Scan(&count) err := db.QueryRow(sql).Scan(&count)
if !checkError(err, "Fail to QueryRow for key="+key) { if checkError(err, "Fail to QueryRow for key="+key) {
return err return err
} }
if count == 0 { if count == 0 {
@ -336,7 +341,7 @@ func GetSetting(db *sql.DB, key string) string {
sql := "select value from settings where key = '" + key + "';" sql := "select value from settings where key = '" + key + "';"
value := "" value := ""
err := db.QueryRow(sql).Scan(&value) err := db.QueryRow(sql).Scan(&value)
if !checkError(err, "Fail to QueryRow for key "+key) { if checkError(err, "Fail to QueryRow for key "+key) {
return value return value
} }
return value return value

View File

@ -29,7 +29,7 @@ func parseLink(row linkRecord) (*share.Link, error) {
passwordhash := "" passwordhash := ""
token := "" token := ""
err := row.Scan(&path, &hash, &userid, &expire, &passwordhash, &token) err := row.Scan(&path, &hash, &userid, &expire, &passwordhash, &token)
if !checkError(err, "Fail to parse record for share.Link") { if checkError(err, "Fail to parse record for share.Link") {
return nil, err return nil, err
} }
link := share.Link{} link := share.Link{}
@ -48,13 +48,13 @@ func queryLinks(db *sql.DB, condition string) ([]*share.Link, error) {
sql = sql + " where " + condition sql = sql + " where " + condition
} }
rows, err := db.Query(sql) rows, err := db.Query(sql)
if !checkError(err, "Fail to Query links") { if checkError(err, "Fail to Query links") {
return nil, err return nil, err
} }
var links []*share.Link = []*share.Link{} var links []*share.Link = []*share.Link{}
for rows.Next() { for rows.Next() {
link, err := parseLink(rows) link, err := parseLink(rows)
if !checkError(err, "Fail to parse record for share.Link") { if checkError(err, "Fail to parse record for share.Link") {
continue continue
} }
links = append(links, link) links = append(links, link)

View File

@ -3,7 +3,6 @@ package sql
import ( import (
"database/sql" "database/sql"
"errors" "errors"
"fmt"
"strings" "strings"
"github.com/filebrowser/filebrowser/v2/auth" "github.com/filebrowser/filebrowser/v2/auth"
@ -56,17 +55,19 @@ func NewStorage(db *sql.DB) (*storage.Storage, error) {
authStore := auth.NewStorage(authBackend{db: db}, userStore) authStore := auth.NewStorage(authBackend{db: db}, userStore)
err := SetSetting(db, "version", "2") err := SetSetting(db, "version", "2")
if !checkError(err, "Fail to set version") { if checkError(err, "Fail to set version") {
return nil, err return nil, err
} }
// TODO: default // TODO: default
if GetSetting(db, "auther") == "" { /*
err := SetSetting(db, "auther", "json") if GetSetting(db, "auther") == "" {
if !checkError(err, "Fail to set auther") { err := SetSetting(db, "auther", "json")
return nil, err if checkError(err, "Fail to set auther") {
return nil, err
}
} }
} */
storage := &storage.Storage{ storage := &storage.Storage{
Auth: authStore, Auth: authStore,
@ -76,12 +77,3 @@ func NewStorage(db *sql.DB) (*storage.Storage, error) {
} }
return storage, nil return storage, nil
} }
func checkError(err error, message string) bool {
if err != nil {
fmt.Println("ERROR: " + err.Error())
fmt.Println("ERROR: " + message)
return false
}
return true
}

View File

@ -4,10 +4,12 @@ import (
"database/sql" "database/sql"
"encoding/json" "encoding/json"
"fmt" "fmt"
"log"
"reflect" "reflect"
"strconv" "strconv"
"strings" "strings"
"github.com/filebrowser/filebrowser/v2/errors"
"github.com/filebrowser/filebrowser/v2/files" "github.com/filebrowser/filebrowser/v2/files"
"github.com/filebrowser/filebrowser/v2/rules" "github.com/filebrowser/filebrowser/v2/rules"
"github.com/filebrowser/filebrowser/v2/users" "github.com/filebrowser/filebrowser/v2/users"
@ -18,10 +20,10 @@ type usersBackend struct {
} }
func PermFromString(s string) users.Permissions { func PermFromString(s string) users.Permissions {
if s == "" {
return users.Permissions{}
}
var perm users.Permissions var perm users.Permissions
if s == "" {
return perm
}
err := json.Unmarshal([]byte(s), &perm) err := json.Unmarshal([]byte(s), &perm)
checkError(err, "Fail to parse perm from string") checkError(err, "Fail to parse perm from string")
return perm return perm
@ -29,7 +31,7 @@ func PermFromString(s string) users.Permissions {
func PermToString(perm users.Permissions) string { func PermToString(perm users.Permissions) string {
data, err := json.Marshal(perm) data, err := json.Marshal(perm)
if !checkError(err, "Fail to stringify users.Permissions") { if checkError(err, "Fail to stringify users.Permissions") {
return "" return ""
} }
return string(data) return string(data)
@ -37,7 +39,7 @@ func PermToString(perm users.Permissions) string {
func CommandsFromString(s string) []string { func CommandsFromString(s string) []string {
if s == "" { if s == "" {
return []string{} return make([]string, 0)
} }
var commands []string var commands []string
err := json.Unmarshal([]byte(s), &commands) err := json.Unmarshal([]byte(s), &commands)
@ -47,7 +49,7 @@ func CommandsFromString(s string) []string {
func CommandsToString(commands []string) string { func CommandsToString(commands []string) string {
data, err := json.Marshal(commands) data, err := json.Marshal(commands)
if !checkError(err, "Fail to stringify users commands") { if checkError(err, "Fail to stringify users commands") {
return "" return ""
} }
return string(data) return string(data)
@ -65,17 +67,17 @@ func SortingFromString(s string) files.Sorting {
func SortingToString(sorting files.Sorting) string { func SortingToString(sorting files.Sorting) string {
data, err := json.Marshal(sorting) data, err := json.Marshal(sorting)
if !checkError(err, "Fail to stringify files.Sorting") { if checkError(err, "Fail to stringify files.Sorting") {
return "" return ""
} }
return string(data) return string(data)
} }
func rulesFromString(s string) []rules.Rule { func rulesFromString(s string) []rules.Rule {
rules := make([]rules.Rule, 0)
if s == "" { if s == "" {
return []rules.Rule{} return rules
} }
var rules []rules.Rule
err := json.Unmarshal([]byte(s), &rules) err := json.Unmarshal([]byte(s), &rules)
checkError(err, "Fail to parse Rules from string") checkError(err, "Fail to parse Rules from string")
return rules return rules
@ -83,34 +85,82 @@ func rulesFromString(s string) []rules.Rule {
func RulesToString(rules []rules.Rule) string { func RulesToString(rules []rules.Rule) string {
data, err := json.Marshal(rules) data, err := json.Marshal(rules)
if !checkError(err, "Fail to stringify []rules.Rule") { if checkError(err, "Fail to stringify []rules.Rule") {
return "" return ""
} }
return string(data) return string(data)
} }
var adminUser = createAdminUser()
func createAdminUser() users.User {
userDefault := defaultSettings.Defaults
user := users.User{}
user.Username = "admin"
user.Password = "admin"
user.Scope = userDefault.Scope
user.LockPassword = false
user.ViewMode = userDefault.ViewMode
user.Perm = users.Permissions{
Admin: true,
Execute: true,
Create: true,
Rename: true,
Modify: true,
Delete: true,
Share: true,
Download: true,
}
user.Commands = userDefault.Commands
user.Sorting = userDefault.Sorting
return user
}
func InitUserTable(db *sql.DB) error { func InitUserTable(db *sql.DB) error {
logBacktrace()
sql := "create table if not exists users (id integer primary key, username string, password string, scope string, lockpassword bool, viewmode string, perm string, commands string, sorting string, rules string);" sql := "create table if not exists users (id integer primary key, username string, password string, scope string, lockpassword bool, viewmode string, perm string, commands string, sorting string, rules string);"
_, err := db.Exec(sql) _, err := db.Exec(sql)
if checkError(err, "Fail to create users table") {
return err
}
user, err := usersBackend{db}.Get("admin")
if user == nil {
log.Println("No admin exists")
err := usersBackend{db}.Save(&adminUser)
checkError(err, "Fail to init admin user")
}
return err return err
} }
func (s usersBackend) Get(id interface{}) (*users.User, error) { func (s usersBackend) Get(i interface{}) (*users.User, error) {
userID := id.(uint) columns := []string{"id", "username", "password", "scope", "lockpassword", "viewmode", "perm", "commands", "sorting", "rules"}
columnsStr := strings.Join(columns, ",")
var conditionStr string
switch i.(type) {
case uint:
conditionStr = fmt.Sprintf("id=%v", i)
case int:
conditionStr = fmt.Sprintf("id=%v", i)
case string:
conditionStr = fmt.Sprintf("username='%v'", i)
default:
return nil, errors.ErrInvalidDataType
}
userID := uint(0)
username := "" username := ""
password := "" password := ""
scope := "" scope := ""
lockpassword := false lockpassword := false
var viewmode users.ViewMode = "list" var viewmode users.ViewMode = users.ListViewMode
perm := "" perm := ""
commands := "" commands := ""
sorting := "" sorting := ""
rules := "" rules := ""
user := users.User{} user := users.User{}
sql := "select username, password, scope, lockpassword, viewmode, perm,commands,sorting,rules from users where id=" + strconv.Itoa(int(userID)) sql := fmt.Sprintf("select %s from users where %s", columnsStr, conditionStr)
err := s.db.QueryRow(sql).Scan(&username, &password, &scope, &lockpassword, &viewmode, &perm, &commands, &sorting, &rules) err := s.db.QueryRow(sql).Scan(&userID, &username, &password, &scope, &lockpassword, &viewmode, &perm, &commands, &sorting, &rules)
if !checkError(err, "Fail to QueryRow for user") { if checkError(err, "") {
return &user, err return nil, err
} }
user.ID = userID user.ID = userID
user.Username = username user.Username = username
@ -128,10 +178,10 @@ func (s usersBackend) Get(id interface{}) (*users.User, error) {
func (s usersBackend) Gets() ([]*users.User, error) { func (s usersBackend) Gets() ([]*users.User, error) {
sql := "select id, username, password, scope, lockpassword, viewmode, perm,commands,sorting,rules from users" sql := "select id, username, password, scope, lockpassword, viewmode, perm,commands,sorting,rules from users"
rows, err := s.db.Query(sql) rows, err := s.db.Query(sql)
if !checkError(err, "Fail to Query []*users.User") { if checkError(err, "Fail to Query []*users.User") {
return nil, err return nil, err
} }
var users2 []*users.User = []*users.User{} var users2 []*users.User = make([]*users.User, 0)
for rows.Next() { for rows.Next() {
id := 0 id := 0
username := "" username := ""
@ -144,7 +194,7 @@ func (s usersBackend) Gets() ([]*users.User, error) {
sorting := "" sorting := ""
rules := "" rules := ""
err := rows.Scan(&id, &username, &password, &scope, &lockpassword, &viewmode, &perm, &commands, &sorting, &rules) err := rows.Scan(&id, &username, &password, &scope, &lockpassword, &viewmode, &perm, &commands, &sorting, &rules)
if !checkError(err, "Fail to parse record for user.User") { if checkError(err, "Fail to parse record for user.User") {
continue continue
} }
user := users.User{} user := users.User{}
@ -191,10 +241,14 @@ func (s usersBackend) updateUser(id uint, user *users.User) error {
} }
func (s usersBackend) insertUser(user *users.User) error { func (s usersBackend) insertUser(user *users.User) error {
password, err := users.HashPwd(user.Password)
if checkError(err, "Fail to hash password") {
return err
}
sql := fmt.Sprintf( sql := fmt.Sprintf(
"insert into users (username, password, scope, lockpassword, viewmode, perm, commands, sorting) values ('%s','%s','%s',%s,'%s','%s','%s','%s','%s')", "insert into users (username, password, scope, lockpassword, viewmode, perm, commands, sorting, rules) values ('%s','%s','%s',%s,'%s','%s','%s','%s','%s')",
user.Username, user.Username,
user.Password, password,
user.Scope, user.Scope,
boolToString(user.LockPassword), boolToString(user.LockPassword),
user.ViewMode, user.ViewMode,
@ -203,15 +257,14 @@ func (s usersBackend) insertUser(user *users.User) error {
SortingToString(user.Sorting), SortingToString(user.Sorting),
RulesToString(user.Rules), RulesToString(user.Rules),
) )
_, err := s.db.Exec(sql) _, err = s.db.Exec(sql)
checkError(err, "Fail to insert user")
return err return err
} }
func (s usersBackend) Save(user *users.User) error { func (s usersBackend) Save(user *users.User) error {
userOriginal, err := s.GetBy(user.ID) userOriginal, err := s.GetBy(user.Username)
if !checkError(err, "Fail to Save *users.User") { checkError(err, "")
return err
}
if userOriginal != nil { if userOriginal != nil {
return s.updateUser(user.ID, user) return s.updateUser(user.ID, user)
} }

57
storage/sql/utils.go Normal file
View File

@ -0,0 +1,57 @@
package sql
import (
"log"
"path/filepath"
"runtime"
"strings"
)
func getRuntimeFunctionName(frame uint) string {
pc := make([]uintptr, 1)
count := runtime.Callers(int(frame)+2, pc)
if count == 0 {
return ""
}
f := runtime.FuncForPC(pc[0])
return f.Name()
}
func checkError(err error, message string) bool {
if err != nil {
if len(message) > 0 {
funcname := filepath.Base(getRuntimeFunctionName(1))
log.Printf("ERROR [%s]: %s\n", funcname, err.Error())
log.Printf("ERROR [%s]: %s\n", funcname, message)
}
return true
}
return false
}
func logFunction() {
funcname := getRuntimeFunctionName(1)
log.Printf("%s is running\n", funcname)
}
func reverse(list []string) []string {
var output []string
for i := len(list) - 1; i >= 0; i-- {
output = append(output, list[i])
}
return output
}
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, " -> "))
}