feat: support mysql/postgres/sqlite3
This commit is contained in:
parent
8c8be1cdf2
commit
53265fd64b
47
cmd/utils.go
47
cmd/utils.go
@ -17,7 +17,7 @@ import (
|
||||
"github.com/filebrowser/filebrowser/v2/settings"
|
||||
"github.com/filebrowser/filebrowser/v2/storage"
|
||||
"github.com/filebrowser/filebrowser/v2/storage/bolt"
|
||||
"github.com/filebrowser/filebrowser/v2/storage/psql"
|
||||
"github.com/filebrowser/filebrowser/v2/storage/sql"
|
||||
)
|
||||
|
||||
func checkErr(err error) {
|
||||
@ -107,49 +107,22 @@ func openBoltDB(path string, cfg pythonConfig) (pythonData, Closeable) {
|
||||
return data, db
|
||||
}
|
||||
|
||||
func isPsqlDB(path string) bool {
|
||||
return strings.HasPrefix(path, "postgres:")
|
||||
}
|
||||
|
||||
func openPsqlDB(path string, cfg pythonConfig) (pythonData, Closeable) {
|
||||
data := pythonData{hadDB: true}
|
||||
db, err := psql.ConnectDB(path)
|
||||
if err != nil {
|
||||
data.store, err = psql.NewStorage(db)
|
||||
} else {
|
||||
log.Fatal("Fail to open psql database " + path)
|
||||
}
|
||||
return data, db
|
||||
}
|
||||
|
||||
func openDB(path string, cfg pythonConfig) (pythonData, Closeable) {
|
||||
if isPsqlDB(path) {
|
||||
return openPsqlDB(path, cfg)
|
||||
if sql.IsDBPath(path) {
|
||||
data := pythonData{hadDB: true}
|
||||
db, err := sql.OpenDB(path)
|
||||
if err != nil {
|
||||
data.store, err = sql.NewStorage(db)
|
||||
} else {
|
||||
log.Fatal("Fail to open database " + path)
|
||||
}
|
||||
return data, db
|
||||
}
|
||||
return openBoltDB(path, cfg)
|
||||
}
|
||||
|
||||
func python(fn pythonFunc, cfg pythonConfig) cobraFunc {
|
||||
return func(cmd *cobra.Command, args []string) {
|
||||
// data := pythonData{hadDB: true}
|
||||
|
||||
// path := getParam(cmd.Flags(), "database")
|
||||
// exists, err := dbExists(path)
|
||||
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// } else if exists && cfg.noDB {
|
||||
// log.Fatal(path + " already exists")
|
||||
// } else if !exists && !cfg.noDB && !cfg.allowNoDB {
|
||||
// log.Fatal(path + " does not exist. Please run 'filebrowser config init' first.")
|
||||
// }
|
||||
|
||||
// data.hadDB = exists
|
||||
// db, err := storm.Open(path)
|
||||
// checkErr(err)
|
||||
// defer db.Close()
|
||||
// data.store, err = bolt.NewStorage(db)
|
||||
// checkErr(err)
|
||||
data, db := openDB(getParam(cmd.Flags(), "database"), cfg)
|
||||
defer db.Close()
|
||||
fn(cmd, args, data)
|
||||
|
||||
2
go.mod
2
go.mod
@ -41,6 +41,7 @@ require (
|
||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
||||
github.com/go-errors/errors v1.1.1 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-sql-driver/mysql v1.6.0 // indirect
|
||||
github.com/golang/geo v0.0.0-20200319012246-673a6f80352d // indirect
|
||||
github.com/golang/snappy v0.0.2 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
@ -54,6 +55,7 @@ require (
|
||||
github.com/lib/pq v1.10.7 // indirect
|
||||
github.com/magiconair/properties v1.8.6 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.4 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.16 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.3 // indirect
|
||||
github.com/nwaples/rardecode v1.1.0 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.2 // indirect
|
||||
|
||||
4
go.sum
4
go.sum
@ -97,6 +97,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.1 h1:pC5DB52sCeK48Wlb9oPcdhnjkz1TKt1D/P7WKJ0kUcQ=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
|
||||
@ -210,6 +212,8 @@ github.com/marusama/semaphore/v2 v2.5.0 h1:o/1QJD9DBYOWRnDhPwDVAXQn6mQYD0gZaS1Tp
|
||||
github.com/marusama/semaphore/v2 v2.5.0/go.mod h1:z9nMiNUekt/LTpTUQdpp+4sJeYqUGpwMHfW0Z8V8fnQ=
|
||||
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
|
||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo=
|
||||
github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
|
||||
@ -1,44 +0,0 @@
|
||||
package psql
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/filebrowser/filebrowser/v2/auth"
|
||||
"github.com/filebrowser/filebrowser/v2/settings"
|
||||
"github.com/filebrowser/filebrowser/v2/share"
|
||||
"github.com/filebrowser/filebrowser/v2/storage"
|
||||
"github.com/filebrowser/filebrowser/v2/users"
|
||||
)
|
||||
|
||||
func ConnectDB(path string) (*sql.DB, error) {
|
||||
db, err := sql.Open("postgres", path)
|
||||
if err == nil {
|
||||
return db, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// NewStorage creates a storage.Storage based on Bolt DB.
|
||||
func NewStorage(db *sql.DB) (*storage.Storage, error) {
|
||||
userStore := users.NewStorage(usersBackend{db: db})
|
||||
shareStore := share.NewStorage(shareBackend{db: db})
|
||||
settingsStore := settings.NewStorage(settingsBackend{db: db})
|
||||
authStore := auth.NewStorage(authBackend{db: db}, userStore)
|
||||
|
||||
err := save(db, "version", 2) //nolint:gomnd
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &storage.Storage{
|
||||
Auth: authStore,
|
||||
Users: userStore,
|
||||
Share: shareStore,
|
||||
Settings: settingsStore,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func save(db *sql.DB, name string, from interface{}) error {
|
||||
// return db.Set("config", name, from)
|
||||
return nil
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
package psql
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
|
||||
_ "github.com/lib/pq"
|
||||
)
|
||||
|
||||
const (
|
||||
// DB_DSN is a
|
||||
DB_DSN = "postgres://postgres:12345678@127.0.0.1:5432/postgres?sslmode=disable"
|
||||
)
|
||||
|
||||
func loadUsers() {
|
||||
db, err := sql.Open("postgres", DB_DSN)
|
||||
if err != nil {
|
||||
log.Fatal("Fail to open a DB connection")
|
||||
}
|
||||
rows, err := db.Query("select id, name from users")
|
||||
if err == nil {
|
||||
log.Fatal("Fail to query db")
|
||||
}
|
||||
defer db.Close()
|
||||
for rows.Next() {
|
||||
id := ""
|
||||
name := ""
|
||||
err := rows.Scan(&id, &name)
|
||||
if err != nil {
|
||||
log.Fatal("Fail to scan db row")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func getConfig(db *sql.DB, key string, to interface{}) error {
|
||||
var value string = ""
|
||||
err := db.QueryRow("select value from config where name='" + key + "'").Scan(&value)
|
||||
if err == nil {
|
||||
return err
|
||||
}
|
||||
to = value
|
||||
return nil
|
||||
}
|
||||
|
||||
func setConfig(db *sql.DB, key string, to interface{}) error {
|
||||
var value string = to.(string)
|
||||
_, err := db.Exec("insert into config (name, value) values('" + key + "','" + value + "')")
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
@ -1,7 +1,8 @@
|
||||
package psql
|
||||
package sql
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/filebrowser/filebrowser/v2/auth"
|
||||
"github.com/filebrowser/filebrowser/v2/errors"
|
||||
@ -12,6 +13,12 @@ type authBackend struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func InitAuthTable(db *sql.DB) error {
|
||||
sql := "create table if not exists appliction(key string primary key, value string)"
|
||||
_, err := db.Exec(sql)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s authBackend) Get(t settings.AuthMethod) (auth.Auther, error) {
|
||||
var auther auth.Auther
|
||||
|
||||
@ -28,9 +35,17 @@ func (s authBackend) Get(t settings.AuthMethod) (auth.Auther, error) {
|
||||
return nil, errors.ErrInvalidAuthMethod
|
||||
}
|
||||
|
||||
return auther, getConfig(s.db, "auther", auther)
|
||||
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 {
|
||||
return setConfig(s.db, "author", a)
|
||||
val, err := json.Marshal(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return SetSetting(s.db, "auther", string(val))
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package psql
|
||||
package sql
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
@ -13,6 +13,12 @@ type settingsBackend struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func InitSettingsTable(db *sql.DB) error {
|
||||
sql := "create table if not exists settings(key string primary key, value string)"
|
||||
_, err := db.Exec(sql)
|
||||
return err
|
||||
}
|
||||
|
||||
func userDefaultsFromString(s string) settings.UserDefaults {
|
||||
if s == "" {
|
||||
return settings.UserDefaults{}
|
||||
@ -252,3 +258,39 @@ func (s settingsBackend) SaveServer(ss *settings.Server) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetSetting(db *sql.DB, key string, value string) error {
|
||||
sql := "select count(key) from settings"
|
||||
count := 0
|
||||
err := db.QueryRow(sql).Scan(&count)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if count == 0 {
|
||||
return addSetting(db, key, value)
|
||||
}
|
||||
return updateSetting(db, key, value)
|
||||
}
|
||||
|
||||
func GetSetting(db *sql.DB, key string) string {
|
||||
sql := "select value from settings where key = '" + key + "';"
|
||||
value := ""
|
||||
err := db.QueryRow(sql).Scan(&value)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: " + err.Error())
|
||||
return value
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func addSetting(db *sql.DB, key string, value string) error {
|
||||
sql := "insert into settings(key, value) values('" + key + "', '" + value + "')"
|
||||
_, err := db.Exec(sql)
|
||||
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)
|
||||
return err
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package psql
|
||||
package sql
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
@ -16,6 +16,12 @@ type linkRecord interface {
|
||||
Scan(dest ...interface{}) error
|
||||
}
|
||||
|
||||
func InitShareTable(db *sql.DB) error {
|
||||
sql := "create table if not exists share_links (path string, userid integer, expire integer, passwordhash string, token string)"
|
||||
_, err := db.Exec(sql)
|
||||
return err
|
||||
}
|
||||
|
||||
func parseLink(row linkRecord) (*share.Link, error) {
|
||||
path := ""
|
||||
hash := ""
|
||||
68
storage/sql/sql.go
Normal file
68
storage/sql/sql.go
Normal file
@ -0,0 +1,68 @@
|
||||
package sql
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/filebrowser/filebrowser/v2/auth"
|
||||
"github.com/filebrowser/filebrowser/v2/settings"
|
||||
"github.com/filebrowser/filebrowser/v2/share"
|
||||
"github.com/filebrowser/filebrowser/v2/storage"
|
||||
"github.com/filebrowser/filebrowser/v2/users"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/lib/pq"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
func IsDBPath(path string) bool {
|
||||
prefixes := []string{"sqlite3", "postgres", "mysql"}
|
||||
for _, prefix := range prefixes {
|
||||
if strings.HasPrefix(path, prefix+"://") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func OpenDB(path string) (*sql.DB, error) {
|
||||
prefixes := []string{"sqlite3", "postgres", "mysql"}
|
||||
for _, prefix := range prefixes {
|
||||
if strings.HasPrefix(path, prefix) {
|
||||
return connectDB(prefix, strings.TrimPrefix(path, prefix+"://"))
|
||||
}
|
||||
}
|
||||
return nil, errors.New("Unsupported db scheme")
|
||||
}
|
||||
|
||||
func connectDB(dbType string, path string) (*sql.DB, error) {
|
||||
db, err := sql.Open(dbType, path)
|
||||
if err == nil {
|
||||
return db, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func NewStorage(db *sql.DB) (*storage.Storage, error) {
|
||||
|
||||
InitUserTable(db)
|
||||
InitShareTable(db)
|
||||
InitSettingsTable(db)
|
||||
|
||||
userStore := users.NewStorage(usersBackend{db: db})
|
||||
shareStore := share.NewStorage(shareBackend{db: db})
|
||||
settingsStore := settings.NewStorage(settingsBackend{db: db})
|
||||
authStore := auth.NewStorage(authBackend{db: db}, userStore)
|
||||
|
||||
err := SetSetting(db, "version", "2")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &storage.Storage{
|
||||
Auth: authStore,
|
||||
Users: userStore,
|
||||
Share: shareStore,
|
||||
Settings: settingsStore,
|
||||
}, nil
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package psql
|
||||
package sql
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
@ -88,6 +88,12 @@ func RulesToString(rules []rules.Rule) string {
|
||||
return string(data)
|
||||
}
|
||||
|
||||
func InitUserTable(db *sql.DB) error {
|
||||
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)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s usersBackend) Get(id interface{}) (*users.User, error) {
|
||||
userId := id.(uint)
|
||||
username := ""
|
||||
Loading…
Reference in New Issue
Block a user