mirror of
https://github.com/filebrowser/filebrowser.git
synced 2024-06-07 23:00:43 +00:00
feat: per-user auto directory creation (#676)
This commit is contained in:
commit
f72addc780
@ -89,6 +89,7 @@ func printSettings(ser *settings.Server, set *settings.Settings, auther auth.Aut
|
|||||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
||||||
|
|
||||||
fmt.Fprintf(w, "Sign up:\t%t\n", set.Signup)
|
fmt.Fprintf(w, "Sign up:\t%t\n", set.Signup)
|
||||||
|
fmt.Fprintf(w, "Create User Dir:\t%t\n", set.CreateUserDir)
|
||||||
fmt.Fprintf(w, "Auth method:\t%s\n", set.AuthMethod)
|
fmt.Fprintf(w, "Auth method:\t%s\n", set.AuthMethod)
|
||||||
fmt.Fprintf(w, "Shell:\t%s\t\n", strings.Join(set.Shell, " "))
|
fmt.Fprintf(w, "Shell:\t%s\t\n", strings.Join(set.Shell, " "))
|
||||||
fmt.Fprintln(w, "\nBranding:")
|
fmt.Fprintln(w, "\nBranding:")
|
||||||
|
@ -215,6 +215,7 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) {
|
|||||||
set := &settings.Settings{
|
set := &settings.Settings{
|
||||||
Key: generateKey(),
|
Key: generateKey(),
|
||||||
Signup: false,
|
Signup: false,
|
||||||
|
CreateUserDir: false,
|
||||||
Defaults: settings.UserDefaults{
|
Defaults: settings.UserDefaults{
|
||||||
Scope: ".",
|
Scope: ".",
|
||||||
Locale: "en",
|
Locale: "en",
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/filebrowser/filebrowser/v2/settings"
|
||||||
"github.com/filebrowser/filebrowser/v2/users"
|
"github.com/filebrowser/filebrowser/v2/users"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
@ -30,6 +31,19 @@ var usersAddCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
s.Defaults.Apply(user)
|
s.Defaults.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 := settings.CreateUserDir(user.Username, user.Scope, servSettings.Root, s2)
|
||||||
|
checkErr(err)
|
||||||
|
user.Scope = userHome
|
||||||
|
|
||||||
err = d.store.Users.Save(user)
|
err = d.store.Users.Save(user)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
printUsers([]*users.User{user})
|
printUsers([]*users.User{user})
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
type settingsData struct {
|
type settingsData struct {
|
||||||
Signup bool `json:"signup"`
|
Signup bool `json:"signup"`
|
||||||
|
CreateUserDir bool `json:"createUserDir"`
|
||||||
Defaults settings.UserDefaults `json:"defaults"`
|
Defaults settings.UserDefaults `json:"defaults"`
|
||||||
Rules []rules.Rule `json:"rules"`
|
Rules []rules.Rule `json:"rules"`
|
||||||
Branding settings.Branding `json:"branding"`
|
Branding settings.Branding `json:"branding"`
|
||||||
@ -20,6 +21,7 @@ type settingsData struct {
|
|||||||
var settingsGetHandler = withAdmin(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
var settingsGetHandler = withAdmin(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
||||||
data := &settingsData{
|
data := &settingsData{
|
||||||
Signup: d.settings.Signup,
|
Signup: d.settings.Signup,
|
||||||
|
CreateUserDir: d.settings.CreateUserDir,
|
||||||
Defaults: d.settings.Defaults,
|
Defaults: d.settings.Defaults,
|
||||||
Rules: d.settings.Rules,
|
Rules: d.settings.Rules,
|
||||||
Branding: d.settings.Branding,
|
Branding: d.settings.Branding,
|
||||||
@ -38,6 +40,7 @@ var settingsPutHandler = withAdmin(func(w http.ResponseWriter, r *http.Request,
|
|||||||
}
|
}
|
||||||
|
|
||||||
d.settings.Signup = req.Signup
|
d.settings.Signup = req.Signup
|
||||||
|
d.settings.CreateUserDir = req.CreateUserDir
|
||||||
d.settings.Defaults = req.Defaults
|
d.settings.Defaults = req.Defaults
|
||||||
d.settings.Rules = req.Rules
|
d.settings.Rules = req.Rules
|
||||||
d.settings.Branding = req.Branding
|
d.settings.Branding = req.Branding
|
||||||
|
@ -2,6 +2,8 @@ package http
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"github.com/filebrowser/filebrowser/v2/settings"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -119,6 +121,14 @@ var userPostHandler = withAdmin(func(w http.ResponseWriter, r *http.Request, d *
|
|||||||
return http.StatusInternalServerError, err
|
return http.StatusInternalServerError, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userHome,err := settings.CreateUserDir(req.Data.Username, req.Data.Scope, d.server.Root, d.settings)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("create user: failed to mkdir user home dir: [%s]", userHome)
|
||||||
|
return http.StatusInternalServerError, err
|
||||||
|
}
|
||||||
|
req.Data.Scope = userHome
|
||||||
|
log.Printf("user: %s, home dir: [%s].", req.Data.Username, userHome)
|
||||||
|
|
||||||
err = d.store.Users.Save(req.Data)
|
err = d.store.Users.Save(req.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return http.StatusInternalServerError, err
|
return http.StatusInternalServerError, err
|
||||||
|
77
settings/dir.go
Normal file
77
settings/dir.go
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
package settings
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"github.com/spf13/afero"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
invalidFilenameChars = regexp.MustCompile(`[^0-9A-Za-z@_\-.]`)
|
||||||
|
|
||||||
|
dashes = regexp.MustCompile(`[\-]+`)
|
||||||
|
)
|
||||||
|
|
||||||
|
func CreateUserDir(username, userScope, serverRoot string, settings *Settings) (string, error) {
|
||||||
|
var err error
|
||||||
|
userScope = strings.TrimSpace(userScope)
|
||||||
|
if userScope == "" || userScope == "./" {
|
||||||
|
userScope = "."
|
||||||
|
}
|
||||||
|
|
||||||
|
if !settings.CreateUserDir {
|
||||||
|
return userScope, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fs := afero.NewBasePathFs(afero.NewOsFs(), serverRoot)
|
||||||
|
|
||||||
|
//use the default auto create logic only if specific scope is not the default scope
|
||||||
|
if userScope != settings.Defaults.Scope {
|
||||||
|
//try create the dir, for example: settings.Defaults.Scope == "." and userScope == "./foo"
|
||||||
|
if userScope != "." {
|
||||||
|
err = fs.MkdirAll(userScope, os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("create user: failed to mkdir user home dir: [%s]", userScope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return userScope, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//clean username first
|
||||||
|
username = cleanUsername(username)
|
||||||
|
if username == "" || username == "-" || username == "." {
|
||||||
|
log.Printf("create user: invalid user for home dir creation: [%s]", username)
|
||||||
|
return "", errors.New("invalid user for home dir creation")
|
||||||
|
}
|
||||||
|
|
||||||
|
//create default user dir
|
||||||
|
userHomeBase := settings.Defaults.Scope + string(os.PathSeparator) + "users"
|
||||||
|
userHome := userHomeBase + string(os.PathSeparator) + username
|
||||||
|
err = fs.MkdirAll(userHome, os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("create user: failed to mkdir user home dir: [%s]", userHome)
|
||||||
|
} else {
|
||||||
|
log.Printf("create user: mkdir user home dir: [%s] successfully.", userHome)
|
||||||
|
}
|
||||||
|
return userHome,err
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func cleanUsername(s string) string {
|
||||||
|
|
||||||
|
// Remove any trailing space to avoid ending on -
|
||||||
|
s = strings.Trim(s, " ")
|
||||||
|
|
||||||
|
s = strings.Replace(s, "..", "", -1)
|
||||||
|
|
||||||
|
// Replace all characters which not in the list `0-9A-Za-z@_\-.` with a dash
|
||||||
|
s = invalidFilenameChars.ReplaceAllString(s, "-")
|
||||||
|
|
||||||
|
// Remove any multiple dashes caused by replacements above
|
||||||
|
s = dashes.ReplaceAllString(s, "-")
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
@ -14,6 +14,7 @@ type AuthMethod string
|
|||||||
type Settings struct {
|
type Settings struct {
|
||||||
Key []byte `json:"key"`
|
Key []byte `json:"key"`
|
||||||
Signup bool `json:"signup"`
|
Signup bool `json:"signup"`
|
||||||
|
CreateUserDir bool `json:"createUserDir"`
|
||||||
Defaults UserDefaults `json:"defaults"`
|
Defaults UserDefaults `json:"defaults"`
|
||||||
AuthMethod AuthMethod `json:"authMethod"`
|
AuthMethod AuthMethod `json:"authMethod"`
|
||||||
Branding Branding `json:"branding"`
|
Branding Branding `json:"branding"`
|
||||||
|
Loading…
Reference in New Issue
Block a user