feat: psql support
This commit is contained in:
parent
02db83c72e
commit
8cd5ecd077
63
cmd/utils.go
63
cmd/utils.go
@ -17,6 +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"
|
||||
)
|
||||
|
||||
func checkErr(err error) {
|
||||
@ -82,27 +83,53 @@ func dbExists(path string) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
func openBoltDB(path string, cfg pythonConfig) pythonData {
|
||||
data := pythonData{hadDB: true}
|
||||
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)
|
||||
return data
|
||||
}
|
||||
|
||||
func isPsqlDB(path string) bool {
|
||||
return strings.HasPrefix(path, "postgres:")
|
||||
}
|
||||
|
||||
func openPsqlDB(path string, cfg pythonConfig) pythonData {
|
||||
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
|
||||
}
|
||||
|
||||
func openDB(path string, cfg pythonConfig) pythonData {
|
||||
if isPsqlDB(path) {
|
||||
return openPsqlDB(path, cfg)
|
||||
}
|
||||
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 := openDB(path, cfg)
|
||||
fn(cmd, args, data)
|
||||
}
|
||||
}
|
||||
|
||||
15632
frontend/package-lock.json
generated
15632
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
go.mod
12
go.mod
@ -32,6 +32,8 @@ require (
|
||||
|
||||
require (
|
||||
github.com/andybalholm/brotli v1.0.1 // indirect
|
||||
github.com/boltdb/bolt v1.3.1 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
|
||||
github.com/dsoprea/go-logging v0.0.0-20200517223158-a10564966e9d // indirect
|
||||
@ -42,20 +44,30 @@ require (
|
||||
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
|
||||
github.com/hasit/bolter v0.0.0-20221019173212-593eefaa56b7 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/klauspost/compress v1.11.4 // indirect
|
||||
github.com/klauspost/pgzip v1.2.5 // indirect
|
||||
github.com/kval-access-language/kval-boltdb v0.0.0-20170330045345-f3797777c95e // indirect
|
||||
github.com/kval-access-language/kval-parse v0.0.0-20170504112528-b96aa5a26330 // indirect
|
||||
github.com/kval-access-language/kval-scanner v0.0.0-20170504112421-4f097cacd289 // indirect
|
||||
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/mitchellh/mapstructure v1.4.3 // indirect
|
||||
github.com/nwaples/rardecode v1.1.0 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.2 // indirect
|
||||
github.com/pelletier/go-toml v1.9.4 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/spf13/cast v1.4.1 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/subosito/gotenv v1.2.0 // indirect
|
||||
github.com/ulikunitz/xz v0.5.9 // indirect
|
||||
github.com/urfave/cli v1.22.1 // indirect
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
golang.org/x/net v0.0.0-20220412020605-290c469a71a5 // indirect
|
||||
|
||||
26
go.sum
26
go.sum
@ -47,6 +47,8 @@ github.com/andybalholm/brotli v1.0.1 h1:KqhlKozYbRtJvsPrrEeXcO+N2l6NYT5A2QAFmSUL
|
||||
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/asdine/storm/v3 v3.2.1 h1:I5AqhkPK6nBZ/qJXySdI7ot5BlXSZ7qvDY1zAn5ZJac=
|
||||
github.com/asdine/storm/v3 v3.2.1/go.mod h1:LEpXwGt4pIqrE/XcTvCnZHT5MgZCV6Ub9q7yQzOFWr0=
|
||||
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
|
||||
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
@ -55,6 +57,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
@ -167,6 +171,8 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hasit/bolter v0.0.0-20221019173212-593eefaa56b7 h1:Plet+TSM/QDQjX84z7sD4ZiAxXO6NDQ3HF8gVZ4J7H8=
|
||||
github.com/hasit/bolter v0.0.0-20221019173212-593eefaa56b7/go.mod h1:QeiIIsu6N8sVPeSHpo1i9cID5fjR5/9nEgumickazDo=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
@ -187,6 +193,14 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kval-access-language/kval-boltdb v0.0.0-20170330045345-f3797777c95e h1:6eQQkLvMgIY9ecZKVtEsKdUeApg6qkNl8IwJp6cZBNg=
|
||||
github.com/kval-access-language/kval-boltdb v0.0.0-20170330045345-f3797777c95e/go.mod h1:CJfrSSteer+JJgIkdw/LU7Ss1CiZ6G/+oIfo4nJ1P/s=
|
||||
github.com/kval-access-language/kval-parse v0.0.0-20170504112528-b96aa5a26330 h1:u+bu63lKw/77wcyhzRB9YwipGEa4l3et/hu4xkcX2cQ=
|
||||
github.com/kval-access-language/kval-parse v0.0.0-20170504112528-b96aa5a26330/go.mod h1:sIViryZLFGwtty1cz01GVfqCzHR2j5O7ZCcuYiGJAJA=
|
||||
github.com/kval-access-language/kval-scanner v0.0.0-20170504112421-4f097cacd289 h1:xp6dE/eMUsoTqp/A4p846HSDlETgYPcW+gmtSW7G0tc=
|
||||
github.com/kval-access-language/kval-scanner v0.0.0-20170504112421-4f097cacd289/go.mod h1:YAawD4QhDnNbLB6455T6SheCYnZh90kII4jhq5HWzAQ=
|
||||
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
|
||||
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
|
||||
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
@ -194,6 +208,8 @@ github.com/maruel/natural v1.0.0 h1:C1GqgYygkdnwD1H1psoEVsPazXyUqRooEvX/XyWFFDg=
|
||||
github.com/maruel/natural v1.0.0/go.mod h1:eFVhYCcUOfZFxXoDZam8Ktya72wa79fNC3lc/leA0DQ=
|
||||
github.com/marusama/semaphore/v2 v2.5.0 h1:o/1QJD9DBYOWRnDhPwDVAXQn6mQYD0gZaS1Tpx6DJGM=
|
||||
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/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=
|
||||
@ -202,12 +218,17 @@ github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGg
|
||||
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ=
|
||||
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
||||
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/olekukonko/tablewriter v0.0.2 h1:sq53g+DWf0J6/ceFUHpQ0nAEb6WgM++fq16MZ91cS6o=
|
||||
github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ=
|
||||
github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
|
||||
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/pelletier/go-toml/v2 v2.0.0 h1:P7Bq0SaI8nsexyay5UAyDo+ICWy5MQPgEZ5+l8JQTKo=
|
||||
github.com/pelletier/go-toml/v2 v2.0.0/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
|
||||
github.com/pierrec/lz4/v4 v4.1.2 h1:qvY3YFXRQE/XB8MlLzJH7mSzBs74eA2gg52YTk6jUPM=
|
||||
github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
@ -216,9 +237,12 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/shirou/gopsutil/v3 v3.22.5 h1:atX36I/IXgFiB81687vSiBI5zrMsxcIBkP9cQMJQoJA=
|
||||
github.com/shirou/gopsutil/v3 v3.22.5/go.mod h1:so9G9VzeHt/hsd0YwqprnjHnfARAUktauykSbr+y2gA=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo=
|
||||
github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo=
|
||||
github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
|
||||
@ -247,6 +271,8 @@ github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoi
|
||||
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/ulikunitz/xz v0.5.9 h1:RsKRIA2MO8x56wkkcd3LbtcE/uMszhb6DpRf+3uwa3I=
|
||||
github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI=
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
|
||||
|
||||
36
storage/psql/auth.go
Normal file
36
storage/psql/auth.go
Normal file
@ -0,0 +1,36 @@
|
||||
package psql
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/filebrowser/filebrowser/v2/auth"
|
||||
"github.com/filebrowser/filebrowser/v2/errors"
|
||||
"github.com/filebrowser/filebrowser/v2/settings"
|
||||
)
|
||||
|
||||
type authBackend struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func (s authBackend) Get(t settings.AuthMethod) (auth.Auther, error) {
|
||||
var auther auth.Auther
|
||||
|
||||
switch t {
|
||||
case auth.MethodJSONAuth:
|
||||
auther = &auth.JSONAuth{}
|
||||
case auth.MethodProxyAuth:
|
||||
auther = &auth.ProxyAuth{}
|
||||
case auth.MethodHookAuth:
|
||||
auther = &auth.HookAuth{}
|
||||
case auth.MethodNoAuth:
|
||||
auther = &auth.NoAuth{}
|
||||
default:
|
||||
return nil, errors.ErrInvalidAuthMethod
|
||||
}
|
||||
|
||||
return auther, getConfig(s.db, "auther", auther)
|
||||
}
|
||||
|
||||
func (s authBackend) Save(a auth.Auther) error {
|
||||
return setConfig(s.db, "author", a)
|
||||
}
|
||||
44
storage/psql/psql.go
Normal file
44
storage/psql/psql.go
Normal file
@ -0,0 +1,44 @@
|
||||
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
|
||||
}
|
||||
254
storage/psql/settings.go
Normal file
254
storage/psql/settings.go
Normal file
@ -0,0 +1,254 @@
|
||||
package psql
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/filebrowser/filebrowser/v2/settings"
|
||||
)
|
||||
|
||||
type settingsBackend struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func userDefaultsFromString(s string) settings.UserDefaults {
|
||||
if s == "" {
|
||||
return settings.UserDefaults{}
|
||||
}
|
||||
userDefaults := settings.UserDefaults{}
|
||||
err := json.Unmarshal([]byte(s), &userDefaults)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: fail to parse settings.UserDefaults")
|
||||
}
|
||||
return userDefaults
|
||||
}
|
||||
|
||||
func userDefaultsToString(d settings.UserDefaults) string {
|
||||
data, err := json.Marshal(d)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(data)
|
||||
}
|
||||
|
||||
func brandingFromString(s string) settings.Branding {
|
||||
if s == "" {
|
||||
return settings.Branding{}
|
||||
}
|
||||
branding := settings.Branding{}
|
||||
err := json.Unmarshal([]byte(s), &branding)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: fail to parse settings.Branding")
|
||||
}
|
||||
return branding
|
||||
}
|
||||
|
||||
func brandingToString(s settings.Branding) string {
|
||||
data, err := json.Marshal(s)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: fail to jsonify settings.Branding")
|
||||
return ""
|
||||
}
|
||||
return string(data)
|
||||
}
|
||||
|
||||
func commandsToString(c map[string][]string) string {
|
||||
data, err := json.Marshal(c)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: fail to jsonify commands")
|
||||
return ""
|
||||
}
|
||||
return string(data)
|
||||
}
|
||||
|
||||
func commandsFromString(s string) map[string][]string {
|
||||
if s == "" {
|
||||
return map[string][]string{}
|
||||
}
|
||||
c := map[string][]string{}
|
||||
err := json.Unmarshal([]byte(s), &c)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: fail to parse commands")
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func stringsFromString(s string) []string {
|
||||
if s == "" {
|
||||
return []string{}
|
||||
}
|
||||
c := []string{}
|
||||
err := json.Unmarshal([]byte(s), &c)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: fail to parse []string")
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func stringsToString(c []string) string {
|
||||
data, err := json.Marshal(c)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: fail to jsonify strings")
|
||||
return ""
|
||||
}
|
||||
return string(data)
|
||||
}
|
||||
|
||||
func boolToInt(b bool) int {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func boolFromInt(i int) bool {
|
||||
if i == 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func boolFromString(s string) bool {
|
||||
if s == "0" || s == "" || s == "f" || s == "F" {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func boolToString(b bool) string {
|
||||
if b {
|
||||
return "1"
|
||||
}
|
||||
return "0"
|
||||
}
|
||||
|
||||
func (s settingsBackend) Get() (*settings.Settings, error) {
|
||||
sql := "select key, value from settings"
|
||||
rows, err := s.db.Query(sql)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
key := ""
|
||||
value := ""
|
||||
settings1 := settings.Settings{}
|
||||
for rows.Next() {
|
||||
err = rows.Scan(key, value)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: fail to query settings.Settings")
|
||||
}
|
||||
if key == "Key" {
|
||||
settings1.Key = []byte(value)
|
||||
} else if key == "Signup" {
|
||||
settings1.Signup = boolFromString(value)
|
||||
} else if key == "CreateUserDir" {
|
||||
settings1.CreateUserDir = boolFromString(value)
|
||||
} else if key == "Defaults" {
|
||||
settings1.Defaults = userDefaultsFromString(value)
|
||||
} else if key == "AuthMethod" {
|
||||
settings1.AuthMethod = settings.AuthMethod(value)
|
||||
} else if key == "Branding" {
|
||||
settings1.Branding = brandingFromString(value)
|
||||
} else if key == "Commands" {
|
||||
settings1.Commands = commandsFromString(value)
|
||||
} else if key == "Shell" {
|
||||
settings1.Shell = stringsFromString(value)
|
||||
} else if key == "Rules" {
|
||||
settings1.Rules = rulesFromString(value)
|
||||
} else {
|
||||
fmt.Printf("ERROR: unknown settings key " + key)
|
||||
}
|
||||
}
|
||||
return &settings1, nil
|
||||
}
|
||||
|
||||
func (s settingsBackend) Save(ss *settings.Settings) error {
|
||||
columns := []string{"Key", "Signup", "CreateUserDir", "UserHomeBasePath", "Defaults", "AuthMethod", "Branding", "Commands", "Shell", "Rules"}
|
||||
values := []string{
|
||||
"'" + string(ss.Key) + "'",
|
||||
boolToString(ss.Signup),
|
||||
boolToString(ss.CreateUserDir),
|
||||
"'" + 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 err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s settingsBackend) GetServer() (*settings.Server, error) {
|
||||
sql := "select key, value from settings"
|
||||
rows, err := s.db.Query(sql)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
key := ""
|
||||
value := ""
|
||||
server := settings.Server{}
|
||||
for rows.Next() {
|
||||
err = rows.Scan(key, value)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: fail to query settings.Settings")
|
||||
}
|
||||
if key == "Root" {
|
||||
server.Root = value
|
||||
} else if key == "BaseURL" {
|
||||
server.BaseURL = value
|
||||
} else if key == "Socket" {
|
||||
server.Socket = value
|
||||
} else if key == "TLSKey" {
|
||||
server.TLSKey = value
|
||||
} else if key == "TLSCert" {
|
||||
server.TLSCert = value
|
||||
} else if key == "Port" {
|
||||
server.Port = value
|
||||
} else if key == "Address" {
|
||||
server.Address = value
|
||||
} else if key == "Log" {
|
||||
server.Log = value
|
||||
} else if key == "EnableThumbnails" {
|
||||
server.EnableThumbnails = boolFromString(value)
|
||||
} else if key == "ResizePreview" {
|
||||
server.ResizePreview = boolFromString(value)
|
||||
} else if key == "EnableExec" {
|
||||
server.EnableExec = boolFromString(value)
|
||||
} else if key == "TypeDetectionByHeader" {
|
||||
server.TypeDetectionByHeader = boolFromString(value)
|
||||
} else if key == "AuthHook" {
|
||||
server.AuthHook = value
|
||||
}
|
||||
}
|
||||
return &server, nil
|
||||
}
|
||||
|
||||
func (s settingsBackend) SaveServer(ss *settings.Server) error {
|
||||
columns := []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 + "'",
|
||||
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 err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
96
storage/psql/share.go
Normal file
96
storage/psql/share.go
Normal file
@ -0,0 +1,96 @@
|
||||
package psql
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/filebrowser/filebrowser/v2/share"
|
||||
)
|
||||
|
||||
type shareBackend struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
type linkRecord interface {
|
||||
Scan(dest ...interface{}) error
|
||||
}
|
||||
|
||||
func parseLink(row linkRecord) (*share.Link, error) {
|
||||
path := ""
|
||||
hash := ""
|
||||
userid := uint(0)
|
||||
expire := int64(0)
|
||||
passwordhash := ""
|
||||
token := ""
|
||||
err := row.Scan(path, hash, userid, expire, passwordhash, token)
|
||||
if err != nil {
|
||||
s := "ERROR: Fail to parse record for share.Link"
|
||||
err := errors.New(s)
|
||||
fmt.Printf(s)
|
||||
return nil, err
|
||||
}
|
||||
link := share.Link{}
|
||||
link.Path = path
|
||||
link.Hash = hash
|
||||
link.UserID = userid
|
||||
link.Expire = expire
|
||||
link.PasswordHash = passwordhash
|
||||
link.Token = token
|
||||
return &link, nil
|
||||
}
|
||||
|
||||
func queryLinks(db *sql.DB, condition string) ([]*share.Link, error) {
|
||||
sql := "select hash, path, userid, expire, passwordhash, token from share_links"
|
||||
if len(condition) > 0 {
|
||||
sql = sql + " where " + condition
|
||||
}
|
||||
rows, err := db.Query(sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var links []*share.Link = []*share.Link{}
|
||||
for rows.Next() {
|
||||
link, err := parseLink(rows)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: Fail to parse record for share.Link")
|
||||
continue
|
||||
}
|
||||
links = append(links, link)
|
||||
}
|
||||
return links, nil
|
||||
}
|
||||
|
||||
func (s shareBackend) All() ([]*share.Link, error) {
|
||||
return queryLinks(s.db, "")
|
||||
}
|
||||
|
||||
func (s shareBackend) FindByUserID(id uint) ([]*share.Link, error) {
|
||||
condition := fmt.Sprintf("userid=%d", id)
|
||||
return queryLinks(s.db, condition)
|
||||
}
|
||||
|
||||
func (s shareBackend) GetByHash(hash string) (*share.Link, error) {
|
||||
sql := fmt.Sprintf("select hash, path, userid, expire, passwordhash, token from share_links where hash='%s'", hash)
|
||||
return parseLink(s.db.QueryRow(sql))
|
||||
}
|
||||
|
||||
func (s shareBackend) GetPermanent(path string, id uint) (*share.Link, error) {
|
||||
sql := fmt.Sprintf("select hash, path, userid, expire, passwordhash, token from share_links where path='%s' and userid=%d", path, id)
|
||||
return parseLink(s.db.QueryRow(sql))
|
||||
}
|
||||
|
||||
func (s shareBackend) Gets(path string, id uint) ([]*share.Link, error) {
|
||||
condition := fmt.Sprintf("userid=%d and path='%s'", id, path)
|
||||
return queryLinks(s.db, condition)
|
||||
}
|
||||
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)
|
||||
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)
|
||||
return err
|
||||
}
|
||||
242
storage/psql/users.go
Normal file
242
storage/psql/users.go
Normal file
@ -0,0 +1,242 @@
|
||||
package psql
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/filebrowser/filebrowser/v2/files"
|
||||
"github.com/filebrowser/filebrowser/v2/rules"
|
||||
"github.com/filebrowser/filebrowser/v2/users"
|
||||
)
|
||||
|
||||
type usersBackend struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func PermFromString(s string) users.Permissions {
|
||||
if s == "" {
|
||||
return users.Permissions{}
|
||||
}
|
||||
var perm users.Permissions
|
||||
json.Unmarshal([]byte(s), &perm)
|
||||
return perm
|
||||
}
|
||||
|
||||
func PermToString(perm users.Permissions) string {
|
||||
data, err := json.Marshal(perm)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(data)
|
||||
}
|
||||
|
||||
func CommandsFromString(s string) []string {
|
||||
if s == "" {
|
||||
return []string{}
|
||||
}
|
||||
var commands []string
|
||||
err := json.Unmarshal([]byte(s), &commands)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return commands
|
||||
}
|
||||
|
||||
func CommandsToString(commands []string) string {
|
||||
data, err := json.Marshal(commands)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(data)
|
||||
}
|
||||
|
||||
func SortingFromString(s string) files.Sorting {
|
||||
if s == "" {
|
||||
return files.Sorting{}
|
||||
}
|
||||
var sorting files.Sorting
|
||||
json.Unmarshal([]byte(s), &sorting)
|
||||
return sorting
|
||||
}
|
||||
|
||||
func SortingToString(sorting files.Sorting) string {
|
||||
data, err := json.Marshal(sorting)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(data)
|
||||
}
|
||||
|
||||
func rulesFromString(s string) []rules.Rule {
|
||||
if s == "" {
|
||||
return []rules.Rule{}
|
||||
}
|
||||
var rules []rules.Rule
|
||||
json.Unmarshal([]byte(s), &rules)
|
||||
return rules
|
||||
}
|
||||
|
||||
func RulesToString(rules []rules.Rule) string {
|
||||
data, err := json.Marshal(rules)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(data)
|
||||
}
|
||||
|
||||
func (s usersBackend) Get(id interface{}) (*users.User, error) {
|
||||
userId := id.(uint)
|
||||
username := ""
|
||||
password := ""
|
||||
scope := ""
|
||||
lockpassword := false
|
||||
var viewmode users.ViewMode = "list"
|
||||
perm := ""
|
||||
commands := ""
|
||||
sorting := ""
|
||||
rules := ""
|
||||
sql := "select username, password, scope, lockpassword, viewmode, perm,commands,sorting,rules from users where id=" + strconv.Itoa(int(userId))
|
||||
s.db.QueryRow(sql).Scan(username, password, scope, lockpassword, viewmode, perm, commands, sorting, rules)
|
||||
user := users.User{}
|
||||
user.ID = userId
|
||||
user.Username = username
|
||||
user.Password = password
|
||||
user.Scope = scope
|
||||
user.LockPassword = lockpassword
|
||||
user.ViewMode = viewmode
|
||||
user.Perm = PermFromString(perm)
|
||||
user.Commands = CommandsFromString(commands)
|
||||
user.Sorting = SortingFromString(sorting)
|
||||
user.Rules = rulesFromString(rules)
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
func (s usersBackend) Gets() ([]*users.User, error) {
|
||||
sql := "select id, username, password, scope, lockpassword, viewmode, perm,commands,sorting,rules from users"
|
||||
rows, err := s.db.Query(sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var users2 []*users.User = []*users.User{}
|
||||
for rows.Next() {
|
||||
id := 0
|
||||
username := ""
|
||||
password := ""
|
||||
scope := ""
|
||||
lockpassword := false
|
||||
var viewmode users.ViewMode = "list"
|
||||
perm := ""
|
||||
commands := ""
|
||||
sorting := ""
|
||||
rules := ""
|
||||
err := rows.Scan(id, username, password, scope, lockpassword, viewmode, perm, commands, sorting, rules)
|
||||
if err != nil {
|
||||
fmt.Printf("Fail to parse record for user.User")
|
||||
continue
|
||||
}
|
||||
user := users.User{}
|
||||
user.ID = uint(id)
|
||||
user.Username = username
|
||||
user.Password = password
|
||||
user.Scope = scope
|
||||
user.LockPassword = lockpassword
|
||||
user.ViewMode = viewmode
|
||||
user.Perm = PermFromString(perm)
|
||||
user.Commands = CommandsFromString(commands)
|
||||
user.Sorting = SortingFromString(sorting)
|
||||
user.Rules = rulesFromString(rules)
|
||||
|
||||
users2 = append(users2, &user)
|
||||
}
|
||||
return users2, nil
|
||||
}
|
||||
|
||||
func (s usersBackend) GetBy(id interface{}) (*users.User, error) {
|
||||
return s.Get(id)
|
||||
}
|
||||
|
||||
func (s usersBackend) updateUser(id uint, user *users.User) error {
|
||||
lockpassword := 0
|
||||
if user.LockPassword {
|
||||
lockpassword = 1
|
||||
}
|
||||
sql := fmt.Sprintf(
|
||||
"update users set username='%s',password='%s',scope='%s',lockpassword=%d,viewmode='%s',perm='%s',commands='%s',sorting='%s',rules='%s' where id=%d",
|
||||
user.Username,
|
||||
user.Password,
|
||||
user.Scope,
|
||||
lockpassword,
|
||||
user.ViewMode,
|
||||
PermToString(user.Perm),
|
||||
CommandsToString(user.Commands),
|
||||
SortingToString(user.Sorting),
|
||||
RulesToString(user.Rules),
|
||||
user.ID,
|
||||
)
|
||||
_, err := s.db.Exec(sql)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s usersBackend) insertUser(user *users.User) error {
|
||||
sql := fmt.Sprintf(
|
||||
"insert into users (username, password, scope, lockpassword, viewmode, perm, commands, sorting) values ('%s','%s','%s',%d,'%s','%s','%s','%s','%s')",
|
||||
user.Username,
|
||||
user.Password,
|
||||
user.Scope,
|
||||
user.LockPassword,
|
||||
user.ViewMode,
|
||||
PermToString(user.Perm),
|
||||
CommandsToString(user.Commands),
|
||||
SortingToString(user.Sorting),
|
||||
RulesToString(user.Rules),
|
||||
)
|
||||
_, err := s.db.Exec(sql)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s usersBackend) Save(user *users.User) error {
|
||||
userOriginal, err := s.GetBy(user.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if userOriginal != nil {
|
||||
return s.updateUser(user.ID, user)
|
||||
}
|
||||
return s.insertUser(user)
|
||||
}
|
||||
|
||||
func (s usersBackend) DeleteByID(id uint) error {
|
||||
sql := "delete from users where id=" + strconv.Itoa(int(id))
|
||||
_, err := s.db.Exec(sql)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s usersBackend) DeleteByUsername(username string) error {
|
||||
sql := "delete from users where username='" + username + "'"
|
||||
_, err := s.db.Exec(sql)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s usersBackend) Update(u *users.User, fields ...string) error {
|
||||
var setItems = []string{}
|
||||
for _, field := range fields {
|
||||
userField := reflect.ValueOf(u).Elem().FieldByName(field)
|
||||
if !userField.IsValid() {
|
||||
continue
|
||||
}
|
||||
val := userField.Interface()
|
||||
if reflect.TypeOf(val).Kind().String() == "string" {
|
||||
setItems = append(setItems, fmt.Sprintf("%s='%s'", field, val))
|
||||
} else {
|
||||
// TODO
|
||||
setItems = append(setItems, fmt.Sprintf("%s=%d", field, val))
|
||||
}
|
||||
}
|
||||
sql := fmt.Sprintf("update users set %s if id=%d", strings.Join(setItems, ","), u.ID)
|
||||
_, err := s.db.Exec(sql)
|
||||
return err
|
||||
}
|
||||
53
storage/psql/utils.go
Normal file
53
storage/psql/utils.go
Normal file
@ -0,0 +1,53 @@
|
||||
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
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user