diff --git a/common/common_test.go b/common/common_test.go index 2b6b9590..eea8221d 100644 --- a/common/common_test.go +++ b/common/common_test.go @@ -831,7 +831,10 @@ func TestParseAllowedIPAndRanges(t *testing.T) { } func TestHideConfidentialData(t *testing.T) { - for _, provider := range sdk.ListProviders() { + for _, provider := range []sdk.FilesystemProvider{sdk.LocalFilesystemProvider, + sdk.CryptedFilesystemProvider, sdk.S3FilesystemProvider, sdk.GCSFilesystemProvider, + sdk.AzureBlobFilesystemProvider, sdk.SFTPFilesystemProvider, + } { u := dataprovider.User{ FsConfig: vfs.Filesystem{ Provider: provider, diff --git a/dataprovider/dataprovider.go b/dataprovider/dataprovider.go index 9ea23217..f920c019 100644 --- a/dataprovider/dataprovider.go +++ b/dataprovider/dataprovider.go @@ -457,6 +457,11 @@ func GetQuotaTracking() int { return config.TrackQuota } +// HasUsersBaseDir returns true if users base dir is set +func HasUsersBaseDir() bool { + return config.UsersBaseDir != "" +} + // Provider defines the interface that data providers must implement. type Provider interface { validateUserAndPass(username, password, ip, protocol string) (User, error) diff --git a/dataprovider/user.go b/dataprovider/user.go index 8405a54d..22ba6ac0 100644 --- a/dataprovider/user.go +++ b/dataprovider/user.go @@ -561,19 +561,25 @@ func (u *User) AddVirtualDirs(list []os.FileInfo, virtualPath string) []os.FileI return list } + vdirs := make(map[string]bool) for dir := range u.GetVirtualFoldersInPath(virtualPath) { - fi := vfs.NewFileInfo(dir, true, 0, time.Now(), false) - found := false - for index := range list { - if list[index].Name() == fi.Name() { - list[index] = fi - found = true - break + vdirs[path.Base(dir)] = true + } + if len(vdirs) == 0 { + return list + } + + for index := range list { + for dir := range vdirs { + if list[index].Name() == dir { + delete(vdirs, dir) } } - if !found { - list = append(list, fi) - } + } + + for dir := range vdirs { + fi := vfs.NewFileInfo(dir, true, 0, time.Now(), false) + list = append(list, fi) } return list } diff --git a/go.mod b/go.mod index 135008c4..caaea430 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( github.com/rs/cors v1.8.2 github.com/rs/xid v1.3.0 github.com/rs/zerolog v1.26.2-0.20211219225053-665519c4da50 - github.com/sftpgo/sdk v0.0.0-20220106101837-50e87c59705a + github.com/sftpgo/sdk v0.0.0-20220110174344-ecf586dd8941 github.com/shirou/gopsutil/v3 v3.21.13-0.20220106132423-a3ae4bc40d26 github.com/spf13/afero v1.8.0 github.com/spf13/cobra v1.3.0 diff --git a/go.sum b/go.sum index 47ac017d..a438d5f6 100644 --- a/go.sum +++ b/go.sum @@ -747,8 +747,8 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/secsy/goftp v0.0.0-20200609142545-aa2de14babf4 h1:PT+ElG/UUFMfqy5HrxJxNzj3QBOf7dZwupeVC+mG1Lo= github.com/secsy/goftp v0.0.0-20200609142545-aa2de14babf4/go.mod h1:MnkX001NG75g3p8bhFycnyIjeQoOjGL6CEIsdE/nKSY= -github.com/sftpgo/sdk v0.0.0-20220106101837-50e87c59705a h1:JJc19rE0eW2knPa/KIFYvqyu25CwzKltJ5Cw1kK3o4A= -github.com/sftpgo/sdk v0.0.0-20220106101837-50e87c59705a/go.mod h1:Bhgac6kiwIziILXLzH4wepT8lQXyhF83poDXqZorN6Q= +github.com/sftpgo/sdk v0.0.0-20220110174344-ecf586dd8941 h1:CxKFDSYekL6+dOZ9rSglYGwcXyhM4Aki6yDsdiPlJ5Y= +github.com/sftpgo/sdk v0.0.0-20220110174344-ecf586dd8941/go.mod h1:Bhgac6kiwIziILXLzH4wepT8lQXyhF83poDXqZorN6Q= github.com/shirou/gopsutil/v3 v3.21.13-0.20220106132423-a3ae4bc40d26 h1:nkvraEu1xs6D3AimiR9SkIOCG6lVvVZRfwbbQ7fX1DY= github.com/shirou/gopsutil/v3 v3.21.13-0.20220106132423-a3ae4bc40d26/go.mod h1:BToYZVTlSVlfazpDDYFnsVZLaoRG+g8ufT6fPQLdJzA= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= diff --git a/httpd/webadmin.go b/httpd/webadmin.go index 144e3a0e..6bb1b581 100644 --- a/httpd/webadmin.go +++ b/httpd/webadmin.go @@ -7,6 +7,7 @@ import ( "io" "net/http" "net/url" + "os" "path/filepath" "strconv" "strings" @@ -142,6 +143,13 @@ type statusPage struct { Status ServicesStatus } +type fsWrapper struct { + vfs.Filesystem + IsUserPage bool + HasUsersBaseDir bool + DirPath string +} + type userPage struct { basePage User *dataprovider.User @@ -155,6 +163,8 @@ type userPage struct { RedactedSecret string Mode userPageMode VirtualFolders []vfs.BaseVirtualFolder + CanImpersonate bool + FsWrapper fsWrapper } type adminPage struct { @@ -207,9 +217,10 @@ type setupPage struct { type folderPage struct { basePage - Folder vfs.BaseVirtualFolder - Error string - Mode folderPageMode + Folder vfs.BaseVirtualFolder + Error string + Mode folderPageMode + FsWrapper fsWrapper } type messagePage struct { @@ -307,7 +318,12 @@ func loadAdminTemplates(templatesPath string) { } fsBaseTpl := template.New("fsBaseTemplate").Funcs(template.FuncMap{ - "ListFSProviders": sdk.ListProviders, + "ListFSProviders": func() []sdk.FilesystemProvider { + return []sdk.FilesystemProvider{sdk.LocalFilesystemProvider, sdk.CryptedFilesystemProvider, + sdk.S3FilesystemProvider, sdk.GCSFilesystemProvider, + sdk.AzureBlobFilesystemProvider, sdk.SFTPFilesystemProvider, + } + }, }) usersTmpl := util.LoadTemplate(nil, usersPaths...) userTmpl := util.LoadTemplate(fsBaseTpl, userPaths...) @@ -594,6 +610,13 @@ func renderUserPage(w http.ResponseWriter, r *http.Request, user *dataprovider.U WebClientOptions: sdk.WebClientOptions, RootDirPerms: user.GetPermissionsForPath("/"), VirtualFolders: folders, + CanImpersonate: os.Getuid() == 0, + FsWrapper: fsWrapper{ + Filesystem: user.FsConfig, + IsUserPage: true, + HasUsersBaseDir: dataprovider.HasUsersBaseDir(), + DirPath: user.HomeDir, + }, } renderAdminTemplate(w, templateUser, data) } @@ -619,6 +642,12 @@ func renderFolderPage(w http.ResponseWriter, r *http.Request, folder vfs.BaseVir Error: error, Folder: folder, Mode: mode, + FsWrapper: fsWrapper{ + Filesystem: folder.FsConfig, + IsUserPage: false, + HasUsersBaseDir: false, + DirPath: folder.MappedPath, + }, } renderAdminTemplate(w, templateFolder, data) } @@ -1708,6 +1737,7 @@ func handleWebAddUserGet(w http.ResponseWriter, r *http.Request) { user.ID = 0 user.Username = "" user.Password = "" + user.PublicKeys = nil user.SetEmptySecrets() renderUserPage(w, r, &user, userPageModeAdd, "") } else if _, ok := err.(*util.RecordNotFoundError); ok { @@ -1716,7 +1746,12 @@ func handleWebAddUserGet(w http.ResponseWriter, r *http.Request) { renderInternalServerErrorPage(w, r, err) } } else { - user := dataprovider.User{BaseUser: sdk.BaseUser{Status: 1}} + user := dataprovider.User{BaseUser: sdk.BaseUser{ + Status: 1, + Permissions: map[string][]string{ + "/": {dataprovider.PermAny}, + }, + }} renderUserPage(w, r, &user, userPageModeAdd, "") } } diff --git a/templates/webadmin/folder.html b/templates/webadmin/folder.html index 6d9f9304..6c092991 100644 --- a/templates/webadmin/folder.html +++ b/templates/webadmin/folder.html @@ -76,18 +76,8 @@ -