refactor: add more go linters (#970)
This commit is contained in:
parent
54d92a2708
commit
700f32718e
|
@ -2,10 +2,10 @@ version: 2
|
||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint:
|
||||||
docker:
|
docker:
|
||||||
- image: golangci/golangci-lint:v1.16
|
- image: golangci/golangci-lint:v1.27.0
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- run: golangci-lint run -v -D errcheck
|
- run: golangci-lint run -v
|
||||||
build-node:
|
build-node:
|
||||||
docker:
|
docker:
|
||||||
- image: circleci/node
|
- image: circleci/node
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
linters-settings:
|
||||||
|
dupl:
|
||||||
|
threshold: 100
|
||||||
|
exhaustive:
|
||||||
|
default-signifies-exhaustive: false
|
||||||
|
funlen:
|
||||||
|
lines: 100
|
||||||
|
statements: 50
|
||||||
|
goconst:
|
||||||
|
min-len: 2
|
||||||
|
min-occurrences: 2
|
||||||
|
gocritic:
|
||||||
|
enabled-tags:
|
||||||
|
- diagnostic
|
||||||
|
- experimental
|
||||||
|
- opinionated
|
||||||
|
- performance
|
||||||
|
- style
|
||||||
|
disabled-checks:
|
||||||
|
- dupImport # https://github.com/go-critic/go-critic/issues/845
|
||||||
|
- ifElseChain
|
||||||
|
- octalLiteral
|
||||||
|
- whyNoLint
|
||||||
|
- wrapperFunc
|
||||||
|
gocyclo:
|
||||||
|
min-complexity: 15
|
||||||
|
goimports:
|
||||||
|
local-prefixes: github.com/filebrowser/filebrowser
|
||||||
|
golint:
|
||||||
|
min-confidence: 0
|
||||||
|
gomnd:
|
||||||
|
settings:
|
||||||
|
mnd:
|
||||||
|
# don't include the "operation" and "assign"
|
||||||
|
checks: argument,case,condition,return
|
||||||
|
govet:
|
||||||
|
check-shadowing: true
|
||||||
|
lll:
|
||||||
|
line-length: 140
|
||||||
|
maligned:
|
||||||
|
suggest-new: true
|
||||||
|
misspell:
|
||||||
|
locale: US
|
||||||
|
nolintlint:
|
||||||
|
allow-leading-space: true # don't require machine-readable nolint directives (i.e. with no leading space)
|
||||||
|
allow-unused: false # report any unused nolint directives
|
||||||
|
require-explanation: false # don't require an explanation for nolint directives
|
||||||
|
require-specific: false # don't require nolint directives to be specific about which linter is being skipped
|
||||||
|
|
||||||
|
linters:
|
||||||
|
# please, do not use `enable-all`: it's deprecated and will be removed soon.
|
||||||
|
# inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint
|
||||||
|
disable-all: true
|
||||||
|
enable:
|
||||||
|
- bodyclose
|
||||||
|
- deadcode
|
||||||
|
- depguard
|
||||||
|
- dogsled
|
||||||
|
- dupl
|
||||||
|
- errcheck
|
||||||
|
- funlen
|
||||||
|
- gochecknoinits
|
||||||
|
- goconst
|
||||||
|
- gocritic
|
||||||
|
- gocyclo
|
||||||
|
- gofmt
|
||||||
|
- goimports
|
||||||
|
- golint
|
||||||
|
- gomnd
|
||||||
|
- goprintffuncname
|
||||||
|
- gosec
|
||||||
|
- gosimple
|
||||||
|
- govet
|
||||||
|
- ineffassign
|
||||||
|
- interfacer
|
||||||
|
- lll
|
||||||
|
- misspell
|
||||||
|
- nakedret
|
||||||
|
- nolintlint
|
||||||
|
- rowserrcheck
|
||||||
|
- scopelint
|
||||||
|
- staticcheck
|
||||||
|
- structcheck
|
||||||
|
- stylecheck
|
||||||
|
- typecheck
|
||||||
|
- unconvert
|
||||||
|
- unparam
|
||||||
|
- unused
|
||||||
|
- varcheck
|
||||||
|
- whitespace
|
||||||
|
- prealloc
|
||||||
|
|
||||||
|
# don't enable:
|
||||||
|
# - asciicheck
|
||||||
|
# - exhaustive (TODO: enable after next release; current release at time of writing is v1.27)
|
||||||
|
# - gochecknoglobals
|
||||||
|
# - gocognit
|
||||||
|
# - godot
|
||||||
|
# - godox
|
||||||
|
# - goerr113
|
||||||
|
# - maligned
|
||||||
|
# - nestif
|
||||||
|
# - testpackage
|
||||||
|
# - wsl
|
||||||
|
|
||||||
|
issues:
|
||||||
|
exclude-rules:
|
||||||
|
- path: cmd/.*.go
|
||||||
|
linters:
|
||||||
|
- gochecknoinits
|
||||||
|
- path: .*_test.go
|
||||||
|
linters:
|
||||||
|
- lll
|
||||||
|
- gochecknoinits
|
||||||
|
- gocyclo
|
||||||
|
- funlen
|
||||||
|
- dupl
|
||||||
|
- scopelint
|
||||||
|
- text: "Auther"
|
||||||
|
linters:
|
||||||
|
- misspell
|
||||||
|
|
||||||
|
run:
|
||||||
|
skip-dirs:
|
||||||
|
- frontend/
|
||||||
|
skip-files:
|
||||||
|
- http/rice-box.go
|
||||||
|
|
||||||
|
# golangci.com configuration
|
||||||
|
# https://github.com/golangci/golangci/wiki/Configuration
|
||||||
|
service:
|
||||||
|
golangci-lint-version: 1.27.x # use the fixed version to not introduce new linters unexpectedly
|
|
@ -20,7 +20,7 @@ type jsonCred struct {
|
||||||
ReCaptcha string `json:"recaptcha"`
|
ReCaptcha string `json:"recaptcha"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSONAuth is a json implementaion of an Auther.
|
// JSONAuth is a json implementation of an Auther.
|
||||||
type JSONAuth struct {
|
type JSONAuth struct {
|
||||||
ReCaptcha *ReCaptcha `json:"recaptcha" yaml:"recaptcha"`
|
ReCaptcha *ReCaptcha `json:"recaptcha" yaml:"recaptcha"`
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ func (a JSONAuth) Auth(r *http.Request, sto *users.Storage, root string) (*users
|
||||||
|
|
||||||
// If ReCaptcha is enabled, check the code.
|
// If ReCaptcha is enabled, check the code.
|
||||||
if a.ReCaptcha != nil && len(a.ReCaptcha.Secret) > 0 {
|
if a.ReCaptcha != nil && len(a.ReCaptcha.Secret) > 0 {
|
||||||
ok, err := a.ReCaptcha.Ok(cred.ReCaptcha)
|
ok, err := a.ReCaptcha.Ok(cred.ReCaptcha) //nolint:shadow
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -66,7 +66,7 @@ func (a JSONAuth) LoginPage() bool {
|
||||||
|
|
||||||
const reCaptchaAPI = "/recaptcha/api/siteverify"
|
const reCaptchaAPI = "/recaptcha/api/siteverify"
|
||||||
|
|
||||||
// ReCaptcha identifies a recaptcha conenction.
|
// ReCaptcha identifies a recaptcha connection.
|
||||||
type ReCaptcha struct {
|
type ReCaptcha struct {
|
||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
|
@ -89,6 +89,7 @@ func (r *ReCaptcha) Ok(response string) (bool, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
return false, nil
|
return false, nil
|
||||||
|
|
|
@ -18,8 +18,8 @@ type Storage struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStorage creates a auth storage from a backend.
|
// NewStorage creates a auth storage from a backend.
|
||||||
func NewStorage(back StorageBackend, users *users.Storage) *Storage {
|
func NewStorage(back StorageBackend, userStore *users.Storage) *Storage {
|
||||||
return &Storage{back: back, users: users}
|
return &Storage{back: back, users: userStore}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get wraps a StorageBackend.Get.
|
// Get wraps a StorageBackend.Get.
|
||||||
|
|
|
@ -14,7 +14,7 @@ var cmdsAddCmd = &cobra.Command{
|
||||||
Use: "add <event> <command>",
|
Use: "add <event> <command>",
|
||||||
Short: "Add a command to run on a specific event",
|
Short: "Add a command to run on a specific event",
|
||||||
Long: `Add a command to run on a specific event.`,
|
Long: `Add a command to run on a specific event.`,
|
||||||
Args: cobra.MinimumNArgs(2),
|
Args: cobra.MinimumNArgs(2), //nolint:mnd
|
||||||
Run: python(func(cmd *cobra.Command, args []string, d pythonData) {
|
Run: python(func(cmd *cobra.Command, args []string, d pythonData) {
|
||||||
s, err := d.store.Settings.Get()
|
s, err := d.store.Settings.Get()
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
|
@ -23,7 +23,7 @@ You can also specify an optional parameter (index_end) so
|
||||||
you can remove all commands from 'index' to 'index_end',
|
you can remove all commands from 'index' to 'index_end',
|
||||||
including 'index_end'.`,
|
including 'index_end'.`,
|
||||||
Args: func(cmd *cobra.Command, args []string) error {
|
Args: func(cmd *cobra.Command, args []string) error {
|
||||||
if err := cobra.RangeArgs(2, 3)(cmd, args); err != nil {
|
if err := cobra.RangeArgs(2, 3)(cmd, args); err != nil { //nolint:mnd
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ including 'index_end'.`,
|
||||||
i, err := strconv.Atoi(args[1])
|
i, err := strconv.Atoi(args[1])
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
f := i
|
f := i
|
||||||
if len(args) == 3 {
|
if len(args) == 3 { //nolint:mnd
|
||||||
f, err = strconv.Atoi(args[2])
|
f, err = strconv.Atoi(args[2])
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,12 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/auth"
|
"github.com/filebrowser/filebrowser/v2/auth"
|
||||||
"github.com/filebrowser/filebrowser/v2/errors"
|
"github.com/filebrowser/filebrowser/v2/errors"
|
||||||
"github.com/filebrowser/filebrowser/v2/settings"
|
"github.com/filebrowser/filebrowser/v2/settings"
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/spf13/pflag"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -44,6 +45,7 @@ func addConfigFlags(flags *pflag.FlagSet) {
|
||||||
flags.Bool("branding.disableExternal", false, "disable external links such as GitHub links")
|
flags.Bool("branding.disableExternal", false, "disable external links such as GitHub links")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint:gocyclo
|
||||||
func getAuthentication(flags *pflag.FlagSet, defaults ...interface{}) (settings.AuthMethod, auth.Auther) {
|
func getAuthentication(flags *pflag.FlagSet, defaults ...interface{}) (settings.AuthMethod, auth.Auther) {
|
||||||
method := settings.AuthMethod(mustGetString(flags, "auth.method"))
|
method := settings.AuthMethod(mustGetString(flags, "auth.method"))
|
||||||
|
|
||||||
|
@ -53,11 +55,12 @@ func getAuthentication(flags *pflag.FlagSet, defaults ...interface{}) (settings.
|
||||||
for _, arg := range defaults {
|
for _, arg := range defaults {
|
||||||
switch def := arg.(type) {
|
switch def := arg.(type) {
|
||||||
case *settings.Settings:
|
case *settings.Settings:
|
||||||
method = settings.AuthMethod(def.AuthMethod)
|
method = def.AuthMethod
|
||||||
case auth.Auther:
|
case auth.Auther:
|
||||||
ms, err := json.Marshal(def)
|
ms, err := json.Marshal(def)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
json.Unmarshal(ms, &defaultAuther)
|
err = json.Unmarshal(ms, &defaultAuther)
|
||||||
|
checkErr(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,10 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/auth"
|
"github.com/filebrowser/filebrowser/v2/auth"
|
||||||
"github.com/filebrowser/filebrowser/v2/settings"
|
"github.com/filebrowser/filebrowser/v2/settings"
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -55,7 +56,7 @@ The path must be for a json or yaml file.`,
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
var rawAuther interface{}
|
var rawAuther interface{}
|
||||||
if filepath.Ext(args[0]) != ".json" {
|
if filepath.Ext(args[0]) != ".json" { //nolint:goconst
|
||||||
rawAuther = cleanUpInterfaceMap(file.Auther.(map[interface{}]interface{}))
|
rawAuther = cleanUpInterfaceMap(file.Auther.(map[interface{}]interface{}))
|
||||||
} else {
|
} else {
|
||||||
rawAuther = file.Auther
|
rawAuther = file.Auther
|
||||||
|
|
|
@ -4,8 +4,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/settings"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/filebrowser/filebrowser/v2/settings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
12
cmd/docs.go
12
cmd/docs.go
|
@ -88,7 +88,7 @@ func generateMarkdown(cmd *cobra.Command, w io.Writer) {
|
||||||
|
|
||||||
short := cmd.Short
|
short := cmd.Short
|
||||||
long := cmd.Long
|
long := cmd.Long
|
||||||
if len(long) == 0 {
|
if long == "" {
|
||||||
long = short
|
long = short
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,21 +106,21 @@ func generateMarkdown(cmd *cobra.Command, w io.Writer) {
|
||||||
buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.Example))
|
buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.Example))
|
||||||
}
|
}
|
||||||
|
|
||||||
printOptions(buf, cmd, name)
|
printOptions(buf, cmd)
|
||||||
_, err := buf.WriteTo(w)
|
_, err := buf.WriteTo(w)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateFlagsTable(fs *pflag.FlagSet, buf io.StringWriter) {
|
func generateFlagsTable(fs *pflag.FlagSet, buf io.StringWriter) {
|
||||||
buf.WriteString("| Name | Shorthand | Usage |\n")
|
_, _ = buf.WriteString("| Name | Shorthand | Usage |\n")
|
||||||
buf.WriteString("|------|-----------|-------|\n")
|
_, _ = buf.WriteString("|------|-----------|-------|\n")
|
||||||
|
|
||||||
fs.VisitAll(func(f *pflag.Flag) {
|
fs.VisitAll(func(f *pflag.Flag) {
|
||||||
buf.WriteString("|" + f.Name + "|" + f.Shorthand + "|" + f.Usage + "|\n")
|
_, _ = buf.WriteString("|" + f.Name + "|" + f.Shorthand + "|" + f.Usage + "|\n")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func printOptions(buf *bytes.Buffer, cmd *cobra.Command, name string) {
|
func printOptions(buf *bytes.Buffer, cmd *cobra.Command) {
|
||||||
flags := cmd.NonInheritedFlags()
|
flags := cmd.NonInheritedFlags()
|
||||||
flags.SetOutput(buf)
|
flags.SetOutput(buf)
|
||||||
if flags.HasAvailableFlags() {
|
if flags.HasAvailableFlags() {
|
||||||
|
|
|
@ -3,8 +3,9 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/users"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/filebrowser/filebrowser/v2/users"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
28
cmd/root.go
28
cmd/root.go
|
@ -13,16 +13,17 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/auth"
|
|
||||||
fbhttp "github.com/filebrowser/filebrowser/v2/http"
|
|
||||||
"github.com/filebrowser/filebrowser/v2/settings"
|
|
||||||
"github.com/filebrowser/filebrowser/v2/storage"
|
|
||||||
"github.com/filebrowser/filebrowser/v2/users"
|
|
||||||
homedir "github.com/mitchellh/go-homedir"
|
homedir "github.com/mitchellh/go-homedir"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
v "github.com/spf13/viper"
|
v "github.com/spf13/viper"
|
||||||
lumberjack "gopkg.in/natefinch/lumberjack.v2"
|
lumberjack "gopkg.in/natefinch/lumberjack.v2"
|
||||||
|
|
||||||
|
"github.com/filebrowser/filebrowser/v2/auth"
|
||||||
|
fbhttp "github.com/filebrowser/filebrowser/v2/http"
|
||||||
|
"github.com/filebrowser/filebrowser/v2/settings"
|
||||||
|
"github.com/filebrowser/filebrowser/v2/storage"
|
||||||
|
"github.com/filebrowser/filebrowser/v2/users"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -113,16 +114,17 @@ user created with the credentials from options "username" and "password".`,
|
||||||
|
|
||||||
var listener net.Listener
|
var listener net.Listener
|
||||||
|
|
||||||
if server.Socket != "" {
|
switch {
|
||||||
|
case server.Socket != "":
|
||||||
listener, err = net.Listen("unix", server.Socket)
|
listener, err = net.Listen("unix", server.Socket)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
} else if server.TLSKey != "" && server.TLSCert != "" {
|
case server.TLSKey != "" && server.TLSCert != "":
|
||||||
cer, err := tls.LoadX509KeyPair(server.TLSCert, server.TLSKey)
|
cer, err := tls.LoadX509KeyPair(server.TLSCert, server.TLSKey) //nolint:shadow
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
listener, err = tls.Listen("tcp", adr, &tls.Config{Certificates: []tls.Certificate{cer}})
|
listener, err = tls.Listen("tcp", adr, &tls.Config{Certificates: []tls.Certificate{cer}}) //nolint:shadow
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
} else {
|
default:
|
||||||
listener, err = net.Listen("tcp", adr)
|
listener, err = net.Listen("tcp", adr) //nolint:shadow
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,13 +144,14 @@ user created with the credentials from options "username" and "password".`,
|
||||||
}, pythonConfig{allowNoDB: true}),
|
}, pythonConfig{allowNoDB: true}),
|
||||||
}
|
}
|
||||||
|
|
||||||
func cleanupHandler(listener net.Listener, c chan os.Signal) {
|
func cleanupHandler(listener net.Listener, c chan os.Signal) { //nolint:interfacer
|
||||||
sig := <-c
|
sig := <-c
|
||||||
log.Printf("Caught signal %s: shutting down.", sig)
|
log.Printf("Caught signal %s: shutting down.", sig)
|
||||||
listener.Close()
|
listener.Close()
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint:gocyclo
|
||||||
func getRunParams(flags *pflag.FlagSet, st *storage.Storage) *settings.Server {
|
func getRunParams(flags *pflag.FlagSet, st *storage.Storage) *settings.Server {
|
||||||
server, err := st.Settings.GetServer()
|
server, err := st.Settings.GetServer()
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
@ -348,5 +351,4 @@ func initConfig() {
|
||||||
} else {
|
} else {
|
||||||
cfgFile = "Using config file: " + v.ConfigFileUsed()
|
cfgFile = "Using config file: " + v.ConfigFileUsed()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,15 +3,16 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/settings"
|
"github.com/filebrowser/filebrowser/v2/settings"
|
||||||
"github.com/filebrowser/filebrowser/v2/users"
|
"github.com/filebrowser/filebrowser/v2/users"
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rulesCmd.AddCommand(rulesRmCommand)
|
rulesCmd.AddCommand(rulesRmCommand)
|
||||||
rulesRmCommand.Flags().Uint("index", 0, "index of rule to remove")
|
rulesRmCommand.Flags().Uint("index", 0, "index of rule to remove")
|
||||||
rulesRmCommand.MarkFlagRequired("index")
|
_ = rulesRmCommand.MarkFlagRequired("index")
|
||||||
}
|
}
|
||||||
|
|
||||||
var rulesRmCommand = &cobra.Command{
|
var rulesRmCommand = &cobra.Command{
|
||||||
|
@ -43,7 +44,7 @@ including 'index_end'.`,
|
||||||
i, err := strconv.Atoi(args[0])
|
i, err := strconv.Atoi(args[0])
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
f := i
|
f := i
|
||||||
if len(args) == 2 {
|
if len(args) == 2 { //nolint:mnd
|
||||||
f, err = strconv.Atoi(args[1])
|
f, err = strconv.Atoi(args[1])
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
}
|
}
|
||||||
|
|
19
cmd/rules.go
19
cmd/rules.go
|
@ -3,12 +3,13 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
"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/storage"
|
"github.com/filebrowser/filebrowser/v2/storage"
|
||||||
"github.com/filebrowser/filebrowser/v2/users"
|
"github.com/filebrowser/filebrowser/v2/users"
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/spf13/pflag"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -28,14 +29,14 @@ rules.`,
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
}
|
}
|
||||||
|
|
||||||
func runRules(st *storage.Storage, cmd *cobra.Command, users func(*users.User), global func(*settings.Settings)) {
|
func runRules(st *storage.Storage, cmd *cobra.Command, usersFn func(*users.User), globalFn func(*settings.Settings)) {
|
||||||
id := getUserIdentifier(cmd.Flags())
|
id := getUserIdentifier(cmd.Flags())
|
||||||
if id != nil {
|
if id != nil {
|
||||||
user, err := st.Users.Get("", id)
|
user, err := st.Users.Get("", id)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
if users != nil {
|
if usersFn != nil {
|
||||||
users(user)
|
usersFn(user)
|
||||||
}
|
}
|
||||||
|
|
||||||
printRules(user.Rules, id)
|
printRules(user.Rules, id)
|
||||||
|
@ -45,8 +46,8 @@ func runRules(st *storage.Storage, cmd *cobra.Command, users func(*users.User),
|
||||||
s, err := st.Settings.Get()
|
s, err := st.Settings.Get()
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
if global != nil {
|
if globalFn != nil {
|
||||||
global(s)
|
globalFn(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
printRules(s.Rules, id)
|
printRules(s.Rules, id)
|
||||||
|
@ -65,14 +66,14 @@ func getUserIdentifier(flags *pflag.FlagSet) interface{} {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func printRules(rules []rules.Rule, id interface{}) {
|
func printRules(rulez []rules.Rule, id interface{}) {
|
||||||
if id == nil {
|
if id == nil {
|
||||||
fmt.Printf("Global Rules:\n\n")
|
fmt.Printf("Global Rules:\n\n")
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("Rules for user %v:\n\n", id)
|
fmt.Printf("Rules for user %v:\n\n", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
for id, rule := range rules {
|
for id, rule := range rulez {
|
||||||
fmt.Printf("(%d) ", id)
|
fmt.Printf("(%d) ", id)
|
||||||
if rule.Regex {
|
if rule.Regex {
|
||||||
if rule.Allow {
|
if rule.Allow {
|
||||||
|
|
|
@ -3,10 +3,11 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"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"
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/filebrowser/filebrowser/v2/storage/bolt/importer"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/filebrowser/filebrowser/v2/storage/bolt/importer"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -10,7 +11,7 @@ func init() {
|
||||||
|
|
||||||
upgradeCmd.Flags().String("old.database", "", "")
|
upgradeCmd.Flags().String("old.database", "", "")
|
||||||
upgradeCmd.Flags().String("old.config", "", "")
|
upgradeCmd.Flags().String("old.config", "", "")
|
||||||
upgradeCmd.MarkFlagRequired("old.database")
|
_ = upgradeCmd.MarkFlagRequired("old.database")
|
||||||
}
|
}
|
||||||
|
|
||||||
var upgradeCmd = &cobra.Command{
|
var upgradeCmd = &cobra.Command{
|
||||||
|
|
44
cmd/users.go
44
cmd/users.go
|
@ -7,10 +7,11 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/settings"
|
|
||||||
"github.com/filebrowser/filebrowser/v2/users"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
|
"github.com/filebrowser/filebrowser/v2/settings"
|
||||||
|
"github.com/filebrowser/filebrowser/v2/users"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -24,38 +25,38 @@ var usersCmd = &cobra.Command{
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
}
|
}
|
||||||
|
|
||||||
func printUsers(users []*users.User) {
|
func printUsers(usrs []*users.User) {
|
||||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
||||||
fmt.Fprintln(w, "ID\tUsername\tScope\tLocale\tV. Mode\tAdmin\tExecute\tCreate\tRename\tModify\tDelete\tShare\tDownload\tPwd Lock")
|
fmt.Fprintln(w, "ID\tUsername\tScope\tLocale\tV. Mode\tAdmin\tExecute\tCreate\tRename\tModify\tDelete\tShare\tDownload\tPwd Lock")
|
||||||
|
|
||||||
for _, user := range users {
|
for _, u := range usrs {
|
||||||
fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%s\t%t\t%t\t%t\t%t\t%t\t%t\t%t\t%t\t%t\t\n",
|
fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%s\t%t\t%t\t%t\t%t\t%t\t%t\t%t\t%t\t%t\t\n",
|
||||||
user.ID,
|
u.ID,
|
||||||
user.Username,
|
u.Username,
|
||||||
user.Scope,
|
u.Scope,
|
||||||
user.Locale,
|
u.Locale,
|
||||||
user.ViewMode,
|
u.ViewMode,
|
||||||
user.Perm.Admin,
|
u.Perm.Admin,
|
||||||
user.Perm.Execute,
|
u.Perm.Execute,
|
||||||
user.Perm.Create,
|
u.Perm.Create,
|
||||||
user.Perm.Rename,
|
u.Perm.Rename,
|
||||||
user.Perm.Modify,
|
u.Perm.Modify,
|
||||||
user.Perm.Delete,
|
u.Perm.Delete,
|
||||||
user.Perm.Share,
|
u.Perm.Share,
|
||||||
user.Perm.Download,
|
u.Perm.Download,
|
||||||
user.LockPassword,
|
u.LockPassword,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Flush()
|
w.Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseUsernameOrID(arg string) (string, uint) {
|
func parseUsernameOrID(arg string) (username string, id uint) {
|
||||||
id, err := strconv.ParseUint(arg, 10, 0)
|
id64, err := strconv.ParseUint(arg, 10, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return arg, 0
|
return arg, 0
|
||||||
}
|
}
|
||||||
return "", uint(id)
|
return "", uint(id64)
|
||||||
}
|
}
|
||||||
|
|
||||||
func addUserFlags(flags *pflag.FlagSet) {
|
func addUserFlags(flags *pflag.FlagSet) {
|
||||||
|
@ -84,6 +85,7 @@ func getViewMode(flags *pflag.FlagSet) users.ViewMode {
|
||||||
return viewMode
|
return viewMode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint:gocyclo
|
||||||
func getUserDefaults(flags *pflag.FlagSet, defaults *settings.UserDefaults, all bool) {
|
func getUserDefaults(flags *pflag.FlagSet, defaults *settings.UserDefaults, all bool) {
|
||||||
visit := func(flag *pflag.Flag) {
|
visit := func(flag *pflag.Flag) {
|
||||||
switch flag.Name {
|
switch flag.Name {
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/filebrowser/filebrowser/v2/users"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/filebrowser/filebrowser/v2/users"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -14,7 +15,7 @@ var usersAddCmd = &cobra.Command{
|
||||||
Use: "add <username> <password>",
|
Use: "add <username> <password>",
|
||||||
Short: "Create a new user",
|
Short: "Create a new user",
|
||||||
Long: `Create a new user and add it to the database.`,
|
Long: `Create a new user and add it to the database.`,
|
||||||
Args: cobra.ExactArgs(2),
|
Args: cobra.ExactArgs(2), //nolint:mnd
|
||||||
Run: python(func(cmd *cobra.Command, args []string, d pythonData) {
|
Run: python(func(cmd *cobra.Command, args []string, d pythonData) {
|
||||||
s, err := d.store.Settings.Get()
|
s, err := d.store.Settings.Get()
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
@ -33,9 +34,9 @@ var usersAddCmd = &cobra.Command{
|
||||||
|
|
||||||
servSettings, err := d.store.Settings.GetServer()
|
servSettings, err := d.store.Settings.GetServer()
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
//since getUserDefaults() polluted s.Defaults.Scope
|
// since getUserDefaults() polluted s.Defaults.Scope
|
||||||
//which makes the Scope not the one saved in the db
|
// which makes the Scope not the one saved in the db
|
||||||
//we need the right s.Defaults.Scope here
|
// we need the right s.Defaults.Scope here
|
||||||
s2, err := d.store.Settings.Get()
|
s2, err := d.store.Settings.Get()
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/filebrowser/filebrowser/v2/users"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/filebrowser/filebrowser/v2/users"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -2,11 +2,13 @@ package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/users"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/filebrowser/filebrowser/v2/users"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -65,8 +67,7 @@ list or set it to 0.`,
|
||||||
// with the new username. If there is, print an error and cancel the
|
// with the new username. If there is, print an error and cancel the
|
||||||
// operation
|
// operation
|
||||||
if user.Username != onDB.Username {
|
if user.Username != onDB.Username {
|
||||||
conflictuous, err := d.store.Users.Get("", user.Username)
|
if conflictuous, err := d.store.Users.Get("", user.Username); err == nil { //nolint:shadow
|
||||||
if err == nil {
|
|
||||||
checkErr(usernameConflictError(user.Username, conflictuous.ID, user.ID))
|
checkErr(usernameConflictError(user.Username, conflictuous.ID, user.ID))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,6 +83,7 @@ list or set it to 0.`,
|
||||||
}, pythonConfig{}),
|
}, pythonConfig{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
func usernameConflictError(username string, original, new uint) error {
|
func usernameConflictError(username string, originalID, newID uint) error {
|
||||||
return errors.New("can't import user with ID " + strconv.Itoa(int(new)) + " and username \"" + username + "\" because the username is already registred with the user " + strconv.Itoa(int(original)))
|
return fmt.Errorf(`can't import user with ID %d and username "%s" because the username is already registred with the user %d`,
|
||||||
|
newID, username, originalID)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/settings"
|
"github.com/filebrowser/filebrowser/v2/settings"
|
||||||
"github.com/filebrowser/filebrowser/v2/users"
|
"github.com/filebrowser/filebrowser/v2/users"
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
13
cmd/utils.go
13
cmd/utils.go
|
@ -9,12 +9,13 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/asdine/storm"
|
"github.com/asdine/storm"
|
||||||
"github.com/filebrowser/filebrowser/v2/settings"
|
|
||||||
"github.com/filebrowser/filebrowser/v2/storage"
|
|
||||||
"github.com/filebrowser/filebrowser/v2/storage/bolt"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
yaml "gopkg.in/yaml.v2"
|
yaml "gopkg.in/yaml.v2"
|
||||||
|
|
||||||
|
"github.com/filebrowser/filebrowser/v2/settings"
|
||||||
|
"github.com/filebrowser/filebrowser/v2/storage"
|
||||||
|
"github.com/filebrowser/filebrowser/v2/storage/bolt"
|
||||||
)
|
)
|
||||||
|
|
||||||
func checkErr(err error) {
|
func checkErr(err error) {
|
||||||
|
@ -70,7 +71,9 @@ func dbExists(path string) (bool, error) {
|
||||||
d := filepath.Dir(path)
|
d := filepath.Dir(path)
|
||||||
_, err = os.Stat(d)
|
_, err = os.Stat(d)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
os.MkdirAll(d, 0700)
|
if err := os.MkdirAll(d, 0700); err != nil { //nolint:shadow
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,7 +116,7 @@ func marshal(filename string, data interface{}) error {
|
||||||
encoder := json.NewEncoder(fd)
|
encoder := json.NewEncoder(fd)
|
||||||
encoder.SetIndent("", " ")
|
encoder.SetIndent("", " ")
|
||||||
return encoder.Encode(data)
|
return encoder.Encode(data)
|
||||||
case ".yml", ".yaml":
|
case ".yml", ".yaml": //nolint:goconst
|
||||||
encoder := yaml.NewEncoder(fd)
|
encoder := yaml.NewEncoder(fd)
|
||||||
return encoder.Encode(data)
|
return encoder.Encode(data)
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -3,8 +3,9 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/version"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/filebrowser/filebrowser/v2/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package files
|
package files
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/md5"
|
"crypto/md5" //nolint:gosec
|
||||||
"crypto/sha1"
|
"crypto/sha1" //nolint:gosec
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"crypto/sha512"
|
"crypto/sha512"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
@ -17,9 +17,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/spf13/afero"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/errors"
|
"github.com/filebrowser/filebrowser/v2/errors"
|
||||||
"github.com/filebrowser/filebrowser/v2/rules"
|
"github.com/filebrowser/filebrowser/v2/rules"
|
||||||
"github.com/spf13/afero"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// FileInfo describes a file.
|
// FileInfo describes a file.
|
||||||
|
@ -74,7 +75,10 @@ func NewFileInfo(opts FileOptions) (*FileInfo, error) {
|
||||||
|
|
||||||
if opts.Expand {
|
if opts.Expand {
|
||||||
if file.IsDir {
|
if file.IsDir {
|
||||||
return file, file.readListing(opts.Checker)
|
if err := file.readListing(opts.Checker); err != nil { //nolint:shadow
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return file, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
err = file.detectType(opts.Modify, true)
|
err = file.detectType(opts.Modify, true)
|
||||||
|
@ -105,6 +109,7 @@ func (i *FileInfo) Checksum(algo string) error {
|
||||||
|
|
||||||
var h hash.Hash
|
var h hash.Hash
|
||||||
|
|
||||||
|
//nolint:gosec
|
||||||
switch algo {
|
switch algo {
|
||||||
case "md5":
|
case "md5":
|
||||||
h = md5.New()
|
h = md5.New()
|
||||||
|
@ -127,6 +132,8 @@ func (i *FileInfo) Checksum(algo string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint:goconst
|
||||||
|
//TODO: use constants
|
||||||
func (i *FileInfo) detectType(modify, saveContent bool) error {
|
func (i *FileInfo) detectType(modify, saveContent bool) error {
|
||||||
// failing to detect the type should not return error.
|
// failing to detect the type should not return error.
|
||||||
// imagine the situation where a file in a dir with thousands
|
// imagine the situation where a file in a dir with thousands
|
||||||
|
@ -198,9 +205,9 @@ func (i *FileInfo) detectSubtitles() {
|
||||||
|
|
||||||
// TODO: detect multiple languages. Base.Lang.vtt
|
// TODO: detect multiple languages. Base.Lang.vtt
|
||||||
|
|
||||||
path := strings.TrimSuffix(i.Path, ext) + ".vtt"
|
fPath := strings.TrimSuffix(i.Path, ext) + ".vtt"
|
||||||
if _, err := i.Fs.Stat(path); err == nil {
|
if _, err := i.Fs.Stat(fPath); err == nil {
|
||||||
i.Subtitles = append(i.Subtitles, path)
|
i.Subtitles = append(i.Subtitles, fPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,16 +226,16 @@ func (i *FileInfo) readListing(checker rules.Checker) error {
|
||||||
|
|
||||||
for _, f := range dir {
|
for _, f := range dir {
|
||||||
name := f.Name()
|
name := f.Name()
|
||||||
path := path.Join(i.Path, name)
|
fPath := path.Join(i.Path, name)
|
||||||
|
|
||||||
if !checker.Check(path) {
|
if !checker.Check(fPath) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(f.Mode().String(), "L") {
|
if strings.HasPrefix(f.Mode().String(), "L") {
|
||||||
// It's a symbolic link. We try to follow it. If it doesn't work,
|
// It's a symbolic link. We try to follow it. If it doesn't work,
|
||||||
// we stay with the link information instead if the target's.
|
// we stay with the link information instead if the target's.
|
||||||
info, err := i.Fs.Stat(path)
|
info, err := i.Fs.Stat(fPath)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
f = info
|
f = info
|
||||||
}
|
}
|
||||||
|
@ -242,7 +249,7 @@ func (i *FileInfo) readListing(checker rules.Checker) error {
|
||||||
Mode: f.Mode(),
|
Mode: f.Mode(),
|
||||||
IsDir: f.IsDir(),
|
IsDir: f.IsDir(),
|
||||||
Extension: filepath.Ext(name),
|
Extension: filepath.Ext(name),
|
||||||
Path: path,
|
Path: fPath,
|
||||||
}
|
}
|
||||||
|
|
||||||
if file.IsDir {
|
if file.IsDir {
|
||||||
|
|
|
@ -16,8 +16,10 @@ type Listing struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ApplySort applies the sort order using .Order and .Sort
|
// ApplySort applies the sort order using .Order and .Sort
|
||||||
|
//nolint:goconst
|
||||||
func (l Listing) ApplySort() {
|
func (l Listing) ApplySort() {
|
||||||
// Check '.Order' to know how to sort
|
// Check '.Order' to know how to sort
|
||||||
|
// TODO: use enum
|
||||||
if !l.Sorting.Asc {
|
if !l.Sorting.Asc {
|
||||||
switch l.Sorting.By {
|
switch l.Sorting.By {
|
||||||
case "name":
|
case "name":
|
||||||
|
|
|
@ -4,41 +4,45 @@ import (
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
func isBinary(content []byte, n int) bool {
|
func isBinary(content []byte, _ int) bool {
|
||||||
maybeStr := string(content)
|
maybeStr := string(content)
|
||||||
runeCnt := utf8.RuneCount(content)
|
runeCnt := utf8.RuneCount(content)
|
||||||
runeIndex := 0
|
runeIndex := 0
|
||||||
gotRuneErrCnt := 0
|
gotRuneErrCnt := 0
|
||||||
firstRuneErrIndex := -1
|
firstRuneErrIndex := -1
|
||||||
|
|
||||||
for _, b := range maybeStr {
|
const (
|
||||||
// 8 and below are control chars (e.g. backspace, null, eof, etc)
|
// 8 and below are control chars (e.g. backspace, null, eof, etc)
|
||||||
if b <= 8 {
|
maxControlCharsCode = 8
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 0xFFFD(65533) is the "error" Rune or "Unicode replacement character"
|
// 0xFFFD(65533) is the "error" Rune or "Unicode replacement character"
|
||||||
// see https://golang.org/pkg/unicode/utf8/#pkg-constants
|
// see https://golang.org/pkg/unicode/utf8/#pkg-constants
|
||||||
if b == 0xFFFD {
|
unicodeReplacementChar = 0xFFFD
|
||||||
//if it is not the last (utf8.UTFMax - x) rune
|
)
|
||||||
|
|
||||||
|
for _, b := range maybeStr {
|
||||||
|
if b <= maxControlCharsCode {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if b == unicodeReplacementChar {
|
||||||
|
// if it is not the last (utf8.UTFMax - x) rune
|
||||||
if runeCnt > utf8.UTFMax && runeIndex < runeCnt-utf8.UTFMax {
|
if runeCnt > utf8.UTFMax && runeIndex < runeCnt-utf8.UTFMax {
|
||||||
return true
|
return true
|
||||||
} else {
|
}
|
||||||
//else it is the last (utf8.UTFMax - x) rune
|
// else it is the last (utf8.UTFMax - x) rune
|
||||||
//there maybe Vxxx, VVxx, VVVx, thus, we may got max 3 0xFFFD rune (asume V is the byte we got)
|
// there maybe Vxxx, VVxx, VVVx, thus, we may got max 3 0xFFFD rune (assume V is the byte we got)
|
||||||
//for Chinese, it can only be Vxx, VVx, we may got max 2 0xFFFD rune
|
// for Chinese, it can only be Vxx, VVx, we may got max 2 0xFFFD rune
|
||||||
gotRuneErrCnt++
|
gotRuneErrCnt++
|
||||||
|
|
||||||
//mark the first time
|
// mark the first time
|
||||||
if firstRuneErrIndex == -1 {
|
if firstRuneErrIndex == -1 {
|
||||||
firstRuneErrIndex = runeIndex
|
firstRuneErrIndex = runeIndex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
runeIndex++
|
runeIndex++
|
||||||
}
|
}
|
||||||
|
|
||||||
//if last (utf8.UTFMax - x ) rune has the "error" Rune, but not all
|
// if last (utf8.UTFMax - x ) rune has the "error" Rune, but not all
|
||||||
if firstRuneErrIndex != -1 && gotRuneErrCnt != runeCnt-firstRuneErrIndex {
|
if firstRuneErrIndex != -1 && gotRuneErrCnt != runeCnt-firstRuneErrIndex {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
// CopyDir copies a directory from source to dest and all
|
// CopyDir copies a directory from source to dest and all
|
||||||
// of its sub-directories. It doesn't stop if it finds an error
|
// of its sub-directories. It doesn't stop if it finds an error
|
||||||
// during the copy. Returns an error if any.
|
// during the copy. Returns an error if any.
|
||||||
func CopyDir(fs afero.Fs, source string, dest string) error {
|
func CopyDir(fs afero.Fs, source, dest string) error {
|
||||||
// Get properties of source.
|
// Get properties of source.
|
||||||
srcinfo, err := fs.Stat(source)
|
srcinfo, err := fs.Stat(source)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
|
|
||||||
// CopyFile copies a file from source to dest and returns
|
// CopyFile copies a file from source to dest and returns
|
||||||
// an error if any.
|
// an error if any.
|
||||||
func CopyFile(fs afero.Fs, source string, dest string) error {
|
func CopyFile(fs afero.Fs, source, dest string) error {
|
||||||
// Open the source file.
|
// Open the source file.
|
||||||
src, err := fs.Open(source)
|
src, err := fs.Open(source)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
13
http/auth.go
13
http/auth.go
|
@ -10,10 +10,15 @@ import (
|
||||||
|
|
||||||
jwt "github.com/dgrijalva/jwt-go"
|
jwt "github.com/dgrijalva/jwt-go"
|
||||||
"github.com/dgrijalva/jwt-go/request"
|
"github.com/dgrijalva/jwt-go/request"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/errors"
|
"github.com/filebrowser/filebrowser/v2/errors"
|
||||||
"github.com/filebrowser/filebrowser/v2/users"
|
"github.com/filebrowser/filebrowser/v2/users"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
TokenExpirationTime = time.Hour * 2
|
||||||
|
)
|
||||||
|
|
||||||
type userInfo struct {
|
type userInfo struct {
|
||||||
ID uint `json:"id"`
|
ID uint `json:"id"`
|
||||||
Locale string `json:"locale"`
|
Locale string `json:"locale"`
|
||||||
|
@ -161,7 +166,7 @@ var renewHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data
|
||||||
return printToken(w, r, d, d.user)
|
return printToken(w, r, d, d.user)
|
||||||
})
|
})
|
||||||
|
|
||||||
func printToken(w http.ResponseWriter, r *http.Request, d *data, user *users.User) (int, error) {
|
func printToken(w http.ResponseWriter, _ *http.Request, d *data, user *users.User) (int, error) {
|
||||||
claims := &authToken{
|
claims := &authToken{
|
||||||
User: userInfo{
|
User: userInfo{
|
||||||
ID: user.ID,
|
ID: user.ID,
|
||||||
|
@ -173,7 +178,7 @@ func printToken(w http.ResponseWriter, r *http.Request, d *data, user *users.Use
|
||||||
},
|
},
|
||||||
StandardClaims: jwt.StandardClaims{
|
StandardClaims: jwt.StandardClaims{
|
||||||
IssuedAt: time.Now().Unix(),
|
IssuedAt: time.Now().Unix(),
|
||||||
ExpiresAt: time.Now().Add(time.Hour * 2).Unix(),
|
ExpiresAt: time.Now().Add(TokenExpirationTime).Unix(),
|
||||||
Issuer: "File Browser",
|
Issuer: "File Browser",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -185,6 +190,8 @@ func printToken(w http.ResponseWriter, r *http.Request, d *data, user *users.Use
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "cty")
|
w.Header().Set("Content-Type", "cty")
|
||||||
w.Write([]byte(signed))
|
if _, err := w.Write([]byte(signed)); err != nil {
|
||||||
|
return http.StatusInternalServerError, err
|
||||||
|
}
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,13 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/runner"
|
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
|
|
||||||
|
"github.com/filebrowser/filebrowser/v2/runner"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
WSWriteDeadline = 10 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
var upgrader = websocket.Upgrader{
|
var upgrader = websocket.Upgrader{
|
||||||
|
@ -22,12 +27,14 @@ var (
|
||||||
cmdNotAllowed = []byte("Command not allowed.")
|
cmdNotAllowed = []byte("Command not allowed.")
|
||||||
)
|
)
|
||||||
|
|
||||||
func wsErr(ws *websocket.Conn, r *http.Request, status int, err error) {
|
func wsErr(ws *websocket.Conn, r *http.Request, status int, err error) { //nolint:unparam
|
||||||
txt := http.StatusText(status)
|
txt := http.StatusText(status)
|
||||||
if err != nil || status >= 400 {
|
if err != nil || status >= 400 {
|
||||||
log.Printf("%s: %v %s %v", r.URL.Path, status, r.RemoteAddr, err)
|
log.Printf("%s: %v %s %v", r.URL.Path, status, r.RemoteAddr, err)
|
||||||
}
|
}
|
||||||
ws.WriteControl(websocket.CloseInternalServerErr, []byte(txt), time.Now().Add(10*time.Second))
|
if err := ws.WriteControl(websocket.CloseInternalServerErr, []byte(txt), time.Now().Add(WSWriteDeadline)); err != nil { //nolint:shadow
|
||||||
|
log.Print(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var commandsHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
var commandsHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
||||||
|
@ -40,7 +47,7 @@ var commandsHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *d
|
||||||
var raw string
|
var raw string
|
||||||
|
|
||||||
for {
|
for {
|
||||||
_, msg, err := conn.ReadMessage()
|
_, msg, err := conn.ReadMessage() //nolint:shadow
|
||||||
if err != nil {
|
if err != nil {
|
||||||
wsErr(conn, r, http.StatusInternalServerError, err)
|
wsErr(conn, r, http.StatusInternalServerError, err)
|
||||||
return 0, nil
|
return 0, nil
|
||||||
|
@ -53,8 +60,7 @@ var commandsHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *d
|
||||||
}
|
}
|
||||||
|
|
||||||
if !d.user.CanExecute(strings.Split(raw, " ")[0]) {
|
if !d.user.CanExecute(strings.Split(raw, " ")[0]) {
|
||||||
err := conn.WriteMessage(websocket.TextMessage, cmdNotAllowed)
|
if err := conn.WriteMessage(websocket.TextMessage, cmdNotAllowed); err != nil { //nolint:shadow
|
||||||
if err != nil {
|
|
||||||
wsErr(conn, r, http.StatusInternalServerError, err)
|
wsErr(conn, r, http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,15 +69,13 @@ var commandsHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *d
|
||||||
|
|
||||||
command, err := runner.ParseCommand(d.settings, raw)
|
command, err := runner.ParseCommand(d.settings, raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := conn.WriteMessage(websocket.TextMessage, []byte(err.Error()))
|
if err := conn.WriteMessage(websocket.TextMessage, []byte(err.Error())); err != nil { //nolint:shadow
|
||||||
if err != nil {
|
|
||||||
wsErr(conn, r, http.StatusInternalServerError, err)
|
wsErr(conn, r, http.StatusInternalServerError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.Command(command[0], command[1:]...)
|
cmd := exec.Command(command[0], command[1:]...) //nolint:gosec
|
||||||
cmd.Dir = d.user.FullPath(r.URL.Path)
|
cmd.Dir = d.user.FullPath(r.URL.Path)
|
||||||
|
|
||||||
stdout, err := cmd.StdoutPipe()
|
stdout, err := cmd.StdoutPipe()
|
||||||
|
@ -93,7 +97,9 @@ var commandsHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *d
|
||||||
|
|
||||||
s := bufio.NewScanner(io.MultiReader(stdout, stderr))
|
s := bufio.NewScanner(io.MultiReader(stdout, stderr))
|
||||||
for s.Scan() {
|
for s.Scan() {
|
||||||
conn.WriteMessage(websocket.TextMessage, s.Bytes())
|
if err := conn.WriteMessage(websocket.TextMessage, s.Bytes()); err != nil {
|
||||||
|
log.Print(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cmd.Wait(); err != nil {
|
if err := cmd.Wait(); err != nil {
|
||||||
|
|
|
@ -41,9 +41,9 @@ func (d *data) Check(path string) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func handle(fn handleFunc, prefix string, storage *storage.Storage, server *settings.Server) http.Handler {
|
func handle(fn handleFunc, prefix string, store *storage.Storage, server *settings.Server) http.Handler {
|
||||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
settings, err := storage.Settings.Get()
|
settings, err := store.Settings.Get()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("ERROR: couldn't get settings")
|
log.Fatalln("ERROR: couldn't get settings")
|
||||||
return
|
return
|
||||||
|
@ -51,7 +51,7 @@ func handle(fn handleFunc, prefix string, storage *storage.Storage, server *sett
|
||||||
|
|
||||||
status, err := fn(w, r, &data{
|
status, err := fn(w, r, &data{
|
||||||
Runner: &runner.Runner{Settings: settings},
|
Runner: &runner.Runner{Settings: settings},
|
||||||
store: storage,
|
store: store,
|
||||||
settings: settings,
|
settings: settings,
|
||||||
server: server,
|
server: server,
|
||||||
})
|
})
|
||||||
|
|
|
@ -3,9 +3,10 @@ package http
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/settings"
|
"github.com/filebrowser/filebrowser/v2/settings"
|
||||||
"github.com/filebrowser/filebrowser/v2/storage"
|
"github.com/filebrowser/filebrowser/v2/storage"
|
||||||
"github.com/gorilla/mux"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type modifyRequest struct {
|
type modifyRequest struct {
|
||||||
|
@ -13,11 +14,11 @@ type modifyRequest struct {
|
||||||
Which []string `json:"which"` // Answer to: which fields?
|
Which []string `json:"which"` // Answer to: which fields?
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHandler(storage *storage.Storage, server *settings.Server) (http.Handler, error) {
|
func NewHandler(store *storage.Storage, server *settings.Server) (http.Handler, error) {
|
||||||
server.Clean()
|
server.Clean()
|
||||||
|
|
||||||
r := mux.NewRouter()
|
r := mux.NewRouter()
|
||||||
index, static := getStaticHandlers(storage, server)
|
index, static := getStaticHandlers(store, server)
|
||||||
|
|
||||||
// NOTE: This fixes the issue where it would redirect if people did not put a
|
// NOTE: This fixes the issue where it would redirect if people did not put a
|
||||||
// trailing slash in the end. I hate this decision since this allows some awful
|
// trailing slash in the end. I hate this decision since this allows some awful
|
||||||
|
@ -25,7 +26,7 @@ func NewHandler(storage *storage.Storage, server *settings.Server) (http.Handler
|
||||||
r = r.SkipClean(true)
|
r = r.SkipClean(true)
|
||||||
|
|
||||||
monkey := func(fn handleFunc, prefix string) http.Handler {
|
monkey := func(fn handleFunc, prefix string) http.Handler {
|
||||||
return handle(fn, prefix, storage, server)
|
return handle(fn, prefix, store, server)
|
||||||
}
|
}
|
||||||
|
|
||||||
r.PathPrefix("/static").Handler(static)
|
r.PathPrefix("/static").Handler(static)
|
||||||
|
|
|
@ -46,7 +46,7 @@ func ifPathWithName(r *http.Request) string {
|
||||||
pathElements := strings.Split(r.URL.Path, "/")
|
pathElements := strings.Split(r.URL.Path, "/")
|
||||||
// prevent maliciously constructed parameters like `/api/public/dl/XZzCDnK2_not_exists_hash_name`
|
// prevent maliciously constructed parameters like `/api/public/dl/XZzCDnK2_not_exists_hash_name`
|
||||||
// len(pathElements) will be 1, and golang will panic `runtime error: index out of range`
|
// len(pathElements) will be 1, and golang will panic `runtime error: index out of range`
|
||||||
if len(pathElements) < 2 {
|
if len(pathElements) < 2 { //nolint: mnd
|
||||||
return r.URL.Path
|
return r.URL.Path
|
||||||
}
|
}
|
||||||
id := pathElements[len(pathElements)-2]
|
id := pathElements[len(pathElements)-2]
|
||||||
|
|
19
http/raw.go
19
http/raw.go
|
@ -7,34 +7,37 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/files"
|
|
||||||
"github.com/filebrowser/filebrowser/v2/users"
|
|
||||||
"github.com/hacdias/fileutils"
|
"github.com/hacdias/fileutils"
|
||||||
"github.com/mholt/archiver"
|
"github.com/mholt/archiver"
|
||||||
|
|
||||||
|
"github.com/filebrowser/filebrowser/v2/files"
|
||||||
|
"github.com/filebrowser/filebrowser/v2/users"
|
||||||
)
|
)
|
||||||
|
|
||||||
func parseQueryFiles(r *http.Request, f *files.FileInfo, u *users.User) ([]string, error) {
|
func parseQueryFiles(r *http.Request, f *files.FileInfo, _ *users.User) ([]string, error) {
|
||||||
files := []string{}
|
var fileSlice []string
|
||||||
names := strings.Split(r.URL.Query().Get("files"), ",")
|
names := strings.Split(r.URL.Query().Get("files"), ",")
|
||||||
|
|
||||||
if len(names) == 0 {
|
if len(names) == 0 {
|
||||||
files = append(files, f.Path)
|
fileSlice = append(fileSlice, f.Path)
|
||||||
} else {
|
} else {
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
name, err := url.QueryUnescape(strings.Replace(name, "+", "%2B", -1))
|
name, err := url.QueryUnescape(strings.Replace(name, "+", "%2B", -1)) //nolint:shadow
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
name = fileutils.SlashClean(name)
|
name = fileutils.SlashClean(name)
|
||||||
files = append(files, filepath.Join(f.Path, name))
|
fileSlice = append(fileSlice, filepath.Join(f.Path, name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return files, nil
|
return fileSlice, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint: goconst
|
||||||
func parseQueryAlgorithm(r *http.Request) (string, archiver.Writer, error) {
|
func parseQueryAlgorithm(r *http.Request) (string, archiver.Writer, error) {
|
||||||
|
// TODO: use enum
|
||||||
switch r.URL.Query().Get("algo") {
|
switch r.URL.Query().Get("algo") {
|
||||||
case "zip", "true", "":
|
case "zip", "true", "":
|
||||||
return ".zip", archiver.NewZip(), nil
|
return ".zip", archiver.NewZip(), nil
|
||||||
|
|
|
@ -74,7 +74,7 @@ var resourcePostPutHandler = withUser(func(w http.ResponseWriter, r *http.Reques
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
io.Copy(ioutil.Discard, r.Body)
|
_, _ = io.Copy(ioutil.Discard, r.Body)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// For directories, only allow POST for creation.
|
// For directories, only allow POST for creation.
|
||||||
|
@ -119,6 +119,7 @@ var resourcePostPutHandler = withUser(func(w http.ResponseWriter, r *http.Reques
|
||||||
return errToStatus(err), err
|
return errToStatus(err), err
|
||||||
})
|
})
|
||||||
|
|
||||||
|
//nolint: goconst
|
||||||
var resourcePatchHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
var resourcePatchHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
||||||
src := r.URL.Path
|
src := r.URL.Path
|
||||||
dst := r.URL.Query().Get("destination")
|
dst := r.URL.Query().Get("destination")
|
||||||
|
@ -134,6 +135,7 @@ var resourcePatchHandler = withUser(func(w http.ResponseWriter, r *http.Request,
|
||||||
}
|
}
|
||||||
|
|
||||||
switch action {
|
switch action {
|
||||||
|
// TODO: use enum
|
||||||
case "copy":
|
case "copy":
|
||||||
if !d.user.Perm.Create {
|
if !d.user.Perm.Create {
|
||||||
return http.StatusForbidden, nil
|
return http.StatusForbidden, nil
|
||||||
|
|
|
@ -57,7 +57,9 @@ var sharePostHandler = withPermShare(func(w http.ResponseWriter, r *http.Request
|
||||||
var err error
|
var err error
|
||||||
s, err = d.store.Share.GetPermanent(r.URL.Path, d.user.ID)
|
s, err = d.store.Share.GetPermanent(r.URL.Path, d.user.ID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
w.Write([]byte(path.Join(d.server.BaseURL, "/share/", s.Hash)))
|
if _, err := w.Write([]byte(path.Join(d.server.BaseURL, "/share/", s.Hash))); err != nil {
|
||||||
|
return http.StatusInternalServerError, err
|
||||||
|
}
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,14 @@ import (
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
rice "github.com/GeertJohan/go.rice"
|
rice "github.com/GeertJohan/go.rice"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/auth"
|
"github.com/filebrowser/filebrowser/v2/auth"
|
||||||
"github.com/filebrowser/filebrowser/v2/settings"
|
"github.com/filebrowser/filebrowser/v2/settings"
|
||||||
"github.com/filebrowser/filebrowser/v2/storage"
|
"github.com/filebrowser/filebrowser/v2/storage"
|
||||||
"github.com/filebrowser/filebrowser/v2/version"
|
"github.com/filebrowser/filebrowser/v2/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
func handleWithStaticData(w http.ResponseWriter, r *http.Request, d *data, box *rice.Box, file, contentType string) (int, error) {
|
func handleWithStaticData(w http.ResponseWriter, _ *http.Request, d *data, box *rice.Box, file, contentType string) (int, error) {
|
||||||
w.Header().Set("Content-Type", contentType)
|
w.Header().Set("Content-Type", contentType)
|
||||||
|
|
||||||
auther, err := d.store.Auth.Get(d.settings.AuthMethod)
|
auther, err := d.store.Auth.Get(d.settings.AuthMethod)
|
||||||
|
@ -41,8 +42,8 @@ func handleWithStaticData(w http.ResponseWriter, r *http.Request, d *data, box *
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.settings.Branding.Files != "" {
|
if d.settings.Branding.Files != "" {
|
||||||
path := filepath.Join(d.settings.Branding.Files, "custom.css")
|
fPath := filepath.Join(d.settings.Branding.Files, "custom.css")
|
||||||
_, err := os.Stat(path)
|
_, err := os.Stat(fPath) //nolint:shadow
|
||||||
|
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
log.Printf("couldn't load custom styles: %v", err)
|
log.Printf("couldn't load custom styles: %v", err)
|
||||||
|
@ -54,7 +55,7 @@ func handleWithStaticData(w http.ResponseWriter, r *http.Request, d *data, box *
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.settings.AuthMethod == auth.MethodJSONAuth {
|
if d.settings.AuthMethod == auth.MethodJSONAuth {
|
||||||
raw, err := d.store.Auth.Get(d.settings.AuthMethod)
|
raw, err := d.store.Auth.Get(d.settings.AuthMethod) //nolint:shadow
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return http.StatusInternalServerError, err
|
return http.StatusInternalServerError, err
|
||||||
}
|
}
|
||||||
|
@ -84,29 +85,29 @@ func handleWithStaticData(w http.ResponseWriter, r *http.Request, d *data, box *
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getStaticHandlers(storage *storage.Storage, server *settings.Server) (http.Handler, http.Handler) {
|
func getStaticHandlers(store *storage.Storage, server *settings.Server) (index, static http.Handler) {
|
||||||
box := rice.MustFindBox("../frontend/dist")
|
box := rice.MustFindBox("../frontend/dist")
|
||||||
handler := http.FileServer(box.HTTPBox())
|
handler := http.FileServer(box.HTTPBox())
|
||||||
|
|
||||||
index := handle(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
index = handle(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
||||||
if r.Method != http.MethodGet {
|
if r.Method != http.MethodGet {
|
||||||
return http.StatusNotFound, nil
|
return http.StatusNotFound, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("x-xss-protection", "1; mode=block")
|
w.Header().Set("x-xss-protection", "1; mode=block")
|
||||||
return handleWithStaticData(w, r, d, box, "index.html", "text/html; charset=utf-8")
|
return handleWithStaticData(w, r, d, box, "index.html", "text/html; charset=utf-8")
|
||||||
}, "", storage, server)
|
}, "", store, server)
|
||||||
|
|
||||||
static := handle(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
static = handle(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
||||||
if r.Method != http.MethodGet {
|
if r.Method != http.MethodGet {
|
||||||
return http.StatusNotFound, nil
|
return http.StatusNotFound, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.settings.Branding.Files != "" {
|
if d.settings.Branding.Files != "" {
|
||||||
if strings.HasPrefix(r.URL.Path, "img/") {
|
if strings.HasPrefix(r.URL.Path, "img/") {
|
||||||
path := filepath.Join(d.settings.Branding.Files, r.URL.Path)
|
fPath := filepath.Join(d.settings.Branding.Files, r.URL.Path)
|
||||||
if _, err := os.Stat(path); err == nil {
|
if _, err := os.Stat(fPath); err == nil {
|
||||||
http.ServeFile(w, r, path)
|
http.ServeFile(w, r, fPath)
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
} else if r.URL.Path == "custom.css" && d.settings.Branding.Files != "" {
|
} else if r.URL.Path == "custom.css" && d.settings.Branding.Files != "" {
|
||||||
|
@ -121,7 +122,7 @@ func getStaticHandlers(storage *storage.Storage, server *settings.Server) (http.
|
||||||
}
|
}
|
||||||
|
|
||||||
return handleWithStaticData(w, r, d, box, r.URL.Path, "application/javascript; charset=utf-8")
|
return handleWithStaticData(w, r, d, box, r.URL.Path, "application/javascript; charset=utf-8")
|
||||||
}, "/static/", storage, server)
|
}, "/static/", store, server)
|
||||||
|
|
||||||
return index, static
|
return index, static
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,10 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/errors"
|
"github.com/filebrowser/filebrowser/v2/errors"
|
||||||
"github.com/filebrowser/filebrowser/v2/users"
|
"github.com/filebrowser/filebrowser/v2/users"
|
||||||
"github.com/gorilla/mux"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type modifyUserRequest struct {
|
type modifyUserRequest struct {
|
||||||
|
@ -27,7 +28,7 @@ func getUserID(r *http.Request) (uint, error) {
|
||||||
return uint(i), err
|
return uint(i), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func getUser(w http.ResponseWriter, r *http.Request) (*modifyUserRequest, error) {
|
func getUser(_ http.ResponseWriter, r *http.Request) (*modifyUserRequest, error) {
|
||||||
if r.Body == nil {
|
if r.Body == nil {
|
||||||
return nil, errors.ErrEmptyRequest
|
return nil, errors.ErrEmptyRequest
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"github.com/filebrowser/filebrowser/v2/errors"
|
"github.com/filebrowser/filebrowser/v2/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func renderJSON(w http.ResponseWriter, r *http.Request, data interface{}) (int, error) {
|
func renderJSON(w http.ResponseWriter, _ *http.Request, data interface{}) (int, error) {
|
||||||
marsh, err := json.Marshal(data)
|
marsh, err := json.Marshal(data)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -3,15 +3,16 @@ package runner
|
||||||
import (
|
import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/settings"
|
|
||||||
"github.com/caddyserver/caddy"
|
"github.com/caddyserver/caddy"
|
||||||
|
|
||||||
|
"github.com/filebrowser/filebrowser/v2/settings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParseCommand parses the command taking in account if the current
|
// ParseCommand parses the command taking in account if the current
|
||||||
// instance uses a shell to run the commands or just calls the binary
|
// instance uses a shell to run the commands or just calls the binary
|
||||||
// directyly.
|
// directyly.
|
||||||
func ParseCommand(s *settings.Settings, raw string) ([]string, error) {
|
func ParseCommand(s *settings.Settings, raw string) ([]string, error) {
|
||||||
command := []string{}
|
var command []string
|
||||||
|
|
||||||
if len(s.Shell) == 0 {
|
if len(s.Shell) == 0 {
|
||||||
cmd, args, err := caddy.SplitCommandAndArgs(raw)
|
cmd, args, err := caddy.SplitCommandAndArgs(raw)
|
||||||
|
@ -27,7 +28,7 @@ func ParseCommand(s *settings.Settings, raw string) ([]string, error) {
|
||||||
command = append(command, cmd)
|
command = append(command, cmd)
|
||||||
command = append(command, args...)
|
command = append(command, args...)
|
||||||
} else {
|
} else {
|
||||||
command = append(s.Shell, raw)
|
command = append(s.Shell, raw) //nolint:gocritic
|
||||||
}
|
}
|
||||||
|
|
||||||
return command, nil
|
return command, nil
|
||||||
|
|
|
@ -60,9 +60,9 @@ func (r *Runner) exec(raw, evt, path, dst string, user *users.User) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.Command(command[0], command[1:]...)
|
cmd := exec.Command(command[0], command[1:]...) //nolint:gosec
|
||||||
cmd.Env = append(os.Environ(), fmt.Sprintf("FILE=%s", path))
|
cmd.Env = append(os.Environ(), fmt.Sprintf("FILE=%s", path))
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("SCOPE=%s", user.Scope))
|
cmd.Env = append(cmd.Env, fmt.Sprintf("SCOPE=%s", user.Scope)) //nolint:gocritic
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("TRIGGER=%s", evt))
|
cmd.Env = append(cmd.Env, fmt.Sprintf("TRIGGER=%s", evt))
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("USERNAME=%s", user.Username))
|
cmd.Env = append(cmd.Env, fmt.Sprintf("USERNAME=%s", user.Username))
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("DESTINATION=%s", dst))
|
cmd.Env = append(cmd.Env, fmt.Sprintf("DESTINATION=%s", dst))
|
||||||
|
|
|
@ -4,8 +4,9 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/rules"
|
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
|
|
||||||
|
"github.com/filebrowser/filebrowser/v2/rules"
|
||||||
)
|
)
|
||||||
|
|
||||||
type searchOptions struct {
|
type searchOptions struct {
|
||||||
|
|
|
@ -17,21 +17,21 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// MakeUserDir makes the user directory according to settings.
|
// MakeUserDir makes the user directory according to settings.
|
||||||
func (settings *Settings) MakeUserDir(username, userScope, serverRoot string) (string, error) {
|
func (s *Settings) MakeUserDir(username, userScope, serverRoot string) (string, error) {
|
||||||
var err error
|
var err error
|
||||||
userScope = strings.TrimSpace(userScope)
|
userScope = strings.TrimSpace(userScope)
|
||||||
if userScope == "" || userScope == "./" {
|
if userScope == "" || userScope == "./" {
|
||||||
userScope = "."
|
userScope = "."
|
||||||
}
|
}
|
||||||
|
|
||||||
if !settings.CreateUserDir {
|
if !s.CreateUserDir {
|
||||||
return userScope, nil
|
return userScope, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
fs := afero.NewBasePathFs(afero.NewOsFs(), serverRoot)
|
fs := afero.NewBasePathFs(afero.NewOsFs(), serverRoot)
|
||||||
|
|
||||||
// Use the default auto create logic only if specific scope is not the default scope
|
// Use the default auto create logic only if specific scope is not the default scope
|
||||||
if userScope != settings.Defaults.Scope {
|
if userScope != s.Defaults.Scope {
|
||||||
// Try create the dir, for example: settings.Defaults.Scope == "." and userScope == "./foo"
|
// Try create the dir, for example: settings.Defaults.Scope == "." and userScope == "./foo"
|
||||||
if userScope != "." {
|
if userScope != "." {
|
||||||
err = fs.MkdirAll(userScope, os.ModePerm)
|
err = fs.MkdirAll(userScope, os.ModePerm)
|
||||||
|
@ -50,7 +50,7 @@ func (settings *Settings) MakeUserDir(username, userScope, serverRoot string) (s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create default user dir
|
// Create default user dir
|
||||||
userHomeBase := settings.Defaults.Scope + string(os.PathSeparator) + "users"
|
userHomeBase := s.Defaults.Scope + string(os.PathSeparator) + "users"
|
||||||
userHome := userHomeBase + string(os.PathSeparator) + username
|
userHome := userHomeBase + string(os.PathSeparator) + username
|
||||||
err = fs.MkdirAll(userHome, os.ModePerm)
|
err = fs.MkdirAll(userHome, os.ModePerm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -33,7 +33,9 @@ func (s *Storage) GetByHash(hash string) (*Link, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if link.Expire != 0 && link.Expire <= time.Now().Unix() {
|
if link.Expire != 0 && link.Expire <= time.Now().Unix() {
|
||||||
s.Delete(link.Hash)
|
if err := s.Delete(link.Hash); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return nil, errors.ErrNotExist
|
return nil, errors.ErrNotExist
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +57,9 @@ func (s *Storage) Gets(path string, id uint) ([]*Link, error) {
|
||||||
|
|
||||||
for i, link := range links {
|
for i, link := range links {
|
||||||
if link.Expire != 0 && link.Expire <= time.Now().Unix() {
|
if link.Expire != 0 && link.Expire <= time.Now().Unix() {
|
||||||
s.Delete(link.Hash)
|
if err := s.Delete(link.Hash); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
links = append(links[:i], links[i+1:]...)
|
links = append(links[:i], links[i+1:]...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package bolt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/asdine/storm"
|
"github.com/asdine/storm"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/auth"
|
"github.com/filebrowser/filebrowser/v2/auth"
|
||||||
"github.com/filebrowser/filebrowser/v2/errors"
|
"github.com/filebrowser/filebrowser/v2/errors"
|
||||||
"github.com/filebrowser/filebrowser/v2/settings"
|
"github.com/filebrowser/filebrowser/v2/settings"
|
||||||
|
|
|
@ -2,6 +2,7 @@ package bolt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/asdine/storm"
|
"github.com/asdine/storm"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/auth"
|
"github.com/filebrowser/filebrowser/v2/auth"
|
||||||
"github.com/filebrowser/filebrowser/v2/settings"
|
"github.com/filebrowser/filebrowser/v2/settings"
|
||||||
"github.com/filebrowser/filebrowser/v2/share"
|
"github.com/filebrowser/filebrowser/v2/share"
|
||||||
|
@ -11,10 +12,10 @@ import (
|
||||||
|
|
||||||
// NewStorage creates a storage.Storage based on Bolt DB.
|
// NewStorage creates a storage.Storage based on Bolt DB.
|
||||||
func NewStorage(db *storm.DB) (*storage.Storage, error) {
|
func NewStorage(db *storm.DB) (*storage.Storage, error) {
|
||||||
users := users.NewStorage(usersBackend{db: db})
|
userStore := users.NewStorage(usersBackend{db: db})
|
||||||
share := share.NewStorage(shareBackend{db: db})
|
shareStore := share.NewStorage(shareBackend{db: db})
|
||||||
settings := settings.NewStorage(settingsBackend{db: db})
|
settingsStore := settings.NewStorage(settingsBackend{db: db})
|
||||||
auth := auth.NewStorage(authBackend{db: db}, users)
|
authStore := auth.NewStorage(authBackend{db: db}, userStore)
|
||||||
|
|
||||||
err := save(db, "version", 2)
|
err := save(db, "version", 2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -22,9 +23,9 @@ func NewStorage(db *storm.DB) (*storage.Storage, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return &storage.Storage{
|
return &storage.Storage{
|
||||||
Auth: auth,
|
Auth: authStore,
|
||||||
Users: users,
|
Users: userStore,
|
||||||
Share: share,
|
Share: shareStore,
|
||||||
Settings: settings,
|
Settings: settingsStore,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package bolt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/asdine/storm"
|
"github.com/asdine/storm"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/settings"
|
"github.com/filebrowser/filebrowser/v2/settings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -10,12 +11,12 @@ type settingsBackend struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s settingsBackend) Get() (*settings.Settings, error) {
|
func (s settingsBackend) Get() (*settings.Settings, error) {
|
||||||
settings := &settings.Settings{}
|
set := &settings.Settings{}
|
||||||
return settings, get(s.db, "settings", settings)
|
return set, get(s.db, "settings", set)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s settingsBackend) Save(settings *settings.Settings) error {
|
func (s settingsBackend) Save(set *settings.Settings) error {
|
||||||
return save(s.db, "settings", settings)
|
return save(s.db, "settings", set)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s settingsBackend) GetServer() (*settings.Server, error) {
|
func (s settingsBackend) GetServer() (*settings.Server, error) {
|
||||||
|
|
|
@ -7,14 +7,14 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/auth"
|
|
||||||
"github.com/filebrowser/filebrowser/v2/users"
|
|
||||||
|
|
||||||
"github.com/asdine/storm"
|
"github.com/asdine/storm"
|
||||||
"github.com/filebrowser/filebrowser/v2/settings"
|
|
||||||
"github.com/filebrowser/filebrowser/v2/storage"
|
|
||||||
toml "github.com/pelletier/go-toml"
|
toml "github.com/pelletier/go-toml"
|
||||||
yaml "gopkg.in/yaml.v2"
|
yaml "gopkg.in/yaml.v2"
|
||||||
|
|
||||||
|
"github.com/filebrowser/filebrowser/v2/auth"
|
||||||
|
"github.com/filebrowser/filebrowser/v2/settings"
|
||||||
|
"github.com/filebrowser/filebrowser/v2/storage"
|
||||||
|
"github.com/filebrowser/filebrowser/v2/users"
|
||||||
)
|
)
|
||||||
|
|
||||||
type oldDefs struct {
|
type oldDefs struct {
|
||||||
|
|
|
@ -2,34 +2,35 @@ package importer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/asdine/storm"
|
"github.com/asdine/storm"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/storage/bolt"
|
"github.com/filebrowser/filebrowser/v2/storage/bolt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Import imports an old configuration to a newer database.
|
// Import imports an old configuration to a newer database.
|
||||||
func Import(oldDB, oldConf, newDB string) error {
|
func Import(oldDBPath, oldConf, newDBPath string) error {
|
||||||
old, err := storm.Open(oldDB)
|
oldDB, err := storm.Open(oldDBPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer old.Close()
|
defer oldDB.Close()
|
||||||
|
|
||||||
new, err := storm.Open(newDB)
|
newDB, err := storm.Open(newDBPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer new.Close()
|
defer newDB.Close()
|
||||||
|
|
||||||
sto, err := bolt.NewStorage(new)
|
sto, err := bolt.NewStorage(newDB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = importUsers(old, sto)
|
err = importUsers(oldDB, sto)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = importConf(old, oldConf, sto)
|
err = importConf(oldDB, oldConf, sto)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,11 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/asdine/storm"
|
"github.com/asdine/storm"
|
||||||
|
bolt "go.etcd.io/bbolt"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/rules"
|
"github.com/filebrowser/filebrowser/v2/rules"
|
||||||
"github.com/filebrowser/filebrowser/v2/storage"
|
"github.com/filebrowser/filebrowser/v2/storage"
|
||||||
"github.com/filebrowser/filebrowser/v2/users"
|
"github.com/filebrowser/filebrowser/v2/users"
|
||||||
bolt "go.etcd.io/bbolt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type oldUser struct {
|
type oldUser struct {
|
||||||
|
@ -29,7 +30,7 @@ type oldUser struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func readOldUsers(db *storm.DB) ([]*oldUser, error) {
|
func readOldUsers(db *storm.DB) ([]*oldUser, error) {
|
||||||
users := []*oldUser{}
|
var oldUsers []*oldUser
|
||||||
err := db.Bolt.View(func(tx *bolt.Tx) error {
|
err := db.Bolt.View(func(tx *bolt.Tx) error {
|
||||||
return tx.Bucket([]byte("User")).ForEach(func(k []byte, v []byte) error {
|
return tx.Bucket([]byte("User")).ForEach(func(k []byte, v []byte) error {
|
||||||
if len(v) > 0 && string(v)[0] == '{' {
|
if len(v) > 0 && string(v)[0] == '{' {
|
||||||
|
@ -40,14 +41,14 @@ func readOldUsers(db *storm.DB) ([]*oldUser, error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
users = append(users, user)
|
oldUsers = append(oldUsers, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
return users, err
|
return oldUsers, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertUsersToNew(old []*oldUser) ([]*users.User, error) {
|
func convertUsersToNew(old []*oldUser) ([]*users.User, error) {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package bolt
|
||||||
import (
|
import (
|
||||||
"github.com/asdine/storm"
|
"github.com/asdine/storm"
|
||||||
"github.com/asdine/storm/q"
|
"github.com/asdine/storm/q"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/errors"
|
"github.com/filebrowser/filebrowser/v2/errors"
|
||||||
"github.com/filebrowser/filebrowser/v2/share"
|
"github.com/filebrowser/filebrowser/v2/share"
|
||||||
)
|
)
|
||||||
|
@ -46,5 +47,9 @@ func (s shareBackend) Save(l *share.Link) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s shareBackend) Delete(hash string) error {
|
func (s shareBackend) Delete(hash string) error {
|
||||||
return s.db.DeleteStruct(&share.Link{Hash: hash})
|
err := s.db.DeleteStruct(&share.Link{Hash: hash})
|
||||||
|
if err == storm.ErrNotFound {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"github.com/asdine/storm"
|
"github.com/asdine/storm"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/errors"
|
"github.com/filebrowser/filebrowser/v2/errors"
|
||||||
"github.com/filebrowser/filebrowser/v2/users"
|
"github.com/filebrowser/filebrowser/v2/users"
|
||||||
)
|
)
|
||||||
|
@ -38,17 +39,17 @@ func (st usersBackend) GetBy(i interface{}) (user *users.User, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st usersBackend) Gets() ([]*users.User, error) {
|
func (st usersBackend) Gets() ([]*users.User, error) {
|
||||||
users := []*users.User{}
|
var allUsers []*users.User
|
||||||
err := st.db.All(&users)
|
err := st.db.All(&allUsers)
|
||||||
if err == storm.ErrNotFound {
|
if err == storm.ErrNotFound {
|
||||||
return nil, errors.ErrNotExist
|
return nil, errors.ErrNotExist
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return users, err
|
return allUsers, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return users, err
|
return allUsers, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st usersBackend) Update(user *users.User, fields ...string) error {
|
func (st usersBackend) Update(user *users.User, fields ...string) error {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package bolt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/asdine/storm"
|
"github.com/asdine/storm"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/errors"
|
"github.com/filebrowser/filebrowser/v2/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"github.com/filebrowser/filebrowser/v2/users"
|
"github.com/filebrowser/filebrowser/v2/users"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Storage is a storage powered by a Backend whih makes the neccessary
|
// Storage is a storage powered by a Backend which makes the necessary
|
||||||
// verifications when fetching and saving data to ensure consistency.
|
// verifications when fetching and saving data to ensure consistency.
|
||||||
type Storage struct {
|
type Storage struct {
|
||||||
Users *users.Storage
|
Users *users.Storage
|
||||||
|
|
|
@ -40,7 +40,9 @@ func (s *Storage) Get(baseScope string, id interface{}) (user *User, err error)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user.Clean(baseScope)
|
if err := user.Clean(baseScope); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +54,9 @@ func (s *Storage) Gets(baseScope string) ([]*User, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
user.Clean(baseScope)
|
if err := user.Clean(baseScope); err != nil { //nolint:shadow
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return users, err
|
return users, err
|
||||||
|
|
|
@ -4,11 +4,11 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/errors"
|
"github.com/spf13/afero"
|
||||||
|
|
||||||
|
"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/spf13/afero"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ViewMode describes a view mode.
|
// ViewMode describes a view mode.
|
||||||
|
@ -52,6 +52,7 @@ var checkableFields = []string{
|
||||||
|
|
||||||
// Clean cleans up a user and verifies if all its fields
|
// Clean cleans up a user and verifies if all its fields
|
||||||
// are alright to be saved.
|
// are alright to be saved.
|
||||||
|
//nolint:gocyclo
|
||||||
func (u *User) Clean(baseScope string, fields ...string) error {
|
func (u *User) Clean(baseScope string, fields ...string) error {
|
||||||
if len(fields) == 0 {
|
if len(fields) == 0 {
|
||||||
fields = checkableFields
|
fields = checkableFields
|
||||||
|
|
Loading…
Reference in New Issue