connection_test.go 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036
  1. // Copyright (C) 2019 Nicola Murino
  2. //
  3. // This program is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU Affero General Public License as published
  5. // by the Free Software Foundation, version 3.
  6. //
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU Affero General Public License for more details.
  11. //
  12. // You should have received a copy of the GNU Affero General Public License
  13. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. package common
  15. import (
  16. "errors"
  17. "fmt"
  18. "os"
  19. "path"
  20. "path/filepath"
  21. "runtime"
  22. "testing"
  23. "time"
  24. "github.com/pkg/sftp"
  25. "github.com/rs/xid"
  26. "github.com/sftpgo/sdk"
  27. "github.com/stretchr/testify/assert"
  28. "github.com/stretchr/testify/require"
  29. "github.com/drakkan/sftpgo/v2/internal/dataprovider"
  30. "github.com/drakkan/sftpgo/v2/internal/kms"
  31. "github.com/drakkan/sftpgo/v2/internal/util"
  32. "github.com/drakkan/sftpgo/v2/internal/vfs"
  33. )
  34. var (
  35. errWalkDir = errors.New("err walk dir")
  36. )
  37. // MockOsFs mockable OsFs
  38. type MockOsFs struct {
  39. vfs.Fs
  40. hasVirtualFolders bool
  41. name string
  42. err error
  43. }
  44. // Name returns the name for the Fs implementation
  45. func (fs *MockOsFs) Name() string {
  46. if fs.name != "" {
  47. return fs.name
  48. }
  49. return "mockOsFs"
  50. }
  51. // HasVirtualFolders returns true if folders are emulated
  52. func (fs *MockOsFs) HasVirtualFolders() bool {
  53. return fs.hasVirtualFolders
  54. }
  55. func (fs *MockOsFs) IsUploadResumeSupported() bool {
  56. return !fs.hasVirtualFolders
  57. }
  58. func (fs *MockOsFs) Chtimes(_ string, _, _ time.Time, _ bool) error {
  59. return vfs.ErrVfsUnsupported
  60. }
  61. func (fs *MockOsFs) Lstat(name string) (os.FileInfo, error) {
  62. if fs.err != nil {
  63. return nil, fs.err
  64. }
  65. return fs.Fs.Lstat(name)
  66. }
  67. // Walk returns a duplicate path for testing
  68. func (fs *MockOsFs) Walk(_ string, walkFn filepath.WalkFunc) error {
  69. if fs.err == errWalkDir {
  70. walkFn("fsdpath", vfs.NewFileInfo("dpath", true, 0, time.Now(), false), nil) //nolint:errcheck
  71. return walkFn("fsdpath", vfs.NewFileInfo("dpath", true, 0, time.Now(), false), nil) //nolint:errcheck
  72. }
  73. walkFn("fsfpath", vfs.NewFileInfo("fpath", false, 0, time.Now(), false), nil) //nolint:errcheck
  74. return fs.err
  75. }
  76. func newMockOsFs(hasVirtualFolders bool, connectionID, rootDir, name string, err error) vfs.Fs {
  77. return &MockOsFs{
  78. Fs: vfs.NewOsFs(connectionID, rootDir, "", nil),
  79. name: name,
  80. hasVirtualFolders: hasVirtualFolders,
  81. err: err,
  82. }
  83. }
  84. func TestRemoveErrors(t *testing.T) {
  85. mappedPath := filepath.Join(os.TempDir(), "map")
  86. homePath := filepath.Join(os.TempDir(), "home")
  87. user := dataprovider.User{
  88. BaseUser: sdk.BaseUser{
  89. Username: "remove_errors_user",
  90. HomeDir: homePath,
  91. },
  92. VirtualFolders: []vfs.VirtualFolder{
  93. {
  94. BaseVirtualFolder: vfs.BaseVirtualFolder{
  95. Name: filepath.Base(mappedPath),
  96. MappedPath: mappedPath,
  97. },
  98. VirtualPath: "/virtualpath",
  99. },
  100. },
  101. }
  102. user.Permissions = make(map[string][]string)
  103. user.Permissions["/"] = []string{dataprovider.PermAny}
  104. fs := vfs.NewOsFs("", os.TempDir(), "", nil)
  105. conn := NewBaseConnection("", ProtocolFTP, "", "", user)
  106. err := conn.IsRemoveDirAllowed(fs, mappedPath, "/virtualpath1")
  107. if assert.Error(t, err) {
  108. assert.Contains(t, err.Error(), "permission denied")
  109. }
  110. err = conn.RemoveFile(fs, filepath.Join(homePath, "missing_file"), "/missing_file",
  111. vfs.NewFileInfo("info", false, 100, time.Now(), false))
  112. assert.Error(t, err)
  113. }
  114. func TestSetStatMode(t *testing.T) {
  115. oldSetStatMode := Config.SetstatMode
  116. Config.SetstatMode = 1
  117. fakePath := "fake path"
  118. user := dataprovider.User{
  119. BaseUser: sdk.BaseUser{
  120. HomeDir: os.TempDir(),
  121. },
  122. }
  123. user.Permissions = make(map[string][]string)
  124. user.Permissions["/"] = []string{dataprovider.PermAny}
  125. fs := newMockOsFs(true, "", user.GetHomeDir(), "", nil)
  126. conn := NewBaseConnection("", ProtocolWebDAV, "", "", user)
  127. err := conn.handleChmod(fs, fakePath, fakePath, nil)
  128. assert.NoError(t, err)
  129. err = conn.handleChown(fs, fakePath, fakePath, nil)
  130. assert.NoError(t, err)
  131. err = conn.handleChtimes(fs, fakePath, fakePath, nil)
  132. assert.NoError(t, err)
  133. Config.SetstatMode = 2
  134. err = conn.handleChmod(fs, fakePath, fakePath, nil)
  135. assert.NoError(t, err)
  136. err = conn.handleChtimes(fs, fakePath, fakePath, &StatAttributes{
  137. Atime: time.Now(),
  138. Mtime: time.Now(),
  139. })
  140. assert.NoError(t, err)
  141. Config.SetstatMode = oldSetStatMode
  142. }
  143. func TestRecursiveRenameWalkError(t *testing.T) {
  144. fs := vfs.NewOsFs("", filepath.Clean(os.TempDir()), "", nil)
  145. conn := NewBaseConnection("", ProtocolWebDAV, "", "", dataprovider.User{
  146. BaseUser: sdk.BaseUser{
  147. Permissions: map[string][]string{
  148. "/": {dataprovider.PermListItems, dataprovider.PermUpload,
  149. dataprovider.PermDownload, dataprovider.PermRenameDirs},
  150. },
  151. },
  152. })
  153. err := conn.checkRecursiveRenameDirPermissions(fs, fs, filepath.Join(os.TempDir(), "/source"),
  154. filepath.Join(os.TempDir(), "/target"), "/source", "/target",
  155. vfs.NewFileInfo("source", true, 0, time.Now(), false))
  156. assert.ErrorIs(t, err, os.ErrNotExist)
  157. fs = newMockOsFs(false, "mockID", filepath.Clean(os.TempDir()), "S3Fs", errWalkDir)
  158. err = conn.checkRecursiveRenameDirPermissions(fs, fs, filepath.Join(os.TempDir(), "/source"),
  159. filepath.Join(os.TempDir(), "/target"), "/source", "/target",
  160. vfs.NewFileInfo("source", true, 0, time.Now(), false))
  161. if assert.Error(t, err) {
  162. assert.Equal(t, err.Error(), conn.GetOpUnsupportedError().Error())
  163. }
  164. conn.User.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermUpload,
  165. dataprovider.PermDownload, dataprovider.PermRenameFiles}
  166. // no dir rename permission, the quick check path returns permission error without walking
  167. err = conn.checkRecursiveRenameDirPermissions(fs, fs, filepath.Join(os.TempDir(), "/source"),
  168. filepath.Join(os.TempDir(), "/target"), "/source", "/target",
  169. vfs.NewFileInfo("source", true, 0, time.Now(), false))
  170. if assert.Error(t, err) {
  171. assert.EqualError(t, err, conn.GetPermissionDeniedError().Error())
  172. }
  173. }
  174. func TestCrossRenameFsErrors(t *testing.T) {
  175. fs := vfs.NewOsFs("", os.TempDir(), "", nil)
  176. conn := NewBaseConnection("", ProtocolWebDAV, "", "", dataprovider.User{})
  177. res := conn.hasSpaceForCrossRename(fs, vfs.QuotaCheckResult{}, 1, "missingsource")
  178. assert.False(t, res)
  179. if runtime.GOOS != osWindows {
  180. dirPath := filepath.Join(os.TempDir(), "d")
  181. err := os.Mkdir(dirPath, os.ModePerm)
  182. assert.NoError(t, err)
  183. err = os.Chmod(dirPath, 0001)
  184. assert.NoError(t, err)
  185. res = conn.hasSpaceForCrossRename(fs, vfs.QuotaCheckResult{}, 1, dirPath)
  186. assert.False(t, res)
  187. err = os.Chmod(dirPath, os.ModePerm)
  188. assert.NoError(t, err)
  189. err = os.Remove(dirPath)
  190. assert.NoError(t, err)
  191. }
  192. }
  193. func TestRenameVirtualFolders(t *testing.T) {
  194. vdir := "/avdir"
  195. u := dataprovider.User{}
  196. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  197. BaseVirtualFolder: vfs.BaseVirtualFolder{
  198. Name: "name",
  199. MappedPath: "mappedPath",
  200. },
  201. VirtualPath: vdir,
  202. })
  203. fs := vfs.NewOsFs("", os.TempDir(), "", nil)
  204. conn := NewBaseConnection("", ProtocolFTP, "", "", u)
  205. res := conn.isRenamePermitted(fs, fs, "source", "target", vdir, "vdirtarget", nil)
  206. assert.False(t, res)
  207. }
  208. func TestRenamePerms(t *testing.T) {
  209. src := "source"
  210. target := "target"
  211. sub := "/sub"
  212. subTarget := sub + "/target"
  213. u := dataprovider.User{}
  214. u.Permissions = map[string][]string{}
  215. u.Permissions["/"] = []string{dataprovider.PermCreateDirs, dataprovider.PermUpload, dataprovider.PermCreateSymlinks,
  216. dataprovider.PermDeleteFiles}
  217. conn := NewBaseConnection("", ProtocolSFTP, "", "", u)
  218. assert.False(t, conn.hasRenamePerms(src, target, nil))
  219. u.Permissions["/"] = []string{dataprovider.PermRename}
  220. assert.True(t, conn.hasRenamePerms(src, target, nil))
  221. u.Permissions["/"] = []string{dataprovider.PermCreateDirs, dataprovider.PermUpload, dataprovider.PermDeleteFiles,
  222. dataprovider.PermDeleteDirs}
  223. assert.False(t, conn.hasRenamePerms(src, target, nil))
  224. info := vfs.NewFileInfo(src, true, 0, time.Now(), false)
  225. u.Permissions["/"] = []string{dataprovider.PermRenameFiles}
  226. assert.False(t, conn.hasRenamePerms(src, target, info))
  227. u.Permissions["/"] = []string{dataprovider.PermRenameDirs}
  228. assert.True(t, conn.hasRenamePerms(src, target, info))
  229. u.Permissions["/"] = []string{dataprovider.PermRename}
  230. assert.True(t, conn.hasRenamePerms(src, target, info))
  231. u.Permissions["/"] = []string{dataprovider.PermDownload, dataprovider.PermUpload, dataprovider.PermDeleteDirs}
  232. assert.False(t, conn.hasRenamePerms(src, target, info))
  233. // test with different permissions between source and target
  234. u.Permissions["/"] = []string{dataprovider.PermRename}
  235. u.Permissions[sub] = []string{dataprovider.PermRenameFiles}
  236. assert.False(t, conn.hasRenamePerms(src, subTarget, info))
  237. u.Permissions[sub] = []string{dataprovider.PermRenameDirs}
  238. assert.True(t, conn.hasRenamePerms(src, subTarget, info))
  239. // test files
  240. info = vfs.NewFileInfo(src, false, 0, time.Now(), false)
  241. u.Permissions["/"] = []string{dataprovider.PermRenameDirs}
  242. assert.False(t, conn.hasRenamePerms(src, target, info))
  243. u.Permissions["/"] = []string{dataprovider.PermRenameFiles}
  244. assert.True(t, conn.hasRenamePerms(src, target, info))
  245. u.Permissions["/"] = []string{dataprovider.PermRename}
  246. assert.True(t, conn.hasRenamePerms(src, target, info))
  247. // test with different permissions between source and target
  248. u.Permissions["/"] = []string{dataprovider.PermRename}
  249. u.Permissions[sub] = []string{dataprovider.PermRenameDirs}
  250. assert.False(t, conn.hasRenamePerms(src, subTarget, info))
  251. u.Permissions[sub] = []string{dataprovider.PermRenameFiles}
  252. assert.True(t, conn.hasRenamePerms(src, subTarget, info))
  253. }
  254. func TestRenameNestedFolders(t *testing.T) {
  255. u := dataprovider.User{}
  256. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  257. BaseVirtualFolder: vfs.BaseVirtualFolder{
  258. Name: "vfolder",
  259. MappedPath: filepath.Join(os.TempDir(), "f"),
  260. },
  261. VirtualPath: "/vdirs/f",
  262. })
  263. conn := NewBaseConnection("", ProtocolSFTP, "", "", u)
  264. err := conn.checkFolderRename(nil, nil, filepath.Clean(os.TempDir()), filepath.Join(os.TempDir(), "subdir"), "/src", "/dst", nil)
  265. assert.Error(t, err)
  266. err = conn.checkFolderRename(nil, nil, filepath.Join(os.TempDir(), "subdir"), filepath.Clean(os.TempDir()), "/src", "/dst", nil)
  267. assert.Error(t, err)
  268. err = conn.checkFolderRename(nil, nil, "", "", "/src/sub", "/src", nil)
  269. assert.Error(t, err)
  270. err = conn.checkFolderRename(nil, nil, filepath.Join(os.TempDir(), "src"), filepath.Join(os.TempDir(), "vdirs"), "/src", "/vdirs", nil)
  271. assert.Error(t, err)
  272. }
  273. func TestUpdateQuotaAfterRename(t *testing.T) {
  274. user := dataprovider.User{
  275. BaseUser: sdk.BaseUser{
  276. Username: userTestUsername,
  277. HomeDir: filepath.Join(os.TempDir(), "home"),
  278. },
  279. }
  280. mappedPath := filepath.Join(os.TempDir(), "vdir")
  281. user.Permissions = make(map[string][]string)
  282. user.Permissions["/"] = []string{dataprovider.PermAny}
  283. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  284. BaseVirtualFolder: vfs.BaseVirtualFolder{
  285. MappedPath: mappedPath,
  286. },
  287. VirtualPath: "/vdir",
  288. QuotaFiles: -1,
  289. QuotaSize: -1,
  290. })
  291. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  292. BaseVirtualFolder: vfs.BaseVirtualFolder{
  293. MappedPath: mappedPath,
  294. },
  295. VirtualPath: "/vdir1",
  296. QuotaFiles: -1,
  297. QuotaSize: -1,
  298. })
  299. err := os.MkdirAll(user.GetHomeDir(), os.ModePerm)
  300. assert.NoError(t, err)
  301. err = os.MkdirAll(mappedPath, os.ModePerm)
  302. assert.NoError(t, err)
  303. fs, err := user.GetFilesystem("id")
  304. assert.NoError(t, err)
  305. c := NewBaseConnection("", ProtocolSFTP, "", "", user)
  306. request := sftp.NewRequest("Rename", "/testfile")
  307. if runtime.GOOS != osWindows {
  308. request.Filepath = "/dir"
  309. request.Target = path.Join("/vdir", "dir")
  310. testDirPath := filepath.Join(mappedPath, "dir")
  311. err := os.MkdirAll(testDirPath, os.ModePerm)
  312. assert.NoError(t, err)
  313. err = os.Chmod(testDirPath, 0001)
  314. assert.NoError(t, err)
  315. err = c.updateQuotaAfterRename(fs, request.Filepath, request.Target, testDirPath, 0, -1, -1)
  316. assert.Error(t, err)
  317. err = os.Chmod(testDirPath, os.ModePerm)
  318. assert.NoError(t, err)
  319. }
  320. testFile1 := "/testfile1"
  321. request.Target = testFile1
  322. request.Filepath = path.Join("/vdir", "file")
  323. err = c.updateQuotaAfterRename(fs, request.Filepath, request.Target, filepath.Join(mappedPath, "file"), 0, -1, -1)
  324. assert.Error(t, err)
  325. err = os.WriteFile(filepath.Join(mappedPath, "file"), []byte("test content"), os.ModePerm)
  326. assert.NoError(t, err)
  327. request.Filepath = testFile1
  328. request.Target = path.Join("/vdir", "file")
  329. err = c.updateQuotaAfterRename(fs, request.Filepath, request.Target, filepath.Join(mappedPath, "file"), 12, -1, -1)
  330. assert.NoError(t, err)
  331. err = os.WriteFile(filepath.Join(user.GetHomeDir(), "testfile1"), []byte("test content"), os.ModePerm)
  332. assert.NoError(t, err)
  333. request.Target = testFile1
  334. request.Filepath = path.Join("/vdir", "file")
  335. err = c.updateQuotaAfterRename(fs, request.Filepath, request.Target, filepath.Join(mappedPath, "file"), 12, -1, -1)
  336. assert.NoError(t, err)
  337. request.Target = path.Join("/vdir1", "file")
  338. request.Filepath = path.Join("/vdir", "file")
  339. err = c.updateQuotaAfterRename(fs, request.Filepath, request.Target, filepath.Join(mappedPath, "file"), 12, -1, -1)
  340. assert.NoError(t, err)
  341. err = c.updateQuotaAfterRename(fs, request.Filepath, request.Target, filepath.Join(mappedPath, "file"), 12, 1, 100)
  342. assert.NoError(t, err)
  343. err = os.RemoveAll(mappedPath)
  344. assert.NoError(t, err)
  345. err = os.RemoveAll(user.GetHomeDir())
  346. assert.NoError(t, err)
  347. }
  348. func TestErrorsMapping(t *testing.T) {
  349. fs := vfs.NewOsFs("", os.TempDir(), "", nil)
  350. conn := NewBaseConnection("", ProtocolSFTP, "", "", dataprovider.User{BaseUser: sdk.BaseUser{HomeDir: os.TempDir()}})
  351. osErrorsProtocols := []string{ProtocolWebDAV, ProtocolFTP, ProtocolHTTP, ProtocolHTTPShare,
  352. ProtocolDataRetention, ProtocolOIDC, protocolEventAction}
  353. for _, protocol := range supportedProtocols {
  354. conn.SetProtocol(protocol)
  355. err := conn.GetFsError(fs, os.ErrNotExist)
  356. if protocol == ProtocolSFTP {
  357. assert.ErrorIs(t, err, sftp.ErrSSHFxNoSuchFile)
  358. } else if util.Contains(osErrorsProtocols, protocol) {
  359. assert.EqualError(t, err, os.ErrNotExist.Error())
  360. } else {
  361. assert.EqualError(t, err, ErrNotExist.Error())
  362. }
  363. err = conn.GetFsError(fs, os.ErrPermission)
  364. if protocol == ProtocolSFTP {
  365. assert.EqualError(t, err, sftp.ErrSSHFxPermissionDenied.Error())
  366. } else {
  367. assert.EqualError(t, err, ErrPermissionDenied.Error())
  368. }
  369. err = conn.GetFsError(fs, os.ErrClosed)
  370. if protocol == ProtocolSFTP {
  371. assert.ErrorIs(t, err, sftp.ErrSSHFxFailure)
  372. } else {
  373. assert.EqualError(t, err, ErrGenericFailure.Error())
  374. }
  375. err = conn.GetFsError(fs, ErrPermissionDenied)
  376. if protocol == ProtocolSFTP {
  377. assert.ErrorIs(t, err, sftp.ErrSSHFxFailure)
  378. } else {
  379. assert.EqualError(t, err, ErrPermissionDenied.Error())
  380. }
  381. err = conn.GetFsError(fs, vfs.ErrVfsUnsupported)
  382. if protocol == ProtocolSFTP {
  383. assert.EqualError(t, err, sftp.ErrSSHFxOpUnsupported.Error())
  384. } else {
  385. assert.EqualError(t, err, ErrOpUnsupported.Error())
  386. }
  387. err = conn.GetFsError(fs, vfs.ErrStorageSizeUnavailable)
  388. if protocol == ProtocolSFTP {
  389. assert.ErrorIs(t, err, sftp.ErrSSHFxOpUnsupported)
  390. assert.Contains(t, err.Error(), vfs.ErrStorageSizeUnavailable.Error())
  391. } else {
  392. assert.EqualError(t, err, vfs.ErrStorageSizeUnavailable.Error())
  393. }
  394. err = conn.GetQuotaExceededError()
  395. assert.True(t, conn.IsQuotaExceededError(err))
  396. err = conn.GetReadQuotaExceededError()
  397. if protocol == ProtocolSFTP {
  398. assert.ErrorIs(t, err, sftp.ErrSSHFxFailure)
  399. assert.Contains(t, err.Error(), ErrReadQuotaExceeded.Error())
  400. } else {
  401. assert.ErrorIs(t, err, ErrReadQuotaExceeded)
  402. }
  403. err = conn.GetNotExistError()
  404. assert.True(t, conn.IsNotExistError(err))
  405. err = conn.GetFsError(fs, nil)
  406. assert.NoError(t, err)
  407. err = conn.GetOpUnsupportedError()
  408. if protocol == ProtocolSFTP {
  409. assert.EqualError(t, err, sftp.ErrSSHFxOpUnsupported.Error())
  410. } else {
  411. assert.EqualError(t, err, ErrOpUnsupported.Error())
  412. }
  413. err = conn.GetFsError(fs, ErrShuttingDown)
  414. if protocol == ProtocolSFTP {
  415. assert.ErrorIs(t, err, sftp.ErrSSHFxFailure)
  416. assert.Contains(t, err.Error(), ErrShuttingDown.Error())
  417. } else {
  418. assert.EqualError(t, err, ErrShuttingDown.Error())
  419. }
  420. }
  421. }
  422. func TestMaxWriteSize(t *testing.T) {
  423. permissions := make(map[string][]string)
  424. permissions["/"] = []string{dataprovider.PermAny}
  425. user := dataprovider.User{
  426. BaseUser: sdk.BaseUser{
  427. Username: userTestUsername,
  428. Permissions: permissions,
  429. HomeDir: filepath.Clean(os.TempDir()),
  430. },
  431. }
  432. fs, err := user.GetFilesystem("123")
  433. assert.NoError(t, err)
  434. conn := NewBaseConnection("", ProtocolFTP, "", "", user)
  435. quotaResult := vfs.QuotaCheckResult{
  436. HasSpace: true,
  437. }
  438. size, err := conn.GetMaxWriteSize(quotaResult, false, 0, fs.IsUploadResumeSupported())
  439. assert.NoError(t, err)
  440. assert.Equal(t, int64(0), size)
  441. conn.User.Filters.MaxUploadFileSize = 100
  442. size, err = conn.GetMaxWriteSize(quotaResult, false, 0, fs.IsUploadResumeSupported())
  443. assert.NoError(t, err)
  444. assert.Equal(t, int64(100), size)
  445. quotaResult.QuotaSize = 1000
  446. size, err = conn.GetMaxWriteSize(quotaResult, false, 50, fs.IsUploadResumeSupported())
  447. assert.NoError(t, err)
  448. assert.Equal(t, int64(100), size)
  449. quotaResult.QuotaSize = 1000
  450. quotaResult.UsedSize = 990
  451. size, err = conn.GetMaxWriteSize(quotaResult, false, 50, fs.IsUploadResumeSupported())
  452. assert.NoError(t, err)
  453. assert.Equal(t, int64(60), size)
  454. quotaResult.QuotaSize = 0
  455. quotaResult.UsedSize = 0
  456. size, err = conn.GetMaxWriteSize(quotaResult, true, 100, fs.IsUploadResumeSupported())
  457. assert.True(t, conn.IsQuotaExceededError(err))
  458. assert.Equal(t, int64(0), size)
  459. size, err = conn.GetMaxWriteSize(quotaResult, true, 10, fs.IsUploadResumeSupported())
  460. assert.NoError(t, err)
  461. assert.Equal(t, int64(90), size)
  462. fs = newMockOsFs(true, fs.ConnectionID(), user.GetHomeDir(), "", nil)
  463. size, err = conn.GetMaxWriteSize(quotaResult, true, 100, fs.IsUploadResumeSupported())
  464. assert.EqualError(t, err, ErrOpUnsupported.Error())
  465. assert.Equal(t, int64(0), size)
  466. }
  467. func TestCheckParentDirsErrors(t *testing.T) {
  468. permissions := make(map[string][]string)
  469. permissions["/"] = []string{dataprovider.PermAny}
  470. user := dataprovider.User{
  471. BaseUser: sdk.BaseUser{
  472. Username: userTestUsername,
  473. Permissions: permissions,
  474. HomeDir: filepath.Clean(os.TempDir()),
  475. },
  476. FsConfig: vfs.Filesystem{
  477. Provider: sdk.CryptedFilesystemProvider,
  478. },
  479. }
  480. c := NewBaseConnection(xid.New().String(), ProtocolSFTP, "", "", user)
  481. err := c.CheckParentDirs("/a/dir")
  482. assert.Error(t, err)
  483. user.FsConfig.Provider = sdk.LocalFilesystemProvider
  484. user.VirtualFolders = nil
  485. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  486. BaseVirtualFolder: vfs.BaseVirtualFolder{
  487. FsConfig: vfs.Filesystem{
  488. Provider: sdk.CryptedFilesystemProvider,
  489. },
  490. },
  491. VirtualPath: "/vdir",
  492. })
  493. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  494. BaseVirtualFolder: vfs.BaseVirtualFolder{
  495. MappedPath: filepath.Clean(os.TempDir()),
  496. },
  497. VirtualPath: "/vdir/sub",
  498. })
  499. c = NewBaseConnection(xid.New().String(), ProtocolSFTP, "", "", user)
  500. err = c.CheckParentDirs("/vdir/sub/dir")
  501. assert.Error(t, err)
  502. user = dataprovider.User{
  503. BaseUser: sdk.BaseUser{
  504. Username: userTestUsername,
  505. Permissions: permissions,
  506. HomeDir: filepath.Clean(os.TempDir()),
  507. },
  508. FsConfig: vfs.Filesystem{
  509. Provider: sdk.S3FilesystemProvider,
  510. S3Config: vfs.S3FsConfig{
  511. BaseS3FsConfig: sdk.BaseS3FsConfig{
  512. Bucket: "buck",
  513. Region: "us-east-1",
  514. AccessKey: "key",
  515. },
  516. AccessSecret: kms.NewPlainSecret("s3secret"),
  517. },
  518. },
  519. }
  520. c = NewBaseConnection(xid.New().String(), ProtocolSFTP, "", "", user)
  521. err = c.CheckParentDirs("/a/dir")
  522. assert.NoError(t, err)
  523. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  524. BaseVirtualFolder: vfs.BaseVirtualFolder{
  525. MappedPath: filepath.Clean(os.TempDir()),
  526. },
  527. VirtualPath: "/local/dir",
  528. })
  529. c = NewBaseConnection(xid.New().String(), ProtocolSFTP, "", "", user)
  530. err = c.CheckParentDirs("/local/dir/sub-dir")
  531. assert.NoError(t, err)
  532. err = os.RemoveAll(filepath.Join(os.TempDir(), "sub-dir"))
  533. assert.NoError(t, err)
  534. }
  535. func TestErrorResolvePath(t *testing.T) {
  536. u := dataprovider.User{
  537. BaseUser: sdk.BaseUser{
  538. HomeDir: filepath.Join(os.TempDir(), "u"),
  539. Status: 1,
  540. Permissions: map[string][]string{
  541. "/": {dataprovider.PermAny},
  542. },
  543. },
  544. }
  545. u.FsConfig.Provider = sdk.GCSFilesystemProvider
  546. u.FsConfig.GCSConfig.Bucket = "test"
  547. u.FsConfig.GCSConfig.Credentials = kms.NewPlainSecret("invalid JSON for credentials")
  548. u.VirtualFolders = []vfs.VirtualFolder{
  549. {
  550. BaseVirtualFolder: vfs.BaseVirtualFolder{
  551. Name: "f",
  552. MappedPath: filepath.Join(os.TempDir(), "f"),
  553. },
  554. VirtualPath: "/f",
  555. },
  556. }
  557. conn := NewBaseConnection("", ProtocolSFTP, "", "", u)
  558. err := conn.doRecursiveRemoveDirEntry("/vpath", nil)
  559. assert.Error(t, err)
  560. err = conn.checkCopy(vfs.NewFileInfo("name", true, 0, time.Unix(0, 0), false), nil, "/source", "/target")
  561. assert.Error(t, err)
  562. sourceFile := filepath.Join(os.TempDir(), "f", "source")
  563. err = os.MkdirAll(filepath.Dir(sourceFile), os.ModePerm)
  564. assert.NoError(t, err)
  565. err = os.WriteFile(sourceFile, []byte(""), 0666)
  566. assert.NoError(t, err)
  567. err = conn.checkCopy(vfs.NewFileInfo("name", true, 0, time.Unix(0, 0), false), nil, "/f/source", "/target")
  568. assert.Error(t, err)
  569. err = conn.checkCopy(vfs.NewFileInfo("source", false, 0, time.Unix(0, 0), false), vfs.NewFileInfo("target", true, 0, time.Unix(0, 0), false), "/f/source", "/f/target")
  570. assert.Error(t, err)
  571. err = os.RemoveAll(filepath.Dir(sourceFile))
  572. assert.NoError(t, err)
  573. }
  574. func TestConnectionKeepAlive(t *testing.T) {
  575. conn := NewBaseConnection("", ProtocolWebDAV, "", "", dataprovider.User{})
  576. lastActivity := conn.GetLastActivity()
  577. done := make(chan bool)
  578. go func() {
  579. time.Sleep(200 * time.Millisecond)
  580. close(done)
  581. }()
  582. keepConnectionAlive(conn, done, 50*time.Millisecond)
  583. assert.Greater(t, conn.GetLastActivity(), lastActivity)
  584. }
  585. func TestFsFileCopier(t *testing.T) {
  586. fs := vfs.Fs(&vfs.AzureBlobFs{})
  587. _, ok := fs.(vfs.FsFileCopier)
  588. assert.True(t, ok)
  589. fs = vfs.Fs(&vfs.OsFs{})
  590. _, ok = fs.(vfs.FsFileCopier)
  591. assert.False(t, ok)
  592. fs = vfs.Fs(&vfs.SFTPFs{})
  593. _, ok = fs.(vfs.FsFileCopier)
  594. assert.False(t, ok)
  595. fs = vfs.Fs(&vfs.GCSFs{})
  596. _, ok = fs.(vfs.FsFileCopier)
  597. assert.True(t, ok)
  598. fs = vfs.Fs(&vfs.S3Fs{})
  599. _, ok = fs.(vfs.FsFileCopier)
  600. assert.True(t, ok)
  601. }
  602. func TestFilePatterns(t *testing.T) {
  603. filters := dataprovider.UserFilters{
  604. BaseUserFilters: sdk.BaseUserFilters{
  605. FilePatterns: []sdk.PatternsFilter{
  606. {
  607. Path: "/dir1",
  608. DenyPolicy: sdk.DenyPolicyDefault,
  609. AllowedPatterns: []string{"*.jpg"},
  610. },
  611. {
  612. Path: "/dir2",
  613. DenyPolicy: sdk.DenyPolicyHide,
  614. AllowedPatterns: []string{"*.jpg"},
  615. },
  616. {
  617. Path: "/dir3",
  618. DenyPolicy: sdk.DenyPolicyDefault,
  619. DeniedPatterns: []string{"*.jpg"},
  620. },
  621. {
  622. Path: "/dir4",
  623. DenyPolicy: sdk.DenyPolicyHide,
  624. DeniedPatterns: []string{"*"},
  625. },
  626. },
  627. },
  628. }
  629. virtualFolders := []vfs.VirtualFolder{
  630. {
  631. VirtualPath: "/dir1/vdir1",
  632. },
  633. {
  634. VirtualPath: "/dir1/vdir2",
  635. },
  636. {
  637. VirtualPath: "/dir1/vdir3",
  638. },
  639. {
  640. VirtualPath: "/dir2/vdir1",
  641. },
  642. {
  643. VirtualPath: "/dir2/vdir2",
  644. },
  645. {
  646. VirtualPath: "/dir2/vdir3.jpg",
  647. },
  648. }
  649. user := dataprovider.User{
  650. Filters: filters,
  651. VirtualFolders: virtualFolders,
  652. }
  653. dirContents := []os.FileInfo{
  654. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  655. vfs.NewFileInfo("file1.jpg", false, 123, time.Now(), false),
  656. }
  657. // dirContents are modified in place, we need to redefine them each time
  658. filtered := user.FilterListDir(dirContents, "/dir1")
  659. assert.Len(t, filtered, 5)
  660. dirContents = []os.FileInfo{
  661. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  662. vfs.NewFileInfo("file1.jpg", false, 123, time.Now(), false),
  663. }
  664. filtered = user.FilterListDir(dirContents, "/dir1/vdir1")
  665. assert.Len(t, filtered, 2)
  666. dirContents = []os.FileInfo{
  667. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  668. vfs.NewFileInfo("file1.jpg", false, 123, time.Now(), false),
  669. }
  670. filtered = user.FilterListDir(dirContents, "/dir2/vdir2")
  671. require.Len(t, filtered, 1)
  672. assert.Equal(t, "file1.jpg", filtered[0].Name())
  673. dirContents = []os.FileInfo{
  674. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  675. vfs.NewFileInfo("file1.jpg", false, 123, time.Now(), false),
  676. }
  677. filtered = user.FilterListDir(dirContents, "/dir2/vdir2/sub")
  678. require.Len(t, filtered, 1)
  679. assert.Equal(t, "file1.jpg", filtered[0].Name())
  680. res, _ := user.IsFileAllowed("/dir1/vdir1/file.txt")
  681. assert.False(t, res)
  682. res, _ = user.IsFileAllowed("/dir1/vdir1/sub/file.txt")
  683. assert.False(t, res)
  684. res, _ = user.IsFileAllowed("/dir1/vdir1/file.jpg")
  685. assert.True(t, res)
  686. res, _ = user.IsFileAllowed("/dir1/vdir1/sub/file.jpg")
  687. assert.True(t, res)
  688. res, _ = user.IsFileAllowed("/dir3/file.jpg")
  689. assert.False(t, res)
  690. res, _ = user.IsFileAllowed("/dir3/dir1/file.jpg")
  691. assert.False(t, res)
  692. res, _ = user.IsFileAllowed("/dir3/dir1/sub/file.jpg")
  693. assert.False(t, res)
  694. res, _ = user.IsFileAllowed("/dir4/file.jpg")
  695. assert.False(t, res)
  696. res, _ = user.IsFileAllowed("/dir4/dir1/sub/file.jpg")
  697. assert.False(t, res)
  698. dirContents = []os.FileInfo{
  699. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  700. vfs.NewFileInfo("file1.jpg", false, 123, time.Now(), false),
  701. }
  702. filtered = user.FilterListDir(dirContents, "/dir4")
  703. require.Len(t, filtered, 0)
  704. dirContents = []os.FileInfo{
  705. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  706. vfs.NewFileInfo("file1.jpg", false, 123, time.Now(), false),
  707. }
  708. filtered = user.FilterListDir(dirContents, "/dir4/vdir2/sub")
  709. require.Len(t, filtered, 0)
  710. dirContents = []os.FileInfo{
  711. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  712. vfs.NewFileInfo("file1.jpg", false, 123, time.Now(), false),
  713. }
  714. filtered = user.FilterListDir(dirContents, "/dir2")
  715. assert.Len(t, filtered, 2)
  716. dirContents = []os.FileInfo{
  717. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  718. vfs.NewFileInfo("file1.jpg", false, 123, time.Now(), false),
  719. }
  720. filtered = user.FilterListDir(dirContents, "/dir4")
  721. assert.Len(t, filtered, 0)
  722. dirContents = []os.FileInfo{
  723. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  724. vfs.NewFileInfo("file1.jpg", false, 123, time.Now(), false),
  725. }
  726. filtered = user.FilterListDir(dirContents, "/dir4/sub")
  727. assert.Len(t, filtered, 0)
  728. dirContents = []os.FileInfo{
  729. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  730. vfs.NewFileInfo("vdir3.jpg", false, 123, time.Now(), false),
  731. }
  732. filtered = user.FilterListDir(dirContents, "/dir1")
  733. assert.Len(t, filtered, 5)
  734. filtered = user.FilterListDir(dirContents, "/dir2")
  735. if assert.Len(t, filtered, 1) {
  736. assert.True(t, filtered[0].IsDir())
  737. }
  738. user.VirtualFolders = nil
  739. dirContents = []os.FileInfo{
  740. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  741. vfs.NewFileInfo("vdir3.jpg", false, 123, time.Now(), false),
  742. }
  743. filtered = user.FilterListDir(dirContents, "/dir1")
  744. assert.Len(t, filtered, 2)
  745. dirContents = []os.FileInfo{
  746. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  747. vfs.NewFileInfo("vdir3.jpg", false, 123, time.Now(), false),
  748. }
  749. filtered = user.FilterListDir(dirContents, "/dir2")
  750. if assert.Len(t, filtered, 1) {
  751. assert.False(t, filtered[0].IsDir())
  752. }
  753. dirContents = []os.FileInfo{
  754. vfs.NewFileInfo("file1.jpg", false, 123, time.Now(), false),
  755. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  756. vfs.NewFileInfo("file2.txt", false, 123, time.Now(), false),
  757. vfs.NewFileInfo("vdir3.jpg", false, 123, time.Now(), false),
  758. }
  759. filtered = user.FilterListDir(dirContents, "/dir2")
  760. if assert.Len(t, filtered, 2) {
  761. assert.False(t, filtered[0].IsDir())
  762. assert.False(t, filtered[1].IsDir())
  763. }
  764. user.VirtualFolders = virtualFolders
  765. user.Filters = filters
  766. filtered = user.FilterListDir(nil, "/dir1")
  767. assert.Len(t, filtered, 3)
  768. filtered = user.FilterListDir(nil, "/dir2")
  769. assert.Len(t, filtered, 1)
  770. dirContents = []os.FileInfo{
  771. vfs.NewFileInfo("file1.jPg", false, 123, time.Now(), false),
  772. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  773. vfs.NewFileInfo("file2.txt", false, 123, time.Now(), false),
  774. vfs.NewFileInfo("vdir3.jpg", false, 456, time.Now(), false),
  775. }
  776. filtered = user.FilterListDir(dirContents, "/dir2")
  777. assert.Len(t, filtered, 2)
  778. user = dataprovider.User{
  779. Filters: dataprovider.UserFilters{
  780. BaseUserFilters: sdk.BaseUserFilters{
  781. FilePatterns: []sdk.PatternsFilter{
  782. {
  783. Path: "/dir3",
  784. AllowedPatterns: []string{"ic35"},
  785. DeniedPatterns: []string{"*"},
  786. DenyPolicy: sdk.DenyPolicyHide,
  787. },
  788. },
  789. },
  790. },
  791. }
  792. dirContents = []os.FileInfo{
  793. vfs.NewFileInfo("file1.jpg", false, 123, time.Now(), false),
  794. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  795. vfs.NewFileInfo("file2.txt", false, 123, time.Now(), false),
  796. vfs.NewFileInfo("vdir3.jpg", false, 456, time.Now(), false),
  797. }
  798. filtered = user.FilterListDir(dirContents, "/dir3")
  799. assert.Len(t, filtered, 0)
  800. dirContents = nil
  801. for i := 0; i < 100; i++ {
  802. dirContents = append(dirContents, vfs.NewFileInfo(fmt.Sprintf("ic%02d", i), i%2 == 0, int64(i), time.Now(), false))
  803. }
  804. dirContents = append(dirContents, vfs.NewFileInfo("ic350", false, 123, time.Now(), false))
  805. dirContents = append(dirContents, vfs.NewFileInfo(".ic35", false, 123, time.Now(), false))
  806. dirContents = append(dirContents, vfs.NewFileInfo("ic35.", false, 123, time.Now(), false))
  807. dirContents = append(dirContents, vfs.NewFileInfo("*ic35", false, 123, time.Now(), false))
  808. dirContents = append(dirContents, vfs.NewFileInfo("ic35*", false, 123, time.Now(), false))
  809. dirContents = append(dirContents, vfs.NewFileInfo("ic35.*", false, 123, time.Now(), false))
  810. dirContents = append(dirContents, vfs.NewFileInfo("file.jpg", false, 123, time.Now(), false))
  811. filtered = user.FilterListDir(dirContents, "/dir3")
  812. require.Len(t, filtered, 1)
  813. assert.Equal(t, "ic35", filtered[0].Name())
  814. dirContents = []os.FileInfo{
  815. vfs.NewFileInfo("file1.jpg", false, 123, time.Now(), false),
  816. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  817. vfs.NewFileInfo("file2.txt", false, 123, time.Now(), false),
  818. }
  819. filtered = user.FilterListDir(dirContents, "/dir3/ic36")
  820. require.Len(t, filtered, 0)
  821. dirContents = []os.FileInfo{
  822. vfs.NewFileInfo("file1.jpg", false, 123, time.Now(), false),
  823. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  824. vfs.NewFileInfo("file2.txt", false, 123, time.Now(), false),
  825. }
  826. filtered = user.FilterListDir(dirContents, "/dir3/ic35")
  827. require.Len(t, filtered, 3)
  828. dirContents = []os.FileInfo{
  829. vfs.NewFileInfo("file1.jpg", false, 123, time.Now(), false),
  830. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  831. vfs.NewFileInfo("file2.txt", false, 123, time.Now(), false),
  832. }
  833. filtered = user.FilterListDir(dirContents, "/dir3/ic35/sub")
  834. require.Len(t, filtered, 3)
  835. res, _ = user.IsFileAllowed("/dir3/file.txt")
  836. assert.False(t, res)
  837. res, _ = user.IsFileAllowed("/dir3/ic35a")
  838. assert.False(t, res)
  839. res, policy := user.IsFileAllowed("/dir3/ic35a/file")
  840. assert.False(t, res)
  841. assert.Equal(t, sdk.DenyPolicyHide, policy)
  842. res, _ = user.IsFileAllowed("/dir3/ic35")
  843. assert.True(t, res)
  844. res, _ = user.IsFileAllowed("/dir3/ic35/file.jpg")
  845. assert.True(t, res)
  846. res, _ = user.IsFileAllowed("/dir3/ic35/file.txt")
  847. assert.True(t, res)
  848. res, _ = user.IsFileAllowed("/dir3/ic35/sub/file.txt")
  849. assert.True(t, res)
  850. dirContents = []os.FileInfo{
  851. vfs.NewFileInfo("file1.jpg", false, 123, time.Now(), false),
  852. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  853. vfs.NewFileInfo("file2.txt", false, 123, time.Now(), false),
  854. }
  855. filtered = user.FilterListDir(dirContents, "/dir3/ic35/sub")
  856. require.Len(t, filtered, 3)
  857. user.Filters.FilePatterns = append(user.Filters.FilePatterns, sdk.PatternsFilter{
  858. Path: "/dir3/ic35/sub1",
  859. AllowedPatterns: []string{"*.jpg"},
  860. DenyPolicy: sdk.DenyPolicyDefault,
  861. })
  862. user.Filters.FilePatterns = append(user.Filters.FilePatterns, sdk.PatternsFilter{
  863. Path: "/dir3/ic35/sub2",
  864. DeniedPatterns: []string{"*.jpg"},
  865. DenyPolicy: sdk.DenyPolicyHide,
  866. })
  867. dirContents = []os.FileInfo{
  868. vfs.NewFileInfo("file1.jpg", false, 123, time.Now(), false),
  869. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  870. vfs.NewFileInfo("file2.txt", false, 123, time.Now(), false),
  871. }
  872. filtered = user.FilterListDir(dirContents, "/dir3/ic35/sub1")
  873. require.Len(t, filtered, 3)
  874. dirContents = []os.FileInfo{
  875. vfs.NewFileInfo("file1.jpg", false, 123, time.Now(), false),
  876. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  877. vfs.NewFileInfo("file2.txt", false, 123, time.Now(), false),
  878. }
  879. filtered = user.FilterListDir(dirContents, "/dir3/ic35/sub2")
  880. require.Len(t, filtered, 2)
  881. dirContents = []os.FileInfo{
  882. vfs.NewFileInfo("file1.jpg", false, 123, time.Now(), false),
  883. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  884. vfs.NewFileInfo("file2.txt", false, 123, time.Now(), false),
  885. }
  886. filtered = user.FilterListDir(dirContents, "/dir3/ic35/sub2/sub1")
  887. require.Len(t, filtered, 2)
  888. res, _ = user.IsFileAllowed("/dir3/ic35/file.jpg")
  889. assert.True(t, res)
  890. res, _ = user.IsFileAllowed("/dir3/ic35/file.txt")
  891. assert.True(t, res)
  892. res, _ = user.IsFileAllowed("/dir3/ic35/sub/dir/file.txt")
  893. assert.True(t, res)
  894. res, _ = user.IsFileAllowed("/dir3/ic35/sub/dir/file.jpg")
  895. assert.True(t, res)
  896. res, _ = user.IsFileAllowed("/dir3/ic35/sub1/file.jpg")
  897. assert.True(t, res)
  898. res, _ = user.IsFileAllowed("/dir3/ic35/sub1/file.txt")
  899. assert.False(t, res)
  900. res, _ = user.IsFileAllowed("/dir3/ic35/sub1/sub/file.jpg")
  901. assert.True(t, res)
  902. res, _ = user.IsFileAllowed("/dir3/ic35/sub1/sub2/file.txt")
  903. assert.False(t, res)
  904. res, _ = user.IsFileAllowed("/dir3/ic35/sub2/file.jpg")
  905. assert.False(t, res)
  906. res, _ = user.IsFileAllowed("/dir3/ic35/sub2/file.txt")
  907. assert.True(t, res)
  908. res, _ = user.IsFileAllowed("/dir3/ic35/sub2/sub/file.jpg")
  909. assert.False(t, res)
  910. res, _ = user.IsFileAllowed("/dir3/ic35/sub2/sub1/file.txt")
  911. assert.True(t, res)
  912. user.Filters.FilePatterns = append(user.Filters.FilePatterns, sdk.PatternsFilter{
  913. Path: "/dir3/ic35",
  914. DeniedPatterns: []string{"*.txt"},
  915. DenyPolicy: sdk.DenyPolicyHide,
  916. })
  917. res, _ = user.IsFileAllowed("/dir3/ic35/file.jpg")
  918. assert.True(t, res)
  919. res, _ = user.IsFileAllowed("/dir3/ic35/file.txt")
  920. assert.False(t, res)
  921. res, _ = user.IsFileAllowed("/dir3/ic35/adir/sub/file.jpg")
  922. assert.True(t, res)
  923. res, _ = user.IsFileAllowed("/dir3/ic35/adir/file.txt")
  924. assert.False(t, res)
  925. res, _ = user.IsFileAllowed("/dir3/ic35/sub2/file.jpg")
  926. assert.False(t, res)
  927. res, _ = user.IsFileAllowed("/dir3/ic35/sub2/file.txt")
  928. assert.True(t, res)
  929. res, _ = user.IsFileAllowed("/dir3/ic35/sub2/sub/file.jpg")
  930. assert.False(t, res)
  931. res, _ = user.IsFileAllowed("/dir3/ic35/sub2/sub1/file.txt")
  932. assert.True(t, res)
  933. dirContents = []os.FileInfo{
  934. vfs.NewFileInfo("file1.jpg", false, 123, time.Now(), false),
  935. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  936. vfs.NewFileInfo("file2.txt", false, 123, time.Now(), false),
  937. }
  938. filtered = user.FilterListDir(dirContents, "/dir3/ic35")
  939. require.Len(t, filtered, 1)
  940. dirContents = []os.FileInfo{
  941. vfs.NewFileInfo("file1.jpg", false, 123, time.Now(), false),
  942. vfs.NewFileInfo("file1.txt", false, 123, time.Now(), false),
  943. vfs.NewFileInfo("file2.txt", false, 123, time.Now(), false),
  944. }
  945. filtered = user.FilterListDir(dirContents, "/dir3/ic35/abc")
  946. require.Len(t, filtered, 1)
  947. }