Selaa lähdekoodia

file patterns: evaluate allowed filters before the denied ones

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
Nicola Murino 2 vuotta sitten
vanhempi
commit
f8f8962ccb
6 muutettua tiedostoa jossa 165 lisäystä ja 7 poistoa
  1. 1 1
      go.mod
  2. 2 2
      go.sum
  3. 158 0
      internal/common/connection_test.go
  4. 2 2
      openapi/openapi.yaml
  5. 1 1
      templates/webadmin/group.html
  6. 1 1
      templates/webadmin/user.html

+ 1 - 1
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

+ 2 - 2
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=

+ 158 - 0
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())
+	}
+}

+ 2 - 2
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:

+ 1 - 1
templates/webadmin/group.html

@@ -222,7 +222,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
                                 </div>
                                 <div class="card-body">
                                     <h6 class="card-title mb-4">Comma separated denied or allowed files/directories, based on shell patterns.</h6>
-                                    <p class="card-text">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</p>
+                                    <p class="card-text">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</p>
                                     <div class="form-group row">
                                         <div class="col-md-12 form_field_patterns_outer">
                                             {{range $idx, $pattern := .Group.UserSettings.Filters.GetFlatFilePatterns -}}

+ 1 - 1
templates/webadmin/user.html

@@ -502,7 +502,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
                                 </div>
                                 <div class="card-body">
                                     <h6 class="card-title mb-4">Comma separated denied or allowed files/directories, based on shell patterns.</h6>
-                                    <p class="card-text">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</p>
+                                    <p class="card-text">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</p>
                                     <div class="form-group row">
                                         <div class="col-md-12 form_field_patterns_outer">
                                             {{range $idx, $pattern := .User.Filters.GetFlatFilePatterns -}}