mirror of
https://github.com/drakkan/sftpgo.git
synced 2024-11-25 00:50:31 +00:00
file patterns: evaluate allowed filters before the denied ones
Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
parent
2238043efd
commit
f8f8962ccb
6 changed files with 165 additions and 7 deletions
2
go.mod
2
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
|
||||
|
|
4
go.sum
4
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=
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 -}}
|
||||
|
|
|
@ -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 -}}
|
||||
|
|
Loading…
Reference in a new issue