fix : return error rather than log.fatal using checkErr

pull/5286/head
jagadam97 2025-07-19 19:45:01 +05:30
parent c694df4f5c
commit 42ce3cc5d1
25 changed files with 699 additions and 297 deletions

View File

@ -17,11 +17,15 @@ var cmdsAddCmd = &cobra.Command{
Args: cobra.MinimumNArgs(2),
RunE: python(func(_ *cobra.Command, args []string, d *pythonData) error {
s, err := d.store.Settings.Get()
checkErr(err)
if err != nil {
return err
}
command := strings.Join(args[1:], " ")
s.Commands[args[0]] = append(s.Commands[args[0]], command)
err = d.store.Settings.Save(s)
checkErr(err)
if err != nil {
return err
}
printEvents(s.Commands)
return nil
}, pythonConfig{}),

View File

@ -16,8 +16,13 @@ var cmdsLsCmd = &cobra.Command{
Args: cobra.NoArgs,
RunE: python(func(cmd *cobra.Command, _ []string, d *pythonData) error {
s, err := d.store.Settings.Get()
checkErr(err)
evt := mustGetString(cmd.Flags(), "event")
if err != nil {
return err
}
evt, err := mustGetString(cmd.Flags(), "event")
if err != nil {
return err
}
if evt == "" {
printEvents(s.Commands)

View File

@ -37,20 +37,28 @@ including 'index_end'.`,
},
RunE: python(func(_ *cobra.Command, args []string, d *pythonData) error {
s, err := d.store.Settings.Get()
checkErr(err)
if err != nil {
return err
}
evt := args[0]
i, err := strconv.Atoi(args[1])
checkErr(err)
if err != nil {
return err
}
f := i
if len(args) == 3 {
f, err = strconv.Atoi(args[2])
checkErr(err)
if err != nil {
return err
}
}
s.Commands[evt] = append(s.Commands[evt][:i], s.Commands[evt][f+1:]...)
err = d.store.Settings.Save(s)
checkErr(err)
if err != nil {
return err
}
printEvents(s.Commands)
return nil
}, pythonConfig{}),

View File

@ -51,9 +51,12 @@ func addConfigFlags(flags *pflag.FlagSet) {
flags.Bool("branding.disableUsedPercentage", false, "disable used disk percentage graph")
}
//nolint:gocyclo
func getAuthentication(flags *pflag.FlagSet, defaults ...interface{}) (settings.AuthMethod, auth.Auther) {
method := settings.AuthMethod(mustGetString(flags, "auth.method"))
func getAuthMethod(flags *pflag.FlagSet, defaults ...interface{}) (settings.AuthMethod, map[string]interface{}, error) {
methodStr, err := mustGetString(flags, "auth.method")
if err != nil {
return "", nil, err
}
method := settings.AuthMethod(methodStr)
var defaultAuther map[string]interface{}
if len(defaults) > 0 {
@ -64,83 +67,124 @@ func getAuthentication(flags *pflag.FlagSet, defaults ...interface{}) (settings.
method = def.AuthMethod
case auth.Auther:
ms, err := json.Marshal(def)
checkErr(err)
if err != nil {
return "", nil, err
}
err = json.Unmarshal(ms, &defaultAuther)
checkErr(err)
if err != nil {
return "", nil, err
}
}
}
}
}
var auther auth.Auther
if method == auth.MethodProxyAuth {
header := mustGetString(flags, "auth.header")
if header == "" {
header = defaultAuther["header"].(string)
}
if header == "" {
checkErr(nerrors.New("you must set the flag 'auth.header' for method 'proxy'"))
}
auther = &auth.ProxyAuth{Header: header}
}
if method == auth.MethodNoAuth {
auther = &auth.NoAuth{}
}
if method == auth.MethodJSONAuth {
jsonAuth := &auth.JSONAuth{}
host := mustGetString(flags, "recaptcha.host")
key := mustGetString(flags, "recaptcha.key")
secret := mustGetString(flags, "recaptcha.secret")
if key == "" {
if kmap, ok := defaultAuther["recaptcha"].(map[string]interface{}); ok {
key = kmap["key"].(string)
}
}
if secret == "" {
if smap, ok := defaultAuther["recaptcha"].(map[string]interface{}); ok {
secret = smap["secret"].(string)
}
}
if key != "" && secret != "" {
jsonAuth.ReCaptcha = &auth.ReCaptcha{
Host: host,
Key: key,
Secret: secret,
}
}
auther = jsonAuth
}
if method == auth.MethodHookAuth {
command := mustGetString(flags, "auth.command")
if command == "" {
command = defaultAuther["command"].(string)
}
if command == "" {
checkErr(nerrors.New("you must set the flag 'auth.command' for method 'hook'"))
}
auther = &auth.HookAuth{Command: command}
}
if auther == nil {
panic(errors.ErrInvalidAuthMethod)
}
return method, auther
return method, defaultAuther, nil
}
func printSettings(ser *settings.Server, set *settings.Settings, auther auth.Auther) {
func getProxyAuth(flags *pflag.FlagSet, defaultAuther map[string]interface{}) (auth.Auther, error) {
header, err := mustGetString(flags, "auth.header")
if err != nil {
return nil, err
}
if header == "" {
header = defaultAuther["header"].(string)
}
if header == "" {
return nil, nerrors.New("you must set the flag 'auth.header' for method 'proxy'")
}
return &auth.ProxyAuth{Header: header}, nil
}
func getNoAuth() auth.Auther {
return &auth.NoAuth{}
}
func getJSONAuth(flags *pflag.FlagSet, defaultAuther map[string]interface{}) (auth.Auther, error) {
jsonAuth := &auth.JSONAuth{}
host, err := mustGetString(flags, "recaptcha.host")
if err != nil {
return nil, err
}
key, err := mustGetString(flags, "recaptcha.key")
if err != nil {
return nil, err
}
secret, err := mustGetString(flags, "recaptcha.secret")
if err != nil {
return nil, err
}
if key == "" {
if kmap, ok := defaultAuther["recaptcha"].(map[string]interface{}); ok {
key = kmap["key"].(string)
}
}
if secret == "" {
if smap, ok := defaultAuther["recaptcha"].(map[string]interface{}); ok {
secret = smap["secret"].(string)
}
}
if key != "" && secret != "" {
jsonAuth.ReCaptcha = &auth.ReCaptcha{
Host: host,
Key: key,
Secret: secret,
}
}
return jsonAuth, nil
}
func getHookAuth(flags *pflag.FlagSet, defaultAuther map[string]interface{}) (auth.Auther, error) {
command, err := mustGetString(flags, "auth.command")
if err != nil {
return nil, err
}
if command == "" {
command = defaultAuther["command"].(string)
}
if command == "" {
return nil, nerrors.New("you must set the flag 'auth.command' for method 'hook'")
}
return &auth.HookAuth{Command: command}, nil
}
func getAuthentication(flags *pflag.FlagSet, defaults ...interface{}) (settings.AuthMethod, auth.Auther, error) {
method, defaultAuther, err := getAuthMethod(flags, defaults...)
if err != nil {
return "", nil, err
}
var auther auth.Auther
switch method {
case auth.MethodProxyAuth:
auther, err = getProxyAuth(flags, defaultAuther)
case auth.MethodNoAuth:
auther = getNoAuth()
case auth.MethodJSONAuth:
auther, err = getJSONAuth(flags, defaultAuther)
case auth.MethodHookAuth:
auther, err = getHookAuth(flags, defaultAuther)
default:
return "", nil, errors.ErrInvalidAuthMethod
}
if err != nil {
return "", nil, err
}
return method, auther, nil
}
func printSettings(ser *settings.Server, set *settings.Settings, auther auth.Auther) error {
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
fmt.Fprintf(w, "Sign up:\t%t\n", set.Signup)
@ -186,6 +230,9 @@ func printSettings(ser *settings.Server, set *settings.Settings, auther auth.Aut
w.Flush()
b, err := json.MarshalIndent(auther, "", " ")
checkErr(err)
if err != nil {
return err
}
fmt.Printf("\nAuther configuration (raw):\n\n%s\n\n", string(b))
return nil
}

View File

@ -15,12 +15,17 @@ var configCatCmd = &cobra.Command{
Args: cobra.NoArgs,
RunE: python(func(_ *cobra.Command, _ []string, d *pythonData) error {
set, err := d.store.Settings.Get()
checkErr(err)
if err != nil {
return err
}
ser, err := d.store.Settings.GetServer()
checkErr(err)
if err != nil {
return err
}
auther, err := d.store.Auth.Get(set.AuthMethod)
checkErr(err)
printSettings(ser, set, auther)
return nil
if err != nil {
return err
}
return printSettings(ser, set, auther)
}, pythonConfig{}),
}

View File

@ -17,13 +17,19 @@ and imported again with 'config import' command.`,
Args: jsonYamlArg,
RunE: python(func(_ *cobra.Command, args []string, d *pythonData) error {
settings, err := d.store.Settings.Get()
checkErr(err)
if err != nil {
return err
}
server, err := d.store.Settings.GetServer()
checkErr(err)
if err != nil {
return err
}
auther, err := d.store.Auth.Get(settings.AuthMethod)
checkErr(err)
if err != nil {
return err
}
data := &settingsFile{
Settings: settings,
@ -32,7 +38,9 @@ and imported again with 'config import' command.`,
}
err = marshal(args[0], data)
checkErr(err)
if err != nil {
return err
}
return nil
}, pythonConfig{}),
}

View File

@ -36,24 +36,33 @@ The path must be for a json or yaml file.`,
Args: jsonYamlArg,
RunE: python(func(_ *cobra.Command, args []string, d *pythonData) error {
var key []byte
var err error
if d.hadDB {
settings, err := d.store.Settings.Get()
checkErr(err)
settings, settingErr := d.store.Settings.Get()
if settingErr != nil {
return settingErr
}
key = settings.Key
} else {
key = generateKey()
}
file := settingsFile{}
err := unmarshal(args[0], &file)
checkErr(err)
err = unmarshal(args[0], &file)
if err != nil {
return err
}
file.Settings.Key = key
err = d.store.Settings.Save(file.Settings)
checkErr(err)
if err != nil {
return err
}
err = d.store.Settings.SaveServer(file.Server)
checkErr(err)
if err != nil {
return err
}
var rawAuther interface{}
if filepath.Ext(args[0]) != ".json" {
@ -63,33 +72,51 @@ The path must be for a json or yaml file.`,
}
var auther auth.Auther
var autherErr error
switch file.Settings.AuthMethod {
case auth.MethodJSONAuth:
auther = getAuther(auth.JSONAuth{}, rawAuther).(*auth.JSONAuth)
var a interface{}
a, autherErr = getAuther(auth.JSONAuth{}, rawAuther)
auther = a.(*auth.JSONAuth)
case auth.MethodNoAuth:
auther = getAuther(auth.NoAuth{}, rawAuther).(*auth.NoAuth)
var a interface{}
a, autherErr = getAuther(auth.NoAuth{}, rawAuther)
auther = a.(*auth.NoAuth)
case auth.MethodProxyAuth:
auther = getAuther(auth.ProxyAuth{}, rawAuther).(*auth.ProxyAuth)
var a interface{}
a, autherErr = getAuther(auth.ProxyAuth{}, rawAuther)
auther = a.(*auth.ProxyAuth)
case auth.MethodHookAuth:
auther = getAuther(&auth.HookAuth{}, rawAuther).(*auth.HookAuth)
var a interface{}
a, autherErr = getAuther(&auth.HookAuth{}, rawAuther)
auther = a.(*auth.HookAuth)
default:
checkErr(errors.New("invalid auth method"))
return errors.New("invalid auth method")
}
if autherErr != nil {
return autherErr
}
err = d.store.Auth.Save(auther)
checkErr(err)
if err != nil {
return err
}
printSettings(file.Server, file.Settings, auther)
return nil
return printSettings(file.Server, file.Settings, auther)
}, pythonConfig{allowNoDB: true}),
}
func getAuther(sample auth.Auther, data interface{}) interface{} {
func getAuther(sample auth.Auther, data interface{}) (interface{}, error) {
authType := reflect.TypeOf(sample)
auther := reflect.New(authType).Interface()
bytes, err := json.Marshal(data)
checkErr(err)
if err != nil {
return nil, err
}
err = json.Unmarshal(bytes, &auther)
checkErr(err)
return auther
if err != nil {
return nil, err
}
return auther, nil
}

View File

@ -25,50 +25,148 @@ override the options.`,
RunE: python(func(cmd *cobra.Command, _ []string, d *pythonData) error {
defaults := settings.UserDefaults{}
flags := cmd.Flags()
getUserDefaults(flags, &defaults, true)
authMethod, auther := getAuthentication(flags)
err := getUserDefaults(flags, &defaults, true)
if err != nil {
return err
}
authMethod, auther, err := getAuthentication(flags)
if err != nil {
return err
}
key := generateKey()
signup, err := mustGetBool(flags, "signup")
if err != nil {
return err
}
createUserDir, err := mustGetBool(flags, "create-user-dir")
if err != nil {
return err
}
minLength, err := mustGetUint(flags, "minimum-password-length")
if err != nil {
return err
}
shell, err := mustGetString(flags, "shell")
if err != nil {
return err
}
brandingName, err := mustGetString(flags, "branding.name")
if err != nil {
return err
}
brandingDisableExternal, err := mustGetBool(flags, "branding.disableExternal")
if err != nil {
return err
}
brandingDisableUsedPercentage, err := mustGetBool(flags, "branding.disableUsedPercentage")
if err != nil {
return err
}
brandingTheme, err := mustGetString(flags, "branding.theme")
if err != nil {
return err
}
brandingFiles, err := mustGetString(flags, "branding.files")
if err != nil {
return err
}
s := &settings.Settings{
Key: generateKey(),
Signup: mustGetBool(flags, "signup"),
CreateUserDir: mustGetBool(flags, "create-user-dir"),
MinimumPasswordLength: mustGetUint(flags, "minimum-password-length"),
Shell: convertCmdStrToCmdArray(mustGetString(flags, "shell")),
Key: key,
Signup: signup,
CreateUserDir: createUserDir,
MinimumPasswordLength: minLength,
Shell: convertCmdStrToCmdArray(shell),
AuthMethod: authMethod,
Defaults: defaults,
Branding: settings.Branding{
Name: mustGetString(flags, "branding.name"),
DisableExternal: mustGetBool(flags, "branding.disableExternal"),
DisableUsedPercentage: mustGetBool(flags, "branding.disableUsedPercentage"),
Theme: mustGetString(flags, "branding.theme"),
Files: mustGetString(flags, "branding.files"),
Name: brandingName,
DisableExternal: brandingDisableExternal,
DisableUsedPercentage: brandingDisableUsedPercentage,
Theme: brandingTheme,
Files: brandingFiles,
},
}
ser := &settings.Server{
Address: mustGetString(flags, "address"),
Socket: mustGetString(flags, "socket"),
Root: mustGetString(flags, "root"),
BaseURL: mustGetString(flags, "baseurl"),
TLSKey: mustGetString(flags, "key"),
TLSCert: mustGetString(flags, "cert"),
Port: mustGetString(flags, "port"),
Log: mustGetString(flags, "log"),
address, err := mustGetString(flags, "address")
if err != nil {
return err
}
err := d.store.Settings.Save(s)
checkErr(err)
socket, err := mustGetString(flags, "socket")
if err != nil {
return err
}
root, err := mustGetString(flags, "root")
if err != nil {
return err
}
baseURL, err := mustGetString(flags, "baseurl")
if err != nil {
return err
}
tlsKey, err := mustGetString(flags, "key")
if err != nil {
return err
}
cert, err := mustGetString(flags, "cert")
if err != nil {
return err
}
port, err := mustGetString(flags, "port")
if err != nil {
return err
}
log, err := mustGetString(flags, "log")
if err != nil {
return err
}
ser := &settings.Server{
Address: address,
Socket: socket,
Root: root,
BaseURL: baseURL,
TLSKey: tlsKey,
TLSCert: cert,
Port: port,
Log: log,
}
err = d.store.Settings.Save(s)
if err != nil {
return err
}
err = d.store.Settings.SaveServer(ser)
checkErr(err)
if err != nil {
return err
}
err = d.store.Auth.Save(auther)
checkErr(err)
if err != nil {
return 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.
`)
printSettings(ser, s, auther)
return nil
return printSettings(ser, s, auther)
}, pythonConfig{noDB: true}),
}

View File

@ -19,71 +19,102 @@ you want to change. Other options will remain unchanged.`,
RunE: python(func(cmd *cobra.Command, _ []string, d *pythonData) error {
flags := cmd.Flags()
set, err := d.store.Settings.Get()
checkErr(err)
if err != nil {
return err
}
ser, err := d.store.Settings.GetServer()
checkErr(err)
if err != nil {
return err
}
hasAuth := false
var visitErr error
flags.Visit(func(flag *pflag.Flag) {
if visitErr != nil {
return
}
var configSetErr error
switch flag.Name {
case "baseurl":
ser.BaseURL = mustGetString(flags, flag.Name)
ser.BaseURL, configSetErr = mustGetString(flags, flag.Name)
case "root":
ser.Root = mustGetString(flags, flag.Name)
ser.Root, configSetErr = mustGetString(flags, flag.Name)
case "socket":
ser.Socket = mustGetString(flags, flag.Name)
ser.Socket, configSetErr = mustGetString(flags, flag.Name)
case "cert":
ser.TLSCert = mustGetString(flags, flag.Name)
ser.TLSCert, configSetErr = mustGetString(flags, flag.Name)
case "key":
ser.TLSKey = mustGetString(flags, flag.Name)
ser.TLSKey, configSetErr = mustGetString(flags, flag.Name)
case "address":
ser.Address = mustGetString(flags, flag.Name)
ser.Address, configSetErr = mustGetString(flags, flag.Name)
case "port":
ser.Port = mustGetString(flags, flag.Name)
ser.Port, configSetErr = mustGetString(flags, flag.Name)
case "log":
ser.Log = mustGetString(flags, flag.Name)
ser.Log, configSetErr = mustGetString(flags, flag.Name)
case "signup":
set.Signup = mustGetBool(flags, flag.Name)
set.Signup, configSetErr = mustGetBool(flags, flag.Name)
case "auth.method":
hasAuth = true
case "shell":
set.Shell = convertCmdStrToCmdArray(mustGetString(flags, flag.Name))
var shell string
shell, configSetErr = mustGetString(flags, flag.Name)
set.Shell = convertCmdStrToCmdArray(shell)
case "create-user-dir":
set.CreateUserDir = mustGetBool(flags, flag.Name)
set.CreateUserDir, configSetErr = mustGetBool(flags, flag.Name)
case "minimum-password-length":
set.MinimumPasswordLength = mustGetUint(flags, flag.Name)
set.MinimumPasswordLength, configSetErr = mustGetUint(flags, flag.Name)
case "branding.name":
set.Branding.Name = mustGetString(flags, flag.Name)
set.Branding.Name, configSetErr = mustGetString(flags, flag.Name)
case "branding.color":
set.Branding.Color = mustGetString(flags, flag.Name)
set.Branding.Color, configSetErr = mustGetString(flags, flag.Name)
case "branding.theme":
set.Branding.Theme = mustGetString(flags, flag.Name)
set.Branding.Theme, configSetErr = mustGetString(flags, flag.Name)
case "branding.disableExternal":
set.Branding.DisableExternal = mustGetBool(flags, flag.Name)
set.Branding.DisableExternal, configSetErr = mustGetBool(flags, flag.Name)
case "branding.disableUsedPercentage":
set.Branding.DisableUsedPercentage = mustGetBool(flags, flag.Name)
set.Branding.DisableUsedPercentage, configSetErr = mustGetBool(flags, flag.Name)
case "branding.files":
set.Branding.Files = mustGetString(flags, flag.Name)
set.Branding.Files, configSetErr = mustGetString(flags, flag.Name)
}
if configSetErr != nil {
visitErr = configSetErr
}
})
getUserDefaults(flags, &set.Defaults, false)
if visitErr != nil {
return visitErr
}
err = getUserDefaults(flags, &set.Defaults, false)
if err != nil {
return err
}
// read the defaults
auther, err := d.store.Auth.Get(set.AuthMethod)
checkErr(err)
if err != nil {
return err
}
// check if there are new flags for existing auth method
set.AuthMethod, auther = getAuthentication(flags, hasAuth, set, auther)
set.AuthMethod, auther, err = getAuthentication(flags, hasAuth, set, auther)
if err != nil {
return err
}
err = d.store.Auth.Save(auther)
checkErr(err)
if err != nil {
return err
}
err = d.store.Settings.Save(set)
checkErr(err)
if err != nil {
return err
}
err = d.store.Settings.SaveServer(ser)
checkErr(err)
printSettings(ser, set, auther)
return nil
if err != nil {
return err
}
return printSettings(ser, set, auther)
}, pythonConfig{}),
}

View File

@ -39,12 +39,18 @@ var docsCmd = &cobra.Command{
Use: "docs",
Hidden: true,
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, _ []string) {
dir := mustGetString(cmd.Flags(), "path")
generateDocs(rootCmd, dir)
RunE: func(cmd *cobra.Command, _ []string) error {
dir, err := mustGetString(cmd.Flags(), "path")
if err != nil {
return err
}
err = generateDocs(rootCmd, dir)
if err != nil {
return err
}
names := []string{}
err := filepath.Walk(dir, func(_ string, info os.FileInfo, err error) error {
walkErr := filepath.Walk(dir, func(_ string, info os.FileInfo, err error) error {
if err != nil || info.IsDir() {
return err
}
@ -57,29 +63,37 @@ var docsCmd = &cobra.Command{
return nil
})
checkErr(err)
if walkErr != nil {
return walkErr
}
printToc(names)
return nil
},
}
func generateDocs(cmd *cobra.Command, dir string) {
func generateDocs(cmd *cobra.Command, dir string) error {
for _, c := range cmd.Commands() {
if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() {
continue
}
generateDocs(c, dir)
err := generateDocs(c, dir)
if err != nil {
return err
}
}
basename := strings.Replace(cmd.CommandPath(), " ", "-", -1) + ".md"
filename := filepath.Join(dir, basename)
f, err := os.Create(filename)
checkErr(err)
if err != nil {
return err
}
defer f.Close()
generateMarkdown(cmd, f)
return generateMarkdown(cmd, f)
}
func generateMarkdown(cmd *cobra.Command, w io.Writer) {
func generateMarkdown(cmd *cobra.Command, w io.Writer) error {
cmd.InitDefaultHelpCmd()
cmd.InitDefaultHelpFlag()
@ -108,7 +122,7 @@ func generateMarkdown(cmd *cobra.Command, w io.Writer) {
printOptions(buf, cmd)
_, err := buf.WriteTo(w)
checkErr(err)
return err
}
func generateFlagsTable(fs *pflag.FlagSet, buf io.StringWriter) {

View File

@ -17,9 +17,12 @@ var hashCmd = &cobra.Command{
Short: "Hashes a password",
Long: `Hashes a password using bcrypt algorithm.`,
Args: cobra.ExactArgs(1),
Run: func(_ *cobra.Command, args []string) {
RunE: func(_ *cobra.Command, args []string) error {
pwd, err := users.HashPwd(args[0])
checkErr(err)
if err != nil {
return err
}
fmt.Println(pwd)
return nil
},
}

View File

@ -4,6 +4,7 @@ import (
"context"
"crypto/tls"
"errors"
"fmt"
"io"
"io/fs"
"log"
@ -123,18 +124,22 @@ user created with the credentials from options "username" and "password".`,
// build img service
workersCount, err := cmd.Flags().GetInt("img-processors")
checkErr(err)
if err != nil {
return err
}
if workersCount < 1 {
log.Fatal("Image resize workers count could not be < 1")
return errors.New("image resize workers count could not be < 1")
}
imgSvc := img.New(workersCount)
var fileCache diskcache.Interface = diskcache.NewNoOp()
cacheDir, err := cmd.Flags().GetString("cache-dir")
checkErr(err)
if err != nil {
return err
}
if cacheDir != "" {
if err := os.MkdirAll(cacheDir, 0700); err != nil { //nolint:govet
log.Fatalf("can't make directory %s: %s", cacheDir, err)
return fmt.Errorf("can't make directory %s: %w", cacheDir, err)
}
fileCache = diskcache.New(afero.NewOsFs(), cacheDir)
}
@ -143,7 +148,9 @@ user created with the credentials from options "username" and "password".`,
setupLog(server.Log)
root, err := filepath.Abs(server.Root)
checkErr(err)
if err != nil {
return err
}
server.Root = root
adr := server.Address + ":" + server.Port
@ -153,22 +160,34 @@ user created with the credentials from options "username" and "password".`,
switch {
case server.Socket != "":
listener, err = net.Listen("unix", server.Socket)
checkErr(err)
if err != nil {
return err
}
socketPerm, err := cmd.Flags().GetUint32("socket-perm") //nolint:govet
checkErr(err)
if err != nil {
return err
}
err = os.Chmod(server.Socket, os.FileMode(socketPerm))
checkErr(err)
if err != nil {
return err
}
case server.TLSKey != "" && server.TLSCert != "":
cer, err := tls.LoadX509KeyPair(server.TLSCert, server.TLSKey) //nolint:govet
checkErr(err)
if err != nil {
return err
}
listener, err = tls.Listen("tcp", adr, &tls.Config{
MinVersion: tls.VersionTLS12,
Certificates: []tls.Certificate{cer}},
)
checkErr(err)
if err != nil {
return err
}
default:
listener, err = net.Listen("tcp", adr)
checkErr(err)
if err != nil {
return err
}
}
assetsFs, err := fs.Sub(frontend.Assets(), "dist")
@ -177,7 +196,9 @@ user created with the credentials from options "username" and "password".`,
}
handler, err := fbhttp.NewHandler(imgSvc, fileCache, d.store, server, assetsFs)
checkErr(err)
if err != nil {
return err
}
defer listener.Close()

View File

@ -42,26 +42,33 @@ including 'index_end'.`,
},
RunE: python(func(cmd *cobra.Command, args []string, d *pythonData) error {
i, err := strconv.Atoi(args[0])
checkErr(err)
if err != nil {
return err
}
f := i
if len(args) == 2 {
f, err = strconv.Atoi(args[1])
checkErr(err)
if err != nil {
return err
}
}
user := func(u *users.User) {
u.Rules = append(u.Rules[:i], u.Rules[f+1:]...)
err := d.store.Users.Save(u)
checkErr(err)
if err != nil {
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)
if err != nil {
checkErr(err)
}
}
runRules(d.store, cmd, user, global)
return nil
return runRules(d.store, cmd, user, global)
}, pythonConfig{}),
}

View File

@ -29,41 +29,55 @@ rules.`,
Args: cobra.NoArgs,
}
func runRules(st *storage.Storage, cmd *cobra.Command, usersFn func(*users.User), globalFn func(*settings.Settings)) {
id := getUserIdentifier(cmd.Flags())
func runRules(st *storage.Storage, cmd *cobra.Command, usersFn func(*users.User), globalFn func(*settings.Settings)) error {
id, err := getUserIdentifier(cmd.Flags())
if err != nil {
return err
}
if id != nil {
user, err := st.Users.Get("", id)
checkErr(err)
user, usrErr := st.Users.Get("", id)
if usrErr != nil {
return usrErr
}
if usersFn != nil {
usersFn(user)
}
printRules(user.Rules, id)
return
return nil
}
s, err := st.Settings.Get()
checkErr(err)
if err != nil {
return err
}
if globalFn != nil {
globalFn(s)
}
printRules(s.Rules, id)
return nil
}
func getUserIdentifier(flags *pflag.FlagSet) interface{} {
id := mustGetUint(flags, "id")
username := mustGetString(flags, "username")
if id != 0 {
return id
} else if username != "" {
return username
func getUserIdentifier(flags *pflag.FlagSet) (interface{}, error) {
id, err := mustGetUint(flags, "id")
if err != nil {
return nil, err
}
username, err := mustGetString(flags, "username")
if err != nil {
return nil, err
}
return nil
if id != 0 {
return id, nil
} else if username != "" {
return username, nil
}
return nil, nil
}
func printRules(rulez []rules.Rule, id interface{}) {

View File

@ -22,8 +22,14 @@ var rulesAddCmd = &cobra.Command{
Long: `Add a global rule or user rule.`,
Args: cobra.ExactArgs(1),
RunE: python(func(cmd *cobra.Command, args []string, d *pythonData) error {
allow := mustGetBool(cmd.Flags(), "allow")
regex := mustGetBool(cmd.Flags(), "regex")
allow, err := mustGetBool(cmd.Flags(), "allow")
if err != nil {
return err
}
regex, err := mustGetBool(cmd.Flags(), "regex")
if err != nil {
return err
}
exp := args[0]
if regex {
@ -44,16 +50,19 @@ var rulesAddCmd = &cobra.Command{
user := func(u *users.User) {
u.Rules = append(u.Rules, rule)
err := d.store.Users.Save(u)
checkErr(err)
if err != nil {
checkErr(err)
}
}
global := func(s *settings.Settings) {
s.Rules = append(s.Rules, rule)
err := d.store.Settings.Save(s)
checkErr(err)
if err != nil {
checkErr(err)
}
}
runRules(d.store, cmd, user, global)
return nil
return runRules(d.store, cmd, user, global)
}, pythonConfig{}),
}

View File

@ -14,7 +14,6 @@ var rulesLsCommand = &cobra.Command{
Long: `List global rules or user specific rules.`,
Args: cobra.NoArgs,
RunE: python(func(cmd *cobra.Command, _ []string, d *pythonData) error {
runRules(d.store, cmd, nil, nil)
return nil
return runRules(d.store, cmd, nil, nil)
}, pythonConfig{}),
}

View File

@ -21,11 +21,20 @@ var upgradeCmd = &cobra.Command{
import share links because they are incompatible with
this version.`,
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, _ []string) {
RunE: func(cmd *cobra.Command, _ []string) error {
flags := cmd.Flags()
oldDB := mustGetString(flags, "old.database")
oldConf := mustGetString(flags, "old.config")
err := importer.Import(oldDB, oldConf, getStringParam(flags, "database"))
checkErr(err)
oldDB, err := mustGetString(flags, "old.database")
if err != nil {
return err
}
oldConf, err := mustGetString(flags, "old.config")
if err != nil {
return err
}
db, err := mustGetString(flags, "database")
if err != nil {
return err
}
return importer.Import(oldDB, oldConf, db)
},
}

View File

@ -79,50 +79,60 @@ func addUserFlags(flags *pflag.FlagSet) {
flags.Bool("singleClick", false, "use single clicks only")
}
func getViewMode(flags *pflag.FlagSet) users.ViewMode {
viewMode := users.ViewMode(mustGetString(flags, "viewMode"))
if viewMode != users.ListViewMode && viewMode != users.MosaicViewMode {
checkErr(errors.New("view mode must be \"" + string(users.ListViewMode) + "\" or \"" + string(users.MosaicViewMode) + "\""))
func getViewMode(flags *pflag.FlagSet) (users.ViewMode, error) {
viewModeStr, err := mustGetString(flags, "viewMode")
if err != nil {
return "", err
}
return viewMode
viewMode := users.ViewMode(viewModeStr)
if viewMode != users.ListViewMode && viewMode != users.MosaicViewMode {
return "", errors.New("view mode must be \"" + string(users.ListViewMode) + "\" or \"" + string(users.MosaicViewMode) + "\"")
}
return viewMode, nil
}
//nolint:gocyclo
func getUserDefaults(flags *pflag.FlagSet, defaults *settings.UserDefaults, all bool) {
func getUserDefaults(flags *pflag.FlagSet, defaults *settings.UserDefaults, all bool) error {
var visitErr error
visit := func(flag *pflag.Flag) {
if visitErr != nil {
return
}
var err error
switch flag.Name {
case "scope":
defaults.Scope = mustGetString(flags, flag.Name)
defaults.Scope, err = mustGetString(flags, flag.Name)
case "locale":
defaults.Locale = mustGetString(flags, flag.Name)
defaults.Locale, err = mustGetString(flags, flag.Name)
case "viewMode":
defaults.ViewMode = getViewMode(flags)
defaults.ViewMode, err = getViewMode(flags)
case "singleClick":
defaults.SingleClick = mustGetBool(flags, flag.Name)
defaults.SingleClick, err = mustGetBool(flags, flag.Name)
case "perm.admin":
defaults.Perm.Admin = mustGetBool(flags, flag.Name)
defaults.Perm.Admin, err = mustGetBool(flags, flag.Name)
case "perm.execute":
defaults.Perm.Execute = mustGetBool(flags, flag.Name)
defaults.Perm.Execute, err = mustGetBool(flags, flag.Name)
case "perm.create":
defaults.Perm.Create = mustGetBool(flags, flag.Name)
defaults.Perm.Create, err = mustGetBool(flags, flag.Name)
case "perm.rename":
defaults.Perm.Rename = mustGetBool(flags, flag.Name)
defaults.Perm.Rename, err = mustGetBool(flags, flag.Name)
case "perm.modify":
defaults.Perm.Modify = mustGetBool(flags, flag.Name)
defaults.Perm.Modify, err = mustGetBool(flags, flag.Name)
case "perm.delete":
defaults.Perm.Delete = mustGetBool(flags, flag.Name)
defaults.Perm.Delete, err = mustGetBool(flags, flag.Name)
case "perm.share":
defaults.Perm.Share = mustGetBool(flags, flag.Name)
defaults.Perm.Share, err = mustGetBool(flags, flag.Name)
case "perm.download":
defaults.Perm.Download = mustGetBool(flags, flag.Name)
defaults.Perm.Download, err = mustGetBool(flags, flag.Name)
case "commands":
commands, err := flags.GetStringSlice(flag.Name)
checkErr(err)
defaults.Commands = commands
defaults.Commands, err = flags.GetStringSlice(flag.Name)
case "sorting.by":
defaults.Sorting.By = mustGetString(flags, flag.Name)
defaults.Sorting.By, err = mustGetString(flags, flag.Name)
case "sorting.asc":
defaults.Sorting.Asc = mustGetBool(flags, flag.Name)
defaults.Sorting.Asc, err = mustGetBool(flags, flag.Name)
}
if err != nil {
visitErr = err
}
}
@ -131,4 +141,5 @@ func getUserDefaults(flags *pflag.FlagSet, defaults *settings.UserDefaults, all
} else {
flags.Visit(visit)
}
return visitErr
}

View File

@ -18,34 +18,54 @@ var usersAddCmd = &cobra.Command{
Args: cobra.ExactArgs(2),
RunE: python(func(cmd *cobra.Command, args []string, d *pythonData) error {
s, err := d.store.Settings.Get()
checkErr(err)
getUserDefaults(cmd.Flags(), &s.Defaults, false)
if err != nil {
return err
}
err = getUserDefaults(cmd.Flags(), &s.Defaults, false)
if err != nil {
return err
}
password, err := users.ValidateAndHashPwd(args[1], s.MinimumPasswordLength)
checkErr(err)
if err != nil {
return err
}
lockPassword, err := mustGetBool(cmd.Flags(), "lockPassword")
if err != nil {
return err
}
user := &users.User{
Username: args[0],
Password: password,
LockPassword: mustGetBool(cmd.Flags(), "lockPassword"),
LockPassword: lockPassword,
}
s.Defaults.Apply(user)
servSettings, err := d.store.Settings.GetServer()
checkErr(err)
if err != nil {
return 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)
if err != nil {
return err
}
userHome, err := s2.MakeUserDir(user.Username, user.Scope, servSettings.Root)
checkErr(err)
if err != nil {
return err
}
user.Scope = userHome
err = d.store.Users.Save(user)
checkErr(err)
if err != nil {
return err
}
printUsers([]*users.User{user})
return nil
}, pythonConfig{}),

View File

@ -16,10 +16,14 @@ path to the file where you want to write the users.`,
Args: jsonYamlArg,
RunE: python(func(_ *cobra.Command, args []string, d *pythonData) error {
list, err := d.store.Users.Gets("")
checkErr(err)
if err != nil {
return err
}
err = marshal(args[0], list)
checkErr(err)
if err != nil {
return err
}
return nil
}, pythonConfig{}),
}

View File

@ -46,7 +46,9 @@ var findUsers = python(func(_ *cobra.Command, args []string, d *pythonData) erro
list, err = d.store.Users.Gets("")
}
checkErr(err)
if err != nil {
return err
}
printUsers(list)
return nil
}, pythonConfig{})

View File

@ -27,32 +27,52 @@ list or set it to 0.`,
Args: jsonYamlArg,
RunE: python(func(cmd *cobra.Command, args []string, d *pythonData) error {
fd, err := os.Open(args[0])
checkErr(err)
if err != nil {
return err
}
defer fd.Close()
list := []*users.User{}
err = unmarshal(args[0], &list)
checkErr(err)
if err != nil {
return 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)
if err != nil {
return err
}
}
overwrite := mustGetBool(cmd.Flags(), "overwrite")
replace, err := mustGetBool(cmd.Flags(), "replace")
if err != nil {
return err
}
if replace {
oldUsers, userImportErr := d.store.Users.Gets("")
if userImportErr != nil {
return userImportErr
}
err = marshal("users.backup.json", list)
if err != nil {
return err
}
for _, user := range oldUsers {
err = d.store.Users.Delete(user.ID)
if err != nil {
return err
}
}
}
overwrite, err := mustGetBool(cmd.Flags(), "overwrite")
if err != nil {
return err
}
for _, user := range list {
onDB, err := d.store.Users.Get("", user.ID)
@ -60,7 +80,7 @@ list or set it to 0.`,
// User exists in DB.
if err == nil {
if !overwrite {
checkErr(errors.New("user " + strconv.Itoa(int(user.ID)) + " is already registered"))
return errors.New("user " + strconv.Itoa(int(user.ID)) + " is already registered")
}
// If the usernames mismatch, check if there is another one in the DB
@ -68,7 +88,7 @@ list or set it to 0.`,
// 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))
return usernameConflictError(user.Username, conflictuous.ID, user.ID)
}
}
} else {
@ -78,7 +98,9 @@ list or set it to 0.`,
}
err = d.store.Users.Save(user)
checkErr(err)
if err != nil {
return err
}
}
return nil
}, pythonConfig{}),

View File

@ -25,7 +25,9 @@ var usersRmCmd = &cobra.Command{
err = d.store.Users.Delete(id)
}
checkErr(err)
if err != nil {
return err
}
fmt.Println("user deleted successfully")
return nil
}, pythonConfig{}),

View File

@ -24,11 +24,19 @@ options you want to change.`,
RunE: python(func(cmd *cobra.Command, args []string, d *pythonData) error {
username, id := parseUsernameOrID(args[0])
flags := cmd.Flags()
password := mustGetString(flags, "password")
newUsername := mustGetString(flags, "username")
password, err := mustGetString(flags, "password")
if err != nil {
return err
}
newUsername, err := mustGetString(flags, "username")
if err != nil {
return err
}
s, err := d.store.Settings.Get()
checkErr(err)
if err != nil {
return err
}
var (
user *users.User
@ -40,7 +48,9 @@ options you want to change.`,
user, err = d.store.Users.Get("", username)
}
checkErr(err)
if err != nil {
return err
}
defaults := settings.UserDefaults{
Scope: user.Scope,
@ -51,7 +61,10 @@ options you want to change.`,
Sorting: user.Sorting,
Commands: user.Commands,
}
getUserDefaults(flags, &defaults, false)
err = getUserDefaults(flags, &defaults, false)
if err != nil {
return err
}
user.Scope = defaults.Scope
user.Locale = defaults.Locale
user.ViewMode = defaults.ViewMode
@ -59,7 +72,10 @@ options you want to change.`,
user.Perm = defaults.Perm
user.Commands = defaults.Commands
user.Sorting = defaults.Sorting
user.LockPassword = mustGetBool(flags, "lockPassword")
user.LockPassword, err = mustGetBool(flags, "lockPassword")
if err != nil {
return err
}
if newUsername != "" {
user.Username = newUsername
@ -67,11 +83,15 @@ options you want to change.`,
if password != "" {
user.Password, err = users.ValidateAndHashPwd(password, s.MinimumPasswordLength)
checkErr(err)
if err != nil {
return err
}
}
err = d.store.Users.Update(user)
checkErr(err)
if err != nil {
return err
}
printUsers([]*users.User{user})
return nil
}, pythonConfig{}),

View File

@ -26,22 +26,26 @@ func checkErr(err error) {
}
}
func mustGetString(flags *pflag.FlagSet, flag string) string {
func returnErr(err error) error {
if err != nil {
return err
}
return nil
}
func mustGetString(flags *pflag.FlagSet, flag string) (string, error) {
s, err := flags.GetString(flag)
checkErr(err)
return s
return s, returnErr(err)
}
func mustGetBool(flags *pflag.FlagSet, flag string) bool {
func mustGetBool(flags *pflag.FlagSet, flag string) (bool, error) {
b, err := flags.GetBool(flag)
checkErr(err)
return b
return b, returnErr(err)
}
func mustGetUint(flags *pflag.FlagSet, flag string) uint {
func mustGetUint(flags *pflag.FlagSet, flag string) (uint, error) {
b, err := flags.GetUint(flag)
checkErr(err)
return b
return b, returnErr(err)
}
func generateKey() []byte {
@ -108,17 +112,23 @@ func python(fn pythonFunc, cfg pythonConfig) cobraFunc {
log.Println("Using database: " + absPath)
data.hadDB = exists
db, err := storm.Open(path, storm.BoltOptions(files.PermFile, nil))
checkErr(err)
if err != nil {
return err
}
defer db.Close()
data.store, err = bolt.NewStorage(db)
checkErr(err)
if err != nil {
return err
}
return fn(cmd, args, data)
}
}
func marshal(filename string, data interface{}) error {
fd, err := os.Create(filename)
checkErr(err)
if err != nil {
return err
}
defer fd.Close()
switch ext := filepath.Ext(filename); ext {
@ -136,7 +146,9 @@ func marshal(filename string, data interface{}) error {
func unmarshal(filename string, data interface{}) error {
fd, err := os.Open(filename)
checkErr(err)
if err != nil {
return err
}
defer fd.Close()
switch ext := filepath.Ext(filename); ext {