httpd_test.go 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108
  1. package httpd_test
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "net"
  7. "net/http"
  8. "net/http/httptest"
  9. "net/url"
  10. "os"
  11. "path/filepath"
  12. "runtime"
  13. "strconv"
  14. "strings"
  15. "testing"
  16. "time"
  17. "github.com/go-chi/render"
  18. _ "github.com/go-sql-driver/mysql"
  19. _ "github.com/lib/pq"
  20. _ "github.com/mattn/go-sqlite3"
  21. "github.com/rs/zerolog"
  22. "github.com/drakkan/sftpgo/config"
  23. "github.com/drakkan/sftpgo/dataprovider"
  24. "github.com/drakkan/sftpgo/httpd"
  25. "github.com/drakkan/sftpgo/logger"
  26. "github.com/drakkan/sftpgo/sftpd"
  27. "github.com/drakkan/sftpgo/utils"
  28. )
  29. const (
  30. defaultUsername = "test_user"
  31. defaultPassword = "test_password"
  32. testPubKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC03jj0D+djk7pxIf/0OhrxrchJTRZklofJ1NoIu4752Sq02mdXmarMVsqJ1cAjV5LBVy3D1F5U6XW4rppkXeVtd04Pxb09ehtH0pRRPaoHHlALiJt8CoMpbKYMA8b3KXPPriGxgGomvtU2T2RMURSwOZbMtpsugfjYSWenyYX+VORYhylWnSXL961LTyC21ehd6d6QnW9G7E5hYMITMY9TuQZz3bROYzXiTsgN0+g6Hn7exFQp50p45StUMfV/SftCMdCxlxuyGny2CrN/vfjO7xxOo2uv7q1qm10Q46KPWJQv+pgZ/OfL+EDjy07n5QVSKHlbx+2nT4Q0EgOSQaCTYwn3YjtABfIxWwgAFdyj6YlPulCL22qU4MYhDcA6PSBwDdf8hvxBfvsiHdM+JcSHvv8/VeJhk6CmnZxGY0fxBupov27z3yEO8nAg8k+6PaUiW1MSUfuGMF/ktB8LOstXsEPXSszuyXiOv4DaryOXUiSn7bmRqKcEFlJusO6aZP0= nicola@p1"
  33. logSender = "APITesting"
  34. userPath = "/api/v1/user"
  35. activeConnectionsPath = "/api/v1/connection"
  36. quotaScanPath = "/api/v1/quota_scan"
  37. versionPath = "/api/v1/version"
  38. metricsPath = "/metrics"
  39. webBasePath = "/web"
  40. webUsersPath = "/web/users"
  41. webUserPath = "/web/user"
  42. webConnectionsPath = "/web/connections"
  43. configDir = ".."
  44. )
  45. var (
  46. defaultPerms = []string{dataprovider.PermAny}
  47. homeBasePath string
  48. testServer *httptest.Server
  49. providerDriverName string
  50. )
  51. func TestMain(m *testing.M) {
  52. if runtime.GOOS == "windows" {
  53. homeBasePath = "C:\\"
  54. } else {
  55. homeBasePath = "/tmp"
  56. }
  57. logfilePath := filepath.Join(configDir, "sftpgo_api_test.log")
  58. logger.InitLogger(logfilePath, 5, 1, 28, false, zerolog.DebugLevel)
  59. config.LoadConfig(configDir, "")
  60. providerConf := config.GetProviderConf()
  61. providerDriverName = providerConf.Driver
  62. err := dataprovider.Initialize(providerConf, configDir)
  63. if err != nil {
  64. logger.Warn(logSender, "", "error initializing data provider: %v", err)
  65. os.Exit(1)
  66. }
  67. dataProvider := dataprovider.GetProvider()
  68. httpdConf := config.GetHTTPDConfig()
  69. httpdConf.BindPort = 8081
  70. httpd.SetBaseURL("http://127.0.0.1:8081")
  71. sftpd.SetDataProvider(dataProvider)
  72. httpd.SetDataProvider(dataProvider)
  73. go func() {
  74. go func() {
  75. if err := httpdConf.Initialize(configDir); err != nil {
  76. logger.Error(logSender, "", "could not start HTTP server: %v", err)
  77. }
  78. }()
  79. }()
  80. waitTCPListening(fmt.Sprintf("%s:%d", httpdConf.BindAddress, httpdConf.BindPort))
  81. testServer = httptest.NewServer(httpd.GetHTTPRouter())
  82. defer testServer.Close()
  83. exitCode := m.Run()
  84. os.Remove(logfilePath)
  85. os.Exit(exitCode)
  86. }
  87. func TestBasicUserHandling(t *testing.T) {
  88. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  89. if err != nil {
  90. t.Errorf("unable to add user: %v", err)
  91. }
  92. user.MaxSessions = 10
  93. user.QuotaSize = 4096
  94. user.QuotaFiles = 2
  95. user.UploadBandwidth = 128
  96. user.DownloadBandwidth = 64
  97. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  98. if err != nil {
  99. t.Errorf("unable to update user: %v", err)
  100. }
  101. users, _, err := httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  102. if err != nil {
  103. t.Errorf("unable to get users: %v", err)
  104. }
  105. if len(users) != 1 {
  106. t.Errorf("number of users mismatch, expected: 1, actual: %v", len(users))
  107. }
  108. _, err = httpd.RemoveUser(user, http.StatusOK)
  109. if err != nil {
  110. t.Errorf("unable to remove: %v", err)
  111. }
  112. }
  113. func TestAddUserNoCredentials(t *testing.T) {
  114. u := getTestUser()
  115. u.Password = ""
  116. u.PublicKeys = []string{}
  117. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  118. if err != nil {
  119. t.Errorf("unexpected error adding user with no credentials: %v", err)
  120. }
  121. }
  122. func TestAddUserNoUsername(t *testing.T) {
  123. u := getTestUser()
  124. u.Username = ""
  125. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  126. if err != nil {
  127. t.Errorf("unexpected error adding user with no home dir: %v", err)
  128. }
  129. }
  130. func TestAddUserNoHomeDir(t *testing.T) {
  131. u := getTestUser()
  132. u.HomeDir = ""
  133. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  134. if err != nil {
  135. t.Errorf("unexpected error adding user with no home dir: %v", err)
  136. }
  137. }
  138. func TestAddUserInvalidHomeDir(t *testing.T) {
  139. u := getTestUser()
  140. u.HomeDir = "relative_path"
  141. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  142. if err != nil {
  143. t.Errorf("unexpected error adding user with invalid home dir: %v", err)
  144. }
  145. }
  146. func TestAddUserNoPerms(t *testing.T) {
  147. u := getTestUser()
  148. u.Permissions = []string{}
  149. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  150. if err != nil {
  151. t.Errorf("unexpected error adding user with no perms: %v", err)
  152. }
  153. }
  154. func TestAddUserInvalidPerms(t *testing.T) {
  155. u := getTestUser()
  156. u.Permissions = []string{"invalidPerm"}
  157. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  158. if err != nil {
  159. t.Errorf("unexpected error adding user with no perms: %v", err)
  160. }
  161. }
  162. func TestUserPublicKey(t *testing.T) {
  163. u := getTestUser()
  164. invalidPubKey := "invalid"
  165. validPubKey := "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC03jj0D+djk7pxIf/0OhrxrchJTRZklofJ1NoIu4752Sq02mdXmarMVsqJ1cAjV5LBVy3D1F5U6XW4rppkXeVtd04Pxb09ehtH0pRRPaoHHlALiJt8CoMpbKYMA8b3KXPPriGxgGomvtU2T2RMURSwOZbMtpsugfjYSWenyYX+VORYhylWnSXL961LTyC21ehd6d6QnW9G7E5hYMITMY9TuQZz3bROYzXiTsgN0+g6Hn7exFQp50p45StUMfV/SftCMdCxlxuyGny2CrN/vfjO7xxOo2uv7q1qm10Q46KPWJQv+pgZ/OfL+EDjy07n5QVSKHlbx+2nT4Q0EgOSQaCTYwn3YjtABfIxWwgAFdyj6YlPulCL22qU4MYhDcA6PSBwDdf8hvxBfvsiHdM+JcSHvv8/VeJhk6CmnZxGY0fxBupov27z3yEO8nAg8k+6PaUiW1MSUfuGMF/ktB8LOstXsEPXSszuyXiOv4DaryOXUiSn7bmRqKcEFlJusO6aZP0= nicola@p1"
  166. u.PublicKeys = []string{invalidPubKey}
  167. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  168. if err != nil {
  169. t.Errorf("unexpected error adding user with invalid pub key: %v", err)
  170. }
  171. u.PublicKeys = []string{validPubKey}
  172. user, _, err := httpd.AddUser(u, http.StatusOK)
  173. if err != nil {
  174. t.Errorf("unable to add user: %v", err)
  175. }
  176. user.PublicKeys = []string{validPubKey, invalidPubKey}
  177. _, _, err = httpd.UpdateUser(user, http.StatusBadRequest)
  178. if err != nil {
  179. t.Errorf("update user with invalid public key must fail: %v", err)
  180. }
  181. user.PublicKeys = []string{validPubKey, validPubKey, validPubKey}
  182. _, _, err = httpd.UpdateUser(user, http.StatusOK)
  183. if err != nil {
  184. t.Errorf("unable to update user: %v", err)
  185. }
  186. _, err = httpd.RemoveUser(user, http.StatusOK)
  187. if err != nil {
  188. t.Errorf("unable to remove: %v", err)
  189. }
  190. }
  191. func TestUpdateUser(t *testing.T) {
  192. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  193. if err != nil {
  194. t.Errorf("unable to add user: %v", err)
  195. }
  196. user.HomeDir = filepath.Join(homeBasePath, "testmod")
  197. user.UID = 33
  198. user.GID = 101
  199. user.MaxSessions = 10
  200. user.QuotaSize = 4096
  201. user.QuotaFiles = 2
  202. user.Permissions = []string{dataprovider.PermCreateDirs, dataprovider.PermDelete, dataprovider.PermDownload}
  203. user.UploadBandwidth = 1024
  204. user.DownloadBandwidth = 512
  205. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  206. if err != nil {
  207. t.Errorf("unable to update user: %v", err)
  208. }
  209. _, err = httpd.RemoveUser(user, http.StatusOK)
  210. if err != nil {
  211. t.Errorf("unable to remove: %v", err)
  212. }
  213. }
  214. func TestUpdateUserNoCredentials(t *testing.T) {
  215. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  216. if err != nil {
  217. t.Errorf("unable to add user: %v", err)
  218. }
  219. user.Password = ""
  220. user.PublicKeys = []string{}
  221. // password and public key will be omitted from json serialization if empty and so they will remain unchanged
  222. // and no validation error will be raised
  223. _, _, err = httpd.UpdateUser(user, http.StatusOK)
  224. if err != nil {
  225. t.Errorf("unexpected error updating user with no credentials: %v", err)
  226. }
  227. _, err = httpd.RemoveUser(user, http.StatusOK)
  228. if err != nil {
  229. t.Errorf("unable to remove: %v", err)
  230. }
  231. }
  232. func TestUpdateUserEmptyHomeDir(t *testing.T) {
  233. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  234. if err != nil {
  235. t.Errorf("unable to add user: %v", err)
  236. }
  237. user.HomeDir = ""
  238. _, _, err = httpd.UpdateUser(user, http.StatusBadRequest)
  239. if err != nil {
  240. t.Errorf("unexpected error updating user with empty home dir: %v", err)
  241. }
  242. _, err = httpd.RemoveUser(user, http.StatusOK)
  243. if err != nil {
  244. t.Errorf("unable to remove: %v", err)
  245. }
  246. }
  247. func TestUpdateUserInvalidHomeDir(t *testing.T) {
  248. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  249. if err != nil {
  250. t.Errorf("unable to add user: %v", err)
  251. }
  252. user.HomeDir = "relative_path"
  253. _, _, err = httpd.UpdateUser(user, http.StatusBadRequest)
  254. if err != nil {
  255. t.Errorf("unexpected error updating user with empty home dir: %v", err)
  256. }
  257. _, err = httpd.RemoveUser(user, http.StatusOK)
  258. if err != nil {
  259. t.Errorf("unable to remove: %v", err)
  260. }
  261. }
  262. func TestUpdateNonExistentUser(t *testing.T) {
  263. _, _, err := httpd.UpdateUser(getTestUser(), http.StatusNotFound)
  264. if err != nil {
  265. t.Errorf("unable to update user: %v", err)
  266. }
  267. }
  268. func TestGetNonExistentUser(t *testing.T) {
  269. _, _, err := httpd.GetUserByID(0, http.StatusNotFound)
  270. if err != nil {
  271. t.Errorf("unable to get user: %v", err)
  272. }
  273. }
  274. func TestDeleteNonExistentUser(t *testing.T) {
  275. _, err := httpd.RemoveUser(getTestUser(), http.StatusNotFound)
  276. if err != nil {
  277. t.Errorf("unable to remove user: %v", err)
  278. }
  279. }
  280. func TestAddDuplicateUser(t *testing.T) {
  281. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  282. if err != nil {
  283. t.Errorf("unable to add user: %v", err)
  284. }
  285. _, _, err = httpd.AddUser(getTestUser(), http.StatusInternalServerError)
  286. if err != nil {
  287. t.Errorf("unable to add second user: %v", err)
  288. }
  289. _, _, err = httpd.AddUser(getTestUser(), http.StatusOK)
  290. if err == nil {
  291. t.Errorf("adding a duplicate user must fail")
  292. }
  293. _, err = httpd.RemoveUser(user, http.StatusOK)
  294. if err != nil {
  295. t.Errorf("unable to remove user: %v", err)
  296. }
  297. }
  298. func TestGetUsers(t *testing.T) {
  299. user1, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  300. if err != nil {
  301. t.Errorf("unable to add user: %v", err)
  302. }
  303. u := getTestUser()
  304. u.Username = defaultUsername + "1"
  305. user2, _, err := httpd.AddUser(u, http.StatusOK)
  306. if err != nil {
  307. t.Errorf("unable to add second user: %v", err)
  308. }
  309. users, _, err := httpd.GetUsers(0, 0, "", http.StatusOK)
  310. if err != nil {
  311. t.Errorf("unable to get users: %v", err)
  312. }
  313. if len(users) < 2 {
  314. t.Errorf("at least 2 users are expected")
  315. }
  316. users, _, err = httpd.GetUsers(1, 0, "", http.StatusOK)
  317. if err != nil {
  318. t.Errorf("unable to get users: %v", err)
  319. }
  320. if len(users) != 1 {
  321. t.Errorf("1 user is expected")
  322. }
  323. users, _, err = httpd.GetUsers(1, 1, "", http.StatusOK)
  324. if err != nil {
  325. t.Errorf("unable to get users: %v", err)
  326. }
  327. if len(users) != 1 {
  328. t.Errorf("1 user is expected")
  329. }
  330. _, _, err = httpd.GetUsers(1, 1, "", http.StatusInternalServerError)
  331. if err == nil {
  332. t.Errorf("get users must succeed, we requested a fail for a good request")
  333. }
  334. _, err = httpd.RemoveUser(user1, http.StatusOK)
  335. if err != nil {
  336. t.Errorf("unable to remove user: %v", err)
  337. }
  338. _, err = httpd.RemoveUser(user2, http.StatusOK)
  339. if err != nil {
  340. t.Errorf("unable to remove user: %v", err)
  341. }
  342. }
  343. func TestGetQuotaScans(t *testing.T) {
  344. _, _, err := httpd.GetQuotaScans(http.StatusOK)
  345. if err != nil {
  346. t.Errorf("unable to get quota scans: %v", err)
  347. }
  348. _, _, err = httpd.GetQuotaScans(http.StatusInternalServerError)
  349. if err == nil {
  350. t.Errorf("quota scan request must succeed, we requested to check a wrong status code")
  351. }
  352. }
  353. func TestStartQuotaScan(t *testing.T) {
  354. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  355. if err != nil {
  356. t.Errorf("unable to add user: %v", err)
  357. }
  358. _, err = httpd.StartQuotaScan(user, http.StatusCreated)
  359. if err != nil {
  360. t.Errorf("unable to start quota scan: %v", err)
  361. }
  362. _, err = httpd.RemoveUser(user, http.StatusOK)
  363. if err != nil {
  364. t.Errorf("unable to remove user: %v", err)
  365. }
  366. }
  367. func TestGetVersion(t *testing.T) {
  368. _, _, err := httpd.GetVersion(http.StatusOK)
  369. if err != nil {
  370. t.Errorf("unable to get sftp version: %v", err)
  371. }
  372. _, _, err = httpd.GetVersion(http.StatusInternalServerError)
  373. if err == nil {
  374. t.Errorf("get version request must succeed, we requested to check a wrong status code")
  375. }
  376. }
  377. func TestGetConnections(t *testing.T) {
  378. _, _, err := httpd.GetConnections(http.StatusOK)
  379. if err != nil {
  380. t.Errorf("unable to get sftp connections: %v", err)
  381. }
  382. _, _, err = httpd.GetConnections(http.StatusInternalServerError)
  383. if err == nil {
  384. t.Errorf("get sftp connections request must succeed, we requested to check a wrong status code")
  385. }
  386. }
  387. func TestCloseActiveConnection(t *testing.T) {
  388. _, err := httpd.CloseConnection("non_existent_id", http.StatusNotFound)
  389. if err != nil {
  390. t.Errorf("unexpected error closing non existent sftp connection: %v", err)
  391. }
  392. }
  393. func TestUserBaseDir(t *testing.T) {
  394. dataProvider := dataprovider.GetProvider()
  395. dataprovider.Close(dataProvider)
  396. config.LoadConfig(configDir, "")
  397. providerConf := config.GetProviderConf()
  398. providerConf.UsersBaseDir = homeBasePath
  399. err := dataprovider.Initialize(providerConf, configDir)
  400. if err != nil {
  401. t.Errorf("error initializing data provider with users base dir")
  402. }
  403. httpd.SetDataProvider(dataprovider.GetProvider())
  404. u := getTestUser()
  405. u.HomeDir = ""
  406. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  407. if err != nil {
  408. t.Errorf("unable to add user: %v", err)
  409. }
  410. if user.HomeDir != filepath.Join(providerConf.UsersBaseDir, u.Username) {
  411. t.Errorf("invalid home dir: %v", user.HomeDir)
  412. }
  413. _, err = httpd.RemoveUser(user, http.StatusOK)
  414. if err != nil {
  415. t.Errorf("unable to remove: %v", err)
  416. }
  417. dataProvider = dataprovider.GetProvider()
  418. dataprovider.Close(dataProvider)
  419. config.LoadConfig(configDir, "")
  420. providerConf = config.GetProviderConf()
  421. err = dataprovider.Initialize(providerConf, configDir)
  422. if err != nil {
  423. t.Errorf("error initializing data provider")
  424. }
  425. httpd.SetDataProvider(dataprovider.GetProvider())
  426. sftpd.SetDataProvider(dataprovider.GetProvider())
  427. }
  428. func TestProviderErrors(t *testing.T) {
  429. if providerDriverName == dataprovider.BoltDataProviderName {
  430. t.Skip("skipping test provider errors for bolt provider")
  431. }
  432. dataProvider := dataprovider.GetProvider()
  433. dataprovider.Close(dataProvider)
  434. _, _, err := httpd.GetUserByID(0, http.StatusInternalServerError)
  435. if err != nil {
  436. t.Errorf("get user with provider closed must fail: %v", err)
  437. }
  438. _, _, err = httpd.GetUsers(1, 0, defaultUsername, http.StatusInternalServerError)
  439. if err != nil {
  440. t.Errorf("get users with provider closed must fail: %v", err)
  441. }
  442. _, _, err = httpd.UpdateUser(dataprovider.User{}, http.StatusInternalServerError)
  443. if err != nil {
  444. t.Errorf("update user with provider closed must fail: %v", err)
  445. }
  446. _, err = httpd.RemoveUser(dataprovider.User{}, http.StatusInternalServerError)
  447. if err != nil {
  448. t.Errorf("delete user with provider closed must fail: %v", err)
  449. }
  450. config.LoadConfig(configDir, "")
  451. providerConf := config.GetProviderConf()
  452. err = dataprovider.Initialize(providerConf, configDir)
  453. if err != nil {
  454. t.Errorf("error initializing data provider")
  455. }
  456. httpd.SetDataProvider(dataprovider.GetProvider())
  457. sftpd.SetDataProvider(dataprovider.GetProvider())
  458. }
  459. // test using mock http server
  460. func TestBasicUserHandlingMock(t *testing.T) {
  461. user := getTestUser()
  462. userAsJSON := getUserAsJSON(t, user)
  463. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  464. rr := executeRequest(req)
  465. checkResponseCode(t, http.StatusOK, rr.Code)
  466. err := render.DecodeJSON(rr.Body, &user)
  467. if err != nil {
  468. t.Errorf("Error get user: %v", err)
  469. }
  470. req, _ = http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  471. rr = executeRequest(req)
  472. checkResponseCode(t, http.StatusInternalServerError, rr.Code)
  473. user.MaxSessions = 10
  474. user.UploadBandwidth = 128
  475. user.Permissions = []string{dataprovider.PermAny, dataprovider.PermDelete, dataprovider.PermDownload}
  476. userAsJSON = getUserAsJSON(t, user)
  477. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer(userAsJSON))
  478. rr = executeRequest(req)
  479. checkResponseCode(t, http.StatusOK, rr.Code)
  480. req, _ = http.NewRequest(http.MethodGet, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  481. rr = executeRequest(req)
  482. checkResponseCode(t, http.StatusOK, rr.Code)
  483. var updatedUser dataprovider.User
  484. err = render.DecodeJSON(rr.Body, &updatedUser)
  485. if err != nil {
  486. t.Errorf("Error decoding updated user: %v", err)
  487. }
  488. if user.MaxSessions != updatedUser.MaxSessions || user.UploadBandwidth != updatedUser.UploadBandwidth {
  489. t.Errorf("Error modifying user actual: %v, %v", updatedUser.MaxSessions, updatedUser.UploadBandwidth)
  490. }
  491. if len(updatedUser.Permissions) != 1 {
  492. t.Errorf("permissions other than any should be removed")
  493. }
  494. if !utils.IsStringInSlice(dataprovider.PermAny, updatedUser.Permissions) {
  495. t.Errorf("permissions mismatch")
  496. }
  497. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  498. rr = executeRequest(req)
  499. checkResponseCode(t, http.StatusOK, rr.Code)
  500. }
  501. func TestGetUserByIdInvalidParamsMock(t *testing.T) {
  502. req, _ := http.NewRequest(http.MethodGet, userPath+"/0", nil)
  503. rr := executeRequest(req)
  504. checkResponseCode(t, http.StatusNotFound, rr.Code)
  505. req, _ = http.NewRequest(http.MethodGet, userPath+"/a", nil)
  506. rr = executeRequest(req)
  507. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  508. }
  509. func TestAddUserNoUsernameMock(t *testing.T) {
  510. user := getTestUser()
  511. user.Username = ""
  512. userAsJSON := getUserAsJSON(t, user)
  513. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  514. rr := executeRequest(req)
  515. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  516. }
  517. func TestAddUserInvalidHomeDirMock(t *testing.T) {
  518. user := getTestUser()
  519. user.HomeDir = "relative_path"
  520. userAsJSON := getUserAsJSON(t, user)
  521. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  522. rr := executeRequest(req)
  523. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  524. }
  525. func TestAddUserInvalidPermsMock(t *testing.T) {
  526. user := getTestUser()
  527. user.Permissions = []string{}
  528. userAsJSON := getUserAsJSON(t, user)
  529. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  530. rr := executeRequest(req)
  531. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  532. }
  533. func TestAddUserInvalidJsonMock(t *testing.T) {
  534. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer([]byte("invalid json")))
  535. rr := executeRequest(req)
  536. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  537. }
  538. func TestUpdateUserInvalidJsonMock(t *testing.T) {
  539. user := getTestUser()
  540. userAsJSON := getUserAsJSON(t, user)
  541. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  542. rr := executeRequest(req)
  543. checkResponseCode(t, http.StatusOK, rr.Code)
  544. err := render.DecodeJSON(rr.Body, &user)
  545. if err != nil {
  546. t.Errorf("Error get user: %v", err)
  547. }
  548. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer([]byte("Invalid json")))
  549. rr = executeRequest(req)
  550. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  551. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  552. rr = executeRequest(req)
  553. checkResponseCode(t, http.StatusOK, rr.Code)
  554. }
  555. func TestUpdateUserInvalidParamsMock(t *testing.T) {
  556. user := getTestUser()
  557. userAsJSON := getUserAsJSON(t, user)
  558. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  559. rr := executeRequest(req)
  560. checkResponseCode(t, http.StatusOK, rr.Code)
  561. err := render.DecodeJSON(rr.Body, &user)
  562. if err != nil {
  563. t.Errorf("Error get user: %v", err)
  564. }
  565. user.HomeDir = ""
  566. userAsJSON = getUserAsJSON(t, user)
  567. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer(userAsJSON))
  568. rr = executeRequest(req)
  569. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  570. userID := user.ID
  571. user.ID = 0
  572. userAsJSON = getUserAsJSON(t, user)
  573. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(userID, 10), bytes.NewBuffer(userAsJSON))
  574. rr = executeRequest(req)
  575. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  576. user.ID = userID
  577. req, _ = http.NewRequest(http.MethodPut, userPath+"/0", bytes.NewBuffer(userAsJSON))
  578. rr = executeRequest(req)
  579. checkResponseCode(t, http.StatusNotFound, rr.Code)
  580. req, _ = http.NewRequest(http.MethodPut, userPath+"/a", bytes.NewBuffer(userAsJSON))
  581. rr = executeRequest(req)
  582. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  583. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  584. rr = executeRequest(req)
  585. checkResponseCode(t, http.StatusOK, rr.Code)
  586. }
  587. func TestGetUsersMock(t *testing.T) {
  588. user := getTestUser()
  589. userAsJSON := getUserAsJSON(t, user)
  590. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  591. rr := executeRequest(req)
  592. checkResponseCode(t, http.StatusOK, rr.Code)
  593. err := render.DecodeJSON(rr.Body, &user)
  594. if err != nil {
  595. t.Errorf("Error get user: %v", err)
  596. }
  597. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=510&offset=0&order=ASC&username="+defaultUsername, nil)
  598. rr = executeRequest(req)
  599. checkResponseCode(t, http.StatusOK, rr.Code)
  600. var users []dataprovider.User
  601. err = render.DecodeJSON(rr.Body, &users)
  602. if err != nil {
  603. t.Errorf("Error decoding users: %v", err)
  604. }
  605. if len(users) != 1 {
  606. t.Errorf("1 user is expected")
  607. }
  608. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=a&offset=0&order=ASC", nil)
  609. rr = executeRequest(req)
  610. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  611. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=a&order=ASC", nil)
  612. rr = executeRequest(req)
  613. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  614. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=0&order=ASCa", nil)
  615. rr = executeRequest(req)
  616. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  617. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  618. rr = executeRequest(req)
  619. checkResponseCode(t, http.StatusOK, rr.Code)
  620. }
  621. func TestDeleteUserInvalidParamsMock(t *testing.T) {
  622. req, _ := http.NewRequest(http.MethodDelete, userPath+"/0", nil)
  623. rr := executeRequest(req)
  624. checkResponseCode(t, http.StatusNotFound, rr.Code)
  625. req, _ = http.NewRequest(http.MethodDelete, userPath+"/a", nil)
  626. rr = executeRequest(req)
  627. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  628. }
  629. func TestGetQuotaScansMock(t *testing.T) {
  630. req, err := http.NewRequest("GET", quotaScanPath, nil)
  631. if err != nil {
  632. t.Errorf("error get quota scan: %v", err)
  633. }
  634. rr := executeRequest(req)
  635. checkResponseCode(t, http.StatusOK, rr.Code)
  636. }
  637. func TestStartQuotaScanMock(t *testing.T) {
  638. user := getTestUser()
  639. userAsJSON := getUserAsJSON(t, user)
  640. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  641. rr := executeRequest(req)
  642. checkResponseCode(t, http.StatusOK, rr.Code)
  643. err := render.DecodeJSON(rr.Body, &user)
  644. if err != nil {
  645. t.Errorf("Error get user: %v", err)
  646. }
  647. _, err = os.Stat(user.HomeDir)
  648. if err == nil {
  649. os.Remove(user.HomeDir)
  650. }
  651. // simulate a duplicate quota scan
  652. userAsJSON = getUserAsJSON(t, user)
  653. sftpd.AddQuotaScan(user.Username)
  654. req, _ = http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer(userAsJSON))
  655. rr = executeRequest(req)
  656. checkResponseCode(t, http.StatusConflict, rr.Code)
  657. sftpd.RemoveQuotaScan(user.Username)
  658. userAsJSON = getUserAsJSON(t, user)
  659. req, _ = http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer(userAsJSON))
  660. rr = executeRequest(req)
  661. checkResponseCode(t, http.StatusCreated, rr.Code)
  662. req, _ = http.NewRequest(http.MethodGet, quotaScanPath, nil)
  663. rr = executeRequest(req)
  664. checkResponseCode(t, http.StatusOK, rr.Code)
  665. var scans []sftpd.ActiveQuotaScan
  666. err = render.DecodeJSON(rr.Body, &scans)
  667. if err != nil {
  668. t.Errorf("Error get active scans: %v", err)
  669. }
  670. for len(scans) > 0 {
  671. req, _ = http.NewRequest(http.MethodGet, quotaScanPath, nil)
  672. rr = executeRequest(req)
  673. checkResponseCode(t, http.StatusOK, rr.Code)
  674. err = render.DecodeJSON(rr.Body, &scans)
  675. if err != nil {
  676. t.Errorf("Error get active scans: %v", err)
  677. break
  678. }
  679. }
  680. _, err = os.Stat(user.HomeDir)
  681. if err != nil && os.IsNotExist(err) {
  682. os.MkdirAll(user.HomeDir, 0777)
  683. }
  684. req, _ = http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer(userAsJSON))
  685. rr = executeRequest(req)
  686. checkResponseCode(t, http.StatusCreated, rr.Code)
  687. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  688. rr = executeRequest(req)
  689. checkResponseCode(t, http.StatusOK, rr.Code)
  690. }
  691. func TestStartQuotaScanBadUserMock(t *testing.T) {
  692. user := getTestUser()
  693. userAsJSON := getUserAsJSON(t, user)
  694. req, _ := http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer(userAsJSON))
  695. rr := executeRequest(req)
  696. checkResponseCode(t, http.StatusNotFound, rr.Code)
  697. }
  698. func TestStartQuotaScanNonExistentUserMock(t *testing.T) {
  699. req, _ := http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer([]byte("invalid json")))
  700. rr := executeRequest(req)
  701. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  702. }
  703. func TestGetVersionMock(t *testing.T) {
  704. req, _ := http.NewRequest(http.MethodGet, versionPath, nil)
  705. rr := executeRequest(req)
  706. checkResponseCode(t, http.StatusOK, rr.Code)
  707. }
  708. func TestGetConnectionsMock(t *testing.T) {
  709. req, _ := http.NewRequest(http.MethodGet, activeConnectionsPath, nil)
  710. rr := executeRequest(req)
  711. checkResponseCode(t, http.StatusOK, rr.Code)
  712. }
  713. func TestDeleteActiveConnectionMock(t *testing.T) {
  714. req, _ := http.NewRequest(http.MethodDelete, activeConnectionsPath+"/connectionID", nil)
  715. rr := executeRequest(req)
  716. checkResponseCode(t, http.StatusNotFound, rr.Code)
  717. }
  718. func TestNotFoundMock(t *testing.T) {
  719. req, _ := http.NewRequest(http.MethodGet, "/non/existing/path", nil)
  720. rr := executeRequest(req)
  721. checkResponseCode(t, http.StatusNotFound, rr.Code)
  722. }
  723. func TestMethodNotAllowedMock(t *testing.T) {
  724. req, _ := http.NewRequest(http.MethodPost, activeConnectionsPath, nil)
  725. rr := executeRequest(req)
  726. checkResponseCode(t, http.StatusMethodNotAllowed, rr.Code)
  727. }
  728. func TestMetricsMock(t *testing.T) {
  729. req, _ := http.NewRequest(http.MethodGet, metricsPath, nil)
  730. rr := executeRequest(req)
  731. checkResponseCode(t, http.StatusOK, rr.Code)
  732. }
  733. func TestGetWebRootMock(t *testing.T) {
  734. req, _ := http.NewRequest(http.MethodGet, "/", nil)
  735. rr := executeRequest(req)
  736. checkResponseCode(t, http.StatusMovedPermanently, rr.Code)
  737. req, _ = http.NewRequest(http.MethodGet, webBasePath, nil)
  738. rr = executeRequest(req)
  739. checkResponseCode(t, http.StatusMovedPermanently, rr.Code)
  740. }
  741. func TestBasicWebUsersMock(t *testing.T) {
  742. user := getTestUser()
  743. userAsJSON := getUserAsJSON(t, user)
  744. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  745. rr := executeRequest(req)
  746. checkResponseCode(t, http.StatusOK, rr.Code)
  747. err := render.DecodeJSON(rr.Body, &user)
  748. if err != nil {
  749. t.Errorf("Error get user: %v", err)
  750. }
  751. user1 := getTestUser()
  752. user1.Username += "1"
  753. user1AsJSON := getUserAsJSON(t, user1)
  754. req, _ = http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(user1AsJSON))
  755. rr = executeRequest(req)
  756. checkResponseCode(t, http.StatusOK, rr.Code)
  757. err = render.DecodeJSON(rr.Body, &user1)
  758. if err != nil {
  759. t.Errorf("Error get user1: %v", err)
  760. }
  761. req, _ = http.NewRequest(http.MethodGet, webUsersPath, nil)
  762. rr = executeRequest(req)
  763. checkResponseCode(t, http.StatusOK, rr.Code)
  764. req, _ = http.NewRequest(http.MethodGet, webUsersPath+"?qlimit=a", nil)
  765. rr = executeRequest(req)
  766. checkResponseCode(t, http.StatusOK, rr.Code)
  767. req, _ = http.NewRequest(http.MethodGet, webUsersPath+"?qlimit=1", nil)
  768. rr = executeRequest(req)
  769. checkResponseCode(t, http.StatusOK, rr.Code)
  770. req, _ = http.NewRequest(http.MethodGet, webUserPath, nil)
  771. rr = executeRequest(req)
  772. checkResponseCode(t, http.StatusOK, rr.Code)
  773. req, _ = http.NewRequest(http.MethodGet, webUserPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  774. rr = executeRequest(req)
  775. checkResponseCode(t, http.StatusOK, rr.Code)
  776. req, _ = http.NewRequest(http.MethodGet, webUserPath+"/0", nil)
  777. rr = executeRequest(req)
  778. checkResponseCode(t, http.StatusNotFound, rr.Code)
  779. req, _ = http.NewRequest(http.MethodGet, webUserPath+"/a", nil)
  780. rr = executeRequest(req)
  781. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  782. form := make(url.Values)
  783. form.Set("username", user.Username)
  784. req, _ = http.NewRequest(http.MethodPost, webUserPath, strings.NewReader(form.Encode()))
  785. rr = executeRequest(req)
  786. checkResponseCode(t, http.StatusOK, rr.Code)
  787. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), strings.NewReader(form.Encode()))
  788. rr = executeRequest(req)
  789. checkResponseCode(t, http.StatusOK, rr.Code)
  790. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/0", strings.NewReader(form.Encode()))
  791. rr = executeRequest(req)
  792. checkResponseCode(t, http.StatusNotFound, rr.Code)
  793. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/a", strings.NewReader(form.Encode()))
  794. rr = executeRequest(req)
  795. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  796. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  797. rr = executeRequest(req)
  798. checkResponseCode(t, http.StatusOK, rr.Code)
  799. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user1.ID, 10), nil)
  800. rr = executeRequest(req)
  801. checkResponseCode(t, http.StatusOK, rr.Code)
  802. }
  803. func TestWebUserAddMock(t *testing.T) {
  804. user := getTestUser()
  805. user.UploadBandwidth = 32
  806. user.DownloadBandwidth = 64
  807. user.UID = 1000
  808. form := make(url.Values)
  809. form.Set("username", user.Username)
  810. form.Set("home_dir", user.HomeDir)
  811. form.Set("password", user.Password)
  812. form.Set("permissions", "*")
  813. // test invalid url escape
  814. req, _ := http.NewRequest(http.MethodPost, webUserPath+"?a=%2", strings.NewReader(form.Encode()))
  815. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  816. rr := executeRequest(req)
  817. checkResponseCode(t, http.StatusOK, rr.Code)
  818. form.Set("public_keys", testPubKey)
  819. form.Set("uid", strconv.FormatInt(int64(user.UID), 10))
  820. form.Set("gid", "a")
  821. // test invalid gid
  822. req, _ = http.NewRequest(http.MethodPost, webUserPath, strings.NewReader(form.Encode()))
  823. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  824. rr = executeRequest(req)
  825. checkResponseCode(t, http.StatusOK, rr.Code)
  826. form.Set("gid", "0")
  827. form.Set("max_sessions", "a")
  828. // test invalid max sessions
  829. req, _ = http.NewRequest(http.MethodPost, webUserPath, strings.NewReader(form.Encode()))
  830. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  831. rr = executeRequest(req)
  832. checkResponseCode(t, http.StatusOK, rr.Code)
  833. form.Set("max_sessions", "0")
  834. form.Set("quota_size", "a")
  835. // test invalid quota size
  836. req, _ = http.NewRequest(http.MethodPost, webUserPath, strings.NewReader(form.Encode()))
  837. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  838. rr = executeRequest(req)
  839. checkResponseCode(t, http.StatusOK, rr.Code)
  840. form.Set("quota_size", "0")
  841. form.Set("quota_files", "a")
  842. // test invalid quota files
  843. req, _ = http.NewRequest(http.MethodPost, webUserPath, strings.NewReader(form.Encode()))
  844. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  845. rr = executeRequest(req)
  846. checkResponseCode(t, http.StatusOK, rr.Code)
  847. form.Set("quota_files", "0")
  848. form.Set("upload_bandwidth", "a")
  849. // test invalid upload bandwidth
  850. req, _ = http.NewRequest(http.MethodPost, webUserPath, strings.NewReader(form.Encode()))
  851. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  852. rr = executeRequest(req)
  853. checkResponseCode(t, http.StatusOK, rr.Code)
  854. form.Set("upload_bandwidth", strconv.FormatInt(user.UploadBandwidth, 10))
  855. form.Set("download_bandwidth", "a")
  856. // test invalid download bandwidth
  857. req, _ = http.NewRequest(http.MethodPost, webUserPath, strings.NewReader(form.Encode()))
  858. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  859. rr = executeRequest(req)
  860. checkResponseCode(t, http.StatusOK, rr.Code)
  861. form.Set("download_bandwidth", strconv.FormatInt(user.DownloadBandwidth, 10))
  862. req, _ = http.NewRequest(http.MethodPost, webUserPath, strings.NewReader(form.Encode()))
  863. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  864. rr = executeRequest(req)
  865. checkResponseCode(t, http.StatusSeeOther, rr.Code)
  866. // the user already exists, was created with the above request
  867. req, _ = http.NewRequest(http.MethodPost, webUserPath, strings.NewReader(form.Encode()))
  868. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  869. rr = executeRequest(req)
  870. checkResponseCode(t, http.StatusOK, rr.Code)
  871. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=0&order=ASC&username="+user.Username, nil)
  872. rr = executeRequest(req)
  873. checkResponseCode(t, http.StatusOK, rr.Code)
  874. var users []dataprovider.User
  875. err := render.DecodeJSON(rr.Body, &users)
  876. if err != nil {
  877. t.Errorf("Error decoding users: %v", err)
  878. }
  879. if len(users) != 1 {
  880. t.Errorf("1 user is expected")
  881. }
  882. newUser := users[0]
  883. if newUser.UID != user.UID {
  884. t.Errorf("uid does not match")
  885. }
  886. if newUser.UploadBandwidth != user.UploadBandwidth {
  887. t.Errorf("upload_bandwidth does not match")
  888. }
  889. if newUser.DownloadBandwidth != user.DownloadBandwidth {
  890. t.Errorf("download_bandwidth does not match")
  891. }
  892. if !utils.IsStringInSlice(testPubKey, newUser.PublicKeys) {
  893. t.Errorf("public_keys does not match")
  894. }
  895. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(newUser.ID, 10), nil)
  896. rr = executeRequest(req)
  897. checkResponseCode(t, http.StatusOK, rr.Code)
  898. }
  899. func TestWebUserUpdateMock(t *testing.T) {
  900. user := getTestUser()
  901. userAsJSON := getUserAsJSON(t, user)
  902. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  903. rr := executeRequest(req)
  904. checkResponseCode(t, http.StatusOK, rr.Code)
  905. err := render.DecodeJSON(rr.Body, &user)
  906. if err != nil {
  907. t.Errorf("Error get user: %v", err)
  908. }
  909. user.MaxSessions = 1
  910. user.QuotaFiles = 2
  911. user.QuotaSize = 3
  912. user.GID = 1000
  913. form := make(url.Values)
  914. form.Set("username", user.Username)
  915. form.Set("home_dir", user.HomeDir)
  916. form.Set("uid", "0")
  917. form.Set("gid", strconv.FormatInt(int64(user.GID), 10))
  918. form.Set("max_sessions", strconv.FormatInt(int64(user.MaxSessions), 10))
  919. form.Set("quota_size", strconv.FormatInt(user.QuotaSize, 10))
  920. form.Set("quota_files", strconv.FormatInt(int64(user.QuotaFiles), 10))
  921. form.Set("upload_bandwidth", "0")
  922. form.Set("download_bandwidth", "0")
  923. form.Set("permissions", "*")
  924. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), strings.NewReader(form.Encode()))
  925. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  926. rr = executeRequest(req)
  927. checkResponseCode(t, http.StatusSeeOther, rr.Code)
  928. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=0&order=ASC&username="+user.Username, nil)
  929. rr = executeRequest(req)
  930. checkResponseCode(t, http.StatusOK, rr.Code)
  931. var users []dataprovider.User
  932. err = render.DecodeJSON(rr.Body, &users)
  933. if err != nil {
  934. t.Errorf("Error decoding users: %v", err)
  935. }
  936. if len(users) != 1 {
  937. t.Errorf("1 user is expected")
  938. }
  939. updateUser := users[0]
  940. if user.HomeDir != updateUser.HomeDir {
  941. t.Errorf("home dir does not match")
  942. }
  943. if user.MaxSessions != updateUser.MaxSessions {
  944. t.Errorf("max_sessions does not match")
  945. }
  946. if user.QuotaFiles != updateUser.QuotaFiles {
  947. t.Errorf("quota_files does not match")
  948. }
  949. if user.QuotaSize != updateUser.QuotaSize {
  950. t.Errorf("quota_size does not match")
  951. }
  952. if user.GID != updateUser.GID {
  953. t.Errorf("gid does not match")
  954. }
  955. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  956. rr = executeRequest(req)
  957. checkResponseCode(t, http.StatusOK, rr.Code)
  958. }
  959. func TestProviderClosedMock(t *testing.T) {
  960. if providerDriverName == dataprovider.BoltDataProviderName {
  961. t.Skip("skipping test provider errors for bolt provider")
  962. }
  963. dataProvider := dataprovider.GetProvider()
  964. dataprovider.Close(dataProvider)
  965. req, _ := http.NewRequest(http.MethodGet, webUsersPath, nil)
  966. rr := executeRequest(req)
  967. checkResponseCode(t, http.StatusInternalServerError, rr.Code)
  968. req, _ = http.NewRequest(http.MethodGet, webUserPath+"/0", nil)
  969. rr = executeRequest(req)
  970. checkResponseCode(t, http.StatusInternalServerError, rr.Code)
  971. form := make(url.Values)
  972. form.Set("username", "test")
  973. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/0", strings.NewReader(form.Encode()))
  974. rr = executeRequest(req)
  975. checkResponseCode(t, http.StatusInternalServerError, rr.Code)
  976. config.LoadConfig(configDir, "")
  977. providerConf := config.GetProviderConf()
  978. err := dataprovider.Initialize(providerConf, configDir)
  979. if err != nil {
  980. t.Errorf("error initializing data provider")
  981. }
  982. httpd.SetDataProvider(dataprovider.GetProvider())
  983. sftpd.SetDataProvider(dataprovider.GetProvider())
  984. }
  985. func TestGetWebConnectionsMock(t *testing.T) {
  986. req, _ := http.NewRequest(http.MethodGet, webConnectionsPath, nil)
  987. rr := executeRequest(req)
  988. checkResponseCode(t, http.StatusOK, rr.Code)
  989. }
  990. func TestStaticFilesMock(t *testing.T) {
  991. req, _ := http.NewRequest(http.MethodGet, "/static/favicon.ico", nil)
  992. rr := executeRequest(req)
  993. checkResponseCode(t, http.StatusOK, rr.Code)
  994. }
  995. func waitTCPListening(address string) {
  996. for {
  997. conn, err := net.Dial("tcp", address)
  998. if err != nil {
  999. logger.WarnToConsole("tcp server %v not listening: %v\n", address, err)
  1000. time.Sleep(100 * time.Millisecond)
  1001. continue
  1002. }
  1003. logger.InfoToConsole("tcp server %v now listening\n", address)
  1004. defer conn.Close()
  1005. break
  1006. }
  1007. }
  1008. func getTestUser() dataprovider.User {
  1009. return dataprovider.User{
  1010. Username: defaultUsername,
  1011. Password: defaultPassword,
  1012. HomeDir: filepath.Join(homeBasePath, defaultUsername),
  1013. Permissions: defaultPerms,
  1014. }
  1015. }
  1016. func getUserAsJSON(t *testing.T, user dataprovider.User) []byte {
  1017. json, err := json.Marshal(user)
  1018. if err != nil {
  1019. t.Errorf("error get user as json: %v", err)
  1020. return []byte("{}")
  1021. }
  1022. return json
  1023. }
  1024. func executeRequest(req *http.Request) *httptest.ResponseRecorder {
  1025. rr := httptest.NewRecorder()
  1026. testServer.Config.Handler.ServeHTTP(rr, req)
  1027. return rr
  1028. }
  1029. func checkResponseCode(t *testing.T, expected, actual int) {
  1030. if expected != actual {
  1031. t.Errorf("Expected response code %d. Got %d", expected, actual)
  1032. }
  1033. }