api_test.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670
  1. package api_test
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "net"
  7. "net/http"
  8. "net/http/httptest"
  9. "os"
  10. "path/filepath"
  11. "runtime"
  12. "strconv"
  13. "testing"
  14. "time"
  15. "github.com/go-chi/render"
  16. _ "github.com/go-sql-driver/mysql"
  17. _ "github.com/lib/pq"
  18. _ "github.com/mattn/go-sqlite3"
  19. "github.com/rs/zerolog"
  20. "github.com/drakkan/sftpgo/api"
  21. "github.com/drakkan/sftpgo/config"
  22. "github.com/drakkan/sftpgo/dataprovider"
  23. "github.com/drakkan/sftpgo/logger"
  24. "github.com/drakkan/sftpgo/sftpd"
  25. )
  26. const (
  27. defaultUsername = "test_user"
  28. defaultPassword = "test_password"
  29. testPubKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC03jj0D+djk7pxIf/0OhrxrchJTRZklofJ1NoIu4752Sq02mdXmarMVsqJ1cAjV5LBVy3D1F5U6XW4rppkXeVtd04Pxb09ehtH0pRRPaoHHlALiJt8CoMpbKYMA8b3KXPPriGxgGomvtU2T2RMURSwOZbMtpsugfjYSWenyYX+VORYhylWnSXL961LTyC21ehd6d6QnW9G7E5hYMITMY9TuQZz3bROYzXiTsgN0+g6Hn7exFQp50p45StUMfV/SftCMdCxlxuyGny2CrN/vfjO7xxOo2uv7q1qm10Q46KPWJQv+pgZ/OfL+EDjy07n5QVSKHlbx+2nT4Q0EgOSQaCTYwn3YjtABfIxWwgAFdyj6YlPulCL22qU4MYhDcA6PSBwDdf8hvxBfvsiHdM+JcSHvv8/VeJhk6CmnZxGY0fxBupov27z3yEO8nAg8k+6PaUiW1MSUfuGMF/ktB8LOstXsEPXSszuyXiOv4DaryOXUiSn7bmRqKcEFlJusO6aZP0= nicola@p1"
  30. logSender = "APITesting"
  31. userPath = "/api/v1/user"
  32. activeConnectionsPath = "/api/v1/sftp_connection"
  33. quotaScanPath = "/api/v1/quota_scan"
  34. )
  35. var (
  36. defaultPerms = []string{dataprovider.PermAny}
  37. homeBasePath string
  38. testServer *httptest.Server
  39. )
  40. func TestMain(m *testing.M) {
  41. if runtime.GOOS == "windows" {
  42. homeBasePath = "C:\\"
  43. } else {
  44. homeBasePath = "/tmp"
  45. }
  46. configDir := ".."
  47. logfilePath := filepath.Join(configDir, "sftpgo_api_test.log")
  48. confName := "sftpgo.conf"
  49. logger.InitLogger(logfilePath, zerolog.DebugLevel)
  50. configFilePath := filepath.Join(configDir, confName)
  51. config.LoadConfig(configFilePath)
  52. providerConf := config.GetProviderConf()
  53. err := dataprovider.Initialize(providerConf, configDir)
  54. if err != nil {
  55. logger.Warn(logSender, "error initializing data provider: %v", err)
  56. os.Exit(1)
  57. }
  58. dataProvider := dataprovider.GetProvider()
  59. httpdConf := config.GetHTTPDConfig()
  60. router := api.GetHTTPRouter()
  61. httpdConf.BindPort = 8081
  62. api.SetBaseURL("http://127.0.0.1:8081")
  63. sftpd.SetDataProvider(dataProvider)
  64. api.SetDataProvider(dataProvider)
  65. go func() {
  66. logger.Debug(logSender, "initializing HTTP server with config %+v", httpdConf)
  67. s := &http.Server{
  68. Addr: fmt.Sprintf("%s:%d", httpdConf.BindAddress, httpdConf.BindPort),
  69. Handler: router,
  70. ReadTimeout: 300 * time.Second,
  71. WriteTimeout: 300 * time.Second,
  72. MaxHeaderBytes: 1 << 20, // 1MB
  73. }
  74. if err := s.ListenAndServe(); err != nil {
  75. logger.Error(logSender, "could not start HTTP server: %v", err)
  76. }
  77. }()
  78. testServer = httptest.NewServer(api.GetHTTPRouter())
  79. defer testServer.Close()
  80. waitTCPListening(fmt.Sprintf("%s:%d", httpdConf.BindAddress, httpdConf.BindPort))
  81. exitCode := m.Run()
  82. os.Remove(logfilePath)
  83. os.Exit(exitCode)
  84. }
  85. func waitTCPListening(address string) {
  86. for {
  87. conn, err := net.Dial("tcp", address)
  88. if err != nil {
  89. fmt.Printf("tcp server %v not listening: %v\n", address, err)
  90. continue
  91. }
  92. fmt.Printf("tcp server %v now listening\n", address)
  93. defer conn.Close()
  94. break
  95. }
  96. }
  97. func getTestUser() dataprovider.User {
  98. return dataprovider.User{
  99. Username: defaultUsername,
  100. Password: defaultPassword,
  101. HomeDir: filepath.Join(homeBasePath, defaultUsername),
  102. Permissions: defaultPerms,
  103. }
  104. }
  105. func getUserAsJSON(t *testing.T, user dataprovider.User) []byte {
  106. json, err := json.Marshal(user)
  107. if err != nil {
  108. t.Errorf("error get user as json: %v", err)
  109. return []byte("{}")
  110. }
  111. return json
  112. }
  113. func executeRequest(req *http.Request) *httptest.ResponseRecorder {
  114. rr := httptest.NewRecorder()
  115. testServer.Config.Handler.ServeHTTP(rr, req)
  116. return rr
  117. }
  118. func checkResponseCode(t *testing.T, expected, actual int) {
  119. if expected != actual {
  120. t.Errorf("Expected response code %d. Got %d", expected, actual)
  121. }
  122. }
  123. func TestBasicUserHandling(t *testing.T) {
  124. user, err := api.AddUser(getTestUser(), http.StatusOK)
  125. if err != nil {
  126. t.Errorf("unable to add user: %v", err)
  127. }
  128. user.MaxSessions = 10
  129. user.QuotaSize = 4096
  130. user.QuotaFiles = 2
  131. user.UploadBandwidth = 128
  132. user.DownloadBandwidth = 64
  133. user, err = api.UpdateUser(user, http.StatusOK)
  134. if err != nil {
  135. t.Errorf("unable to update user: %v", err)
  136. }
  137. users, err := api.GetUsers(0, 0, defaultUsername, http.StatusOK)
  138. if err != nil {
  139. t.Errorf("unable to get users: %v", err)
  140. }
  141. if len(users) != 1 {
  142. t.Errorf("number of users mismatch, expected: 1, actual: %v", len(users))
  143. }
  144. err = api.RemoveUser(user, http.StatusOK)
  145. if err != nil {
  146. t.Errorf("unable to remove: %v", err)
  147. }
  148. }
  149. func TestAddUserNoCredentials(t *testing.T) {
  150. u := getTestUser()
  151. u.Password = ""
  152. u.PublicKey = ""
  153. _, err := api.AddUser(u, http.StatusBadRequest)
  154. if err != nil {
  155. t.Errorf("unexpected error adding user with no credentials: %v", err)
  156. }
  157. }
  158. func TestAddUserNoUsername(t *testing.T) {
  159. u := getTestUser()
  160. u.Username = ""
  161. _, err := api.AddUser(u, http.StatusBadRequest)
  162. if err != nil {
  163. t.Errorf("unexpected error adding user with no home dir: %v", err)
  164. }
  165. }
  166. func TestAddUserNoHomeDir(t *testing.T) {
  167. u := getTestUser()
  168. u.HomeDir = ""
  169. _, err := api.AddUser(u, http.StatusBadRequest)
  170. if err != nil {
  171. t.Errorf("unexpected error adding user with no home dir: %v", err)
  172. }
  173. }
  174. func TestAddUserInvalidHomeDir(t *testing.T) {
  175. u := getTestUser()
  176. u.HomeDir = "relative_path"
  177. _, err := api.AddUser(u, http.StatusBadRequest)
  178. if err != nil {
  179. t.Errorf("unexpected error adding user with invalid home dir: %v", err)
  180. }
  181. }
  182. func TestAddUserNoPerms(t *testing.T) {
  183. u := getTestUser()
  184. u.Permissions = []string{}
  185. _, err := api.AddUser(u, http.StatusBadRequest)
  186. if err != nil {
  187. t.Errorf("unexpected error adding user with no perms: %v", err)
  188. }
  189. }
  190. func TestAddUserInvalidPerms(t *testing.T) {
  191. u := getTestUser()
  192. u.Permissions = []string{"invalidPerm"}
  193. _, err := api.AddUser(u, http.StatusBadRequest)
  194. if err != nil {
  195. t.Errorf("unexpected error adding user with no perms: %v", err)
  196. }
  197. }
  198. func TestUpdateUser(t *testing.T) {
  199. user, err := api.AddUser(getTestUser(), http.StatusOK)
  200. if err != nil {
  201. t.Errorf("unable to add user: %v", err)
  202. }
  203. user.HomeDir = filepath.Join(homeBasePath, "testmod")
  204. user.UID = 33
  205. user.GID = 101
  206. user.MaxSessions = 10
  207. user.QuotaSize = 4096
  208. user.QuotaFiles = 2
  209. user.Permissions = []string{dataprovider.PermCreateDirs, dataprovider.PermDelete, dataprovider.PermDownload}
  210. user.UploadBandwidth = 1024
  211. user.DownloadBandwidth = 512
  212. user, err = api.UpdateUser(user, http.StatusOK)
  213. if err != nil {
  214. t.Errorf("unable to update user: %v", err)
  215. }
  216. err = api.RemoveUser(user, http.StatusOK)
  217. if err != nil {
  218. t.Errorf("unable to remove: %v", err)
  219. }
  220. }
  221. func TestUpdateUserNoCredentials(t *testing.T) {
  222. user, err := api.AddUser(getTestUser(), http.StatusOK)
  223. if err != nil {
  224. t.Errorf("unable to add user: %v", err)
  225. }
  226. user.Password = ""
  227. user.PublicKey = ""
  228. // password and public key will be omitted from json serialization if empty and so they will remain unchanged
  229. // and no validation error will be raised
  230. _, err = api.UpdateUser(user, http.StatusOK)
  231. if err != nil {
  232. t.Errorf("unexpected error updating user with no credentials: %v", err)
  233. }
  234. err = api.RemoveUser(user, http.StatusOK)
  235. if err != nil {
  236. t.Errorf("unable to remove: %v", err)
  237. }
  238. }
  239. func TestUpdateUserEmptyHomeDir(t *testing.T) {
  240. user, err := api.AddUser(getTestUser(), http.StatusOK)
  241. if err != nil {
  242. t.Errorf("unable to add user: %v", err)
  243. }
  244. user.HomeDir = ""
  245. _, err = api.UpdateUser(user, http.StatusBadRequest)
  246. if err != nil {
  247. t.Errorf("unexpected error updating user with empty home dir: %v", err)
  248. }
  249. err = api.RemoveUser(user, http.StatusOK)
  250. if err != nil {
  251. t.Errorf("unable to remove: %v", err)
  252. }
  253. }
  254. func TestUpdateUserInvalidHomeDir(t *testing.T) {
  255. user, err := api.AddUser(getTestUser(), http.StatusOK)
  256. if err != nil {
  257. t.Errorf("unable to add user: %v", err)
  258. }
  259. user.HomeDir = "relative_path"
  260. _, err = api.UpdateUser(user, http.StatusBadRequest)
  261. if err != nil {
  262. t.Errorf("unexpected error updating user with empty home dir: %v", err)
  263. }
  264. err = api.RemoveUser(user, http.StatusOK)
  265. if err != nil {
  266. t.Errorf("unable to remove: %v", err)
  267. }
  268. }
  269. func TestUpdateNonExistentUser(t *testing.T) {
  270. _, err := api.UpdateUser(getTestUser(), http.StatusNotFound)
  271. if err != nil {
  272. t.Errorf("unable to update user: %v", err)
  273. }
  274. }
  275. func TestGetNonExistentUser(t *testing.T) {
  276. _, err := api.GetUserByID(0, http.StatusNotFound)
  277. if err != nil {
  278. t.Errorf("unable to get user: %v", err)
  279. }
  280. }
  281. func TestDeleteNonExistentUser(t *testing.T) {
  282. err := api.RemoveUser(getTestUser(), http.StatusNotFound)
  283. if err != nil {
  284. t.Errorf("unable to remove user: %v", err)
  285. }
  286. }
  287. func TestAddDuplicateUser(t *testing.T) {
  288. user, err := api.AddUser(getTestUser(), http.StatusOK)
  289. if err != nil {
  290. t.Errorf("unable to add user: %v", err)
  291. }
  292. _, err = api.AddUser(getTestUser(), http.StatusInternalServerError)
  293. if err != nil {
  294. t.Errorf("unable to add second user: %v", err)
  295. }
  296. err = api.RemoveUser(user, http.StatusOK)
  297. if err != nil {
  298. t.Errorf("unable to remove user: %v", err)
  299. }
  300. }
  301. func TestGetUsers(t *testing.T) {
  302. user1, err := api.AddUser(getTestUser(), http.StatusOK)
  303. if err != nil {
  304. t.Errorf("unable to add user: %v", err)
  305. }
  306. u := getTestUser()
  307. u.Username = defaultUsername + "1"
  308. user2, err := api.AddUser(u, http.StatusOK)
  309. if err != nil {
  310. t.Errorf("unable to add second user: %v", err)
  311. }
  312. users, err := api.GetUsers(0, 0, "", http.StatusOK)
  313. if err != nil {
  314. t.Errorf("unable to get users: %v", err)
  315. }
  316. if len(users) < 2 {
  317. t.Errorf("at least 2 users are expected")
  318. }
  319. users, err = api.GetUsers(1, 0, "", http.StatusOK)
  320. if err != nil {
  321. t.Errorf("unable to get users: %v", err)
  322. }
  323. if len(users) != 1 {
  324. t.Errorf("1 user is expected")
  325. }
  326. users, err = api.GetUsers(1, 1, "", http.StatusOK)
  327. if err != nil {
  328. t.Errorf("unable to get users: %v", err)
  329. }
  330. if len(users) != 1 {
  331. t.Errorf("1 user is expected")
  332. }
  333. err = api.RemoveUser(user1, http.StatusOK)
  334. if err != nil {
  335. t.Errorf("unable to remove user: %v", err)
  336. }
  337. err = api.RemoveUser(user2, http.StatusOK)
  338. if err != nil {
  339. t.Errorf("unable to remove user: %v", err)
  340. }
  341. }
  342. func TestGetQuotaScans(t *testing.T) {
  343. _, err := api.GetQuotaScans(http.StatusOK)
  344. if err != nil {
  345. t.Errorf("unable to get quota scans: %v", err)
  346. }
  347. }
  348. func TestStartQuotaScan(t *testing.T) {
  349. user, err := api.AddUser(getTestUser(), http.StatusOK)
  350. if err != nil {
  351. t.Errorf("unable to add user: %v", err)
  352. }
  353. err = api.StartQuotaScan(user, http.StatusCreated)
  354. if err != nil {
  355. t.Errorf("unable to start quota scan: %v", err)
  356. }
  357. err = api.RemoveUser(user, http.StatusOK)
  358. if err != nil {
  359. t.Errorf("unable to remove user: %v", err)
  360. }
  361. }
  362. // test using mock http server
  363. func TestBasicUserHandlingMock(t *testing.T) {
  364. user := getTestUser()
  365. userAsJSON := getUserAsJSON(t, user)
  366. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  367. rr := executeRequest(req)
  368. checkResponseCode(t, http.StatusOK, rr.Code)
  369. err := render.DecodeJSON(rr.Body, &user)
  370. if err != nil {
  371. t.Errorf("Error get user: %v", err)
  372. }
  373. req, _ = http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  374. rr = executeRequest(req)
  375. checkResponseCode(t, http.StatusInternalServerError, rr.Code)
  376. user.MaxSessions = 10
  377. user.UploadBandwidth = 128
  378. userAsJSON = getUserAsJSON(t, user)
  379. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer(userAsJSON))
  380. rr = executeRequest(req)
  381. checkResponseCode(t, http.StatusOK, rr.Code)
  382. req, _ = http.NewRequest(http.MethodGet, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  383. rr = executeRequest(req)
  384. checkResponseCode(t, http.StatusOK, rr.Code)
  385. var updatedUser dataprovider.User
  386. err = render.DecodeJSON(rr.Body, &updatedUser)
  387. if err != nil {
  388. t.Errorf("Error decoding updated user: %v", err)
  389. }
  390. if user.MaxSessions != updatedUser.MaxSessions || user.UploadBandwidth != updatedUser.UploadBandwidth {
  391. t.Errorf("Error modifying user actual: %v, %v", updatedUser.MaxSessions, updatedUser.UploadBandwidth)
  392. }
  393. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  394. rr = executeRequest(req)
  395. checkResponseCode(t, http.StatusOK, rr.Code)
  396. }
  397. func TestGetUserByIdInvalidParamsMock(t *testing.T) {
  398. req, _ := http.NewRequest(http.MethodGet, userPath+"/0", nil)
  399. rr := executeRequest(req)
  400. checkResponseCode(t, http.StatusNotFound, rr.Code)
  401. req, _ = http.NewRequest(http.MethodGet, userPath+"/a", nil)
  402. rr = executeRequest(req)
  403. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  404. }
  405. func TestAddUserNoUsernameMock(t *testing.T) {
  406. user := getTestUser()
  407. user.Username = ""
  408. userAsJSON := getUserAsJSON(t, user)
  409. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  410. rr := executeRequest(req)
  411. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  412. }
  413. func TestAddUserInvalidHomeDirMock(t *testing.T) {
  414. user := getTestUser()
  415. user.HomeDir = "relative_path"
  416. userAsJSON := getUserAsJSON(t, user)
  417. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  418. rr := executeRequest(req)
  419. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  420. }
  421. func TestAddUserInvalidPermsMock(t *testing.T) {
  422. user := getTestUser()
  423. user.Permissions = []string{}
  424. userAsJSON := getUserAsJSON(t, user)
  425. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  426. rr := executeRequest(req)
  427. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  428. }
  429. func TestAddUserInvalidJsonMock(t *testing.T) {
  430. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer([]byte("invalid json")))
  431. rr := executeRequest(req)
  432. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  433. }
  434. func TestUpdateUserInvalidJsonMock(t *testing.T) {
  435. user := getTestUser()
  436. userAsJSON := getUserAsJSON(t, user)
  437. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  438. rr := executeRequest(req)
  439. checkResponseCode(t, http.StatusOK, rr.Code)
  440. err := render.DecodeJSON(rr.Body, &user)
  441. if err != nil {
  442. t.Errorf("Error get user: %v", err)
  443. }
  444. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer([]byte("Invalid json")))
  445. rr = executeRequest(req)
  446. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  447. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  448. rr = executeRequest(req)
  449. checkResponseCode(t, http.StatusOK, rr.Code)
  450. }
  451. func TestUpdateUserInvalidParamsMock(t *testing.T) {
  452. user := getTestUser()
  453. userAsJSON := getUserAsJSON(t, user)
  454. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  455. rr := executeRequest(req)
  456. checkResponseCode(t, http.StatusOK, rr.Code)
  457. err := render.DecodeJSON(rr.Body, &user)
  458. if err != nil {
  459. t.Errorf("Error get user: %v", err)
  460. }
  461. user.HomeDir = ""
  462. userAsJSON = getUserAsJSON(t, user)
  463. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer(userAsJSON))
  464. rr = executeRequest(req)
  465. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  466. userID := user.ID
  467. user.ID = 0
  468. userAsJSON = getUserAsJSON(t, user)
  469. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(userID, 10), bytes.NewBuffer(userAsJSON))
  470. rr = executeRequest(req)
  471. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  472. user.ID = userID
  473. req, _ = http.NewRequest(http.MethodPut, userPath+"/0", bytes.NewBuffer(userAsJSON))
  474. rr = executeRequest(req)
  475. checkResponseCode(t, http.StatusNotFound, rr.Code)
  476. req, _ = http.NewRequest(http.MethodPut, userPath+"/a", bytes.NewBuffer(userAsJSON))
  477. rr = executeRequest(req)
  478. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  479. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  480. rr = executeRequest(req)
  481. checkResponseCode(t, http.StatusOK, rr.Code)
  482. }
  483. func TestGetUsersMock(t *testing.T) {
  484. user := getTestUser()
  485. userAsJSON := getUserAsJSON(t, user)
  486. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  487. rr := executeRequest(req)
  488. checkResponseCode(t, http.StatusOK, rr.Code)
  489. err := render.DecodeJSON(rr.Body, &user)
  490. if err != nil {
  491. t.Errorf("Error get user: %v", err)
  492. }
  493. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=510&offset=0&order=ASC&username="+defaultUsername, nil)
  494. rr = executeRequest(req)
  495. checkResponseCode(t, http.StatusOK, rr.Code)
  496. var users []dataprovider.User
  497. err = render.DecodeJSON(rr.Body, &users)
  498. if err != nil {
  499. t.Errorf("Error decoding users: %v", err)
  500. }
  501. if len(users) != 1 {
  502. t.Errorf("1 user is expected")
  503. }
  504. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=a&offset=0&order=ASC", nil)
  505. rr = executeRequest(req)
  506. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  507. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=a&order=ASC", nil)
  508. rr = executeRequest(req)
  509. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  510. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=0&order=ASCa", nil)
  511. rr = executeRequest(req)
  512. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  513. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  514. rr = executeRequest(req)
  515. checkResponseCode(t, http.StatusOK, rr.Code)
  516. }
  517. func TestDeleteUserInvalidParamsMock(t *testing.T) {
  518. req, _ := http.NewRequest(http.MethodDelete, userPath+"/0", nil)
  519. rr := executeRequest(req)
  520. checkResponseCode(t, http.StatusNotFound, rr.Code)
  521. req, _ = http.NewRequest(http.MethodDelete, userPath+"/a", nil)
  522. rr = executeRequest(req)
  523. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  524. }
  525. func TestGetQuotaScansMock(t *testing.T) {
  526. req, err := http.NewRequest("GET", quotaScanPath, nil)
  527. if err != nil {
  528. t.Errorf("error get quota scan: %v", err)
  529. }
  530. rr := executeRequest(req)
  531. checkResponseCode(t, http.StatusOK, rr.Code)
  532. }
  533. func TestStartQuotaScanMock(t *testing.T) {
  534. user := getTestUser()
  535. userAsJSON := getUserAsJSON(t, user)
  536. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  537. rr := executeRequest(req)
  538. checkResponseCode(t, http.StatusOK, rr.Code)
  539. err := render.DecodeJSON(rr.Body, &user)
  540. if err != nil {
  541. t.Errorf("Error get user: %v", err)
  542. }
  543. _, err = os.Stat(user.HomeDir)
  544. if err == nil {
  545. os.Remove(user.HomeDir)
  546. }
  547. userAsJSON = getUserAsJSON(t, user)
  548. req, _ = http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer(userAsJSON))
  549. rr = executeRequest(req)
  550. checkResponseCode(t, http.StatusCreated, rr.Code)
  551. req, _ = http.NewRequest(http.MethodGet, quotaScanPath, nil)
  552. rr = executeRequest(req)
  553. checkResponseCode(t, http.StatusOK, rr.Code)
  554. var scans []sftpd.ActiveQuotaScan
  555. err = render.DecodeJSON(rr.Body, &scans)
  556. if err != nil {
  557. t.Errorf("Error get active scans: %v", err)
  558. }
  559. for len(scans) > 0 {
  560. req, _ = http.NewRequest(http.MethodGet, quotaScanPath, nil)
  561. rr = executeRequest(req)
  562. checkResponseCode(t, http.StatusOK, rr.Code)
  563. err = render.DecodeJSON(rr.Body, &scans)
  564. if err != nil {
  565. t.Errorf("Error get active scans: %v", err)
  566. break
  567. }
  568. }
  569. _, err = os.Stat(user.HomeDir)
  570. if err != nil && os.IsNotExist(err) {
  571. os.MkdirAll(user.HomeDir, 0777)
  572. }
  573. req, _ = http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer(userAsJSON))
  574. rr = executeRequest(req)
  575. checkResponseCode(t, http.StatusCreated, rr.Code)
  576. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  577. rr = executeRequest(req)
  578. checkResponseCode(t, http.StatusOK, rr.Code)
  579. }
  580. func TestStartQuotaScanBadUserMock(t *testing.T) {
  581. user := getTestUser()
  582. userAsJSON := getUserAsJSON(t, user)
  583. req, _ := http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer(userAsJSON))
  584. rr := executeRequest(req)
  585. checkResponseCode(t, http.StatusNotFound, rr.Code)
  586. }
  587. func TestStartQuotaScanNonExistentUserMock(t *testing.T) {
  588. req, _ := http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer([]byte("invalid json")))
  589. rr := executeRequest(req)
  590. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  591. }
  592. func TestGetSFTPConnectionsMock(t *testing.T) {
  593. req, _ := http.NewRequest(http.MethodGet, activeConnectionsPath, nil)
  594. rr := executeRequest(req)
  595. checkResponseCode(t, http.StatusOK, rr.Code)
  596. }
  597. func TestDeleteActiveConnectionMock(t *testing.T) {
  598. req, _ := http.NewRequest(http.MethodDelete, activeConnectionsPath+"/connectionID", nil)
  599. rr := executeRequest(req)
  600. checkResponseCode(t, http.StatusNotFound, rr.Code)
  601. }
  602. func TestNotFoundMock(t *testing.T) {
  603. req, _ := http.NewRequest(http.MethodGet, "/non/existing/path", nil)
  604. rr := executeRequest(req)
  605. checkResponseCode(t, http.StatusNotFound, rr.Code)
  606. }
  607. func TestMethodNotAllowedMock(t *testing.T) {
  608. req, _ := http.NewRequest(http.MethodPost, activeConnectionsPath, nil)
  609. rr := executeRequest(req)
  610. checkResponseCode(t, http.StatusMethodNotAllowed, rr.Code)
  611. }