feat: add global scope
License: MIT Signed-off-by: Henrique Dias <hacdias@gmail.com>
This commit is contained in:
parent
c830b80269
commit
2156b3e68b
@ -3,13 +3,12 @@ package auth
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/filebrowser/filebrowser/v2/settings"
|
||||||
"github.com/filebrowser/filebrowser/v2/users"
|
"github.com/filebrowser/filebrowser/v2/users"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Auther is the authentication interface.
|
// Auther is the authentication interface.
|
||||||
type Auther interface {
|
type Auther interface {
|
||||||
// Auth is called to authenticate a request.
|
// Auth is called to authenticate a request.
|
||||||
Auth(*http.Request) (*users.User, error)
|
Auth(*http.Request, *users.Storage, *settings.Settings) (*users.User, error)
|
||||||
// SetStorage attaches the Storage instance.
|
|
||||||
SetStorage(*users.Storage)
|
|
||||||
}
|
}
|
||||||
|
|||||||
10
auth/json.go
10
auth/json.go
@ -23,11 +23,10 @@ type jsonCred struct {
|
|||||||
// JSONAuth is a json implementaion of an Auther.
|
// JSONAuth is a json implementaion of an Auther.
|
||||||
type JSONAuth struct {
|
type JSONAuth struct {
|
||||||
ReCaptcha *ReCaptcha
|
ReCaptcha *ReCaptcha
|
||||||
storage *users.Storage
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auth authenticates the user via a json in content body.
|
// Auth authenticates the user via a json in content body.
|
||||||
func (a *JSONAuth) Auth(r *http.Request) (*users.User, error) {
|
func (a *JSONAuth) Auth(r *http.Request, sto *users.Storage, set *settings.Settings) (*users.User, error) {
|
||||||
var cred jsonCred
|
var cred jsonCred
|
||||||
|
|
||||||
if r.Body == nil {
|
if r.Body == nil {
|
||||||
@ -52,7 +51,7 @@ func (a *JSONAuth) Auth(r *http.Request) (*users.User, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u, err := a.storage.Get(cred.Username)
|
u, err := sto.Get(set.Scope, cred.Username)
|
||||||
if err != nil || !users.CheckPwd(cred.Password, u.Password) {
|
if err != nil || !users.CheckPwd(cred.Password, u.Password) {
|
||||||
return nil, os.ErrPermission
|
return nil, os.ErrPermission
|
||||||
}
|
}
|
||||||
@ -60,11 +59,6 @@ func (a *JSONAuth) Auth(r *http.Request) (*users.User, error) {
|
|||||||
return u, nil
|
return u, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetStorage attaches the storage to the auther.
|
|
||||||
func (a *JSONAuth) SetStorage(s *users.Storage) {
|
|
||||||
a.storage = s
|
|
||||||
}
|
|
||||||
|
|
||||||
const reCaptchaAPI = "/recaptcha/api/siteverify"
|
const reCaptchaAPI = "/recaptcha/api/siteverify"
|
||||||
|
|
||||||
// ReCaptcha identifies a recaptcha conenction.
|
// ReCaptcha identifies a recaptcha conenction.
|
||||||
|
|||||||
10
auth/none.go
10
auth/none.go
@ -12,15 +12,9 @@ const MethodNoAuth settings.AuthMethod = "noauth"
|
|||||||
|
|
||||||
// NoAuth is no auth implementation of auther.
|
// NoAuth is no auth implementation of auther.
|
||||||
type NoAuth struct {
|
type NoAuth struct {
|
||||||
storage *users.Storage
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auth uses authenticates user 1.
|
// Auth uses authenticates user 1.
|
||||||
func (a *NoAuth) Auth(r *http.Request) (*users.User, error) {
|
func (a *NoAuth) Auth(r *http.Request, sto *users.Storage, set *settings.Settings) (*users.User, error) {
|
||||||
return a.storage.Get(1)
|
return sto.Get(set.Scope, 1)
|
||||||
}
|
|
||||||
|
|
||||||
// SetStorage attaches the storage to the auther.
|
|
||||||
func (a *NoAuth) SetStorage(s *users.Storage) {
|
|
||||||
a.storage = s
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,17 +19,12 @@ type ProxyAuth struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Auth authenticates the user via an HTTP header.
|
// Auth authenticates the user via an HTTP header.
|
||||||
func (a *ProxyAuth) Auth(r *http.Request) (*users.User, error) {
|
func (a *ProxyAuth) Auth(r *http.Request, sto *users.Storage, set *settings.Settings) (*users.User, error) {
|
||||||
username := r.Header.Get(a.Header)
|
username := r.Header.Get(a.Header)
|
||||||
user, err := a.storage.Get(username)
|
user, err := sto.Get(set.Scope, username)
|
||||||
if err == errors.ErrNotExist {
|
if err == errors.ErrNotExist {
|
||||||
return nil, os.ErrPermission
|
return nil, os.ErrPermission
|
||||||
}
|
}
|
||||||
|
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetStorage attaches the storage to the auther.
|
|
||||||
func (a *ProxyAuth) SetStorage(s *users.Storage) {
|
|
||||||
a.storage = s
|
|
||||||
}
|
|
||||||
|
|||||||
@ -22,15 +22,9 @@ func NewStorage(back StorageBackend, users *users.Storage) *Storage {
|
|||||||
return &Storage{back: back, users: users}
|
return &Storage{back: back, users: users}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get wraps a StorageBackend.Get and calls SetStorage on the auther.
|
// Get wraps a StorageBackend.Get.
|
||||||
func (s *Storage) Get(t settings.AuthMethod) (Auther, error) {
|
func (s *Storage) Get(t settings.AuthMethod) (Auther, error) {
|
||||||
auther, err := s.back.Get(t)
|
return s.back.Get(t)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
auther.SetStorage(s.users)
|
|
||||||
return auther, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save wraps a StorageBackend.Save.
|
// Save wraps a StorageBackend.Save.
|
||||||
|
|||||||
@ -30,10 +30,11 @@ var configCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func addConfigFlags(cmd *cobra.Command) {
|
func addConfigFlags(cmd *cobra.Command) {
|
||||||
addUserFlags(cmd)
|
addUserFlags(cmd, "defaults.")
|
||||||
cmd.Flags().StringP("baseURL", "b", "/", "base url of this installation")
|
cmd.Flags().StringP("baseURL", "b", "/", "base url of this installation")
|
||||||
cmd.Flags().BoolP("signup", "s", false, "allow users to signup")
|
cmd.Flags().BoolP("signup", "s", false, "allow users to signup")
|
||||||
cmd.Flags().String("shell", "", "shell command to which other commands should be appended")
|
cmd.Flags().String("shell", "", "shell command to which other commands should be appended")
|
||||||
|
cmd.Flags().String("scope", "", "scope to prepend to a user's scope when it is relative (default is current working directory)")
|
||||||
|
|
||||||
cmd.Flags().StringP("address", "a", "127.0.0.1", "default address to listen to")
|
cmd.Flags().StringP("address", "a", "127.0.0.1", "default address to listen to")
|
||||||
cmd.Flags().StringP("log", "l", "stderr", "log output")
|
cmd.Flags().StringP("log", "l", "stderr", "log output")
|
||||||
@ -102,6 +103,7 @@ func printSettings(s *settings.Settings, auther auth.Auther) {
|
|||||||
fmt.Fprintf(w, "Auth method:\t%s\n", s.AuthMethod)
|
fmt.Fprintf(w, "Auth method:\t%s\n", s.AuthMethod)
|
||||||
fmt.Fprintf(w, "Shell:\t%s\t\n", strings.Join(s.Shell, " "))
|
fmt.Fprintf(w, "Shell:\t%s\t\n", strings.Join(s.Shell, " "))
|
||||||
fmt.Fprintf(w, "Log:\t%s\t\n", s.Log)
|
fmt.Fprintf(w, "Log:\t%s\t\n", s.Log)
|
||||||
|
fmt.Fprintf(w, "Scope:\t%s\t\n", s.Scope)
|
||||||
fmt.Fprintln(w, "\nServer:")
|
fmt.Fprintln(w, "\nServer:")
|
||||||
fmt.Fprintf(w, "\tAddress:\t%s\n", s.Server.Address)
|
fmt.Fprintf(w, "\tAddress:\t%s\n", s.Server.Address)
|
||||||
fmt.Fprintf(w, "\tPort:\t%d\n", s.Server.Port)
|
fmt.Fprintf(w, "\tPort:\t%d\n", s.Server.Port)
|
||||||
|
|||||||
@ -15,7 +15,6 @@ func init() {
|
|||||||
configCmd.AddCommand(configInitCmd)
|
configCmd.AddCommand(configInitCmd)
|
||||||
rootCmd.AddCommand(configInitCmd)
|
rootCmd.AddCommand(configInitCmd)
|
||||||
addConfigFlags(configInitCmd)
|
addConfigFlags(configInitCmd)
|
||||||
configInitCmd.MarkFlagRequired("scope")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var configInitCmd = &cobra.Command{
|
var configInitCmd = &cobra.Command{
|
||||||
@ -33,9 +32,16 @@ override the options.`,
|
|||||||
}
|
}
|
||||||
|
|
||||||
defaults := settings.UserDefaults{}
|
defaults := settings.UserDefaults{}
|
||||||
getUserDefaults(cmd, &defaults, true)
|
getUserDefaults(cmd, &defaults, "defaults.", true)
|
||||||
authMethod, auther := getAuthentication(cmd)
|
authMethod, auther := getAuthentication(cmd)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
scope := mustGetString(cmd, "scope")
|
||||||
|
if scope == "" {
|
||||||
|
scope, err = os.Getwd()
|
||||||
|
checkErr(err)
|
||||||
|
}
|
||||||
|
|
||||||
db, err := storm.Open(databasePath)
|
db, err := storm.Open(databasePath)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
@ -45,6 +51,7 @@ override the options.`,
|
|||||||
BaseURL: mustGetString(cmd, "baseURL"),
|
BaseURL: mustGetString(cmd, "baseURL"),
|
||||||
Log: mustGetString(cmd, "log"),
|
Log: mustGetString(cmd, "log"),
|
||||||
Signup: mustGetBool(cmd, "signup"),
|
Signup: mustGetBool(cmd, "signup"),
|
||||||
|
Scope: scope,
|
||||||
Shell: strings.Split(strings.TrimSpace(mustGetString(cmd, "shell")), " "),
|
Shell: strings.Split(strings.TrimSpace(mustGetString(cmd, "shell")), " "),
|
||||||
AuthMethod: authMethod,
|
AuthMethod: authMethod,
|
||||||
Defaults: defaults,
|
Defaults: defaults,
|
||||||
|
|||||||
@ -57,7 +57,7 @@ you want to change.`,
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
getUserDefaults(cmd, &s.Defaults, false)
|
getUserDefaults(cmd, &s.Defaults, "defaults.", false)
|
||||||
|
|
||||||
var auther auth.Auther
|
var auther auth.Auther
|
||||||
if hasAuth {
|
if hasAuth {
|
||||||
|
|||||||
17
cmd/root.go
17
cmd/root.go
@ -3,7 +3,6 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
@ -35,7 +34,7 @@ func init() {
|
|||||||
rootCmd.Flags().IntP("port", "p", 0, "port to listen on (default comes from database)")
|
rootCmd.Flags().IntP("port", "p", 0, "port to listen on (default comes from database)")
|
||||||
rootCmd.Flags().StringP("cert", "c", "", "tls certificate (default comes from database)")
|
rootCmd.Flags().StringP("cert", "c", "", "tls certificate (default comes from database)")
|
||||||
rootCmd.Flags().StringP("key", "k", "", "tls key (default comes from database)")
|
rootCmd.Flags().StringP("key", "k", "", "tls key (default comes from database)")
|
||||||
rootCmd.Flags().StringP("scope", "s", "", "scope for users")
|
rootCmd.Flags().StringP("scope", "s", "", "scope to prepend to a user's scope when it is relative (default comes from database)")
|
||||||
}
|
}
|
||||||
|
|
||||||
var rootCmd = &cobra.Command{
|
var rootCmd = &cobra.Command{
|
||||||
@ -103,9 +102,11 @@ func serverVisitAndReplace(cmd *cobra.Command, s *settings.Settings) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func quickSetup(cmd *cobra.Command) {
|
func quickSetup(cmd *cobra.Command) {
|
||||||
|
var err error
|
||||||
scope := mustGetString(cmd, "scope")
|
scope := mustGetString(cmd, "scope")
|
||||||
if scope == "" {
|
if scope == "" {
|
||||||
panic(errors.New("scope flag must be set for quick setup"))
|
scope, err = os.Getwd()
|
||||||
|
checkErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
db, err := storm.Open(databasePath)
|
db, err := storm.Open(databasePath)
|
||||||
@ -115,6 +116,7 @@ func quickSetup(cmd *cobra.Command) {
|
|||||||
set := &settings.Settings{
|
set := &settings.Settings{
|
||||||
Key: generateRandomBytes(64), // 256 bit
|
Key: generateRandomBytes(64), // 256 bit
|
||||||
BaseURL: "",
|
BaseURL: "",
|
||||||
|
Scope: scope,
|
||||||
Log: "stderr",
|
Log: "stderr",
|
||||||
Signup: false,
|
Signup: false,
|
||||||
AuthMethod: auth.MethodJSONAuth,
|
AuthMethod: auth.MethodJSONAuth,
|
||||||
@ -125,7 +127,7 @@ func quickSetup(cmd *cobra.Command) {
|
|||||||
TLSKey: mustGetString(cmd, "key"),
|
TLSKey: mustGetString(cmd, "key"),
|
||||||
},
|
},
|
||||||
Defaults: settings.UserDefaults{
|
Defaults: settings.UserDefaults{
|
||||||
Scope: scope,
|
Scope: ".",
|
||||||
Locale: "en",
|
Locale: "en",
|
||||||
Perm: users.Permissions{
|
Perm: users.Permissions{
|
||||||
Admin: false,
|
Admin: false,
|
||||||
@ -169,6 +171,13 @@ func startServer(cmd *cobra.Command, st *storage.Storage) {
|
|||||||
settings, err := st.Settings.Get()
|
settings, err := st.Settings.Get()
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
|
scope := mustGetString(cmd, "scope")
|
||||||
|
if scope != "" {
|
||||||
|
settings.Scope = scope
|
||||||
|
err = st.Settings.Save(settings)
|
||||||
|
checkErr(err)
|
||||||
|
}
|
||||||
|
|
||||||
serverVisitAndReplace(cmd, settings)
|
serverVisitAndReplace(cmd, settings)
|
||||||
setupLogger(settings)
|
setupLogger(settings)
|
||||||
|
|
||||||
|
|||||||
@ -39,7 +39,7 @@ func runRules(cmd *cobra.Command, users func(*users.User, *storage.Storage), glo
|
|||||||
|
|
||||||
id := getUserIdentifier(cmd)
|
id := getUserIdentifier(cmd)
|
||||||
if id != nil {
|
if id != nil {
|
||||||
user, err := st.Users.Get(id)
|
user, err := st.Users.Get("", id)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
if users != nil {
|
if users != nil {
|
||||||
|
|||||||
88
cmd/users.go
88
cmd/users.go
@ -64,22 +64,22 @@ func usernameOrIDRequired(cmd *cobra.Command, args []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addUserFlags(cmd *cobra.Command) {
|
func addUserFlags(cmd *cobra.Command, prepend string) {
|
||||||
cmd.Flags().Bool("perm.admin", false, "admin perm for users")
|
cmd.Flags().Bool(prepend+"perm.admin", false, "admin perm for users")
|
||||||
cmd.Flags().Bool("perm.execute", true, "execute perm for users")
|
cmd.Flags().Bool(prepend+"perm.execute", true, "execute perm for users")
|
||||||
cmd.Flags().Bool("perm.create", true, "create perm for users")
|
cmd.Flags().Bool(prepend+"perm.create", true, "create perm for users")
|
||||||
cmd.Flags().Bool("perm.rename", true, "rename perm for users")
|
cmd.Flags().Bool(prepend+"perm.rename", true, "rename perm for users")
|
||||||
cmd.Flags().Bool("perm.modify", true, "modify perm for users")
|
cmd.Flags().Bool(prepend+"perm.modify", true, "modify perm for users")
|
||||||
cmd.Flags().Bool("perm.delete", true, "delete perm for users")
|
cmd.Flags().Bool(prepend+"perm.delete", true, "delete perm for users")
|
||||||
cmd.Flags().Bool("perm.share", true, "share perm for users")
|
cmd.Flags().Bool(prepend+"perm.share", true, "share perm for users")
|
||||||
cmd.Flags().Bool("perm.download", true, "download perm for users")
|
cmd.Flags().Bool(prepend+"perm.download", true, "download perm for users")
|
||||||
cmd.Flags().String("sorting.by", "name", "sorting mode (name, size or modified)")
|
cmd.Flags().String(prepend+"sorting.by", "name", "sorting mode (name, size or modified)")
|
||||||
cmd.Flags().Bool("sorting.asc", false, "sorting by ascending order")
|
cmd.Flags().Bool(prepend+"sorting.asc", false, "sorting by ascending order")
|
||||||
cmd.Flags().Bool("lockPassword", false, "lock password")
|
cmd.Flags().Bool(prepend+"lockPassword", false, "lock password")
|
||||||
cmd.Flags().StringSlice("commands", nil, "a list of the commands a user can execute")
|
cmd.Flags().StringSlice(prepend+"commands", nil, "a list of the commands a user can execute")
|
||||||
cmd.Flags().String("scope", "", "scope for users")
|
cmd.Flags().String(prepend+"scope", "", "scope for users")
|
||||||
cmd.Flags().String("locale", "en", "locale for users")
|
cmd.Flags().String(prepend+"locale", "en", "locale for users")
|
||||||
cmd.Flags().String("viewMode", string(users.ListViewMode), "view mode for users")
|
cmd.Flags().String(prepend+"viewMode", string(users.ListViewMode), "view mode for users")
|
||||||
}
|
}
|
||||||
|
|
||||||
func getViewMode(cmd *cobra.Command) users.ViewMode {
|
func getViewMode(cmd *cobra.Command) users.ViewMode {
|
||||||
@ -90,39 +90,39 @@ func getViewMode(cmd *cobra.Command) users.ViewMode {
|
|||||||
return viewMode
|
return viewMode
|
||||||
}
|
}
|
||||||
|
|
||||||
func getUserDefaults(cmd *cobra.Command, defaults *settings.UserDefaults, all bool) {
|
func getUserDefaults(cmd *cobra.Command, defaults *settings.UserDefaults, prepend string, all bool) {
|
||||||
visit := func(flag *pflag.Flag) {
|
visit := func(flag *pflag.Flag) {
|
||||||
switch flag.Name {
|
switch flag.Name {
|
||||||
case "scope":
|
case prepend+"scope":
|
||||||
defaults.Scope = mustGetString(cmd, "scope")
|
defaults.Scope = mustGetString(cmd, flag.Name)
|
||||||
case "locale":
|
case prepend+"locale":
|
||||||
defaults.Locale = mustGetString(cmd, "locale")
|
defaults.Locale = mustGetString(cmd, flag.Name)
|
||||||
case "viewMode":
|
case prepend+"viewMode":
|
||||||
defaults.ViewMode = getViewMode(cmd)
|
defaults.ViewMode = getViewMode(cmd)
|
||||||
case "perm.admin":
|
case prepend+"perm.admin":
|
||||||
defaults.Perm.Admin = mustGetBool(cmd, "perm.admin")
|
defaults.Perm.Admin = mustGetBool(cmd, flag.Name)
|
||||||
case "perm.execute":
|
case prepend+"perm.execute":
|
||||||
defaults.Perm.Execute = mustGetBool(cmd, "perm.execute")
|
defaults.Perm.Execute = mustGetBool(cmd, flag.Name)
|
||||||
case "perm.create":
|
case prepend+"perm.create":
|
||||||
defaults.Perm.Create = mustGetBool(cmd, "perm.create")
|
defaults.Perm.Create = mustGetBool(cmd, flag.Name)
|
||||||
case "perm.rename":
|
case prepend+"perm.rename":
|
||||||
defaults.Perm.Rename = mustGetBool(cmd, "perm.rename")
|
defaults.Perm.Rename = mustGetBool(cmd, flag.Name)
|
||||||
case "perm.modify":
|
case prepend+"perm.modify":
|
||||||
defaults.Perm.Modify = mustGetBool(cmd, "perm.modify")
|
defaults.Perm.Modify = mustGetBool(cmd, flag.Name)
|
||||||
case "perm.delete":
|
case prepend+"perm.delete":
|
||||||
defaults.Perm.Delete = mustGetBool(cmd, "perm.delete")
|
defaults.Perm.Delete = mustGetBool(cmd, flag.Name)
|
||||||
case "perm.share":
|
case prepend+"perm.share":
|
||||||
defaults.Perm.Share = mustGetBool(cmd, "perm.share")
|
defaults.Perm.Share = mustGetBool(cmd, flag.Name)
|
||||||
case "perm.download":
|
case prepend+"perm.download":
|
||||||
defaults.Perm.Download = mustGetBool(cmd, "perm.download")
|
defaults.Perm.Download = mustGetBool(cmd, flag.Name)
|
||||||
case "commands":
|
case prepend+"commands":
|
||||||
commands, err := cmd.Flags().GetStringSlice("commands")
|
commands, err := cmd.Flags().GetStringSlice(flag.Name)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
defaults.Commands = commands
|
defaults.Commands = commands
|
||||||
case "sorting.by":
|
case prepend+"sorting.by":
|
||||||
defaults.Sorting.By = mustGetString(cmd, "sorting.by")
|
defaults.Sorting.By = mustGetString(cmd, flag.Name)
|
||||||
case "sorting.asc":
|
case prepend+"sorting.asc":
|
||||||
defaults.Sorting.Asc = mustGetBool(cmd, "sorting.asc")
|
defaults.Sorting.Asc = mustGetBool(cmd, flag.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -32,19 +32,21 @@ var findUsers = func(cmd *cobra.Command, args []string) {
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
st := getStorage(db)
|
st := getStorage(db)
|
||||||
|
|
||||||
|
settings, err := st.Settings.Get()
|
||||||
|
checkErr(err)
|
||||||
|
|
||||||
username, _ := cmd.Flags().GetString("username")
|
username, _ := cmd.Flags().GetString("username")
|
||||||
id, _ := cmd.Flags().GetUint("id")
|
id, _ := cmd.Flags().GetUint("id")
|
||||||
|
|
||||||
var err error
|
|
||||||
var list []*users.User
|
var list []*users.User
|
||||||
var user *users.User
|
var user *users.User
|
||||||
|
|
||||||
if username != "" {
|
if username != "" {
|
||||||
user, err = st.Users.Get(username)
|
user, err = st.Users.Get(settings.Scope, username)
|
||||||
} else if id != 0 {
|
} else if id != 0 {
|
||||||
user, err = st.Users.Get(id)
|
user, err = st.Users.Get(settings.Scope, id)
|
||||||
} else {
|
} else {
|
||||||
list, err = st.Users.Gets()
|
list, err = st.Users.Gets(settings.Scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import (
|
|||||||
func init() {
|
func init() {
|
||||||
usersCmd.AddCommand(usersNewCmd)
|
usersCmd.AddCommand(usersNewCmd)
|
||||||
|
|
||||||
addUserFlags(usersNewCmd)
|
addUserFlags(usersNewCmd, "")
|
||||||
usersNewCmd.Flags().StringP("username", "u", "", "new users's username")
|
usersNewCmd.Flags().StringP("username", "u", "", "new users's username")
|
||||||
usersNewCmd.Flags().StringP("password", "p", "", "new user's password")
|
usersNewCmd.Flags().StringP("password", "p", "", "new user's password")
|
||||||
usersNewCmd.MarkFlagRequired("username")
|
usersNewCmd.MarkFlagRequired("username")
|
||||||
@ -27,7 +27,7 @@ var usersNewCmd = &cobra.Command{
|
|||||||
|
|
||||||
s, err := st.Settings.Get()
|
s, err := st.Settings.Get()
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
getUserDefaults(cmd, &s.Defaults, false)
|
getUserDefaults(cmd, &s.Defaults, "", false)
|
||||||
|
|
||||||
password, _ := cmd.Flags().GetString("password")
|
password, _ := cmd.Flags().GetString("password")
|
||||||
password, err = users.HashPwd(password)
|
password, err = users.HashPwd(password)
|
||||||
|
|||||||
@ -12,7 +12,7 @@ func init() {
|
|||||||
usersUpdateCmd.Flags().UintP("id", "i", 0, "id of the user")
|
usersUpdateCmd.Flags().UintP("id", "i", 0, "id of the user")
|
||||||
usersUpdateCmd.Flags().StringP("username", "u", "", "user to change or new username if flag 'id' is set")
|
usersUpdateCmd.Flags().StringP("username", "u", "", "user to change or new username if flag 'id' is set")
|
||||||
usersUpdateCmd.Flags().StringP("password", "p", "", "new password")
|
usersUpdateCmd.Flags().StringP("password", "p", "", "new password")
|
||||||
addUserFlags(usersUpdateCmd)
|
addUserFlags(usersUpdateCmd, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
var usersUpdateCmd = &cobra.Command{
|
var usersUpdateCmd = &cobra.Command{
|
||||||
@ -26,17 +26,19 @@ options you want to change.`,
|
|||||||
defer db.Close()
|
defer db.Close()
|
||||||
st := getStorage(db)
|
st := getStorage(db)
|
||||||
|
|
||||||
|
set, err := st.Settings.Get()
|
||||||
|
checkErr(err)
|
||||||
|
|
||||||
id, _ := cmd.Flags().GetUint("id")
|
id, _ := cmd.Flags().GetUint("id")
|
||||||
username := mustGetString(cmd, "username")
|
username := mustGetString(cmd, "username")
|
||||||
password := mustGetString(cmd, "password")
|
password := mustGetString(cmd, "password")
|
||||||
|
|
||||||
var user *users.User
|
var user *users.User
|
||||||
var err error
|
|
||||||
|
|
||||||
if id != 0 {
|
if id != 0 {
|
||||||
user, err = st.Users.Get(id)
|
user, err = st.Users.Get(set.Scope, id)
|
||||||
} else {
|
} else {
|
||||||
user, err = st.Users.Get(username)
|
user, err = st.Users.Get(set.Scope, username)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
@ -49,7 +51,7 @@ options you want to change.`,
|
|||||||
Sorting: user.Sorting,
|
Sorting: user.Sorting,
|
||||||
Commands: user.Commands,
|
Commands: user.Commands,
|
||||||
}
|
}
|
||||||
getUserDefaults(cmd, &defaults, false)
|
getUserDefaults(cmd, &defaults, "", false)
|
||||||
user.Scope = defaults.Scope
|
user.Scope = defaults.Scope
|
||||||
user.Locale = defaults.Locale
|
user.Locale = defaults.Locale
|
||||||
user.ViewMode = defaults.ViewMode
|
user.ViewMode = defaults.ViewMode
|
||||||
|
|||||||
@ -67,7 +67,7 @@ func withUser(fn handleFunc) handleFunc {
|
|||||||
w.Header().Add("X-Renew-Token", "true")
|
w.Header().Add("X-Renew-Token", "true")
|
||||||
}
|
}
|
||||||
|
|
||||||
d.user, err = d.store.Users.Get(tk.User.ID)
|
d.user, err = d.store.Users.Get(d.settings.Scope, tk.User.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return http.StatusInternalServerError, err
|
return http.StatusInternalServerError, err
|
||||||
}
|
}
|
||||||
@ -91,7 +91,7 @@ var loginHandler = func(w http.ResponseWriter, r *http.Request, d *data) (int, e
|
|||||||
return http.StatusInternalServerError, err
|
return http.StatusInternalServerError, err
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := auther.Auth(r)
|
user, err := auther.Auth(r, d.store.Users, d.Settings)
|
||||||
if err == os.ErrPermission {
|
if err == os.ErrPermission {
|
||||||
return http.StatusForbidden, nil
|
return http.StatusForbidden, nil
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
|
|||||||
@ -13,7 +13,7 @@ var withHashFile = func(fn handleFunc) handleFunc {
|
|||||||
return errToStatus(err), err
|
return errToStatus(err), err
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := d.store.Users.Get(link.UserID)
|
user, err := d.store.Users.Get(d.settings.Scope, link.UserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errToStatus(err), err
|
return errToStatus(err), err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,7 +61,7 @@ func withSelfOrAdmin(fn handleFunc) handleFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var usersGetHandler = withAdmin(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
var usersGetHandler = withAdmin(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
||||||
users, err := d.store.Users.Gets()
|
users, err := d.store.Users.Gets(d.settings.Scope)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return http.StatusInternalServerError, err
|
return http.StatusInternalServerError, err
|
||||||
}
|
}
|
||||||
@ -78,7 +78,7 @@ var usersGetHandler = withAdmin(func(w http.ResponseWriter, r *http.Request, d *
|
|||||||
})
|
})
|
||||||
|
|
||||||
var userGetHandler = withSelfOrAdmin(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
var userGetHandler = withSelfOrAdmin(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
||||||
u, err := d.store.Users.Get(d.raw.(uint))
|
u, err := d.store.Users.Get(d.settings.Scope, d.raw.(uint))
|
||||||
if err == errors.ErrNotExist {
|
if err == errors.ErrNotExist {
|
||||||
return http.StatusNotFound, err
|
return http.StatusNotFound, err
|
||||||
}
|
}
|
||||||
@ -147,7 +147,7 @@ var userPutHandler = withSelfOrAdmin(func(w http.ResponseWriter, r *http.Request
|
|||||||
req.Data.Password, err = users.HashPwd(req.Data.Password)
|
req.Data.Password, err = users.HashPwd(req.Data.Password)
|
||||||
} else {
|
} else {
|
||||||
var suser *users.User
|
var suser *users.User
|
||||||
suser, err = d.store.Users.Get(d.raw.(uint))
|
suser, err = d.store.Users.Get(d.settings.Scope, d.raw.(uint))
|
||||||
req.Data.Password = suser.Password
|
req.Data.Password = suser.Password
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,7 @@ type Settings struct {
|
|||||||
Key []byte `json:"key"`
|
Key []byte `json:"key"`
|
||||||
BaseURL string `json:"baseURL"`
|
BaseURL string `json:"baseURL"`
|
||||||
Log string `json:"log"`
|
Log string `json:"log"`
|
||||||
|
Scope string `json:"scope"`
|
||||||
Server Server `json:"server"`
|
Server Server `json:"server"`
|
||||||
Signup bool `json:"signup"`
|
Signup bool `json:"signup"`
|
||||||
Defaults UserDefaults `json:"defaults"`
|
Defaults UserDefaults `json:"defaults"`
|
||||||
|
|||||||
@ -3,7 +3,7 @@ package importer
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"os"
|
||||||
|
|
||||||
"github.com/asdine/storm"
|
"github.com/asdine/storm"
|
||||||
"github.com/filebrowser/filebrowser/v2/rules"
|
"github.com/filebrowser/filebrowser/v2/rules"
|
||||||
@ -52,7 +52,6 @@ func readOldUsers(db *storm.DB) ([]*oldUser, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func convertUsersToNew(old []*oldUser) ([]*users.User, error) {
|
func convertUsersToNew(old []*oldUser) ([]*users.User, error) {
|
||||||
var err error
|
|
||||||
list := []*users.User{}
|
list := []*users.User{}
|
||||||
|
|
||||||
for _, oldUser := range old {
|
for _, oldUser := range old {
|
||||||
@ -82,12 +81,12 @@ func convertUsersToNew(old []*oldUser) ([]*users.User, error) {
|
|||||||
user.Rules = append(user.Rules, *rule)
|
user.Rules = append(user.Rules, *rule)
|
||||||
}
|
}
|
||||||
|
|
||||||
user.Scope, err = filepath.Abs(user.Scope)
|
baseScope, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = user.Clean()
|
err = user.Clean(baseScope)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,7 +36,7 @@ func NewStorage(back StorageBackend) *Storage {
|
|||||||
// Get allows you to get a user by its name or username. The provided
|
// Get allows you to get a user by its name or username. The provided
|
||||||
// id must be a string for username lookup or a uint for id lookup. If id
|
// id must be a string for username lookup or a uint for id lookup. If id
|
||||||
// is neither, a ErrInvalidDataType will be returned.
|
// is neither, a ErrInvalidDataType will be returned.
|
||||||
func (s *Storage) Get(id interface{}) (*User, error) {
|
func (s *Storage) Get(baseScope string, id interface{}) (*User, error) {
|
||||||
var (
|
var (
|
||||||
user *User
|
user *User
|
||||||
err error
|
err error
|
||||||
@ -55,19 +55,19 @@ func (s *Storage) Get(id interface{}) (*User, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
user.Clean()
|
user.Clean(baseScope)
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets gets a list of all users.
|
// Gets gets a list of all users.
|
||||||
func (s *Storage) Gets() ([]*User, error) {
|
func (s *Storage) Gets(baseScope string) ([]*User, error) {
|
||||||
users, err := s.back.Gets()
|
users, err := s.back.Gets()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
user.Clean()
|
user.Clean(baseScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
return users, err
|
return users, err
|
||||||
@ -75,7 +75,7 @@ func (s *Storage) Gets() ([]*User, error) {
|
|||||||
|
|
||||||
// Update updates a user in the database.
|
// Update updates a user in the database.
|
||||||
func (s *Storage) Update(user *User, fields ...string) error {
|
func (s *Storage) Update(user *User, fields ...string) error {
|
||||||
err := user.Clean(fields...)
|
err := user.Clean("", fields...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -93,7 +93,7 @@ func (s *Storage) Update(user *User, fields ...string) error {
|
|||||||
|
|
||||||
// Save saves the user in a storage.
|
// Save saves the user in a storage.
|
||||||
func (s *Storage) Save(user *User) error {
|
func (s *Storage) Save(user *User) error {
|
||||||
if err := user.Clean(); err != nil {
|
if err := user.Clean(""); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
package users
|
package users
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/filebrowser/filebrowser/v2/errors"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/filebrowser/filebrowser/v2/errors"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/files"
|
"github.com/filebrowser/filebrowser/v2/files"
|
||||||
"github.com/filebrowser/filebrowser/v2/rules"
|
"github.com/filebrowser/filebrowser/v2/rules"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
@ -51,7 +52,7 @@ var checkableFields = []string{
|
|||||||
|
|
||||||
// Clean cleans up a user and verifies if all its fields
|
// Clean cleans up a user and verifies if all its fields
|
||||||
// are alright to be saved.
|
// are alright to be saved.
|
||||||
func (u *User) Clean(fields ...string) error {
|
func (u *User) Clean(baseScope string, fields ...string) error {
|
||||||
if len(fields) == 0 {
|
if len(fields) == 0 {
|
||||||
fields = checkableFields
|
fields = checkableFields
|
||||||
}
|
}
|
||||||
@ -66,10 +67,6 @@ func (u *User) Clean(fields ...string) error {
|
|||||||
if u.Password == "" {
|
if u.Password == "" {
|
||||||
return errors.ErrEmptyPassword
|
return errors.ErrEmptyPassword
|
||||||
}
|
}
|
||||||
case "Scope":
|
|
||||||
if !filepath.IsAbs(u.Scope) {
|
|
||||||
return errors.ErrScopeIsRelative
|
|
||||||
}
|
|
||||||
case "ViewMode":
|
case "ViewMode":
|
||||||
if u.ViewMode == "" {
|
if u.ViewMode == "" {
|
||||||
u.ViewMode = ListViewMode
|
u.ViewMode = ListViewMode
|
||||||
@ -90,7 +87,13 @@ func (u *User) Clean(fields ...string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if u.Fs == nil {
|
if u.Fs == nil {
|
||||||
u.Fs = afero.NewBasePathFs(afero.NewOsFs(), u.Scope)
|
scope := u.Scope
|
||||||
|
|
||||||
|
if !filepath.IsAbs(scope) {
|
||||||
|
scope = filepath.Join(baseScope, scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
u.Fs = afero.NewBasePathFs(afero.NewOsFs(), scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user