httpd_test.go 74 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103
  1. package httpd_test
  2. import (
  3. "bytes"
  4. "crypto/rand"
  5. "encoding/base64"
  6. "encoding/json"
  7. "fmt"
  8. "io"
  9. "io/ioutil"
  10. "mime/multipart"
  11. "net"
  12. "net/http"
  13. "net/http/httptest"
  14. "net/url"
  15. "os"
  16. "path/filepath"
  17. "runtime"
  18. "strconv"
  19. "strings"
  20. "testing"
  21. "time"
  22. "github.com/go-chi/render"
  23. _ "github.com/go-sql-driver/mysql"
  24. _ "github.com/lib/pq"
  25. _ "github.com/mattn/go-sqlite3"
  26. "github.com/rs/zerolog"
  27. "github.com/drakkan/sftpgo/config"
  28. "github.com/drakkan/sftpgo/dataprovider"
  29. "github.com/drakkan/sftpgo/httpd"
  30. "github.com/drakkan/sftpgo/logger"
  31. "github.com/drakkan/sftpgo/sftpd"
  32. "github.com/drakkan/sftpgo/utils"
  33. )
  34. const (
  35. defaultUsername = "test_user"
  36. defaultPassword = "test_password"
  37. testPubKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC03jj0D+djk7pxIf/0OhrxrchJTRZklofJ1NoIu4752Sq02mdXmarMVsqJ1cAjV5LBVy3D1F5U6XW4rppkXeVtd04Pxb09ehtH0pRRPaoHHlALiJt8CoMpbKYMA8b3KXPPriGxgGomvtU2T2RMURSwOZbMtpsugfjYSWenyYX+VORYhylWnSXL961LTyC21ehd6d6QnW9G7E5hYMITMY9TuQZz3bROYzXiTsgN0+g6Hn7exFQp50p45StUMfV/SftCMdCxlxuyGny2CrN/vfjO7xxOo2uv7q1qm10Q46KPWJQv+pgZ/OfL+EDjy07n5QVSKHlbx+2nT4Q0EgOSQaCTYwn3YjtABfIxWwgAFdyj6YlPulCL22qU4MYhDcA6PSBwDdf8hvxBfvsiHdM+JcSHvv8/VeJhk6CmnZxGY0fxBupov27z3yEO8nAg8k+6PaUiW1MSUfuGMF/ktB8LOstXsEPXSszuyXiOv4DaryOXUiSn7bmRqKcEFlJusO6aZP0= nicola@p1"
  38. logSender = "APITesting"
  39. userPath = "/api/v1/user"
  40. activeConnectionsPath = "/api/v1/connection"
  41. quotaScanPath = "/api/v1/quota_scan"
  42. versionPath = "/api/v1/version"
  43. providerStatusPath = "/api/v1/providerstatus"
  44. dumpDataPath = "/api/v1/dumpdata"
  45. loadDataPath = "/api/v1/loaddata"
  46. metricsPath = "/metrics"
  47. webBasePath = "/web"
  48. webUsersPath = "/web/users"
  49. webUserPath = "/web/user"
  50. webConnectionsPath = "/web/connections"
  51. configDir = ".."
  52. httpsCert = `-----BEGIN CERTIFICATE-----
  53. MIICHTCCAaKgAwIBAgIUHnqw7QnB1Bj9oUsNpdb+ZkFPOxMwCgYIKoZIzj0EAwIw
  54. RTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGElu
  55. dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDAyMDQwOTUzMDRaFw0zMDAyMDEw
  56. OTUzMDRaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYD
  57. VQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwdjAQBgcqhkjOPQIBBgUrgQQA
  58. IgNiAARCjRMqJ85rzMC998X5z761nJ+xL3bkmGVqWvrJ51t5OxV0v25NsOgR82CA
  59. NXUgvhVYs7vNFN+jxtb2aj6Xg+/2G/BNxkaFspIVCzgWkxiz7XE4lgUwX44FCXZM
  60. 3+JeUbKjUzBRMB0GA1UdDgQWBBRhLw+/o3+Z02MI/d4tmaMui9W16jAfBgNVHSME
  61. GDAWgBRhLw+/o3+Z02MI/d4tmaMui9W16jAPBgNVHRMBAf8EBTADAQH/MAoGCCqG
  62. SM49BAMCA2kAMGYCMQDqLt2lm8mE+tGgtjDmtFgdOcI72HSbRQ74D5rYTzgST1rY
  63. /8wTi5xl8TiFUyLMUsICMQC5ViVxdXbhuG7gX6yEqSkMKZICHpO8hqFwOD/uaFVI
  64. dV4vKmHUzwK/eIx+8Ay3neE=
  65. -----END CERTIFICATE-----`
  66. httpsKey = `-----BEGIN EC PARAMETERS-----
  67. BgUrgQQAIg==
  68. -----END EC PARAMETERS-----
  69. -----BEGIN EC PRIVATE KEY-----
  70. MIGkAgEBBDCfMNsN6miEE3rVyUPwElfiJSWaR5huPCzUenZOfJT04GAcQdWvEju3
  71. UM2lmBLIXpGgBwYFK4EEACKhZANiAARCjRMqJ85rzMC998X5z761nJ+xL3bkmGVq
  72. WvrJ51t5OxV0v25NsOgR82CANXUgvhVYs7vNFN+jxtb2aj6Xg+/2G/BNxkaFspIV
  73. CzgWkxiz7XE4lgUwX44FCXZM3+JeUbI=
  74. -----END EC PRIVATE KEY-----`
  75. )
  76. var (
  77. defaultPerms = []string{dataprovider.PermAny}
  78. homeBasePath string
  79. backupsPath string
  80. credentialsPath string
  81. testServer *httptest.Server
  82. providerDriverName string
  83. )
  84. func TestMain(m *testing.M) {
  85. homeBasePath = os.TempDir()
  86. logfilePath := filepath.Join(configDir, "sftpgo_api_test.log")
  87. logger.InitLogger(logfilePath, 5, 1, 28, false, zerolog.DebugLevel)
  88. config.LoadConfig(configDir, "")
  89. providerConf := config.GetProviderConf()
  90. credentialsPath = filepath.Join(os.TempDir(), "test_credentials")
  91. providerConf.CredentialsPath = credentialsPath
  92. providerDriverName = providerConf.Driver
  93. os.RemoveAll(credentialsPath)
  94. err := dataprovider.Initialize(providerConf, configDir)
  95. if err != nil {
  96. logger.Warn(logSender, "", "error initializing data provider: %v", err)
  97. os.Exit(1)
  98. }
  99. dataProvider := dataprovider.GetProvider()
  100. httpdConf := config.GetHTTPDConfig()
  101. httpdConf.BindPort = 8081
  102. httpd.SetBaseURLAndCredentials("http://127.0.0.1:8081", "", "")
  103. backupsPath = filepath.Join(os.TempDir(), "test_backups")
  104. httpdConf.BackupsPath = backupsPath
  105. os.MkdirAll(backupsPath, 0777)
  106. sftpd.SetDataProvider(dataProvider)
  107. httpd.SetDataProvider(dataProvider)
  108. go func() {
  109. if err := httpdConf.Initialize(configDir); err != nil {
  110. logger.Error(logSender, "", "could not start HTTP server: %v", err)
  111. }
  112. }()
  113. waitTCPListening(fmt.Sprintf("%s:%d", httpdConf.BindAddress, httpdConf.BindPort))
  114. // now start an https server
  115. certPath := filepath.Join(os.TempDir(), "test.crt")
  116. keyPath := filepath.Join(os.TempDir(), "test.key")
  117. ioutil.WriteFile(certPath, []byte(httpsCert), 0666)
  118. ioutil.WriteFile(keyPath, []byte(httpsKey), 0666)
  119. httpdConf.BindPort = 8443
  120. httpdConf.CertificateFile = certPath
  121. httpdConf.CertificateKeyFile = keyPath
  122. go func() {
  123. if err := httpdConf.Initialize(configDir); err != nil {
  124. logger.Error(logSender, "", "could not start HTTPS server: %v", err)
  125. }
  126. }()
  127. waitTCPListening(fmt.Sprintf("%s:%d", httpdConf.BindAddress, httpdConf.BindPort))
  128. httpd.ReloadTLSCertificate()
  129. testServer = httptest.NewServer(httpd.GetHTTPRouter())
  130. defer testServer.Close()
  131. exitCode := m.Run()
  132. os.Remove(logfilePath)
  133. os.RemoveAll(backupsPath)
  134. os.RemoveAll(credentialsPath)
  135. os.Remove(certPath)
  136. os.Remove(keyPath)
  137. os.Exit(exitCode)
  138. }
  139. func TestInitialization(t *testing.T) {
  140. config.LoadConfig(configDir, "")
  141. httpdConf := config.GetHTTPDConfig()
  142. httpdConf.BackupsPath = "test_backups"
  143. httpdConf.AuthUserFile = "invalid file"
  144. err := httpdConf.Initialize(configDir)
  145. if err == nil {
  146. t.Error("Inizialize must fail")
  147. }
  148. httpdConf.BackupsPath = backupsPath
  149. httpdConf.AuthUserFile = ""
  150. httpdConf.CertificateFile = "invalid file"
  151. httpdConf.CertificateKeyFile = "invalid file"
  152. err = httpdConf.Initialize(configDir)
  153. if err == nil {
  154. t.Error("Inizialize must fail")
  155. }
  156. }
  157. func TestBasicUserHandling(t *testing.T) {
  158. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  159. if err != nil {
  160. t.Errorf("unable to add user: %v", err)
  161. }
  162. user.MaxSessions = 10
  163. user.QuotaSize = 4096
  164. user.QuotaFiles = 2
  165. user.UploadBandwidth = 128
  166. user.DownloadBandwidth = 64
  167. user.ExpirationDate = utils.GetTimeAsMsSinceEpoch(time.Now())
  168. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  169. if err != nil {
  170. t.Errorf("unable to update user: %v", err)
  171. }
  172. users, _, err := httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  173. if err != nil {
  174. t.Errorf("unable to get users: %v", err)
  175. }
  176. if len(users) != 1 {
  177. t.Errorf("number of users mismatch, expected: 1, actual: %v", len(users))
  178. }
  179. _, err = httpd.RemoveUser(user, http.StatusOK)
  180. if err != nil {
  181. t.Errorf("unable to remove: %v", err)
  182. }
  183. }
  184. func TestUserStatus(t *testing.T) {
  185. u := getTestUser()
  186. u.Status = 3
  187. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  188. if err != nil {
  189. t.Errorf("unexpected error adding user with bad status: %v", err)
  190. }
  191. u.Status = 0
  192. user, _, err := httpd.AddUser(u, http.StatusOK)
  193. if err != nil {
  194. t.Errorf("unable to add user: %v", err)
  195. }
  196. user.Status = 2
  197. _, _, err = httpd.UpdateUser(user, http.StatusBadRequest)
  198. if err != nil {
  199. t.Errorf("unexpected error updating user with bad status: %v", err)
  200. }
  201. user.Status = 1
  202. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  203. if err != nil {
  204. t.Errorf("unable to update user: %v", err)
  205. }
  206. _, err = httpd.RemoveUser(user, http.StatusOK)
  207. if err != nil {
  208. t.Errorf("unable to remove: %v", err)
  209. }
  210. }
  211. func TestAddUserNoCredentials(t *testing.T) {
  212. u := getTestUser()
  213. u.Password = ""
  214. u.PublicKeys = []string{}
  215. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  216. if err != nil {
  217. t.Errorf("unexpected error adding user with no credentials: %v", err)
  218. }
  219. }
  220. func TestAddUserNoUsername(t *testing.T) {
  221. u := getTestUser()
  222. u.Username = ""
  223. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  224. if err != nil {
  225. t.Errorf("unexpected error adding user with no home dir: %v", err)
  226. }
  227. }
  228. func TestAddUserNoHomeDir(t *testing.T) {
  229. u := getTestUser()
  230. u.HomeDir = ""
  231. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  232. if err != nil {
  233. t.Errorf("unexpected error adding user with no home dir: %v", err)
  234. }
  235. }
  236. func TestAddUserInvalidHomeDir(t *testing.T) {
  237. u := getTestUser()
  238. u.HomeDir = "relative_path"
  239. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  240. if err != nil {
  241. t.Errorf("unexpected error adding user with invalid home dir: %v", err)
  242. }
  243. }
  244. func TestAddUserNoPerms(t *testing.T) {
  245. u := getTestUser()
  246. u.Permissions = make(map[string][]string)
  247. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  248. if err != nil {
  249. t.Errorf("unexpected error adding user with no perms: %v", err)
  250. }
  251. u.Permissions["/"] = []string{}
  252. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  253. if err != nil {
  254. t.Errorf("unexpected error adding user with no perms: %v", err)
  255. }
  256. }
  257. func TestAddUserInvalidPerms(t *testing.T) {
  258. u := getTestUser()
  259. u.Permissions["/"] = []string{"invalidPerm"}
  260. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  261. if err != nil {
  262. t.Errorf("unexpected error adding user with invalid perms: %v", err)
  263. }
  264. // permissions for root dir are mandatory
  265. u.Permissions["/"] = []string{}
  266. u.Permissions["/somedir"] = []string{dataprovider.PermAny}
  267. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  268. if err != nil {
  269. t.Errorf("unexpected error adding user with no root dir perms: %v", err)
  270. }
  271. u.Permissions["/"] = []string{dataprovider.PermAny}
  272. u.Permissions["/subdir/.."] = []string{dataprovider.PermAny}
  273. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  274. if err != nil {
  275. t.Errorf("unexpected error adding user with invalid dir perms: %v", err)
  276. }
  277. }
  278. func TestAddUserInvalidFilters(t *testing.T) {
  279. u := getTestUser()
  280. u.Filters.AllowedIP = []string{"192.168.1.0/24", "192.168.2.0"}
  281. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  282. if err != nil {
  283. t.Errorf("unexpected error adding user with invalid filters: %v", err)
  284. }
  285. u.Filters.AllowedIP = []string{}
  286. u.Filters.DeniedIP = []string{"192.168.3.0/16", "invalid"}
  287. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  288. if err != nil {
  289. t.Errorf("unexpected error adding user with invalid filters: %v", err)
  290. }
  291. }
  292. func TestAddUserInvalidFsConfig(t *testing.T) {
  293. u := getTestUser()
  294. u.FsConfig.Provider = 1
  295. u.FsConfig.S3Config.Bucket = ""
  296. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  297. if err != nil {
  298. t.Errorf("unexpected error adding user with invalid fs config: %v", err)
  299. }
  300. os.RemoveAll(credentialsPath)
  301. os.MkdirAll(credentialsPath, 0700)
  302. u.FsConfig.S3Config.Bucket = "test"
  303. u.FsConfig.S3Config.Region = "eu-west-1"
  304. u.FsConfig.S3Config.AccessKey = "access-key"
  305. u.FsConfig.S3Config.AccessSecret = "access-secret"
  306. u.FsConfig.S3Config.Endpoint = "http://127.0.0.1:9000/path?a=b"
  307. u.FsConfig.S3Config.StorageClass = "Standard"
  308. u.FsConfig.S3Config.KeyPrefix = "/somedir/subdir/"
  309. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  310. if err != nil {
  311. t.Errorf("unexpected error adding user with invalid fs config: %v", err)
  312. }
  313. u = getTestUser()
  314. u.FsConfig.Provider = 2
  315. u.FsConfig.GCSConfig.Bucket = ""
  316. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  317. if err != nil {
  318. t.Errorf("unexpected error adding user with invalid fs config: %v", err)
  319. }
  320. u.FsConfig.GCSConfig.Bucket = "test"
  321. u.FsConfig.GCSConfig.StorageClass = "Standard"
  322. u.FsConfig.GCSConfig.KeyPrefix = "/somedir/subdir/"
  323. u.FsConfig.GCSConfig.Credentials = base64.StdEncoding.EncodeToString([]byte("test"))
  324. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  325. if err != nil {
  326. t.Errorf("unexpected error adding user with invalid fs config: %v", err)
  327. }
  328. u.FsConfig.GCSConfig.KeyPrefix = "somedir/subdir/"
  329. u.FsConfig.GCSConfig.Credentials = ""
  330. u.FsConfig.GCSConfig.AutomaticCredentials = 0
  331. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  332. if err != nil {
  333. t.Errorf("unexpected error adding user with invalid fs config: %v", err)
  334. }
  335. u.FsConfig.GCSConfig.Credentials = "no base64 encoded"
  336. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  337. if err != nil {
  338. t.Errorf("unexpected error adding user with invalid fs config: %v", err)
  339. }
  340. }
  341. func TestUserPublicKey(t *testing.T) {
  342. u := getTestUser()
  343. invalidPubKey := "invalid"
  344. validPubKey := "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC03jj0D+djk7pxIf/0OhrxrchJTRZklofJ1NoIu4752Sq02mdXmarMVsqJ1cAjV5LBVy3D1F5U6XW4rppkXeVtd04Pxb09ehtH0pRRPaoHHlALiJt8CoMpbKYMA8b3KXPPriGxgGomvtU2T2RMURSwOZbMtpsugfjYSWenyYX+VORYhylWnSXL961LTyC21ehd6d6QnW9G7E5hYMITMY9TuQZz3bROYzXiTsgN0+g6Hn7exFQp50p45StUMfV/SftCMdCxlxuyGny2CrN/vfjO7xxOo2uv7q1qm10Q46KPWJQv+pgZ/OfL+EDjy07n5QVSKHlbx+2nT4Q0EgOSQaCTYwn3YjtABfIxWwgAFdyj6YlPulCL22qU4MYhDcA6PSBwDdf8hvxBfvsiHdM+JcSHvv8/VeJhk6CmnZxGY0fxBupov27z3yEO8nAg8k+6PaUiW1MSUfuGMF/ktB8LOstXsEPXSszuyXiOv4DaryOXUiSn7bmRqKcEFlJusO6aZP0= nicola@p1"
  345. u.PublicKeys = []string{invalidPubKey}
  346. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  347. if err != nil {
  348. t.Errorf("unexpected error adding user with invalid pub key: %v", err)
  349. }
  350. u.PublicKeys = []string{validPubKey}
  351. user, _, err := httpd.AddUser(u, http.StatusOK)
  352. if err != nil {
  353. t.Errorf("unable to add user: %v", err)
  354. }
  355. user.PublicKeys = []string{validPubKey, invalidPubKey}
  356. _, _, err = httpd.UpdateUser(user, http.StatusBadRequest)
  357. if err != nil {
  358. t.Errorf("update user with invalid public key must fail: %v", err)
  359. }
  360. user.PublicKeys = []string{validPubKey, validPubKey, validPubKey}
  361. _, _, err = httpd.UpdateUser(user, http.StatusOK)
  362. if err != nil {
  363. t.Errorf("unable to update user: %v", err)
  364. }
  365. _, err = httpd.RemoveUser(user, http.StatusOK)
  366. if err != nil {
  367. t.Errorf("unable to remove: %v", err)
  368. }
  369. }
  370. func TestUpdateUser(t *testing.T) {
  371. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  372. if err != nil {
  373. t.Errorf("unable to add user: %v", err)
  374. }
  375. user.HomeDir = filepath.Join(homeBasePath, "testmod")
  376. user.UID = 33
  377. user.GID = 101
  378. user.MaxSessions = 10
  379. user.QuotaSize = 4096
  380. user.QuotaFiles = 2
  381. user.Permissions["/"] = []string{dataprovider.PermCreateDirs, dataprovider.PermDelete, dataprovider.PermDownload}
  382. user.Permissions["/subdir"] = []string{dataprovider.PermListItems, dataprovider.PermUpload}
  383. user.Filters.AllowedIP = []string{"192.168.1.0/24", "192.168.2.0/24"}
  384. user.Filters.DeniedIP = []string{"192.168.3.0/24", "192.168.4.0/24"}
  385. user.UploadBandwidth = 1024
  386. user.DownloadBandwidth = 512
  387. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  388. if err != nil {
  389. t.Errorf("unable to update user: %v", err)
  390. }
  391. user.Permissions["/subdir"] = []string{}
  392. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  393. if err != nil {
  394. t.Errorf("unable to update user: %v", err)
  395. }
  396. if len(user.Permissions["/subdir"]) > 0 {
  397. t.Errorf("unexpected subdir permissions, must be empty")
  398. }
  399. _, err = httpd.RemoveUser(user, http.StatusOK)
  400. if err != nil {
  401. t.Errorf("unable to remove: %v", err)
  402. }
  403. }
  404. func TestUserS3Config(t *testing.T) {
  405. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  406. if err != nil {
  407. t.Errorf("unable to add user: %v", err)
  408. }
  409. user.FsConfig.Provider = 1
  410. user.FsConfig.S3Config.Bucket = "test"
  411. user.FsConfig.S3Config.Region = "us-east-1"
  412. user.FsConfig.S3Config.AccessKey = "Server-Access-Key"
  413. user.FsConfig.S3Config.AccessSecret = "Server-Access-Secret"
  414. user.FsConfig.S3Config.Endpoint = "http://127.0.0.1:9000"
  415. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  416. if err != nil {
  417. t.Errorf("unable to update user: %v", err)
  418. }
  419. _, err = httpd.RemoveUser(user, http.StatusOK)
  420. if err != nil {
  421. t.Errorf("unable to remove: %v", err)
  422. }
  423. user.Password = defaultPassword
  424. user.ID = 0
  425. secret, _ := utils.EncryptData("Server-Access-Secret")
  426. user.FsConfig.S3Config.AccessSecret = secret
  427. user, _, err = httpd.AddUser(user, http.StatusOK)
  428. if err != nil {
  429. t.Errorf("unable to add user: %v", err)
  430. }
  431. user.FsConfig.Provider = 1
  432. user.FsConfig.S3Config.Bucket = "test1"
  433. user.FsConfig.S3Config.Region = "us-east-1"
  434. user.FsConfig.S3Config.AccessKey = "Server-Access-Key1"
  435. user.FsConfig.S3Config.Endpoint = "http://localhost:9000"
  436. user.FsConfig.S3Config.KeyPrefix = "somedir/subdir"
  437. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  438. if err != nil {
  439. t.Errorf("unable to update user: %v", err)
  440. }
  441. user.FsConfig.Provider = 0
  442. user.FsConfig.S3Config.Bucket = ""
  443. user.FsConfig.S3Config.Region = ""
  444. user.FsConfig.S3Config.AccessKey = ""
  445. user.FsConfig.S3Config.AccessSecret = ""
  446. user.FsConfig.S3Config.Endpoint = ""
  447. user.FsConfig.S3Config.KeyPrefix = ""
  448. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  449. if err != nil {
  450. t.Errorf("unable to update user: %v", err)
  451. }
  452. // test user without access key and access secret (shared config state)
  453. user.FsConfig.Provider = 1
  454. user.FsConfig.S3Config.Bucket = "test1"
  455. user.FsConfig.S3Config.Region = "us-east-1"
  456. user.FsConfig.S3Config.AccessKey = ""
  457. user.FsConfig.S3Config.AccessSecret = ""
  458. user.FsConfig.S3Config.Endpoint = ""
  459. user.FsConfig.S3Config.KeyPrefix = "somedir/subdir"
  460. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  461. if err != nil {
  462. t.Errorf("unable to update user: %v", err)
  463. }
  464. _, err = httpd.RemoveUser(user, http.StatusOK)
  465. if err != nil {
  466. t.Errorf("unable to remove: %v", err)
  467. }
  468. }
  469. func TestUserGCSConfig(t *testing.T) {
  470. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  471. if err != nil {
  472. t.Errorf("unable to add user: %v", err)
  473. }
  474. os.RemoveAll(credentialsPath)
  475. os.MkdirAll(credentialsPath, 0700)
  476. user.FsConfig.Provider = 2
  477. user.FsConfig.GCSConfig.Bucket = "test"
  478. user.FsConfig.GCSConfig.Credentials = base64.StdEncoding.EncodeToString([]byte("fake credentials"))
  479. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  480. if err != nil {
  481. t.Errorf("unable to update user: %v", err)
  482. }
  483. _, err = httpd.RemoveUser(user, http.StatusOK)
  484. if err != nil {
  485. t.Errorf("unable to remove: %v", err)
  486. }
  487. user.Password = defaultPassword
  488. user.ID = 0
  489. // the user will be added since the credentials file is found
  490. user, _, err = httpd.AddUser(user, http.StatusOK)
  491. if err != nil {
  492. t.Errorf("unable to add user: %v", err)
  493. }
  494. os.RemoveAll(credentialsPath)
  495. os.MkdirAll(credentialsPath, 0700)
  496. user.FsConfig.GCSConfig.Credentials = ""
  497. user.FsConfig.GCSConfig.AutomaticCredentials = 1
  498. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  499. if err != nil {
  500. t.Errorf("unable to update user: %v", err)
  501. }
  502. user.FsConfig.Provider = 1
  503. user.FsConfig.S3Config.Bucket = "test1"
  504. user.FsConfig.S3Config.Region = "us-east-1"
  505. user.FsConfig.S3Config.AccessKey = "Server-Access-Key1"
  506. user.FsConfig.S3Config.AccessSecret = "secret"
  507. user.FsConfig.S3Config.Endpoint = "http://localhost:9000"
  508. user.FsConfig.S3Config.KeyPrefix = "somedir/subdir"
  509. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  510. if err != nil {
  511. t.Errorf("unable to update user: %v", err)
  512. }
  513. user.FsConfig.Provider = 2
  514. user.FsConfig.GCSConfig.Bucket = "test1"
  515. user.FsConfig.GCSConfig.Credentials = base64.StdEncoding.EncodeToString([]byte("fake credentials"))
  516. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  517. if err != nil {
  518. t.Errorf("unable to update user: %v", err)
  519. }
  520. _, err = httpd.RemoveUser(user, http.StatusOK)
  521. if err != nil {
  522. t.Errorf("unable to remove: %v", err)
  523. }
  524. }
  525. func TestUpdateUserNoCredentials(t *testing.T) {
  526. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  527. if err != nil {
  528. t.Errorf("unable to add user: %v", err)
  529. }
  530. user.Password = ""
  531. user.PublicKeys = []string{}
  532. // password and public key will be omitted from json serialization if empty and so they will remain unchanged
  533. // and no validation error will be raised
  534. _, _, err = httpd.UpdateUser(user, http.StatusOK)
  535. if err != nil {
  536. t.Errorf("unexpected error updating user with no credentials: %v", err)
  537. }
  538. _, err = httpd.RemoveUser(user, http.StatusOK)
  539. if err != nil {
  540. t.Errorf("unable to remove: %v", err)
  541. }
  542. }
  543. func TestUpdateUserEmptyHomeDir(t *testing.T) {
  544. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  545. if err != nil {
  546. t.Errorf("unable to add user: %v", err)
  547. }
  548. user.HomeDir = ""
  549. _, _, err = httpd.UpdateUser(user, http.StatusBadRequest)
  550. if err != nil {
  551. t.Errorf("unexpected error updating user with empty home dir: %v", err)
  552. }
  553. _, err = httpd.RemoveUser(user, http.StatusOK)
  554. if err != nil {
  555. t.Errorf("unable to remove: %v", err)
  556. }
  557. }
  558. func TestUpdateUserInvalidHomeDir(t *testing.T) {
  559. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  560. if err != nil {
  561. t.Errorf("unable to add user: %v", err)
  562. }
  563. user.HomeDir = "relative_path"
  564. _, _, err = httpd.UpdateUser(user, http.StatusBadRequest)
  565. if err != nil {
  566. t.Errorf("unexpected error updating user with empty home dir: %v", err)
  567. }
  568. _, err = httpd.RemoveUser(user, http.StatusOK)
  569. if err != nil {
  570. t.Errorf("unable to remove: %v", err)
  571. }
  572. }
  573. func TestUpdateNonExistentUser(t *testing.T) {
  574. _, _, err := httpd.UpdateUser(getTestUser(), http.StatusNotFound)
  575. if err != nil {
  576. t.Errorf("unable to update user: %v", err)
  577. }
  578. }
  579. func TestGetNonExistentUser(t *testing.T) {
  580. _, _, err := httpd.GetUserByID(0, http.StatusNotFound)
  581. if err != nil {
  582. t.Errorf("unable to get user: %v", err)
  583. }
  584. }
  585. func TestDeleteNonExistentUser(t *testing.T) {
  586. _, err := httpd.RemoveUser(getTestUser(), http.StatusNotFound)
  587. if err != nil {
  588. t.Errorf("unable to remove user: %v", err)
  589. }
  590. }
  591. func TestAddDuplicateUser(t *testing.T) {
  592. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  593. if err != nil {
  594. t.Errorf("unable to add user: %v", err)
  595. }
  596. _, _, err = httpd.AddUser(getTestUser(), http.StatusInternalServerError)
  597. if err != nil {
  598. t.Errorf("unable to add second user: %v", err)
  599. }
  600. _, _, err = httpd.AddUser(getTestUser(), http.StatusOK)
  601. if err == nil {
  602. t.Errorf("adding a duplicate user must fail")
  603. }
  604. _, err = httpd.RemoveUser(user, http.StatusOK)
  605. if err != nil {
  606. t.Errorf("unable to remove user: %v", err)
  607. }
  608. }
  609. func TestGetUsers(t *testing.T) {
  610. user1, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  611. if err != nil {
  612. t.Errorf("unable to add user: %v", err)
  613. }
  614. u := getTestUser()
  615. u.Username = defaultUsername + "1"
  616. user2, _, err := httpd.AddUser(u, http.StatusOK)
  617. if err != nil {
  618. t.Errorf("unable to add second user: %v", err)
  619. }
  620. users, _, err := httpd.GetUsers(0, 0, "", http.StatusOK)
  621. if err != nil {
  622. t.Errorf("unable to get users: %v", err)
  623. }
  624. if len(users) < 2 {
  625. t.Errorf("at least 2 users are expected")
  626. }
  627. users, _, err = httpd.GetUsers(1, 0, "", http.StatusOK)
  628. if err != nil {
  629. t.Errorf("unable to get users: %v", err)
  630. }
  631. if len(users) != 1 {
  632. t.Errorf("1 user is expected")
  633. }
  634. users, _, err = httpd.GetUsers(1, 1, "", http.StatusOK)
  635. if err != nil {
  636. t.Errorf("unable to get users: %v", err)
  637. }
  638. if len(users) != 1 {
  639. t.Errorf("1 user is expected")
  640. }
  641. _, _, err = httpd.GetUsers(1, 1, "", http.StatusInternalServerError)
  642. if err == nil {
  643. t.Errorf("get users must succeed, we requested a fail for a good request")
  644. }
  645. _, err = httpd.RemoveUser(user1, http.StatusOK)
  646. if err != nil {
  647. t.Errorf("unable to remove user: %v", err)
  648. }
  649. _, err = httpd.RemoveUser(user2, http.StatusOK)
  650. if err != nil {
  651. t.Errorf("unable to remove user: %v", err)
  652. }
  653. }
  654. func TestGetQuotaScans(t *testing.T) {
  655. _, _, err := httpd.GetQuotaScans(http.StatusOK)
  656. if err != nil {
  657. t.Errorf("unable to get quota scans: %v", err)
  658. }
  659. _, _, err = httpd.GetQuotaScans(http.StatusInternalServerError)
  660. if err == nil {
  661. t.Errorf("quota scan request must succeed, we requested to check a wrong status code")
  662. }
  663. }
  664. func TestStartQuotaScan(t *testing.T) {
  665. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  666. if err != nil {
  667. t.Errorf("unable to add user: %v", err)
  668. }
  669. _, err = httpd.StartQuotaScan(user, http.StatusCreated)
  670. if err != nil {
  671. t.Errorf("unable to start quota scan: %v", err)
  672. }
  673. _, err = httpd.RemoveUser(user, http.StatusOK)
  674. if err != nil {
  675. t.Errorf("unable to remove user: %v", err)
  676. }
  677. }
  678. func TestGetVersion(t *testing.T) {
  679. _, _, err := httpd.GetVersion(http.StatusOK)
  680. if err != nil {
  681. t.Errorf("unable to get version: %v", err)
  682. }
  683. _, _, err = httpd.GetVersion(http.StatusInternalServerError)
  684. if err == nil {
  685. t.Errorf("get version request must succeed, we requested to check a wrong status code")
  686. }
  687. }
  688. func TestGetProviderStatus(t *testing.T) {
  689. _, _, err := httpd.GetProviderStatus(http.StatusOK)
  690. if err != nil {
  691. t.Errorf("unable to get provider status: %v", err)
  692. }
  693. _, _, err = httpd.GetProviderStatus(http.StatusBadRequest)
  694. if err == nil {
  695. t.Errorf("get provider status request must succeed, we requested to check a wrong status code")
  696. }
  697. }
  698. func TestGetConnections(t *testing.T) {
  699. _, _, err := httpd.GetConnections(http.StatusOK)
  700. if err != nil {
  701. t.Errorf("unable to get sftp connections: %v", err)
  702. }
  703. _, _, err = httpd.GetConnections(http.StatusInternalServerError)
  704. if err == nil {
  705. t.Errorf("get sftp connections request must succeed, we requested to check a wrong status code")
  706. }
  707. }
  708. func TestCloseActiveConnection(t *testing.T) {
  709. _, err := httpd.CloseConnection("non_existent_id", http.StatusNotFound)
  710. if err != nil {
  711. t.Errorf("unexpected error closing non existent sftp connection: %v", err)
  712. }
  713. }
  714. func TestUserBaseDir(t *testing.T) {
  715. dataProvider := dataprovider.GetProvider()
  716. dataprovider.Close(dataProvider)
  717. config.LoadConfig(configDir, "")
  718. providerConf := config.GetProviderConf()
  719. providerConf.UsersBaseDir = homeBasePath
  720. err := dataprovider.Initialize(providerConf, configDir)
  721. if err != nil {
  722. t.Errorf("error initializing data provider with users base dir")
  723. }
  724. httpd.SetDataProvider(dataprovider.GetProvider())
  725. u := getTestUser()
  726. u.HomeDir = ""
  727. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  728. if err != nil {
  729. t.Errorf("unable to add user: %v", err)
  730. }
  731. if user.HomeDir != filepath.Join(providerConf.UsersBaseDir, u.Username) {
  732. t.Errorf("invalid home dir: %v", user.HomeDir)
  733. }
  734. _, err = httpd.RemoveUser(user, http.StatusOK)
  735. if err != nil {
  736. t.Errorf("unable to remove: %v", err)
  737. }
  738. dataProvider = dataprovider.GetProvider()
  739. dataprovider.Close(dataProvider)
  740. config.LoadConfig(configDir, "")
  741. providerConf = config.GetProviderConf()
  742. providerConf.CredentialsPath = credentialsPath
  743. os.RemoveAll(credentialsPath)
  744. err = dataprovider.Initialize(providerConf, configDir)
  745. if err != nil {
  746. t.Errorf("error initializing data provider")
  747. }
  748. httpd.SetDataProvider(dataprovider.GetProvider())
  749. sftpd.SetDataProvider(dataprovider.GetProvider())
  750. }
  751. func TestProviderErrors(t *testing.T) {
  752. if providerDriverName == dataprovider.BoltDataProviderName {
  753. t.Skip("skipping test provider errors for bolt provider")
  754. }
  755. dataProvider := dataprovider.GetProvider()
  756. dataprovider.Close(dataProvider)
  757. _, _, err := httpd.GetUserByID(0, http.StatusInternalServerError)
  758. if err != nil {
  759. t.Errorf("get user with provider closed must fail: %v", err)
  760. }
  761. _, _, err = httpd.GetUsers(1, 0, defaultUsername, http.StatusInternalServerError)
  762. if err != nil {
  763. t.Errorf("get users with provider closed must fail: %v", err)
  764. }
  765. _, _, err = httpd.UpdateUser(dataprovider.User{}, http.StatusInternalServerError)
  766. if err != nil {
  767. t.Errorf("update user with provider closed must fail: %v", err)
  768. }
  769. _, err = httpd.RemoveUser(dataprovider.User{}, http.StatusInternalServerError)
  770. if err != nil {
  771. t.Errorf("delete user with provider closed must fail: %v", err)
  772. }
  773. _, _, err = httpd.GetProviderStatus(http.StatusInternalServerError)
  774. if err != nil {
  775. t.Errorf("get provider status with provider closed must fail: %v", err)
  776. }
  777. _, _, err = httpd.Dumpdata("backup.json", "", http.StatusInternalServerError)
  778. if err != nil {
  779. t.Errorf("get provider status with provider closed must fail: %v", err)
  780. }
  781. user := getTestUser()
  782. user.ID = 1
  783. backupData := dataprovider.BackupData{}
  784. backupData.Users = append(backupData.Users, user)
  785. backupContent, _ := json.Marshal(backupData)
  786. backupFilePath := filepath.Join(backupsPath, "backup.json")
  787. ioutil.WriteFile(backupFilePath, backupContent, 0666)
  788. _, _, err = httpd.Loaddata(backupFilePath, "", "", http.StatusInternalServerError)
  789. if err != nil {
  790. t.Errorf("get provider status with provider closed must fail: %v", err)
  791. }
  792. os.Remove(backupFilePath)
  793. config.LoadConfig(configDir, "")
  794. providerConf := config.GetProviderConf()
  795. providerConf.CredentialsPath = credentialsPath
  796. os.RemoveAll(credentialsPath)
  797. err = dataprovider.Initialize(providerConf, configDir)
  798. if err != nil {
  799. t.Errorf("error initializing data provider")
  800. }
  801. httpd.SetDataProvider(dataprovider.GetProvider())
  802. sftpd.SetDataProvider(dataprovider.GetProvider())
  803. }
  804. func TestDumpdata(t *testing.T) {
  805. dataProvider := dataprovider.GetProvider()
  806. dataprovider.Close(dataProvider)
  807. config.LoadConfig(configDir, "")
  808. providerConf := config.GetProviderConf()
  809. err := dataprovider.Initialize(providerConf, configDir)
  810. if err != nil {
  811. t.Errorf("error initializing data provider")
  812. }
  813. httpd.SetDataProvider(dataprovider.GetProvider())
  814. sftpd.SetDataProvider(dataprovider.GetProvider())
  815. _, _, err = httpd.Dumpdata("", "", http.StatusBadRequest)
  816. if err != nil {
  817. t.Errorf("unexpected error: %v", err)
  818. }
  819. _, _, err = httpd.Dumpdata(filepath.Join(backupsPath, "backup.json"), "", http.StatusBadRequest)
  820. if err != nil {
  821. t.Errorf("unexpected error: %v", err)
  822. }
  823. _, _, err = httpd.Dumpdata("../backup.json", "", http.StatusBadRequest)
  824. if err != nil {
  825. t.Errorf("unexpected error: %v", err)
  826. }
  827. _, _, err = httpd.Dumpdata("backup.json", "0", http.StatusOK)
  828. if err != nil {
  829. t.Errorf("unexpected error: %v", err)
  830. }
  831. _, _, err = httpd.Dumpdata("backup.json", "1", http.StatusOK)
  832. if err != nil {
  833. t.Errorf("unexpected error: %v", err)
  834. }
  835. os.Remove(filepath.Join(backupsPath, "backup.json"))
  836. if runtime.GOOS != "windows" {
  837. os.Chmod(backupsPath, 0001)
  838. _, _, err = httpd.Dumpdata("bck.json", "", http.StatusInternalServerError)
  839. if err != nil {
  840. t.Errorf("unexpected error: %v", err)
  841. }
  842. os.Chmod(backupsPath, 0755)
  843. }
  844. providerConf = config.GetProviderConf()
  845. providerConf.CredentialsPath = credentialsPath
  846. os.RemoveAll(credentialsPath)
  847. err = dataprovider.Initialize(providerConf, configDir)
  848. if err != nil {
  849. t.Errorf("error initializing data provider")
  850. }
  851. httpd.SetDataProvider(dataprovider.GetProvider())
  852. sftpd.SetDataProvider(dataprovider.GetProvider())
  853. }
  854. func TestLoaddata(t *testing.T) {
  855. user := getTestUser()
  856. user.ID = 1
  857. user.Username = "test_user_restore"
  858. backupData := dataprovider.BackupData{}
  859. backupData.Users = append(backupData.Users, user)
  860. backupContent, _ := json.Marshal(backupData)
  861. backupFilePath := filepath.Join(backupsPath, "backup.json")
  862. ioutil.WriteFile(backupFilePath, backupContent, 0666)
  863. _, _, err := httpd.Loaddata(backupFilePath, "a", "", http.StatusBadRequest)
  864. if err != nil {
  865. t.Errorf("unexpected error: %v", err)
  866. }
  867. _, _, err = httpd.Loaddata(backupFilePath, "", "a", http.StatusBadRequest)
  868. if err != nil {
  869. t.Errorf("unexpected error: %v", err)
  870. }
  871. _, _, err = httpd.Loaddata("backup.json", "1", "", http.StatusBadRequest)
  872. if err != nil {
  873. t.Errorf("unexpected error: %v", err)
  874. }
  875. _, _, err = httpd.Loaddata(backupFilePath+"a", "1", "", http.StatusBadRequest)
  876. if err != nil {
  877. t.Errorf("unexpected error: %v", err)
  878. }
  879. if runtime.GOOS != "windows" {
  880. os.Chmod(backupFilePath, 0111)
  881. _, _, err = httpd.Loaddata(backupFilePath, "1", "", http.StatusInternalServerError)
  882. if err != nil {
  883. t.Errorf("unexpected error: %v", err)
  884. }
  885. os.Chmod(backupFilePath, 0644)
  886. }
  887. // add user from backup
  888. _, _, err = httpd.Loaddata(backupFilePath, "1", "", http.StatusOK)
  889. if err != nil {
  890. t.Errorf("unexpected error: %v", err)
  891. }
  892. // update user from backup
  893. _, _, err = httpd.Loaddata(backupFilePath, "2", "", http.StatusOK)
  894. if err != nil {
  895. t.Errorf("unexpected error: %v", err)
  896. }
  897. users, _, err := httpd.GetUsers(1, 0, user.Username, http.StatusOK)
  898. if err != nil {
  899. t.Errorf("unable to get users: %v", err)
  900. }
  901. if len(users) != 1 {
  902. t.Error("Unable to get restored user")
  903. }
  904. user = users[0]
  905. _, err = httpd.RemoveUser(user, http.StatusOK)
  906. if err != nil {
  907. t.Errorf("unable to remove user: %v", err)
  908. }
  909. os.Remove(backupFilePath)
  910. createTestFile(backupFilePath, 10485761)
  911. _, _, err = httpd.Loaddata(backupFilePath, "1", "0", http.StatusBadRequest)
  912. if err != nil {
  913. t.Errorf("unexpected error: %v", err)
  914. }
  915. os.Remove(backupFilePath)
  916. createTestFile(backupFilePath, 65535)
  917. _, _, err = httpd.Loaddata(backupFilePath, "1", "0", http.StatusBadRequest)
  918. if err != nil {
  919. t.Errorf("unexpected error: %v", err)
  920. }
  921. os.Remove(backupFilePath)
  922. }
  923. func TestLoaddataMode(t *testing.T) {
  924. user := getTestUser()
  925. user.ID = 1
  926. user.Username = "test_user_restore"
  927. backupData := dataprovider.BackupData{}
  928. backupData.Users = append(backupData.Users, user)
  929. backupContent, _ := json.Marshal(backupData)
  930. backupFilePath := filepath.Join(backupsPath, "backup.json")
  931. ioutil.WriteFile(backupFilePath, backupContent, 0666)
  932. _, _, err := httpd.Loaddata(backupFilePath, "0", "0", http.StatusOK)
  933. if err != nil {
  934. t.Errorf("unexpected error: %v", err)
  935. }
  936. users, _, err := httpd.GetUsers(1, 0, user.Username, http.StatusOK)
  937. if err != nil {
  938. t.Errorf("unable to get users: %v", err)
  939. }
  940. if len(users) != 1 {
  941. t.Error("Unable to get restored user")
  942. }
  943. user = users[0]
  944. oldUploadBandwidth := user.UploadBandwidth
  945. user.UploadBandwidth = oldUploadBandwidth + 128
  946. user, _, err = httpd.UpdateUser(user, http.StatusOK)
  947. if err != nil {
  948. t.Errorf("unable to update user: %v", err)
  949. }
  950. _, _, err = httpd.Loaddata(backupFilePath, "0", "1", http.StatusOK)
  951. if err != nil {
  952. t.Errorf("unexpected error: %v", err)
  953. }
  954. users, _, err = httpd.GetUsers(1, 0, user.Username, http.StatusOK)
  955. if err != nil {
  956. t.Errorf("unable to get users: %v", err)
  957. }
  958. if len(users) != 1 {
  959. t.Error("Unable to get restored user")
  960. }
  961. user = users[0]
  962. if user.UploadBandwidth == oldUploadBandwidth {
  963. t.Error("user must not be modified")
  964. }
  965. _, err = httpd.RemoveUser(user, http.StatusOK)
  966. if err != nil {
  967. t.Errorf("unable to remove user: %v", err)
  968. }
  969. os.Remove(backupFilePath)
  970. }
  971. func TestHTTPSConnection(t *testing.T) {
  972. client := &http.Client{
  973. Timeout: 5 * time.Second,
  974. }
  975. _, err := client.Get("https://localhost:8443" + metricsPath)
  976. if err == nil || (!strings.Contains(err.Error(), "certificate is not valid") &&
  977. !strings.Contains(err.Error(), "certificate signed by unknown authority")) {
  978. t.Errorf("unexpected error: %v", err)
  979. }
  980. }
  981. // test using mock http server
  982. func TestBasicUserHandlingMock(t *testing.T) {
  983. user := getTestUser()
  984. userAsJSON := getUserAsJSON(t, user)
  985. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  986. rr := executeRequest(req)
  987. checkResponseCode(t, http.StatusOK, rr.Code)
  988. err := render.DecodeJSON(rr.Body, &user)
  989. if err != nil {
  990. t.Errorf("Error get user: %v", err)
  991. }
  992. req, _ = http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  993. rr = executeRequest(req)
  994. checkResponseCode(t, http.StatusInternalServerError, rr.Code)
  995. user.MaxSessions = 10
  996. user.UploadBandwidth = 128
  997. user.Permissions["/"] = []string{dataprovider.PermAny, dataprovider.PermDelete, dataprovider.PermDownload}
  998. userAsJSON = getUserAsJSON(t, user)
  999. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer(userAsJSON))
  1000. rr = executeRequest(req)
  1001. checkResponseCode(t, http.StatusOK, rr.Code)
  1002. req, _ = http.NewRequest(http.MethodGet, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  1003. rr = executeRequest(req)
  1004. checkResponseCode(t, http.StatusOK, rr.Code)
  1005. var updatedUser dataprovider.User
  1006. err = render.DecodeJSON(rr.Body, &updatedUser)
  1007. if err != nil {
  1008. t.Errorf("Error decoding updated user: %v", err)
  1009. }
  1010. if user.MaxSessions != updatedUser.MaxSessions || user.UploadBandwidth != updatedUser.UploadBandwidth {
  1011. t.Errorf("Error modifying user actual: %v, %v", updatedUser.MaxSessions, updatedUser.UploadBandwidth)
  1012. }
  1013. if len(updatedUser.Permissions["/"]) != 1 {
  1014. t.Errorf("permissions other than any should be removed")
  1015. }
  1016. if !utils.IsStringInSlice(dataprovider.PermAny, updatedUser.Permissions["/"]) {
  1017. t.Errorf("permissions mismatch")
  1018. }
  1019. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  1020. rr = executeRequest(req)
  1021. checkResponseCode(t, http.StatusOK, rr.Code)
  1022. }
  1023. func TestGetUserByIdInvalidParamsMock(t *testing.T) {
  1024. req, _ := http.NewRequest(http.MethodGet, userPath+"/0", nil)
  1025. rr := executeRequest(req)
  1026. checkResponseCode(t, http.StatusNotFound, rr.Code)
  1027. req, _ = http.NewRequest(http.MethodGet, userPath+"/a", nil)
  1028. rr = executeRequest(req)
  1029. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  1030. }
  1031. func TestAddUserNoUsernameMock(t *testing.T) {
  1032. user := getTestUser()
  1033. user.Username = ""
  1034. userAsJSON := getUserAsJSON(t, user)
  1035. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  1036. rr := executeRequest(req)
  1037. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  1038. }
  1039. func TestAddUserInvalidHomeDirMock(t *testing.T) {
  1040. user := getTestUser()
  1041. user.HomeDir = "relative_path"
  1042. userAsJSON := getUserAsJSON(t, user)
  1043. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  1044. rr := executeRequest(req)
  1045. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  1046. }
  1047. func TestAddUserInvalidPermsMock(t *testing.T) {
  1048. user := getTestUser()
  1049. user.Permissions["/"] = []string{}
  1050. userAsJSON := getUserAsJSON(t, user)
  1051. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  1052. rr := executeRequest(req)
  1053. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  1054. }
  1055. func TestAddUserInvalidJsonMock(t *testing.T) {
  1056. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer([]byte("invalid json")))
  1057. rr := executeRequest(req)
  1058. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  1059. }
  1060. func TestUpdateUserMock(t *testing.T) {
  1061. user := getTestUser()
  1062. userAsJSON := getUserAsJSON(t, user)
  1063. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  1064. rr := executeRequest(req)
  1065. checkResponseCode(t, http.StatusOK, rr.Code)
  1066. err := render.DecodeJSON(rr.Body, &user)
  1067. if err != nil {
  1068. t.Errorf("Error get user: %v", err)
  1069. }
  1070. // permissions should not change if empty or nil
  1071. permissions := user.Permissions
  1072. user.Permissions = make(map[string][]string)
  1073. userAsJSON = getUserAsJSON(t, user)
  1074. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer(userAsJSON))
  1075. rr = executeRequest(req)
  1076. checkResponseCode(t, http.StatusOK, rr.Code)
  1077. req, _ = http.NewRequest(http.MethodGet, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  1078. rr = executeRequest(req)
  1079. checkResponseCode(t, http.StatusOK, rr.Code)
  1080. var updatedUser dataprovider.User
  1081. err = render.DecodeJSON(rr.Body, &updatedUser)
  1082. if err != nil {
  1083. t.Errorf("Error decoding updated user: %v", err)
  1084. }
  1085. for dir, perms := range permissions {
  1086. if actualPerms, ok := updatedUser.Permissions[dir]; ok {
  1087. for _, v := range actualPerms {
  1088. if !utils.IsStringInSlice(v, perms) {
  1089. t.Error("Permissions contents mismatch")
  1090. }
  1091. }
  1092. } else {
  1093. t.Error("Permissions directories mismatch")
  1094. }
  1095. }
  1096. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  1097. rr = executeRequest(req)
  1098. checkResponseCode(t, http.StatusOK, rr.Code)
  1099. }
  1100. func TestUserPermissionsMock(t *testing.T) {
  1101. user := getTestUser()
  1102. user.Permissions = make(map[string][]string)
  1103. user.Permissions["/somedir"] = []string{dataprovider.PermAny}
  1104. userAsJSON := getUserAsJSON(t, user)
  1105. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  1106. rr := executeRequest(req)
  1107. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  1108. user.Permissions = make(map[string][]string)
  1109. user.Permissions["/"] = []string{dataprovider.PermAny}
  1110. user.Permissions[".."] = []string{dataprovider.PermAny}
  1111. userAsJSON = getUserAsJSON(t, user)
  1112. req, _ = http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  1113. rr = executeRequest(req)
  1114. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  1115. user.Permissions = make(map[string][]string)
  1116. user.Permissions["/"] = []string{dataprovider.PermAny}
  1117. userAsJSON = getUserAsJSON(t, user)
  1118. req, _ = http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  1119. rr = executeRequest(req)
  1120. checkResponseCode(t, http.StatusOK, rr.Code)
  1121. err := render.DecodeJSON(rr.Body, &user)
  1122. if err != nil {
  1123. t.Errorf("Error get user: %v", err)
  1124. }
  1125. user.Permissions["/somedir"] = []string{"invalid"}
  1126. userAsJSON = getUserAsJSON(t, user)
  1127. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer(userAsJSON))
  1128. rr = executeRequest(req)
  1129. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  1130. delete(user.Permissions, "/somedir")
  1131. user.Permissions["/somedir/.."] = []string{dataprovider.PermAny}
  1132. userAsJSON = getUserAsJSON(t, user)
  1133. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer(userAsJSON))
  1134. rr = executeRequest(req)
  1135. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  1136. delete(user.Permissions, "/somedir/..")
  1137. user.Permissions["not_abs_path"] = []string{dataprovider.PermAny}
  1138. userAsJSON = getUserAsJSON(t, user)
  1139. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer(userAsJSON))
  1140. rr = executeRequest(req)
  1141. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  1142. delete(user.Permissions, "not_abs_path")
  1143. user.Permissions["/somedir/../otherdir/"] = []string{dataprovider.PermListItems}
  1144. userAsJSON = getUserAsJSON(t, user)
  1145. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer(userAsJSON))
  1146. rr = executeRequest(req)
  1147. checkResponseCode(t, http.StatusOK, rr.Code)
  1148. req, _ = http.NewRequest(http.MethodGet, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  1149. rr = executeRequest(req)
  1150. checkResponseCode(t, http.StatusOK, rr.Code)
  1151. var updatedUser dataprovider.User
  1152. err = render.DecodeJSON(rr.Body, &updatedUser)
  1153. if err != nil {
  1154. t.Errorf("Error decoding updated user: %v", err)
  1155. }
  1156. if val, ok := updatedUser.Permissions["/otherdir"]; ok {
  1157. if !utils.IsStringInSlice(dataprovider.PermListItems, val) {
  1158. t.Error("expected permission list not found")
  1159. }
  1160. if len(val) != 1 {
  1161. t.Errorf("Unexpected number of permissions, expected 1, actual: %v", len(val))
  1162. }
  1163. } else {
  1164. t.Errorf("expected dir not found in permissions")
  1165. }
  1166. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  1167. rr = executeRequest(req)
  1168. checkResponseCode(t, http.StatusOK, rr.Code)
  1169. }
  1170. func TestUpdateUserInvalidJsonMock(t *testing.T) {
  1171. user := getTestUser()
  1172. userAsJSON := getUserAsJSON(t, user)
  1173. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  1174. rr := executeRequest(req)
  1175. checkResponseCode(t, http.StatusOK, rr.Code)
  1176. err := render.DecodeJSON(rr.Body, &user)
  1177. if err != nil {
  1178. t.Errorf("Error get user: %v", err)
  1179. }
  1180. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer([]byte("Invalid json")))
  1181. rr = executeRequest(req)
  1182. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  1183. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  1184. rr = executeRequest(req)
  1185. checkResponseCode(t, http.StatusOK, rr.Code)
  1186. }
  1187. func TestUpdateUserInvalidParamsMock(t *testing.T) {
  1188. user := getTestUser()
  1189. userAsJSON := getUserAsJSON(t, user)
  1190. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  1191. rr := executeRequest(req)
  1192. checkResponseCode(t, http.StatusOK, rr.Code)
  1193. err := render.DecodeJSON(rr.Body, &user)
  1194. if err != nil {
  1195. t.Errorf("Error get user: %v", err)
  1196. }
  1197. user.HomeDir = ""
  1198. userAsJSON = getUserAsJSON(t, user)
  1199. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer(userAsJSON))
  1200. rr = executeRequest(req)
  1201. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  1202. userID := user.ID
  1203. user.ID = 0
  1204. userAsJSON = getUserAsJSON(t, user)
  1205. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(userID, 10), bytes.NewBuffer(userAsJSON))
  1206. rr = executeRequest(req)
  1207. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  1208. user.ID = userID
  1209. req, _ = http.NewRequest(http.MethodPut, userPath+"/0", bytes.NewBuffer(userAsJSON))
  1210. rr = executeRequest(req)
  1211. checkResponseCode(t, http.StatusNotFound, rr.Code)
  1212. req, _ = http.NewRequest(http.MethodPut, userPath+"/a", bytes.NewBuffer(userAsJSON))
  1213. rr = executeRequest(req)
  1214. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  1215. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  1216. rr = executeRequest(req)
  1217. checkResponseCode(t, http.StatusOK, rr.Code)
  1218. }
  1219. func TestGetUsersMock(t *testing.T) {
  1220. user := getTestUser()
  1221. userAsJSON := getUserAsJSON(t, user)
  1222. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  1223. rr := executeRequest(req)
  1224. checkResponseCode(t, http.StatusOK, rr.Code)
  1225. err := render.DecodeJSON(rr.Body, &user)
  1226. if err != nil {
  1227. t.Errorf("Error get user: %v", err)
  1228. }
  1229. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=510&offset=0&order=ASC&username="+defaultUsername, nil)
  1230. rr = executeRequest(req)
  1231. checkResponseCode(t, http.StatusOK, rr.Code)
  1232. var users []dataprovider.User
  1233. err = render.DecodeJSON(rr.Body, &users)
  1234. if err != nil {
  1235. t.Errorf("Error decoding users: %v", err)
  1236. }
  1237. if len(users) != 1 {
  1238. t.Errorf("1 user is expected")
  1239. }
  1240. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=a&offset=0&order=ASC", nil)
  1241. rr = executeRequest(req)
  1242. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  1243. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=a&order=ASC", nil)
  1244. rr = executeRequest(req)
  1245. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  1246. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=0&order=ASCa", nil)
  1247. rr = executeRequest(req)
  1248. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  1249. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  1250. rr = executeRequest(req)
  1251. checkResponseCode(t, http.StatusOK, rr.Code)
  1252. }
  1253. func TestDeleteUserInvalidParamsMock(t *testing.T) {
  1254. req, _ := http.NewRequest(http.MethodDelete, userPath+"/0", nil)
  1255. rr := executeRequest(req)
  1256. checkResponseCode(t, http.StatusNotFound, rr.Code)
  1257. req, _ = http.NewRequest(http.MethodDelete, userPath+"/a", nil)
  1258. rr = executeRequest(req)
  1259. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  1260. }
  1261. func TestGetQuotaScansMock(t *testing.T) {
  1262. req, err := http.NewRequest("GET", quotaScanPath, nil)
  1263. if err != nil {
  1264. t.Errorf("error get quota scan: %v", err)
  1265. }
  1266. rr := executeRequest(req)
  1267. checkResponseCode(t, http.StatusOK, rr.Code)
  1268. }
  1269. func TestStartQuotaScanMock(t *testing.T) {
  1270. user := getTestUser()
  1271. userAsJSON := getUserAsJSON(t, user)
  1272. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  1273. rr := executeRequest(req)
  1274. checkResponseCode(t, http.StatusOK, rr.Code)
  1275. err := render.DecodeJSON(rr.Body, &user)
  1276. if err != nil {
  1277. t.Errorf("Error get user: %v", err)
  1278. }
  1279. _, err = os.Stat(user.HomeDir)
  1280. if err == nil {
  1281. os.Remove(user.HomeDir)
  1282. }
  1283. // simulate a duplicate quota scan
  1284. userAsJSON = getUserAsJSON(t, user)
  1285. sftpd.AddQuotaScan(user.Username)
  1286. req, _ = http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer(userAsJSON))
  1287. rr = executeRequest(req)
  1288. checkResponseCode(t, http.StatusConflict, rr.Code)
  1289. sftpd.RemoveQuotaScan(user.Username)
  1290. userAsJSON = getUserAsJSON(t, user)
  1291. req, _ = http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer(userAsJSON))
  1292. rr = executeRequest(req)
  1293. checkResponseCode(t, http.StatusCreated, rr.Code)
  1294. req, _ = http.NewRequest(http.MethodGet, quotaScanPath, nil)
  1295. rr = executeRequest(req)
  1296. checkResponseCode(t, http.StatusOK, rr.Code)
  1297. var scans []sftpd.ActiveQuotaScan
  1298. err = render.DecodeJSON(rr.Body, &scans)
  1299. if err != nil {
  1300. t.Errorf("Error get active scans: %v", err)
  1301. }
  1302. for len(scans) > 0 {
  1303. req, _ = http.NewRequest(http.MethodGet, quotaScanPath, nil)
  1304. rr = executeRequest(req)
  1305. checkResponseCode(t, http.StatusOK, rr.Code)
  1306. err = render.DecodeJSON(rr.Body, &scans)
  1307. if err != nil {
  1308. t.Errorf("Error get active scans: %v", err)
  1309. break
  1310. }
  1311. time.Sleep(100 * time.Millisecond)
  1312. }
  1313. _, err = os.Stat(user.HomeDir)
  1314. if err != nil && os.IsNotExist(err) {
  1315. os.MkdirAll(user.HomeDir, 0777)
  1316. }
  1317. req, _ = http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer(userAsJSON))
  1318. rr = executeRequest(req)
  1319. checkResponseCode(t, http.StatusCreated, rr.Code)
  1320. req, _ = http.NewRequest(http.MethodGet, quotaScanPath, nil)
  1321. rr = executeRequest(req)
  1322. checkResponseCode(t, http.StatusOK, rr.Code)
  1323. err = render.DecodeJSON(rr.Body, &scans)
  1324. if err != nil {
  1325. t.Errorf("Error get active scans: %v", err)
  1326. }
  1327. for len(scans) > 0 {
  1328. req, _ = http.NewRequest(http.MethodGet, quotaScanPath, nil)
  1329. rr = executeRequest(req)
  1330. checkResponseCode(t, http.StatusOK, rr.Code)
  1331. err = render.DecodeJSON(rr.Body, &scans)
  1332. if err != nil {
  1333. t.Errorf("Error get active scans: %v", err)
  1334. break
  1335. }
  1336. time.Sleep(100 * time.Millisecond)
  1337. }
  1338. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  1339. rr = executeRequest(req)
  1340. checkResponseCode(t, http.StatusOK, rr.Code)
  1341. os.RemoveAll(user.GetHomeDir())
  1342. }
  1343. func TestStartQuotaScanBadUserMock(t *testing.T) {
  1344. user := getTestUser()
  1345. userAsJSON := getUserAsJSON(t, user)
  1346. req, _ := http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer(userAsJSON))
  1347. rr := executeRequest(req)
  1348. checkResponseCode(t, http.StatusNotFound, rr.Code)
  1349. }
  1350. func TestStartQuotaScanNonExistentUserMock(t *testing.T) {
  1351. req, _ := http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer([]byte("invalid json")))
  1352. rr := executeRequest(req)
  1353. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  1354. }
  1355. func TestGetVersionMock(t *testing.T) {
  1356. req, _ := http.NewRequest(http.MethodGet, versionPath, nil)
  1357. rr := executeRequest(req)
  1358. checkResponseCode(t, http.StatusOK, rr.Code)
  1359. }
  1360. func TestGetConnectionsMock(t *testing.T) {
  1361. req, _ := http.NewRequest(http.MethodGet, activeConnectionsPath, nil)
  1362. rr := executeRequest(req)
  1363. checkResponseCode(t, http.StatusOK, rr.Code)
  1364. }
  1365. func TestDeleteActiveConnectionMock(t *testing.T) {
  1366. req, _ := http.NewRequest(http.MethodDelete, activeConnectionsPath+"/connectionID", nil)
  1367. rr := executeRequest(req)
  1368. checkResponseCode(t, http.StatusNotFound, rr.Code)
  1369. }
  1370. func TestNotFoundMock(t *testing.T) {
  1371. req, _ := http.NewRequest(http.MethodGet, "/non/existing/path", nil)
  1372. rr := executeRequest(req)
  1373. checkResponseCode(t, http.StatusNotFound, rr.Code)
  1374. }
  1375. func TestMethodNotAllowedMock(t *testing.T) {
  1376. req, _ := http.NewRequest(http.MethodPost, activeConnectionsPath, nil)
  1377. rr := executeRequest(req)
  1378. checkResponseCode(t, http.StatusMethodNotAllowed, rr.Code)
  1379. }
  1380. func TestMetricsMock(t *testing.T) {
  1381. req, _ := http.NewRequest(http.MethodGet, metricsPath, nil)
  1382. rr := executeRequest(req)
  1383. checkResponseCode(t, http.StatusOK, rr.Code)
  1384. }
  1385. func TestGetWebRootMock(t *testing.T) {
  1386. req, _ := http.NewRequest(http.MethodGet, "/", nil)
  1387. rr := executeRequest(req)
  1388. checkResponseCode(t, http.StatusMovedPermanently, rr.Code)
  1389. req, _ = http.NewRequest(http.MethodGet, webBasePath, nil)
  1390. rr = executeRequest(req)
  1391. checkResponseCode(t, http.StatusMovedPermanently, rr.Code)
  1392. }
  1393. func TestBasicWebUsersMock(t *testing.T) {
  1394. user := getTestUser()
  1395. userAsJSON := getUserAsJSON(t, user)
  1396. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  1397. rr := executeRequest(req)
  1398. checkResponseCode(t, http.StatusOK, rr.Code)
  1399. err := render.DecodeJSON(rr.Body, &user)
  1400. if err != nil {
  1401. t.Errorf("Error get user: %v", err)
  1402. }
  1403. user1 := getTestUser()
  1404. user1.Username += "1"
  1405. user1AsJSON := getUserAsJSON(t, user1)
  1406. req, _ = http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(user1AsJSON))
  1407. rr = executeRequest(req)
  1408. checkResponseCode(t, http.StatusOK, rr.Code)
  1409. err = render.DecodeJSON(rr.Body, &user1)
  1410. if err != nil {
  1411. t.Errorf("Error get user1: %v", err)
  1412. }
  1413. req, _ = http.NewRequest(http.MethodGet, webUsersPath, nil)
  1414. rr = executeRequest(req)
  1415. checkResponseCode(t, http.StatusOK, rr.Code)
  1416. req, _ = http.NewRequest(http.MethodGet, webUsersPath+"?qlimit=a", nil)
  1417. rr = executeRequest(req)
  1418. checkResponseCode(t, http.StatusOK, rr.Code)
  1419. req, _ = http.NewRequest(http.MethodGet, webUsersPath+"?qlimit=1", nil)
  1420. rr = executeRequest(req)
  1421. checkResponseCode(t, http.StatusOK, rr.Code)
  1422. req, _ = http.NewRequest(http.MethodGet, webUserPath, nil)
  1423. rr = executeRequest(req)
  1424. checkResponseCode(t, http.StatusOK, rr.Code)
  1425. req, _ = http.NewRequest(http.MethodGet, webUserPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  1426. rr = executeRequest(req)
  1427. checkResponseCode(t, http.StatusOK, rr.Code)
  1428. req, _ = http.NewRequest(http.MethodGet, webUserPath+"/0", nil)
  1429. rr = executeRequest(req)
  1430. checkResponseCode(t, http.StatusNotFound, rr.Code)
  1431. req, _ = http.NewRequest(http.MethodGet, webUserPath+"/a", nil)
  1432. rr = executeRequest(req)
  1433. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  1434. form := make(url.Values)
  1435. form.Set("username", user.Username)
  1436. b, contentType, _ := getMultipartFormData(form, "", "")
  1437. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  1438. req.Header.Set("Content-Type", contentType)
  1439. rr = executeRequest(req)
  1440. checkResponseCode(t, http.StatusOK, rr.Code)
  1441. b, contentType, _ = getMultipartFormData(form, "", "")
  1442. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  1443. req.Header.Set("Content-Type", contentType)
  1444. rr = executeRequest(req)
  1445. checkResponseCode(t, http.StatusOK, rr.Code)
  1446. b, contentType, _ = getMultipartFormData(form, "", "")
  1447. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/0", &b)
  1448. req.Header.Set("Content-Type", contentType)
  1449. rr = executeRequest(req)
  1450. checkResponseCode(t, http.StatusNotFound, rr.Code)
  1451. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/a", &b)
  1452. req.Header.Set("Content-Type", contentType)
  1453. rr = executeRequest(req)
  1454. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  1455. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  1456. rr = executeRequest(req)
  1457. checkResponseCode(t, http.StatusOK, rr.Code)
  1458. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user1.ID, 10), nil)
  1459. rr = executeRequest(req)
  1460. checkResponseCode(t, http.StatusOK, rr.Code)
  1461. }
  1462. func TestWebUserAddMock(t *testing.T) {
  1463. user := getTestUser()
  1464. user.UploadBandwidth = 32
  1465. user.DownloadBandwidth = 64
  1466. user.UID = 1000
  1467. form := make(url.Values)
  1468. form.Set("username", user.Username)
  1469. form.Set("home_dir", user.HomeDir)
  1470. form.Set("password", user.Password)
  1471. form.Set("status", strconv.Itoa(user.Status))
  1472. form.Set("expiration_date", "")
  1473. form.Set("permissions", "*")
  1474. form.Set("sub_dirs_permissions", " /subdir:list ,download ")
  1475. b, contentType, _ := getMultipartFormData(form, "", "")
  1476. // test invalid url escape
  1477. req, _ := http.NewRequest(http.MethodPost, webUserPath+"?a=%2", &b)
  1478. req.Header.Set("Content-Type", contentType)
  1479. rr := executeRequest(req)
  1480. checkResponseCode(t, http.StatusOK, rr.Code)
  1481. form.Set("public_keys", testPubKey)
  1482. form.Set("uid", strconv.FormatInt(int64(user.UID), 10))
  1483. form.Set("gid", "a")
  1484. b, contentType, _ = getMultipartFormData(form, "", "")
  1485. // test invalid gid
  1486. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  1487. req.Header.Set("Content-Type", contentType)
  1488. rr = executeRequest(req)
  1489. checkResponseCode(t, http.StatusOK, rr.Code)
  1490. form.Set("gid", "0")
  1491. form.Set("max_sessions", "a")
  1492. b, contentType, _ = getMultipartFormData(form, "", "")
  1493. // test invalid max sessions
  1494. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  1495. req.Header.Set("Content-Type", contentType)
  1496. rr = executeRequest(req)
  1497. checkResponseCode(t, http.StatusOK, rr.Code)
  1498. form.Set("max_sessions", "0")
  1499. form.Set("quota_size", "a")
  1500. b, contentType, _ = getMultipartFormData(form, "", "")
  1501. // test invalid quota size
  1502. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  1503. req.Header.Set("Content-Type", contentType)
  1504. rr = executeRequest(req)
  1505. checkResponseCode(t, http.StatusOK, rr.Code)
  1506. form.Set("quota_size", "0")
  1507. form.Set("quota_files", "a")
  1508. b, contentType, _ = getMultipartFormData(form, "", "")
  1509. // test invalid quota files
  1510. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  1511. req.Header.Set("Content-Type", contentType)
  1512. rr = executeRequest(req)
  1513. checkResponseCode(t, http.StatusOK, rr.Code)
  1514. form.Set("quota_files", "0")
  1515. form.Set("upload_bandwidth", "a")
  1516. b, contentType, _ = getMultipartFormData(form, "", "")
  1517. // test invalid upload bandwidth
  1518. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  1519. req.Header.Set("Content-Type", contentType)
  1520. rr = executeRequest(req)
  1521. checkResponseCode(t, http.StatusOK, rr.Code)
  1522. form.Set("upload_bandwidth", strconv.FormatInt(user.UploadBandwidth, 10))
  1523. form.Set("download_bandwidth", "a")
  1524. b, contentType, _ = getMultipartFormData(form, "", "")
  1525. // test invalid download bandwidth
  1526. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  1527. req.Header.Set("Content-Type", contentType)
  1528. rr = executeRequest(req)
  1529. checkResponseCode(t, http.StatusOK, rr.Code)
  1530. form.Set("download_bandwidth", strconv.FormatInt(user.DownloadBandwidth, 10))
  1531. form.Set("status", "a")
  1532. b, contentType, _ = getMultipartFormData(form, "", "")
  1533. // test invalid status
  1534. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  1535. req.Header.Set("Content-Type", contentType)
  1536. rr = executeRequest(req)
  1537. checkResponseCode(t, http.StatusOK, rr.Code)
  1538. form.Set("status", strconv.Itoa(user.Status))
  1539. form.Set("expiration_date", "123")
  1540. b, contentType, _ = getMultipartFormData(form, "", "")
  1541. // test invalid expiration date
  1542. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  1543. req.Header.Set("Content-Type", contentType)
  1544. rr = executeRequest(req)
  1545. checkResponseCode(t, http.StatusOK, rr.Code)
  1546. form.Set("expiration_date", "")
  1547. form.Set("allowed_ip", "invalid,ip")
  1548. b, contentType, _ = getMultipartFormData(form, "", "")
  1549. // test invalid allowed_ip
  1550. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  1551. req.Header.Set("Content-Type", contentType)
  1552. rr = executeRequest(req)
  1553. checkResponseCode(t, http.StatusOK, rr.Code)
  1554. form.Set("allowed_ip", "")
  1555. form.Set("denied_ip", "192.168.1.2") // it should be 192.168.1.2/32
  1556. b, contentType, _ = getMultipartFormData(form, "", "")
  1557. // test invalid denied_ip
  1558. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  1559. req.Header.Set("Content-Type", contentType)
  1560. rr = executeRequest(req)
  1561. checkResponseCode(t, http.StatusOK, rr.Code)
  1562. form.Set("denied_ip", "")
  1563. b, contentType, _ = getMultipartFormData(form, "", "")
  1564. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  1565. req.Header.Set("Content-Type", contentType)
  1566. rr = executeRequest(req)
  1567. checkResponseCode(t, http.StatusSeeOther, rr.Code)
  1568. // the user already exists, was created with the above request
  1569. b, contentType, _ = getMultipartFormData(form, "", "")
  1570. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  1571. req.Header.Set("Content-Type", contentType)
  1572. rr = executeRequest(req)
  1573. checkResponseCode(t, http.StatusOK, rr.Code)
  1574. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=0&order=ASC&username="+user.Username, nil)
  1575. rr = executeRequest(req)
  1576. checkResponseCode(t, http.StatusOK, rr.Code)
  1577. var users []dataprovider.User
  1578. err := render.DecodeJSON(rr.Body, &users)
  1579. if err != nil {
  1580. t.Errorf("Error decoding users: %v", err)
  1581. }
  1582. if len(users) != 1 {
  1583. t.Errorf("1 user is expected, actual: %v", len(users))
  1584. }
  1585. newUser := users[0]
  1586. if newUser.UID != user.UID {
  1587. t.Errorf("uid does not match")
  1588. }
  1589. if newUser.UploadBandwidth != user.UploadBandwidth {
  1590. t.Errorf("upload_bandwidth does not match")
  1591. }
  1592. if newUser.DownloadBandwidth != user.DownloadBandwidth {
  1593. t.Errorf("download_bandwidth does not match")
  1594. }
  1595. if !utils.IsStringInSlice(testPubKey, newUser.PublicKeys) {
  1596. t.Errorf("public_keys does not match")
  1597. }
  1598. if val, ok := newUser.Permissions["/subdir"]; ok {
  1599. if !utils.IsStringInSlice(dataprovider.PermListItems, val) || !utils.IsStringInSlice(dataprovider.PermDownload, val) {
  1600. t.Error("permssions for /subdir does not match")
  1601. }
  1602. } else {
  1603. t.Errorf("user permissions must contains /somedir, actual: %v", newUser.Permissions)
  1604. }
  1605. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(newUser.ID, 10), nil)
  1606. rr = executeRequest(req)
  1607. checkResponseCode(t, http.StatusOK, rr.Code)
  1608. }
  1609. func TestWebUserUpdateMock(t *testing.T) {
  1610. user := getTestUser()
  1611. userAsJSON := getUserAsJSON(t, user)
  1612. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  1613. rr := executeRequest(req)
  1614. checkResponseCode(t, http.StatusOK, rr.Code)
  1615. err := render.DecodeJSON(rr.Body, &user)
  1616. if err != nil {
  1617. t.Errorf("Error get user: %v", err)
  1618. }
  1619. user.MaxSessions = 1
  1620. user.QuotaFiles = 2
  1621. user.QuotaSize = 3
  1622. user.GID = 1000
  1623. form := make(url.Values)
  1624. form.Set("username", user.Username)
  1625. form.Set("home_dir", user.HomeDir)
  1626. form.Set("uid", "0")
  1627. form.Set("gid", strconv.FormatInt(int64(user.GID), 10))
  1628. form.Set("max_sessions", strconv.FormatInt(int64(user.MaxSessions), 10))
  1629. form.Set("quota_size", strconv.FormatInt(user.QuotaSize, 10))
  1630. form.Set("quota_files", strconv.FormatInt(int64(user.QuotaFiles), 10))
  1631. form.Set("upload_bandwidth", "0")
  1632. form.Set("download_bandwidth", "0")
  1633. form.Set("permissions", "*")
  1634. form.Set("sub_dirs_permissions", "/otherdir : list ,upload ")
  1635. form.Set("status", strconv.Itoa(user.Status))
  1636. form.Set("expiration_date", "2020-01-01 00:00:00")
  1637. form.Set("allowed_ip", " 192.168.1.3/32, 192.168.2.0/24 ")
  1638. form.Set("denied_ip", " 10.0.0.2/32 ")
  1639. b, contentType, _ := getMultipartFormData(form, "", "")
  1640. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  1641. req.Header.Set("Content-Type", contentType)
  1642. rr = executeRequest(req)
  1643. checkResponseCode(t, http.StatusSeeOther, rr.Code)
  1644. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=0&order=ASC&username="+user.Username, nil)
  1645. rr = executeRequest(req)
  1646. checkResponseCode(t, http.StatusOK, rr.Code)
  1647. var users []dataprovider.User
  1648. err = render.DecodeJSON(rr.Body, &users)
  1649. if err != nil {
  1650. t.Errorf("Error decoding users: %v", err)
  1651. }
  1652. if len(users) != 1 {
  1653. t.Errorf("1 user is expected")
  1654. }
  1655. updateUser := users[0]
  1656. if user.HomeDir != updateUser.HomeDir {
  1657. t.Errorf("home dir does not match")
  1658. }
  1659. if user.MaxSessions != updateUser.MaxSessions {
  1660. t.Errorf("max_sessions does not match")
  1661. }
  1662. if user.QuotaFiles != updateUser.QuotaFiles {
  1663. t.Errorf("quota_files does not match")
  1664. }
  1665. if user.QuotaSize != updateUser.QuotaSize {
  1666. t.Errorf("quota_size does not match")
  1667. }
  1668. if user.GID != updateUser.GID {
  1669. t.Errorf("gid does not match")
  1670. }
  1671. if val, ok := updateUser.Permissions["/otherdir"]; ok {
  1672. if !utils.IsStringInSlice(dataprovider.PermListItems, val) || !utils.IsStringInSlice(dataprovider.PermUpload, val) {
  1673. t.Error("permssions for /otherdir does not match")
  1674. }
  1675. } else {
  1676. t.Errorf("user permissions must contains /otherdir, actual: %v", updateUser.Permissions)
  1677. }
  1678. if !utils.IsStringInSlice("192.168.1.3/32", updateUser.Filters.AllowedIP) {
  1679. t.Errorf("Allowed IP/Mask does not match: %v", updateUser.Filters.AllowedIP)
  1680. }
  1681. if !utils.IsStringInSlice("10.0.0.2/32", updateUser.Filters.DeniedIP) {
  1682. t.Errorf("Denied IP/Mask does not match: %v", updateUser.Filters.DeniedIP)
  1683. }
  1684. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  1685. rr = executeRequest(req)
  1686. checkResponseCode(t, http.StatusOK, rr.Code)
  1687. }
  1688. func TestWebUserS3Mock(t *testing.T) {
  1689. user := getTestUser()
  1690. userAsJSON := getUserAsJSON(t, user)
  1691. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  1692. rr := executeRequest(req)
  1693. checkResponseCode(t, http.StatusOK, rr.Code)
  1694. err := render.DecodeJSON(rr.Body, &user)
  1695. if err != nil {
  1696. t.Errorf("Error get user: %v", err)
  1697. }
  1698. user.FsConfig.Provider = 1
  1699. user.FsConfig.S3Config.Bucket = "test"
  1700. user.FsConfig.S3Config.Region = "eu-west-1"
  1701. user.FsConfig.S3Config.AccessKey = "access-key"
  1702. user.FsConfig.S3Config.AccessSecret = "access-secret"
  1703. user.FsConfig.S3Config.Endpoint = "http://127.0.0.1:9000/path?a=b"
  1704. user.FsConfig.S3Config.StorageClass = "Standard"
  1705. user.FsConfig.S3Config.KeyPrefix = "somedir/subdir/"
  1706. form := make(url.Values)
  1707. form.Set("username", user.Username)
  1708. form.Set("home_dir", user.HomeDir)
  1709. form.Set("uid", "0")
  1710. form.Set("gid", strconv.FormatInt(int64(user.GID), 10))
  1711. form.Set("max_sessions", strconv.FormatInt(int64(user.MaxSessions), 10))
  1712. form.Set("quota_size", strconv.FormatInt(user.QuotaSize, 10))
  1713. form.Set("quota_files", strconv.FormatInt(int64(user.QuotaFiles), 10))
  1714. form.Set("upload_bandwidth", "0")
  1715. form.Set("download_bandwidth", "0")
  1716. form.Set("permissions", "*")
  1717. form.Set("sub_dirs_permissions", "")
  1718. form.Set("status", strconv.Itoa(user.Status))
  1719. form.Set("expiration_date", "2020-01-01 00:00:00")
  1720. form.Set("allowed_ip", "")
  1721. form.Set("denied_ip", "")
  1722. form.Set("fs_provider", "1")
  1723. form.Set("s3_bucket", user.FsConfig.S3Config.Bucket)
  1724. form.Set("s3_region", user.FsConfig.S3Config.Region)
  1725. form.Set("s3_access_key", user.FsConfig.S3Config.AccessKey)
  1726. form.Set("s3_access_secret", user.FsConfig.S3Config.AccessSecret)
  1727. form.Set("s3_storage_class", user.FsConfig.S3Config.StorageClass)
  1728. form.Set("s3_endpoint", user.FsConfig.S3Config.Endpoint)
  1729. form.Set("s3_key_prefix", user.FsConfig.S3Config.KeyPrefix)
  1730. b, contentType, _ := getMultipartFormData(form, "", "")
  1731. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  1732. req.Header.Set("Content-Type", contentType)
  1733. rr = executeRequest(req)
  1734. checkResponseCode(t, http.StatusSeeOther, rr.Code)
  1735. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=0&order=ASC&username="+user.Username, nil)
  1736. rr = executeRequest(req)
  1737. checkResponseCode(t, http.StatusOK, rr.Code)
  1738. var users []dataprovider.User
  1739. err = render.DecodeJSON(rr.Body, &users)
  1740. if err != nil {
  1741. t.Errorf("Error decoding users: %v", err)
  1742. }
  1743. if len(users) != 1 {
  1744. t.Errorf("1 user is expected")
  1745. }
  1746. updateUser := users[0]
  1747. if updateUser.ExpirationDate != 1577836800000 {
  1748. t.Errorf("invalid expiration date: %v", updateUser.ExpirationDate)
  1749. }
  1750. if updateUser.FsConfig.Provider != user.FsConfig.Provider {
  1751. t.Error("fs provider mismatch")
  1752. }
  1753. if updateUser.FsConfig.S3Config.Bucket != user.FsConfig.S3Config.Bucket {
  1754. t.Error("s3 bucket mismatch")
  1755. }
  1756. if updateUser.FsConfig.S3Config.Region != user.FsConfig.S3Config.Region {
  1757. t.Error("s3 region mismatch")
  1758. }
  1759. if updateUser.FsConfig.S3Config.AccessKey != user.FsConfig.S3Config.AccessKey {
  1760. t.Error("s3 access key mismatch")
  1761. }
  1762. if !strings.HasPrefix(updateUser.FsConfig.S3Config.AccessSecret, "$aes$") {
  1763. t.Error("s3 access secret is not encrypted")
  1764. }
  1765. if updateUser.FsConfig.S3Config.StorageClass != user.FsConfig.S3Config.StorageClass {
  1766. t.Error("s3 storage class mismatch")
  1767. }
  1768. if updateUser.FsConfig.S3Config.Endpoint != user.FsConfig.S3Config.Endpoint {
  1769. t.Error("s3 endpoint mismatch")
  1770. }
  1771. if updateUser.FsConfig.S3Config.KeyPrefix != user.FsConfig.S3Config.KeyPrefix {
  1772. t.Error("s3 key prefix mismatch")
  1773. }
  1774. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  1775. rr = executeRequest(req)
  1776. checkResponseCode(t, http.StatusOK, rr.Code)
  1777. }
  1778. func TestWebUserGCSMock(t *testing.T) {
  1779. user := getTestUser()
  1780. userAsJSON := getUserAsJSON(t, user)
  1781. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  1782. rr := executeRequest(req)
  1783. checkResponseCode(t, http.StatusOK, rr.Code)
  1784. err := render.DecodeJSON(rr.Body, &user)
  1785. if err != nil {
  1786. t.Errorf("Error get user: %v", err)
  1787. }
  1788. credentialsFilePath := filepath.Join(os.TempDir(), "gcs.json")
  1789. err = createTestFile(credentialsFilePath, 0)
  1790. if err != nil {
  1791. t.Errorf("unable to create credential test file: %v", err)
  1792. }
  1793. user.FsConfig.Provider = 2
  1794. user.FsConfig.GCSConfig.Bucket = "test"
  1795. user.FsConfig.GCSConfig.KeyPrefix = "somedir/subdir/"
  1796. user.FsConfig.GCSConfig.StorageClass = "standard"
  1797. form := make(url.Values)
  1798. form.Set("username", user.Username)
  1799. form.Set("home_dir", user.HomeDir)
  1800. form.Set("uid", "0")
  1801. form.Set("gid", strconv.FormatInt(int64(user.GID), 10))
  1802. form.Set("max_sessions", strconv.FormatInt(int64(user.MaxSessions), 10))
  1803. form.Set("quota_size", strconv.FormatInt(user.QuotaSize, 10))
  1804. form.Set("quota_files", strconv.FormatInt(int64(user.QuotaFiles), 10))
  1805. form.Set("upload_bandwidth", "0")
  1806. form.Set("download_bandwidth", "0")
  1807. form.Set("permissions", "*")
  1808. form.Set("sub_dirs_permissions", "")
  1809. form.Set("status", strconv.Itoa(user.Status))
  1810. form.Set("expiration_date", "2020-01-01 00:00:00")
  1811. form.Set("allowed_ip", "")
  1812. form.Set("denied_ip", "")
  1813. form.Set("fs_provider", "2")
  1814. form.Set("gcs_bucket", user.FsConfig.GCSConfig.Bucket)
  1815. form.Set("gcs_storage_class", user.FsConfig.GCSConfig.StorageClass)
  1816. form.Set("gcs_key_prefix", user.FsConfig.GCSConfig.KeyPrefix)
  1817. b, contentType, _ := getMultipartFormData(form, "", "")
  1818. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  1819. req.Header.Set("Content-Type", contentType)
  1820. rr = executeRequest(req)
  1821. checkResponseCode(t, http.StatusOK, rr.Code)
  1822. b, contentType, _ = getMultipartFormData(form, "gcs_credential_file", credentialsFilePath)
  1823. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  1824. req.Header.Set("Content-Type", contentType)
  1825. rr = executeRequest(req)
  1826. checkResponseCode(t, http.StatusOK, rr.Code)
  1827. err = createTestFile(credentialsFilePath, 4096)
  1828. if err != nil {
  1829. t.Errorf("unable to create credential test file: %v", err)
  1830. }
  1831. b, contentType, _ = getMultipartFormData(form, "gcs_credential_file", credentialsFilePath)
  1832. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  1833. req.Header.Set("Content-Type", contentType)
  1834. rr = executeRequest(req)
  1835. checkResponseCode(t, http.StatusSeeOther, rr.Code)
  1836. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=0&order=ASC&username="+user.Username, nil)
  1837. rr = executeRequest(req)
  1838. checkResponseCode(t, http.StatusOK, rr.Code)
  1839. var users []dataprovider.User
  1840. err = render.DecodeJSON(rr.Body, &users)
  1841. if err != nil {
  1842. t.Errorf("Error decoding users: %v", err)
  1843. }
  1844. if len(users) != 1 {
  1845. t.Errorf("1 user is expected")
  1846. }
  1847. updateUser := users[0]
  1848. if updateUser.ExpirationDate != 1577836800000 {
  1849. t.Errorf("invalid expiration date: %v", updateUser.ExpirationDate)
  1850. }
  1851. if updateUser.FsConfig.Provider != user.FsConfig.Provider {
  1852. t.Error("fs provider mismatch")
  1853. }
  1854. if updateUser.FsConfig.GCSConfig.Bucket != user.FsConfig.GCSConfig.Bucket {
  1855. t.Error("GCS bucket mismatch")
  1856. }
  1857. if updateUser.FsConfig.GCSConfig.StorageClass != user.FsConfig.GCSConfig.StorageClass {
  1858. t.Error("GCS storage class mismatch")
  1859. }
  1860. if updateUser.FsConfig.GCSConfig.KeyPrefix != user.FsConfig.GCSConfig.KeyPrefix {
  1861. t.Error("GCS key prefix mismatch")
  1862. }
  1863. form.Set("gcs_auto_credentials", "on")
  1864. b, contentType, _ = getMultipartFormData(form, "", "")
  1865. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  1866. req.Header.Set("Content-Type", contentType)
  1867. rr = executeRequest(req)
  1868. checkResponseCode(t, http.StatusSeeOther, rr.Code)
  1869. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=0&order=ASC&username="+user.Username, nil)
  1870. rr = executeRequest(req)
  1871. checkResponseCode(t, http.StatusOK, rr.Code)
  1872. err = render.DecodeJSON(rr.Body, &users)
  1873. if err != nil {
  1874. t.Errorf("Error decoding users: %v", err)
  1875. }
  1876. if len(users) != 1 {
  1877. t.Errorf("1 user is expected")
  1878. }
  1879. updateUser = users[0]
  1880. if updateUser.FsConfig.GCSConfig.AutomaticCredentials != 1 {
  1881. t.Error("GCS automatic credentials mismatch")
  1882. }
  1883. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  1884. rr = executeRequest(req)
  1885. checkResponseCode(t, http.StatusOK, rr.Code)
  1886. os.Remove(credentialsFilePath)
  1887. }
  1888. func TestProviderClosedMock(t *testing.T) {
  1889. if providerDriverName == dataprovider.BoltDataProviderName {
  1890. t.Skip("skipping test provider errors for bolt provider")
  1891. }
  1892. dataProvider := dataprovider.GetProvider()
  1893. dataprovider.Close(dataProvider)
  1894. req, _ := http.NewRequest(http.MethodGet, webUsersPath, nil)
  1895. rr := executeRequest(req)
  1896. checkResponseCode(t, http.StatusInternalServerError, rr.Code)
  1897. req, _ = http.NewRequest(http.MethodGet, webUserPath+"/0", nil)
  1898. rr = executeRequest(req)
  1899. checkResponseCode(t, http.StatusInternalServerError, rr.Code)
  1900. form := make(url.Values)
  1901. form.Set("username", "test")
  1902. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/0", strings.NewReader(form.Encode()))
  1903. rr = executeRequest(req)
  1904. checkResponseCode(t, http.StatusInternalServerError, rr.Code)
  1905. config.LoadConfig(configDir, "")
  1906. providerConf := config.GetProviderConf()
  1907. providerConf.CredentialsPath = credentialsPath
  1908. os.RemoveAll(credentialsPath)
  1909. err := dataprovider.Initialize(providerConf, configDir)
  1910. if err != nil {
  1911. t.Errorf("error initializing data provider")
  1912. }
  1913. httpd.SetDataProvider(dataprovider.GetProvider())
  1914. sftpd.SetDataProvider(dataprovider.GetProvider())
  1915. }
  1916. func TestGetWebConnectionsMock(t *testing.T) {
  1917. req, _ := http.NewRequest(http.MethodGet, webConnectionsPath, nil)
  1918. rr := executeRequest(req)
  1919. checkResponseCode(t, http.StatusOK, rr.Code)
  1920. }
  1921. func TestStaticFilesMock(t *testing.T) {
  1922. req, _ := http.NewRequest(http.MethodGet, "/static/favicon.ico", nil)
  1923. rr := executeRequest(req)
  1924. checkResponseCode(t, http.StatusOK, rr.Code)
  1925. }
  1926. func waitTCPListening(address string) {
  1927. for {
  1928. conn, err := net.Dial("tcp", address)
  1929. if err != nil {
  1930. logger.WarnToConsole("tcp server %v not listening: %v\n", address, err)
  1931. time.Sleep(100 * time.Millisecond)
  1932. continue
  1933. }
  1934. logger.InfoToConsole("tcp server %v now listening\n", address)
  1935. defer conn.Close()
  1936. break
  1937. }
  1938. }
  1939. func getTestUser() dataprovider.User {
  1940. user := dataprovider.User{
  1941. Username: defaultUsername,
  1942. Password: defaultPassword,
  1943. HomeDir: filepath.Join(homeBasePath, defaultUsername),
  1944. Status: 1,
  1945. }
  1946. user.Permissions = make(map[string][]string)
  1947. user.Permissions["/"] = defaultPerms
  1948. return user
  1949. }
  1950. func getUserAsJSON(t *testing.T, user dataprovider.User) []byte {
  1951. json, err := json.Marshal(user)
  1952. if err != nil {
  1953. t.Errorf("error get user as json: %v", err)
  1954. return []byte("{}")
  1955. }
  1956. return json
  1957. }
  1958. func executeRequest(req *http.Request) *httptest.ResponseRecorder {
  1959. rr := httptest.NewRecorder()
  1960. testServer.Config.Handler.ServeHTTP(rr, req)
  1961. return rr
  1962. }
  1963. func checkResponseCode(t *testing.T, expected, actual int) {
  1964. if expected != actual {
  1965. t.Errorf("Expected response code %d. Got %d", expected, actual)
  1966. }
  1967. }
  1968. func createTestFile(path string, size int64) error {
  1969. baseDir := filepath.Dir(path)
  1970. if _, err := os.Stat(baseDir); os.IsNotExist(err) {
  1971. os.MkdirAll(baseDir, 0777)
  1972. }
  1973. content := make([]byte, size)
  1974. if size > 0 {
  1975. _, err := rand.Read(content)
  1976. if err != nil {
  1977. return err
  1978. }
  1979. }
  1980. return ioutil.WriteFile(path, content, 0666)
  1981. }
  1982. func getMultipartFormData(values url.Values, fileFieldName, filePath string) (bytes.Buffer, string, error) {
  1983. var b bytes.Buffer
  1984. w := multipart.NewWriter(&b)
  1985. for k, v := range values {
  1986. for _, s := range v {
  1987. if err := w.WriteField(k, s); err != nil {
  1988. return b, "", err
  1989. }
  1990. }
  1991. }
  1992. if len(fileFieldName) > 0 && len(filePath) > 0 {
  1993. fw, err := w.CreateFormFile(fileFieldName, filepath.Base(filePath))
  1994. if err != nil {
  1995. return b, "", err
  1996. }
  1997. f, err := os.Open(filePath)
  1998. if err != nil {
  1999. return b, "", err
  2000. }
  2001. if _, err = io.Copy(fw, f); err != nil {
  2002. return b, "", err
  2003. }
  2004. }
  2005. err := w.Close()
  2006. return b, w.FormDataContentType(), err
  2007. }