webdavd_test.go 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628
  1. package webdavd_test
  2. import (
  3. "bytes"
  4. "crypto/rand"
  5. "encoding/json"
  6. "errors"
  7. "fmt"
  8. "io"
  9. "io/ioutil"
  10. "net"
  11. "net/http"
  12. "os"
  13. "os/exec"
  14. "path"
  15. "path/filepath"
  16. "runtime"
  17. "strings"
  18. "sync"
  19. "testing"
  20. "time"
  21. "github.com/minio/sio"
  22. "github.com/rs/zerolog"
  23. "github.com/stretchr/testify/assert"
  24. "github.com/studio-b12/gowebdav"
  25. "github.com/drakkan/sftpgo/common"
  26. "github.com/drakkan/sftpgo/config"
  27. "github.com/drakkan/sftpgo/dataprovider"
  28. "github.com/drakkan/sftpgo/httpclient"
  29. "github.com/drakkan/sftpgo/httpd"
  30. "github.com/drakkan/sftpgo/kms"
  31. "github.com/drakkan/sftpgo/logger"
  32. "github.com/drakkan/sftpgo/vfs"
  33. "github.com/drakkan/sftpgo/webdavd"
  34. )
  35. const (
  36. logSender = "webavdTesting"
  37. webDavServerAddr = "127.0.0.1:9090"
  38. webDavServerPort = 9090
  39. sftpServerAddr = "127.0.0.1:9022"
  40. defaultUsername = "test_user_dav"
  41. defaultPassword = "test_password"
  42. configDir = ".."
  43. osWindows = "windows"
  44. webDavCert = `-----BEGIN CERTIFICATE-----
  45. MIICHTCCAaKgAwIBAgIUHnqw7QnB1Bj9oUsNpdb+ZkFPOxMwCgYIKoZIzj0EAwIw
  46. RTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGElu
  47. dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDAyMDQwOTUzMDRaFw0zMDAyMDEw
  48. OTUzMDRaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYD
  49. VQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwdjAQBgcqhkjOPQIBBgUrgQQA
  50. IgNiAARCjRMqJ85rzMC998X5z761nJ+xL3bkmGVqWvrJ51t5OxV0v25NsOgR82CA
  51. NXUgvhVYs7vNFN+jxtb2aj6Xg+/2G/BNxkaFspIVCzgWkxiz7XE4lgUwX44FCXZM
  52. 3+JeUbKjUzBRMB0GA1UdDgQWBBRhLw+/o3+Z02MI/d4tmaMui9W16jAfBgNVHSME
  53. GDAWgBRhLw+/o3+Z02MI/d4tmaMui9W16jAPBgNVHRMBAf8EBTADAQH/MAoGCCqG
  54. SM49BAMCA2kAMGYCMQDqLt2lm8mE+tGgtjDmtFgdOcI72HSbRQ74D5rYTzgST1rY
  55. /8wTi5xl8TiFUyLMUsICMQC5ViVxdXbhuG7gX6yEqSkMKZICHpO8hqFwOD/uaFVI
  56. dV4vKmHUzwK/eIx+8Ay3neE=
  57. -----END CERTIFICATE-----`
  58. webDavKey = `-----BEGIN EC PARAMETERS-----
  59. BgUrgQQAIg==
  60. -----END EC PARAMETERS-----
  61. -----BEGIN EC PRIVATE KEY-----
  62. MIGkAgEBBDCfMNsN6miEE3rVyUPwElfiJSWaR5huPCzUenZOfJT04GAcQdWvEju3
  63. UM2lmBLIXpGgBwYFK4EEACKhZANiAARCjRMqJ85rzMC998X5z761nJ+xL3bkmGVq
  64. WvrJ51t5OxV0v25NsOgR82CANXUgvhVYs7vNFN+jxtb2aj6Xg+/2G/BNxkaFspIV
  65. CzgWkxiz7XE4lgUwX44FCXZM3+JeUbI=
  66. -----END EC PRIVATE KEY-----`
  67. testFileName = "test_file_dav.dat"
  68. testDLFileName = "test_download_dav.dat"
  69. )
  70. var (
  71. allPerms = []string{dataprovider.PermAny}
  72. homeBasePath string
  73. hookCmdPath string
  74. extAuthPath string
  75. preLoginPath string
  76. postConnectPath string
  77. logFilePath string
  78. certPath string
  79. keyPath string
  80. )
  81. func TestMain(m *testing.M) {
  82. logFilePath = filepath.Join(configDir, "sftpgo_webdavd_test.log")
  83. logger.InitLogger(logFilePath, 5, 1, 28, false, zerolog.DebugLevel)
  84. err := config.LoadConfig(configDir, "")
  85. if err != nil {
  86. logger.ErrorToConsole("error loading configuration: %v", err)
  87. os.Exit(1)
  88. }
  89. providerConf := config.GetProviderConf()
  90. logger.InfoToConsole("Starting WebDAVD tests, provider: %v", providerConf.Driver)
  91. commonConf := config.GetCommonConfig()
  92. commonConf.UploadMode = 2
  93. homeBasePath = os.TempDir()
  94. if runtime.GOOS != osWindows {
  95. commonConf.Actions.ExecuteOn = []string{"download", "upload", "rename", "delete"}
  96. commonConf.Actions.Hook = hookCmdPath
  97. hookCmdPath, err = exec.LookPath("true")
  98. if err != nil {
  99. logger.Warn(logSender, "", "unable to get hook command: %v", err)
  100. logger.WarnToConsole("unable to get hook command: %v", err)
  101. }
  102. }
  103. certPath = filepath.Join(os.TempDir(), "test_dav.crt")
  104. keyPath = filepath.Join(os.TempDir(), "test_dav.key")
  105. err = ioutil.WriteFile(certPath, []byte(webDavCert), os.ModePerm)
  106. if err != nil {
  107. logger.ErrorToConsole("error writing WebDAV certificate: %v", err)
  108. os.Exit(1)
  109. }
  110. err = ioutil.WriteFile(keyPath, []byte(webDavKey), os.ModePerm)
  111. if err != nil {
  112. logger.ErrorToConsole("error writing WebDAV private key: %v", err)
  113. os.Exit(1)
  114. }
  115. common.Initialize(commonConf)
  116. err = dataprovider.Initialize(providerConf, configDir)
  117. if err != nil {
  118. logger.ErrorToConsole("error initializing data provider: %v", err)
  119. os.Exit(1)
  120. }
  121. httpConfig := config.GetHTTPConfig()
  122. httpConfig.Initialize(configDir)
  123. kmsConfig := config.GetKMSConfig()
  124. err = kmsConfig.Initialize()
  125. if err != nil {
  126. logger.ErrorToConsole("error initializing kms: %v", err)
  127. os.Exit(1)
  128. }
  129. httpdConf := config.GetHTTPDConfig()
  130. httpdConf.BindPort = 8078
  131. httpd.SetBaseURLAndCredentials("http://127.0.0.1:8078", "", "")
  132. // required to test sftpfs
  133. sftpdConf := config.GetSFTPDConfig()
  134. sftpdConf.BindPort = 9022
  135. sftpdConf.HostKeys = []string{filepath.Join(os.TempDir(), "id_ecdsa")}
  136. webDavConf := config.GetWebDAVDConfig()
  137. webDavConf.BindPort = webDavServerPort
  138. webDavConf.Cors = webdavd.Cors{
  139. Enabled: true,
  140. AllowedOrigins: []string{"*"},
  141. AllowedMethods: []string{
  142. http.MethodHead,
  143. http.MethodGet,
  144. http.MethodPost,
  145. http.MethodPut,
  146. http.MethodPatch,
  147. http.MethodDelete,
  148. },
  149. AllowedHeaders: []string{"*"},
  150. AllowCredentials: true,
  151. }
  152. status := webdavd.GetStatus()
  153. if status.IsActive {
  154. logger.ErrorToConsole("webdav server is already active")
  155. os.Exit(1)
  156. }
  157. extAuthPath = filepath.Join(homeBasePath, "extauth.sh")
  158. preLoginPath = filepath.Join(homeBasePath, "prelogin.sh")
  159. postConnectPath = filepath.Join(homeBasePath, "postconnect.sh")
  160. go func() {
  161. logger.Debug(logSender, "", "initializing WebDAV server with config %+v", webDavConf)
  162. if err := webDavConf.Initialize(configDir); err != nil {
  163. logger.ErrorToConsole("could not start WebDAV server: %v", err)
  164. os.Exit(1)
  165. }
  166. }()
  167. go func() {
  168. if err := httpdConf.Initialize(configDir, false); err != nil {
  169. logger.ErrorToConsole("could not start HTTP server: %v", err)
  170. os.Exit(1)
  171. }
  172. }()
  173. go func() {
  174. logger.Debug(logSender, "", "initializing SFTP server with config %+v", sftpdConf)
  175. if err := sftpdConf.Initialize(configDir); err != nil {
  176. logger.ErrorToConsole("could not start SFTP server: %v", err)
  177. os.Exit(1)
  178. }
  179. }()
  180. waitTCPListening(fmt.Sprintf("%s:%d", webDavConf.BindAddress, webDavConf.BindPort))
  181. waitTCPListening(fmt.Sprintf("%s:%d", httpdConf.BindAddress, httpdConf.BindPort))
  182. waitTCPListening(fmt.Sprintf("%s:%d", sftpdConf.BindAddress, sftpdConf.BindPort))
  183. webdavd.ReloadTLSCertificate() //nolint:errcheck
  184. exitCode := m.Run()
  185. os.Remove(logFilePath)
  186. os.Remove(extAuthPath)
  187. os.Remove(preLoginPath)
  188. os.Remove(postConnectPath)
  189. os.Remove(certPath)
  190. os.Remove(keyPath)
  191. os.Exit(exitCode)
  192. }
  193. func TestInitialization(t *testing.T) {
  194. cfg := webdavd.Configuration{
  195. BindPort: 1234,
  196. CertificateFile: "missing path",
  197. CertificateKeyFile: "bad path",
  198. }
  199. err := cfg.Initialize(configDir)
  200. assert.Error(t, err)
  201. cfg.Cache = config.GetWebDAVDConfig().Cache
  202. cfg.BindPort = webDavServerPort
  203. cfg.CertificateFile = certPath
  204. cfg.CertificateKeyFile = keyPath
  205. err = cfg.Initialize(configDir)
  206. assert.Error(t, err)
  207. err = webdavd.ReloadTLSCertificate()
  208. assert.NoError(t, err)
  209. }
  210. func TestBasicHandling(t *testing.T) {
  211. u := getTestUser()
  212. u.QuotaSize = 6553600
  213. localUser, _, err := httpd.AddUser(u, http.StatusOK)
  214. assert.NoError(t, err)
  215. u = getTestSFTPUser()
  216. u.QuotaSize = 6553600
  217. sftpUser, _, err := httpd.AddUser(u, http.StatusOK)
  218. assert.NoError(t, err)
  219. for _, user := range []dataprovider.User{localUser, sftpUser} {
  220. client := getWebDavClient(user)
  221. assert.NoError(t, checkBasicFunc(client))
  222. testFilePath := filepath.Join(homeBasePath, testFileName)
  223. testFileSize := int64(65535)
  224. expectedQuotaSize := testFileSize
  225. expectedQuotaFiles := 1
  226. err = createTestFile(testFilePath, testFileSize)
  227. assert.NoError(t, err)
  228. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  229. assert.NoError(t, err)
  230. // overwrite an existing file
  231. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  232. assert.NoError(t, err)
  233. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  234. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  235. assert.NoError(t, err)
  236. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  237. assert.NoError(t, err)
  238. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  239. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  240. err = client.Rename(testFileName, testFileName+"1", false)
  241. assert.NoError(t, err)
  242. _, err = client.Stat(testFileName)
  243. assert.Error(t, err)
  244. // the webdav client hide the error we check the quota
  245. err = client.Remove(testFileName)
  246. assert.NoError(t, err)
  247. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  248. assert.NoError(t, err)
  249. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  250. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  251. err = client.Remove(testFileName + "1")
  252. assert.NoError(t, err)
  253. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  254. assert.NoError(t, err)
  255. assert.Equal(t, expectedQuotaFiles-1, user.UsedQuotaFiles)
  256. assert.Equal(t, expectedQuotaSize-testFileSize, user.UsedQuotaSize)
  257. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  258. assert.Error(t, err)
  259. testDir := "testdir"
  260. err = client.Mkdir(testDir, os.ModePerm)
  261. assert.NoError(t, err)
  262. err = client.MkdirAll(path.Join(testDir, "sub", "sub"), os.ModePerm)
  263. assert.NoError(t, err)
  264. err = client.MkdirAll(path.Join(testDir, "sub1", "sub1"), os.ModePerm)
  265. assert.NoError(t, err)
  266. err = client.MkdirAll(path.Join(testDir, "sub2", "sub2"), os.ModePerm)
  267. assert.NoError(t, err)
  268. err = uploadFile(testFilePath, path.Join(testDir, testFileName+".txt"), testFileSize, client)
  269. assert.NoError(t, err)
  270. err = uploadFile(testFilePath, path.Join(testDir, testFileName), testFileSize, client)
  271. assert.NoError(t, err)
  272. files, err := client.ReadDir(testDir)
  273. assert.NoError(t, err)
  274. assert.Len(t, files, 5)
  275. err = client.Copy(testDir, testDir+"_copy", false)
  276. assert.NoError(t, err)
  277. err = client.RemoveAll(testDir)
  278. assert.NoError(t, err)
  279. err = os.Remove(testFilePath)
  280. assert.NoError(t, err)
  281. err = os.Remove(localDownloadPath)
  282. assert.NoError(t, err)
  283. if user.Username == defaultUsername {
  284. err = os.RemoveAll(user.GetHomeDir())
  285. assert.NoError(t, err)
  286. }
  287. }
  288. _, err = httpd.RemoveUser(sftpUser, http.StatusOK)
  289. assert.NoError(t, err)
  290. _, err = httpd.RemoveUser(localUser, http.StatusOK)
  291. assert.NoError(t, err)
  292. err = os.RemoveAll(localUser.GetHomeDir())
  293. assert.NoError(t, err)
  294. assert.Len(t, common.Connections.GetStats(), 0)
  295. status := webdavd.GetStatus()
  296. assert.True(t, status.IsActive)
  297. }
  298. func TestBasicHandlingCryptFs(t *testing.T) {
  299. u := getTestUserWithCryptFs()
  300. u.QuotaSize = 6553600
  301. user, _, err := httpd.AddUser(u, http.StatusOK)
  302. assert.NoError(t, err)
  303. client := getWebDavClient(user)
  304. assert.NoError(t, checkBasicFunc(client))
  305. testFilePath := filepath.Join(homeBasePath, testFileName)
  306. testFileSize := int64(65535)
  307. encryptedFileSize, err := getEncryptedFileSize(testFileSize)
  308. assert.NoError(t, err)
  309. expectedQuotaSize := user.UsedQuotaSize + encryptedFileSize
  310. expectedQuotaFiles := user.UsedQuotaFiles + 1
  311. err = createTestFile(testFilePath, testFileSize)
  312. assert.NoError(t, err)
  313. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  314. assert.NoError(t, err)
  315. // overwrite an existing file
  316. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  317. assert.NoError(t, err)
  318. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  319. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  320. assert.NoError(t, err)
  321. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  322. assert.NoError(t, err)
  323. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  324. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  325. files, err := client.ReadDir("/")
  326. assert.NoError(t, err)
  327. if assert.Len(t, files, 1) {
  328. assert.Equal(t, testFileSize, files[0].Size())
  329. }
  330. err = client.Remove(testFileName)
  331. assert.NoError(t, err)
  332. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  333. assert.NoError(t, err)
  334. assert.Equal(t, expectedQuotaFiles-1, user.UsedQuotaFiles)
  335. assert.Equal(t, expectedQuotaSize-encryptedFileSize, user.UsedQuotaSize)
  336. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  337. assert.Error(t, err)
  338. testDir := "testdir"
  339. err = client.Mkdir(testDir, os.ModePerm)
  340. assert.NoError(t, err)
  341. err = client.MkdirAll(path.Join(testDir, "sub", "sub"), os.ModePerm)
  342. assert.NoError(t, err)
  343. err = client.MkdirAll(path.Join(testDir, "sub1", "sub1"), os.ModePerm)
  344. assert.NoError(t, err)
  345. err = client.MkdirAll(path.Join(testDir, "sub2", "sub2"), os.ModePerm)
  346. assert.NoError(t, err)
  347. err = uploadFile(testFilePath, path.Join(testDir, testFileName+".txt"), testFileSize, client)
  348. assert.NoError(t, err)
  349. err = uploadFile(testFilePath, path.Join(testDir, testFileName), testFileSize, client)
  350. assert.NoError(t, err)
  351. files, err = client.ReadDir(testDir)
  352. assert.NoError(t, err)
  353. assert.Len(t, files, 5)
  354. for _, f := range files {
  355. if strings.HasPrefix(f.Name(), testFileName) {
  356. assert.Equal(t, testFileSize, f.Size())
  357. } else {
  358. assert.True(t, f.IsDir())
  359. }
  360. }
  361. err = os.Remove(testFilePath)
  362. assert.NoError(t, err)
  363. err = os.Remove(localDownloadPath)
  364. assert.NoError(t, err)
  365. _, err = httpd.RemoveUser(user, http.StatusOK)
  366. assert.NoError(t, err)
  367. err = os.RemoveAll(user.GetHomeDir())
  368. assert.NoError(t, err)
  369. assert.Len(t, common.Connections.GetStats(), 0)
  370. }
  371. func TestPropPatch(t *testing.T) {
  372. u := getTestUser()
  373. u.Username = u.Username + "1"
  374. localUser, _, err := httpd.AddUser(u, http.StatusOK)
  375. assert.NoError(t, err)
  376. sftpUser := getTestSFTPUser()
  377. sftpUser.FsConfig.SFTPConfig.Username = localUser.Username
  378. for _, u := range []dataprovider.User{getTestUser(), getTestUserWithCryptFs(), sftpUser} {
  379. user, _, err := httpd.AddUser(u, http.StatusOK)
  380. assert.NoError(t, err)
  381. client := getWebDavClient(user)
  382. assert.NoError(t, checkBasicFunc(client), sftpUser.Username)
  383. testFilePath := filepath.Join(homeBasePath, testFileName)
  384. testFileSize := int64(65535)
  385. err = createTestFile(testFilePath, testFileSize)
  386. assert.NoError(t, err)
  387. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  388. assert.NoError(t, err)
  389. httpClient := httpclient.GetHTTPClient()
  390. propatchBody := `<?xml version="1.0" encoding="utf-8" ?><D:propertyupdate xmlns:D="DAV:" xmlns:Z="urn:schemas-microsoft-com:"><D:set><D:prop><Z:Win32CreationTime>Wed, 04 Nov 2020 13:25:51 GMT</Z:Win32CreationTime><Z:Win32LastAccessTime>Sat, 05 Dec 2020 21:16:12 GMT</Z:Win32LastAccessTime><Z:Win32LastModifiedTime>Wed, 04 Nov 2020 13:25:51 GMT</Z:Win32LastModifiedTime><Z:Win32FileAttributes>00000000</Z:Win32FileAttributes></D:prop></D:set></D:propertyupdate>`
  391. req, err := http.NewRequest("PROPPATCH", fmt.Sprintf("http://%v/%v/%v", webDavServerAddr, user.Username, testFileName), bytes.NewReader([]byte(propatchBody)))
  392. assert.NoError(t, err)
  393. req.SetBasicAuth(u.Username, u.Password)
  394. resp, err := httpClient.Do(req)
  395. assert.NoError(t, err)
  396. assert.Equal(t, 207, resp.StatusCode)
  397. err = resp.Body.Close()
  398. assert.NoError(t, err)
  399. info, err := client.Stat(testFileName)
  400. if assert.NoError(t, err) {
  401. assert.Equal(t, testFileSize, info.Size())
  402. }
  403. err = os.Remove(testFilePath)
  404. assert.NoError(t, err)
  405. _, err = httpd.RemoveUser(user, http.StatusOK)
  406. assert.NoError(t, err)
  407. err = os.RemoveAll(user.GetHomeDir())
  408. assert.NoError(t, err)
  409. assert.Len(t, common.Connections.GetStats(), 0)
  410. }
  411. _, err = httpd.RemoveUser(localUser, http.StatusOK)
  412. assert.NoError(t, err)
  413. err = os.RemoveAll(localUser.GetHomeDir())
  414. assert.NoError(t, err)
  415. }
  416. func TestLoginInvalidPwd(t *testing.T) {
  417. u := getTestUser()
  418. user, _, err := httpd.AddUser(u, http.StatusOK)
  419. assert.NoError(t, err)
  420. client := getWebDavClient(user)
  421. assert.NoError(t, checkBasicFunc(client))
  422. user.Password = "wrong"
  423. client = getWebDavClient(user)
  424. assert.Error(t, checkBasicFunc(client))
  425. _, err = httpd.RemoveUser(user, http.StatusOK)
  426. assert.NoError(t, err)
  427. }
  428. func TestLoginInvalidURL(t *testing.T) {
  429. u := getTestUser()
  430. user, _, err := httpd.AddUser(u, http.StatusOK)
  431. assert.NoError(t, err)
  432. u1 := getTestUser()
  433. u1.Username = user.Username + "1"
  434. user1, _, err := httpd.AddUser(u1, http.StatusOK)
  435. assert.NoError(t, err)
  436. rootPath := fmt.Sprintf("http://%v/%v", webDavServerAddr, user.Username+"1")
  437. client := gowebdav.NewClient(rootPath, user.Username, defaultPassword)
  438. client.SetTimeout(5 * time.Second)
  439. assert.Error(t, checkBasicFunc(client))
  440. _, err = httpd.RemoveUser(user, http.StatusOK)
  441. assert.NoError(t, err)
  442. _, err = httpd.RemoveUser(user1, http.StatusOK)
  443. assert.NoError(t, err)
  444. }
  445. func TestRootRedirect(t *testing.T) {
  446. errRedirect := errors.New("redirect error")
  447. u := getTestUser()
  448. user, _, err := httpd.AddUser(u, http.StatusOK)
  449. assert.NoError(t, err)
  450. client := getWebDavClient(user)
  451. assert.NoError(t, checkBasicFunc(client))
  452. rootPath := fmt.Sprintf("http://%v/", webDavServerAddr)
  453. httpClient := httpclient.GetHTTPClient()
  454. httpClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
  455. return errRedirect
  456. }
  457. req, err := http.NewRequest(http.MethodOptions, rootPath, nil)
  458. assert.NoError(t, err)
  459. req.SetBasicAuth(u.Username, u.Password)
  460. resp, err := httpClient.Do(req)
  461. if assert.Error(t, err) {
  462. assert.Contains(t, err.Error(), errRedirect.Error())
  463. }
  464. err = resp.Body.Close()
  465. assert.NoError(t, err)
  466. req, err = http.NewRequest(http.MethodGet, rootPath, nil)
  467. assert.NoError(t, err)
  468. req.SetBasicAuth(u.Username, u.Password)
  469. resp, err = httpClient.Do(req)
  470. if assert.Error(t, err) {
  471. assert.Contains(t, err.Error(), errRedirect.Error())
  472. }
  473. err = resp.Body.Close()
  474. assert.NoError(t, err)
  475. req, err = http.NewRequest("PROPFIND", rootPath, nil)
  476. assert.NoError(t, err)
  477. req.SetBasicAuth(u.Username, u.Password)
  478. resp, err = httpClient.Do(req)
  479. if assert.Error(t, err) {
  480. assert.Contains(t, err.Error(), errRedirect.Error())
  481. }
  482. err = resp.Body.Close()
  483. assert.NoError(t, err)
  484. _, err = httpd.RemoveUser(user, http.StatusOK)
  485. assert.NoError(t, err)
  486. }
  487. func TestLoginExternalAuth(t *testing.T) {
  488. if runtime.GOOS == osWindows {
  489. t.Skip("this test is not available on Windows")
  490. }
  491. u := getTestUser()
  492. err := dataprovider.Close()
  493. assert.NoError(t, err)
  494. err = config.LoadConfig(configDir, "")
  495. assert.NoError(t, err)
  496. providerConf := config.GetProviderConf()
  497. err = ioutil.WriteFile(extAuthPath, getExtAuthScriptContent(u, false, ""), os.ModePerm)
  498. assert.NoError(t, err)
  499. providerConf.ExternalAuthHook = extAuthPath
  500. providerConf.ExternalAuthScope = 0
  501. err = dataprovider.Initialize(providerConf, configDir)
  502. assert.NoError(t, err)
  503. client := getWebDavClient(u)
  504. assert.NoError(t, checkBasicFunc(client))
  505. u.Username = defaultUsername + "1"
  506. client = getWebDavClient(u)
  507. assert.Error(t, checkBasicFunc(client))
  508. users, _, err := httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  509. assert.NoError(t, err)
  510. if assert.Len(t, users, 1) {
  511. user := users[0]
  512. assert.Equal(t, defaultUsername, user.Username)
  513. _, err = httpd.RemoveUser(user, http.StatusOK)
  514. assert.NoError(t, err)
  515. err = os.RemoveAll(user.GetHomeDir())
  516. assert.NoError(t, err)
  517. }
  518. err = dataprovider.Close()
  519. assert.NoError(t, err)
  520. err = config.LoadConfig(configDir, "")
  521. assert.NoError(t, err)
  522. providerConf = config.GetProviderConf()
  523. err = dataprovider.Initialize(providerConf, configDir)
  524. assert.NoError(t, err)
  525. err = os.Remove(extAuthPath)
  526. assert.NoError(t, err)
  527. }
  528. func TestPreLoginHook(t *testing.T) {
  529. if runtime.GOOS == osWindows {
  530. t.Skip("this test is not available on Windows")
  531. }
  532. u := getTestUser()
  533. err := dataprovider.Close()
  534. assert.NoError(t, err)
  535. err = config.LoadConfig(configDir, "")
  536. assert.NoError(t, err)
  537. providerConf := config.GetProviderConf()
  538. err = ioutil.WriteFile(preLoginPath, getPreLoginScriptContent(u, false), os.ModePerm)
  539. assert.NoError(t, err)
  540. providerConf.PreLoginHook = preLoginPath
  541. err = dataprovider.Initialize(providerConf, configDir)
  542. assert.NoError(t, err)
  543. users, _, err := httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  544. assert.NoError(t, err)
  545. assert.Equal(t, 0, len(users))
  546. client := getWebDavClient(u)
  547. assert.NoError(t, checkBasicFunc(client))
  548. users, _, err = httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  549. assert.NoError(t, err)
  550. assert.Equal(t, 1, len(users))
  551. user := users[0]
  552. // test login with an existing user
  553. client = getWebDavClient(user)
  554. assert.NoError(t, checkBasicFunc(client))
  555. err = ioutil.WriteFile(preLoginPath, getPreLoginScriptContent(user, true), os.ModePerm)
  556. assert.NoError(t, err)
  557. // update the user to remove it from the cache
  558. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  559. assert.NoError(t, err)
  560. client = getWebDavClient(user)
  561. assert.Error(t, checkBasicFunc(client))
  562. // update the user to remove it from the cache
  563. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  564. assert.NoError(t, err)
  565. user.Status = 0
  566. err = ioutil.WriteFile(preLoginPath, getPreLoginScriptContent(user, false), os.ModePerm)
  567. assert.NoError(t, err)
  568. client = getWebDavClient(user)
  569. assert.Error(t, checkBasicFunc(client))
  570. _, err = httpd.RemoveUser(user, http.StatusOK)
  571. assert.NoError(t, err)
  572. err = os.RemoveAll(user.GetHomeDir())
  573. assert.NoError(t, err)
  574. err = dataprovider.Close()
  575. assert.NoError(t, err)
  576. err = config.LoadConfig(configDir, "")
  577. assert.NoError(t, err)
  578. providerConf = config.GetProviderConf()
  579. err = dataprovider.Initialize(providerConf, configDir)
  580. assert.NoError(t, err)
  581. err = os.Remove(preLoginPath)
  582. assert.NoError(t, err)
  583. }
  584. func TestPostConnectHook(t *testing.T) {
  585. if runtime.GOOS == osWindows {
  586. t.Skip("this test is not available on Windows")
  587. }
  588. common.Config.PostConnectHook = postConnectPath
  589. u := getTestUser()
  590. user, _, err := httpd.AddUser(u, http.StatusOK)
  591. assert.NoError(t, err)
  592. err = ioutil.WriteFile(postConnectPath, getPostConnectScriptContent(0), os.ModePerm)
  593. assert.NoError(t, err)
  594. client := getWebDavClient(user)
  595. assert.NoError(t, checkBasicFunc(client))
  596. err = ioutil.WriteFile(postConnectPath, getPostConnectScriptContent(1), os.ModePerm)
  597. assert.NoError(t, err)
  598. assert.Error(t, checkBasicFunc(client))
  599. common.Config.PostConnectHook = "http://127.0.0.1:8078/api/v1/version"
  600. assert.NoError(t, checkBasicFunc(client))
  601. common.Config.PostConnectHook = "http://127.0.0.1:8078/notfound"
  602. assert.Error(t, checkBasicFunc(client))
  603. _, err = httpd.RemoveUser(user, http.StatusOK)
  604. assert.NoError(t, err)
  605. err = os.RemoveAll(user.GetHomeDir())
  606. assert.NoError(t, err)
  607. common.Config.PostConnectHook = ""
  608. }
  609. func TestMaxConnections(t *testing.T) {
  610. oldValue := common.Config.MaxTotalConnections
  611. common.Config.MaxTotalConnections = 1
  612. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  613. assert.NoError(t, err)
  614. client := getWebDavClient(user)
  615. assert.NoError(t, checkBasicFunc(client))
  616. // now add a fake connection
  617. fs := vfs.NewOsFs("id", os.TempDir(), nil)
  618. connection := &webdavd.Connection{
  619. BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, user, fs),
  620. }
  621. common.Connections.Add(connection)
  622. assert.Error(t, checkBasicFunc(client))
  623. common.Connections.Remove(connection.GetID())
  624. _, err = httpd.RemoveUser(user, http.StatusOK)
  625. assert.NoError(t, err)
  626. err = os.RemoveAll(user.GetHomeDir())
  627. assert.NoError(t, err)
  628. assert.Len(t, common.Connections.GetStats(), 0)
  629. common.Config.MaxTotalConnections = oldValue
  630. }
  631. func TestMaxSessions(t *testing.T) {
  632. u := getTestUser()
  633. u.MaxSessions = 1
  634. user, _, err := httpd.AddUser(u, http.StatusOK)
  635. assert.NoError(t, err)
  636. client := getWebDavClient(user)
  637. assert.NoError(t, checkBasicFunc(client))
  638. // now add a fake connection
  639. fs := vfs.NewOsFs("id", os.TempDir(), nil)
  640. connection := &webdavd.Connection{
  641. BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, user, fs),
  642. }
  643. common.Connections.Add(connection)
  644. assert.Error(t, checkBasicFunc(client))
  645. common.Connections.Remove(connection.GetID())
  646. _, err = httpd.RemoveUser(user, http.StatusOK)
  647. assert.NoError(t, err)
  648. err = os.RemoveAll(user.GetHomeDir())
  649. assert.NoError(t, err)
  650. assert.Len(t, common.Connections.GetStats(), 0)
  651. }
  652. func TestLoginWithIPilters(t *testing.T) {
  653. u := getTestUser()
  654. u.Filters.DeniedIP = []string{"192.167.0.0/24", "172.18.0.0/16"}
  655. u.Filters.AllowedIP = []string{"172.19.0.0/16"}
  656. user, _, err := httpd.AddUser(u, http.StatusOK)
  657. assert.NoError(t, err)
  658. client := getWebDavClient(user)
  659. assert.Error(t, checkBasicFunc(client))
  660. _, err = httpd.RemoveUser(user, http.StatusOK)
  661. assert.NoError(t, err)
  662. err = os.RemoveAll(user.GetHomeDir())
  663. assert.NoError(t, err)
  664. }
  665. func TestDownloadErrors(t *testing.T) {
  666. u := getTestUser()
  667. u.QuotaFiles = 1
  668. subDir1 := "sub1"
  669. subDir2 := "sub2"
  670. u.Permissions[path.Join("/", subDir1)] = []string{dataprovider.PermListItems}
  671. u.Permissions[path.Join("/", subDir2)] = []string{dataprovider.PermListItems, dataprovider.PermUpload,
  672. dataprovider.PermDelete, dataprovider.PermDownload}
  673. // use an unknown mime to trigger content type detection
  674. u.Filters.FileExtensions = []dataprovider.ExtensionsFilter{
  675. {
  676. Path: "/sub2",
  677. AllowedExtensions: []string{},
  678. DeniedExtensions: []string{".zipp"},
  679. },
  680. }
  681. u.Filters.FilePatterns = []dataprovider.PatternsFilter{
  682. {
  683. Path: "/sub2",
  684. AllowedPatterns: []string{},
  685. DeniedPatterns: []string{"*.jpg"},
  686. },
  687. }
  688. user, _, err := httpd.AddUser(u, http.StatusOK)
  689. assert.NoError(t, err)
  690. client := getWebDavClient(user)
  691. testFilePath1 := filepath.Join(user.HomeDir, subDir1, "file.zipp")
  692. testFilePath2 := filepath.Join(user.HomeDir, subDir2, "file.zipp")
  693. testFilePath3 := filepath.Join(user.HomeDir, subDir2, "file.jpg")
  694. err = os.MkdirAll(filepath.Dir(testFilePath1), os.ModePerm)
  695. assert.NoError(t, err)
  696. err = os.MkdirAll(filepath.Dir(testFilePath2), os.ModePerm)
  697. assert.NoError(t, err)
  698. err = ioutil.WriteFile(testFilePath1, []byte("file1"), os.ModePerm)
  699. assert.NoError(t, err)
  700. err = ioutil.WriteFile(testFilePath2, []byte("file2"), os.ModePerm)
  701. assert.NoError(t, err)
  702. err = ioutil.WriteFile(testFilePath3, []byte("file3"), os.ModePerm)
  703. assert.NoError(t, err)
  704. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  705. err = downloadFile(path.Join("/", subDir1, "file.zipp"), localDownloadPath, 5, client)
  706. assert.Error(t, err)
  707. err = downloadFile(path.Join("/", subDir2, "file.zipp"), localDownloadPath, 5, client)
  708. assert.Error(t, err)
  709. err = downloadFile(path.Join("/", subDir2, "file.jpg"), localDownloadPath, 5, client)
  710. assert.Error(t, err)
  711. err = downloadFile(path.Join("missing.zip"), localDownloadPath, 5, client)
  712. assert.Error(t, err)
  713. err = os.Remove(localDownloadPath)
  714. assert.NoError(t, err)
  715. _, err = httpd.RemoveUser(user, http.StatusOK)
  716. assert.NoError(t, err)
  717. err = os.RemoveAll(user.GetHomeDir())
  718. assert.NoError(t, err)
  719. }
  720. func TestUploadErrors(t *testing.T) {
  721. u := getTestUser()
  722. u.QuotaSize = 65535
  723. subDir1 := "sub1"
  724. subDir2 := "sub2"
  725. // we need download permission to get size since PROPFIND will open the file
  726. u.Permissions[path.Join("/", subDir1)] = []string{dataprovider.PermListItems, dataprovider.PermDownload}
  727. u.Permissions[path.Join("/", subDir2)] = []string{dataprovider.PermListItems, dataprovider.PermUpload,
  728. dataprovider.PermDelete, dataprovider.PermDownload}
  729. u.Filters.FileExtensions = []dataprovider.ExtensionsFilter{
  730. {
  731. Path: "/sub2",
  732. AllowedExtensions: []string{},
  733. DeniedExtensions: []string{".zip"},
  734. },
  735. }
  736. user, _, err := httpd.AddUser(u, http.StatusOK)
  737. assert.NoError(t, err)
  738. client := getWebDavClient(user)
  739. testFilePath := filepath.Join(homeBasePath, testFileName)
  740. testFileSize := user.QuotaSize
  741. err = createTestFile(testFilePath, testFileSize)
  742. assert.NoError(t, err)
  743. err = client.Mkdir(subDir1, os.ModePerm)
  744. assert.NoError(t, err)
  745. err = client.Mkdir(subDir2, os.ModePerm)
  746. assert.NoError(t, err)
  747. err = uploadFile(testFilePath, path.Join(subDir1, testFileName), testFileSize, client)
  748. assert.Error(t, err)
  749. err = uploadFile(testFilePath, path.Join(subDir2, testFileName+".zip"), testFileSize, client)
  750. assert.Error(t, err)
  751. err = uploadFile(testFilePath, path.Join(subDir2, testFileName), testFileSize, client)
  752. assert.NoError(t, err)
  753. err = client.Rename(path.Join(subDir2, testFileName), path.Join(subDir1, testFileName), false)
  754. assert.Error(t, err)
  755. err = uploadFile(testFilePath, path.Join(subDir2, testFileName), testFileSize, client)
  756. assert.Error(t, err)
  757. err = uploadFile(testFilePath, subDir1, testFileSize, client)
  758. assert.Error(t, err)
  759. // overquota
  760. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  761. assert.Error(t, err)
  762. err = client.Remove(path.Join(subDir2, testFileName))
  763. assert.NoError(t, err)
  764. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  765. assert.NoError(t, err)
  766. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  767. assert.Error(t, err)
  768. err = os.Remove(testFilePath)
  769. assert.NoError(t, err)
  770. _, err = httpd.RemoveUser(user, http.StatusOK)
  771. assert.NoError(t, err)
  772. err = os.RemoveAll(user.GetHomeDir())
  773. assert.NoError(t, err)
  774. }
  775. func TestDeniedLoginMethod(t *testing.T) {
  776. u := getTestUser()
  777. u.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword}
  778. user, _, err := httpd.AddUser(u, http.StatusOK)
  779. assert.NoError(t, err)
  780. client := getWebDavClient(user)
  781. assert.Error(t, checkBasicFunc(client))
  782. user.Filters.DeniedLoginMethods = []string{dataprovider.SSHLoginMethodPublicKey, dataprovider.SSHLoginMethodKeyAndKeyboardInt}
  783. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  784. assert.NoError(t, err)
  785. client = getWebDavClient(user)
  786. assert.NoError(t, checkBasicFunc(client))
  787. _, err = httpd.RemoveUser(user, http.StatusOK)
  788. assert.NoError(t, err)
  789. err = os.RemoveAll(user.GetHomeDir())
  790. assert.NoError(t, err)
  791. }
  792. func TestDeniedProtocols(t *testing.T) {
  793. u := getTestUser()
  794. u.Filters.DeniedProtocols = []string{common.ProtocolWebDAV}
  795. user, _, err := httpd.AddUser(u, http.StatusOK)
  796. assert.NoError(t, err)
  797. client := getWebDavClient(user)
  798. assert.Error(t, checkBasicFunc(client))
  799. user.Filters.DeniedProtocols = []string{common.ProtocolSSH, common.ProtocolFTP}
  800. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  801. assert.NoError(t, err)
  802. client = getWebDavClient(user)
  803. assert.NoError(t, checkBasicFunc(client))
  804. _, err = httpd.RemoveUser(user, http.StatusOK)
  805. assert.NoError(t, err)
  806. err = os.RemoveAll(user.GetHomeDir())
  807. assert.NoError(t, err)
  808. }
  809. func TestQuotaLimits(t *testing.T) {
  810. u := getTestUser()
  811. u.QuotaFiles = 1
  812. localUser, _, err := httpd.AddUser(u, http.StatusOK)
  813. assert.NoError(t, err)
  814. u = getTestSFTPUser()
  815. u.QuotaFiles = 1
  816. sftpUser, _, err := httpd.AddUser(u, http.StatusOK)
  817. assert.NoError(t, err)
  818. for _, user := range []dataprovider.User{localUser, sftpUser} {
  819. testFileSize := int64(65535)
  820. testFilePath := filepath.Join(homeBasePath, testFileName)
  821. err = createTestFile(testFilePath, testFileSize)
  822. assert.NoError(t, err)
  823. testFileSize1 := int64(131072)
  824. testFileName1 := "test_file1.dat"
  825. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  826. err = createTestFile(testFilePath1, testFileSize1)
  827. assert.NoError(t, err)
  828. testFileSize2 := int64(32768)
  829. testFileName2 := "test_file2.dat"
  830. testFilePath2 := filepath.Join(homeBasePath, testFileName2)
  831. err = createTestFile(testFilePath2, testFileSize2)
  832. assert.NoError(t, err)
  833. client := getWebDavClient(user)
  834. // test quota files
  835. err = uploadFile(testFilePath, testFileName+".quota", testFileSize, client)
  836. assert.NoError(t, err)
  837. err = uploadFile(testFilePath, testFileName+".quota1", testFileSize, client)
  838. assert.Error(t, err)
  839. err = client.Rename(testFileName+".quota", testFileName, false)
  840. assert.NoError(t, err)
  841. files, err := client.ReadDir("/")
  842. assert.NoError(t, err)
  843. assert.Len(t, files, 1)
  844. // test quota size
  845. user.QuotaSize = testFileSize - 1
  846. user.QuotaFiles = 0
  847. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  848. assert.NoError(t, err)
  849. err = uploadFile(testFilePath, testFileName+".quota", testFileSize, client)
  850. assert.Error(t, err)
  851. err = client.Rename(testFileName, testFileName+".quota", false)
  852. assert.NoError(t, err)
  853. // now test quota limits while uploading the current file, we have 1 bytes remaining
  854. user.QuotaSize = testFileSize + 1
  855. user.QuotaFiles = 0
  856. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  857. assert.NoError(t, err)
  858. err = uploadFile(testFilePath1, testFileName1, testFileSize1, client)
  859. assert.Error(t, err)
  860. _, err = client.Stat(testFileName1)
  861. assert.Error(t, err)
  862. err = client.Rename(testFileName+".quota", testFileName, false)
  863. assert.NoError(t, err)
  864. // overwriting an existing file will work if the resulting size is lesser or equal than the current one
  865. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  866. assert.NoError(t, err)
  867. err = uploadFile(testFilePath2, testFileName, testFileSize2, client)
  868. assert.NoError(t, err)
  869. err = uploadFile(testFilePath1, testFileName, testFileSize1, client)
  870. assert.Error(t, err)
  871. err = uploadFile(testFilePath2, testFileName, testFileSize2, client)
  872. assert.NoError(t, err)
  873. err = os.Remove(testFilePath)
  874. assert.NoError(t, err)
  875. err = os.Remove(testFilePath1)
  876. assert.NoError(t, err)
  877. err = os.Remove(testFilePath2)
  878. assert.NoError(t, err)
  879. if user.Username == defaultUsername {
  880. err = os.RemoveAll(user.GetHomeDir())
  881. assert.NoError(t, err)
  882. user.QuotaFiles = 0
  883. user.QuotaSize = 0
  884. _, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  885. assert.NoError(t, err)
  886. }
  887. }
  888. _, err = httpd.RemoveUser(sftpUser, http.StatusOK)
  889. assert.NoError(t, err)
  890. _, err = httpd.RemoveUser(localUser, http.StatusOK)
  891. assert.NoError(t, err)
  892. err = os.RemoveAll(localUser.GetHomeDir())
  893. assert.NoError(t, err)
  894. }
  895. func TestUploadMaxSize(t *testing.T) {
  896. testFileSize := int64(65535)
  897. u := getTestUser()
  898. u.Filters.MaxUploadFileSize = testFileSize + 1
  899. localUser, _, err := httpd.AddUser(u, http.StatusOK)
  900. assert.NoError(t, err)
  901. u = getTestSFTPUser()
  902. u.Filters.MaxUploadFileSize = testFileSize + 1
  903. sftpUser, _, err := httpd.AddUser(u, http.StatusOK)
  904. assert.NoError(t, err)
  905. for _, user := range []dataprovider.User{localUser, sftpUser} {
  906. testFilePath := filepath.Join(homeBasePath, testFileName)
  907. err = createTestFile(testFilePath, testFileSize)
  908. assert.NoError(t, err)
  909. testFileSize1 := int64(131072)
  910. testFileName1 := "test_file_dav1.dat"
  911. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  912. err = createTestFile(testFilePath1, testFileSize1)
  913. assert.NoError(t, err)
  914. client := getWebDavClient(user)
  915. err = uploadFile(testFilePath1, testFileName1, testFileSize1, client)
  916. assert.Error(t, err)
  917. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  918. assert.NoError(t, err)
  919. // now test overwrite an existing file with a size bigger than the allowed one
  920. err = createTestFile(filepath.Join(user.GetHomeDir(), testFileName1), testFileSize1)
  921. assert.NoError(t, err)
  922. err = uploadFile(testFilePath1, testFileName1, testFileSize1, client)
  923. assert.Error(t, err)
  924. err = os.Remove(testFilePath)
  925. assert.NoError(t, err)
  926. err = os.Remove(testFilePath1)
  927. assert.NoError(t, err)
  928. if user.Username == defaultUsername {
  929. err = os.RemoveAll(user.GetHomeDir())
  930. assert.NoError(t, err)
  931. user.Filters.MaxUploadFileSize = 65536000
  932. _, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  933. assert.NoError(t, err)
  934. }
  935. }
  936. _, err = httpd.RemoveUser(sftpUser, http.StatusOK)
  937. assert.NoError(t, err)
  938. _, err = httpd.RemoveUser(localUser, http.StatusOK)
  939. assert.NoError(t, err)
  940. err = os.RemoveAll(localUser.GetHomeDir())
  941. assert.NoError(t, err)
  942. }
  943. func TestClientClose(t *testing.T) {
  944. u := getTestUser()
  945. u.UploadBandwidth = 64
  946. u.DownloadBandwidth = 64
  947. localUser, _, err := httpd.AddUser(u, http.StatusOK)
  948. assert.NoError(t, err)
  949. u = getTestSFTPUser()
  950. u.UploadBandwidth = 64
  951. u.DownloadBandwidth = 64
  952. sftpUser, _, err := httpd.AddUser(u, http.StatusOK)
  953. assert.NoError(t, err)
  954. for _, user := range []dataprovider.User{localUser, sftpUser} {
  955. testFileSize := int64(1048576)
  956. testFilePath := filepath.Join(homeBasePath, testFileName)
  957. err = createTestFile(testFilePath, testFileSize)
  958. assert.NoError(t, err)
  959. client := getWebDavClient(user)
  960. assert.NoError(t, checkBasicFunc(client))
  961. var wg sync.WaitGroup
  962. wg.Add(1)
  963. go func() {
  964. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  965. assert.Error(t, err)
  966. wg.Done()
  967. }()
  968. assert.Eventually(t, func() bool {
  969. for _, stat := range common.Connections.GetStats() {
  970. if len(stat.Transfers) > 0 {
  971. return true
  972. }
  973. }
  974. return false
  975. }, 1*time.Second, 50*time.Millisecond)
  976. for _, stat := range common.Connections.GetStats() {
  977. common.Connections.Close(stat.ConnectionID)
  978. }
  979. wg.Wait()
  980. assert.Eventually(t, func() bool { return len(common.Connections.GetStats()) == 0 },
  981. 1*time.Second, 100*time.Millisecond)
  982. err = os.Remove(testFilePath)
  983. assert.NoError(t, err)
  984. testFilePath = filepath.Join(user.HomeDir, testFileName)
  985. err = createTestFile(testFilePath, testFileSize)
  986. assert.NoError(t, err)
  987. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  988. wg.Add(1)
  989. go func() {
  990. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  991. assert.Error(t, err)
  992. wg.Done()
  993. }()
  994. assert.Eventually(t, func() bool {
  995. for _, stat := range common.Connections.GetStats() {
  996. if len(stat.Transfers) > 0 {
  997. return true
  998. }
  999. }
  1000. return false
  1001. }, 1*time.Second, 50*time.Millisecond)
  1002. for _, stat := range common.Connections.GetStats() {
  1003. common.Connections.Close(stat.ConnectionID)
  1004. }
  1005. wg.Wait()
  1006. assert.Eventually(t, func() bool { return len(common.Connections.GetStats()) == 0 },
  1007. 1*time.Second, 100*time.Millisecond)
  1008. err = os.Remove(localDownloadPath)
  1009. assert.NoError(t, err)
  1010. }
  1011. _, err = httpd.RemoveUser(sftpUser, http.StatusOK)
  1012. assert.NoError(t, err)
  1013. _, err = httpd.RemoveUser(localUser, http.StatusOK)
  1014. assert.NoError(t, err)
  1015. err = os.RemoveAll(localUser.GetHomeDir())
  1016. assert.NoError(t, err)
  1017. }
  1018. func TestLoginWithDatabaseCredentials(t *testing.T) {
  1019. u := getTestUser()
  1020. u.FsConfig.Provider = dataprovider.GCSFilesystemProvider
  1021. u.FsConfig.GCSConfig.Bucket = "test"
  1022. u.FsConfig.GCSConfig.Credentials = kms.NewPlainSecret(`{ "type": "service_account" }`)
  1023. providerConf := config.GetProviderConf()
  1024. providerConf.PreferDatabaseCredentials = true
  1025. credentialsFile := filepath.Join(providerConf.CredentialsPath, fmt.Sprintf("%v_gcs_credentials.json", u.Username))
  1026. if !filepath.IsAbs(credentialsFile) {
  1027. credentialsFile = filepath.Join(configDir, credentialsFile)
  1028. }
  1029. assert.NoError(t, dataprovider.Close())
  1030. err := dataprovider.Initialize(providerConf, configDir)
  1031. assert.NoError(t, err)
  1032. if _, err = os.Stat(credentialsFile); err == nil {
  1033. // remove the credentials file
  1034. assert.NoError(t, os.Remove(credentialsFile))
  1035. }
  1036. user, _, err := httpd.AddUser(u, http.StatusOK)
  1037. assert.NoError(t, err)
  1038. assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.GCSConfig.Credentials.GetStatus())
  1039. assert.NotEmpty(t, user.FsConfig.GCSConfig.Credentials.GetPayload())
  1040. assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetAdditionalData())
  1041. assert.Empty(t, user.FsConfig.GCSConfig.Credentials.GetKey())
  1042. assert.NoFileExists(t, credentialsFile)
  1043. client := getWebDavClient(user)
  1044. err = client.Connect()
  1045. assert.NoError(t, err)
  1046. _, err = httpd.RemoveUser(user, http.StatusOK)
  1047. assert.NoError(t, err)
  1048. err = os.RemoveAll(user.GetHomeDir())
  1049. assert.NoError(t, err)
  1050. assert.NoError(t, dataprovider.Close())
  1051. assert.NoError(t, config.LoadConfig(configDir, ""))
  1052. providerConf = config.GetProviderConf()
  1053. assert.NoError(t, dataprovider.Initialize(providerConf, configDir))
  1054. }
  1055. func TestLoginInvalidFs(t *testing.T) {
  1056. u := getTestUser()
  1057. u.FsConfig.Provider = dataprovider.GCSFilesystemProvider
  1058. u.FsConfig.GCSConfig.Bucket = "test"
  1059. u.FsConfig.GCSConfig.Credentials = kms.NewPlainSecret("invalid JSON for credentials")
  1060. user, _, err := httpd.AddUser(u, http.StatusOK)
  1061. assert.NoError(t, err)
  1062. providerConf := config.GetProviderConf()
  1063. credentialsFile := filepath.Join(providerConf.CredentialsPath, fmt.Sprintf("%v_gcs_credentials.json", u.Username))
  1064. if !filepath.IsAbs(credentialsFile) {
  1065. credentialsFile = filepath.Join(configDir, credentialsFile)
  1066. }
  1067. // now remove the credentials file so the filesystem creation will fail
  1068. err = os.Remove(credentialsFile)
  1069. assert.NoError(t, err)
  1070. client := getWebDavClient(user)
  1071. assert.Error(t, checkBasicFunc(client))
  1072. _, err = httpd.RemoveUser(user, http.StatusOK)
  1073. assert.NoError(t, err)
  1074. err = os.RemoveAll(user.GetHomeDir())
  1075. assert.NoError(t, err)
  1076. }
  1077. func TestBytesRangeRequests(t *testing.T) {
  1078. u := getTestUser()
  1079. u.Username = u.Username + "1"
  1080. localUser, _, err := httpd.AddUser(u, http.StatusOK)
  1081. assert.NoError(t, err)
  1082. sftpUser := getTestSFTPUser()
  1083. sftpUser.FsConfig.SFTPConfig.Username = localUser.Username
  1084. for _, u := range []dataprovider.User{getTestUser(), getTestUserWithCryptFs(), sftpUser} {
  1085. user, _, err := httpd.AddUser(u, http.StatusOK)
  1086. assert.NoError(t, err)
  1087. testFileName := "test_file.txt"
  1088. testFilePath := filepath.Join(homeBasePath, testFileName)
  1089. fileContent := []byte("test file contents")
  1090. err = ioutil.WriteFile(testFilePath, fileContent, os.ModePerm)
  1091. assert.NoError(t, err)
  1092. client := getWebDavClient(user)
  1093. err = uploadFile(testFilePath, testFileName, int64(len(fileContent)), client)
  1094. assert.NoError(t, err)
  1095. remotePath := fmt.Sprintf("http://%v/%v/%v", webDavServerAddr, user.Username, testFileName)
  1096. req, err := http.NewRequest(http.MethodGet, remotePath, nil)
  1097. if assert.NoError(t, err) {
  1098. httpClient := httpclient.GetHTTPClient()
  1099. req.SetBasicAuth(user.Username, defaultPassword)
  1100. req.Header.Set("Range", "bytes=5-")
  1101. resp, err := httpClient.Do(req)
  1102. if assert.NoError(t, err) {
  1103. defer resp.Body.Close()
  1104. assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
  1105. bodyBytes, err := ioutil.ReadAll(resp.Body)
  1106. assert.NoError(t, err)
  1107. assert.Equal(t, "file contents", string(bodyBytes))
  1108. }
  1109. req.Header.Set("Range", "bytes=5-8")
  1110. resp, err = httpClient.Do(req)
  1111. if assert.NoError(t, err) {
  1112. defer resp.Body.Close()
  1113. assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
  1114. bodyBytes, err := ioutil.ReadAll(resp.Body)
  1115. assert.NoError(t, err)
  1116. assert.Equal(t, "file", string(bodyBytes))
  1117. }
  1118. }
  1119. assert.NoError(t, err)
  1120. err = os.Remove(testFilePath)
  1121. assert.NoError(t, err)
  1122. _, err = httpd.RemoveUser(user, http.StatusOK)
  1123. assert.NoError(t, err)
  1124. err = os.RemoveAll(user.GetHomeDir())
  1125. assert.NoError(t, err)
  1126. }
  1127. _, err = httpd.RemoveUser(localUser, http.StatusOK)
  1128. assert.NoError(t, err)
  1129. err = os.RemoveAll(localUser.GetHomeDir())
  1130. assert.NoError(t, err)
  1131. }
  1132. func TestGETAsPROPFIND(t *testing.T) {
  1133. u := getTestUser()
  1134. subDir1 := "/sub1"
  1135. u.Permissions[subDir1] = []string{dataprovider.PermUpload, dataprovider.PermCreateDirs}
  1136. user, _, err := httpd.AddUser(u, http.StatusOK)
  1137. assert.NoError(t, err)
  1138. rootPath := fmt.Sprintf("http://%v/%v", webDavServerAddr, user.Username)
  1139. httpClient := httpclient.GetHTTPClient()
  1140. req, err := http.NewRequest(http.MethodGet, rootPath, nil)
  1141. if assert.NoError(t, err) {
  1142. req.SetBasicAuth(u.Username, u.Password)
  1143. resp, err := httpClient.Do(req)
  1144. if assert.NoError(t, err) {
  1145. assert.Equal(t, http.StatusMultiStatus, resp.StatusCode)
  1146. resp.Body.Close()
  1147. }
  1148. }
  1149. client := getWebDavClient(user)
  1150. err = client.MkdirAll(path.Join(subDir1, "sub", "sub1"), os.ModePerm)
  1151. assert.NoError(t, err)
  1152. subPath := fmt.Sprintf("http://%v/%v", webDavServerAddr, path.Join(user.Username, subDir1))
  1153. req, err = http.NewRequest(http.MethodGet, subPath, nil)
  1154. if assert.NoError(t, err) {
  1155. req.SetBasicAuth(u.Username, u.Password)
  1156. resp, err := httpClient.Do(req)
  1157. if assert.NoError(t, err) {
  1158. // before the performance patch we have a 500 here, now we have 207 but an empty list
  1159. //assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)
  1160. assert.Equal(t, http.StatusMultiStatus, resp.StatusCode)
  1161. resp.Body.Close()
  1162. }
  1163. }
  1164. // we cannot stat the sub at all
  1165. subPath1 := fmt.Sprintf("http://%v/%v", webDavServerAddr, path.Join(user.Username, subDir1, "sub"))
  1166. req, err = http.NewRequest(http.MethodGet, subPath1, nil)
  1167. if assert.NoError(t, err) {
  1168. req.SetBasicAuth(u.Username, u.Password)
  1169. resp, err := httpClient.Do(req)
  1170. if assert.NoError(t, err) {
  1171. // here the stat will fail, so the request will not be changed in propfind
  1172. assert.Equal(t, http.StatusForbidden, resp.StatusCode)
  1173. resp.Body.Close()
  1174. }
  1175. }
  1176. // we have no permission, we get an empty list
  1177. files, err := client.ReadDir(subDir1)
  1178. assert.NoError(t, err)
  1179. assert.Len(t, files, 0)
  1180. // if we grant the permissions the files are listed
  1181. user.Permissions[subDir1] = []string{dataprovider.PermDownload, dataprovider.PermListItems}
  1182. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1183. assert.NoError(t, err)
  1184. files, err = client.ReadDir(subDir1)
  1185. assert.NoError(t, err)
  1186. assert.Len(t, files, 1)
  1187. _, err = httpd.RemoveUser(user, http.StatusOK)
  1188. assert.NoError(t, err)
  1189. err = os.RemoveAll(user.GetHomeDir())
  1190. assert.NoError(t, err)
  1191. }
  1192. func TestStat(t *testing.T) {
  1193. u := getTestUser()
  1194. u.Permissions["/subdir"] = []string{dataprovider.PermUpload, dataprovider.PermListItems, dataprovider.PermDownload}
  1195. user, _, err := httpd.AddUser(u, http.StatusOK)
  1196. assert.NoError(t, err)
  1197. client := getWebDavClient(user)
  1198. subDir := "subdir"
  1199. testFilePath := filepath.Join(homeBasePath, testFileName)
  1200. testFileSize := int64(65535)
  1201. err = createTestFile(testFilePath, testFileSize)
  1202. assert.NoError(t, err)
  1203. err = client.Mkdir(subDir, os.ModePerm)
  1204. assert.NoError(t, err)
  1205. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  1206. assert.NoError(t, err)
  1207. err = uploadFile(testFilePath, path.Join("/", subDir, testFileName), testFileSize, client)
  1208. assert.NoError(t, err)
  1209. user.Permissions["/subdir"] = []string{dataprovider.PermUpload, dataprovider.PermDownload}
  1210. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1211. assert.NoError(t, err)
  1212. _, err = client.Stat(testFileName)
  1213. assert.NoError(t, err)
  1214. _, err = client.Stat(path.Join("/", subDir, testFileName))
  1215. assert.Error(t, err)
  1216. err = os.Remove(testFilePath)
  1217. assert.NoError(t, err)
  1218. _, err = httpd.RemoveUser(user, http.StatusOK)
  1219. assert.NoError(t, err)
  1220. err = os.RemoveAll(user.GetHomeDir())
  1221. assert.NoError(t, err)
  1222. }
  1223. func TestUploadOverwriteVfolder(t *testing.T) {
  1224. u := getTestUser()
  1225. vdir := "/vdir"
  1226. mappedPath := filepath.Join(os.TempDir(), "mappedDir")
  1227. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1228. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1229. MappedPath: mappedPath,
  1230. },
  1231. VirtualPath: vdir,
  1232. QuotaSize: -1,
  1233. QuotaFiles: -1,
  1234. })
  1235. err := os.MkdirAll(mappedPath, os.ModePerm)
  1236. assert.NoError(t, err)
  1237. user, _, err := httpd.AddUser(u, http.StatusOK)
  1238. assert.NoError(t, err)
  1239. client := getWebDavClient(user)
  1240. files, err := client.ReadDir(".")
  1241. assert.NoError(t, err)
  1242. vdirFound := false
  1243. for _, info := range files {
  1244. if info.Name() == path.Base(vdir) {
  1245. vdirFound = true
  1246. break
  1247. }
  1248. }
  1249. assert.True(t, vdirFound)
  1250. info, err := client.Stat(vdir)
  1251. if assert.NoError(t, err) {
  1252. assert.Equal(t, path.Base(vdir), info.Name())
  1253. }
  1254. testFilePath := filepath.Join(homeBasePath, testFileName)
  1255. testFileSize := int64(65535)
  1256. err = createTestFile(testFilePath, testFileSize)
  1257. assert.NoError(t, err)
  1258. err = uploadFile(testFilePath, path.Join(vdir, testFileName), testFileSize, client)
  1259. assert.NoError(t, err)
  1260. folder, _, err := httpd.GetFolders(0, 0, mappedPath, http.StatusOK)
  1261. assert.NoError(t, err)
  1262. if assert.Len(t, folder, 1) {
  1263. f := folder[0]
  1264. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  1265. assert.Equal(t, 1, f.UsedQuotaFiles)
  1266. }
  1267. err = uploadFile(testFilePath, path.Join(vdir, testFileName), testFileSize, client)
  1268. assert.NoError(t, err)
  1269. folder, _, err = httpd.GetFolders(0, 0, mappedPath, http.StatusOK)
  1270. assert.NoError(t, err)
  1271. if assert.Len(t, folder, 1) {
  1272. f := folder[0]
  1273. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  1274. assert.Equal(t, 1, f.UsedQuotaFiles)
  1275. }
  1276. err = os.Remove(testFilePath)
  1277. assert.NoError(t, err)
  1278. _, err = httpd.RemoveUser(user, http.StatusOK)
  1279. assert.NoError(t, err)
  1280. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath}, http.StatusOK)
  1281. assert.NoError(t, err)
  1282. err = os.RemoveAll(user.GetHomeDir())
  1283. assert.NoError(t, err)
  1284. err = os.RemoveAll(mappedPath)
  1285. assert.NoError(t, err)
  1286. }
  1287. func TestMiscCommands(t *testing.T) {
  1288. u := getTestUser()
  1289. u.QuotaFiles = 100
  1290. localUser, _, err := httpd.AddUser(u, http.StatusOK)
  1291. assert.NoError(t, err)
  1292. u = getTestSFTPUser()
  1293. u.QuotaFiles = 100
  1294. sftpUser, _, err := httpd.AddUser(u, http.StatusOK)
  1295. assert.NoError(t, err)
  1296. for _, user := range []dataprovider.User{localUser, sftpUser} {
  1297. dir := "testDir"
  1298. client := getWebDavClient(user)
  1299. err = client.MkdirAll(path.Join(dir, "sub1", "sub2"), os.ModePerm)
  1300. assert.NoError(t, err)
  1301. testFilePath := filepath.Join(homeBasePath, testFileName)
  1302. testFileSize := int64(65535)
  1303. err = createTestFile(testFilePath, testFileSize)
  1304. assert.NoError(t, err)
  1305. err = uploadFile(testFilePath, path.Join(dir, testFileName), testFileSize, client)
  1306. assert.NoError(t, err)
  1307. err = uploadFile(testFilePath, path.Join(dir, "sub1", testFileName), testFileSize, client)
  1308. assert.NoError(t, err)
  1309. err = uploadFile(testFilePath, path.Join(dir, "sub1", "sub2", testFileName), testFileSize, client)
  1310. assert.NoError(t, err)
  1311. err = client.Copy(dir, dir+"_copy", false)
  1312. assert.NoError(t, err)
  1313. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  1314. assert.NoError(t, err)
  1315. assert.Equal(t, 6, user.UsedQuotaFiles)
  1316. assert.Equal(t, 6*testFileSize, user.UsedQuotaSize)
  1317. err = client.Copy(dir, dir+"_copy1", false)
  1318. assert.NoError(t, err)
  1319. err = client.Copy(dir+"_copy", dir+"_copy1", false)
  1320. assert.Error(t, err)
  1321. err = client.Copy(dir+"_copy", dir+"_copy1", true)
  1322. assert.NoError(t, err)
  1323. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  1324. assert.NoError(t, err)
  1325. assert.Equal(t, 9, user.UsedQuotaFiles)
  1326. assert.Equal(t, 9*testFileSize, user.UsedQuotaSize)
  1327. err = client.Rename(dir+"_copy1", dir+"_copy2", false)
  1328. assert.NoError(t, err)
  1329. err = client.Remove(path.Join(dir+"_copy", testFileName))
  1330. assert.NoError(t, err)
  1331. err = client.Rename(dir+"_copy2", dir+"_copy", true)
  1332. assert.NoError(t, err)
  1333. err = client.Copy(dir+"_copy", dir+"_copy1", false)
  1334. assert.NoError(t, err)
  1335. err = client.RemoveAll(dir + "_copy1")
  1336. assert.NoError(t, err)
  1337. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  1338. assert.NoError(t, err)
  1339. assert.Equal(t, 6, user.UsedQuotaFiles)
  1340. assert.Equal(t, 6*testFileSize, user.UsedQuotaSize)
  1341. err = os.Remove(testFilePath)
  1342. assert.NoError(t, err)
  1343. if user.Username == defaultUsername {
  1344. err = os.RemoveAll(user.GetHomeDir())
  1345. assert.NoError(t, err)
  1346. user.QuotaFiles = 0
  1347. _, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1348. assert.NoError(t, err)
  1349. }
  1350. }
  1351. _, err = httpd.RemoveUser(sftpUser, http.StatusOK)
  1352. assert.NoError(t, err)
  1353. _, err = httpd.RemoveUser(localUser, http.StatusOK)
  1354. assert.NoError(t, err)
  1355. err = os.RemoveAll(localUser.GetHomeDir())
  1356. assert.NoError(t, err)
  1357. }
  1358. func checkBasicFunc(client *gowebdav.Client) error {
  1359. err := client.Connect()
  1360. if err != nil {
  1361. return err
  1362. }
  1363. _, err = client.ReadDir("/")
  1364. return err
  1365. }
  1366. func uploadFile(localSourcePath string, remoteDestPath string, expectedSize int64, client *gowebdav.Client) error {
  1367. srcFile, err := os.Open(localSourcePath)
  1368. if err != nil {
  1369. return err
  1370. }
  1371. defer srcFile.Close()
  1372. err = client.WriteStream(remoteDestPath, srcFile, os.ModePerm)
  1373. if err != nil {
  1374. return err
  1375. }
  1376. if expectedSize > 0 {
  1377. info, err := client.Stat(remoteDestPath)
  1378. if err != nil {
  1379. return err
  1380. }
  1381. if info.Size() != expectedSize {
  1382. return fmt.Errorf("uploaded file size does not match, actual: %v, expected: %v", info.Size(), expectedSize)
  1383. }
  1384. }
  1385. return nil
  1386. }
  1387. func downloadFile(remoteSourcePath string, localDestPath string, expectedSize int64, client *gowebdav.Client) error {
  1388. downloadDest, err := os.Create(localDestPath)
  1389. if err != nil {
  1390. return err
  1391. }
  1392. defer downloadDest.Close()
  1393. reader, err := client.ReadStream(remoteSourcePath)
  1394. if err != nil {
  1395. return err
  1396. }
  1397. defer reader.Close()
  1398. written, err := io.Copy(downloadDest, reader)
  1399. if err != nil {
  1400. return err
  1401. }
  1402. if written != expectedSize {
  1403. return fmt.Errorf("downloaded file size does not match, actual: %v, expected: %v", written, expectedSize)
  1404. }
  1405. return nil
  1406. }
  1407. func getWebDavClient(user dataprovider.User) *gowebdav.Client {
  1408. rootPath := fmt.Sprintf("http://%v/%v", webDavServerAddr, user.Username)
  1409. pwd := defaultPassword
  1410. if len(user.Password) > 0 {
  1411. pwd = user.Password
  1412. }
  1413. client := gowebdav.NewClient(rootPath, user.Username, pwd)
  1414. client.SetTimeout(5 * time.Second)
  1415. return client
  1416. }
  1417. func waitTCPListening(address string) {
  1418. for {
  1419. conn, err := net.Dial("tcp", address)
  1420. if err != nil {
  1421. logger.WarnToConsole("tcp server %v not listening: %v\n", address, err)
  1422. time.Sleep(100 * time.Millisecond)
  1423. continue
  1424. }
  1425. logger.InfoToConsole("tcp server %v now listening\n", address)
  1426. conn.Close()
  1427. break
  1428. }
  1429. }
  1430. func getTestUser() dataprovider.User {
  1431. user := dataprovider.User{
  1432. Username: defaultUsername,
  1433. Password: defaultPassword,
  1434. HomeDir: filepath.Join(homeBasePath, defaultUsername),
  1435. Status: 1,
  1436. ExpirationDate: 0,
  1437. }
  1438. user.Permissions = make(map[string][]string)
  1439. user.Permissions["/"] = allPerms
  1440. return user
  1441. }
  1442. func getTestSFTPUser() dataprovider.User {
  1443. u := getTestUser()
  1444. u.Username = u.Username + "_sftp"
  1445. u.FsConfig.Provider = dataprovider.SFTPFilesystemProvider
  1446. u.FsConfig.SFTPConfig.Endpoint = sftpServerAddr
  1447. u.FsConfig.SFTPConfig.Username = defaultUsername
  1448. u.FsConfig.SFTPConfig.Password = kms.NewPlainSecret(defaultPassword)
  1449. return u
  1450. }
  1451. func getTestUserWithCryptFs() dataprovider.User {
  1452. user := getTestUser()
  1453. user.FsConfig.Provider = dataprovider.CryptedFilesystemProvider
  1454. user.FsConfig.CryptConfig.Passphrase = kms.NewPlainSecret("testPassphrase")
  1455. return user
  1456. }
  1457. func getEncryptedFileSize(size int64) (int64, error) {
  1458. encSize, err := sio.EncryptedSize(uint64(size))
  1459. return int64(encSize) + 33, err
  1460. }
  1461. func getExtAuthScriptContent(user dataprovider.User, nonJSONResponse bool, username string) []byte {
  1462. extAuthContent := []byte("#!/bin/sh\n\n")
  1463. extAuthContent = append(extAuthContent, []byte(fmt.Sprintf("if test \"$SFTPGO_AUTHD_USERNAME\" = \"%v\"; then\n", user.Username))...)
  1464. if len(username) > 0 {
  1465. user.Username = username
  1466. }
  1467. u, _ := json.Marshal(user)
  1468. if nonJSONResponse {
  1469. extAuthContent = append(extAuthContent, []byte("echo 'text response'\n")...)
  1470. } else {
  1471. extAuthContent = append(extAuthContent, []byte(fmt.Sprintf("echo '%v'\n", string(u)))...)
  1472. }
  1473. extAuthContent = append(extAuthContent, []byte("else\n")...)
  1474. if nonJSONResponse {
  1475. extAuthContent = append(extAuthContent, []byte("echo 'text response'\n")...)
  1476. } else {
  1477. extAuthContent = append(extAuthContent, []byte("echo '{\"username\":\"\"}'\n")...)
  1478. }
  1479. extAuthContent = append(extAuthContent, []byte("fi\n")...)
  1480. return extAuthContent
  1481. }
  1482. func getPreLoginScriptContent(user dataprovider.User, nonJSONResponse bool) []byte {
  1483. content := []byte("#!/bin/sh\n\n")
  1484. if nonJSONResponse {
  1485. content = append(content, []byte("echo 'text response'\n")...)
  1486. return content
  1487. }
  1488. if len(user.Username) > 0 {
  1489. u, _ := json.Marshal(user)
  1490. content = append(content, []byte(fmt.Sprintf("echo '%v'\n", string(u)))...)
  1491. }
  1492. return content
  1493. }
  1494. func getPostConnectScriptContent(exitCode int) []byte {
  1495. content := []byte("#!/bin/sh\n\n")
  1496. content = append(content, []byte(fmt.Sprintf("exit %v", exitCode))...)
  1497. return content
  1498. }
  1499. func createTestFile(path string, size int64) error {
  1500. baseDir := filepath.Dir(path)
  1501. if _, err := os.Stat(baseDir); os.IsNotExist(err) {
  1502. err = os.MkdirAll(baseDir, os.ModePerm)
  1503. if err != nil {
  1504. return err
  1505. }
  1506. }
  1507. content := make([]byte, size)
  1508. _, err := rand.Read(content)
  1509. if err != nil {
  1510. return err
  1511. }
  1512. return ioutil.WriteFile(path, content, os.ModePerm)
  1513. }