webdavd_test.go 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114
  1. package webdavd_test
  2. import (
  3. "crypto/rand"
  4. "encoding/base64"
  5. "encoding/json"
  6. "fmt"
  7. "io"
  8. "io/ioutil"
  9. "net"
  10. "net/http"
  11. "os"
  12. "os/exec"
  13. "path"
  14. "path/filepath"
  15. "runtime"
  16. "sync"
  17. "testing"
  18. "time"
  19. "github.com/rs/zerolog"
  20. "github.com/stretchr/testify/assert"
  21. "github.com/studio-b12/gowebdav"
  22. "github.com/drakkan/sftpgo/common"
  23. "github.com/drakkan/sftpgo/config"
  24. "github.com/drakkan/sftpgo/dataprovider"
  25. "github.com/drakkan/sftpgo/httpclient"
  26. "github.com/drakkan/sftpgo/httpd"
  27. "github.com/drakkan/sftpgo/logger"
  28. "github.com/drakkan/sftpgo/vfs"
  29. "github.com/drakkan/sftpgo/webdavd"
  30. )
  31. const (
  32. logSender = "webavdTesting"
  33. webDavServerAddr = "127.0.0.1:9090"
  34. webDavServerPort = 9090
  35. defaultUsername = "test_user_dav"
  36. defaultPassword = "test_password"
  37. configDir = ".."
  38. osWindows = "windows"
  39. webDavCert = `-----BEGIN CERTIFICATE-----
  40. MIICHTCCAaKgAwIBAgIUHnqw7QnB1Bj9oUsNpdb+ZkFPOxMwCgYIKoZIzj0EAwIw
  41. RTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGElu
  42. dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDAyMDQwOTUzMDRaFw0zMDAyMDEw
  43. OTUzMDRaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYD
  44. VQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwdjAQBgcqhkjOPQIBBgUrgQQA
  45. IgNiAARCjRMqJ85rzMC998X5z761nJ+xL3bkmGVqWvrJ51t5OxV0v25NsOgR82CA
  46. NXUgvhVYs7vNFN+jxtb2aj6Xg+/2G/BNxkaFspIVCzgWkxiz7XE4lgUwX44FCXZM
  47. 3+JeUbKjUzBRMB0GA1UdDgQWBBRhLw+/o3+Z02MI/d4tmaMui9W16jAfBgNVHSME
  48. GDAWgBRhLw+/o3+Z02MI/d4tmaMui9W16jAPBgNVHRMBAf8EBTADAQH/MAoGCCqG
  49. SM49BAMCA2kAMGYCMQDqLt2lm8mE+tGgtjDmtFgdOcI72HSbRQ74D5rYTzgST1rY
  50. /8wTi5xl8TiFUyLMUsICMQC5ViVxdXbhuG7gX6yEqSkMKZICHpO8hqFwOD/uaFVI
  51. dV4vKmHUzwK/eIx+8Ay3neE=
  52. -----END CERTIFICATE-----`
  53. webDavKey = `-----BEGIN EC PARAMETERS-----
  54. BgUrgQQAIg==
  55. -----END EC PARAMETERS-----
  56. -----BEGIN EC PRIVATE KEY-----
  57. MIGkAgEBBDCfMNsN6miEE3rVyUPwElfiJSWaR5huPCzUenZOfJT04GAcQdWvEju3
  58. UM2lmBLIXpGgBwYFK4EEACKhZANiAARCjRMqJ85rzMC998X5z761nJ+xL3bkmGVq
  59. WvrJ51t5OxV0v25NsOgR82CANXUgvhVYs7vNFN+jxtb2aj6Xg+/2G/BNxkaFspIV
  60. CzgWkxiz7XE4lgUwX44FCXZM3+JeUbI=
  61. -----END EC PRIVATE KEY-----`
  62. testFileName = "test_file_dav.dat"
  63. testDLFileName = "test_download_dav.dat"
  64. )
  65. var (
  66. allPerms = []string{dataprovider.PermAny}
  67. homeBasePath string
  68. hookCmdPath string
  69. extAuthPath string
  70. preLoginPath string
  71. postConnectPath string
  72. logFilePath string
  73. certPath string
  74. keyPath string
  75. )
  76. func TestMain(m *testing.M) {
  77. logFilePath = filepath.Join(configDir, "sftpgo_webdavd_test.log")
  78. logger.InitLogger(logFilePath, 5, 1, 28, false, zerolog.DebugLevel)
  79. err := config.LoadConfig(configDir, "")
  80. if err != nil {
  81. logger.ErrorToConsole("error loading configuration: %v", err)
  82. os.Exit(1)
  83. }
  84. providerConf := config.GetProviderConf()
  85. logger.InfoToConsole("Starting WebDAVD tests, provider: %v", providerConf.Driver)
  86. commonConf := config.GetCommonConfig()
  87. commonConf.UploadMode = 2
  88. homeBasePath = os.TempDir()
  89. if runtime.GOOS != osWindows {
  90. commonConf.Actions.ExecuteOn = []string{"download", "upload", "rename", "delete"}
  91. commonConf.Actions.Hook = hookCmdPath
  92. hookCmdPath, err = exec.LookPath("true")
  93. if err != nil {
  94. logger.Warn(logSender, "", "unable to get hook command: %v", err)
  95. logger.WarnToConsole("unable to get hook command: %v", err)
  96. }
  97. }
  98. certPath = filepath.Join(os.TempDir(), "test_dav.crt")
  99. keyPath = filepath.Join(os.TempDir(), "test_dav.key")
  100. err = ioutil.WriteFile(certPath, []byte(webDavCert), os.ModePerm)
  101. if err != nil {
  102. logger.ErrorToConsole("error writing WebDAV certificate: %v", err)
  103. os.Exit(1)
  104. }
  105. err = ioutil.WriteFile(keyPath, []byte(webDavKey), os.ModePerm)
  106. if err != nil {
  107. logger.ErrorToConsole("error writing WebDAV private key: %v", err)
  108. os.Exit(1)
  109. }
  110. common.Initialize(commonConf)
  111. err = dataprovider.Initialize(providerConf, configDir)
  112. if err != nil {
  113. logger.ErrorToConsole("error initializing data provider: %v", err)
  114. os.Exit(1)
  115. }
  116. httpConfig := config.GetHTTPConfig()
  117. httpConfig.Initialize(configDir)
  118. httpdConf := config.GetHTTPDConfig()
  119. httpdConf.BindPort = 8078
  120. httpd.SetBaseURLAndCredentials("http://127.0.0.1:8078", "", "")
  121. webDavConf := config.GetWebDAVDConfig()
  122. webDavConf.BindPort = webDavServerPort
  123. extAuthPath = filepath.Join(homeBasePath, "extauth.sh")
  124. preLoginPath = filepath.Join(homeBasePath, "prelogin.sh")
  125. postConnectPath = filepath.Join(homeBasePath, "postconnect.sh")
  126. go func() {
  127. logger.Debug(logSender, "", "initializing WebDAV server with config %+v", webDavConf)
  128. if err := webDavConf.Initialize(configDir); err != nil {
  129. logger.ErrorToConsole("could not start WebDAV server: %v", err)
  130. os.Exit(1)
  131. }
  132. }()
  133. go func() {
  134. if err := httpdConf.Initialize(configDir, false); err != nil {
  135. logger.ErrorToConsole("could not start HTTP server: %v", err)
  136. os.Exit(1)
  137. }
  138. }()
  139. waitTCPListening(fmt.Sprintf("%s:%d", webDavConf.BindAddress, webDavConf.BindPort))
  140. waitTCPListening(fmt.Sprintf("%s:%d", httpdConf.BindAddress, httpdConf.BindPort))
  141. webdavd.ReloadTLSCertificate() //nolint:errcheck
  142. exitCode := m.Run()
  143. os.Remove(logFilePath)
  144. os.Remove(extAuthPath)
  145. os.Remove(preLoginPath)
  146. os.Remove(postConnectPath)
  147. os.Remove(certPath)
  148. os.Remove(keyPath)
  149. os.Exit(exitCode)
  150. }
  151. func TestInitialization(t *testing.T) {
  152. config := webdavd.Configuration{
  153. BindPort: 1234,
  154. CertificateFile: "missing path",
  155. CertificateKeyFile: "bad path",
  156. }
  157. err := config.Initialize(configDir)
  158. assert.Error(t, err)
  159. config.BindPort = webDavServerPort
  160. config.CertificateFile = certPath
  161. config.CertificateKeyFile = keyPath
  162. err = config.Initialize(configDir)
  163. assert.Error(t, err)
  164. err = webdavd.ReloadTLSCertificate()
  165. assert.NoError(t, err)
  166. }
  167. func TestBasicHandling(t *testing.T) {
  168. u := getTestUser()
  169. u.QuotaSize = 6553600
  170. user, _, err := httpd.AddUser(u, http.StatusOK)
  171. assert.NoError(t, err)
  172. client := getWebDavClient(user)
  173. assert.NoError(t, checkBasicFunc(client))
  174. testFilePath := filepath.Join(homeBasePath, testFileName)
  175. testFileSize := int64(65535)
  176. expectedQuotaSize := user.UsedQuotaSize + testFileSize
  177. expectedQuotaFiles := user.UsedQuotaFiles + 1
  178. err = createTestFile(testFilePath, testFileSize)
  179. assert.NoError(t, err)
  180. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  181. assert.NoError(t, err)
  182. // overwrite an existing file
  183. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  184. assert.NoError(t, err)
  185. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  186. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  187. assert.NoError(t, err)
  188. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  189. assert.NoError(t, err)
  190. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  191. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  192. err = client.Rename(testFileName, testFileName+"1", false)
  193. assert.NoError(t, err)
  194. _, err = client.Stat(testFileName)
  195. assert.Error(t, err)
  196. // the webdav client hide the error we check the quota
  197. err = client.Remove(testFileName)
  198. assert.NoError(t, err)
  199. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  200. assert.NoError(t, err)
  201. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  202. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  203. err = client.Remove(testFileName + "1")
  204. assert.NoError(t, err)
  205. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  206. assert.NoError(t, err)
  207. assert.Equal(t, expectedQuotaFiles-1, user.UsedQuotaFiles)
  208. assert.Equal(t, expectedQuotaSize-testFileSize, user.UsedQuotaSize)
  209. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  210. assert.Error(t, err)
  211. testDir := "testdir"
  212. err = client.Mkdir(testDir, os.ModePerm)
  213. assert.NoError(t, err)
  214. err = client.MkdirAll(path.Join(testDir, "sub", "sub"), os.ModePerm)
  215. assert.NoError(t, err)
  216. err = client.MkdirAll(path.Join(testDir, "sub1", "sub1"), os.ModePerm)
  217. assert.NoError(t, err)
  218. err = client.MkdirAll(path.Join(testDir, "sub2", "sub2"), os.ModePerm)
  219. assert.NoError(t, err)
  220. err = uploadFile(testFilePath, path.Join(testDir, testFileName+".txt"), testFileSize, client)
  221. assert.NoError(t, err)
  222. files, err := client.ReadDir(testDir)
  223. assert.NoError(t, err)
  224. assert.Len(t, files, 4)
  225. err = client.Copy(testDir, testDir+"_copy", false)
  226. assert.NoError(t, err)
  227. err = client.RemoveAll(testDir)
  228. assert.NoError(t, err)
  229. err = os.Remove(testFilePath)
  230. assert.NoError(t, err)
  231. err = os.Remove(localDownloadPath)
  232. assert.NoError(t, err)
  233. _, err = httpd.RemoveUser(user, http.StatusOK)
  234. assert.NoError(t, err)
  235. err = os.RemoveAll(user.GetHomeDir())
  236. assert.NoError(t, err)
  237. assert.Len(t, common.Connections.GetStats(), 0)
  238. }
  239. func TestLoginInvalidPwd(t *testing.T) {
  240. u := getTestUser()
  241. user, _, err := httpd.AddUser(u, http.StatusOK)
  242. assert.NoError(t, err)
  243. user.Password = "wrong"
  244. client := getWebDavClient(user)
  245. assert.Error(t, checkBasicFunc(client))
  246. _, err = httpd.RemoveUser(user, http.StatusOK)
  247. assert.NoError(t, err)
  248. }
  249. func TestLoginInvalidURL(t *testing.T) {
  250. u := getTestUser()
  251. user, _, err := httpd.AddUser(u, http.StatusOK)
  252. assert.NoError(t, err)
  253. u1 := getTestUser()
  254. u1.Username = user.Username + "1"
  255. user1, _, err := httpd.AddUser(u1, http.StatusOK)
  256. assert.NoError(t, err)
  257. rootPath := fmt.Sprintf("http://%v/%v", webDavServerAddr, user.Username+"1")
  258. client := gowebdav.NewClient(rootPath, user.Username, defaultPassword)
  259. client.SetTimeout(5 * time.Second)
  260. assert.Error(t, checkBasicFunc(client))
  261. _, err = httpd.RemoveUser(user, http.StatusOK)
  262. assert.NoError(t, err)
  263. _, err = httpd.RemoveUser(user1, http.StatusOK)
  264. assert.NoError(t, err)
  265. }
  266. func TestLoginExternalAuth(t *testing.T) {
  267. if runtime.GOOS == osWindows {
  268. t.Skip("this test is not available on Windows")
  269. }
  270. u := getTestUser()
  271. err := dataprovider.Close()
  272. assert.NoError(t, err)
  273. err = config.LoadConfig(configDir, "")
  274. assert.NoError(t, err)
  275. providerConf := config.GetProviderConf()
  276. err = ioutil.WriteFile(extAuthPath, getExtAuthScriptContent(u, false, ""), os.ModePerm)
  277. assert.NoError(t, err)
  278. providerConf.ExternalAuthHook = extAuthPath
  279. providerConf.ExternalAuthScope = 0
  280. err = dataprovider.Initialize(providerConf, configDir)
  281. assert.NoError(t, err)
  282. client := getWebDavClient(u)
  283. assert.NoError(t, checkBasicFunc(client))
  284. u.Username = defaultUsername + "1"
  285. client = getWebDavClient(u)
  286. assert.Error(t, checkBasicFunc(client))
  287. users, _, err := httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  288. assert.NoError(t, err)
  289. if assert.Len(t, users, 1) {
  290. user := users[0]
  291. assert.Equal(t, defaultUsername, user.Username)
  292. _, err = httpd.RemoveUser(user, http.StatusOK)
  293. assert.NoError(t, err)
  294. err = os.RemoveAll(user.GetHomeDir())
  295. assert.NoError(t, err)
  296. }
  297. err = dataprovider.Close()
  298. assert.NoError(t, err)
  299. err = config.LoadConfig(configDir, "")
  300. assert.NoError(t, err)
  301. providerConf = config.GetProviderConf()
  302. err = dataprovider.Initialize(providerConf, configDir)
  303. assert.NoError(t, err)
  304. err = os.Remove(extAuthPath)
  305. assert.NoError(t, err)
  306. }
  307. func TestPreLoginHook(t *testing.T) {
  308. if runtime.GOOS == osWindows {
  309. t.Skip("this test is not available on Windows")
  310. }
  311. u := getTestUser()
  312. err := dataprovider.Close()
  313. assert.NoError(t, err)
  314. err = config.LoadConfig(configDir, "")
  315. assert.NoError(t, err)
  316. providerConf := config.GetProviderConf()
  317. err = ioutil.WriteFile(preLoginPath, getPreLoginScriptContent(u, false), os.ModePerm)
  318. assert.NoError(t, err)
  319. providerConf.PreLoginHook = preLoginPath
  320. err = dataprovider.Initialize(providerConf, configDir)
  321. assert.NoError(t, err)
  322. users, _, err := httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  323. assert.NoError(t, err)
  324. assert.Equal(t, 0, len(users))
  325. client := getWebDavClient(u)
  326. assert.NoError(t, checkBasicFunc(client))
  327. users, _, err = httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  328. assert.NoError(t, err)
  329. assert.Equal(t, 1, len(users))
  330. user := users[0]
  331. // test login with an existing user
  332. client = getWebDavClient(user)
  333. assert.NoError(t, checkBasicFunc(client))
  334. err = ioutil.WriteFile(preLoginPath, getPreLoginScriptContent(user, true), os.ModePerm)
  335. assert.NoError(t, err)
  336. client = getWebDavClient(user)
  337. assert.Error(t, checkBasicFunc(client))
  338. user.Status = 0
  339. err = ioutil.WriteFile(preLoginPath, getPreLoginScriptContent(user, false), os.ModePerm)
  340. assert.NoError(t, err)
  341. client = getWebDavClient(user)
  342. assert.Error(t, checkBasicFunc(client))
  343. _, err = httpd.RemoveUser(user, http.StatusOK)
  344. assert.NoError(t, err)
  345. err = os.RemoveAll(user.GetHomeDir())
  346. assert.NoError(t, err)
  347. err = dataprovider.Close()
  348. assert.NoError(t, err)
  349. err = config.LoadConfig(configDir, "")
  350. assert.NoError(t, err)
  351. providerConf = config.GetProviderConf()
  352. err = dataprovider.Initialize(providerConf, configDir)
  353. assert.NoError(t, err)
  354. err = os.Remove(preLoginPath)
  355. assert.NoError(t, err)
  356. }
  357. func TestPostConnectHook(t *testing.T) {
  358. if runtime.GOOS == osWindows {
  359. t.Skip("this test is not available on Windows")
  360. }
  361. common.Config.PostConnectHook = postConnectPath
  362. u := getTestUser()
  363. user, _, err := httpd.AddUser(u, http.StatusOK)
  364. assert.NoError(t, err)
  365. err = ioutil.WriteFile(postConnectPath, getPostConnectScriptContent(0), os.ModePerm)
  366. assert.NoError(t, err)
  367. client := getWebDavClient(user)
  368. assert.NoError(t, checkBasicFunc(client))
  369. err = ioutil.WriteFile(postConnectPath, getPostConnectScriptContent(1), os.ModePerm)
  370. assert.NoError(t, err)
  371. assert.Error(t, checkBasicFunc(client))
  372. common.Config.PostConnectHook = "http://127.0.0.1:8078/api/v1/version"
  373. assert.NoError(t, checkBasicFunc(client))
  374. common.Config.PostConnectHook = "http://127.0.0.1:8078/notfound"
  375. assert.Error(t, checkBasicFunc(client))
  376. _, err = httpd.RemoveUser(user, http.StatusOK)
  377. assert.NoError(t, err)
  378. err = os.RemoveAll(user.GetHomeDir())
  379. assert.NoError(t, err)
  380. common.Config.PostConnectHook = ""
  381. }
  382. func TestMaxSessions(t *testing.T) {
  383. u := getTestUser()
  384. u.MaxSessions = 1
  385. user, _, err := httpd.AddUser(u, http.StatusOK)
  386. assert.NoError(t, err)
  387. client := getWebDavClient(user)
  388. assert.NoError(t, checkBasicFunc(client))
  389. // now add a fake connection
  390. fs := vfs.NewOsFs("id", os.TempDir(), nil)
  391. connection := &webdavd.Connection{
  392. BaseConnection: common.NewBaseConnection(fs.ConnectionID(), common.ProtocolWebDAV, user, fs),
  393. }
  394. common.Connections.Add(connection)
  395. assert.Error(t, checkBasicFunc(client))
  396. common.Connections.Remove(connection.GetID())
  397. _, err = httpd.RemoveUser(user, http.StatusOK)
  398. assert.NoError(t, err)
  399. err = os.RemoveAll(user.GetHomeDir())
  400. assert.NoError(t, err)
  401. assert.Len(t, common.Connections.GetStats(), 0)
  402. }
  403. func TestLoginWithIPilters(t *testing.T) {
  404. u := getTestUser()
  405. u.Filters.DeniedIP = []string{"192.167.0.0/24", "172.18.0.0/16"}
  406. u.Filters.AllowedIP = []string{"172.19.0.0/16"}
  407. user, _, err := httpd.AddUser(u, http.StatusOK)
  408. assert.NoError(t, err)
  409. client := getWebDavClient(user)
  410. assert.Error(t, checkBasicFunc(client))
  411. _, err = httpd.RemoveUser(user, http.StatusOK)
  412. assert.NoError(t, err)
  413. err = os.RemoveAll(user.GetHomeDir())
  414. assert.NoError(t, err)
  415. }
  416. func TestDownloadErrors(t *testing.T) {
  417. u := getTestUser()
  418. u.QuotaFiles = 1
  419. subDir1 := "sub1"
  420. subDir2 := "sub2"
  421. u.Permissions[path.Join("/", subDir1)] = []string{dataprovider.PermListItems}
  422. u.Permissions[path.Join("/", subDir2)] = []string{dataprovider.PermListItems, dataprovider.PermUpload,
  423. dataprovider.PermDelete, dataprovider.PermDownload}
  424. u.Filters.FileExtensions = []dataprovider.ExtensionsFilter{
  425. {
  426. Path: "/sub2",
  427. AllowedExtensions: []string{},
  428. DeniedExtensions: []string{".zip"},
  429. },
  430. }
  431. user, _, err := httpd.AddUser(u, http.StatusOK)
  432. assert.NoError(t, err)
  433. client := getWebDavClient(user)
  434. testFilePath1 := filepath.Join(user.HomeDir, subDir1, "file.zip")
  435. testFilePath2 := filepath.Join(user.HomeDir, subDir2, "file.zip")
  436. err = os.MkdirAll(filepath.Dir(testFilePath1), os.ModePerm)
  437. assert.NoError(t, err)
  438. err = os.MkdirAll(filepath.Dir(testFilePath2), os.ModePerm)
  439. assert.NoError(t, err)
  440. err = ioutil.WriteFile(testFilePath1, []byte("file1"), os.ModePerm)
  441. assert.NoError(t, err)
  442. err = ioutil.WriteFile(testFilePath2, []byte("file2"), os.ModePerm)
  443. assert.NoError(t, err)
  444. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  445. err = downloadFile(path.Join("/", subDir1, "file.zip"), localDownloadPath, 5, client)
  446. assert.Error(t, err)
  447. err = downloadFile(path.Join("/", subDir2, "file.zip"), localDownloadPath, 5, client)
  448. assert.Error(t, err)
  449. err = downloadFile(path.Join("missing.zip"), localDownloadPath, 5, client)
  450. assert.Error(t, err)
  451. err = os.Remove(localDownloadPath)
  452. assert.NoError(t, err)
  453. _, err = httpd.RemoveUser(user, http.StatusOK)
  454. assert.NoError(t, err)
  455. err = os.RemoveAll(user.GetHomeDir())
  456. assert.NoError(t, err)
  457. }
  458. func TestUploadErrors(t *testing.T) {
  459. u := getTestUser()
  460. u.QuotaSize = 65535
  461. subDir1 := "sub1"
  462. subDir2 := "sub2"
  463. // we need download permission to get size since PROPFIND will open the file
  464. u.Permissions[path.Join("/", subDir1)] = []string{dataprovider.PermListItems, dataprovider.PermDownload}
  465. u.Permissions[path.Join("/", subDir2)] = []string{dataprovider.PermListItems, dataprovider.PermUpload,
  466. dataprovider.PermDelete, dataprovider.PermDownload}
  467. u.Filters.FileExtensions = []dataprovider.ExtensionsFilter{
  468. {
  469. Path: "/sub2",
  470. AllowedExtensions: []string{},
  471. DeniedExtensions: []string{".zip"},
  472. },
  473. }
  474. user, _, err := httpd.AddUser(u, http.StatusOK)
  475. assert.NoError(t, err)
  476. client := getWebDavClient(user)
  477. testFilePath := filepath.Join(homeBasePath, testFileName)
  478. testFileSize := user.QuotaSize
  479. err = createTestFile(testFilePath, testFileSize)
  480. assert.NoError(t, err)
  481. err = client.Mkdir(subDir1, os.ModePerm)
  482. assert.NoError(t, err)
  483. err = client.Mkdir(subDir2, os.ModePerm)
  484. assert.NoError(t, err)
  485. err = uploadFile(testFilePath, path.Join(subDir1, testFileName), testFileSize, client)
  486. assert.Error(t, err)
  487. err = uploadFile(testFilePath, path.Join(subDir2, testFileName+".zip"), testFileSize, client)
  488. assert.Error(t, err)
  489. err = uploadFile(testFilePath, path.Join(subDir2, testFileName), testFileSize, client)
  490. assert.NoError(t, err)
  491. err = client.Rename(path.Join(subDir2, testFileName), path.Join(subDir1, testFileName), false)
  492. assert.Error(t, err)
  493. err = uploadFile(testFilePath, path.Join(subDir2, testFileName), testFileSize, client)
  494. assert.Error(t, err)
  495. err = uploadFile(testFilePath, subDir1, testFileSize, client)
  496. assert.Error(t, err)
  497. // overquota
  498. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  499. assert.Error(t, err)
  500. err = client.Remove(path.Join(subDir2, testFileName))
  501. assert.NoError(t, err)
  502. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  503. assert.NoError(t, err)
  504. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  505. assert.Error(t, err)
  506. err = os.Remove(testFilePath)
  507. assert.NoError(t, err)
  508. _, err = httpd.RemoveUser(user, http.StatusOK)
  509. assert.NoError(t, err)
  510. err = os.RemoveAll(user.GetHomeDir())
  511. assert.NoError(t, err)
  512. }
  513. func TestQuotaLimits(t *testing.T) {
  514. u := getTestUser()
  515. u.QuotaFiles = 1
  516. user, _, err := httpd.AddUser(u, http.StatusOK)
  517. assert.NoError(t, err)
  518. testFileSize := int64(65535)
  519. testFilePath := filepath.Join(homeBasePath, testFileName)
  520. err = createTestFile(testFilePath, testFileSize)
  521. assert.NoError(t, err)
  522. testFileSize1 := int64(131072)
  523. testFileName1 := "test_file1.dat"
  524. testFilePath1 := filepath.Join(homeBasePath, testFileName1)
  525. err = createTestFile(testFilePath1, testFileSize1)
  526. assert.NoError(t, err)
  527. testFileSize2 := int64(32768)
  528. testFileName2 := "test_file2.dat"
  529. testFilePath2 := filepath.Join(homeBasePath, testFileName2)
  530. err = createTestFile(testFilePath2, testFileSize2)
  531. assert.NoError(t, err)
  532. client := getWebDavClient(user)
  533. // test quota files
  534. err = uploadFile(testFilePath, testFileName+".quota", testFileSize, client)
  535. assert.NoError(t, err)
  536. err = uploadFile(testFilePath, testFileName+".quota1", testFileSize, client)
  537. assert.Error(t, err)
  538. err = client.Rename(testFileName+".quota", testFileName, false)
  539. assert.NoError(t, err)
  540. // test quota size
  541. user.QuotaSize = testFileSize - 1
  542. user.QuotaFiles = 0
  543. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  544. assert.NoError(t, err)
  545. err = uploadFile(testFilePath, testFileName+".quota", testFileSize, client)
  546. assert.Error(t, err)
  547. err = client.Rename(testFileName, testFileName+".quota", false)
  548. assert.NoError(t, err)
  549. // now test quota limits while uploading the current file, we have 1 bytes remaining
  550. user.QuotaSize = testFileSize + 1
  551. user.QuotaFiles = 0
  552. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  553. assert.NoError(t, err)
  554. err = uploadFile(testFilePath1, testFileName1, testFileSize1, client)
  555. assert.Error(t, err)
  556. _, err = client.Stat(testFileName1)
  557. assert.Error(t, err)
  558. err = client.Rename(testFileName+".quota", testFileName, false)
  559. assert.NoError(t, err)
  560. // overwriting an existing file will work if the resulting size is lesser or equal than the current one
  561. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  562. assert.NoError(t, err)
  563. err = uploadFile(testFilePath2, testFileName, testFileSize2, client)
  564. assert.NoError(t, err)
  565. err = uploadFile(testFilePath1, testFileName, testFileSize1, client)
  566. assert.Error(t, err)
  567. err = uploadFile(testFilePath2, testFileName, testFileSize2, client)
  568. assert.NoError(t, err)
  569. err = os.Remove(testFilePath)
  570. assert.NoError(t, err)
  571. err = os.Remove(testFilePath1)
  572. assert.NoError(t, err)
  573. err = os.Remove(testFilePath2)
  574. assert.NoError(t, err)
  575. _, err = httpd.RemoveUser(user, http.StatusOK)
  576. assert.NoError(t, err)
  577. err = os.RemoveAll(user.GetHomeDir())
  578. assert.NoError(t, err)
  579. }
  580. func TestClientClose(t *testing.T) {
  581. u := getTestUser()
  582. u.UploadBandwidth = 64
  583. u.DownloadBandwidth = 64
  584. user, _, err := httpd.AddUser(u, http.StatusOK)
  585. assert.NoError(t, err)
  586. testFileSize := int64(1048576)
  587. testFilePath := filepath.Join(homeBasePath, testFileName)
  588. err = createTestFile(testFilePath, testFileSize)
  589. assert.NoError(t, err)
  590. client := getWebDavClient(user)
  591. assert.NoError(t, checkBasicFunc(client))
  592. var wg sync.WaitGroup
  593. wg.Add(1)
  594. go func() {
  595. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  596. assert.Error(t, err)
  597. wg.Done()
  598. }()
  599. assert.Eventually(t, func() bool {
  600. for _, stat := range common.Connections.GetStats() {
  601. if len(stat.Transfers) > 0 {
  602. return true
  603. }
  604. }
  605. return false
  606. }, 1*time.Second, 50*time.Millisecond)
  607. for _, stat := range common.Connections.GetStats() {
  608. logger.DebugToConsole("close upload connection id %#v, active transfers: %v", stat.ConnectionID,
  609. stat.GetTransfersAsString())
  610. common.Connections.Close(stat.ConnectionID)
  611. }
  612. wg.Wait()
  613. assert.Eventually(t, func() bool { return len(common.Connections.GetStats()) == 0 },
  614. 1*time.Second, 100*time.Millisecond)
  615. err = os.Remove(testFilePath)
  616. assert.NoError(t, err)
  617. testFilePath = filepath.Join(user.HomeDir, testFileName)
  618. err = createTestFile(testFilePath, testFileSize)
  619. assert.NoError(t, err)
  620. localDownloadPath := filepath.Join(homeBasePath, testDLFileName)
  621. wg.Add(1)
  622. go func() {
  623. err = downloadFile(testFileName, localDownloadPath, testFileSize, client)
  624. assert.Error(t, err)
  625. wg.Done()
  626. }()
  627. assert.Eventually(t, func() bool {
  628. for _, stat := range common.Connections.GetStats() {
  629. if len(stat.Transfers) > 0 {
  630. return true
  631. }
  632. }
  633. return false
  634. }, 1*time.Second, 50*time.Millisecond)
  635. for _, stat := range common.Connections.GetStats() {
  636. logger.DebugToConsole("close download connection id %#v, active transfers: %v", stat.ConnectionID,
  637. stat.GetTransfersAsString())
  638. common.Connections.Close(stat.ConnectionID)
  639. }
  640. wg.Wait()
  641. assert.Eventually(t, func() bool { return len(common.Connections.GetStats()) == 0 },
  642. 1*time.Second, 100*time.Millisecond)
  643. err = os.Remove(localDownloadPath)
  644. assert.NoError(t, err)
  645. _, err = httpd.RemoveUser(user, http.StatusOK)
  646. assert.NoError(t, err)
  647. err = os.RemoveAll(user.GetHomeDir())
  648. assert.NoError(t, err)
  649. }
  650. func TestLoginInvalidFs(t *testing.T) {
  651. u := getTestUser()
  652. u.FsConfig.Provider = 2
  653. u.FsConfig.GCSConfig.Bucket = "test"
  654. u.FsConfig.GCSConfig.Credentials = base64.StdEncoding.EncodeToString([]byte("invalid JSON for credentials"))
  655. user, _, err := httpd.AddUser(u, http.StatusOK)
  656. assert.NoError(t, err)
  657. // now remove the credentials file so the filesystem creation will fail
  658. providerConf := config.GetProviderConf()
  659. credentialsFile := filepath.Join(providerConf.CredentialsPath, fmt.Sprintf("%v_gcs_credentials.json", u.Username))
  660. if !filepath.IsAbs(credentialsFile) {
  661. credentialsFile = filepath.Join(configDir, credentialsFile)
  662. }
  663. err = os.Remove(credentialsFile)
  664. assert.NoError(t, err)
  665. client := getWebDavClient(user)
  666. assert.Error(t, checkBasicFunc(client))
  667. _, err = httpd.RemoveUser(user, http.StatusOK)
  668. assert.NoError(t, err)
  669. err = os.RemoveAll(user.GetHomeDir())
  670. assert.NoError(t, err)
  671. }
  672. func TestBytesRangeRequests(t *testing.T) {
  673. u := getTestUser()
  674. user, _, err := httpd.AddUser(u, http.StatusOK)
  675. assert.NoError(t, err)
  676. testFileName := "test_file.txt"
  677. testFilePath := filepath.Join(homeBasePath, testFileName)
  678. fileContent := []byte("test file contents")
  679. err = ioutil.WriteFile(testFilePath, fileContent, os.ModePerm)
  680. assert.NoError(t, err)
  681. client := getWebDavClient(user)
  682. err = uploadFile(testFilePath, testFileName, int64(len(fileContent)), client)
  683. assert.NoError(t, err)
  684. remotePath := fmt.Sprintf("http://%v/%v/%v", webDavServerAddr, user.Username, testFileName)
  685. req, err := http.NewRequest(http.MethodGet, remotePath, nil)
  686. if assert.NoError(t, err) {
  687. httpClient := httpclient.GetHTTPClient()
  688. req.SetBasicAuth(user.Username, defaultPassword)
  689. req.Header.Set("Range", "bytes=5-")
  690. resp, err := httpClient.Do(req)
  691. if assert.NoError(t, err) {
  692. defer resp.Body.Close()
  693. assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
  694. bodyBytes, err := ioutil.ReadAll(resp.Body)
  695. assert.NoError(t, err)
  696. assert.Equal(t, "file contents", string(bodyBytes))
  697. }
  698. req.Header.Set("Range", "bytes=5-8")
  699. resp, err = httpClient.Do(req)
  700. if assert.NoError(t, err) {
  701. defer resp.Body.Close()
  702. assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
  703. bodyBytes, err := ioutil.ReadAll(resp.Body)
  704. assert.NoError(t, err)
  705. assert.Equal(t, "file", string(bodyBytes))
  706. }
  707. }
  708. assert.NoError(t, err)
  709. err = os.Remove(testFilePath)
  710. assert.NoError(t, err)
  711. _, err = httpd.RemoveUser(user, http.StatusOK)
  712. assert.NoError(t, err)
  713. err = os.RemoveAll(user.GetHomeDir())
  714. assert.NoError(t, err)
  715. }
  716. func TestGETAsPROPFIND(t *testing.T) {
  717. u := getTestUser()
  718. subDir1 := "/sub1"
  719. u.Permissions[subDir1] = []string{dataprovider.PermUpload, dataprovider.PermCreateDirs}
  720. user, _, err := httpd.AddUser(u, http.StatusOK)
  721. assert.NoError(t, err)
  722. rootPath := fmt.Sprintf("http://%v/%v", webDavServerAddr, user.Username)
  723. httpClient := httpclient.GetHTTPClient()
  724. req, err := http.NewRequest(http.MethodGet, rootPath, nil)
  725. if assert.NoError(t, err) {
  726. req.SetBasicAuth(u.Username, u.Password)
  727. resp, err := httpClient.Do(req)
  728. if assert.NoError(t, err) {
  729. assert.Equal(t, http.StatusMultiStatus, resp.StatusCode)
  730. resp.Body.Close()
  731. }
  732. }
  733. client := getWebDavClient(user)
  734. err = client.MkdirAll(path.Join(subDir1, "sub"), os.ModePerm)
  735. assert.NoError(t, err)
  736. subPath := fmt.Sprintf("http://%v/%v", webDavServerAddr, path.Join(user.Username, subDir1))
  737. req, err = http.NewRequest(http.MethodGet, subPath, nil)
  738. if assert.NoError(t, err) {
  739. req.SetBasicAuth(u.Username, u.Password)
  740. resp, err := httpClient.Do(req)
  741. if assert.NoError(t, err) {
  742. assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)
  743. resp.Body.Close()
  744. }
  745. }
  746. _, err = httpd.RemoveUser(user, http.StatusOK)
  747. assert.NoError(t, err)
  748. err = os.RemoveAll(user.GetHomeDir())
  749. assert.NoError(t, err)
  750. }
  751. func TestStat(t *testing.T) {
  752. u := getTestUser()
  753. u.Permissions["/subdir"] = []string{dataprovider.PermUpload, dataprovider.PermListItems, dataprovider.PermDownload}
  754. user, _, err := httpd.AddUser(u, http.StatusOK)
  755. assert.NoError(t, err)
  756. client := getWebDavClient(user)
  757. subDir := "subdir"
  758. testFilePath := filepath.Join(homeBasePath, testFileName)
  759. testFileSize := int64(65535)
  760. err = createTestFile(testFilePath, testFileSize)
  761. assert.NoError(t, err)
  762. err = client.Mkdir(subDir, os.ModePerm)
  763. assert.NoError(t, err)
  764. err = uploadFile(testFilePath, testFileName, testFileSize, client)
  765. assert.NoError(t, err)
  766. err = uploadFile(testFilePath, path.Join("/", subDir, testFileName), testFileSize, client)
  767. assert.NoError(t, err)
  768. user.Permissions["/subdir"] = []string{dataprovider.PermUpload, dataprovider.PermDownload}
  769. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  770. assert.NoError(t, err)
  771. _, err = client.Stat(testFileName)
  772. assert.NoError(t, err)
  773. _, err = client.Stat(path.Join("/", subDir, testFileName))
  774. assert.Error(t, err)
  775. err = os.Remove(testFilePath)
  776. assert.NoError(t, err)
  777. _, err = httpd.RemoveUser(user, http.StatusOK)
  778. assert.NoError(t, err)
  779. err = os.RemoveAll(user.GetHomeDir())
  780. assert.NoError(t, err)
  781. }
  782. func TestUploadOverwriteVfolder(t *testing.T) {
  783. u := getTestUser()
  784. vdir := "/vdir"
  785. mappedPath := filepath.Join(os.TempDir(), "mappedDir")
  786. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  787. BaseVirtualFolder: vfs.BaseVirtualFolder{
  788. MappedPath: mappedPath,
  789. },
  790. VirtualPath: vdir,
  791. QuotaSize: -1,
  792. QuotaFiles: -1,
  793. })
  794. err := os.MkdirAll(mappedPath, os.ModePerm)
  795. assert.NoError(t, err)
  796. user, _, err := httpd.AddUser(u, http.StatusOK)
  797. assert.NoError(t, err)
  798. client := getWebDavClient(user)
  799. files, err := client.ReadDir(".")
  800. assert.NoError(t, err)
  801. vdirFound := false
  802. for _, info := range files {
  803. if info.Name() == path.Base(vdir) {
  804. vdirFound = true
  805. break
  806. }
  807. }
  808. assert.True(t, vdirFound)
  809. info, err := client.Stat(vdir)
  810. if assert.NoError(t, err) {
  811. assert.Equal(t, path.Base(vdir), info.Name())
  812. }
  813. testFilePath := filepath.Join(homeBasePath, testFileName)
  814. testFileSize := int64(65535)
  815. err = createTestFile(testFilePath, testFileSize)
  816. assert.NoError(t, err)
  817. err = uploadFile(testFilePath, path.Join(vdir, testFileName), testFileSize, client)
  818. assert.NoError(t, err)
  819. folder, _, err := httpd.GetFolders(0, 0, mappedPath, http.StatusOK)
  820. assert.NoError(t, err)
  821. if assert.Len(t, folder, 1) {
  822. f := folder[0]
  823. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  824. assert.Equal(t, 1, f.UsedQuotaFiles)
  825. }
  826. err = uploadFile(testFilePath, path.Join(vdir, testFileName), testFileSize, client)
  827. assert.NoError(t, err)
  828. folder, _, err = httpd.GetFolders(0, 0, mappedPath, http.StatusOK)
  829. assert.NoError(t, err)
  830. if assert.Len(t, folder, 1) {
  831. f := folder[0]
  832. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  833. assert.Equal(t, 1, f.UsedQuotaFiles)
  834. }
  835. err = os.Remove(testFilePath)
  836. assert.NoError(t, err)
  837. _, err = httpd.RemoveUser(user, http.StatusOK)
  838. assert.NoError(t, err)
  839. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath}, http.StatusOK)
  840. assert.NoError(t, err)
  841. err = os.RemoveAll(user.GetHomeDir())
  842. assert.NoError(t, err)
  843. err = os.RemoveAll(mappedPath)
  844. assert.NoError(t, err)
  845. }
  846. func TestMiscCommands(t *testing.T) {
  847. u := getTestUser()
  848. u.QuotaFiles = 100
  849. user, _, err := httpd.AddUser(u, http.StatusOK)
  850. assert.NoError(t, err)
  851. dir := "testDir"
  852. client := getWebDavClient(user)
  853. err = client.MkdirAll(path.Join(dir, "sub1", "sub2"), os.ModePerm)
  854. assert.NoError(t, err)
  855. testFilePath := filepath.Join(homeBasePath, testFileName)
  856. testFileSize := int64(65535)
  857. err = createTestFile(testFilePath, testFileSize)
  858. assert.NoError(t, err)
  859. err = uploadFile(testFilePath, path.Join(dir, testFileName), testFileSize, client)
  860. assert.NoError(t, err)
  861. err = uploadFile(testFilePath, path.Join(dir, "sub1", testFileName), testFileSize, client)
  862. assert.NoError(t, err)
  863. err = uploadFile(testFilePath, path.Join(dir, "sub1", "sub2", testFileName), testFileSize, client)
  864. assert.NoError(t, err)
  865. err = client.Copy(dir, dir+"_copy", false)
  866. assert.NoError(t, err)
  867. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  868. assert.NoError(t, err)
  869. assert.Equal(t, 6, user.UsedQuotaFiles)
  870. assert.Equal(t, 6*testFileSize, user.UsedQuotaSize)
  871. err = client.Copy(dir, dir+"_copy1", false)
  872. assert.NoError(t, err)
  873. err = client.Copy(dir+"_copy", dir+"_copy1", false)
  874. assert.Error(t, err)
  875. err = client.Copy(dir+"_copy", dir+"_copy1", true)
  876. assert.NoError(t, err)
  877. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  878. assert.NoError(t, err)
  879. assert.Equal(t, 9, user.UsedQuotaFiles)
  880. assert.Equal(t, 9*testFileSize, user.UsedQuotaSize)
  881. err = client.Rename(dir+"_copy1", dir+"_copy2", false)
  882. assert.NoError(t, err)
  883. err = client.Remove(path.Join(dir+"_copy", testFileName))
  884. assert.NoError(t, err)
  885. err = client.Rename(dir+"_copy2", dir+"_copy", true)
  886. assert.NoError(t, err)
  887. err = client.Copy(dir+"_copy", dir+"_copy1", false)
  888. assert.NoError(t, err)
  889. err = client.RemoveAll(dir + "_copy1")
  890. assert.NoError(t, err)
  891. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  892. assert.NoError(t, err)
  893. assert.Equal(t, 6, user.UsedQuotaFiles)
  894. assert.Equal(t, 6*testFileSize, user.UsedQuotaSize)
  895. err = os.Remove(testFilePath)
  896. assert.NoError(t, err)
  897. _, err = httpd.RemoveUser(user, http.StatusOK)
  898. assert.NoError(t, err)
  899. err = os.RemoveAll(user.GetHomeDir())
  900. assert.NoError(t, err)
  901. }
  902. func checkBasicFunc(client *gowebdav.Client) error {
  903. err := client.Connect()
  904. if err != nil {
  905. return err
  906. }
  907. _, err = client.ReadDir("/")
  908. return err
  909. }
  910. func uploadFile(localSourcePath string, remoteDestPath string, expectedSize int64, client *gowebdav.Client) error {
  911. srcFile, err := os.Open(localSourcePath)
  912. if err != nil {
  913. return err
  914. }
  915. defer srcFile.Close()
  916. err = client.WriteStream(remoteDestPath, srcFile, os.ModePerm)
  917. if err != nil {
  918. return err
  919. }
  920. if expectedSize > 0 {
  921. info, err := client.Stat(remoteDestPath)
  922. if err != nil {
  923. return err
  924. }
  925. if info.Size() != expectedSize {
  926. return fmt.Errorf("uploaded file size does not match, actual: %v, expected: %v", info.Size(), expectedSize)
  927. }
  928. }
  929. return nil
  930. }
  931. func downloadFile(remoteSourcePath string, localDestPath string, expectedSize int64, client *gowebdav.Client) error {
  932. downloadDest, err := os.Create(localDestPath)
  933. if err != nil {
  934. return err
  935. }
  936. defer downloadDest.Close()
  937. reader, err := client.ReadStream(remoteSourcePath)
  938. if err != nil {
  939. return err
  940. }
  941. defer reader.Close()
  942. written, err := io.Copy(downloadDest, reader)
  943. if err != nil {
  944. return err
  945. }
  946. if written != expectedSize {
  947. return fmt.Errorf("downloaded file size does not match, actual: %v, expected: %v", written, expectedSize)
  948. }
  949. return nil
  950. }
  951. func getWebDavClient(user dataprovider.User) *gowebdav.Client {
  952. rootPath := fmt.Sprintf("http://%v/%v", webDavServerAddr, user.Username)
  953. pwd := defaultPassword
  954. if len(user.Password) > 0 {
  955. pwd = user.Password
  956. }
  957. client := gowebdav.NewClient(rootPath, user.Username, pwd)
  958. client.SetTimeout(5 * time.Second)
  959. return client
  960. }
  961. func waitTCPListening(address string) {
  962. for {
  963. conn, err := net.Dial("tcp", address)
  964. if err != nil {
  965. logger.WarnToConsole("tcp server %v not listening: %v\n", address, err)
  966. time.Sleep(100 * time.Millisecond)
  967. continue
  968. }
  969. logger.InfoToConsole("tcp server %v now listening\n", address)
  970. conn.Close()
  971. break
  972. }
  973. }
  974. func getTestUser() dataprovider.User {
  975. user := dataprovider.User{
  976. Username: defaultUsername,
  977. Password: defaultPassword,
  978. HomeDir: filepath.Join(homeBasePath, defaultUsername),
  979. Status: 1,
  980. ExpirationDate: 0,
  981. }
  982. user.Permissions = make(map[string][]string)
  983. user.Permissions["/"] = allPerms
  984. return user
  985. }
  986. func getExtAuthScriptContent(user dataprovider.User, nonJSONResponse bool, username string) []byte {
  987. extAuthContent := []byte("#!/bin/sh\n\n")
  988. extAuthContent = append(extAuthContent, []byte(fmt.Sprintf("if test \"$SFTPGO_AUTHD_USERNAME\" = \"%v\"; then\n", user.Username))...)
  989. if len(username) > 0 {
  990. user.Username = username
  991. }
  992. u, _ := json.Marshal(user)
  993. if nonJSONResponse {
  994. extAuthContent = append(extAuthContent, []byte("echo 'text response'\n")...)
  995. } else {
  996. extAuthContent = append(extAuthContent, []byte(fmt.Sprintf("echo '%v'\n", string(u)))...)
  997. }
  998. extAuthContent = append(extAuthContent, []byte("else\n")...)
  999. if nonJSONResponse {
  1000. extAuthContent = append(extAuthContent, []byte("echo 'text response'\n")...)
  1001. } else {
  1002. extAuthContent = append(extAuthContent, []byte("echo '{\"username\":\"\"}'\n")...)
  1003. }
  1004. extAuthContent = append(extAuthContent, []byte("fi\n")...)
  1005. return extAuthContent
  1006. }
  1007. func getPreLoginScriptContent(user dataprovider.User, nonJSONResponse bool) []byte {
  1008. content := []byte("#!/bin/sh\n\n")
  1009. if nonJSONResponse {
  1010. content = append(content, []byte("echo 'text response'\n")...)
  1011. return content
  1012. }
  1013. if len(user.Username) > 0 {
  1014. u, _ := json.Marshal(user)
  1015. content = append(content, []byte(fmt.Sprintf("echo '%v'\n", string(u)))...)
  1016. }
  1017. return content
  1018. }
  1019. func getPostConnectScriptContent(exitCode int) []byte {
  1020. content := []byte("#!/bin/sh\n\n")
  1021. content = append(content, []byte(fmt.Sprintf("exit %v", exitCode))...)
  1022. return content
  1023. }
  1024. func createTestFile(path string, size int64) error {
  1025. baseDir := filepath.Dir(path)
  1026. if _, err := os.Stat(baseDir); os.IsNotExist(err) {
  1027. err = os.MkdirAll(baseDir, os.ModePerm)
  1028. if err != nil {
  1029. return err
  1030. }
  1031. }
  1032. content := make([]byte, size)
  1033. _, err := rand.Read(content)
  1034. if err != nil {
  1035. return err
  1036. }
  1037. return ioutil.WriteFile(path, content, os.ModePerm)
  1038. }