connection_test.go 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208
  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. Config.SetstatMode = oldSetStatMode
  472. // chmod
  473. err = c.SetStat(dir1, "/dir1/file", &StatAttributes{
  474. Mode: os.ModePerm,
  475. Flags: StatAttrPerms,
  476. })
  477. assert.NoError(t, err)
  478. err = c.SetStat(dir2, "/dir2/file", &StatAttributes{
  479. Mode: os.ModePerm,
  480. Flags: StatAttrPerms,
  481. })
  482. if assert.Error(t, err) {
  483. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  484. }
  485. err = c.SetStat(filepath.Join(user.GetHomeDir(), "missing"), "/missing", &StatAttributes{
  486. Mode: os.ModePerm,
  487. Flags: StatAttrPerms,
  488. })
  489. assert.Error(t, err)
  490. // chown
  491. if runtime.GOOS != osWindows {
  492. err = c.SetStat(dir1, "/dir2/file", &StatAttributes{
  493. UID: os.Getuid(),
  494. GID: os.Getgid(),
  495. Flags: StatAttrUIDGID,
  496. })
  497. assert.NoError(t, err)
  498. }
  499. err = c.SetStat(dir1, "/dir3/file", &StatAttributes{
  500. UID: os.Getuid(),
  501. GID: os.Getgid(),
  502. Flags: StatAttrUIDGID,
  503. })
  504. if assert.Error(t, err) {
  505. assert.EqualError(t, err, c.GetPermissionDeniedError().Error())
  506. }
  507. err = c.SetStat(filepath.Join(user.GetHomeDir(), "missing"), "/missing", &StatAttributes{
  508. UID: os.Getuid(),
  509. GID: os.Getgid(),
  510. Flags: StatAttrUIDGID,
  511. })
  512. assert.Error(t, err)
  513. // chtimes
  514. err = c.SetStat(dir1, "/dir3/file", &StatAttributes{
  515. Atime: time.Now(),
  516. Mtime: time.Now(),
  517. Flags: StatAttrTimes,
  518. })
  519. assert.NoError(t, err)
  520. err = c.SetStat(dir1, "/dir1/file", &StatAttributes{
  521. Atime: time.Now(),
  522. Mtime: time.Now(),
  523. Flags: StatAttrTimes,
  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. Atime: time.Now(),
  530. Mtime: time.Now(),
  531. Flags: StatAttrTimes,
  532. })
  533. assert.Error(t, err)
  534. // truncate
  535. err = c.SetStat(filepath.Join(user.GetHomeDir(), "/missing/missing"), "/missing/missing", &StatAttributes{
  536. Size: 1,
  537. Flags: StatAttrSize,
  538. })
  539. assert.Error(t, err)
  540. err = c.SetStat(filepath.Join(dir3, "afile.txt"), "/dir3/afile.txt", &StatAttributes{
  541. Size: 1,
  542. Flags: StatAttrSize,
  543. })
  544. assert.Error(t, err)
  545. filePath := filepath.Join(user.GetHomeDir(), "afile.txt")
  546. err = ioutil.WriteFile(filePath, []byte("hello"), os.ModePerm)
  547. assert.NoError(t, err)
  548. err = c.SetStat(filePath, "/afile.txt", &StatAttributes{
  549. Flags: StatAttrSize,
  550. Size: 1,
  551. })
  552. assert.NoError(t, err)
  553. fi, err := os.Stat(filePath)
  554. if assert.NoError(t, err) {
  555. assert.Equal(t, int64(1), fi.Size())
  556. }
  557. vDir := filepath.Join(os.TempDir(), "vdir")
  558. err = os.MkdirAll(vDir, os.ModePerm)
  559. assert.NoError(t, err)
  560. c.User.VirtualFolders = nil
  561. c.User.VirtualFolders = append(c.User.VirtualFolders, vfs.VirtualFolder{
  562. BaseVirtualFolder: vfs.BaseVirtualFolder{
  563. MappedPath: vDir,
  564. },
  565. VirtualPath: "/vpath",
  566. QuotaSize: -1,
  567. QuotaFiles: -1,
  568. })
  569. filePath = filepath.Join(vDir, "afile.txt")
  570. err = ioutil.WriteFile(filePath, []byte("hello"), os.ModePerm)
  571. assert.NoError(t, err)
  572. err = c.SetStat(filePath, "/vpath/afile.txt", &StatAttributes{
  573. Flags: StatAttrSize,
  574. Size: 1,
  575. })
  576. assert.NoError(t, err)
  577. fi, err = os.Stat(filePath)
  578. if assert.NoError(t, err) {
  579. assert.Equal(t, int64(1), fi.Size())
  580. }
  581. err = os.RemoveAll(user.GetHomeDir())
  582. assert.NoError(t, err)
  583. err = os.RemoveAll(vDir)
  584. assert.NoError(t, err)
  585. }
  586. func TestSpaceForCrossRename(t *testing.T) {
  587. permissions := make(map[string][]string)
  588. permissions["/"] = []string{dataprovider.PermAny}
  589. user := dataprovider.User{
  590. Username: userTestUsername,
  591. Permissions: permissions,
  592. HomeDir: filepath.Clean(os.TempDir()),
  593. }
  594. fs, err := user.GetFilesystem("123")
  595. assert.NoError(t, err)
  596. conn := NewBaseConnection("", ProtocolSFTP, user, fs)
  597. quotaResult := vfs.QuotaCheckResult{
  598. HasSpace: true,
  599. }
  600. assert.False(t, conn.hasSpaceForCrossRename(quotaResult, -1, filepath.Join(os.TempDir(), "a missing file")))
  601. if runtime.GOOS != osWindows {
  602. testDir := filepath.Join(os.TempDir(), "dir")
  603. err = os.MkdirAll(testDir, os.ModePerm)
  604. assert.NoError(t, err)
  605. err = ioutil.WriteFile(filepath.Join(testDir, "afile.txt"), []byte("content"), os.ModePerm)
  606. assert.NoError(t, err)
  607. err = os.Chmod(testDir, 0001)
  608. assert.NoError(t, err)
  609. assert.False(t, conn.hasSpaceForCrossRename(quotaResult, -1, testDir))
  610. err = os.Chmod(testDir, os.ModePerm)
  611. assert.NoError(t, err)
  612. err = os.RemoveAll(testDir)
  613. assert.NoError(t, err)
  614. }
  615. testFile := filepath.Join(os.TempDir(), "afile.txt")
  616. err = ioutil.WriteFile(testFile, []byte("test data"), os.ModePerm)
  617. assert.NoError(t, err)
  618. quotaResult = vfs.QuotaCheckResult{
  619. HasSpace: false,
  620. QuotaSize: 0,
  621. }
  622. assert.True(t, conn.hasSpaceForCrossRename(quotaResult, 123, testFile))
  623. quotaResult = vfs.QuotaCheckResult{
  624. HasSpace: false,
  625. QuotaSize: 124,
  626. UsedSize: 125,
  627. }
  628. assert.False(t, conn.hasSpaceForCrossRename(quotaResult, 8, testFile))
  629. quotaResult = vfs.QuotaCheckResult{
  630. HasSpace: false,
  631. QuotaSize: 124,
  632. UsedSize: 124,
  633. }
  634. assert.True(t, conn.hasSpaceForCrossRename(quotaResult, 123, testFile))
  635. quotaResult = vfs.QuotaCheckResult{
  636. HasSpace: true,
  637. QuotaSize: 10,
  638. UsedSize: 1,
  639. }
  640. assert.True(t, conn.hasSpaceForCrossRename(quotaResult, -1, testFile))
  641. quotaResult = vfs.QuotaCheckResult{
  642. HasSpace: true,
  643. QuotaSize: 7,
  644. UsedSize: 0,
  645. }
  646. assert.False(t, conn.hasSpaceForCrossRename(quotaResult, -1, testFile))
  647. err = os.Remove(testFile)
  648. assert.NoError(t, err)
  649. testDir := filepath.Join(os.TempDir(), "testDir")
  650. err = os.MkdirAll(testDir, os.ModePerm)
  651. assert.NoError(t, err)
  652. err = ioutil.WriteFile(filepath.Join(testDir, "1"), []byte("1"), os.ModePerm)
  653. assert.NoError(t, err)
  654. err = ioutil.WriteFile(filepath.Join(testDir, "2"), []byte("2"), os.ModePerm)
  655. assert.NoError(t, err)
  656. quotaResult = vfs.QuotaCheckResult{
  657. HasSpace: true,
  658. QuotaFiles: 2,
  659. UsedFiles: 1,
  660. }
  661. assert.False(t, conn.hasSpaceForCrossRename(quotaResult, -1, testDir))
  662. quotaResult = vfs.QuotaCheckResult{
  663. HasSpace: true,
  664. QuotaFiles: 2,
  665. UsedFiles: 0,
  666. }
  667. assert.True(t, conn.hasSpaceForCrossRename(quotaResult, -1, testDir))
  668. err = os.RemoveAll(testDir)
  669. assert.NoError(t, err)
  670. }
  671. func TestRenamePermission(t *testing.T) {
  672. permissions := make(map[string][]string)
  673. permissions["/"] = []string{dataprovider.PermAny}
  674. permissions["/dir1"] = []string{dataprovider.PermRename}
  675. permissions["/dir2"] = []string{dataprovider.PermUpload}
  676. permissions["/dir3"] = []string{dataprovider.PermDelete}
  677. permissions["/dir4"] = []string{dataprovider.PermListItems}
  678. permissions["/dir5"] = []string{dataprovider.PermCreateDirs, dataprovider.PermUpload}
  679. permissions["/dir6"] = []string{dataprovider.PermCreateDirs, dataprovider.PermUpload,
  680. dataprovider.PermListItems, dataprovider.PermCreateSymlinks}
  681. permissions["/dir7"] = []string{dataprovider.PermAny}
  682. permissions["/dir8"] = []string{dataprovider.PermAny}
  683. user := dataprovider.User{
  684. Username: userTestUsername,
  685. Permissions: permissions,
  686. HomeDir: os.TempDir(),
  687. }
  688. fs, err := user.GetFilesystem("123")
  689. assert.NoError(t, err)
  690. conn := NewBaseConnection("", ProtocolSFTP, user, fs)
  691. request := sftp.NewRequest("Rename", "/testfile")
  692. request.Target = "/dir1/testfile"
  693. // rename is granted on Source and Target
  694. assert.True(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  695. request.Target = "/dir4/testfile"
  696. // rename is not granted on Target
  697. assert.False(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  698. request = sftp.NewRequest("Rename", "/dir1/testfile")
  699. request.Target = "/dir2/testfile" //nolint:goconst
  700. // rename is granted on Source but not on Target
  701. assert.False(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  702. request = sftp.NewRequest("Rename", "/dir4/testfile")
  703. request.Target = "/dir1/testfile"
  704. // rename is granted on Target but not on Source
  705. assert.False(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  706. request = sftp.NewRequest("Rename", "/dir4/testfile")
  707. request.Target = "/testfile"
  708. // rename is granted on Target but not on Source
  709. assert.False(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  710. request = sftp.NewRequest("Rename", "/dir3/testfile")
  711. request.Target = "/dir2/testfile"
  712. // delete is granted on Source and Upload on Target, the target is a file this is enough
  713. assert.True(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  714. request = sftp.NewRequest("Rename", "/dir2/testfile")
  715. request.Target = "/dir3/testfile"
  716. assert.False(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  717. tmpDir := filepath.Join(os.TempDir(), "dir")
  718. tmpDirLink := filepath.Join(os.TempDir(), "link")
  719. err = os.Mkdir(tmpDir, os.ModePerm)
  720. assert.NoError(t, err)
  721. err = os.Symlink(tmpDir, tmpDirLink)
  722. assert.NoError(t, err)
  723. request.Filepath = "/dir"
  724. request.Target = "/dir2/dir"
  725. // the source is a dir and the target has no createDirs perm
  726. info, err := os.Lstat(tmpDir)
  727. if assert.NoError(t, err) {
  728. assert.False(t, conn.isRenamePermitted(tmpDir, request.Filepath, request.Target, info))
  729. conn.User.Permissions["/dir2"] = []string{dataprovider.PermUpload, dataprovider.PermCreateDirs}
  730. // the source is a dir and the target has createDirs perm
  731. assert.True(t, conn.isRenamePermitted(tmpDir, request.Filepath, request.Target, info))
  732. request = sftp.NewRequest("Rename", "/testfile")
  733. request.Target = "/dir5/testfile"
  734. // the source is a dir and the target has createDirs and upload perm
  735. assert.True(t, conn.isRenamePermitted(tmpDir, request.Filepath, request.Target, info))
  736. }
  737. info, err = os.Lstat(tmpDirLink)
  738. if assert.NoError(t, err) {
  739. assert.True(t, info.Mode()&os.ModeSymlink == os.ModeSymlink)
  740. // the source is a symlink and the target has createDirs and upload perm
  741. assert.False(t, conn.isRenamePermitted(tmpDir, request.Filepath, request.Target, info))
  742. }
  743. err = os.RemoveAll(tmpDir)
  744. assert.NoError(t, err)
  745. err = os.Remove(tmpDirLink)
  746. assert.NoError(t, err)
  747. conn.User.VirtualFolders = append(conn.User.VirtualFolders, vfs.VirtualFolder{
  748. BaseVirtualFolder: vfs.BaseVirtualFolder{
  749. MappedPath: os.TempDir(),
  750. },
  751. VirtualPath: "/dir1",
  752. })
  753. request = sftp.NewRequest("Rename", "/dir1")
  754. request.Target = "/dir2/testfile"
  755. // renaming a virtual folder is not allowed
  756. assert.False(t, conn.isRenamePermitted("", request.Filepath, request.Target, nil))
  757. err = conn.checkRecursiveRenameDirPermissions("invalid", "invalid")
  758. assert.Error(t, err)
  759. dir3 := filepath.Join(conn.User.HomeDir, "dir3")
  760. dir6 := filepath.Join(conn.User.HomeDir, "dir6")
  761. err = os.MkdirAll(filepath.Join(dir3, "subdir"), os.ModePerm)
  762. assert.NoError(t, err)
  763. err = ioutil.WriteFile(filepath.Join(dir3, "subdir", "testfile"), []byte("test"), os.ModePerm)
  764. assert.NoError(t, err)
  765. err = conn.checkRecursiveRenameDirPermissions(dir3, dir6)
  766. assert.NoError(t, err)
  767. err = os.RemoveAll(dir3)
  768. assert.NoError(t, err)
  769. dir7 := filepath.Join(conn.User.HomeDir, "dir7")
  770. dir8 := filepath.Join(conn.User.HomeDir, "dir8")
  771. err = os.MkdirAll(filepath.Join(dir8, "subdir"), os.ModePerm)
  772. assert.NoError(t, err)
  773. err = ioutil.WriteFile(filepath.Join(dir8, "subdir", "testfile"), []byte("test"), os.ModePerm)
  774. assert.NoError(t, err)
  775. err = conn.checkRecursiveRenameDirPermissions(dir8, dir7)
  776. assert.NoError(t, err)
  777. err = os.RemoveAll(dir8)
  778. assert.NoError(t, err)
  779. assert.False(t, conn.isRenamePermitted(user.GetHomeDir(), "", "", nil))
  780. conn.User.Filters.FileExtensions = []dataprovider.ExtensionsFilter{
  781. {
  782. Path: "/p",
  783. AllowedExtensions: []string{},
  784. DeniedExtensions: []string{".zip"},
  785. },
  786. }
  787. testFile := filepath.Join(user.HomeDir, "testfile")
  788. err = ioutil.WriteFile(testFile, []byte("data"), os.ModePerm)
  789. assert.NoError(t, err)
  790. info, err = os.Stat(testFile)
  791. assert.NoError(t, err)
  792. assert.False(t, conn.isRenamePermitted(dir7, "/file", "/p/file.zip", info))
  793. err = os.Remove(testFile)
  794. assert.NoError(t, err)
  795. }
  796. func TestHasSpaceForRename(t *testing.T) {
  797. err := closeDataprovider()
  798. assert.NoError(t, err)
  799. _, err = initializeDataprovider(0)
  800. assert.NoError(t, err)
  801. user := dataprovider.User{
  802. Username: userTestUsername,
  803. HomeDir: filepath.Join(os.TempDir(), "home"),
  804. }
  805. mappedPath := filepath.Join(os.TempDir(), "vdir")
  806. user.Permissions = make(map[string][]string)
  807. user.Permissions["/"] = []string{dataprovider.PermAny}
  808. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  809. BaseVirtualFolder: vfs.BaseVirtualFolder{
  810. MappedPath: mappedPath,
  811. },
  812. VirtualPath: "/vdir1",
  813. })
  814. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  815. BaseVirtualFolder: vfs.BaseVirtualFolder{
  816. MappedPath: mappedPath,
  817. },
  818. VirtualPath: "/vdir2",
  819. QuotaSize: -1,
  820. QuotaFiles: -1,
  821. })
  822. fs, err := user.GetFilesystem("id")
  823. assert.NoError(t, err)
  824. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  825. // with quota tracking disabled hasSpaceForRename will always return true
  826. assert.True(t, c.hasSpaceForRename("", "", 0, ""))
  827. quotaResult := c.HasSpace(true, "")
  828. assert.True(t, quotaResult.HasSpace)
  829. err = closeDataprovider()
  830. assert.NoError(t, err)
  831. _, err = initializeDataprovider(-1)
  832. assert.NoError(t, err)
  833. // rename inside the same mapped path
  834. assert.True(t, c.hasSpaceForRename("/vdir1/file", "/vdir2/file", 0, filepath.Join(mappedPath, "file")))
  835. // rename between user root dir and a virtual folder included in user quota
  836. assert.True(t, c.hasSpaceForRename("/file", "/vdir2/file", 0, filepath.Join(mappedPath, "file")))
  837. assert.True(t, c.isCrossFoldersRequest("/file", "/vdir2/file"))
  838. }
  839. func TestUpdateQuotaAfterRename(t *testing.T) {
  840. user := dataprovider.User{
  841. Username: userTestUsername,
  842. HomeDir: filepath.Join(os.TempDir(), "home"),
  843. }
  844. mappedPath := filepath.Join(os.TempDir(), "vdir")
  845. user.Permissions = make(map[string][]string)
  846. user.Permissions["/"] = []string{dataprovider.PermAny}
  847. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  848. BaseVirtualFolder: vfs.BaseVirtualFolder{
  849. MappedPath: mappedPath,
  850. },
  851. VirtualPath: "/vdir",
  852. QuotaFiles: -1,
  853. QuotaSize: -1,
  854. })
  855. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  856. BaseVirtualFolder: vfs.BaseVirtualFolder{
  857. MappedPath: mappedPath,
  858. },
  859. VirtualPath: "/vdir1",
  860. QuotaFiles: -1,
  861. QuotaSize: -1,
  862. })
  863. err := os.MkdirAll(user.GetHomeDir(), os.ModePerm)
  864. assert.NoError(t, err)
  865. err = os.MkdirAll(mappedPath, os.ModePerm)
  866. assert.NoError(t, err)
  867. fs, err := user.GetFilesystem("id")
  868. assert.NoError(t, err)
  869. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  870. request := sftp.NewRequest("Rename", "/testfile")
  871. if runtime.GOOS != osWindows {
  872. request.Filepath = "/dir"
  873. request.Target = path.Join("/vdir", "dir")
  874. testDirPath := filepath.Join(mappedPath, "dir")
  875. err := os.MkdirAll(testDirPath, os.ModePerm)
  876. assert.NoError(t, err)
  877. err = os.Chmod(testDirPath, 0001)
  878. assert.NoError(t, err)
  879. err = c.updateQuotaAfterRename(request.Filepath, request.Target, testDirPath, 0)
  880. assert.Error(t, err)
  881. err = os.Chmod(testDirPath, os.ModePerm)
  882. assert.NoError(t, err)
  883. }
  884. testFile1 := "/testfile1"
  885. request.Target = testFile1
  886. request.Filepath = path.Join("/vdir", "file")
  887. err = c.updateQuotaAfterRename(request.Filepath, request.Target, filepath.Join(mappedPath, "file"), 0)
  888. assert.Error(t, err)
  889. err = ioutil.WriteFile(filepath.Join(mappedPath, "file"), []byte("test content"), os.ModePerm)
  890. assert.NoError(t, err)
  891. request.Filepath = testFile1
  892. request.Target = path.Join("/vdir", "file")
  893. err = c.updateQuotaAfterRename(request.Filepath, request.Target, filepath.Join(mappedPath, "file"), 12)
  894. assert.NoError(t, err)
  895. err = ioutil.WriteFile(filepath.Join(user.GetHomeDir(), "testfile1"), []byte("test content"), os.ModePerm)
  896. assert.NoError(t, err)
  897. request.Target = testFile1
  898. request.Filepath = path.Join("/vdir", "file")
  899. err = c.updateQuotaAfterRename(request.Filepath, request.Target, filepath.Join(mappedPath, "file"), 12)
  900. assert.NoError(t, err)
  901. request.Target = path.Join("/vdir1", "file")
  902. request.Filepath = path.Join("/vdir", "file")
  903. err = c.updateQuotaAfterRename(request.Filepath, request.Target, filepath.Join(mappedPath, "file"), 12)
  904. assert.NoError(t, err)
  905. err = os.RemoveAll(mappedPath)
  906. assert.NoError(t, err)
  907. err = os.RemoveAll(user.GetHomeDir())
  908. assert.NoError(t, err)
  909. }
  910. func TestHasSpace(t *testing.T) {
  911. user := dataprovider.User{
  912. Username: userTestUsername,
  913. HomeDir: filepath.Join(os.TempDir(), "home"),
  914. Password: userTestPwd,
  915. }
  916. mappedPath := filepath.Join(os.TempDir(), "vdir")
  917. user.Permissions = make(map[string][]string)
  918. user.Permissions["/"] = []string{dataprovider.PermAny}
  919. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  920. BaseVirtualFolder: vfs.BaseVirtualFolder{
  921. MappedPath: mappedPath,
  922. },
  923. VirtualPath: "/vdir",
  924. QuotaFiles: -1,
  925. QuotaSize: -1,
  926. })
  927. fs, err := user.GetFilesystem("id")
  928. assert.NoError(t, err)
  929. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  930. quotaResult := c.HasSpace(true, "/")
  931. assert.True(t, quotaResult.HasSpace)
  932. user.VirtualFolders[0].QuotaFiles = 0
  933. user.VirtualFolders[0].QuotaSize = 0
  934. err = dataprovider.AddUser(user)
  935. assert.NoError(t, err)
  936. user, err = dataprovider.UserExists(user.Username)
  937. assert.NoError(t, err)
  938. c.User = user
  939. quotaResult = c.HasSpace(true, "/vdir/file")
  940. assert.True(t, quotaResult.HasSpace)
  941. user.VirtualFolders[0].QuotaFiles = 10
  942. user.VirtualFolders[0].QuotaSize = 1048576
  943. err = dataprovider.UpdateUser(user)
  944. assert.NoError(t, err)
  945. c.User = user
  946. quotaResult = c.HasSpace(true, "/vdir/file1")
  947. assert.True(t, quotaResult.HasSpace)
  948. quotaResult = c.HasSpace(true, "/file")
  949. assert.True(t, quotaResult.HasSpace)
  950. folder, err := dataprovider.GetFolderByPath(mappedPath)
  951. assert.NoError(t, err)
  952. err = dataprovider.UpdateVirtualFolderQuota(folder, 10, 1048576, true)
  953. assert.NoError(t, err)
  954. quotaResult = c.HasSpace(true, "/vdir/file1")
  955. assert.False(t, quotaResult.HasSpace)
  956. err = dataprovider.DeleteUser(user)
  957. assert.NoError(t, err)
  958. err = dataprovider.DeleteFolder(folder)
  959. assert.NoError(t, err)
  960. }
  961. func TestUpdateQuotaMoveVFolders(t *testing.T) {
  962. user := dataprovider.User{
  963. Username: userTestUsername,
  964. HomeDir: filepath.Join(os.TempDir(), "home"),
  965. Password: userTestPwd,
  966. QuotaFiles: 100,
  967. }
  968. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  969. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  970. user.Permissions = make(map[string][]string)
  971. user.Permissions["/"] = []string{dataprovider.PermAny}
  972. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  973. BaseVirtualFolder: vfs.BaseVirtualFolder{
  974. MappedPath: mappedPath1,
  975. },
  976. VirtualPath: "/vdir1",
  977. QuotaFiles: -1,
  978. QuotaSize: -1,
  979. })
  980. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  981. BaseVirtualFolder: vfs.BaseVirtualFolder{
  982. MappedPath: mappedPath2,
  983. },
  984. VirtualPath: "/vdir2",
  985. QuotaFiles: -1,
  986. QuotaSize: -1,
  987. })
  988. err := dataprovider.AddUser(user)
  989. assert.NoError(t, err)
  990. user, err = dataprovider.UserExists(user.Username)
  991. assert.NoError(t, err)
  992. folder1, err := dataprovider.GetFolderByPath(mappedPath1)
  993. assert.NoError(t, err)
  994. folder2, err := dataprovider.GetFolderByPath(mappedPath2)
  995. assert.NoError(t, err)
  996. err = dataprovider.UpdateVirtualFolderQuota(folder1, 1, 100, true)
  997. assert.NoError(t, err)
  998. err = dataprovider.UpdateVirtualFolderQuota(folder2, 2, 150, true)
  999. assert.NoError(t, err)
  1000. fs, err := user.GetFilesystem("id")
  1001. assert.NoError(t, err)
  1002. c := NewBaseConnection("", ProtocolSFTP, user, fs)
  1003. c.updateQuotaMoveBetweenVFolders(user.VirtualFolders[0], user.VirtualFolders[1], -1, 100, 1)
  1004. folder1, err = dataprovider.GetFolderByPath(mappedPath1)
  1005. assert.NoError(t, err)
  1006. assert.Equal(t, 0, folder1.UsedQuotaFiles)
  1007. assert.Equal(t, int64(0), folder1.UsedQuotaSize)
  1008. folder2, err = dataprovider.GetFolderByPath(mappedPath2)
  1009. assert.NoError(t, err)
  1010. assert.Equal(t, 3, folder2.UsedQuotaFiles)
  1011. assert.Equal(t, int64(250), folder2.UsedQuotaSize)
  1012. c.updateQuotaMoveBetweenVFolders(user.VirtualFolders[1], user.VirtualFolders[0], 10, 100, 1)
  1013. folder1, err = dataprovider.GetFolderByPath(mappedPath1)
  1014. assert.NoError(t, err)
  1015. assert.Equal(t, 0, folder1.UsedQuotaFiles)
  1016. assert.Equal(t, int64(90), folder1.UsedQuotaSize)
  1017. folder2, err = dataprovider.GetFolderByPath(mappedPath2)
  1018. assert.NoError(t, err)
  1019. assert.Equal(t, 2, folder2.UsedQuotaFiles)
  1020. assert.Equal(t, int64(150), folder2.UsedQuotaSize)
  1021. err = dataprovider.UpdateUserQuota(user, 1, 100, true)
  1022. assert.NoError(t, err)
  1023. c.updateQuotaMoveFromVFolder(user.VirtualFolders[1], -1, 50, 1)
  1024. folder2, err = dataprovider.GetFolderByPath(mappedPath2)
  1025. assert.NoError(t, err)
  1026. assert.Equal(t, 1, folder2.UsedQuotaFiles)
  1027. assert.Equal(t, int64(100), folder2.UsedQuotaSize)
  1028. user, err = dataprovider.GetUserByID(user.ID)
  1029. assert.NoError(t, err)
  1030. assert.Equal(t, 1, user.UsedQuotaFiles)
  1031. assert.Equal(t, int64(100), user.UsedQuotaSize)
  1032. c.updateQuotaMoveToVFolder(user.VirtualFolders[1], -1, 100, 1)
  1033. folder2, err = dataprovider.GetFolderByPath(mappedPath2)
  1034. assert.NoError(t, err)
  1035. assert.Equal(t, 2, folder2.UsedQuotaFiles)
  1036. assert.Equal(t, int64(200), folder2.UsedQuotaSize)
  1037. user, err = dataprovider.GetUserByID(user.ID)
  1038. assert.NoError(t, err)
  1039. assert.Equal(t, 1, user.UsedQuotaFiles)
  1040. assert.Equal(t, int64(100), user.UsedQuotaSize)
  1041. err = dataprovider.DeleteUser(user)
  1042. assert.NoError(t, err)
  1043. err = dataprovider.DeleteFolder(folder1)
  1044. assert.NoError(t, err)
  1045. err = dataprovider.DeleteFolder(folder2)
  1046. assert.NoError(t, err)
  1047. }
  1048. func TestErrorsMapping(t *testing.T) {
  1049. fs := vfs.NewOsFs("", os.TempDir(), nil)
  1050. conn := NewBaseConnection("", ProtocolSFTP, dataprovider.User{}, fs)
  1051. for _, protocol := range supportedProtocols {
  1052. conn.SetProtocol(protocol)
  1053. err := conn.GetFsError(os.ErrNotExist)
  1054. if protocol == ProtocolSFTP {
  1055. assert.EqualError(t, err, sftp.ErrSSHFxNoSuchFile.Error())
  1056. } else if protocol == ProtocolWebDAV {
  1057. assert.EqualError(t, err, os.ErrNotExist.Error())
  1058. } else {
  1059. assert.EqualError(t, err, ErrNotExist.Error())
  1060. }
  1061. err = conn.GetFsError(os.ErrPermission)
  1062. if protocol == ProtocolSFTP {
  1063. assert.EqualError(t, err, sftp.ErrSSHFxPermissionDenied.Error())
  1064. } else {
  1065. assert.EqualError(t, err, ErrPermissionDenied.Error())
  1066. }
  1067. err = conn.GetFsError(os.ErrClosed)
  1068. if protocol == ProtocolSFTP {
  1069. assert.EqualError(t, err, sftp.ErrSSHFxFailure.Error())
  1070. } else {
  1071. assert.EqualError(t, err, ErrGenericFailure.Error())
  1072. }
  1073. err = conn.GetFsError(ErrPermissionDenied)
  1074. if protocol == ProtocolSFTP {
  1075. assert.EqualError(t, err, sftp.ErrSSHFxFailure.Error())
  1076. } else {
  1077. assert.EqualError(t, err, ErrPermissionDenied.Error())
  1078. }
  1079. err = conn.GetFsError(nil)
  1080. assert.NoError(t, err)
  1081. err = conn.GetOpUnsupportedError()
  1082. if protocol == ProtocolSFTP {
  1083. assert.EqualError(t, err, sftp.ErrSSHFxOpUnsupported.Error())
  1084. } else {
  1085. assert.EqualError(t, err, ErrOpUnsupported.Error())
  1086. }
  1087. }
  1088. }
  1089. func TestMaxWriteSize(t *testing.T) {
  1090. permissions := make(map[string][]string)
  1091. permissions["/"] = []string{dataprovider.PermAny}
  1092. user := dataprovider.User{
  1093. Username: userTestUsername,
  1094. Permissions: permissions,
  1095. HomeDir: filepath.Clean(os.TempDir()),
  1096. }
  1097. fs, err := user.GetFilesystem("123")
  1098. assert.NoError(t, err)
  1099. conn := NewBaseConnection("", ProtocolFTP, user, fs)
  1100. quotaResult := vfs.QuotaCheckResult{
  1101. HasSpace: true,
  1102. }
  1103. size, err := conn.GetMaxWriteSize(quotaResult, false, 0)
  1104. assert.NoError(t, err)
  1105. assert.Equal(t, int64(0), size)
  1106. conn.User.Filters.MaxUploadFileSize = 100
  1107. size, err = conn.GetMaxWriteSize(quotaResult, false, 0)
  1108. assert.NoError(t, err)
  1109. assert.Equal(t, int64(100), size)
  1110. quotaResult.QuotaSize = 1000
  1111. size, err = conn.GetMaxWriteSize(quotaResult, false, 50)
  1112. assert.NoError(t, err)
  1113. assert.Equal(t, int64(100), size)
  1114. quotaResult.QuotaSize = 1000
  1115. quotaResult.UsedSize = 990
  1116. size, err = conn.GetMaxWriteSize(quotaResult, false, 50)
  1117. assert.NoError(t, err)
  1118. assert.Equal(t, int64(60), size)
  1119. quotaResult.QuotaSize = 0
  1120. quotaResult.UsedSize = 0
  1121. size, err = conn.GetMaxWriteSize(quotaResult, true, 100)
  1122. assert.EqualError(t, err, ErrQuotaExceeded.Error())
  1123. assert.Equal(t, int64(0), size)
  1124. size, err = conn.GetMaxWriteSize(quotaResult, true, 10)
  1125. assert.NoError(t, err)
  1126. assert.Equal(t, int64(90), size)
  1127. conn.Fs = newMockOsFs(true, fs.ConnectionID(), user.GetHomeDir())
  1128. size, err = conn.GetMaxWriteSize(quotaResult, true, 100)
  1129. assert.EqualError(t, err, ErrOpUnsupported.Error())
  1130. assert.Equal(t, int64(0), size)
  1131. }