removed all settings
This commit is contained in:
parent
43bf5b6f51
commit
805381a017
|
@ -9,7 +9,6 @@ import (
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/pflag"
|
|
||||||
|
|
||||||
"github.com/gtsteffaniak/filebrowser/auth"
|
"github.com/gtsteffaniak/filebrowser/auth"
|
||||||
"github.com/gtsteffaniak/filebrowser/errors"
|
"github.com/gtsteffaniak/filebrowser/errors"
|
||||||
|
@ -27,22 +26,6 @@ var configCmd = &cobra.Command{
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
}
|
}
|
||||||
|
|
||||||
func addConfigFlags(flags *pflag.FlagSet) {
|
|
||||||
addUserFlags(flags)
|
|
||||||
flags.BoolP("signup", "s", false, "allow users to signup")
|
|
||||||
flags.String("shell", "", "shell command to which other commands should be appended")
|
|
||||||
|
|
||||||
flags.String("recaptcha.host", "https://www.google.com", "use another host for ReCAPTCHA. recaptcha.net might be useful in China")
|
|
||||||
flags.String("recaptcha.key", "", "ReCaptcha site key")
|
|
||||||
flags.String("recaptcha.secret", "", "ReCaptcha secret")
|
|
||||||
|
|
||||||
flags.String("frontend.name", "", "replace 'File Browser' by this name")
|
|
||||||
flags.String("frontend.color", "", "set the theme color")
|
|
||||||
flags.String("frontend.files", "", "path to directory with images and custom styles")
|
|
||||||
flags.Bool("frontend.disableExternal", false, "disable external links such as GitHub links")
|
|
||||||
flags.Bool("frontend.disableUsedPercentage", false, "disable used disk percentage graph")
|
|
||||||
}
|
|
||||||
|
|
||||||
//nolint:gocyclo
|
//nolint:gocyclo
|
||||||
func getAuthentication() (string, auth.Auther) {
|
func getAuthentication() (string, auth.Auther) {
|
||||||
method := settings.GlobalConfiguration.Auth.Method
|
method := settings.GlobalConfiguration.Auth.Method
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
configCmd.AddCommand(configCatCmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
var configCatCmd = &cobra.Command{
|
|
||||||
Use: "cat",
|
|
||||||
Short: "Prints the configuration",
|
|
||||||
Long: `Prints the configuration.`,
|
|
||||||
Args: cobra.NoArgs,
|
|
||||||
Run: python(func(cmd *cobra.Command, args []string, d pythonData) {
|
|
||||||
set, err := d.store.Settings.Get()
|
|
||||||
checkErr(err)
|
|
||||||
ser, err := d.store.Settings.GetServer()
|
|
||||||
checkErr(err)
|
|
||||||
auther, err := d.store.Auth.Get(set.Auth.Method)
|
|
||||||
checkErr(err)
|
|
||||||
printSettings(ser, set, auther)
|
|
||||||
}, pythonConfig{}),
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
configCmd.AddCommand(configExportCmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
var configExportCmd = &cobra.Command{
|
|
||||||
Use: "export <path>",
|
|
||||||
Short: "Export the configuration to a file",
|
|
||||||
Long: `Export the configuration to a file. The path must be for a
|
|
||||||
json or yaml file. This exported configuration can be changed,
|
|
||||||
and imported again with 'config import' command.`,
|
|
||||||
Args: jsonYamlArg,
|
|
||||||
Run: python(func(cmd *cobra.Command, args []string, d pythonData) {
|
|
||||||
settings, err := d.store.Settings.Get()
|
|
||||||
checkErr(err)
|
|
||||||
|
|
||||||
server, err := d.store.Settings.GetServer()
|
|
||||||
checkErr(err)
|
|
||||||
|
|
||||||
auther, err := d.store.Auth.Get(settings.Auth.Method)
|
|
||||||
checkErr(err)
|
|
||||||
|
|
||||||
data := &settingsFile{
|
|
||||||
Settings: settings,
|
|
||||||
Auther: auther,
|
|
||||||
Server: server,
|
|
||||||
}
|
|
||||||
|
|
||||||
err = marshal(args[0], data)
|
|
||||||
checkErr(err)
|
|
||||||
}, pythonConfig{}),
|
|
||||||
}
|
|
|
@ -1,94 +0,0 @@
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"path/filepath"
|
|
||||||
"reflect"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
|
|
||||||
"github.com/gtsteffaniak/filebrowser/auth"
|
|
||||||
"github.com/gtsteffaniak/filebrowser/settings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
configCmd.AddCommand(configImportCmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
printSettings(file.Server, file.Settings, auther)
|
|
||||||
}, 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
|
|
||||||
}
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
configCmd.AddCommand(configInitCmd)
|
configCmd.AddCommand(configInitCmd)
|
||||||
addConfigFlags(configInitCmd.Flags())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var configInitCmd = &cobra.Command{
|
var configInitCmd = &cobra.Command{
|
||||||
|
|
|
@ -1,74 +0,0 @@
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/spf13/pflag"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
configCmd.AddCommand(configSetCmd)
|
|
||||||
addConfigFlags(configSetCmd.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
var configSetCmd = &cobra.Command{
|
|
||||||
Use: "set",
|
|
||||||
Short: "Updates the configuration",
|
|
||||||
Long: `Updates the configuration. Set the flags for the options
|
|
||||||
you want to change. Other options will remain unchanged.`,
|
|
||||||
Args: cobra.NoArgs,
|
|
||||||
Run: python(func(cmd *cobra.Command, args []string, d pythonData) {
|
|
||||||
flags := cmd.Flags()
|
|
||||||
set, err := d.store.Settings.Get()
|
|
||||||
checkErr(err)
|
|
||||||
|
|
||||||
ser, err := d.store.Settings.GetServer()
|
|
||||||
checkErr(err)
|
|
||||||
|
|
||||||
flags.Visit(func(flag *pflag.Flag) {
|
|
||||||
switch flag.Name {
|
|
||||||
case "baseurl":
|
|
||||||
ser.BaseURL = mustGetString(flags, flag.Name)
|
|
||||||
case "root":
|
|
||||||
ser.Root = mustGetString(flags, flag.Name)
|
|
||||||
case "socket":
|
|
||||||
ser.Socket = mustGetString(flags, flag.Name)
|
|
||||||
case "cert":
|
|
||||||
ser.TLSCert = mustGetString(flags, flag.Name)
|
|
||||||
case "key":
|
|
||||||
ser.TLSKey = mustGetString(flags, flag.Name)
|
|
||||||
case "address":
|
|
||||||
ser.Address = mustGetString(flags, flag.Name)
|
|
||||||
case "port":
|
|
||||||
ser.Port = 8080
|
|
||||||
case "log":
|
|
||||||
ser.Log = mustGetString(flags, flag.Name)
|
|
||||||
case "signup":
|
|
||||||
set.Signup = mustGetBool(flags, flag.Name)
|
|
||||||
case "shell":
|
|
||||||
set.Shell = convertCmdStrToCmdArray(mustGetString(flags, flag.Name))
|
|
||||||
case "frontend.name":
|
|
||||||
set.Frontend.Name = mustGetString(flags, flag.Name)
|
|
||||||
case "frontend.color":
|
|
||||||
set.Frontend.Color = mustGetString(flags, flag.Name)
|
|
||||||
case "frontend.disableExternal":
|
|
||||||
set.Frontend.DisableExternal = mustGetBool(flags, flag.Name)
|
|
||||||
case "frontend.disableUsedPercentage":
|
|
||||||
set.Frontend.DisableUsedPercentage = mustGetBool(flags, flag.Name)
|
|
||||||
case "frontend.files":
|
|
||||||
set.Frontend.Files = mustGetString(flags, flag.Name)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
getUserDefaults(flags, &set.UserDefaults, false)
|
|
||||||
|
|
||||||
// read the defaults
|
|
||||||
_, auther := getAuthentication()
|
|
||||||
err = d.store.Auth.Save(auther)
|
|
||||||
checkErr(err)
|
|
||||||
err = d.store.Settings.Save(set)
|
|
||||||
checkErr(err)
|
|
||||||
err = d.store.Settings.SaveServer(ser)
|
|
||||||
checkErr(err)
|
|
||||||
printSettings(ser, set, auther)
|
|
||||||
}, pythonConfig{}),
|
|
||||||
}
|
|
|
@ -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")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
|
|
||||||
"github.com/gtsteffaniak/filebrowser/users"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
rootCmd.AddCommand(hashCmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
var hashCmd = &cobra.Command{
|
|
||||||
Use: "hash <password>",
|
|
||||||
Short: "Hashes a password",
|
|
||||||
Long: `Hashes a password using bcrypt algorithm.`,
|
|
||||||
Args: cobra.ExactArgs(1),
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
pwd, err := users.HashPwd(args[0])
|
|
||||||
checkErr(err)
|
|
||||||
fmt.Println(pwd)
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -142,6 +142,12 @@ user created with the credentials from options "username" and "password".`,
|
||||||
}, pythonConfig{allowNoDB: true}),
|
}, pythonConfig{allowNoDB: true}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func StartFilebrowser() {
|
||||||
|
if err := rootCmd.Execute(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func cleanupHandler(listener net.Listener, c chan os.Signal) { //nolint:interfacer
|
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)
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
|
|
||||||
"github.com/gtsteffaniak/filebrowser/settings"
|
|
||||||
"github.com/gtsteffaniak/filebrowser/users"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
rulesCmd.AddCommand(rulesRmCommand)
|
|
||||||
rulesRmCommand.Flags().Uint("index", 0, "index of rule to remove")
|
|
||||||
_ = rulesRmCommand.MarkFlagRequired("index")
|
|
||||||
}
|
|
||||||
|
|
||||||
var rulesRmCommand = &cobra.Command{
|
|
||||||
Use: "rm <index> [index_end]",
|
|
||||||
Short: "Remove a global rule or user rule",
|
|
||||||
Long: `Remove a global rule or user rule. The provided index
|
|
||||||
is the same that's printed when you run 'rules 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(1, 2)(cmd, args); err != nil { //nolint:gomnd
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, arg := range args {
|
|
||||||
if _, err := strconv.Atoi(arg); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
Run: python(func(cmd *cobra.Command, args []string, d pythonData) {
|
|
||||||
i, err := strconv.Atoi(args[0])
|
|
||||||
checkErr(err)
|
|
||||||
f := i
|
|
||||||
if len(args) == 2 { //nolint:gomnd
|
|
||||||
f, err = strconv.Atoi(args[1])
|
|
||||||
checkErr(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
user := func(u *users.User) {
|
|
||||||
u.Rules = append(u.Rules[:i], u.Rules[f+1:]...)
|
|
||||||
err := d.store.Users.Save(u)
|
|
||||||
checkErr(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
global := func(s *settings.Settings) {
|
|
||||||
s.Rules = append(s.Rules[:i], s.Rules[f+1:]...)
|
|
||||||
err := d.store.Settings.Save(s)
|
|
||||||
checkErr(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
runRules(d.store, cmd, user, global)
|
|
||||||
}, pythonConfig{}),
|
|
||||||
}
|
|
|
@ -1,92 +0,0 @@
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/spf13/pflag"
|
|
||||||
|
|
||||||
"github.com/gtsteffaniak/filebrowser/rules"
|
|
||||||
"github.com/gtsteffaniak/filebrowser/settings"
|
|
||||||
"github.com/gtsteffaniak/filebrowser/storage"
|
|
||||||
"github.com/gtsteffaniak/filebrowser/users"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
rootCmd.AddCommand(rulesCmd)
|
|
||||||
rulesCmd.PersistentFlags().StringP("username", "u", "", "username of user to which the rules apply")
|
|
||||||
rulesCmd.PersistentFlags().UintP("id", "i", 0, "id of user to which the rules apply")
|
|
||||||
}
|
|
||||||
|
|
||||||
var rulesCmd = &cobra.Command{
|
|
||||||
Use: "rules",
|
|
||||||
Short: "Rules management utility",
|
|
||||||
Long: `On each subcommand you'll have available at least two flags:
|
|
||||||
"username" and "id". You must either set only one of them
|
|
||||||
or none. If you set one of them, the command will apply to
|
|
||||||
an user, otherwise it will be applied to the global set or
|
|
||||||
rules.`,
|
|
||||||
Args: cobra.NoArgs,
|
|
||||||
}
|
|
||||||
|
|
||||||
func runRules(st *storage.Storage, cmd *cobra.Command, usersFn func(*users.User), globalFn func(*settings.Settings)) {
|
|
||||||
id := getUserIdentifier(cmd.Flags())
|
|
||||||
if id != nil {
|
|
||||||
user, err := st.Users.Get("", id)
|
|
||||||
checkErr(err)
|
|
||||||
|
|
||||||
if usersFn != nil {
|
|
||||||
usersFn(user)
|
|
||||||
}
|
|
||||||
|
|
||||||
printRules(user.Rules, id)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
s, err := st.Settings.Get()
|
|
||||||
checkErr(err)
|
|
||||||
|
|
||||||
if globalFn != nil {
|
|
||||||
globalFn(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
printRules(s.Rules, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getUserIdentifier(flags *pflag.FlagSet) interface{} {
|
|
||||||
id := mustGetUint(flags, "id")
|
|
||||||
username := mustGetString(flags, "username")
|
|
||||||
|
|
||||||
if id != 0 {
|
|
||||||
return id
|
|
||||||
} else if username != "" {
|
|
||||||
return username
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func printRules(rulez []rules.Rule, id interface{}) {
|
|
||||||
if id == nil {
|
|
||||||
fmt.Printf("Global Rules:\n\n")
|
|
||||||
} else {
|
|
||||||
fmt.Printf("Rules for user %v:\n\n", id)
|
|
||||||
}
|
|
||||||
|
|
||||||
for id, rule := range rulez {
|
|
||||||
fmt.Printf("(%d) ", id)
|
|
||||||
if rule.Regex {
|
|
||||||
if rule.Allow {
|
|
||||||
fmt.Printf("Allow Regex: \t%s\n", rule.Regexp.Raw)
|
|
||||||
} else {
|
|
||||||
fmt.Printf("Disallow Regex: \t%s\n", rule.Regexp.Raw)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if rule.Allow {
|
|
||||||
fmt.Printf("Allow Path: \t%s\n", rule.Path)
|
|
||||||
} else {
|
|
||||||
fmt.Printf("Disallow Path: \t%s\n", rule.Path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"regexp"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
|
|
||||||
"github.com/gtsteffaniak/filebrowser/rules"
|
|
||||||
"github.com/gtsteffaniak/filebrowser/settings"
|
|
||||||
"github.com/gtsteffaniak/filebrowser/users"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
rulesCmd.AddCommand(rulesAddCmd)
|
|
||||||
rulesAddCmd.Flags().BoolP("allow", "a", false, "indicates this is an allow rule")
|
|
||||||
rulesAddCmd.Flags().BoolP("regex", "r", false, "indicates this is a regex rule")
|
|
||||||
}
|
|
||||||
|
|
||||||
var rulesAddCmd = &cobra.Command{
|
|
||||||
Use: "add <path|expression>",
|
|
||||||
Short: "Add a global rule or user rule",
|
|
||||||
Long: `Add a global rule or user rule.`,
|
|
||||||
Args: cobra.ExactArgs(1),
|
|
||||||
Run: python(func(cmd *cobra.Command, args []string, d pythonData) {
|
|
||||||
allow := mustGetBool(cmd.Flags(), "allow")
|
|
||||||
regex := mustGetBool(cmd.Flags(), "regex")
|
|
||||||
exp := args[0]
|
|
||||||
|
|
||||||
if regex {
|
|
||||||
regexp.MustCompile(exp)
|
|
||||||
}
|
|
||||||
|
|
||||||
rule := rules.Rule{
|
|
||||||
Allow: allow,
|
|
||||||
Regex: regex,
|
|
||||||
}
|
|
||||||
|
|
||||||
if regex {
|
|
||||||
rule.Regexp = &rules.Regexp{Raw: exp}
|
|
||||||
} else {
|
|
||||||
rule.Path = exp
|
|
||||||
}
|
|
||||||
|
|
||||||
user := func(u *users.User) {
|
|
||||||
u.Rules = append(u.Rules, rule)
|
|
||||||
err := d.store.Users.Save(u)
|
|
||||||
checkErr(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
global := func(s *settings.Settings) {
|
|
||||||
s.Rules = append(s.Rules, rule)
|
|
||||||
err := d.store.Settings.Save(s)
|
|
||||||
checkErr(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
runRules(d.store, cmd, user, global)
|
|
||||||
}, pythonConfig{}),
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
rulesCmd.AddCommand(rulesLsCommand)
|
|
||||||
}
|
|
||||||
|
|
||||||
var rulesLsCommand = &cobra.Command{
|
|
||||||
Use: "ls",
|
|
||||||
Short: "List global rules or user specific rules",
|
|
||||||
Long: `List global rules or user specific rules.`,
|
|
||||||
Args: cobra.NoArgs,
|
|
||||||
Run: python(func(cmd *cobra.Command, args []string, d pythonData) {
|
|
||||||
runRules(d.store, cmd, nil, nil)
|
|
||||||
}, pythonConfig{}),
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
|
|
||||||
"github.com/gtsteffaniak/filebrowser/users"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
usersCmd.AddCommand(usersAddCmd)
|
|
||||||
addUserFlags(usersAddCmd.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
var usersAddCmd = &cobra.Command{
|
|
||||||
Use: "add <username> <password>",
|
|
||||||
Short: "Create a new user",
|
|
||||||
Long: `Create a new user and add it to the database.`,
|
|
||||||
Args: cobra.ExactArgs(2), //nolint:gomnd
|
|
||||||
Run: python(func(cmd *cobra.Command, args []string, d pythonData) {
|
|
||||||
s, err := d.store.Settings.Get()
|
|
||||||
checkErr(err)
|
|
||||||
getUserDefaults(cmd.Flags(), &s.UserDefaults, false)
|
|
||||||
|
|
||||||
password, err := users.HashPwd(args[1])
|
|
||||||
checkErr(err)
|
|
||||||
|
|
||||||
user := &users.User{
|
|
||||||
Username: args[0],
|
|
||||||
Password: password,
|
|
||||||
LockPassword: mustGetBool(cmd.Flags(), "lockPassword"),
|
|
||||||
}
|
|
||||||
|
|
||||||
s.UserDefaults.Apply(user)
|
|
||||||
|
|
||||||
servSettings, err := d.store.Settings.GetServer()
|
|
||||||
checkErr(err)
|
|
||||||
// since getUserDefaults() polluted s.Defaults.Scope
|
|
||||||
// which makes the Scope not the one saved in the db
|
|
||||||
// we need the right s.Defaults.Scope here
|
|
||||||
s2, err := d.store.Settings.Get()
|
|
||||||
checkErr(err)
|
|
||||||
|
|
||||||
userHome, err := s2.MakeUserDir(user.Username, user.Scope, servSettings.Root)
|
|
||||||
checkErr(err)
|
|
||||||
user.Scope = userHome
|
|
||||||
|
|
||||||
err = d.store.Users.Save(user)
|
|
||||||
checkErr(err)
|
|
||||||
printUsers([]*users.User{user})
|
|
||||||
}, pythonConfig{}),
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
usersCmd.AddCommand(usersExportCmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
var usersExportCmd = &cobra.Command{
|
|
||||||
Use: "export <path>",
|
|
||||||
Short: "Export all users to a file.",
|
|
||||||
Long: `Export all users to a json or yaml file. Please indicate the
|
|
||||||
path to the file where you want to write the users.`,
|
|
||||||
Args: jsonYamlArg,
|
|
||||||
Run: python(func(cmd *cobra.Command, args []string, d pythonData) {
|
|
||||||
list, err := d.store.Users.Gets("")
|
|
||||||
checkErr(err)
|
|
||||||
|
|
||||||
err = marshal(args[0], list)
|
|
||||||
checkErr(err)
|
|
||||||
}, pythonConfig{}),
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
|
|
||||||
"github.com/gtsteffaniak/filebrowser/users"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
usersCmd.AddCommand(usersFindCmd)
|
|
||||||
usersCmd.AddCommand(usersLsCmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
var usersFindCmd = &cobra.Command{
|
|
||||||
Use: "find <id|username>",
|
|
||||||
Short: "Find a user by username or id",
|
|
||||||
Long: `Find a user by username or id. If no flag is set, all users will be printed.`,
|
|
||||||
Args: cobra.ExactArgs(1),
|
|
||||||
Run: findUsers,
|
|
||||||
}
|
|
||||||
|
|
||||||
var usersLsCmd = &cobra.Command{
|
|
||||||
Use: "ls",
|
|
||||||
Short: "List all users.",
|
|
||||||
Args: cobra.NoArgs,
|
|
||||||
Run: findUsers,
|
|
||||||
}
|
|
||||||
|
|
||||||
var findUsers = python(func(cmd *cobra.Command, args []string, d pythonData) {
|
|
||||||
var (
|
|
||||||
list []*users.User
|
|
||||||
user *users.User
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
|
|
||||||
if len(args) == 1 {
|
|
||||||
username, id := parseUsernameOrID(args[0])
|
|
||||||
if username != "" {
|
|
||||||
user, err = d.store.Users.Get("", username)
|
|
||||||
} else {
|
|
||||||
user, err = d.store.Users.Get("", id)
|
|
||||||
}
|
|
||||||
|
|
||||||
list = []*users.User{user}
|
|
||||||
} else {
|
|
||||||
list, err = d.store.Users.Gets("")
|
|
||||||
}
|
|
||||||
|
|
||||||
checkErr(err)
|
|
||||||
printUsers(list)
|
|
||||||
}, pythonConfig{})
|
|
|
@ -1,89 +0,0 @@
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
|
|
||||||
"github.com/gtsteffaniak/filebrowser/users"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
usersCmd.AddCommand(usersImportCmd)
|
|
||||||
usersImportCmd.Flags().Bool("overwrite", false, "overwrite users with the same id/username combo")
|
|
||||||
usersImportCmd.Flags().Bool("replace", false, "replace the entire user base")
|
|
||||||
}
|
|
||||||
|
|
||||||
var usersImportCmd = &cobra.Command{
|
|
||||||
Use: "import <path>",
|
|
||||||
Short: "Import users from a file",
|
|
||||||
Long: `Import users from a file. The path must be for a json or yaml
|
|
||||||
file. You can use this command to import new users to your
|
|
||||||
installation. For that, just don't place their ID on the files
|
|
||||||
list or set it to 0.`,
|
|
||||||
Args: jsonYamlArg,
|
|
||||||
Run: python(func(cmd *cobra.Command, args []string, d pythonData) {
|
|
||||||
fd, err := os.Open(args[0])
|
|
||||||
checkErr(err)
|
|
||||||
defer fd.Close()
|
|
||||||
|
|
||||||
list := []*users.User{}
|
|
||||||
err = unmarshal(args[0], &list)
|
|
||||||
checkErr(err)
|
|
||||||
|
|
||||||
for _, user := range list {
|
|
||||||
err = user.Clean("")
|
|
||||||
checkErr(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if mustGetBool(cmd.Flags(), "replace") {
|
|
||||||
oldUsers, err := d.store.Users.Gets("")
|
|
||||||
checkErr(err)
|
|
||||||
|
|
||||||
err = marshal("users.backup.json", list)
|
|
||||||
checkErr(err)
|
|
||||||
|
|
||||||
for _, user := range oldUsers {
|
|
||||||
err = d.store.Users.Delete(user.ID)
|
|
||||||
checkErr(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
overwrite := mustGetBool(cmd.Flags(), "overwrite")
|
|
||||||
|
|
||||||
for _, user := range list {
|
|
||||||
onDB, err := d.store.Users.Get("", user.ID)
|
|
||||||
|
|
||||||
// User exists in DB.
|
|
||||||
if err == nil {
|
|
||||||
if !overwrite {
|
|
||||||
checkErr(errors.New("user " + strconv.Itoa(int(user.ID)) + " is already registred"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the usernames mismatch, check if there is another one in the DB
|
|
||||||
// with the new username. If there is, print an error and cancel the
|
|
||||||
// operation
|
|
||||||
if user.Username != onDB.Username {
|
|
||||||
if conflictuous, err := d.store.Users.Get("", user.Username); err == nil { //nolint:govet
|
|
||||||
checkErr(usernameConflictError(user.Username, conflictuous.ID, user.ID))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// If it doesn't exist, set the ID to 0 to automatically get a new
|
|
||||||
// one that make sense in this DB.
|
|
||||||
user.ID = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
err = d.store.Users.Save(user)
|
|
||||||
checkErr(err)
|
|
||||||
}
|
|
||||||
}, pythonConfig{}),
|
|
||||||
}
|
|
||||||
|
|
||||||
func usernameConflictError(username string, originalID, newID uint) error {
|
|
||||||
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,31 +0,0 @@
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
usersCmd.AddCommand(usersRmCmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
var usersRmCmd = &cobra.Command{
|
|
||||||
Use: "rm <id|username>",
|
|
||||||
Short: "Delete a user by username or id",
|
|
||||||
Long: `Delete a user by username or id`,
|
|
||||||
Args: cobra.ExactArgs(1),
|
|
||||||
Run: python(func(cmd *cobra.Command, args []string, d pythonData) {
|
|
||||||
username, id := parseUsernameOrID(args[0])
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if username != "" {
|
|
||||||
err = d.store.Users.Delete(username)
|
|
||||||
} else {
|
|
||||||
err = d.store.Users.Delete(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
checkErr(err)
|
|
||||||
fmt.Println("user deleted successfully")
|
|
||||||
}, pythonConfig{}),
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
|
|
||||||
"github.com/gtsteffaniak/filebrowser/settings"
|
|
||||||
"github.com/gtsteffaniak/filebrowser/users"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
usersCmd.AddCommand(usersUpdateCmd)
|
|
||||||
|
|
||||||
usersUpdateCmd.Flags().StringP("password", "p", "", "new password")
|
|
||||||
usersUpdateCmd.Flags().StringP("username", "u", "", "new username")
|
|
||||||
addUserFlags(usersUpdateCmd.Flags())
|
|
||||||
}
|
|
||||||
|
|
||||||
var usersUpdateCmd = &cobra.Command{
|
|
||||||
Use: "update <id|username>",
|
|
||||||
Short: "Updates an existing user",
|
|
||||||
Long: `Updates an existing user. Set the flags for the
|
|
||||||
options you want to change.`,
|
|
||||||
Args: cobra.ExactArgs(1),
|
|
||||||
Run: python(func(cmd *cobra.Command, args []string, d pythonData) {
|
|
||||||
username, id := parseUsernameOrID(args[0])
|
|
||||||
flags := cmd.Flags()
|
|
||||||
password := mustGetString(flags, "password")
|
|
||||||
newUsername := mustGetString(flags, "username")
|
|
||||||
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
user *users.User
|
|
||||||
)
|
|
||||||
|
|
||||||
if id != 0 {
|
|
||||||
user, err = d.store.Users.Get("", id)
|
|
||||||
} 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,
|
|
||||||
}
|
|
||||||
getUserDefaults(flags, &defaults, false)
|
|
||||||
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")
|
|
||||||
|
|
||||||
if newUsername != "" {
|
|
||||||
user.Username = newUsername
|
|
||||||
}
|
|
||||||
|
|
||||||
if password != "" {
|
|
||||||
user.Password, err = users.HashPwd(password)
|
|
||||||
checkErr(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = d.store.Users.Update(user)
|
|
||||||
checkErr(err)
|
|
||||||
printUsers([]*users.User{user})
|
|
||||||
}, pythonConfig{}),
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
|
|
||||||
"github.com/gtsteffaniak/filebrowser/version"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
rootCmd.AddCommand(versionCmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
var versionCmd = &cobra.Command{
|
|
||||||
Use: "version",
|
|
||||||
Short: "Print the version number",
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
fmt.Println("File Browser v" + version.Version + "/" + version.CommitSHA)
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -1,111 +0,0 @@
|
||||||
package http
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
|
||||||
|
|
||||||
"github.com/gtsteffaniak/filebrowser/runner"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
WSWriteDeadline = 10 * time.Second
|
|
||||||
)
|
|
||||||
|
|
||||||
var upgrader = websocket.Upgrader{
|
|
||||||
ReadBufferSize: 1024,
|
|
||||||
WriteBufferSize: 1024,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
cmdNotAllowed = []byte("Command not allowed.")
|
|
||||||
)
|
|
||||||
|
|
||||||
//nolint:unparam
|
|
||||||
func wsErr(ws *websocket.Conn, r *http.Request, status int, err error) {
|
|
||||||
txt := http.StatusText(status)
|
|
||||||
if err != nil || status >= 400 {
|
|
||||||
log.Printf("%s: %v %s %v", r.URL.Path, status, r.RemoteAddr, err)
|
|
||||||
}
|
|
||||||
if err := ws.WriteControl(websocket.CloseInternalServerErr, []byte(txt), time.Now().Add(WSWriteDeadline)); err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var commandsHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
|
||||||
conn, err := upgrader.Upgrade(w, r, nil)
|
|
||||||
if err != nil {
|
|
||||||
return http.StatusInternalServerError, err
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
var raw string
|
|
||||||
|
|
||||||
for {
|
|
||||||
_, msg, err := conn.ReadMessage() //nolint:govet
|
|
||||||
if err != nil {
|
|
||||||
wsErr(conn, r, http.StatusInternalServerError, err)
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
raw = strings.TrimSpace(string(msg))
|
|
||||||
if raw != "" {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
command, err := runner.ParseCommand(d.settings, raw)
|
|
||||||
if err != nil {
|
|
||||||
if err := conn.WriteMessage(websocket.TextMessage, []byte(err.Error())); err != nil { //nolint:govet
|
|
||||||
wsErr(conn, r, http.StatusInternalServerError, err)
|
|
||||||
}
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if !d.server.EnableExec || !d.user.CanExecute(command[0]) {
|
|
||||||
if err := conn.WriteMessage(websocket.TextMessage, cmdNotAllowed); err != nil { //nolint:govet
|
|
||||||
wsErr(conn, r, http.StatusInternalServerError, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd := exec.Command(command[0], command[1:]...) //nolint:gosec
|
|
||||||
cmd.Dir = d.user.FullPath(r.URL.Path)
|
|
||||||
|
|
||||||
stdout, err := cmd.StdoutPipe()
|
|
||||||
if err != nil {
|
|
||||||
wsErr(conn, r, http.StatusInternalServerError, err)
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
stderr, err := cmd.StderrPipe()
|
|
||||||
if err != nil {
|
|
||||||
wsErr(conn, r, http.StatusInternalServerError, err)
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := cmd.Start(); err != nil {
|
|
||||||
wsErr(conn, r, http.StatusInternalServerError, err)
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
s := bufio.NewScanner(io.MultiReader(stdout, stderr))
|
|
||||||
for s.Scan() {
|
|
||||||
if err := conn.WriteMessage(websocket.TextMessage, s.Bytes()); err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := cmd.Wait(); err != nil {
|
|
||||||
wsErr(conn, r, http.StatusInternalServerError, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0, nil
|
|
||||||
})
|
|
|
@ -32,58 +32,44 @@ func NewHandler(
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
index, static := getStaticHandlers(store, server, assetsFs)
|
index, static := getStaticHandlers(store, server, assetsFs)
|
||||||
|
|
||||||
// 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
|
||||||
// URLs https://www.gorillatoolkit.org/pkg/mux#Router.SkipClean
|
// URLs https://www.gorillatoolkit.org/pkg/mux#Router.SkipClean
|
||||||
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, store, server)
|
return handle(fn, prefix, store, server)
|
||||||
}
|
}
|
||||||
|
|
||||||
r.HandleFunc("/health", healthHandler)
|
r.HandleFunc("/health", healthHandler)
|
||||||
r.PathPrefix("/static").Handler(static)
|
r.PathPrefix("/static").Handler(static)
|
||||||
r.NotFoundHandler = index
|
r.NotFoundHandler = index
|
||||||
|
|
||||||
api := r.PathPrefix("/api").Subrouter()
|
api := r.PathPrefix("/api").Subrouter()
|
||||||
|
|
||||||
api.Handle("/login", monkey(loginHandler, ""))
|
api.Handle("/login", monkey(loginHandler, ""))
|
||||||
api.Handle("/signup", monkey(signupHandler, ""))
|
api.Handle("/signup", monkey(signupHandler, ""))
|
||||||
api.Handle("/renew", monkey(renewHandler, ""))
|
api.Handle("/renew", monkey(renewHandler, ""))
|
||||||
|
|
||||||
users := api.PathPrefix("/users").Subrouter()
|
users := api.PathPrefix("/users").Subrouter()
|
||||||
users.Handle("", monkey(usersGetHandler, "")).Methods("GET")
|
users.Handle("", monkey(usersGetHandler, "")).Methods("GET")
|
||||||
users.Handle("", monkey(userPostHandler, "")).Methods("POST")
|
users.Handle("", monkey(userPostHandler, "")).Methods("POST")
|
||||||
users.Handle("/{id:[0-9]+}", monkey(userPutHandler, "")).Methods("PUT")
|
users.Handle("/{id:[0-9]+}", monkey(userPutHandler, "")).Methods("PUT")
|
||||||
users.Handle("/{id:[0-9]+}", monkey(userGetHandler, "")).Methods("GET")
|
users.Handle("/{id:[0-9]+}", monkey(userGetHandler, "")).Methods("GET")
|
||||||
users.Handle("/{id:[0-9]+}", monkey(userDeleteHandler, "")).Methods("DELETE")
|
users.Handle("/{id:[0-9]+}", monkey(userDeleteHandler, "")).Methods("DELETE")
|
||||||
|
|
||||||
api.PathPrefix("/resources").Handler(monkey(resourceGetHandler, "/api/resources")).Methods("GET")
|
api.PathPrefix("/resources").Handler(monkey(resourceGetHandler, "/api/resources")).Methods("GET")
|
||||||
api.PathPrefix("/resources").Handler(monkey(resourceDeleteHandler(fileCache), "/api/resources")).Methods("DELETE")
|
api.PathPrefix("/resources").Handler(monkey(resourceDeleteHandler(fileCache), "/api/resources")).Methods("DELETE")
|
||||||
api.PathPrefix("/resources").Handler(monkey(resourcePostHandler(fileCache), "/api/resources")).Methods("POST")
|
api.PathPrefix("/resources").Handler(monkey(resourcePostHandler(fileCache), "/api/resources")).Methods("POST")
|
||||||
api.PathPrefix("/resources").Handler(monkey(resourcePutHandler, "/api/resources")).Methods("PUT")
|
api.PathPrefix("/resources").Handler(monkey(resourcePutHandler, "/api/resources")).Methods("PUT")
|
||||||
api.PathPrefix("/resources").Handler(monkey(resourcePatchHandler(fileCache), "/api/resources")).Methods("PATCH")
|
api.PathPrefix("/resources").Handler(monkey(resourcePatchHandler(fileCache), "/api/resources")).Methods("PATCH")
|
||||||
|
|
||||||
api.PathPrefix("/usage").Handler(monkey(diskUsage, "/api/usage")).Methods("GET")
|
api.PathPrefix("/usage").Handler(monkey(diskUsage, "/api/usage")).Methods("GET")
|
||||||
|
|
||||||
api.Path("/shares").Handler(monkey(shareListHandler, "/api/shares")).Methods("GET")
|
api.Path("/shares").Handler(monkey(shareListHandler, "/api/shares")).Methods("GET")
|
||||||
api.PathPrefix("/share").Handler(monkey(shareGetsHandler, "/api/share")).Methods("GET")
|
api.PathPrefix("/share").Handler(monkey(shareGetsHandler, "/api/share")).Methods("GET")
|
||||||
api.PathPrefix("/share").Handler(monkey(sharePostHandler, "/api/share")).Methods("POST")
|
api.PathPrefix("/share").Handler(monkey(sharePostHandler, "/api/share")).Methods("POST")
|
||||||
api.PathPrefix("/share").Handler(monkey(shareDeleteHandler, "/api/share")).Methods("DELETE")
|
api.PathPrefix("/share").Handler(monkey(shareDeleteHandler, "/api/share")).Methods("DELETE")
|
||||||
|
|
||||||
api.Handle("/settings", monkey(settingsGetHandler, "")).Methods("GET")
|
api.Handle("/settings", monkey(settingsGetHandler, "")).Methods("GET")
|
||||||
api.Handle("/settings", monkey(settingsPutHandler, "")).Methods("PUT")
|
api.Handle("/settings", monkey(settingsPutHandler, "")).Methods("PUT")
|
||||||
|
|
||||||
api.PathPrefix("/raw").Handler(monkey(rawHandler, "/api/raw")).Methods("GET")
|
api.PathPrefix("/raw").Handler(monkey(rawHandler, "/api/raw")).Methods("GET")
|
||||||
api.PathPrefix("/preview/{size}/{path:.*}").
|
api.PathPrefix("/preview/{size}/{path:.*}").
|
||||||
Handler(monkey(previewHandler(imgSvc, fileCache, server.EnableThumbnails, server.ResizePreview), "/api/preview")).Methods("GET")
|
Handler(monkey(previewHandler(imgSvc, fileCache, server.EnableThumbnails, server.ResizePreview), "/api/preview")).Methods("GET")
|
||||||
api.PathPrefix("/command").Handler(monkey(commandsHandler, "/api/command")).Methods("GET")
|
|
||||||
api.PathPrefix("/search").Handler(monkey(searchHandler, "/api/search")).Methods("GET")
|
api.PathPrefix("/search").Handler(monkey(searchHandler, "/api/search")).Methods("GET")
|
||||||
|
|
||||||
public := api.PathPrefix("/public").Subrouter()
|
public := api.PathPrefix("/public").Subrouter()
|
||||||
public.PathPrefix("/dl").Handler(monkey(publicDlHandler, "/api/public/dl/")).Methods("GET")
|
public.PathPrefix("/dl").Handler(monkey(publicDlHandler, "/api/public/dl/")).Methods("GET")
|
||||||
public.PathPrefix("/share").Handler(monkey(publicShareHandler, "/api/public/share/")).Methods("GET")
|
public.PathPrefix("/share").Handler(monkey(publicShareHandler, "/api/public/share/")).Methods("GET")
|
||||||
|
|
||||||
return stripPrefix(server.BaseURL, r), nil
|
return stripPrefix(server.BaseURL, r), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,5 +5,5 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cmd.Execute()
|
cmd.StartFilebrowser()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue