updated
This commit is contained in:
		
							parent
							
								
									94f24f05de
								
							
						
					
					
						commit
						7c2723960f
					
				| 
						 | 
				
			
			@ -17,7 +17,7 @@ RUN apk --no-cache add \
 | 
			
		|||
VOLUME /srv
 | 
			
		||||
EXPOSE 8080
 | 
			
		||||
WORKDIR /
 | 
			
		||||
COPY --from=base /app/settings/filebrowser.yaml /filebrowser.yaml
 | 
			
		||||
COPY --from=base /app/filebrowser.yaml /filebrowser.yaml
 | 
			
		||||
COPY --from=base /app/filebrowser /filebrowser
 | 
			
		||||
COPY --from=nbuild /app/dist/ /frontend/dist/
 | 
			
		||||
ENTRYPOINT [ "./filebrowser" ]
 | 
			
		||||
| 
						 | 
				
			
			@ -202,7 +202,7 @@ func (a *HookAuth) SaveUser() (*users.User, error) {
 | 
			
		|||
func (a *HookAuth) GetUser(d *users.User) *users.User {
 | 
			
		||||
	// adds all permissions when user is admin
 | 
			
		||||
	isAdmin := a.Fields.GetBoolean("user.perm.admin", d.Perm.Admin)
 | 
			
		||||
	perms := users.Permissions{
 | 
			
		||||
	perm := users.Perm{
 | 
			
		||||
		Admin:    isAdmin,
 | 
			
		||||
		Execute:  isAdmin || a.Fields.GetBoolean("user.perm.execute", d.Perm.Execute),
 | 
			
		||||
		Create:   isAdmin || a.Fields.GetBoolean("user.perm.create", d.Perm.Create),
 | 
			
		||||
| 
						 | 
				
			
			@ -226,7 +226,7 @@ func (a *HookAuth) GetUser(d *users.User) *users.User {
 | 
			
		|||
		},
 | 
			
		||||
		Commands:     a.Fields.GetArray("user.commands", d.Commands),
 | 
			
		||||
		HideDotfiles: a.Fields.GetBoolean("user.hideDotfiles", d.HideDotfiles),
 | 
			
		||||
		Perm:         perms,
 | 
			
		||||
		Perm:         perm,
 | 
			
		||||
		LockPassword: true,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,12 +0,0 @@
 | 
			
		|||
package cmd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"log"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Execute executes the commands.
 | 
			
		||||
func Execute() {
 | 
			
		||||
	if err := rootCmd.Execute(); err != nil {
 | 
			
		||||
		log.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,26 +0,0 @@
 | 
			
		|||
package cmd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	rootCmd.AddCommand(cmdsCmd)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var cmdsCmd = &cobra.Command{
 | 
			
		||||
	Use:   "cmds",
 | 
			
		||||
	Short: "Command runner management utility",
 | 
			
		||||
	Long:  `Command runner management utility.`,
 | 
			
		||||
	Args:  cobra.NoArgs,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func printEvents(m map[string][]string) {
 | 
			
		||||
	for evt, cmds := range m {
 | 
			
		||||
		for i, cmd := range cmds {
 | 
			
		||||
			fmt.Printf("%s(%d): %s\n", evt, i, cmd)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,27 +0,0 @@
 | 
			
		|||
package cmd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	cmdsCmd.AddCommand(cmdsAddCmd)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var cmdsAddCmd = &cobra.Command{
 | 
			
		||||
	Use:   "add <event> <command>",
 | 
			
		||||
	Short: "Add a command to run on a specific event",
 | 
			
		||||
	Long:  `Add a command to run on a specific event.`,
 | 
			
		||||
	Args:  cobra.MinimumNArgs(2), //nolint:gomnd
 | 
			
		||||
	Run: python(func(cmd *cobra.Command, args []string, d pythonData) {
 | 
			
		||||
		s, err := d.store.Settings.Get()
 | 
			
		||||
		checkErr(err)
 | 
			
		||||
		command := strings.Join(args[1:], " ")
 | 
			
		||||
		s.Commands[args[0]] = append(s.Commands[args[0]], command)
 | 
			
		||||
		err = d.store.Settings.Save(s)
 | 
			
		||||
		checkErr(err)
 | 
			
		||||
		printEvents(s.Commands)
 | 
			
		||||
	}, pythonConfig{}),
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,31 +0,0 @@
 | 
			
		|||
package cmd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	cmdsCmd.AddCommand(cmdsLsCmd)
 | 
			
		||||
	cmdsLsCmd.Flags().StringP("event", "e", "", "event name, without 'before' or 'after'")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var cmdsLsCmd = &cobra.Command{
 | 
			
		||||
	Use:   "ls",
 | 
			
		||||
	Short: "List all commands for each event",
 | 
			
		||||
	Long:  `List all commands for each event.`,
 | 
			
		||||
	Args:  cobra.NoArgs,
 | 
			
		||||
	Run: python(func(cmd *cobra.Command, args []string, d pythonData) {
 | 
			
		||||
		s, err := d.store.Settings.Get()
 | 
			
		||||
		checkErr(err)
 | 
			
		||||
		evt := mustGetString(cmd.Flags(), "event")
 | 
			
		||||
 | 
			
		||||
		if evt == "" {
 | 
			
		||||
			printEvents(s.Commands)
 | 
			
		||||
		} else {
 | 
			
		||||
			show := map[string][]string{}
 | 
			
		||||
			show["before_"+evt] = s.Commands["before_"+evt]
 | 
			
		||||
			show["after_"+evt] = s.Commands["after_"+evt]
 | 
			
		||||
			printEvents(show)
 | 
			
		||||
		}
 | 
			
		||||
	}, pythonConfig{}),
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,56 +0,0 @@
 | 
			
		|||
package cmd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strconv"
 | 
			
		||||
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	cmdsCmd.AddCommand(cmdsRmCmd)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var cmdsRmCmd = &cobra.Command{
 | 
			
		||||
	Use:   "rm <event> <index> [index_end]",
 | 
			
		||||
	Short: "Removes a command from an event hooker",
 | 
			
		||||
	Long: `Removes a command from an event hooker. The provided index
 | 
			
		||||
is the same that's printed when you run 'cmds ls'. Note
 | 
			
		||||
that after each removal/addition, the index of the
 | 
			
		||||
commands change. So be careful when removing them after each
 | 
			
		||||
other.
 | 
			
		||||
 | 
			
		||||
You can also specify an optional parameter (index_end) so
 | 
			
		||||
you can remove all commands from 'index' to 'index_end',
 | 
			
		||||
including 'index_end'.`,
 | 
			
		||||
	Args: func(cmd *cobra.Command, args []string) error {
 | 
			
		||||
		if err := cobra.RangeArgs(2, 3)(cmd, args); err != nil { //nolint:gomnd
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, arg := range args[1:] {
 | 
			
		||||
			if _, err := strconv.Atoi(arg); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return nil
 | 
			
		||||
	},
 | 
			
		||||
	Run: python(func(cmd *cobra.Command, args []string, d pythonData) {
 | 
			
		||||
		s, err := d.store.Settings.Get()
 | 
			
		||||
		checkErr(err)
 | 
			
		||||
		evt := args[0]
 | 
			
		||||
 | 
			
		||||
		i, err := strconv.Atoi(args[1])
 | 
			
		||||
		checkErr(err)
 | 
			
		||||
		f := i
 | 
			
		||||
		if len(args) == 3 { //nolint:gomnd
 | 
			
		||||
			f, err = strconv.Atoi(args[2])
 | 
			
		||||
			checkErr(err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		s.Commands[evt] = append(s.Commands[evt][:i], s.Commands[evt][f+1:]...)
 | 
			
		||||
		err = d.store.Settings.Save(s)
 | 
			
		||||
		checkErr(err)
 | 
			
		||||
		printEvents(s.Commands)
 | 
			
		||||
	}, pythonConfig{}),
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,89 +0,0 @@
 | 
			
		|||
package cmd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"log"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"reflect"
 | 
			
		||||
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
 | 
			
		||||
	"github.com/gtsteffaniak/filebrowser/auth"
 | 
			
		||||
	"github.com/gtsteffaniak/filebrowser/settings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type settingsFile struct {
 | 
			
		||||
	Settings *settings.Settings `json:"settings"`
 | 
			
		||||
	Server   *settings.Server   `json:"server"`
 | 
			
		||||
	Auther   interface{}        `json:"auther"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var configImportCmd = &cobra.Command{
 | 
			
		||||
	Use:   "import <path>",
 | 
			
		||||
	Short: "Import a configuration file",
 | 
			
		||||
	Long: `Import a configuration file. This will replace all the existing
 | 
			
		||||
configuration. Can be used with or without unexisting databases.
 | 
			
		||||
 | 
			
		||||
If used with a nonexisting database, a key will be generated
 | 
			
		||||
automatically. Otherwise the key will be kept the same as in the
 | 
			
		||||
database.
 | 
			
		||||
 | 
			
		||||
The path must be for a json or yaml file.`,
 | 
			
		||||
	Args: jsonYamlArg,
 | 
			
		||||
	Run: python(func(cmd *cobra.Command, args []string, d pythonData) {
 | 
			
		||||
		var key []byte
 | 
			
		||||
		if d.hadDB {
 | 
			
		||||
			settings, err := d.store.Settings.Get()
 | 
			
		||||
			checkErr(err)
 | 
			
		||||
			key = settings.Key
 | 
			
		||||
		} else {
 | 
			
		||||
			key = generateKey()
 | 
			
		||||
		}
 | 
			
		||||
		file := settingsFile{}
 | 
			
		||||
		err := unmarshal(args[0], &file)
 | 
			
		||||
		checkErr(err)
 | 
			
		||||
		log.Println(file.Settings)
 | 
			
		||||
		file.Settings.Key = key
 | 
			
		||||
		err = d.store.Settings.Save(file.Settings)
 | 
			
		||||
		checkErr(err)
 | 
			
		||||
 | 
			
		||||
		err = d.store.Settings.SaveServer(file.Server)
 | 
			
		||||
		checkErr(err)
 | 
			
		||||
 | 
			
		||||
		var rawAuther interface{}
 | 
			
		||||
		if filepath.Ext(args[0]) != ".json" { //nolint:goconst
 | 
			
		||||
			rawAuther = cleanUpInterfaceMap(file.Auther.(map[interface{}]interface{}))
 | 
			
		||||
		} else {
 | 
			
		||||
			rawAuther = file.Auther
 | 
			
		||||
		}
 | 
			
		||||
		log.Println("config_import", file.Settings.Auth)
 | 
			
		||||
		var auther auth.Auther
 | 
			
		||||
		switch file.Settings.Auth.Method {
 | 
			
		||||
		case "password":
 | 
			
		||||
			auther = getAuther(auth.JSONAuth{}, rawAuther).(*auth.JSONAuth)
 | 
			
		||||
		case "noauth":
 | 
			
		||||
			auther = getAuther(auth.NoAuth{}, rawAuther).(*auth.NoAuth)
 | 
			
		||||
		case "proxy":
 | 
			
		||||
			auther = getAuther(auth.ProxyAuth{}, rawAuther).(*auth.ProxyAuth)
 | 
			
		||||
		case "hook":
 | 
			
		||||
			auther = getAuther(&auth.HookAuth{}, rawAuther).(*auth.HookAuth)
 | 
			
		||||
		default:
 | 
			
		||||
			checkErr(errors.New("invalid auth method"))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		err = d.store.Auth.Save(auther)
 | 
			
		||||
		checkErr(err)
 | 
			
		||||
 | 
			
		||||
	}, pythonConfig{allowNoDB: true}),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getAuther(sample auth.Auther, data interface{}) interface{} {
 | 
			
		||||
	authType := reflect.TypeOf(sample)
 | 
			
		||||
	auther := reflect.New(authType).Interface()
 | 
			
		||||
	bytes, err := json.Marshal(data)
 | 
			
		||||
	checkErr(err)
 | 
			
		||||
	err = json.Unmarshal(bytes, &auther)
 | 
			
		||||
	checkErr(err)
 | 
			
		||||
	return auther
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,79 +0,0 @@
 | 
			
		|||
package cmd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
 | 
			
		||||
	"github.com/gtsteffaniak/filebrowser/auth"
 | 
			
		||||
	"github.com/gtsteffaniak/filebrowser/errors"
 | 
			
		||||
	"github.com/gtsteffaniak/filebrowser/settings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var configInitCmd = &cobra.Command{
 | 
			
		||||
	Use:   "init",
 | 
			
		||||
	Short: "Initialize a new database",
 | 
			
		||||
	Long: `Initialize a new database to use with File Browser. All of
 | 
			
		||||
this options can be changed in the future with the command
 | 
			
		||||
'filebrowser config set'. The user related flags apply
 | 
			
		||||
to the defaults when creating new users and you don't
 | 
			
		||||
override the options.`,
 | 
			
		||||
	Args: cobra.NoArgs,
 | 
			
		||||
	Run: python(func(cmd *cobra.Command, args []string, d pythonData) {
 | 
			
		||||
		auther := getAuthentication()
 | 
			
		||||
		s := settings.GlobalConfiguration
 | 
			
		||||
		s.Key = generateKey()
 | 
			
		||||
		err := d.store.Settings.Save(&s)
 | 
			
		||||
		checkErr(err)
 | 
			
		||||
		err = d.store.Settings.SaveServer(&s.Server)
 | 
			
		||||
		checkErr(err)
 | 
			
		||||
		err = d.store.Auth.Save(auther)
 | 
			
		||||
		checkErr(err)
 | 
			
		||||
 | 
			
		||||
		fmt.Printf(`
 | 
			
		||||
Congratulations! You've set up your database to use with File Browser.
 | 
			
		||||
Now add your first user via 'filebrowser users add' and then you just
 | 
			
		||||
need to call the main command to boot up the server.
 | 
			
		||||
`)
 | 
			
		||||
	}, pythonConfig{noDB: true}),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//nolint:gocyclo
 | 
			
		||||
func getAuthentication() auth.Auther {
 | 
			
		||||
	method := settings.GlobalConfiguration.Auth.Method
 | 
			
		||||
	var auther auth.Auther
 | 
			
		||||
	if method == "proxy" {
 | 
			
		||||
		header := settings.GlobalConfiguration.Auth.Header
 | 
			
		||||
		auther = &auth.ProxyAuth{Header: header}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if method == "noauth" {
 | 
			
		||||
		auther = &auth.NoAuth{}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if method == "password" {
 | 
			
		||||
		jsonAuth := &auth.JSONAuth{}
 | 
			
		||||
		host := settings.GlobalConfiguration.Auth.Recaptcha.Host
 | 
			
		||||
		key := settings.GlobalConfiguration.Auth.Recaptcha.Key
 | 
			
		||||
		secret := settings.GlobalConfiguration.Auth.Recaptcha.Secret
 | 
			
		||||
		if key != "" && secret != "" {
 | 
			
		||||
			jsonAuth.ReCaptcha = &auth.ReCaptcha{
 | 
			
		||||
				Host:   host,
 | 
			
		||||
				Key:    key,
 | 
			
		||||
				Secret: secret,
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		auther = jsonAuth
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if method == "hook" {
 | 
			
		||||
		command := settings.GlobalConfiguration.Auth.Command
 | 
			
		||||
		auther = &auth.HookAuth{Command: command}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if auther == nil {
 | 
			
		||||
		panic(errors.ErrInvalidAuthMethod)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return auther
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,139 +0,0 @@
 | 
			
		|||
package cmd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"github.com/spf13/pflag"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	rootCmd.AddCommand(docsCmd)
 | 
			
		||||
	docsCmd.Flags().StringP("path", "p", "./docs", "path to save the docs")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func printToc(names []string) {
 | 
			
		||||
	for i, name := range names {
 | 
			
		||||
		name = strings.TrimSuffix(name, filepath.Ext(name))
 | 
			
		||||
		name = strings.Replace(name, "-", " ", -1)
 | 
			
		||||
		names[i] = name
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sort.Strings(names)
 | 
			
		||||
 | 
			
		||||
	toc := ""
 | 
			
		||||
	for _, name := range names {
 | 
			
		||||
		toc += "* [" + name + "](cli/" + strings.Replace(name, " ", "-", -1) + ".md)\n"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fmt.Println(toc)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var docsCmd = &cobra.Command{
 | 
			
		||||
	Use:    "docs",
 | 
			
		||||
	Hidden: true,
 | 
			
		||||
	Args:   cobra.NoArgs,
 | 
			
		||||
	Run: func(cmd *cobra.Command, args []string) {
 | 
			
		||||
		dir := mustGetString(cmd.Flags(), "path")
 | 
			
		||||
		generateDocs(rootCmd, dir)
 | 
			
		||||
		names := []string{}
 | 
			
		||||
 | 
			
		||||
		err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
 | 
			
		||||
			if err != nil || info.IsDir() {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if !strings.HasPrefix(info.Name(), "filebrowser") {
 | 
			
		||||
				return nil
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			names = append(names, info.Name())
 | 
			
		||||
			return nil
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
		checkErr(err)
 | 
			
		||||
		printToc(names)
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func generateDocs(cmd *cobra.Command, dir string) {
 | 
			
		||||
	for _, c := range cmd.Commands() {
 | 
			
		||||
		if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		generateDocs(c, dir)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	basename := strings.Replace(cmd.CommandPath(), " ", "-", -1) + ".md"
 | 
			
		||||
	filename := filepath.Join(dir, basename)
 | 
			
		||||
	f, err := os.Create(filename)
 | 
			
		||||
	checkErr(err)
 | 
			
		||||
	defer f.Close()
 | 
			
		||||
	generateMarkdown(cmd, f)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func generateMarkdown(cmd *cobra.Command, w io.Writer) {
 | 
			
		||||
	cmd.InitDefaultHelpCmd()
 | 
			
		||||
	cmd.InitDefaultHelpFlag()
 | 
			
		||||
 | 
			
		||||
	buf := new(bytes.Buffer)
 | 
			
		||||
	name := cmd.CommandPath()
 | 
			
		||||
 | 
			
		||||
	short := cmd.Short
 | 
			
		||||
	long := cmd.Long
 | 
			
		||||
	if long == "" {
 | 
			
		||||
		long = short
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buf.WriteString("---\ndescription: " + short + "\n---\n\n")
 | 
			
		||||
	buf.WriteString("# " + name + "\n\n")
 | 
			
		||||
	buf.WriteString("## Synopsis\n\n")
 | 
			
		||||
	buf.WriteString(long + "\n\n")
 | 
			
		||||
 | 
			
		||||
	if cmd.Runnable() {
 | 
			
		||||
		buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.UseLine()))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(cmd.Example) > 0 {
 | 
			
		||||
		buf.WriteString("## Examples\n\n")
 | 
			
		||||
		buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.Example))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	printOptions(buf, cmd)
 | 
			
		||||
	_, err := buf.WriteTo(w)
 | 
			
		||||
	checkErr(err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func generateFlagsTable(fs *pflag.FlagSet, buf io.StringWriter) {
 | 
			
		||||
	_, _ = buf.WriteString("| Name | Shorthand | Usage |\n")
 | 
			
		||||
	_, _ = buf.WriteString("|------|-----------|-------|\n")
 | 
			
		||||
 | 
			
		||||
	fs.VisitAll(func(f *pflag.Flag) {
 | 
			
		||||
		_, _ = buf.WriteString("|" + f.Name + "|" + f.Shorthand + "|" + f.Usage + "|\n")
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func printOptions(buf *bytes.Buffer, cmd *cobra.Command) {
 | 
			
		||||
	flags := cmd.NonInheritedFlags()
 | 
			
		||||
	flags.SetOutput(buf)
 | 
			
		||||
	if flags.HasAvailableFlags() {
 | 
			
		||||
		buf.WriteString("## Options\n\n")
 | 
			
		||||
		generateFlagsTable(flags, buf)
 | 
			
		||||
		buf.WriteString("\n")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	parentFlags := cmd.InheritedFlags()
 | 
			
		||||
	parentFlags.SetOutput(buf)
 | 
			
		||||
	if parentFlags.HasAvailableFlags() {
 | 
			
		||||
		buf.WriteString("### Inherited\n\n")
 | 
			
		||||
		generateFlagsTable(parentFlags, buf)
 | 
			
		||||
		buf.WriteString("\n")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2,6 +2,7 @@ package cmd
 | 
			
		|||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"flag"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/fs"
 | 
			
		||||
	"log"
 | 
			
		||||
| 
						 | 
				
			
			@ -10,13 +11,12 @@ import (
 | 
			
		|||
	"os"
 | 
			
		||||
	"os/signal"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"syscall"
 | 
			
		||||
 | 
			
		||||
	"github.com/spf13/pflag"
 | 
			
		||||
 | 
			
		||||
	"github.com/spf13/afero"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"github.com/spf13/pflag"
 | 
			
		||||
	v "github.com/spf13/viper"
 | 
			
		||||
	lumberjack "gopkg.in/natefinch/lumberjack.v2"
 | 
			
		||||
 | 
			
		||||
	"github.com/gtsteffaniak/filebrowser/auth"
 | 
			
		||||
| 
						 | 
				
			
			@ -30,7 +30,7 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	cfgFile string
 | 
			
		||||
	configFile string
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type dirFS struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -42,52 +42,21 @@ func (d dirFS) Open(name string) (fs.File, error) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	cobra.OnInitialize(initConfig)
 | 
			
		||||
	cobra.MousetrapHelpText = ""
 | 
			
		||||
	rootCmd.SetVersionTemplate("File Browser version {{printf \"%s\" .Version}}\n")
 | 
			
		||||
 | 
			
		||||
	flags := rootCmd.Flags()
 | 
			
		||||
 | 
			
		||||
	persistent := rootCmd.PersistentFlags()
 | 
			
		||||
 | 
			
		||||
	persistent.StringVarP(&cfgFile, "config", "c", "", "config file path")
 | 
			
		||||
	persistent.StringP("database", "d", "./filebrowser.db", "database path")
 | 
			
		||||
	flags.Bool("noauth", false, "use the noauth auther when using quick setup")
 | 
			
		||||
	flags.String("username", "admin", "username for the first user when using quick config")
 | 
			
		||||
	flags.String("password", "", "hashed password for the first user when using quick config (default \"admin\")")
 | 
			
		||||
	// Define a flag for the config option (-c or --config)
 | 
			
		||||
	configFlag := pflag.StringP("config", "c", "filebrowser.yaml", "Path to the config file")
 | 
			
		||||
	// Bind the flags to the pflag command line parser
 | 
			
		||||
	pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
 | 
			
		||||
	pflag.Parse()
 | 
			
		||||
	log.Println("Initializing with config file:", *configFlag)
 | 
			
		||||
	settings.Initialize(*configFlag)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var rootCmd = &cobra.Command{
 | 
			
		||||
	Use:   "filebrowser",
 | 
			
		||||
	Short: "A stylish web-based file browser",
 | 
			
		||||
	Long: `
 | 
			
		||||
If you've never run File Browser, you'll need to have a database for
 | 
			
		||||
it. Don't worry: you don't need to setup a separate database server.
 | 
			
		||||
We're using Bolt DB which is a single file database and all managed
 | 
			
		||||
by ourselves.
 | 
			
		||||
 | 
			
		||||
If you don't set "config", it will look for a configuration file called
 | 
			
		||||
filebrowser.{json, toml, yaml, yml} in the following directories:
 | 
			
		||||
 | 
			
		||||
- ./
 | 
			
		||||
- $HOME/
 | 
			
		||||
- /etc/filebrowser/
 | 
			
		||||
 | 
			
		||||
The precedence of the configuration values are as follows:
 | 
			
		||||
 | 
			
		||||
- flags
 | 
			
		||||
- environment variables
 | 
			
		||||
- configuration file
 | 
			
		||||
- database values
 | 
			
		||||
- defaults
 | 
			
		||||
 | 
			
		||||
Also, if the database path doesn't exist, File Browser will enter into
 | 
			
		||||
the quick setup mode and a new database will be bootstraped and a new
 | 
			
		||||
user created with the credentials from options "username" and "password".`,
 | 
			
		||||
	Use: "filebrowser",
 | 
			
		||||
	Run: python(func(cmd *cobra.Command, args []string, d pythonData) {
 | 
			
		||||
		serverConfig := settings.GlobalConfiguration.Server
 | 
			
		||||
		if !d.hadDB {
 | 
			
		||||
			quickSetup(cmd.Flags(), d)
 | 
			
		||||
			quickSetup(d)
 | 
			
		||||
		}
 | 
			
		||||
		if serverConfig.NumImageProcessors < 1 {
 | 
			
		||||
			log.Fatal("Image resize workers count could not be < 1")
 | 
			
		||||
| 
						 | 
				
			
			@ -156,41 +125,12 @@ func cleanupHandler(listener net.Listener, c chan os.Signal) { //nolint:interfac
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
//nolint:gocyclo
 | 
			
		||||
func getRunParams(flags *pflag.FlagSet, st *storage.Storage) *settings.Server {
 | 
			
		||||
func getRunParams(st *storage.Storage) *settings.Server {
 | 
			
		||||
	server, err := st.Settings.GetServer()
 | 
			
		||||
	checkErr(err)
 | 
			
		||||
	return server
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getParamB returns a parameter as a string and a boolean to tell if it is different from the default
 | 
			
		||||
//
 | 
			
		||||
// NOTE: we could simply bind the flags to viper and use IsSet.
 | 
			
		||||
// Although there is a bug on Viper that always returns true on IsSet
 | 
			
		||||
// if a flag is binded. Our alternative way is to manually check
 | 
			
		||||
// the flag and then the value from env/config/gotten by viper.
 | 
			
		||||
// https://github.com/spf13/viper/pull/331
 | 
			
		||||
func getParamB(flags *pflag.FlagSet, key string) (string, bool) {
 | 
			
		||||
	value, _ := flags.GetString(key)
 | 
			
		||||
 | 
			
		||||
	// If set on Flags, use it.
 | 
			
		||||
	if flags.Changed(key) {
 | 
			
		||||
		return value, true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If set through viper (env, config), return it.
 | 
			
		||||
	if v.IsSet(key) {
 | 
			
		||||
		return v.GetString(key), true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Otherwise use default value on flags.
 | 
			
		||||
	return value, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getParam(flags *pflag.FlagSet, key string) string {
 | 
			
		||||
	val, _ := getParamB(flags, key)
 | 
			
		||||
	return val
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func setupLog(logMethod string) {
 | 
			
		||||
	switch logMethod {
 | 
			
		||||
	case "stdout":
 | 
			
		||||
| 
						 | 
				
			
			@ -209,11 +149,10 @@ func setupLog(logMethod string) {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func quickSetup(flags *pflag.FlagSet, d pythonData) {
 | 
			
		||||
func quickSetup(d pythonData) {
 | 
			
		||||
	settings.GlobalConfiguration.Key = generateKey()
 | 
			
		||||
	var err error
 | 
			
		||||
	if settings.GlobalConfiguration.Auth.Method == "noauth" {
 | 
			
		||||
		settings.GlobalConfiguration.Auth.Method = "noauth"
 | 
			
		||||
		err = d.store.Auth.Save(&auth.NoAuth{})
 | 
			
		||||
	} else {
 | 
			
		||||
		settings.GlobalConfiguration.Auth.Method = "password"
 | 
			
		||||
| 
						 | 
				
			
			@ -223,50 +162,18 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) {
 | 
			
		|||
	checkErr(err)
 | 
			
		||||
	err = d.store.Settings.SaveServer(&settings.GlobalConfiguration.Server)
 | 
			
		||||
	checkErr(err)
 | 
			
		||||
 | 
			
		||||
	username := getParam(flags, "username")
 | 
			
		||||
	password := getParam(flags, "password")
 | 
			
		||||
 | 
			
		||||
	if password == "" {
 | 
			
		||||
		password, err = users.HashPwd("admin")
 | 
			
		||||
		checkErr(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	username := settings.GlobalConfiguration.AdminUsername
 | 
			
		||||
	password := settings.GlobalConfiguration.AdminPassword
 | 
			
		||||
	if username == "" || password == "" {
 | 
			
		||||
		log.Fatal("username and password cannot be empty during quick setup")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	user := &users.User{
 | 
			
		||||
		Username:     username,
 | 
			
		||||
		Password:     password,
 | 
			
		||||
		LockPassword: false,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	settings.GlobalConfiguration.UserDefaults.Apply(user)
 | 
			
		||||
	user.Perm.Admin = true
 | 
			
		||||
 | 
			
		||||
	err = d.store.Users.Save(user)
 | 
			
		||||
	checkErr(err)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func initConfig() {
 | 
			
		||||
	if cfgFile == "" {
 | 
			
		||||
		v.AddConfigPath(".")
 | 
			
		||||
		v.AddConfigPath("/etc/filebrowser/")
 | 
			
		||||
		v.SetConfigName("filebrowser")
 | 
			
		||||
	} else {
 | 
			
		||||
		v.SetConfigFile(cfgFile)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v.SetEnvPrefix("FB")
 | 
			
		||||
	v.AutomaticEnv()
 | 
			
		||||
	v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
 | 
			
		||||
	if err := v.ReadInConfig(); err != nil {
 | 
			
		||||
		if _, ok := err.(v.ConfigParseError); ok {
 | 
			
		||||
			panic(err)
 | 
			
		||||
		}
 | 
			
		||||
		cfgFile = "No config file used"
 | 
			
		||||
	} else {
 | 
			
		||||
		cfgFile = "Using config file: " + v.ConfigFileUsed()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,6 @@ package cmd
 | 
			
		|||
import (
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
 | 
			
		||||
	"github.com/gtsteffaniak/filebrowser/settings"
 | 
			
		||||
	"github.com/gtsteffaniak/filebrowser/users"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -37,26 +36,15 @@ options you want to change.`,
 | 
			
		|||
		} else {
 | 
			
		||||
			user, err = d.store.Users.Get("", username)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		checkErr(err)
 | 
			
		||||
 | 
			
		||||
		defaults := settings.UserDefaults{
 | 
			
		||||
			Scope:       user.Scope,
 | 
			
		||||
			Locale:      user.Locale,
 | 
			
		||||
			ViewMode:    user.ViewMode,
 | 
			
		||||
			SingleClick: user.SingleClick,
 | 
			
		||||
			Perm:        user.Perm,
 | 
			
		||||
			Sorting:     user.Sorting,
 | 
			
		||||
			Commands:    user.Commands,
 | 
			
		||||
		}
 | 
			
		||||
		user.Scope = defaults.Scope
 | 
			
		||||
		user.Locale = defaults.Locale
 | 
			
		||||
		user.ViewMode = defaults.ViewMode
 | 
			
		||||
		user.SingleClick = defaults.SingleClick
 | 
			
		||||
		user.Perm = defaults.Perm
 | 
			
		||||
		user.Commands = defaults.Commands
 | 
			
		||||
		user.Sorting = defaults.Sorting
 | 
			
		||||
		user.LockPassword = mustGetBool(flags, "lockPassword")
 | 
			
		||||
		user.Scope = user.Scope
 | 
			
		||||
		user.Locale = user.Locale
 | 
			
		||||
		user.ViewMode = user.ViewMode
 | 
			
		||||
		user.SingleClick = user.SingleClick
 | 
			
		||||
		user.Perm = user.Perm
 | 
			
		||||
		user.Commands = user.Commands
 | 
			
		||||
		user.Sorting = user.Sorting
 | 
			
		||||
		user.LockPassword = user.LockPassword
 | 
			
		||||
 | 
			
		||||
		if newUsername != "" {
 | 
			
		||||
			user.Username = newUsername
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,9 +10,9 @@ import (
 | 
			
		|||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/asdine/storm/v3"
 | 
			
		||||
	"github.com/goccy/go-yaml"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"github.com/spf13/pflag"
 | 
			
		||||
	yaml "gopkg.in/yaml.v2"
 | 
			
		||||
 | 
			
		||||
	"github.com/gtsteffaniak/filebrowser/settings"
 | 
			
		||||
	"github.com/gtsteffaniak/filebrowser/storage"
 | 
			
		||||
| 
						 | 
				
			
			@ -118,8 +118,8 @@ func marshal(filename string, data interface{}) error {
 | 
			
		|||
		encoder.SetIndent("", "    ")
 | 
			
		||||
		return encoder.Encode(data)
 | 
			
		||||
	case ".yml", ".yaml": //nolint:goconst
 | 
			
		||||
		encoder := yaml.NewEncoder(fd)
 | 
			
		||||
		return encoder.Encode(data)
 | 
			
		||||
		_, err := yaml.Marshal(fd)
 | 
			
		||||
		return err
 | 
			
		||||
	default:
 | 
			
		||||
		return errors.New("invalid format: " + ext)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,7 @@ auth:
 | 
			
		|||
userDefaults:
 | 
			
		||||
  hideDotfiles: true
 | 
			
		||||
  singleClick: false
 | 
			
		||||
  perm:
 | 
			
		||||
  permissions:
 | 
			
		||||
    admin: false
 | 
			
		||||
    create: true
 | 
			
		||||
    rename: true
 | 
			
		||||
| 
						 | 
				
			
			@ -15,3 +15,5 @@ userDefaults:
 | 
			
		|||
    delete: true
 | 
			
		||||
    share: true
 | 
			
		||||
    download: true
 | 
			
		||||
frontend:
 | 
			
		||||
  theme: dark
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
module github.com/gtsteffaniak/filebrowser
 | 
			
		||||
 | 
			
		||||
go 1.20
 | 
			
		||||
go 1.21.0
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/asdine/storm/v3 v3.2.1
 | 
			
		||||
| 
						 | 
				
			
			@ -14,18 +14,16 @@ require (
 | 
			
		|||
	github.com/maruel/natural v1.1.0
 | 
			
		||||
	github.com/marusama/semaphore/v2 v2.5.0
 | 
			
		||||
	github.com/mholt/archiver/v3 v3.5.1
 | 
			
		||||
	github.com/shirou/gopsutil/v3 v3.23.7
 | 
			
		||||
	github.com/shirou/gopsutil/v3 v3.23.8
 | 
			
		||||
	github.com/spf13/afero v1.9.5
 | 
			
		||||
	github.com/spf13/cobra v1.7.0
 | 
			
		||||
	github.com/spf13/pflag v1.0.5
 | 
			
		||||
	github.com/spf13/viper v1.16.0
 | 
			
		||||
	github.com/stretchr/testify v1.8.4
 | 
			
		||||
	github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce
 | 
			
		||||
	golang.org/x/crypto v0.12.0
 | 
			
		||||
	golang.org/x/image v0.11.0
 | 
			
		||||
	golang.org/x/text v0.12.0
 | 
			
		||||
	golang.org/x/image v0.12.0
 | 
			
		||||
	golang.org/x/text v0.13.0
 | 
			
		||||
	gopkg.in/natefinch/lumberjack.v2 v2.2.1
 | 
			
		||||
	gopkg.in/yaml.v2 v2.4.0
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
| 
						 | 
				
			
			@ -34,35 +32,27 @@ require (
 | 
			
		|||
	github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
 | 
			
		||||
	github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect
 | 
			
		||||
	github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 // indirect
 | 
			
		||||
	github.com/fatih/color v1.13.0 // indirect
 | 
			
		||||
	github.com/fsnotify/fsnotify v1.6.0 // indirect
 | 
			
		||||
	github.com/fatih/color v1.10.0 // indirect
 | 
			
		||||
	github.com/go-errors/errors v1.4.2 // indirect
 | 
			
		||||
	github.com/go-ole/go-ole v1.2.6 // indirect
 | 
			
		||||
	github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect
 | 
			
		||||
	github.com/golang/snappy v0.0.2 // indirect
 | 
			
		||||
	github.com/hashicorp/hcl v1.0.0 // indirect
 | 
			
		||||
	github.com/inconshreveable/mousetrap v1.1.0 // indirect
 | 
			
		||||
	github.com/klauspost/compress v1.11.4 // indirect
 | 
			
		||||
	github.com/klauspost/pgzip v1.2.5 // indirect
 | 
			
		||||
	github.com/magiconair/properties v1.8.7 // indirect
 | 
			
		||||
	github.com/mattn/go-colorable v0.1.12 // indirect
 | 
			
		||||
	github.com/mattn/go-isatty v0.0.14 // indirect
 | 
			
		||||
	github.com/mitchellh/mapstructure v1.5.0 // indirect
 | 
			
		||||
	github.com/mattn/go-colorable v0.1.8 // indirect
 | 
			
		||||
	github.com/mattn/go-isatty v0.0.12 // indirect
 | 
			
		||||
	github.com/nwaples/rardecode v1.1.0 // indirect
 | 
			
		||||
	github.com/pelletier/go-toml/v2 v2.0.9 // indirect
 | 
			
		||||
	github.com/pierrec/lz4/v4 v4.1.2 // indirect
 | 
			
		||||
	github.com/pmezard/go-difflib v1.0.0 // indirect
 | 
			
		||||
	github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
 | 
			
		||||
	github.com/spf13/cast v1.5.1 // indirect
 | 
			
		||||
	github.com/spf13/jwalterweatherman v1.1.0 // indirect
 | 
			
		||||
	github.com/subosito/gotenv v1.4.2 // indirect
 | 
			
		||||
	github.com/ulikunitz/xz v0.5.9 // indirect
 | 
			
		||||
	github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
 | 
			
		||||
	github.com/yusufpapurcu/wmi v1.2.3 // indirect
 | 
			
		||||
	go.etcd.io/bbolt v1.3.7 // indirect
 | 
			
		||||
	go.etcd.io/bbolt v1.3.4 // indirect
 | 
			
		||||
	golang.org/x/net v0.10.0 // indirect
 | 
			
		||||
	golang.org/x/sys v0.11.0 // indirect
 | 
			
		||||
	golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
 | 
			
		||||
	gopkg.in/ini.v1 v1.67.0 // indirect
 | 
			
		||||
	golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
 | 
			
		||||
	gopkg.in/yaml.v2 v2.4.0 // indirect
 | 
			
		||||
	gopkg.in/yaml.v3 v3.0.1 // indirect
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -86,13 +86,10 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
 | 
			
		|||
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
 | 
			
		||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
 | 
			
		||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 | 
			
		||||
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
 | 
			
		||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
 | 
			
		||||
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
 | 
			
		||||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
 | 
			
		||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
 | 
			
		||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
 | 
			
		||||
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
 | 
			
		||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
 | 
			
		||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
 | 
			
		||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
 | 
			
		||||
github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
 | 
			
		||||
github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
 | 
			
		||||
| 
						 | 
				
			
			@ -104,8 +101,11 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
 | 
			
		|||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
 | 
			
		||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
 | 
			
		||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
 | 
			
		||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
 | 
			
		||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
 | 
			
		||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
 | 
			
		||||
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
 | 
			
		||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
 | 
			
		||||
github.com/goccy/go-yaml v1.11.0 h1:n7Z+zx8S9f9KgzG6KtQKf+kwqXZlLNR2F6018Dgau54=
 | 
			
		||||
github.com/goccy/go-yaml v1.11.0/go.mod h1:H+mJrWtjPTJAHvRbV09MCK9xYwODM+wRTVFFTWckfng=
 | 
			
		||||
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
 | 
			
		||||
| 
						 | 
				
			
			@ -138,8 +138,8 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
 | 
			
		|||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
 | 
			
		||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
 | 
			
		||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 | 
			
		||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
 | 
			
		||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 | 
			
		||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
 | 
			
		||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 | 
			
		||||
github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw=
 | 
			
		||||
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 | 
			
		||||
| 
						 | 
				
			
			@ -180,8 +180,6 @@ github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
 | 
			
		|||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
 | 
			
		||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
 | 
			
		||||
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/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.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
 | 
			
		||||
| 
						 | 
				
			
			@ -198,33 +196,26 @@ github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgo
 | 
			
		|||
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
 | 
			
		||||
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
 | 
			
		||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
 | 
			
		||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
 | 
			
		||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 | 
			
		||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
 | 
			
		||||
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/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 | 
			
		||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
 | 
			
		||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
 | 
			
		||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
 | 
			
		||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
 | 
			
		||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
 | 
			
		||||
github.com/maruel/natural v1.1.0 h1:2z1NgP/Vae+gYrtC0VuvrTJ6U35OuyUqDdfluLqMWuQ=
 | 
			
		||||
github.com/maruel/natural v1.1.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-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
 | 
			
		||||
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
 | 
			
		||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
 | 
			
		||||
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
 | 
			
		||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
 | 
			
		||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
 | 
			
		||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
 | 
			
		||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
 | 
			
		||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
 | 
			
		||||
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/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
 | 
			
		||||
github.com/mitchellh/mapstructure v1.5.0/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/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0=
 | 
			
		||||
github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
 | 
			
		||||
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.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 | 
			
		||||
| 
						 | 
				
			
			@ -235,24 +226,17 @@ 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/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
 | 
			
		||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 | 
			
		||||
github.com/shirou/gopsutil/v3 v3.23.7 h1:C+fHO8hfIppoJ1WdsVm1RoI0RwXoNdfTK7yWXV0wVj4=
 | 
			
		||||
github.com/shirou/gopsutil/v3 v3.23.7/go.mod h1:c4gnmoRC0hQuaLqvxnx1//VXQ0Ms/X9UnJF8pddY5z4=
 | 
			
		||||
github.com/shirou/gopsutil/v3 v3.23.8 h1:xnATPiybo6GgdRoC4YoGnxXZFRc3dqQTGi73oLvvBrE=
 | 
			
		||||
github.com/shirou/gopsutil/v3 v3.23.8/go.mod h1:7hmCaBn+2ZwaZOr6jmPBZDfawwMGuo1id3C6aM8EDqQ=
 | 
			
		||||
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
 | 
			
		||||
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
 | 
			
		||||
github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM=
 | 
			
		||||
github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
 | 
			
		||||
github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
 | 
			
		||||
github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
 | 
			
		||||
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
 | 
			
		||||
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
 | 
			
		||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
 | 
			
		||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
 | 
			
		||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 | 
			
		||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 | 
			
		||||
github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc=
 | 
			
		||||
github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg=
 | 
			
		||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 | 
			
		||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 | 
			
		||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
 | 
			
		||||
| 
						 | 
				
			
			@ -264,10 +248,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
 | 
			
		|||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 | 
			
		||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
 | 
			
		||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 | 
			
		||||
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
 | 
			
		||||
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
 | 
			
		||||
github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
 | 
			
		||||
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
 | 
			
		||||
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
 | 
			
		||||
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
 | 
			
		||||
github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce h1:fb190+cK2Xz/dvi9Hv8eCYJYvIGUTN2/KLq1pT6CjEc=
 | 
			
		||||
github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4=
 | 
			
		||||
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
 | 
			
		||||
| 
						 | 
				
			
			@ -284,9 +266,8 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
 | 
			
		|||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 | 
			
		||||
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
 | 
			
		||||
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
 | 
			
		||||
go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
 | 
			
		||||
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
 | 
			
		||||
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
 | 
			
		||||
go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
 | 
			
		||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 | 
			
		||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
 | 
			
		||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 | 
			
		||||
| 
						 | 
				
			
			@ -316,8 +297,8 @@ golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMk
 | 
			
		|||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
 | 
			
		||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 | 
			
		||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 | 
			
		||||
golang.org/x/image v0.11.0 h1:ds2RoQvBvYTiJkwpSFDwCcDFNX7DqjL2WsUgTNk0Ooo=
 | 
			
		||||
golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8=
 | 
			
		||||
golang.org/x/image v0.12.0 h1:w13vZbU4o5rKOFFR8y7M+c4A5jXDC0uXTdHYRP8X2DQ=
 | 
			
		||||
golang.org/x/image v0.12.0/go.mod h1:Lu90jvHG7GfemOIcldsh9A2hS01ocl6oNO7ype5mEnk=
 | 
			
		||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 | 
			
		||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 | 
			
		||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 | 
			
		||||
| 
						 | 
				
			
			@ -440,16 +421,12 @@ golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7w
 | 
			
		|||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
 | 
			
		||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
			
		||||
| 
						 | 
				
			
			@ -464,8 +441,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 | 
			
		|||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 | 
			
		||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 | 
			
		||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 | 
			
		||||
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
 | 
			
		||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
 | 
			
		||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
 | 
			
		||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
 | 
			
		||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
			
		||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
			
		||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
			
		||||
| 
						 | 
				
			
			@ -521,9 +498,8 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
 | 
			
		|||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
 | 
			
		||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
 | 
			
		||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
 | 
			
		||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
 | 
			
		||||
| 
						 | 
				
			
			@ -612,15 +588,13 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
 | 
			
		|||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 | 
			
		||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 | 
			
		||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
 | 
			
		||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
 | 
			
		||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
 | 
			
		||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
 | 
			
		||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
 | 
			
		||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
 | 
			
		||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 | 
			
		||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
 | 
			
		||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
 | 
			
		||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,15 +20,15 @@ const (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
type userInfo struct {
 | 
			
		||||
	ID           uint              `json:"id"`
 | 
			
		||||
	Locale       string            `json:"locale"`
 | 
			
		||||
	ViewMode     string            `json:"viewMode"`
 | 
			
		||||
	SingleClick  bool              `json:"singleClick"`
 | 
			
		||||
	Perm         users.Permissions `json:"perm"`
 | 
			
		||||
	Commands     []string          `json:"commands"`
 | 
			
		||||
	LockPassword bool              `json:"lockPassword"`
 | 
			
		||||
	HideDotfiles bool              `json:"hideDotfiles"`
 | 
			
		||||
	DateFormat   bool              `json:"dateFormat"`
 | 
			
		||||
	ID           uint       `json:"id"`
 | 
			
		||||
	Locale       string     `json:"locale"`
 | 
			
		||||
	ViewMode     string     `json:"viewMode"`
 | 
			
		||||
	SingleClick  bool       `json:"singleClick"`
 | 
			
		||||
	Perm         users.Perm `json:"perm"`
 | 
			
		||||
	Commands     []string   `json:"commands"`
 | 
			
		||||
	LockPassword bool       `json:"lockPassword"`
 | 
			
		||||
	HideDotfiles bool       `json:"hideDotfiles"`
 | 
			
		||||
	DateFormat   bool       `json:"dateFormat"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type authToken struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -177,7 +177,6 @@ var renewHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data
 | 
			
		|||
})
 | 
			
		||||
 | 
			
		||||
func printToken(w http.ResponseWriter, _ *http.Request, d *data, user *users.User) (int, error) {
 | 
			
		||||
	log.Printf("%#v", user)
 | 
			
		||||
	claims := &authToken{
 | 
			
		||||
		User: userInfo{
 | 
			
		||||
			ID:           user.ID,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,10 +2,8 @@ package main
 | 
			
		|||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/gtsteffaniak/filebrowser/cmd"
 | 
			
		||||
	"github.com/gtsteffaniak/filebrowser/settings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	settings.Initialize()
 | 
			
		||||
	cmd.StartFilebrowser()
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,25 +5,26 @@ import (
 | 
			
		|||
	"os"
 | 
			
		||||
 | 
			
		||||
	"github.com/goccy/go-yaml"
 | 
			
		||||
	"github.com/gtsteffaniak/filebrowser/users"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var GlobalConfiguration Settings
 | 
			
		||||
var configYml = "filebrowser.yaml"
 | 
			
		||||
 | 
			
		||||
func Initialize() {
 | 
			
		||||
	yamlData := loadConfigFile()
 | 
			
		||||
func Initialize(configFile string) {
 | 
			
		||||
	yamlData := loadConfigFile(configFile)
 | 
			
		||||
	GlobalConfiguration = setDefaults()
 | 
			
		||||
	err := yaml.Unmarshal(yamlData, &GlobalConfiguration)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Fatalf("Error unmarshaling YAML data: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	GlobalConfiguration.Server.Root = "/srv" // hardcoded for now. TODO allow changing
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func loadConfigFile() []byte {
 | 
			
		||||
func loadConfigFile(configFile string) []byte {
 | 
			
		||||
	// Open and read the YAML file
 | 
			
		||||
	yamlFile, err := os.Open(configYml)
 | 
			
		||||
	yamlFile, err := os.Open(configFile)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("Error opening config file: %v\nUsing default config only", err)
 | 
			
		||||
		log.Printf("ERROR: opening config file\n %v\n WARNING: Using default config only\n If this was a mistake, please make sure the file exists and is accessible by the filebrowser binary.\n\n", err)
 | 
			
		||||
		setDefaults()
 | 
			
		||||
		return []byte{}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -44,12 +45,18 @@ func loadConfigFile() []byte {
 | 
			
		|||
 | 
			
		||||
func setDefaults() Settings {
 | 
			
		||||
	return Settings{
 | 
			
		||||
		Signup: true,
 | 
			
		||||
		Signup:        true,
 | 
			
		||||
		AdminUsername: "admin",
 | 
			
		||||
		AdminPassword: "admin",
 | 
			
		||||
		Server: Server{
 | 
			
		||||
			EnableExec:         false,
 | 
			
		||||
			IndexingInterval:   5,
 | 
			
		||||
			Port:               8080,
 | 
			
		||||
			NumImageProcessors: 4,
 | 
			
		||||
			BaseURL:            "",
 | 
			
		||||
			Database:           "database.db",
 | 
			
		||||
			Log:                "stdout",
 | 
			
		||||
			Root:               "/srv",
 | 
			
		||||
		},
 | 
			
		||||
		Auth: Auth{
 | 
			
		||||
			Method: "password",
 | 
			
		||||
| 
						 | 
				
			
			@ -58,7 +65,16 @@ func setDefaults() Settings {
 | 
			
		|||
			},
 | 
			
		||||
		},
 | 
			
		||||
		UserDefaults: UserDefaults{
 | 
			
		||||
			LockPassword: false,
 | 
			
		||||
			HideDotfiles: true,
 | 
			
		||||
			Perm: users.Perm{
 | 
			
		||||
				Create:   true,
 | 
			
		||||
				Rename:   true,
 | 
			
		||||
				Modify:   true,
 | 
			
		||||
				Delete:   true,
 | 
			
		||||
				Share:    true,
 | 
			
		||||
				Download: true,
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,6 +36,6 @@ func GenerateKey() ([]byte, error) {
 | 
			
		|||
	return b, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetSettingsConfig(nameType string,Value string) string {
 | 
			
		||||
func GetSettingsConfig(nameType string, Value string) string {
 | 
			
		||||
	return nameType + Value
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,8 @@ type Settings struct {
 | 
			
		|||
	UserHomeBasePath string              `json:"userHomeBasePath"`
 | 
			
		||||
	Commands         map[string][]string `json:"commands"`
 | 
			
		||||
	Shell            []string            `json:"shell"`
 | 
			
		||||
	AdminUsername    string              `json:"adminUsername"`
 | 
			
		||||
	AdminPassword    string              `json:"adminPassword"`
 | 
			
		||||
	Rules            []rules.Rule        `json:"rules"`
 | 
			
		||||
	Server           Server              `json:"server"`
 | 
			
		||||
	Auth             Auth                `json:"auth"`
 | 
			
		||||
| 
						 | 
				
			
			@ -78,25 +80,17 @@ type Frontend struct {
 | 
			
		|||
// UserDefaults is a type that holds the default values
 | 
			
		||||
// for some fields on User.
 | 
			
		||||
type UserDefaults struct {
 | 
			
		||||
	Scope       string `json:"scope"`
 | 
			
		||||
	Locale      string `json:"locale"`
 | 
			
		||||
	ViewMode    string `json:"viewMode"`
 | 
			
		||||
	SingleClick bool   `json:"singleClick"`
 | 
			
		||||
	Sorting     struct {
 | 
			
		||||
	LockPassword bool   `json:"lockPassword"`
 | 
			
		||||
	Scope        string `json:"scope"`
 | 
			
		||||
	Locale       string `json:"locale"`
 | 
			
		||||
	ViewMode     string `json:"viewMode"`
 | 
			
		||||
	SingleClick  bool   `json:"singleClick"`
 | 
			
		||||
	Sorting      struct {
 | 
			
		||||
		By  string `json:"by"`
 | 
			
		||||
		Asc bool   `json:"asc"`
 | 
			
		||||
	} `json:"sorting"`
 | 
			
		||||
	Perm struct {
 | 
			
		||||
		Admin    bool `json:"admin"`
 | 
			
		||||
		Execute  bool `json:"execute"`
 | 
			
		||||
		Create   bool `json:"create"`
 | 
			
		||||
		Rename   bool `json:"rename"`
 | 
			
		||||
		Modify   bool `json:"modify"`
 | 
			
		||||
		Delete   bool `json:"delete"`
 | 
			
		||||
		Share    bool `json:"share"`
 | 
			
		||||
		Download bool `json:"download"`
 | 
			
		||||
	} `json:"perm"`
 | 
			
		||||
	Commands     []string `json:"commands"`
 | 
			
		||||
	HideDotfiles bool     `json:"hideDotfiles"`
 | 
			
		||||
	DateFormat   bool     `json:"dateFormat"`
 | 
			
		||||
	Perm         users.Perm `json:"permissions"`
 | 
			
		||||
	Commands     []string   `json:"commands"`
 | 
			
		||||
	HideDotfiles bool       `json:"hideDotfiles"`
 | 
			
		||||
	DateFormat   bool       `json:"dateFormat"`
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,7 +38,7 @@ userDefaults:
 | 
			
		|||
  sorting:
 | 
			
		||||
    by: ""
 | 
			
		||||
    asc: true
 | 
			
		||||
  perm:
 | 
			
		||||
  permissions:
 | 
			
		||||
    admin: true
 | 
			
		||||
    execute: true
 | 
			
		||||
    create: true
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,13 +0,0 @@
 | 
			
		|||
package users
 | 
			
		||||
 | 
			
		||||
// Permissions describe a user's permissions.
 | 
			
		||||
type Permissions struct {
 | 
			
		||||
	Admin    bool `json:"admin"`
 | 
			
		||||
	Execute  bool `json:"execute"`
 | 
			
		||||
	Create   bool `json:"create"`
 | 
			
		||||
	Rename   bool `json:"rename"`
 | 
			
		||||
	Modify   bool `json:"modify"`
 | 
			
		||||
	Delete   bool `json:"delete"`
 | 
			
		||||
	Share    bool `json:"share"`
 | 
			
		||||
	Download bool `json:"download"`
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -16,6 +16,17 @@ var (
 | 
			
		|||
	MosaicViewMode = "mosaic"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Perm struct {
 | 
			
		||||
	Admin    bool `json:"admin"`
 | 
			
		||||
	Execute  bool `json:"execute"`
 | 
			
		||||
	Create   bool `json:"create"`
 | 
			
		||||
	Rename   bool `json:"rename"`
 | 
			
		||||
	Modify   bool `json:"modify"`
 | 
			
		||||
	Delete   bool `json:"delete"`
 | 
			
		||||
	Share    bool `json:"share"`
 | 
			
		||||
	Download bool `json:"download"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// User describes a user.
 | 
			
		||||
type User struct {
 | 
			
		||||
	ID           uint          `storm:"id,increment" json:"id"`
 | 
			
		||||
| 
						 | 
				
			
			@ -26,7 +37,7 @@ type User struct {
 | 
			
		|||
	LockPassword bool          `json:"lockPassword"`
 | 
			
		||||
	ViewMode     string        `json:"viewMode"`
 | 
			
		||||
	SingleClick  bool          `json:"singleClick"`
 | 
			
		||||
	Perm         Permissions   `json:"perm"`
 | 
			
		||||
	Perm         Perm          `json:"perm"`
 | 
			
		||||
	Commands     []string      `json:"commands"`
 | 
			
		||||
	Sorting      files.Sorting `json:"sorting"`
 | 
			
		||||
	Fs           afero.Fs      `json:"-" yaml:"-"`
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue