api_test.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. package api_test
  2. import (
  3. "net/http"
  4. "path/filepath"
  5. "runtime"
  6. "testing"
  7. "github.com/drakkan/sftpgo/api"
  8. "github.com/drakkan/sftpgo/dataprovider"
  9. )
  10. // To run test cases you need to manually start sftpgo using port 2022 for sftp and 8080 for http API
  11. const (
  12. defaultUsername = "test_user"
  13. defaultPassword = "test_password"
  14. testPubKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC03jj0D+djk7pxIf/0OhrxrchJTRZklofJ1NoIu4752Sq02mdXmarMVsqJ1cAjV5LBVy3D1F5U6XW4rppkXeVtd04Pxb09ehtH0pRRPaoHHlALiJt8CoMpbKYMA8b3KXPPriGxgGomvtU2T2RMURSwOZbMtpsugfjYSWenyYX+VORYhylWnSXL961LTyC21ehd6d6QnW9G7E5hYMITMY9TuQZz3bROYzXiTsgN0+g6Hn7exFQp50p45StUMfV/SftCMdCxlxuyGny2CrN/vfjO7xxOo2uv7q1qm10Q46KPWJQv+pgZ/OfL+EDjy07n5QVSKHlbx+2nT4Q0EgOSQaCTYwn3YjtABfIxWwgAFdyj6YlPulCL22qU4MYhDcA6PSBwDdf8hvxBfvsiHdM+JcSHvv8/VeJhk6CmnZxGY0fxBupov27z3yEO8nAg8k+6PaUiW1MSUfuGMF/ktB8LOstXsEPXSszuyXiOv4DaryOXUiSn7bmRqKcEFlJusO6aZP0= nicola@p1"
  15. )
  16. var (
  17. defaultPerms = []string{dataprovider.PermAny}
  18. homeBasePath string
  19. )
  20. func init() {
  21. if runtime.GOOS == "windows" {
  22. homeBasePath = "C:\\"
  23. } else {
  24. homeBasePath = "/tmp"
  25. }
  26. }
  27. func getTestUser() dataprovider.User {
  28. return dataprovider.User{
  29. Username: defaultUsername,
  30. Password: defaultPassword,
  31. HomeDir: filepath.Join(homeBasePath, defaultUsername),
  32. Permissions: defaultPerms,
  33. }
  34. }
  35. func TestBasicUserHandling(t *testing.T) {
  36. user, err := api.AddUser(getTestUser(), http.StatusOK)
  37. if err != nil {
  38. t.Errorf("unable to add user: %v", err)
  39. }
  40. user.MaxSessions = 10
  41. user.QuotaSize = 4096
  42. user.QuotaFiles = 2
  43. user.UploadBandwidth = 128
  44. user.DownloadBandwidth = 64
  45. user, err = api.UpdateUser(user, http.StatusOK)
  46. if err != nil {
  47. t.Errorf("unable to update user: %v", err)
  48. }
  49. users, err := api.GetUsers(0, 0, defaultUsername, http.StatusOK)
  50. if err != nil {
  51. t.Errorf("unable to get users: %v", err)
  52. }
  53. if len(users) != 1 {
  54. t.Errorf("number of users mismatch, expected: 1, actual: %v", len(users))
  55. }
  56. err = api.RemoveUser(user, http.StatusOK)
  57. if err != nil {
  58. t.Errorf("unable to remove: %v", err)
  59. }
  60. }
  61. func TestAddUserNoCredentials(t *testing.T) {
  62. u := getTestUser()
  63. u.Password = ""
  64. u.PublicKey = ""
  65. _, err := api.AddUser(u, http.StatusBadRequest)
  66. if err != nil {
  67. t.Errorf("unexpected error adding user with no credentials: %v", err)
  68. }
  69. }
  70. func TestAddUserNoUsername(t *testing.T) {
  71. u := getTestUser()
  72. u.Username = ""
  73. _, err := api.AddUser(u, http.StatusBadRequest)
  74. if err != nil {
  75. t.Errorf("unexpected error adding user with no home dir: %v", err)
  76. }
  77. }
  78. func TestAddUserNoHomeDir(t *testing.T) {
  79. u := getTestUser()
  80. u.HomeDir = ""
  81. _, err := api.AddUser(u, http.StatusBadRequest)
  82. if err != nil {
  83. t.Errorf("unexpected error adding user with no home dir: %v", err)
  84. }
  85. }
  86. func TestAddUserInvalidHomeDir(t *testing.T) {
  87. u := getTestUser()
  88. u.HomeDir = "relative_path"
  89. _, err := api.AddUser(u, http.StatusBadRequest)
  90. if err != nil {
  91. t.Errorf("unexpected error adding user with invalid home dir: %v", err)
  92. }
  93. }
  94. func TestAddUserNoPerms(t *testing.T) {
  95. u := getTestUser()
  96. u.Permissions = []string{}
  97. _, err := api.AddUser(u, http.StatusBadRequest)
  98. if err != nil {
  99. t.Errorf("unexpected error adding user with no perms: %v", err)
  100. }
  101. }
  102. func TestAddUserInvalidPerms(t *testing.T) {
  103. u := getTestUser()
  104. u.Permissions = []string{"invalidPerm"}
  105. _, err := api.AddUser(u, http.StatusBadRequest)
  106. if err != nil {
  107. t.Errorf("unexpected error adding user with no perms: %v", err)
  108. }
  109. }
  110. func TestUpdateUser(t *testing.T) {
  111. user, err := api.AddUser(getTestUser(), http.StatusOK)
  112. if err != nil {
  113. t.Errorf("unable to add user: %v", err)
  114. }
  115. user.HomeDir = filepath.Join(homeBasePath, "testmod")
  116. user.UID = 33
  117. user.GID = 101
  118. user.MaxSessions = 10
  119. user.QuotaSize = 4096
  120. user.QuotaFiles = 2
  121. user.Permissions = []string{dataprovider.PermCreateDirs, dataprovider.PermDelete, dataprovider.PermDownload}
  122. user.UploadBandwidth = 1024
  123. user.DownloadBandwidth = 512
  124. user, err = api.UpdateUser(user, http.StatusOK)
  125. if err != nil {
  126. t.Errorf("unable to update user: %v", err)
  127. }
  128. err = api.RemoveUser(user, http.StatusOK)
  129. if err != nil {
  130. t.Errorf("unable to remove: %v", err)
  131. }
  132. }
  133. func TestUpdateUserNoCredentials(t *testing.T) {
  134. user, err := api.AddUser(getTestUser(), http.StatusOK)
  135. if err != nil {
  136. t.Errorf("unable to add user: %v", err)
  137. }
  138. user.Password = ""
  139. user.PublicKey = ""
  140. // password and public key will be omitted from json serialization if empty and so they will remain unchanged
  141. // and no validation error will be raised
  142. _, err = api.UpdateUser(user, http.StatusOK)
  143. if err != nil {
  144. t.Errorf("unexpected error updating user with no credentials: %v", err)
  145. }
  146. err = api.RemoveUser(user, http.StatusOK)
  147. if err != nil {
  148. t.Errorf("unable to remove: %v", err)
  149. }
  150. }
  151. func TestUpdateUserEmptyHomeDir(t *testing.T) {
  152. user, err := api.AddUser(getTestUser(), http.StatusOK)
  153. if err != nil {
  154. t.Errorf("unable to add user: %v", err)
  155. }
  156. user.HomeDir = ""
  157. _, err = api.UpdateUser(user, http.StatusBadRequest)
  158. if err != nil {
  159. t.Errorf("unexpected error updating user with empty home dir: %v", err)
  160. }
  161. err = api.RemoveUser(user, http.StatusOK)
  162. if err != nil {
  163. t.Errorf("unable to remove: %v", err)
  164. }
  165. }
  166. func TestUpdateUserInvalidHomeDir(t *testing.T) {
  167. user, err := api.AddUser(getTestUser(), http.StatusOK)
  168. if err != nil {
  169. t.Errorf("unable to add user: %v", err)
  170. }
  171. user.HomeDir = "relative_path"
  172. _, err = api.UpdateUser(user, http.StatusBadRequest)
  173. if err != nil {
  174. t.Errorf("unexpected error updating user with empty home dir: %v", err)
  175. }
  176. err = api.RemoveUser(user, http.StatusOK)
  177. if err != nil {
  178. t.Errorf("unable to remove: %v", err)
  179. }
  180. }
  181. func TestUpdateNonExistentUser(t *testing.T) {
  182. _, err := api.UpdateUser(getTestUser(), http.StatusNotFound)
  183. if err != nil {
  184. t.Errorf("unable to update user: %v", err)
  185. }
  186. }
  187. func TestGetNonExistentUser(t *testing.T) {
  188. _, err := api.GetUserByID(0, http.StatusNotFound)
  189. if err != nil {
  190. t.Errorf("unable to get user: %v", err)
  191. }
  192. }
  193. func TestDeleteNonExistentUser(t *testing.T) {
  194. err := api.RemoveUser(getTestUser(), http.StatusNotFound)
  195. if err != nil {
  196. t.Errorf("unable to remove user: %v", err)
  197. }
  198. }
  199. func TestAddDuplicateUser(t *testing.T) {
  200. user, err := api.AddUser(getTestUser(), http.StatusOK)
  201. if err != nil {
  202. t.Errorf("unable to add user: %v", err)
  203. }
  204. _, err = api.AddUser(getTestUser(), http.StatusInternalServerError)
  205. if err != nil {
  206. t.Errorf("unable to add second user: %v", err)
  207. }
  208. err = api.RemoveUser(user, http.StatusOK)
  209. if err != nil {
  210. t.Errorf("unable to remove user: %v", err)
  211. }
  212. }
  213. func TestGetUsers(t *testing.T) {
  214. user1, err := api.AddUser(getTestUser(), http.StatusOK)
  215. if err != nil {
  216. t.Errorf("unable to add user: %v", err)
  217. }
  218. u := getTestUser()
  219. u.Username = defaultUsername + "1"
  220. user2, err := api.AddUser(u, http.StatusOK)
  221. if err != nil {
  222. t.Errorf("unable to add second user: %v", err)
  223. }
  224. users, err := api.GetUsers(0, 0, "", http.StatusOK)
  225. if err != nil {
  226. t.Errorf("unable to get users: %v", err)
  227. }
  228. if len(users) < 2 {
  229. t.Errorf("at least 2 users are expected")
  230. }
  231. users, err = api.GetUsers(1, 0, "", http.StatusOK)
  232. if err != nil {
  233. t.Errorf("unable to get users: %v", err)
  234. }
  235. if len(users) != 1 {
  236. t.Errorf("1 user are expected")
  237. }
  238. users, err = api.GetUsers(1, 1, "", http.StatusOK)
  239. if err != nil {
  240. t.Errorf("unable to get users: %v", err)
  241. }
  242. if len(users) != 1 {
  243. t.Errorf("1 user are expected")
  244. }
  245. err = api.RemoveUser(user1, http.StatusOK)
  246. if err != nil {
  247. t.Errorf("unable to remove user: %v", err)
  248. }
  249. err = api.RemoveUser(user2, http.StatusOK)
  250. if err != nil {
  251. t.Errorf("unable to remove user: %v", err)
  252. }
  253. }
  254. func TestGetQuotaScans(t *testing.T) {
  255. _, err := api.GetQuotaScans(http.StatusOK)
  256. if err != nil {
  257. t.Errorf("unable to get quota scans: %v", err)
  258. }
  259. }
  260. func TestStartQuotaScan(t *testing.T) {
  261. user, err := api.AddUser(getTestUser(), http.StatusOK)
  262. if err != nil {
  263. t.Errorf("unable to add user: %v", err)
  264. }
  265. err = api.StartQuotaScan(user, http.StatusCreated)
  266. if err != nil {
  267. t.Errorf("unable to start quota scan: %v", err)
  268. }
  269. err = api.RemoveUser(user, http.StatusOK)
  270. if err != nil {
  271. t.Errorf("unable to remove user: %v", err)
  272. }
  273. }