diff --git a/go.mod b/go.mod index 93fbd50d..94c9ca26 100644 --- a/go.mod +++ b/go.mod @@ -53,7 +53,7 @@ require ( github.com/rs/cors v1.9.0 github.com/rs/xid v1.5.0 github.com/rs/zerolog v1.29.1 - github.com/sftpgo/sdk v0.1.4 + github.com/sftpgo/sdk v0.1.5-0.20230524172149-afb96ebee860 github.com/shirou/gopsutil/v3 v3.23.4 github.com/spf13/afero v1.9.5 github.com/spf13/cobra v1.7.0 diff --git a/go.sum b/go.sum index d8ad4216..320461d7 100644 --- a/go.sum +++ b/go.sum @@ -1842,8 +1842,8 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/secsy/goftp v0.0.0-20200609142545-aa2de14babf4 h1:PT+ElG/UUFMfqy5HrxJxNzj3QBOf7dZwupeVC+mG1Lo= -github.com/sftpgo/sdk v0.1.4 h1:TyNzpG7o8PuOgAQ1AvpFNJ93quR/90r+9FYyElTKqfw= -github.com/sftpgo/sdk v0.1.4/go.mod h1:TjeoMWS0JEXt9RukJveTnaiHj4+MVLtUiDC+mY++Odk= +github.com/sftpgo/sdk v0.1.5-0.20230524172149-afb96ebee860 h1:adaUl1JO/4bPhQuhSH7bQJ2o+2CW6Ry7R2w2SltS/PE= +github.com/sftpgo/sdk v0.1.5-0.20230524172149-afb96ebee860/go.mod h1:TjeoMWS0JEXt9RukJveTnaiHj4+MVLtUiDC+mY++Odk= github.com/shirou/gopsutil/v3 v3.23.4 h1:hZwmDxZs7Ewt75DV81r4pFMqbq+di2cbt9FsQBqLD2o= github.com/shirou/gopsutil/v3 v3.23.4/go.mod h1:ZcGxyfzAMRevhUR2+cfhXDH6gQdFYE/t8j1nsU4mPI8= github.com/shoenig/go-m1cpu v0.1.5/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ= diff --git a/internal/common/connection_test.go b/internal/common/connection_test.go index d680f3ce..dd5fd32d 100644 --- a/internal/common/connection_test.go +++ b/internal/common/connection_test.go @@ -16,6 +16,7 @@ package common import ( "errors" + "fmt" "os" "path" "path/filepath" @@ -645,3 +646,160 @@ func TestFsFileCopier(t *testing.T) { _, ok = fs.(vfs.FsFileCopier) assert.True(t, ok) } + +func TestFilterListDirs(t *testing.T) { + filters := dataprovider.UserFilters{ + BaseUserFilters: sdk.BaseUserFilters{ + FilePatterns: []sdk.PatternsFilter{ + { + Path: "/dir1", + DenyPolicy: sdk.DenyPolicyDefault, + AllowedPatterns: []string{"*.jpg"}, + }, + { + Path: "/dir2", + DenyPolicy: sdk.DenyPolicyHide, + AllowedPatterns: []string{"*.jpg"}, + }, + }, + }, + } + virtualFolders := []vfs.VirtualFolder{ + { + VirtualPath: "/dir1/vdir1", + }, + { + VirtualPath: "/dir1/vdir2", + }, + { + VirtualPath: "/dir1/vdir3", + }, + { + VirtualPath: "/dir2/vdir1", + }, + { + VirtualPath: "/dir2/vdir2", + }, + { + VirtualPath: "/dir2/vdir3.jpg", + }, + } + user := dataprovider.User{ + Filters: filters, + VirtualFolders: virtualFolders, + } + + dirContents := []os.FileInfo{ + vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false), + vfs.NewFileInfo("file1.jpg", false, 123, time.Now(), false), + } + + filtered := user.FilterListDir(dirContents, "/dir1") + assert.Len(t, filtered, 5) + + filtered = user.FilterListDir(dirContents, "/dir2") + assert.Len(t, filtered, 2) + + dirContents = []os.FileInfo{ + vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false), + vfs.NewFileInfo("vdir3.jpg", false, 123, time.Now(), false), + } + + filtered = user.FilterListDir(dirContents, "/dir1") + assert.Len(t, filtered, 5) + + dirContents = []os.FileInfo{ + vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false), + vfs.NewFileInfo("vdir3.jpg", false, 123, time.Now(), false), + } + + filtered = user.FilterListDir(dirContents, "/dir2") + if assert.Len(t, filtered, 1) { + assert.True(t, filtered[0].IsDir()) + } + + user.VirtualFolders = nil + dirContents = []os.FileInfo{ + vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false), + vfs.NewFileInfo("vdir3.jpg", false, 123, time.Now(), false), + } + filtered = user.FilterListDir(dirContents, "/dir1") + assert.Len(t, filtered, 2) + + dirContents = []os.FileInfo{ + vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false), + vfs.NewFileInfo("vdir3.jpg", false, 123, time.Now(), false), + } + filtered = user.FilterListDir(dirContents, "/dir2") + if assert.Len(t, filtered, 1) { + assert.False(t, filtered[0].IsDir()) + } + + dirContents = []os.FileInfo{ + vfs.NewFileInfo("file1.jpg", false, 123, time.Now(), false), + vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false), + vfs.NewFileInfo("file2.txt", false, 123, time.Now(), false), + vfs.NewFileInfo("vdir3.jpg", false, 123, time.Now(), false), + } + filtered = user.FilterListDir(dirContents, "/dir2") + if assert.Len(t, filtered, 2) { + assert.False(t, filtered[0].IsDir()) + assert.False(t, filtered[1].IsDir()) + } + + user.VirtualFolders = virtualFolders + user.Filters = filters + filtered = user.FilterListDir(nil, "/dir1") + assert.Len(t, filtered, 3) + filtered = user.FilterListDir(nil, "/dir2") + assert.Len(t, filtered, 1) + + dirContents = []os.FileInfo{ + vfs.NewFileInfo("file1.jPg", false, 123, time.Now(), false), + vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false), + vfs.NewFileInfo("file2.txt", false, 123, time.Now(), false), + vfs.NewFileInfo("vdir3.jpg", false, 456, time.Now(), false), + } + filtered = user.FilterListDir(dirContents, "/dir2") + assert.Len(t, filtered, 2) + + user = dataprovider.User{ + Filters: dataprovider.UserFilters{ + BaseUserFilters: sdk.BaseUserFilters{ + FilePatterns: []sdk.PatternsFilter{ + { + Path: "/dir3", + AllowedPatterns: []string{"ic35"}, + DeniedPatterns: []string{"*"}, + DenyPolicy: sdk.DenyPolicyHide, + }, + }, + }, + }, + } + dirContents = []os.FileInfo{ + vfs.NewFileInfo("file1.jpg", false, 123, time.Now(), false), + vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false), + vfs.NewFileInfo("file2.txt", false, 123, time.Now(), false), + vfs.NewFileInfo("vdir3.jpg", false, 456, time.Now(), false), + } + filtered = user.FilterListDir(dirContents, "/dir3") + assert.Len(t, filtered, 0) + + dirContents = nil + for i := 0; i < 100; i++ { + dirContents = append(dirContents, vfs.NewFileInfo(fmt.Sprintf("ic%02d", i), i%2 == 0, int64(i), time.Now(), false)) + } + dirContents = append(dirContents, vfs.NewFileInfo("ic350", false, 123, time.Now(), false)) + dirContents = append(dirContents, vfs.NewFileInfo(".ic35", false, 123, time.Now(), false)) + dirContents = append(dirContents, vfs.NewFileInfo("ic35.", false, 123, time.Now(), false)) + dirContents = append(dirContents, vfs.NewFileInfo("*ic35", false, 123, time.Now(), false)) + dirContents = append(dirContents, vfs.NewFileInfo("ic35*", false, 123, time.Now(), false)) + dirContents = append(dirContents, vfs.NewFileInfo("ic35.*", false, 123, time.Now(), false)) + dirContents = append(dirContents, vfs.NewFileInfo("file.jpg", false, 123, time.Now(), false)) + + filtered = user.FilterListDir(dirContents, "/dir3") + if assert.Len(t, filtered, 1) { + assert.Equal(t, "ic35", filtered[0].Name()) + } +} diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 571fdd87..7e52eca1 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -5403,7 +5403,7 @@ components: type: array items: type: string - description: 'list of, case insensitive, allowed shell like patterns.' + description: 'list of, case insensitive, allowed shell like patterns. Allowed patterns are evaluated before the denied ones' example: - '*.jpg' - a*b?.png @@ -5411,7 +5411,7 @@ components: type: array items: type: string - description: 'list of, case insensitive, denied shell like patterns. Denied patterns are evaluated before the allowed ones' + description: 'list of, case insensitive, denied shell like patterns' example: - '*.zip' deny_policy: diff --git a/templates/webadmin/group.html b/templates/webadmin/group.html index f8d02425..1f8afc81 100644 --- a/templates/webadmin/group.html +++ b/templates/webadmin/group.html @@ -222,7 +222,7 @@ along with this program. If not, see .
Comma separated denied or allowed files/directories, based on shell patterns.
-

Denied entries are visible in directory listing by default, you can hide them by setting the "Hidden" policy, but please be aware that this may cause performance issues for large directories

+

Match is case insensitive, set you patterns as lowercase. Denied entries are visible in directory listing by default, you can hide them by setting the "Hidden" policy, but please be aware that this may cause performance issues for large directories

{{range $idx, $pattern := .Group.UserSettings.Filters.GetFlatFilePatterns -}} diff --git a/templates/webadmin/user.html b/templates/webadmin/user.html index 3dd74174..b56f33d0 100644 --- a/templates/webadmin/user.html +++ b/templates/webadmin/user.html @@ -502,7 +502,7 @@ along with this program. If not, see .
Comma separated denied or allowed files/directories, based on shell patterns.
-

Denied entries are visible in directory listing by default, you can hide them by setting the "Hidden" policy, but please be aware that this may cause performance issues for large directories

+

Match is case insensitive, set you patterns as lowercase. Denied entries are visible in directory listing by default, you can hide them by setting the "Hidden" policy, but please be aware that this may cause performance issues for large directories

{{range $idx, $pattern := .User.Filters.GetFlatFilePatterns -}}