connection_test.go 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237
  1. package common
  2. import (
  3. "io/ioutil"
  4. "os"
  5. "path"
  6. "path/filepath"
  7. "runtime"
  8. "testing"
  9. "time"
  10. "github.com/pkg/sftp"
  11. "github.com/stretchr/testify/assert"
  12. "github.com/stretchr/testify/require"
  13. "github.com/drakkan/sftpgo/dataprovider"
  14. "github.com/drakkan/sftpgo/vfs"
  15. )
  16. // MockOsFs mockable OsFs
  17. type MockOsFs struct {
  18. vfs.Fs
  19. hasVirtualFolders bool
  20. }
  21. // Name returns the name for the Fs implementation
  22. func (fs MockOsFs) Name() string {
  23. return "mockOsFs"
  24. }
  25. // HasVirtualFolders returns true if folders are emulated
  26. func (fs MockOsFs) HasVirtualFolders() bool {
  27. return fs.hasVirtualFolders
  28. }
  29. func (fs MockOsFs) IsUploadResumeSupported() bool {
  30. return !fs.hasVirtualFolders
  31. }
  32. func newMockOsFs(hasVirtualFolders bool, connectionID, rootDir string) vfs.Fs {
  33. return &MockOsFs{
  34. Fs: vfs.NewOsFs(connectionID, rootDir, nil),
  35. hasVirtualFolders: hasVirtualFolders,
  36. }
  37. }
  38. func TestListDir(t *testing.T) {
  39. user := dataprovider.User{
  40. Username: userTestUsername,
  41. HomeDir: filepath.Join(os.TempDir(), "home"),
  42. }
  43. mappedPath := filepath.Join(os.TempDir(), "vdir")
  44. user.Permissions = make(map[string][]string)
  45. user.Permissions["/"] = []string{dataprovider.PermUpload}
  46. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  47. BaseVirtualFolder: vfs.BaseVirtualFolder{
  48. MappedPath: mappedPath,
  49. },
  50. VirtualPath: "/vdir",
  51. })
  52. err := os.Mkdir(user.GetHomeDir(), os.ModePerm)
  53. assert.NoError(t, err)
  54. fs, err := user.GetFilesystem("")
  55. assert.NoError(t, err)
  56. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  57. _, err = c.ListDir(user.GetHomeDir(), "/")
  58. if assert.Error(t, err) {
  59. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  60. }
  61. c.User.Permissions["/"] = []string{dataprovider.PermAny}
  62. files, err := c.ListDir(user.GetHomeDir(), "/")
  63. if assert.NoError(t, err) {
  64. vdirFound := false
  65. for _, f := range files {
  66. if f.Name() == "vdir" {
  67. vdirFound = true
  68. break
  69. }
  70. }
  71. assert.True(t, vdirFound)
  72. }
  73. _, err = c.ListDir(mappedPath, "/vdir")
  74. assert.Error(t, err)
  75. err = os.RemoveAll(user.GetHomeDir())
  76. assert.NoError(t, err)
  77. }
  78. func TestCreateDir(t *testing.T) {
  79. user := dataprovider.User{
  80. Username: userTestUsername,
  81. HomeDir: filepath.Join(os.TempDir(), "home"),
  82. }
  83. mappedPath := filepath.Join(os.TempDir(), "vdir")
  84. user.Permissions = make(map[string][]string)
  85. user.Permissions["/"] = []string{dataprovider.PermAny}
  86. user.Permissions["/sub"] = []string{dataprovider.PermListItems}
  87. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  88. BaseVirtualFolder: vfs.BaseVirtualFolder{
  89. MappedPath: mappedPath,
  90. },
  91. VirtualPath: "/vdir",
  92. })
  93. err := os.Mkdir(user.GetHomeDir(), os.ModePerm)
  94. assert.NoError(t, err)
  95. fs, err := user.GetFilesystem("")
  96. assert.NoError(t, err)
  97. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  98. err = c.CreateDir("", "/sub/dir")
  99. if assert.Error(t, err) {
  100. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  101. }
  102. err = c.CreateDir("", "/vdir")
  103. if assert.Error(t, err) {
  104. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  105. }
  106. err = c.CreateDir(filepath.Join(mappedPath, "adir"), "/vdir/adir")
  107. assert.Error(t, err)
  108. err = c.CreateDir(filepath.Join(user.GetHomeDir(), "dir"), "/dir")
  109. assert.NoError(t, err)
  110. err = os.RemoveAll(user.GetHomeDir())
  111. assert.NoError(t, err)
  112. }
  113. func TestRemoveFile(t *testing.T) {
  114. user := dataprovider.User{
  115. Username: userTestUsername,
  116. HomeDir: filepath.Join(os.TempDir(), "home"),
  117. }
  118. mappedPath := filepath.Join(os.TempDir(), "vdir")
  119. user.Permissions = make(map[string][]string)
  120. user.Permissions["/"] = []string{dataprovider.PermAny}
  121. user.Permissions["/sub"] = []string{dataprovider.PermListItems}
  122. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  123. BaseVirtualFolder: vfs.BaseVirtualFolder{
  124. MappedPath: mappedPath,
  125. },
  126. VirtualPath: "/vdir",
  127. QuotaFiles: -1,
  128. QuotaSize: -1,
  129. })
  130. user.Filters.FileExtensions = []dataprovider.ExtensionsFilter{
  131. {
  132. Path: "/p",
  133. AllowedExtensions: []string{},
  134. DeniedExtensions: []string{".zip"},
  135. },
  136. }
  137. err := os.Mkdir(user.GetHomeDir(), os.ModePerm)
  138. assert.NoError(t, err)
  139. err = os.Mkdir(mappedPath, os.ModePerm)
  140. assert.NoError(t, err)
  141. fs, err := user.GetFilesystem("")
  142. assert.NoError(t, err)
  143. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  144. err = c.RemoveFile("", "/sub/file", nil)
  145. if assert.Error(t, err) {
  146. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  147. }
  148. err = c.RemoveFile("", "/p/file.zip", nil)
  149. if assert.Error(t, err) {
  150. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  151. }
  152. testFile := filepath.Join(mappedPath, "afile")
  153. err = ioutil.WriteFile(testFile, []byte("test data"), os.ModePerm)
  154. assert.NoError(t, err)
  155. info, err := os.Stat(testFile)
  156. assert.NoError(t, err)
  157. err = c.RemoveFile(filepath.Join(user.GetHomeDir(), "missing"), "/missing", info)
  158. assert.Error(t, err)
  159. err = c.RemoveFile(testFile, "/vdir/afile", info)
  160. assert.NoError(t, err)
  161. err = os.RemoveAll(mappedPath)
  162. assert.NoError(t, err)
  163. err = os.RemoveAll(user.GetHomeDir())
  164. assert.NoError(t, err)
  165. }
  166. func TestRemoveDir(t *testing.T) {
  167. user := dataprovider.User{
  168. Username: userTestUsername,
  169. HomeDir: filepath.Join(os.TempDir(), "home"),
  170. }
  171. mappedPath := filepath.Join(os.TempDir(), "vdir")
  172. user.Permissions = make(map[string][]string)
  173. user.Permissions["/"] = []string{dataprovider.PermAny}
  174. user.Permissions["/sub"] = []string{dataprovider.PermListItems}
  175. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  176. BaseVirtualFolder: vfs.BaseVirtualFolder{
  177. MappedPath: mappedPath,
  178. },
  179. VirtualPath: "/adir/vdir",
  180. })
  181. err := os.Mkdir(user.GetHomeDir(), os.ModePerm)
  182. assert.NoError(t, err)
  183. err = os.Mkdir(mappedPath, os.ModePerm)
  184. assert.NoError(t, err)
  185. fs, err := user.GetFilesystem("")
  186. assert.NoError(t, err)
  187. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  188. err = c.RemoveDir(user.GetHomeDir(), "/")
  189. if assert.Error(t, err) {
  190. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  191. }
  192. err = c.RemoveDir(mappedPath, "/adir/vdir")
  193. if assert.Error(t, err) {
  194. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  195. }
  196. err = c.RemoveDir(mappedPath, "/adir")
  197. if assert.Error(t, err) {
  198. assert.EqualError(t, err, c.GetOpUnsupportedError().Error())
  199. }
  200. err = c.RemoveDir(mappedPath, "/adir/dir")
  201. if assert.Error(t, err) {
  202. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  203. }
  204. err = c.RemoveDir(filepath.Join(user.GetHomeDir(), "/sub/dir"), "/sub/dir")
  205. if assert.Error(t, err) {
  206. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  207. }
  208. testDir := filepath.Join(user.GetHomeDir(), "testDir")
  209. err = c.RemoveDir(testDir, "testDir")
  210. assert.Error(t, err)
  211. err = ioutil.WriteFile(testDir, []byte("data"), os.ModePerm)
  212. assert.NoError(t, err)
  213. err = c.RemoveDir(testDir, "testDir")
  214. if assert.Error(t, err) {
  215. assert.EqualError(t, err, c.GetGenericError(err).Error())
  216. }
  217. err = os.Remove(testDir)
  218. assert.NoError(t, err)
  219. testDirSub := filepath.Join(testDir, "sub")
  220. err = os.MkdirAll(testDirSub, os.ModePerm)
  221. assert.NoError(t, err)
  222. err = c.RemoveDir(testDir, "/testDir")
  223. assert.Error(t, err)
  224. err = os.RemoveAll(testDirSub)
  225. assert.NoError(t, err)
  226. err = c.RemoveDir(testDir, "/testDir")
  227. assert.NoError(t, err)
  228. err = c.RemoveDir(testDir, "/testDir")
  229. assert.Error(t, err)
  230. fs = newMockOsFs(true, "", user.GetHomeDir())
  231. c.Fs = fs
  232. err = c.RemoveDir(testDir, "/testDir")
  233. assert.NoError(t, err)
  234. err = os.RemoveAll(mappedPath)
  235. assert.NoError(t, err)
  236. err = os.RemoveAll(user.GetHomeDir())
  237. assert.NoError(t, err)
  238. }
  239. func TestRename(t *testing.T) {
  240. user := dataprovider.User{
  241. Username: userTestUsername,
  242. HomeDir: filepath.Join(os.TempDir(), "home"),
  243. QuotaSize: 10485760,
  244. }
  245. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  246. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  247. user.Permissions = make(map[string][]string)
  248. user.Permissions["/"] = []string{dataprovider.PermAny}
  249. user.Permissions["/sub"] = []string{dataprovider.PermListItems}
  250. user.Permissions["/sub1"] = []string{dataprovider.PermRename}
  251. user.Permissions["/dir"] = []string{dataprovider.PermListItems}
  252. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  253. BaseVirtualFolder: vfs.BaseVirtualFolder{
  254. MappedPath: mappedPath1,
  255. },
  256. VirtualPath: "/vdir1/sub",
  257. QuotaFiles: -1,
  258. QuotaSize: -1,
  259. })
  260. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  261. BaseVirtualFolder: vfs.BaseVirtualFolder{
  262. MappedPath: mappedPath2,
  263. },
  264. VirtualPath: "/vdir2",
  265. QuotaFiles: -1,
  266. QuotaSize: -1,
  267. })
  268. err := os.MkdirAll(filepath.Join(user.GetHomeDir(), "sub"), os.ModePerm)
  269. assert.NoError(t, err)
  270. err = os.MkdirAll(filepath.Join(user.GetHomeDir(), "dir", "sub"), os.ModePerm)
  271. assert.NoError(t, err)
  272. err = os.Mkdir(mappedPath1, os.ModePerm)
  273. assert.NoError(t, err)
  274. err = os.Mkdir(mappedPath2, os.ModePerm)
  275. assert.NoError(t, err)
  276. fs, err := user.GetFilesystem("")
  277. assert.NoError(t, err)
  278. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  279. err = c.Rename(mappedPath1, "", "", "")
  280. if assert.Error(t, err) {
  281. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  282. }
  283. err = c.Rename("", mappedPath2, "", "")
  284. if assert.Error(t, err) {
  285. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  286. }
  287. err = c.Rename("missing", "", "", "")
  288. assert.Error(t, err)
  289. testFile := filepath.Join(user.GetHomeDir(), "file")
  290. err = ioutil.WriteFile(testFile, []byte("data"), os.ModePerm)
  291. assert.NoError(t, err)
  292. testSubFile := filepath.Join(user.GetHomeDir(), "sub", "file")
  293. err = ioutil.WriteFile(testSubFile, []byte("data"), os.ModePerm)
  294. assert.NoError(t, err)
  295. err = c.Rename(testSubFile, filepath.Join(user.GetHomeDir(), "file"), "/sub/file", "/file")
  296. if assert.Error(t, err) {
  297. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  298. }
  299. err = c.Rename(testFile, filepath.Join(user.GetHomeDir(), "sub"), "/file", "/sub")
  300. if assert.Error(t, err) {
  301. assert.EqualError(t, err, c.GetOpUnsupportedError().Error())
  302. }
  303. err = c.Rename(testSubFile, testFile, "/file", "/sub1/file")
  304. if assert.Error(t, err) {
  305. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  306. }
  307. err = c.Rename(filepath.Join(user.GetHomeDir(), "sub"), filepath.Join(user.GetHomeDir(), "adir"), "/vdir1", "/adir")
  308. if assert.Error(t, err) {
  309. assert.EqualError(t, err, c.GetOpUnsupportedError().Error())
  310. }
  311. err = c.Rename(filepath.Join(user.GetHomeDir(), "dir"), filepath.Join(user.GetHomeDir(), "adir"), "/dir", "/adir")
  312. if assert.Error(t, err) {
  313. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  314. }
  315. err = os.MkdirAll(filepath.Join(user.GetHomeDir(), "testdir"), os.ModePerm)
  316. assert.NoError(t, err)
  317. err = c.Rename(filepath.Join(user.GetHomeDir(), "testdir"), filepath.Join(user.GetHomeDir(), "tdir", "sub"), "/testdir", "/tdir/sub")
  318. assert.Error(t, err)
  319. err = os.Remove(testSubFile)
  320. assert.NoError(t, err)
  321. err = c.Rename(filepath.Join(user.GetHomeDir(), "sub"), filepath.Join(user.GetHomeDir(), "adir"), "/sub", "/adir")
  322. assert.NoError(t, err)
  323. err = os.MkdirAll(filepath.Join(user.GetHomeDir(), "adir"), os.ModePerm)
  324. assert.NoError(t, err)
  325. err = ioutil.WriteFile(filepath.Join(user.GetHomeDir(), "adir", "file"), []byte("data"), os.ModePerm)
  326. assert.NoError(t, err)
  327. err = c.Rename(filepath.Join(user.GetHomeDir(), "adir", "file"), filepath.Join(user.GetHomeDir(), "file"), "/adir/file", "/file")
  328. assert.NoError(t, err)
  329. // rename between virtual folder this should fail since the virtual folder is not found inside the data provider
  330. // and so the remaining space cannot be computed
  331. err = c.Rename(filepath.Join(user.GetHomeDir(), "adir"), filepath.Join(user.GetHomeDir(), "another"), "/vdir1/sub/a", "/vdir2/b")
  332. if assert.Error(t, err) {
  333. assert.EqualError(t, err, c.GetGenericError(err).Error())
  334. }
  335. err = os.RemoveAll(mappedPath1)
  336. assert.NoError(t, err)
  337. err = os.RemoveAll(mappedPath2)
  338. assert.NoError(t, err)
  339. err = os.RemoveAll(user.GetHomeDir())
  340. assert.NoError(t, err)
  341. }
  342. func TestCreateSymlink(t *testing.T) {
  343. user := dataprovider.User{
  344. Username: userTestUsername,
  345. HomeDir: filepath.Join(os.TempDir(), "home"),
  346. }
  347. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  348. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  349. user.Permissions = make(map[string][]string)
  350. user.Permissions["/"] = []string{dataprovider.PermAny}
  351. user.Permissions["/sub"] = []string{dataprovider.PermListItems}
  352. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  353. BaseVirtualFolder: vfs.BaseVirtualFolder{
  354. MappedPath: mappedPath1,
  355. },
  356. VirtualPath: "/vdir1",
  357. QuotaFiles: -1,
  358. QuotaSize: -1,
  359. })
  360. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  361. BaseVirtualFolder: vfs.BaseVirtualFolder{
  362. MappedPath: mappedPath2,
  363. },
  364. VirtualPath: "/vdir2",
  365. QuotaFiles: -1,
  366. QuotaSize: -1,
  367. })
  368. err := os.Mkdir(user.GetHomeDir(), os.ModePerm)
  369. assert.NoError(t, err)
  370. err = os.Mkdir(mappedPath1, os.ModePerm)
  371. assert.NoError(t, err)
  372. err = os.Mkdir(mappedPath2, os.ModePerm)
  373. assert.NoError(t, err)
  374. fs, err := user.GetFilesystem("")
  375. assert.NoError(t, err)
  376. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  377. err = c.CreateSymlink(user.GetHomeDir(), mappedPath1, "/", "/vdir1")
  378. if assert.Error(t, err) {
  379. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  380. }
  381. err = c.CreateSymlink(filepath.Join(user.GetHomeDir(), "a"), mappedPath1, "/a", "/vdir1")
  382. if assert.Error(t, err) {
  383. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  384. }
  385. err = c.CreateSymlink(filepath.Join(user.GetHomeDir(), "b"), mappedPath1, "/b", "/sub/b")
  386. if assert.Error(t, err) {
  387. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  388. }
  389. err = c.CreateSymlink(filepath.Join(user.GetHomeDir(), "b"), mappedPath1, "/vdir1/b", "/vdir2/b")
  390. if assert.Error(t, err) {
  391. assert.EqualError(t, err, c.GetOpUnsupportedError().Error())
  392. }
  393. err = c.CreateSymlink(mappedPath1, filepath.Join(mappedPath1, "b"), "/vdir1/a", "/vdir1/b")
  394. if assert.Error(t, err) {
  395. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  396. }
  397. err = c.CreateSymlink(filepath.Join(mappedPath1, "b"), mappedPath1, "/vdir1/a", "/vdir1/b")
  398. if assert.Error(t, err) {
  399. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  400. }
  401. err = os.Mkdir(filepath.Join(user.GetHomeDir(), "b"), os.ModePerm)
  402. assert.NoError(t, err)
  403. err = c.CreateSymlink(filepath.Join(user.GetHomeDir(), "b"), filepath.Join(user.GetHomeDir(), "c"), "/b", "/c")
  404. assert.NoError(t, err)
  405. err = c.CreateSymlink(filepath.Join(user.GetHomeDir(), "b"), filepath.Join(user.GetHomeDir(), "c"), "/b", "/c")
  406. assert.Error(t, err)
  407. err = os.RemoveAll(mappedPath1)
  408. assert.NoError(t, err)
  409. err = os.RemoveAll(mappedPath2)
  410. assert.NoError(t, err)
  411. err = os.RemoveAll(user.GetHomeDir())
  412. assert.NoError(t, err)
  413. }
  414. func TestDoStat(t *testing.T) {
  415. testFile := filepath.Join(os.TempDir(), "afile.txt")
  416. fs := vfs.NewOsFs("123", os.TempDir(), nil)
  417. u := dataprovider.User{
  418. Username: "user",
  419. HomeDir: os.TempDir(),
  420. }
  421. u.Permissions = make(map[string][]string)
  422. u.Permissions["/"] = []string{dataprovider.PermAny}
  423. err := ioutil.WriteFile(testFile, []byte("data"), os.ModePerm)
  424. require.NoError(t, err)
  425. err = os.Symlink(testFile, testFile+".sym")
  426. require.NoError(t, err)
  427. conn := NewBaseConnection(fs.ConnectionID(), ProtocolSFTP, u, fs)
  428. infoStat, err := conn.DoStat(testFile+".sym", 0)
  429. if assert.NoError(t, err) {
  430. assert.Equal(t, int64(4), infoStat.Size())
  431. }
  432. infoLstat, err := conn.DoStat(testFile+".sym", 1)
  433. if assert.NoError(t, err) {
  434. assert.NotEqual(t, int64(4), infoLstat.Size())
  435. }
  436. assert.False(t, os.SameFile(infoStat, infoLstat))
  437. err = os.Remove(testFile)
  438. assert.NoError(t, err)
  439. err = os.Remove(testFile + ".sym")
  440. assert.NoError(t, err)
  441. assert.Len(t, conn.GetTransfers(), 0)
  442. }
  443. func TestSetStat(t *testing.T) {
  444. oldSetStatMode := Config.SetstatMode
  445. Config.SetstatMode = 1
  446. user := dataprovider.User{
  447. Username: userTestUsername,
  448. HomeDir: filepath.Join(os.TempDir(), "home"),
  449. }
  450. user.Permissions = make(map[string][]string)
  451. user.Permissions["/"] = []string{dataprovider.PermAny}
  452. user.Permissions["/dir1"] = []string{dataprovider.PermChmod}
  453. user.Permissions["/dir2"] = []string{dataprovider.PermChown}
  454. user.Permissions["/dir3"] = []string{dataprovider.PermChtimes}
  455. dir1 := filepath.Join(user.GetHomeDir(), "dir1")
  456. dir2 := filepath.Join(user.GetHomeDir(), "dir2")
  457. dir3 := filepath.Join(user.GetHomeDir(), "dir3")
  458. err := os.Mkdir(user.GetHomeDir(), os.ModePerm)
  459. assert.NoError(t, err)
  460. err = os.Mkdir(dir1, os.ModePerm)
  461. assert.NoError(t, err)
  462. err = os.Mkdir(dir2, os.ModePerm)
  463. assert.NoError(t, err)
  464. err = os.Mkdir(dir3, os.ModePerm)
  465. assert.NoError(t, err)
  466. fs, err := user.GetFilesystem("")
  467. assert.NoError(t, err)
  468. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  469. err = c.SetStat(user.GetHomeDir(), "/", &StatAttributes{})
  470. assert.NoError(t, err)
  471. err = c.SetStat(dir2, "/dir1/file", &StatAttributes{
  472. Mode: os.ModePerm,
  473. Flags: StatAttrPerms,
  474. })
  475. assert.NoError(t, err)
  476. err = c.SetStat(dir1, "/dir2/file", &StatAttributes{
  477. UID: os.Getuid(),
  478. GID: os.Getgid(),
  479. Flags: StatAttrUIDGID,
  480. })
  481. assert.NoError(t, err)
  482. err = c.SetStat(dir1, "/dir3/file", &StatAttributes{
  483. Atime: time.Now(),
  484. Mtime: time.Now(),
  485. Flags: StatAttrTimes,
  486. })
  487. assert.NoError(t, err)
  488. Config.SetstatMode = 2
  489. assert.False(t, c.ignoreSetStat())
  490. c1 := NewBaseConnection("", ProtocolSFTP, user, newMockOsFs(false, fs.ConnectionID(), user.GetHomeDir()))
  491. assert.True(t, c1.ignoreSetStat())
  492. Config.SetstatMode = oldSetStatMode
  493. // chmod
  494. err = c.SetStat(dir1, "/dir1/file", &StatAttributes{
  495. Mode: os.ModePerm,
  496. Flags: StatAttrPerms,
  497. })
  498. assert.NoError(t, err)
  499. err = c.SetStat(dir2, "/dir2/file", &StatAttributes{
  500. Mode: os.ModePerm,
  501. Flags: StatAttrPerms,
  502. })
  503. if assert.Error(t, err) {
  504. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  505. }
  506. err = c.SetStat(filepath.Join(user.GetHomeDir(), "missing"), "/missing", &StatAttributes{
  507. Mode: os.ModePerm,
  508. Flags: StatAttrPerms,
  509. })
  510. assert.Error(t, err)
  511. // chown
  512. if runtime.GOOS != osWindows {
  513. err = c.SetStat(dir1, "/dir2/file", &StatAttributes{
  514. UID: os.Getuid(),
  515. GID: os.Getgid(),
  516. Flags: StatAttrUIDGID,
  517. })
  518. assert.NoError(t, err)
  519. }
  520. err = c.SetStat(dir1, "/dir3/file", &StatAttributes{
  521. UID: os.Getuid(),
  522. GID: os.Getgid(),
  523. Flags: StatAttrUIDGID,
  524. })
  525. if assert.Error(t, err) {
  526. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  527. }
  528. err = c.SetStat(filepath.Join(user.GetHomeDir(), "missing"), "/missing", &StatAttributes{
  529. UID: os.Getuid(),
  530. GID: os.Getgid(),
  531. Flags: StatAttrUIDGID,
  532. })
  533. assert.Error(t, err)
  534. // chtimes
  535. err = c.SetStat(dir1, "/dir3/file", &StatAttributes{
  536. Atime: time.Now(),
  537. Mtime: time.Now(),
  538. Flags: StatAttrTimes,
  539. })
  540. assert.NoError(t, err)
  541. err = c.SetStat(dir1, "/dir1/file", &StatAttributes{
  542. Atime: time.Now(),
  543. Mtime: time.Now(),
  544. Flags: StatAttrTimes,
  545. })
  546. if assert.Error(t, err) {
  547. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  548. }
  549. err = c.SetStat(filepath.Join(user.GetHomeDir(), "missing"), "/missing", &StatAttributes{
  550. Atime: time.Now(),
  551. Mtime: time.Now(),
  552. Flags: StatAttrTimes,
  553. })
  554. assert.Error(t, err)
  555. // truncate
  556. err = c.SetStat(filepath.Join(user.GetHomeDir(), "/missing/missing"), "/missing/missing", &StatAttributes{
  557. Size: 1,
  558. Flags: StatAttrSize,
  559. })
  560. assert.Error(t, err)
  561. err = c.SetStat(filepath.Join(dir3, "afile.txt"), "/dir3/afile.txt", &StatAttributes{
  562. Size: 1,
  563. Flags: StatAttrSize,
  564. })
  565. assert.Error(t, err)
  566. filePath := filepath.Join(user.GetHomeDir(), "afile.txt")
  567. err = ioutil.WriteFile(filePath, []byte("hello"), os.ModePerm)
  568. assert.NoError(t, err)
  569. err = c.SetStat(filePath, "/afile.txt", &StatAttributes{
  570. Flags: StatAttrSize,
  571. Size: 1,
  572. })
  573. assert.NoError(t, err)
  574. fi, err := os.Stat(filePath)
  575. if assert.NoError(t, err) {
  576. assert.Equal(t, int64(1), fi.Size())
  577. }
  578. vDir := filepath.Join(os.TempDir(), "vdir")
  579. err = os.MkdirAll(vDir, os.ModePerm)
  580. assert.NoError(t, err)
  581. c.User.VirtualFolders = nil
  582. c.User.VirtualFolders = append(c.User.VirtualFolders, vfs.VirtualFolder{
  583. BaseVirtualFolder: vfs.BaseVirtualFolder{
  584. MappedPath: vDir,
  585. },
  586. VirtualPath: "/vpath",
  587. QuotaSize: -1,
  588. QuotaFiles: -1,
  589. })
  590. filePath = filepath.Join(vDir, "afile.txt")
  591. err = ioutil.WriteFile(filePath, []byte("hello"), os.ModePerm)
  592. assert.NoError(t, err)
  593. err = c.SetStat(filePath, "/vpath/afile.txt", &StatAttributes{
  594. Flags: StatAttrSize,
  595. Size: 1,
  596. })
  597. assert.NoError(t, err)
  598. fi, err = os.Stat(filePath)
  599. if assert.NoError(t, err) {
  600. assert.Equal(t, int64(1), fi.Size())
  601. }
  602. err = os.RemoveAll(user.GetHomeDir())
  603. assert.NoError(t, err)
  604. err = os.RemoveAll(vDir)
  605. assert.NoError(t, err)
  606. }
  607. func TestSpaceForCrossRename(t *testing.T) {
  608. permissions := make(map[string][]string)
  609. permissions["/"] = []string{dataprovider.PermAny}
  610. user := dataprovider.User{
  611. Username: userTestUsername,
  612. Permissions: permissions,
  613. HomeDir: filepath.Clean(os.TempDir()),
  614. }
  615. fs, err := user.GetFilesystem("123")
  616. assert.NoError(t, err)
  617. conn := NewBaseConnection("", ProtocolSFTP, user, fs)
  618. quotaResult := vfs.QuotaCheckResult{
  619. HasSpace: true,
  620. }
  621. assert.False(t, conn.hasSpaceForCrossRename(quotaResult, -1, filepath.Join(os.TempDir(), "a missing file")))
  622. if runtime.GOOS != osWindows {
  623. testDir := filepath.Join(os.TempDir(), "dir")
  624. err = os.MkdirAll(testDir, os.ModePerm)
  625. assert.NoError(t, err)
  626. err = ioutil.WriteFile(filepath.Join(testDir, "afile.txt"), []byte("content"), os.ModePerm)
  627. assert.NoError(t, err)
  628. err = os.Chmod(testDir, 0001)
  629. assert.NoError(t, err)
  630. assert.False(t, conn.hasSpaceForCrossRename(quotaResult, -1, testDir))
  631. err = os.Chmod(testDir, os.ModePerm)
  632. assert.NoError(t, err)
  633. err = os.RemoveAll(testDir)
  634. assert.NoError(t, err)
  635. }
  636. testFile := filepath.Join(os.TempDir(), "afile.txt")
  637. err = ioutil.WriteFile(testFile, []byte("test data"), os.ModePerm)
  638. assert.NoError(t, err)
  639. quotaResult = vfs.QuotaCheckResult{
  640. HasSpace: false,
  641. QuotaSize: 0,
  642. }
  643. assert.True(t, conn.hasSpaceForCrossRename(quotaResult, 123, testFile))
  644. quotaResult = vfs.QuotaCheckResult{
  645. HasSpace: false,
  646. QuotaSize: 124,
  647. UsedSize: 125,
  648. }
  649. assert.False(t, conn.hasSpaceForCrossRename(quotaResult, 8, testFile))
  650. quotaResult = vfs.QuotaCheckResult{
  651. HasSpace: false,
  652. QuotaSize: 124,
  653. UsedSize: 124,
  654. }
  655. assert.True(t, conn.hasSpaceForCrossRename(quotaResult, 123, testFile))
  656. quotaResult = vfs.QuotaCheckResult{
  657. HasSpace: true,
  658. QuotaSize: 10,
  659. UsedSize: 1,
  660. }
  661. assert.True(t, conn.hasSpaceForCrossRename(quotaResult, -1, testFile))
  662. quotaResult = vfs.QuotaCheckResult{
  663. HasSpace: true,
  664. QuotaSize: 7,
  665. UsedSize: 0,
  666. }
  667. assert.False(t, conn.hasSpaceForCrossRename(quotaResult, -1, testFile))
  668. err = os.Remove(testFile)
  669. assert.NoError(t, err)
  670. testDir := filepath.Join(os.TempDir(), "testDir")
  671. err = os.MkdirAll(testDir, os.ModePerm)
  672. assert.NoError(t, err)
  673. err = ioutil.WriteFile(filepath.Join(testDir, "1"), []byte("1"), os.ModePerm)
  674. assert.NoError(t, err)
  675. err = ioutil.WriteFile(filepath.Join(testDir, "2"), []byte("2"), os.ModePerm)
  676. assert.NoError(t, err)
  677. quotaResult = vfs.QuotaCheckResult{
  678. HasSpace: true,
  679. QuotaFiles: 2,
  680. UsedFiles: 1,
  681. }
  682. assert.False(t, conn.hasSpaceForCrossRename(quotaResult, -1, testDir))
  683. quotaResult = vfs.QuotaCheckResult{
  684. HasSpace: true,
  685. QuotaFiles: 2,
  686. UsedFiles: 0,
  687. }
  688. assert.True(t, conn.hasSpaceForCrossRename(quotaResult, -1, testDir))
  689. err = os.RemoveAll(testDir)
  690. assert.NoError(t, err)
  691. }
  692. func TestRenamePermission(t *testing.T) {
  693. permissions := make(map[string][]string)
  694. permissions["/"] = []string{dataprovider.PermAny}
  695. permissions["/dir1"] = []string{dataprovider.PermRename}
  696. permissions["/dir2"] = []string{dataprovider.PermUpload}
  697. permissions["/dir3"] = []string{dataprovider.PermDelete}
  698. permissions["/dir4"] = []string{dataprovider.PermListItems}
  699. permissions["/dir5"] = []string{dataprovider.PermCreateDirs, dataprovider.PermUpload}
  700. permissions["/dir6"] = []string{dataprovider.PermCreateDirs, dataprovider.PermUpload,
  701. dataprovider.PermListItems, dataprovider.PermCreateSymlinks}
  702. permissions["/dir7"] = []string{dataprovider.PermAny}
  703. permissions["/dir8"] = []string{dataprovider.PermAny}
  704. user := dataprovider.User{
  705. Username: userTestUsername,
  706. Permissions: permissions,
  707. HomeDir: os.TempDir(),
  708. }
  709. fs, err := user.GetFilesystem("123")
  710. assert.NoError(t, err)
  711. conn := NewBaseConnection("", ProtocolSFTP, user, fs)
  712. request := sftp.NewRequest("Rename", "/testfile")
  713. request.Target = "/dir1/testfile"
  714. // rename is granted on Source and Target
  715. assert.True(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  716. request.Target = "/dir4/testfile"
  717. // rename is not granted on Target
  718. assert.False(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  719. request = sftp.NewRequest("Rename", "/dir1/testfile")
  720. request.Target = "/dir2/testfile" //nolint:goconst
  721. // rename is granted on Source but not on Target
  722. assert.False(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  723. request = sftp.NewRequest("Rename", "/dir4/testfile")
  724. request.Target = "/dir1/testfile"
  725. // rename is granted on Target but not on Source
  726. assert.False(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  727. request = sftp.NewRequest("Rename", "/dir4/testfile")
  728. request.Target = "/testfile"
  729. // rename is granted on Target but not on Source
  730. assert.False(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  731. request = sftp.NewRequest("Rename", "/dir3/testfile")
  732. request.Target = "/dir2/testfile"
  733. // delete is granted on Source and Upload on Target, the target is a file this is enough
  734. assert.True(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  735. request = sftp.NewRequest("Rename", "/dir2/testfile")
  736. request.Target = "/dir3/testfile"
  737. assert.False(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  738. tmpDir := filepath.Join(os.TempDir(), "dir")
  739. tmpDirLink := filepath.Join(os.TempDir(), "link")
  740. err = os.Mkdir(tmpDir, os.ModePerm)
  741. assert.NoError(t, err)
  742. err = os.Symlink(tmpDir, tmpDirLink)
  743. assert.NoError(t, err)
  744. request.Filepath = "/dir"
  745. request.Target = "/dir2/dir"
  746. // the source is a dir and the target has no createDirs perm
  747. info, err := os.Lstat(tmpDir)
  748. if assert.NoError(t, err) {
  749. assert.False(t, conn.isRenamePermitted(tmpDir, request.Filepath, request.Target, info))
  750. conn.User.Permissions["/dir2"] = []string{dataprovider.PermUpload, dataprovider.PermCreateDirs}
  751. // the source is a dir and the target has createDirs perm
  752. assert.True(t, conn.isRenamePermitted(tmpDir, request.Filepath, request.Target, info))
  753. request = sftp.NewRequest("Rename", "/testfile")
  754. request.Target = "/dir5/testfile"
  755. // the source is a dir and the target has createDirs and upload perm
  756. assert.True(t, conn.isRenamePermitted(tmpDir, request.Filepath, request.Target, info))
  757. }
  758. info, err = os.Lstat(tmpDirLink)
  759. if assert.NoError(t, err) {
  760. assert.True(t, info.Mode()&os.ModeSymlink != 0)
  761. // the source is a symlink and the target has createDirs and upload perm
  762. assert.False(t, conn.isRenamePermitted(tmpDir, request.Filepath, request.Target, info))
  763. }
  764. err = os.RemoveAll(tmpDir)
  765. assert.NoError(t, err)
  766. err = os.Remove(tmpDirLink)
  767. assert.NoError(t, err)
  768. conn.User.VirtualFolders = append(conn.User.VirtualFolders, vfs.VirtualFolder{
  769. BaseVirtualFolder: vfs.BaseVirtualFolder{
  770. MappedPath: os.TempDir(),
  771. },
  772. VirtualPath: "/dir1",
  773. })
  774. request = sftp.NewRequest("Rename", "/dir1")
  775. request.Target = "/dir2/testfile"
  776. // renaming a virtual folder is not allowed
  777. assert.False(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  778. err = conn.checkRecursiveRenameDirPermissions("invalid", "invalid")
  779. assert.Error(t, err)
  780. dir3 := filepath.Join(conn.User.HomeDir, "dir3")
  781. dir6 := filepath.Join(conn.User.HomeDir, "dir6")
  782. err = os.MkdirAll(filepath.Join(dir3, "subdir"), os.ModePerm)
  783. assert.NoError(t, err)
  784. err = ioutil.WriteFile(filepath.Join(dir3, "subdir", "testfile"), []byte("test"), os.ModePerm)
  785. assert.NoError(t, err)
  786. err = conn.checkRecursiveRenameDirPermissions(dir3, dir6)
  787. assert.NoError(t, err)
  788. err = os.RemoveAll(dir3)
  789. assert.NoError(t, err)
  790. dir7 := filepath.Join(conn.User.HomeDir, "dir7")
  791. dir8 := filepath.Join(conn.User.HomeDir, "dir8")
  792. err = os.MkdirAll(filepath.Join(dir8, "subdir"), os.ModePerm)
  793. assert.NoError(t, err)
  794. err = ioutil.WriteFile(filepath.Join(dir8, "subdir", "testfile"), []byte("test"), os.ModePerm)
  795. assert.NoError(t, err)
  796. err = conn.checkRecursiveRenameDirPermissions(dir8, dir7)
  797. assert.NoError(t, err)
  798. err = os.RemoveAll(dir8)
  799. assert.NoError(t, err)
  800. assert.False(t, conn.isRenamePermitted(user.GetHomeDir(), "", "", nil))
  801. conn.User.Filters.FileExtensions = []dataprovider.ExtensionsFilter{
  802. {
  803. Path: "/p",
  804. AllowedExtensions: []string{},
  805. DeniedExtensions: []string{".zip"},
  806. },
  807. }
  808. testFile := filepath.Join(user.HomeDir, "testfile")
  809. err = ioutil.WriteFile(testFile, []byte("data"), os.ModePerm)
  810. assert.NoError(t, err)
  811. info, err = os.Stat(testFile)
  812. assert.NoError(t, err)
  813. assert.False(t, conn.isRenamePermitted(dir7, "/file", "/p/file.zip", info))
  814. err = os.Remove(testFile)
  815. assert.NoError(t, err)
  816. }
  817. func TestHasSpaceForRename(t *testing.T) {
  818. err := closeDataprovider()
  819. assert.NoError(t, err)
  820. _, err = initializeDataprovider(0)
  821. assert.NoError(t, err)
  822. user := dataprovider.User{
  823. Username: userTestUsername,
  824. HomeDir: filepath.Join(os.TempDir(), "home"),
  825. }
  826. mappedPath := filepath.Join(os.TempDir(), "vdir")
  827. user.Permissions = make(map[string][]string)
  828. user.Permissions["/"] = []string{dataprovider.PermAny}
  829. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  830. BaseVirtualFolder: vfs.BaseVirtualFolder{
  831. MappedPath: mappedPath,
  832. },
  833. VirtualPath: "/vdir1",
  834. })
  835. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  836. BaseVirtualFolder: vfs.BaseVirtualFolder{
  837. MappedPath: mappedPath,
  838. },
  839. VirtualPath: "/vdir2",
  840. QuotaSize: -1,
  841. QuotaFiles: -1,
  842. })
  843. fs, err := user.GetFilesystem("id")
  844. assert.NoError(t, err)
  845. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  846. // with quota tracking disabled hasSpaceForRename will always return true
  847. assert.True(t, c.hasSpaceForRename("", "", 0, ""))
  848. quotaResult := c.HasSpace(true, "")
  849. assert.True(t, quotaResult.HasSpace)
  850. err = closeDataprovider()
  851. assert.NoError(t, err)
  852. _, err = initializeDataprovider(-1)
  853. assert.NoError(t, err)
  854. // rename inside the same mapped path
  855. assert.True(t, c.hasSpaceForRename("/vdir1/file", "/vdir2/file", 0, filepath.Join(mappedPath, "file")))
  856. // rename between user root dir and a virtual folder included in user quota
  857. assert.True(t, c.hasSpaceForRename("/file", "/vdir2/file", 0, filepath.Join(mappedPath, "file")))
  858. assert.True(t, c.isCrossFoldersRequest("/file", "/vdir2/file"))
  859. }
  860. func TestUpdateQuotaAfterRename(t *testing.T) {
  861. user := dataprovider.User{
  862. Username: userTestUsername,
  863. HomeDir: filepath.Join(os.TempDir(), "home"),
  864. }
  865. mappedPath := filepath.Join(os.TempDir(), "vdir")
  866. user.Permissions = make(map[string][]string)
  867. user.Permissions["/"] = []string{dataprovider.PermAny}
  868. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  869. BaseVirtualFolder: vfs.BaseVirtualFolder{
  870. MappedPath: mappedPath,
  871. },
  872. VirtualPath: "/vdir",
  873. QuotaFiles: -1,
  874. QuotaSize: -1,
  875. })
  876. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  877. BaseVirtualFolder: vfs.BaseVirtualFolder{
  878. MappedPath: mappedPath,
  879. },
  880. VirtualPath: "/vdir1",
  881. QuotaFiles: -1,
  882. QuotaSize: -1,
  883. })
  884. err := os.MkdirAll(user.GetHomeDir(), os.ModePerm)
  885. assert.NoError(t, err)
  886. err = os.MkdirAll(mappedPath, os.ModePerm)
  887. assert.NoError(t, err)
  888. fs, err := user.GetFilesystem("id")
  889. assert.NoError(t, err)
  890. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  891. request := sftp.NewRequest("Rename", "/testfile")
  892. if runtime.GOOS != osWindows {
  893. request.Filepath = "/dir"
  894. request.Target = path.Join("/vdir", "dir")
  895. testDirPath := filepath.Join(mappedPath, "dir")
  896. err := os.MkdirAll(testDirPath, os.ModePerm)
  897. assert.NoError(t, err)
  898. err = os.Chmod(testDirPath, 0001)
  899. assert.NoError(t, err)
  900. err = c.updateQuotaAfterRename(request.Filepath, request.Target, testDirPath, 0)
  901. assert.Error(t, err)
  902. err = os.Chmod(testDirPath, os.ModePerm)
  903. assert.NoError(t, err)
  904. }
  905. testFile1 := "/testfile1"
  906. request.Target = testFile1
  907. request.Filepath = path.Join("/vdir", "file")
  908. err = c.updateQuotaAfterRename(request.Filepath, request.Target, filepath.Join(mappedPath, "file"), 0)
  909. assert.Error(t, err)
  910. err = ioutil.WriteFile(filepath.Join(mappedPath, "file"), []byte("test content"), os.ModePerm)
  911. assert.NoError(t, err)
  912. request.Filepath = testFile1
  913. request.Target = path.Join("/vdir", "file")
  914. err = c.updateQuotaAfterRename(request.Filepath, request.Target, filepath.Join(mappedPath, "file"), 12)
  915. assert.NoError(t, err)
  916. err = ioutil.WriteFile(filepath.Join(user.GetHomeDir(), "testfile1"), []byte("test content"), os.ModePerm)
  917. assert.NoError(t, err)
  918. request.Target = testFile1
  919. request.Filepath = path.Join("/vdir", "file")
  920. err = c.updateQuotaAfterRename(request.Filepath, request.Target, filepath.Join(mappedPath, "file"), 12)
  921. assert.NoError(t, err)
  922. request.Target = path.Join("/vdir1", "file")
  923. request.Filepath = path.Join("/vdir", "file")
  924. err = c.updateQuotaAfterRename(request.Filepath, request.Target, filepath.Join(mappedPath, "file"), 12)
  925. assert.NoError(t, err)
  926. err = os.RemoveAll(mappedPath)
  927. assert.NoError(t, err)
  928. err = os.RemoveAll(user.GetHomeDir())
  929. assert.NoError(t, err)
  930. }
  931. func TestHasSpace(t *testing.T) {
  932. user := dataprovider.User{
  933. Username: userTestUsername,
  934. HomeDir: filepath.Join(os.TempDir(), "home"),
  935. Password: userTestPwd,
  936. }
  937. mappedPath := filepath.Join(os.TempDir(), "vdir")
  938. user.Permissions = make(map[string][]string)
  939. user.Permissions["/"] = []string{dataprovider.PermAny}
  940. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  941. BaseVirtualFolder: vfs.BaseVirtualFolder{
  942. MappedPath: mappedPath,
  943. },
  944. VirtualPath: "/vdir",
  945. QuotaFiles: -1,
  946. QuotaSize: -1,
  947. })
  948. fs, err := user.GetFilesystem("id")
  949. assert.NoError(t, err)
  950. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  951. quotaResult := c.HasSpace(true, "/")
  952. assert.True(t, quotaResult.HasSpace)
  953. user.VirtualFolders[0].QuotaFiles = 0
  954. user.VirtualFolders[0].QuotaSize = 0
  955. err = dataprovider.AddUser(user)
  956. assert.NoError(t, err)
  957. user, err = dataprovider.UserExists(user.Username)
  958. assert.NoError(t, err)
  959. c.User = user
  960. quotaResult = c.HasSpace(true, "/vdir/file")
  961. assert.True(t, quotaResult.HasSpace)
  962. user.VirtualFolders[0].QuotaFiles = 10
  963. user.VirtualFolders[0].QuotaSize = 1048576
  964. err = dataprovider.UpdateUser(user)
  965. assert.NoError(t, err)
  966. c.User = user
  967. quotaResult = c.HasSpace(true, "/vdir/file1")
  968. assert.True(t, quotaResult.HasSpace)
  969. quotaResult = c.HasSpace(true, "/file")
  970. assert.True(t, quotaResult.HasSpace)
  971. folder, err := dataprovider.GetFolderByPath(mappedPath)
  972. assert.NoError(t, err)
  973. err = dataprovider.UpdateVirtualFolderQuota(folder, 10, 1048576, true)
  974. assert.NoError(t, err)
  975. quotaResult = c.HasSpace(true, "/vdir/file1")
  976. assert.False(t, quotaResult.HasSpace)
  977. err = dataprovider.DeleteUser(user)
  978. assert.NoError(t, err)
  979. err = dataprovider.DeleteFolder(folder)
  980. assert.NoError(t, err)
  981. }
  982. func TestUpdateQuotaMoveVFolders(t *testing.T) {
  983. user := dataprovider.User{
  984. Username: userTestUsername,
  985. HomeDir: filepath.Join(os.TempDir(), "home"),
  986. Password: userTestPwd,
  987. QuotaFiles: 100,
  988. }
  989. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  990. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  991. user.Permissions = make(map[string][]string)
  992. user.Permissions["/"] = []string{dataprovider.PermAny}
  993. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  994. BaseVirtualFolder: vfs.BaseVirtualFolder{
  995. MappedPath: mappedPath1,
  996. },
  997. VirtualPath: "/vdir1",
  998. QuotaFiles: -1,
  999. QuotaSize: -1,
  1000. })
  1001. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  1002. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1003. MappedPath: mappedPath2,
  1004. },
  1005. VirtualPath: "/vdir2",
  1006. QuotaFiles: -1,
  1007. QuotaSize: -1,
  1008. })
  1009. err := dataprovider.AddUser(user)
  1010. assert.NoError(t, err)
  1011. user, err = dataprovider.UserExists(user.Username)
  1012. assert.NoError(t, err)
  1013. folder1, err := dataprovider.GetFolderByPath(mappedPath1)
  1014. assert.NoError(t, err)
  1015. folder2, err := dataprovider.GetFolderByPath(mappedPath2)
  1016. assert.NoError(t, err)
  1017. err = dataprovider.UpdateVirtualFolderQuota(folder1, 1, 100, true)
  1018. assert.NoError(t, err)
  1019. err = dataprovider.UpdateVirtualFolderQuota(folder2, 2, 150, true)
  1020. assert.NoError(t, err)
  1021. fs, err := user.GetFilesystem("id")
  1022. assert.NoError(t, err)
  1023. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  1024. c.updateQuotaMoveBetweenVFolders(user.VirtualFolders[0], user.VirtualFolders[1], -1, 100, 1)
  1025. folder1, err = dataprovider.GetFolderByPath(mappedPath1)
  1026. assert.NoError(t, err)
  1027. assert.Equal(t, 0, folder1.UsedQuotaFiles)
  1028. assert.Equal(t, int64(0), folder1.UsedQuotaSize)
  1029. folder2, err = dataprovider.GetFolderByPath(mappedPath2)
  1030. assert.NoError(t, err)
  1031. assert.Equal(t, 3, folder2.UsedQuotaFiles)
  1032. assert.Equal(t, int64(250), folder2.UsedQuotaSize)
  1033. c.updateQuotaMoveBetweenVFolders(user.VirtualFolders[1], user.VirtualFolders[0], 10, 100, 1)
  1034. folder1, err = dataprovider.GetFolderByPath(mappedPath1)
  1035. assert.NoError(t, err)
  1036. assert.Equal(t, 0, folder1.UsedQuotaFiles)
  1037. assert.Equal(t, int64(90), folder1.UsedQuotaSize)
  1038. folder2, err = dataprovider.GetFolderByPath(mappedPath2)
  1039. assert.NoError(t, err)
  1040. assert.Equal(t, 2, folder2.UsedQuotaFiles)
  1041. assert.Equal(t, int64(150), folder2.UsedQuotaSize)
  1042. err = dataprovider.UpdateUserQuota(user, 1, 100, true)
  1043. assert.NoError(t, err)
  1044. c.updateQuotaMoveFromVFolder(user.VirtualFolders[1], -1, 50, 1)
  1045. folder2, err = dataprovider.GetFolderByPath(mappedPath2)
  1046. assert.NoError(t, err)
  1047. assert.Equal(t, 1, folder2.UsedQuotaFiles)
  1048. assert.Equal(t, int64(100), folder2.UsedQuotaSize)
  1049. user, err = dataprovider.GetUserByID(user.ID)
  1050. assert.NoError(t, err)
  1051. assert.Equal(t, 1, user.UsedQuotaFiles)
  1052. assert.Equal(t, int64(100), user.UsedQuotaSize)
  1053. c.updateQuotaMoveToVFolder(user.VirtualFolders[1], -1, 100, 1)
  1054. folder2, err = dataprovider.GetFolderByPath(mappedPath2)
  1055. assert.NoError(t, err)
  1056. assert.Equal(t, 2, folder2.UsedQuotaFiles)
  1057. assert.Equal(t, int64(200), folder2.UsedQuotaSize)
  1058. user, err = dataprovider.GetUserByID(user.ID)
  1059. assert.NoError(t, err)
  1060. assert.Equal(t, 1, user.UsedQuotaFiles)
  1061. assert.Equal(t, int64(100), user.UsedQuotaSize)
  1062. err = dataprovider.DeleteUser(user)
  1063. assert.NoError(t, err)
  1064. err = dataprovider.DeleteFolder(folder1)
  1065. assert.NoError(t, err)
  1066. err = dataprovider.DeleteFolder(folder2)
  1067. assert.NoError(t, err)
  1068. }
  1069. func TestErrorsMapping(t *testing.T) {
  1070. fs := vfs.NewOsFs("", os.TempDir(), nil)
  1071. conn := NewBaseConnection("", ProtocolSFTP, dataprovider.User{}, fs)
  1072. for _, protocol := range supportedProtocols {
  1073. conn.SetProtocol(protocol)
  1074. err := conn.GetFsError(os.ErrNotExist)
  1075. if protocol == ProtocolSFTP {
  1076. assert.EqualError(t, err, sftp.ErrSSHFxNoSuchFile.Error())
  1077. } else if protocol == ProtocolWebDAV {
  1078. assert.EqualError(t, err, os.ErrNotExist.Error())
  1079. } else {
  1080. assert.EqualError(t, err, ErrNotExist.Error())
  1081. }
  1082. err = conn.GetFsError(os.ErrPermission)
  1083. if protocol == ProtocolSFTP {
  1084. assert.EqualError(t, err, sftp.ErrSSHFxPermissionDenied.Error())
  1085. } else {
  1086. assert.EqualError(t, err, ErrPermissionDenied.Error())
  1087. }
  1088. err = conn.GetFsError(os.ErrClosed)
  1089. if protocol == ProtocolSFTP {
  1090. assert.EqualError(t, err, sftp.ErrSSHFxFailure.Error())
  1091. } else {
  1092. assert.EqualError(t, err, ErrGenericFailure.Error())
  1093. }
  1094. err = conn.GetFsError(ErrPermissionDenied)
  1095. if protocol == ProtocolSFTP {
  1096. assert.EqualError(t, err, sftp.ErrSSHFxFailure.Error())
  1097. } else {
  1098. assert.EqualError(t, err, ErrPermissionDenied.Error())
  1099. }
  1100. err = conn.GetFsError(vfs.ErrVfsUnsupported)
  1101. if protocol == ProtocolSFTP {
  1102. assert.EqualError(t, err, sftp.ErrSSHFxOpUnsupported.Error())
  1103. } else {
  1104. assert.EqualError(t, err, ErrOpUnsupported.Error())
  1105. }
  1106. err = conn.GetFsError(nil)
  1107. assert.NoError(t, err)
  1108. err = conn.GetOpUnsupportedError()
  1109. if protocol == ProtocolSFTP {
  1110. assert.EqualError(t, err, sftp.ErrSSHFxOpUnsupported.Error())
  1111. } else {
  1112. assert.EqualError(t, err, ErrOpUnsupported.Error())
  1113. }
  1114. }
  1115. }
  1116. func TestMaxWriteSize(t *testing.T) {
  1117. permissions := make(map[string][]string)
  1118. permissions["/"] = []string{dataprovider.PermAny}
  1119. user := dataprovider.User{
  1120. Username: userTestUsername,
  1121. Permissions: permissions,
  1122. HomeDir: filepath.Clean(os.TempDir()),
  1123. }
  1124. fs, err := user.GetFilesystem("123")
  1125. assert.NoError(t, err)
  1126. conn := NewBaseConnection("", ProtocolFTP, user, fs)
  1127. quotaResult := vfs.QuotaCheckResult{
  1128. HasSpace: true,
  1129. }
  1130. size, err := conn.GetMaxWriteSize(quotaResult, false, 0)
  1131. assert.NoError(t, err)
  1132. assert.Equal(t, int64(0), size)
  1133. conn.User.Filters.MaxUploadFileSize = 100
  1134. size, err = conn.GetMaxWriteSize(quotaResult, false, 0)
  1135. assert.NoError(t, err)
  1136. assert.Equal(t, int64(100), size)
  1137. quotaResult.QuotaSize = 1000
  1138. size, err = conn.GetMaxWriteSize(quotaResult, false, 50)
  1139. assert.NoError(t, err)
  1140. assert.Equal(t, int64(100), size)
  1141. quotaResult.QuotaSize = 1000
  1142. quotaResult.UsedSize = 990
  1143. size, err = conn.GetMaxWriteSize(quotaResult, false, 50)
  1144. assert.NoError(t, err)
  1145. assert.Equal(t, int64(60), size)
  1146. quotaResult.QuotaSize = 0
  1147. quotaResult.UsedSize = 0
  1148. size, err = conn.GetMaxWriteSize(quotaResult, true, 100)
  1149. assert.EqualError(t, err, ErrQuotaExceeded.Error())
  1150. assert.Equal(t, int64(0), size)
  1151. size, err = conn.GetMaxWriteSize(quotaResult, true, 10)
  1152. assert.NoError(t, err)
  1153. assert.Equal(t, int64(90), size)
  1154. conn.Fs = newMockOsFs(true, fs.ConnectionID(), user.GetHomeDir())
  1155. size, err = conn.GetMaxWriteSize(quotaResult, true, 100)
  1156. assert.EqualError(t, err, ErrOpUnsupported.Error())
  1157. assert.Equal(t, int64(0), size)
  1158. }