httpd_test.go 148 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819
  1. package httpd_test
  2. import (
  3. "bytes"
  4. "crypto/rand"
  5. "encoding/json"
  6. "fmt"
  7. "io"
  8. "io/ioutil"
  9. "mime/multipart"
  10. "net"
  11. "net/http"
  12. "net/http/httptest"
  13. "net/url"
  14. "os"
  15. "path/filepath"
  16. "runtime"
  17. "strconv"
  18. "strings"
  19. "testing"
  20. "time"
  21. "github.com/go-chi/render"
  22. _ "github.com/go-sql-driver/mysql"
  23. _ "github.com/lib/pq"
  24. _ "github.com/mattn/go-sqlite3"
  25. "github.com/rs/zerolog"
  26. "github.com/stretchr/testify/assert"
  27. "github.com/stretchr/testify/require"
  28. "github.com/drakkan/sftpgo/common"
  29. "github.com/drakkan/sftpgo/config"
  30. "github.com/drakkan/sftpgo/dataprovider"
  31. "github.com/drakkan/sftpgo/httpd"
  32. "github.com/drakkan/sftpgo/kms"
  33. "github.com/drakkan/sftpgo/logger"
  34. "github.com/drakkan/sftpgo/utils"
  35. "github.com/drakkan/sftpgo/vfs"
  36. )
  37. const (
  38. defaultUsername = "test_user"
  39. defaultPassword = "test_password"
  40. testPubKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC03jj0D+djk7pxIf/0OhrxrchJTRZklofJ1NoIu4752Sq02mdXmarMVsqJ1cAjV5LBVy3D1F5U6XW4rppkXeVtd04Pxb09ehtH0pRRPaoHHlALiJt8CoMpbKYMA8b3KXPPriGxgGomvtU2T2RMURSwOZbMtpsugfjYSWenyYX+VORYhylWnSXL961LTyC21ehd6d6QnW9G7E5hYMITMY9TuQZz3bROYzXiTsgN0+g6Hn7exFQp50p45StUMfV/SftCMdCxlxuyGny2CrN/vfjO7xxOo2uv7q1qm10Q46KPWJQv+pgZ/OfL+EDjy07n5QVSKHlbx+2nT4Q0EgOSQaCTYwn3YjtABfIxWwgAFdyj6YlPulCL22qU4MYhDcA6PSBwDdf8hvxBfvsiHdM+JcSHvv8/VeJhk6CmnZxGY0fxBupov27z3yEO8nAg8k+6PaUiW1MSUfuGMF/ktB8LOstXsEPXSszuyXiOv4DaryOXUiSn7bmRqKcEFlJusO6aZP0= nicola@p1"
  41. userPath = "/api/v1/user"
  42. folderPath = "/api/v1/folder"
  43. activeConnectionsPath = "/api/v1/connection"
  44. quotaScanPath = "/api/v1/quota_scan"
  45. quotaScanVFolderPath = "/api/v1/folder_quota_scan"
  46. updateUsedQuotaPath = "/api/v1/quota_update"
  47. updateFolderUsedQuotaPath = "/api/v1/folder_quota_update"
  48. versionPath = "/api/v1/version"
  49. metricsPath = "/metrics"
  50. pprofPath = "/debug/pprof/"
  51. webBasePath = "/web"
  52. webUsersPath = "/web/users"
  53. webUserPath = "/web/user"
  54. webFoldersPath = "/web/folders"
  55. webFolderPath = "/web/folder"
  56. webConnectionsPath = "/web/connections"
  57. configDir = ".."
  58. httpsCert = `-----BEGIN CERTIFICATE-----
  59. MIICHTCCAaKgAwIBAgIUHnqw7QnB1Bj9oUsNpdb+ZkFPOxMwCgYIKoZIzj0EAwIw
  60. RTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGElu
  61. dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDAyMDQwOTUzMDRaFw0zMDAyMDEw
  62. OTUzMDRaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYD
  63. VQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwdjAQBgcqhkjOPQIBBgUrgQQA
  64. IgNiAARCjRMqJ85rzMC998X5z761nJ+xL3bkmGVqWvrJ51t5OxV0v25NsOgR82CA
  65. NXUgvhVYs7vNFN+jxtb2aj6Xg+/2G/BNxkaFspIVCzgWkxiz7XE4lgUwX44FCXZM
  66. 3+JeUbKjUzBRMB0GA1UdDgQWBBRhLw+/o3+Z02MI/d4tmaMui9W16jAfBgNVHSME
  67. GDAWgBRhLw+/o3+Z02MI/d4tmaMui9W16jAPBgNVHRMBAf8EBTADAQH/MAoGCCqG
  68. SM49BAMCA2kAMGYCMQDqLt2lm8mE+tGgtjDmtFgdOcI72HSbRQ74D5rYTzgST1rY
  69. /8wTi5xl8TiFUyLMUsICMQC5ViVxdXbhuG7gX6yEqSkMKZICHpO8hqFwOD/uaFVI
  70. dV4vKmHUzwK/eIx+8Ay3neE=
  71. -----END CERTIFICATE-----`
  72. httpsKey = `-----BEGIN EC PARAMETERS-----
  73. BgUrgQQAIg==
  74. -----END EC PARAMETERS-----
  75. -----BEGIN EC PRIVATE KEY-----
  76. MIGkAgEBBDCfMNsN6miEE3rVyUPwElfiJSWaR5huPCzUenZOfJT04GAcQdWvEju3
  77. UM2lmBLIXpGgBwYFK4EEACKhZANiAARCjRMqJ85rzMC998X5z761nJ+xL3bkmGVq
  78. WvrJ51t5OxV0v25NsOgR82CANXUgvhVYs7vNFN+jxtb2aj6Xg+/2G/BNxkaFspIV
  79. CzgWkxiz7XE4lgUwX44FCXZM3+JeUbI=
  80. -----END EC PRIVATE KEY-----`
  81. )
  82. var (
  83. defaultPerms = []string{dataprovider.PermAny}
  84. homeBasePath string
  85. backupsPath string
  86. credentialsPath string
  87. testServer *httptest.Server
  88. providerDriverName string
  89. )
  90. type fakeConnection struct {
  91. *common.BaseConnection
  92. command string
  93. }
  94. func (c *fakeConnection) Disconnect() error {
  95. common.Connections.Remove(c.GetID())
  96. return nil
  97. }
  98. func (c *fakeConnection) GetClientVersion() string {
  99. return ""
  100. }
  101. func (c *fakeConnection) GetCommand() string {
  102. return c.command
  103. }
  104. func (c *fakeConnection) GetRemoteAddress() string {
  105. return ""
  106. }
  107. func TestMain(m *testing.M) {
  108. homeBasePath = os.TempDir()
  109. logfilePath := filepath.Join(configDir, "sftpgo_api_test.log")
  110. logger.InitLogger(logfilePath, 5, 1, 28, false, zerolog.DebugLevel)
  111. err := config.LoadConfig(configDir, "")
  112. if err != nil {
  113. logger.WarnToConsole("error loading configuration: %v", err)
  114. os.Exit(1)
  115. }
  116. providerConf := config.GetProviderConf()
  117. credentialsPath = filepath.Join(os.TempDir(), "test_credentials")
  118. providerConf.CredentialsPath = credentialsPath
  119. providerDriverName = providerConf.Driver
  120. os.RemoveAll(credentialsPath) //nolint:errcheck
  121. logger.InfoToConsole("Starting HTTPD tests, provider: %v", providerConf.Driver)
  122. common.Initialize(config.GetCommonConfig())
  123. err = dataprovider.Initialize(providerConf, configDir)
  124. if err != nil {
  125. logger.WarnToConsole("error initializing data provider: %v", err)
  126. os.Exit(1)
  127. }
  128. httpConfig := config.GetHTTPConfig()
  129. httpConfig.Initialize(configDir)
  130. kmsConfig := config.GetKMSConfig()
  131. err = kmsConfig.Initialize()
  132. if err != nil {
  133. logger.ErrorToConsole("error initializing kms: %v", err)
  134. os.Exit(1)
  135. }
  136. httpdConf := config.GetHTTPDConfig()
  137. httpdConf.BindPort = 8081
  138. httpd.SetBaseURLAndCredentials("http://127.0.0.1:8081", "", "")
  139. backupsPath = filepath.Join(os.TempDir(), "test_backups")
  140. httpdConf.BackupsPath = backupsPath
  141. err = os.MkdirAll(backupsPath, os.ModePerm)
  142. if err != nil {
  143. logger.ErrorToConsole("error creating backups path: %v", err)
  144. os.Exit(1)
  145. }
  146. go func() {
  147. if err := httpdConf.Initialize(configDir, true); err != nil {
  148. logger.ErrorToConsole("could not start HTTP server: %v", err)
  149. os.Exit(1)
  150. }
  151. }()
  152. waitTCPListening(fmt.Sprintf("%s:%d", httpdConf.BindAddress, httpdConf.BindPort))
  153. // now start an https server
  154. certPath := filepath.Join(os.TempDir(), "test.crt")
  155. keyPath := filepath.Join(os.TempDir(), "test.key")
  156. err = ioutil.WriteFile(certPath, []byte(httpsCert), os.ModePerm)
  157. if err != nil {
  158. logger.ErrorToConsole("error writing HTTPS certificate: %v", err)
  159. os.Exit(1)
  160. }
  161. err = ioutil.WriteFile(keyPath, []byte(httpsKey), os.ModePerm)
  162. if err != nil {
  163. logger.ErrorToConsole("error writing HTTPS private key: %v", err)
  164. os.Exit(1)
  165. }
  166. httpdConf.BindPort = 8443
  167. httpdConf.CertificateFile = certPath
  168. httpdConf.CertificateKeyFile = keyPath
  169. go func() {
  170. if err := httpdConf.Initialize(configDir, true); err != nil {
  171. logger.ErrorToConsole("could not start HTTPS server: %v", err)
  172. os.Exit(1)
  173. }
  174. }()
  175. waitTCPListening(fmt.Sprintf("%s:%d", httpdConf.BindAddress, httpdConf.BindPort))
  176. httpd.ReloadTLSCertificate() //nolint:errcheck
  177. testServer = httptest.NewServer(httpd.GetHTTPRouter())
  178. defer testServer.Close()
  179. exitCode := m.Run()
  180. os.Remove(logfilePath) //nolint:errcheck
  181. os.RemoveAll(backupsPath) //nolint:errcheck
  182. os.RemoveAll(credentialsPath) //nolint:errcheck
  183. os.Remove(certPath) //nolint:errcheck
  184. os.Remove(keyPath) //nolint:errcheck
  185. os.Exit(exitCode) //nolint:errcheck
  186. }
  187. func TestInitialization(t *testing.T) {
  188. err := config.LoadConfig(configDir, "")
  189. assert.NoError(t, err)
  190. invalidFile := "invalid file"
  191. httpdConf := config.GetHTTPDConfig()
  192. httpdConf.BackupsPath = "test_backups"
  193. httpdConf.AuthUserFile = invalidFile
  194. err = httpdConf.Initialize(configDir, true)
  195. assert.Error(t, err)
  196. httpdConf.BackupsPath = backupsPath
  197. httpdConf.AuthUserFile = ""
  198. httpdConf.CertificateFile = invalidFile
  199. httpdConf.CertificateKeyFile = invalidFile
  200. err = httpdConf.Initialize(configDir, true)
  201. assert.Error(t, err)
  202. httpdConf.CertificateFile = ""
  203. httpdConf.CertificateKeyFile = ""
  204. httpdConf.TemplatesPath = "."
  205. err = httpdConf.Initialize(configDir, true)
  206. assert.Error(t, err)
  207. err = httpd.ReloadTLSCertificate()
  208. assert.NoError(t, err, "reloading TLS Certificate must return nil error if no certificate is configured")
  209. httpdConf = config.GetHTTPDConfig()
  210. httpdConf.BackupsPath = ".."
  211. err = httpdConf.Initialize(configDir, true)
  212. assert.Error(t, err)
  213. httpdConf.BackupsPath = backupsPath
  214. httpdConf.CertificateFile = invalidFile
  215. httpdConf.CertificateKeyFile = invalidFile
  216. httpdConf.StaticFilesPath = ""
  217. httpdConf.TemplatesPath = ""
  218. err = httpdConf.Initialize(configDir, true)
  219. assert.Error(t, err)
  220. }
  221. func TestBasicUserHandling(t *testing.T) {
  222. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  223. assert.NoError(t, err)
  224. user.MaxSessions = 10
  225. user.QuotaSize = 4096
  226. user.QuotaFiles = 2
  227. user.UploadBandwidth = 128
  228. user.DownloadBandwidth = 64
  229. user.ExpirationDate = utils.GetTimeAsMsSinceEpoch(time.Now())
  230. user.AdditionalInfo = "some free text"
  231. originalUser := user
  232. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  233. assert.NoError(t, err)
  234. assert.Equal(t, originalUser.ID, user.ID)
  235. users, _, err := httpd.GetUsers(0, 0, defaultUsername, http.StatusOK)
  236. assert.NoError(t, err)
  237. assert.Equal(t, 1, len(users))
  238. _, err = httpd.RemoveUser(user, http.StatusOK)
  239. assert.NoError(t, err)
  240. }
  241. func TestUserStatus(t *testing.T) {
  242. u := getTestUser()
  243. u.Status = 3
  244. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  245. assert.NoError(t, err)
  246. u.Status = 0
  247. user, _, err := httpd.AddUser(u, http.StatusOK)
  248. assert.NoError(t, err)
  249. user.Status = 2
  250. _, _, err = httpd.UpdateUser(user, http.StatusBadRequest, "")
  251. assert.NoError(t, err)
  252. user.Status = 1
  253. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  254. assert.NoError(t, err)
  255. _, err = httpd.RemoveUser(user, http.StatusOK)
  256. assert.NoError(t, err)
  257. }
  258. func TestAddUserNoCredentials(t *testing.T) {
  259. u := getTestUser()
  260. u.Password = ""
  261. u.PublicKeys = []string{}
  262. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  263. assert.NoError(t, err)
  264. }
  265. func TestAddUserNoUsername(t *testing.T) {
  266. u := getTestUser()
  267. u.Username = ""
  268. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  269. assert.NoError(t, err)
  270. }
  271. func TestAddUserNoHomeDir(t *testing.T) {
  272. u := getTestUser()
  273. u.HomeDir = ""
  274. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  275. assert.NoError(t, err)
  276. }
  277. func TestAddUserInvalidHomeDir(t *testing.T) {
  278. u := getTestUser()
  279. u.HomeDir = "relative_path" //nolint:goconst
  280. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  281. assert.NoError(t, err)
  282. }
  283. func TestAddUserNoPerms(t *testing.T) {
  284. u := getTestUser()
  285. u.Permissions = make(map[string][]string)
  286. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  287. assert.NoError(t, err)
  288. u.Permissions["/"] = []string{}
  289. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  290. assert.NoError(t, err)
  291. }
  292. func TestAddUserInvalidPerms(t *testing.T) {
  293. u := getTestUser()
  294. u.Permissions["/"] = []string{"invalidPerm"}
  295. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  296. assert.NoError(t, err)
  297. // permissions for root dir are mandatory
  298. u.Permissions["/"] = []string{}
  299. u.Permissions["/somedir"] = []string{dataprovider.PermAny}
  300. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  301. assert.NoError(t, err)
  302. u.Permissions["/"] = []string{dataprovider.PermAny}
  303. u.Permissions["/subdir/.."] = []string{dataprovider.PermAny}
  304. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  305. assert.NoError(t, err)
  306. }
  307. func TestAddUserInvalidFilters(t *testing.T) {
  308. u := getTestUser()
  309. u.Filters.AllowedIP = []string{"192.168.1.0/24", "192.168.2.0"}
  310. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  311. assert.NoError(t, err)
  312. u.Filters.AllowedIP = []string{}
  313. u.Filters.DeniedIP = []string{"192.168.3.0/16", "invalid"}
  314. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  315. assert.NoError(t, err)
  316. u.Filters.DeniedIP = []string{}
  317. u.Filters.DeniedLoginMethods = []string{"invalid"}
  318. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  319. assert.NoError(t, err)
  320. u.Filters.DeniedLoginMethods = dataprovider.ValidSSHLoginMethods
  321. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  322. assert.NoError(t, err)
  323. u.Filters.DeniedLoginMethods = []string{}
  324. u.Filters.FileExtensions = []dataprovider.ExtensionsFilter{
  325. {
  326. Path: "relative",
  327. AllowedExtensions: []string{},
  328. DeniedExtensions: []string{},
  329. },
  330. }
  331. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  332. assert.NoError(t, err)
  333. u.Filters.FileExtensions = []dataprovider.ExtensionsFilter{
  334. {
  335. Path: "/",
  336. AllowedExtensions: []string{},
  337. DeniedExtensions: []string{},
  338. },
  339. }
  340. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  341. assert.NoError(t, err)
  342. u.Filters.FileExtensions = []dataprovider.ExtensionsFilter{
  343. {
  344. Path: "/subdir",
  345. AllowedExtensions: []string{".zip"},
  346. DeniedExtensions: []string{},
  347. },
  348. {
  349. Path: "/subdir",
  350. AllowedExtensions: []string{".rar"},
  351. DeniedExtensions: []string{".jpg"},
  352. },
  353. }
  354. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  355. assert.NoError(t, err)
  356. u.Filters.FileExtensions = nil
  357. u.Filters.FilePatterns = []dataprovider.PatternsFilter{
  358. {
  359. Path: "relative",
  360. AllowedPatterns: []string{},
  361. DeniedPatterns: []string{},
  362. },
  363. }
  364. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  365. assert.NoError(t, err)
  366. u.Filters.FilePatterns = []dataprovider.PatternsFilter{
  367. {
  368. Path: "/",
  369. AllowedPatterns: []string{},
  370. DeniedPatterns: []string{},
  371. },
  372. }
  373. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  374. assert.NoError(t, err)
  375. u.Filters.FilePatterns = []dataprovider.PatternsFilter{
  376. {
  377. Path: "/subdir",
  378. AllowedPatterns: []string{"*.zip"},
  379. },
  380. {
  381. Path: "/subdir",
  382. AllowedPatterns: []string{"*.rar"},
  383. DeniedPatterns: []string{"*.jpg"},
  384. },
  385. }
  386. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  387. assert.NoError(t, err)
  388. u.Filters.FilePatterns = []dataprovider.PatternsFilter{
  389. {
  390. Path: "/subdir",
  391. AllowedPatterns: []string{"a\\"},
  392. },
  393. }
  394. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  395. assert.NoError(t, err)
  396. u.Filters.DeniedProtocols = []string{"invalid"}
  397. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  398. assert.NoError(t, err)
  399. u.Filters.DeniedProtocols = dataprovider.ValidProtocols
  400. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  401. assert.NoError(t, err)
  402. }
  403. func TestAddUserInvalidFsConfig(t *testing.T) {
  404. u := getTestUser()
  405. u.FsConfig.Provider = dataprovider.S3FilesystemProvider
  406. u.FsConfig.S3Config.Bucket = ""
  407. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  408. assert.NoError(t, err)
  409. err = os.RemoveAll(credentialsPath)
  410. assert.NoError(t, err)
  411. err = os.MkdirAll(credentialsPath, 0700)
  412. assert.NoError(t, err)
  413. u.FsConfig.S3Config.Bucket = "testbucket"
  414. u.FsConfig.S3Config.Region = "eu-west-1"
  415. u.FsConfig.S3Config.AccessKey = "access-key"
  416. u.FsConfig.S3Config.AccessSecret = kms.NewSecret(kms.SecretStatusRedacted, "access-secret", "", "")
  417. u.FsConfig.S3Config.Endpoint = "http://127.0.0.1:9000/path?a=b"
  418. u.FsConfig.S3Config.StorageClass = "Standard" //nolint:goconst
  419. u.FsConfig.S3Config.KeyPrefix = "/adir/subdir/"
  420. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  421. assert.NoError(t, err)
  422. u.FsConfig.S3Config.AccessSecret.SetStatus(kms.SecretStatusPlain)
  423. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  424. assert.NoError(t, err)
  425. u.FsConfig.S3Config.KeyPrefix = ""
  426. u.FsConfig.S3Config.UploadPartSize = 3
  427. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  428. assert.NoError(t, err)
  429. u.FsConfig.S3Config.UploadPartSize = 5001
  430. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  431. assert.NoError(t, err)
  432. u.FsConfig.S3Config.UploadPartSize = 0
  433. u.FsConfig.S3Config.UploadConcurrency = -1
  434. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  435. assert.NoError(t, err)
  436. u = getTestUser()
  437. u.FsConfig.Provider = dataprovider.GCSFilesystemProvider
  438. u.FsConfig.GCSConfig.Bucket = ""
  439. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  440. assert.NoError(t, err)
  441. u.FsConfig.GCSConfig.Bucket = "abucket"
  442. u.FsConfig.GCSConfig.StorageClass = "Standard"
  443. u.FsConfig.GCSConfig.KeyPrefix = "/somedir/subdir/"
  444. u.FsConfig.GCSConfig.Credentials = kms.NewSecret(kms.SecretStatusRedacted, "test", "", "") //nolint:goconst
  445. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  446. assert.NoError(t, err)
  447. u.FsConfig.GCSConfig.Credentials.SetStatus(kms.SecretStatusPlain)
  448. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  449. assert.NoError(t, err)
  450. u.FsConfig.GCSConfig.KeyPrefix = "somedir/subdir/" //nolint:goconst
  451. u.FsConfig.GCSConfig.Credentials = kms.NewEmptySecret()
  452. u.FsConfig.GCSConfig.AutomaticCredentials = 0
  453. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  454. assert.NoError(t, err)
  455. u.FsConfig.GCSConfig.Credentials = kms.NewSecret(kms.SecretStatusSecretBox, "invalid", "", "")
  456. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  457. assert.NoError(t, err)
  458. u = getTestUser()
  459. u.FsConfig.Provider = dataprovider.AzureBlobFilesystemProvider
  460. u.FsConfig.AzBlobConfig.SASURL = "http://foo\x7f.com/"
  461. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  462. assert.NoError(t, err)
  463. u.FsConfig.AzBlobConfig.SASURL = ""
  464. u.FsConfig.AzBlobConfig.AccountName = "name"
  465. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  466. assert.NoError(t, err)
  467. u.FsConfig.AzBlobConfig.Container = "container"
  468. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  469. assert.NoError(t, err)
  470. u.FsConfig.AzBlobConfig.AccountKey = kms.NewSecret(kms.SecretStatusRedacted, "key", "", "")
  471. u.FsConfig.AzBlobConfig.KeyPrefix = "/amedir/subdir/"
  472. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  473. assert.NoError(t, err)
  474. u.FsConfig.AzBlobConfig.AccountKey.SetStatus(kms.SecretStatusPlain)
  475. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  476. assert.NoError(t, err)
  477. u.FsConfig.AzBlobConfig.KeyPrefix = "amedir/subdir/"
  478. u.FsConfig.AzBlobConfig.UploadPartSize = -1
  479. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  480. assert.NoError(t, err)
  481. u.FsConfig.AzBlobConfig.UploadPartSize = 101
  482. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  483. assert.NoError(t, err)
  484. u = getTestUser()
  485. u.FsConfig.Provider = dataprovider.CryptedFilesystemProvider
  486. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  487. assert.NoError(t, err)
  488. u.FsConfig.CryptConfig.Passphrase = kms.NewSecret(kms.SecretStatusRedacted, "akey", "", "")
  489. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  490. assert.NoError(t, err)
  491. }
  492. func TestAddUserInvalidVirtualFolders(t *testing.T) {
  493. u := getTestUser()
  494. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  495. BaseVirtualFolder: vfs.BaseVirtualFolder{
  496. MappedPath: filepath.Join(os.TempDir(), "mapped_dir"),
  497. },
  498. VirtualPath: "vdir",
  499. })
  500. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  501. assert.NoError(t, err)
  502. u.VirtualFolders = nil
  503. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  504. BaseVirtualFolder: vfs.BaseVirtualFolder{
  505. MappedPath: filepath.Join(os.TempDir(), "mapped_dir"),
  506. },
  507. VirtualPath: "/",
  508. })
  509. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  510. assert.NoError(t, err)
  511. u.VirtualFolders = nil
  512. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  513. BaseVirtualFolder: vfs.BaseVirtualFolder{
  514. MappedPath: filepath.Join(u.GetHomeDir(), "mapped_dir"),
  515. },
  516. VirtualPath: "/vdir",
  517. })
  518. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  519. assert.NoError(t, err)
  520. u.VirtualFolders = nil
  521. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  522. BaseVirtualFolder: vfs.BaseVirtualFolder{
  523. MappedPath: u.GetHomeDir(),
  524. },
  525. VirtualPath: "/vdir",
  526. })
  527. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  528. assert.NoError(t, err)
  529. u.VirtualFolders = nil
  530. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  531. BaseVirtualFolder: vfs.BaseVirtualFolder{
  532. MappedPath: filepath.Join(u.GetHomeDir(), ".."),
  533. },
  534. VirtualPath: "/vdir",
  535. })
  536. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  537. assert.NoError(t, err)
  538. u.VirtualFolders = nil
  539. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  540. BaseVirtualFolder: vfs.BaseVirtualFolder{
  541. MappedPath: filepath.Join(os.TempDir(), "mapped_dir"),
  542. },
  543. VirtualPath: "/vdir",
  544. })
  545. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  546. BaseVirtualFolder: vfs.BaseVirtualFolder{
  547. MappedPath: filepath.Join(os.TempDir(), "mapped_dir1"),
  548. },
  549. VirtualPath: "/vdir",
  550. })
  551. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  552. assert.NoError(t, err)
  553. u.VirtualFolders = nil
  554. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  555. BaseVirtualFolder: vfs.BaseVirtualFolder{
  556. MappedPath: filepath.Join(os.TempDir(), "mapped_dir"),
  557. },
  558. VirtualPath: "/vdir1",
  559. })
  560. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  561. BaseVirtualFolder: vfs.BaseVirtualFolder{
  562. MappedPath: filepath.Join(os.TempDir(), "mapped_dir"),
  563. },
  564. VirtualPath: "/vdir2",
  565. })
  566. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  567. assert.NoError(t, err)
  568. u.VirtualFolders = nil
  569. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  570. BaseVirtualFolder: vfs.BaseVirtualFolder{
  571. MappedPath: filepath.Join(os.TempDir(), "mapped_dir", "subdir"),
  572. },
  573. VirtualPath: "/vdir1",
  574. })
  575. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  576. BaseVirtualFolder: vfs.BaseVirtualFolder{
  577. MappedPath: filepath.Join(os.TempDir(), "mapped_dir"),
  578. },
  579. VirtualPath: "/vdir2",
  580. })
  581. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  582. assert.NoError(t, err)
  583. u.VirtualFolders = nil
  584. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  585. BaseVirtualFolder: vfs.BaseVirtualFolder{
  586. MappedPath: filepath.Join(os.TempDir(), "mapped_dir"),
  587. },
  588. VirtualPath: "/vdir1",
  589. })
  590. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  591. BaseVirtualFolder: vfs.BaseVirtualFolder{
  592. MappedPath: filepath.Join(os.TempDir(), "mapped_dir", "subdir"),
  593. },
  594. VirtualPath: "/vdir2",
  595. })
  596. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  597. assert.NoError(t, err)
  598. u.VirtualFolders = nil
  599. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  600. BaseVirtualFolder: vfs.BaseVirtualFolder{
  601. MappedPath: filepath.Join(os.TempDir(), "mapped_dir1"),
  602. },
  603. VirtualPath: "/vdir1/subdir",
  604. })
  605. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  606. BaseVirtualFolder: vfs.BaseVirtualFolder{
  607. MappedPath: filepath.Join(os.TempDir(), "mapped_dir2"),
  608. },
  609. VirtualPath: "/vdir1/../vdir1",
  610. })
  611. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  612. assert.NoError(t, err)
  613. u.VirtualFolders = nil
  614. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  615. BaseVirtualFolder: vfs.BaseVirtualFolder{
  616. MappedPath: filepath.Join(os.TempDir(), "mapped_dir1"),
  617. },
  618. VirtualPath: "/vdir1/",
  619. })
  620. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  621. BaseVirtualFolder: vfs.BaseVirtualFolder{
  622. MappedPath: filepath.Join(os.TempDir(), "mapped_dir2"),
  623. },
  624. VirtualPath: "/vdir1/subdir",
  625. })
  626. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  627. assert.NoError(t, err)
  628. u.VirtualFolders = nil
  629. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  630. BaseVirtualFolder: vfs.BaseVirtualFolder{
  631. MappedPath: filepath.Join(os.TempDir(), "mapped_dir1"),
  632. },
  633. VirtualPath: "/vdir1/",
  634. QuotaSize: -1,
  635. QuotaFiles: 1,
  636. })
  637. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  638. assert.NoError(t, err)
  639. u.VirtualFolders = nil
  640. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  641. BaseVirtualFolder: vfs.BaseVirtualFolder{
  642. MappedPath: filepath.Join(os.TempDir(), "mapped_dir1"),
  643. },
  644. VirtualPath: "/vdir1/",
  645. QuotaSize: 1,
  646. QuotaFiles: -1,
  647. })
  648. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  649. assert.NoError(t, err)
  650. u.VirtualFolders = nil
  651. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  652. BaseVirtualFolder: vfs.BaseVirtualFolder{
  653. MappedPath: filepath.Join(os.TempDir(), "mapped_dir1"),
  654. },
  655. VirtualPath: "/vdir1/",
  656. QuotaSize: -2,
  657. QuotaFiles: 0,
  658. })
  659. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  660. assert.NoError(t, err)
  661. u.VirtualFolders = nil
  662. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  663. BaseVirtualFolder: vfs.BaseVirtualFolder{
  664. MappedPath: filepath.Join(os.TempDir(), "mapped_dir1"),
  665. },
  666. VirtualPath: "/vdir1/",
  667. QuotaSize: 0,
  668. QuotaFiles: -2,
  669. })
  670. _, _, err = httpd.AddUser(u, http.StatusBadRequest)
  671. assert.NoError(t, err)
  672. }
  673. func TestUserPublicKey(t *testing.T) {
  674. u := getTestUser()
  675. invalidPubKey := "invalid"
  676. validPubKey := "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC03jj0D+djk7pxIf/0OhrxrchJTRZklofJ1NoIu4752Sq02mdXmarMVsqJ1cAjV5LBVy3D1F5U6XW4rppkXeVtd04Pxb09ehtH0pRRPaoHHlALiJt8CoMpbKYMA8b3KXPPriGxgGomvtU2T2RMURSwOZbMtpsugfjYSWenyYX+VORYhylWnSXL961LTyC21ehd6d6QnW9G7E5hYMITMY9TuQZz3bROYzXiTsgN0+g6Hn7exFQp50p45StUMfV/SftCMdCxlxuyGny2CrN/vfjO7xxOo2uv7q1qm10Q46KPWJQv+pgZ/OfL+EDjy07n5QVSKHlbx+2nT4Q0EgOSQaCTYwn3YjtABfIxWwgAFdyj6YlPulCL22qU4MYhDcA6PSBwDdf8hvxBfvsiHdM+JcSHvv8/VeJhk6CmnZxGY0fxBupov27z3yEO8nAg8k+6PaUiW1MSUfuGMF/ktB8LOstXsEPXSszuyXiOv4DaryOXUiSn7bmRqKcEFlJusO6aZP0= nicola@p1"
  677. u.PublicKeys = []string{invalidPubKey}
  678. _, _, err := httpd.AddUser(u, http.StatusBadRequest)
  679. assert.NoError(t, err)
  680. u.PublicKeys = []string{validPubKey}
  681. user, _, err := httpd.AddUser(u, http.StatusOK)
  682. assert.NoError(t, err)
  683. user.PublicKeys = []string{validPubKey, invalidPubKey}
  684. _, _, err = httpd.UpdateUser(user, http.StatusBadRequest, "")
  685. assert.NoError(t, err)
  686. user.PublicKeys = []string{validPubKey, validPubKey, validPubKey}
  687. _, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  688. assert.NoError(t, err)
  689. _, err = httpd.RemoveUser(user, http.StatusOK)
  690. assert.NoError(t, err)
  691. }
  692. func TestUpdateUser(t *testing.T) {
  693. u := getTestUser()
  694. u.UsedQuotaFiles = 1
  695. u.UsedQuotaSize = 2
  696. user, _, err := httpd.AddUser(u, http.StatusOK)
  697. assert.NoError(t, err)
  698. assert.Equal(t, 0, user.UsedQuotaFiles)
  699. assert.Equal(t, int64(0), user.UsedQuotaSize)
  700. user.HomeDir = filepath.Join(homeBasePath, "testmod")
  701. user.UID = 33
  702. user.GID = 101
  703. user.MaxSessions = 10
  704. user.QuotaSize = 4096
  705. user.QuotaFiles = 2
  706. user.Permissions["/"] = []string{dataprovider.PermCreateDirs, dataprovider.PermDelete, dataprovider.PermDownload}
  707. user.Permissions["/subdir"] = []string{dataprovider.PermListItems, dataprovider.PermUpload}
  708. user.Filters.AllowedIP = []string{"192.168.1.0/24", "192.168.2.0/24"}
  709. user.Filters.DeniedIP = []string{"192.168.3.0/24", "192.168.4.0/24"}
  710. user.Filters.DeniedLoginMethods = []string{dataprovider.LoginMethodPassword}
  711. user.Filters.DeniedProtocols = []string{common.ProtocolWebDAV}
  712. user.Filters.FileExtensions = append(user.Filters.FileExtensions, dataprovider.ExtensionsFilter{
  713. Path: "/subdir",
  714. AllowedExtensions: []string{".zip", ".rar"},
  715. DeniedExtensions: []string{".jpg", ".png"},
  716. })
  717. user.Filters.FilePatterns = append(user.Filters.FilePatterns, dataprovider.PatternsFilter{
  718. Path: "/subdir",
  719. AllowedPatterns: []string{"*.zip", "*.rar"},
  720. DeniedPatterns: []string{"*.jpg", "*.png"},
  721. })
  722. user.Filters.MaxUploadFileSize = 4096
  723. user.UploadBandwidth = 1024
  724. user.DownloadBandwidth = 512
  725. user.VirtualFolders = nil
  726. mappedPath1 := filepath.Join(os.TempDir(), "mapped_dir1")
  727. mappedPath2 := filepath.Join(os.TempDir(), "mapped_dir2")
  728. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  729. BaseVirtualFolder: vfs.BaseVirtualFolder{
  730. MappedPath: mappedPath1,
  731. },
  732. VirtualPath: "/vdir1",
  733. })
  734. user.VirtualFolders = append(user.VirtualFolders, vfs.VirtualFolder{
  735. BaseVirtualFolder: vfs.BaseVirtualFolder{
  736. MappedPath: mappedPath2,
  737. },
  738. VirtualPath: "/vdir12/subdir",
  739. QuotaSize: 123,
  740. QuotaFiles: 2,
  741. })
  742. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  743. assert.NoError(t, err)
  744. _, _, err = httpd.UpdateUser(user, http.StatusBadRequest, "invalid")
  745. assert.NoError(t, err)
  746. user, _, err = httpd.UpdateUser(user, http.StatusOK, "0")
  747. assert.NoError(t, err)
  748. user, _, err = httpd.UpdateUser(user, http.StatusOK, "1")
  749. assert.NoError(t, err)
  750. user.Permissions["/subdir"] = []string{}
  751. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  752. assert.NoError(t, err)
  753. assert.Len(t, user.Permissions["/subdir"], 0)
  754. assert.Len(t, user.VirtualFolders, 2)
  755. for _, folder := range user.VirtualFolders {
  756. assert.Greater(t, folder.ID, int64(0))
  757. if folder.VirtualPath == "/vdir12/subdir" {
  758. assert.Equal(t, int64(123), folder.QuotaSize)
  759. assert.Equal(t, 2, folder.QuotaFiles)
  760. }
  761. }
  762. folder, _, err := httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  763. assert.NoError(t, err)
  764. if assert.Len(t, folder, 1) {
  765. f := folder[0]
  766. assert.Len(t, f.Users, 1)
  767. assert.Contains(t, f.Users, user.Username)
  768. }
  769. _, err = httpd.RemoveUser(user, http.StatusOK)
  770. assert.NoError(t, err)
  771. // removing the user must remove folder mapping
  772. folder, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  773. assert.NoError(t, err)
  774. if assert.Len(t, folder, 1) {
  775. f := folder[0]
  776. assert.Len(t, f.Users, 0)
  777. _, err = httpd.RemoveFolder(f, http.StatusOK)
  778. assert.NoError(t, err)
  779. }
  780. folder, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  781. assert.NoError(t, err)
  782. if assert.Len(t, folder, 1) {
  783. f := folder[0]
  784. assert.Len(t, f.Users, 0)
  785. _, err = httpd.RemoveFolder(f, http.StatusOK)
  786. assert.NoError(t, err)
  787. }
  788. }
  789. func TestUpdateUserQuotaUsage(t *testing.T) {
  790. u := getTestUser()
  791. usedQuotaFiles := 1
  792. usedQuotaSize := int64(65535)
  793. u.UsedQuotaFiles = usedQuotaFiles
  794. u.UsedQuotaSize = usedQuotaSize
  795. user, _, err := httpd.AddUser(u, http.StatusOK)
  796. assert.NoError(t, err)
  797. _, err = httpd.UpdateQuotaUsage(u, "invalid_mode", http.StatusBadRequest)
  798. assert.NoError(t, err)
  799. _, err = httpd.UpdateQuotaUsage(u, "", http.StatusOK)
  800. assert.NoError(t, err)
  801. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  802. assert.NoError(t, err)
  803. assert.Equal(t, usedQuotaFiles, user.UsedQuotaFiles)
  804. assert.Equal(t, usedQuotaSize, user.UsedQuotaSize)
  805. _, err = httpd.UpdateQuotaUsage(u, "add", http.StatusBadRequest)
  806. assert.NoError(t, err, "user has no quota restrictions add mode should fail")
  807. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  808. assert.NoError(t, err)
  809. assert.Equal(t, usedQuotaFiles, user.UsedQuotaFiles)
  810. assert.Equal(t, usedQuotaSize, user.UsedQuotaSize)
  811. user.QuotaFiles = 100
  812. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  813. assert.NoError(t, err)
  814. _, err = httpd.UpdateQuotaUsage(u, "add", http.StatusOK)
  815. assert.NoError(t, err)
  816. user, _, err = httpd.GetUserByID(user.ID, http.StatusOK)
  817. assert.NoError(t, err)
  818. assert.Equal(t, 2*usedQuotaFiles, user.UsedQuotaFiles)
  819. assert.Equal(t, 2*usedQuotaSize, user.UsedQuotaSize)
  820. u.UsedQuotaFiles = -1
  821. _, err = httpd.UpdateQuotaUsage(u, "", http.StatusBadRequest)
  822. assert.NoError(t, err)
  823. u.UsedQuotaFiles = usedQuotaFiles
  824. u.Username = u.Username + "1"
  825. _, err = httpd.UpdateQuotaUsage(u, "", http.StatusNotFound)
  826. assert.NoError(t, err)
  827. _, err = httpd.RemoveUser(user, http.StatusOK)
  828. assert.NoError(t, err)
  829. }
  830. func TestUserFolderMapping(t *testing.T) {
  831. mappedPath1 := filepath.Join(os.TempDir(), "mapped_dir1")
  832. mappedPath2 := filepath.Join(os.TempDir(), "mapped_dir2")
  833. u1 := getTestUser()
  834. u1.VirtualFolders = append(u1.VirtualFolders, vfs.VirtualFolder{
  835. BaseVirtualFolder: vfs.BaseVirtualFolder{
  836. MappedPath: mappedPath1,
  837. UsedQuotaFiles: 2,
  838. UsedQuotaSize: 123,
  839. },
  840. VirtualPath: "/vdir",
  841. QuotaSize: -1,
  842. QuotaFiles: -1,
  843. })
  844. user1, _, err := httpd.AddUser(u1, http.StatusOK)
  845. assert.NoError(t, err)
  846. // virtual folder must be auto created
  847. folders, _, err := httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  848. assert.NoError(t, err)
  849. if assert.Len(t, folders, 1) {
  850. folder := folders[0]
  851. assert.Len(t, folder.Users, 1)
  852. assert.Contains(t, folder.Users, user1.Username)
  853. assert.Equal(t, 0, folder.UsedQuotaFiles)
  854. assert.Equal(t, int64(0), folder.UsedQuotaSize)
  855. }
  856. u2 := getTestUser()
  857. u2.Username = defaultUsername + "2"
  858. u2.VirtualFolders = append(u2.VirtualFolders, vfs.VirtualFolder{
  859. BaseVirtualFolder: vfs.BaseVirtualFolder{
  860. MappedPath: mappedPath1,
  861. },
  862. VirtualPath: "/vdir1",
  863. QuotaSize: 0,
  864. QuotaFiles: 0,
  865. })
  866. u2.VirtualFolders = append(u2.VirtualFolders, vfs.VirtualFolder{
  867. BaseVirtualFolder: vfs.BaseVirtualFolder{
  868. MappedPath: mappedPath2,
  869. },
  870. VirtualPath: "/vdir2",
  871. QuotaSize: -1,
  872. QuotaFiles: -1,
  873. })
  874. user2, _, err := httpd.AddUser(u2, http.StatusOK)
  875. assert.NoError(t, err)
  876. folders, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  877. assert.NoError(t, err)
  878. if assert.Len(t, folders, 1) {
  879. folder := folders[0]
  880. assert.Len(t, folder.Users, 1)
  881. assert.Contains(t, folder.Users, user2.Username)
  882. }
  883. folders, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  884. assert.NoError(t, err)
  885. if assert.Len(t, folders, 1) {
  886. folder := folders[0]
  887. assert.Len(t, folder.Users, 2)
  888. assert.Contains(t, folder.Users, user1.Username)
  889. assert.Contains(t, folder.Users, user2.Username)
  890. }
  891. // now update user2 removing mappedPath1
  892. user2.VirtualFolders = nil
  893. user2.VirtualFolders = append(user2.VirtualFolders, vfs.VirtualFolder{
  894. BaseVirtualFolder: vfs.BaseVirtualFolder{
  895. MappedPath: mappedPath2,
  896. UsedQuotaFiles: 2,
  897. UsedQuotaSize: 123,
  898. },
  899. VirtualPath: "/vdir",
  900. QuotaSize: 0,
  901. QuotaFiles: 0,
  902. })
  903. user2, _, err = httpd.UpdateUser(user2, http.StatusOK, "")
  904. assert.NoError(t, err)
  905. folders, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  906. assert.NoError(t, err)
  907. if assert.Len(t, folders, 1) {
  908. folder := folders[0]
  909. assert.Len(t, folder.Users, 1)
  910. assert.Contains(t, folder.Users, user2.Username)
  911. assert.Equal(t, 0, folder.UsedQuotaFiles)
  912. assert.Equal(t, int64(0), folder.UsedQuotaSize)
  913. }
  914. folders, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  915. assert.NoError(t, err)
  916. if assert.Len(t, folders, 1) {
  917. folder := folders[0]
  918. assert.Len(t, folder.Users, 1)
  919. assert.Contains(t, folder.Users, user1.Username)
  920. }
  921. // add mappedPath1 again to user2
  922. user2.VirtualFolders = append(user2.VirtualFolders, vfs.VirtualFolder{
  923. BaseVirtualFolder: vfs.BaseVirtualFolder{
  924. MappedPath: mappedPath1,
  925. },
  926. VirtualPath: "/vdir1",
  927. })
  928. user2, _, err = httpd.UpdateUser(user2, http.StatusOK, "")
  929. assert.NoError(t, err)
  930. folders, _, err = httpd.GetFolders(0, 0, mappedPath2, http.StatusOK)
  931. assert.NoError(t, err)
  932. if assert.Len(t, folders, 1) {
  933. folder := folders[0]
  934. assert.Len(t, folder.Users, 1)
  935. assert.Contains(t, folder.Users, user2.Username)
  936. }
  937. // removing virtual folders should clear relations on both side
  938. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath2}, http.StatusOK)
  939. assert.NoError(t, err)
  940. user2, _, err = httpd.GetUserByID(user2.ID, http.StatusOK)
  941. assert.NoError(t, err)
  942. if assert.Len(t, user2.VirtualFolders, 1) {
  943. folder := user2.VirtualFolders[0]
  944. assert.Equal(t, mappedPath1, folder.MappedPath)
  945. }
  946. user1, _, err = httpd.GetUserByID(user1.ID, http.StatusOK)
  947. assert.NoError(t, err)
  948. if assert.Len(t, user2.VirtualFolders, 1) {
  949. folder := user2.VirtualFolders[0]
  950. assert.Equal(t, mappedPath1, folder.MappedPath)
  951. }
  952. folders, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  953. assert.NoError(t, err)
  954. if assert.Len(t, folders, 1) {
  955. folder := folders[0]
  956. assert.Len(t, folder.Users, 2)
  957. }
  958. // removing a user should clear virtual folder mapping
  959. _, err = httpd.RemoveUser(user1, http.StatusOK)
  960. assert.NoError(t, err)
  961. folders, _, err = httpd.GetFolders(0, 0, mappedPath1, http.StatusOK)
  962. assert.NoError(t, err)
  963. if assert.Len(t, folders, 1) {
  964. folder := folders[0]
  965. assert.Len(t, folder.Users, 1)
  966. assert.Contains(t, folder.Users, user2.Username)
  967. }
  968. // removing a folder should clear mapping on the user side too
  969. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: mappedPath1}, http.StatusOK)
  970. assert.NoError(t, err)
  971. user2, _, err = httpd.GetUserByID(user2.ID, http.StatusOK)
  972. assert.NoError(t, err)
  973. assert.Len(t, user2.VirtualFolders, 0)
  974. _, err = httpd.RemoveUser(user2, http.StatusOK)
  975. assert.NoError(t, err)
  976. }
  977. func TestUserS3Config(t *testing.T) {
  978. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  979. assert.NoError(t, err)
  980. user.FsConfig.Provider = dataprovider.S3FilesystemProvider
  981. user.FsConfig.S3Config.Bucket = "test" //nolint:goconst
  982. user.FsConfig.S3Config.Region = "us-east-1" //nolint:goconst
  983. user.FsConfig.S3Config.AccessKey = "Server-Access-Key"
  984. user.FsConfig.S3Config.AccessSecret = kms.NewPlainSecret("Server-Access-Secret")
  985. user.FsConfig.S3Config.Endpoint = "http://127.0.0.1:9000"
  986. user.FsConfig.S3Config.UploadPartSize = 8
  987. user, body, err := httpd.UpdateUser(user, http.StatusOK, "")
  988. assert.NoError(t, err, string(body))
  989. assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.S3Config.AccessSecret.GetStatus())
  990. assert.NotEmpty(t, user.FsConfig.S3Config.AccessSecret.GetPayload())
  991. assert.Empty(t, user.FsConfig.S3Config.AccessSecret.GetAdditionalData())
  992. assert.Empty(t, user.FsConfig.S3Config.AccessSecret.GetKey())
  993. _, err = httpd.RemoveUser(user, http.StatusOK)
  994. assert.NoError(t, err)
  995. user.Password = defaultPassword
  996. user.ID = 0
  997. secret := kms.NewSecret(kms.SecretStatusSecretBox, "Server-Access-Secret", "", "")
  998. user.FsConfig.S3Config.AccessSecret = secret
  999. _, _, err = httpd.AddUser(user, http.StatusOK)
  1000. assert.Error(t, err)
  1001. user.FsConfig.S3Config.AccessSecret.SetStatus(kms.SecretStatusPlain)
  1002. user, _, err = httpd.AddUser(user, http.StatusOK)
  1003. assert.NoError(t, err)
  1004. initialSecretPayload := user.FsConfig.S3Config.AccessSecret.GetPayload()
  1005. assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.S3Config.AccessSecret.GetStatus())
  1006. assert.NotEmpty(t, initialSecretPayload)
  1007. assert.Empty(t, user.FsConfig.S3Config.AccessSecret.GetAdditionalData())
  1008. assert.Empty(t, user.FsConfig.S3Config.AccessSecret.GetKey())
  1009. user.FsConfig.Provider = dataprovider.S3FilesystemProvider
  1010. user.FsConfig.S3Config.Bucket = "test-bucket"
  1011. user.FsConfig.S3Config.Region = "us-east-1" //nolint:goconst
  1012. user.FsConfig.S3Config.AccessKey = "Server-Access-Key1"
  1013. user.FsConfig.S3Config.Endpoint = "http://localhost:9000"
  1014. user.FsConfig.S3Config.KeyPrefix = "somedir/subdir" //nolint:goconst
  1015. user.FsConfig.S3Config.UploadConcurrency = 5
  1016. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1017. assert.NoError(t, err)
  1018. assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.S3Config.AccessSecret.GetStatus())
  1019. assert.Equal(t, initialSecretPayload, user.FsConfig.S3Config.AccessSecret.GetPayload())
  1020. assert.Empty(t, user.FsConfig.S3Config.AccessSecret.GetAdditionalData())
  1021. assert.Empty(t, user.FsConfig.S3Config.AccessSecret.GetKey())
  1022. // test user without access key and access secret (shared config state)
  1023. user.FsConfig.Provider = dataprovider.S3FilesystemProvider
  1024. user.FsConfig.S3Config.Bucket = "testbucket"
  1025. user.FsConfig.S3Config.Region = "us-east-1"
  1026. user.FsConfig.S3Config.AccessKey = ""
  1027. user.FsConfig.S3Config.AccessSecret = kms.NewEmptySecret()
  1028. user.FsConfig.S3Config.Endpoint = ""
  1029. user.FsConfig.S3Config.KeyPrefix = "somedir/subdir"
  1030. user.FsConfig.S3Config.UploadPartSize = 6
  1031. user.FsConfig.S3Config.UploadConcurrency = 4
  1032. user, body, err = httpd.UpdateUser(user, http.StatusOK, "")
  1033. assert.NoError(t, err, string(body))
  1034. assert.True(t, user.FsConfig.S3Config.AccessSecret.IsEmpty())
  1035. _, err = httpd.RemoveUser(user, http.StatusOK)
  1036. assert.NoError(t, err)
  1037. user.Password = defaultPassword
  1038. user.ID = 0
  1039. // shared credential test for add instead of update
  1040. user, _, err = httpd.AddUser(user, http.StatusOK)
  1041. assert.NoError(t, err)
  1042. assert.True(t, user.FsConfig.S3Config.AccessSecret.IsEmpty())
  1043. _, err = httpd.RemoveUser(user, http.StatusOK)
  1044. assert.NoError(t, err)
  1045. }
  1046. func TestUserGCSConfig(t *testing.T) {
  1047. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  1048. assert.NoError(t, err)
  1049. err = os.RemoveAll(credentialsPath)
  1050. assert.NoError(t, err)
  1051. err = os.MkdirAll(credentialsPath, 0700)
  1052. assert.NoError(t, err)
  1053. user.FsConfig.Provider = dataprovider.GCSFilesystemProvider
  1054. user.FsConfig.GCSConfig.Bucket = "test"
  1055. user.FsConfig.GCSConfig.Credentials = kms.NewPlainSecret("fake credentials") //nolint:goconst
  1056. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1057. assert.NoError(t, err)
  1058. credentialFile := filepath.Join(credentialsPath, fmt.Sprintf("%v_gcs_credentials.json", user.Username))
  1059. assert.FileExists(t, credentialFile)
  1060. creds, err := ioutil.ReadFile(credentialFile)
  1061. assert.NoError(t, err)
  1062. secret := kms.NewEmptySecret()
  1063. err = json.Unmarshal(creds, secret)
  1064. assert.NoError(t, err)
  1065. err = secret.Decrypt()
  1066. assert.NoError(t, err)
  1067. assert.Equal(t, "fake credentials", secret.GetPayload())
  1068. user.FsConfig.GCSConfig.Credentials = kms.NewSecret(kms.SecretStatusSecretBox, "fake encrypted credentials", "", "")
  1069. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1070. assert.NoError(t, err)
  1071. assert.FileExists(t, credentialFile)
  1072. creds, err = ioutil.ReadFile(credentialFile)
  1073. assert.NoError(t, err)
  1074. secret = kms.NewEmptySecret()
  1075. err = json.Unmarshal(creds, secret)
  1076. assert.NoError(t, err)
  1077. err = secret.Decrypt()
  1078. assert.NoError(t, err)
  1079. assert.Equal(t, "fake credentials", secret.GetPayload())
  1080. _, err = httpd.RemoveUser(user, http.StatusOK)
  1081. assert.NoError(t, err)
  1082. user.Password = defaultPassword
  1083. user.ID = 0
  1084. user.FsConfig.GCSConfig.Credentials = kms.NewSecret(kms.SecretStatusSecretBox, "fake credentials", "", "")
  1085. _, _, err = httpd.AddUser(user, http.StatusOK)
  1086. assert.Error(t, err)
  1087. user.FsConfig.GCSConfig.Credentials.SetStatus(kms.SecretStatusPlain)
  1088. user, body, err := httpd.AddUser(user, http.StatusOK)
  1089. assert.NoError(t, err, string(body))
  1090. err = os.RemoveAll(credentialsPath)
  1091. assert.NoError(t, err)
  1092. err = os.MkdirAll(credentialsPath, 0700)
  1093. assert.NoError(t, err)
  1094. user.FsConfig.GCSConfig.Credentials = kms.NewEmptySecret()
  1095. user.FsConfig.GCSConfig.AutomaticCredentials = 1
  1096. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1097. assert.NoError(t, err)
  1098. assert.NoFileExists(t, credentialFile)
  1099. user.FsConfig.GCSConfig = vfs.GCSFsConfig{}
  1100. user.FsConfig.Provider = dataprovider.S3FilesystemProvider
  1101. user.FsConfig.S3Config.Bucket = "test1"
  1102. user.FsConfig.S3Config.Region = "us-east-1"
  1103. user.FsConfig.S3Config.AccessKey = "Server-Access-Key1"
  1104. user.FsConfig.S3Config.AccessSecret = kms.NewPlainSecret("secret")
  1105. user.FsConfig.S3Config.Endpoint = "http://localhost:9000"
  1106. user.FsConfig.S3Config.KeyPrefix = "somedir/subdir"
  1107. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1108. assert.NoError(t, err)
  1109. user.FsConfig.S3Config = vfs.S3FsConfig{}
  1110. user.FsConfig.Provider = dataprovider.GCSFilesystemProvider
  1111. user.FsConfig.GCSConfig.Bucket = "test1"
  1112. user.FsConfig.GCSConfig.Credentials = kms.NewPlainSecret("fake credentials")
  1113. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1114. assert.NoError(t, err)
  1115. _, err = httpd.RemoveUser(user, http.StatusOK)
  1116. assert.NoError(t, err)
  1117. }
  1118. func TestUserAzureBlobConfig(t *testing.T) {
  1119. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  1120. assert.NoError(t, err)
  1121. user.FsConfig.Provider = dataprovider.AzureBlobFilesystemProvider
  1122. user.FsConfig.AzBlobConfig.Container = "test"
  1123. user.FsConfig.AzBlobConfig.AccountName = "Server-Account-Name"
  1124. user.FsConfig.AzBlobConfig.AccountKey = kms.NewPlainSecret("Server-Account-Key")
  1125. user.FsConfig.AzBlobConfig.Endpoint = "http://127.0.0.1:9000"
  1126. user.FsConfig.AzBlobConfig.UploadPartSize = 8
  1127. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1128. assert.NoError(t, err)
  1129. initialPayload := user.FsConfig.AzBlobConfig.AccountKey.GetPayload()
  1130. assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.AzBlobConfig.AccountKey.GetStatus())
  1131. assert.NotEmpty(t, initialPayload)
  1132. assert.Empty(t, user.FsConfig.AzBlobConfig.AccountKey.GetAdditionalData())
  1133. assert.Empty(t, user.FsConfig.AzBlobConfig.AccountKey.GetKey())
  1134. user.FsConfig.AzBlobConfig.AccountKey.SetStatus(kms.SecretStatusSecretBox)
  1135. user.FsConfig.AzBlobConfig.AccountKey.SetAdditionalData("data")
  1136. user.FsConfig.AzBlobConfig.AccountKey.SetKey("fake key")
  1137. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1138. assert.NoError(t, err)
  1139. assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.AzBlobConfig.AccountKey.GetStatus())
  1140. assert.Equal(t, initialPayload, user.FsConfig.AzBlobConfig.AccountKey.GetPayload())
  1141. assert.Empty(t, user.FsConfig.AzBlobConfig.AccountKey.GetAdditionalData())
  1142. assert.Empty(t, user.FsConfig.AzBlobConfig.AccountKey.GetKey())
  1143. _, err = httpd.RemoveUser(user, http.StatusOK)
  1144. assert.NoError(t, err)
  1145. user.Password = defaultPassword
  1146. user.ID = 0
  1147. secret := kms.NewSecret(kms.SecretStatusSecretBox, "Server-Account-Key", "", "")
  1148. user.FsConfig.AzBlobConfig.AccountKey = secret
  1149. _, _, err = httpd.AddUser(user, http.StatusOK)
  1150. assert.Error(t, err)
  1151. user.FsConfig.AzBlobConfig.AccountKey = kms.NewPlainSecret("Server-Account-Key-Test")
  1152. user, _, err = httpd.AddUser(user, http.StatusOK)
  1153. assert.NoError(t, err)
  1154. initialPayload = user.FsConfig.AzBlobConfig.AccountKey.GetPayload()
  1155. assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.AzBlobConfig.AccountKey.GetStatus())
  1156. assert.NotEmpty(t, initialPayload)
  1157. assert.Empty(t, user.FsConfig.AzBlobConfig.AccountKey.GetAdditionalData())
  1158. assert.Empty(t, user.FsConfig.AzBlobConfig.AccountKey.GetKey())
  1159. user.FsConfig.Provider = dataprovider.AzureBlobFilesystemProvider
  1160. user.FsConfig.AzBlobConfig.Container = "test-container"
  1161. user.FsConfig.AzBlobConfig.Endpoint = "http://localhost:9001"
  1162. user.FsConfig.AzBlobConfig.KeyPrefix = "somedir/subdir"
  1163. user.FsConfig.AzBlobConfig.UploadConcurrency = 5
  1164. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1165. assert.NoError(t, err)
  1166. assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.AzBlobConfig.AccountKey.GetStatus())
  1167. assert.NotEmpty(t, initialPayload)
  1168. assert.Equal(t, initialPayload, user.FsConfig.AzBlobConfig.AccountKey.GetPayload())
  1169. assert.Empty(t, user.FsConfig.AzBlobConfig.AccountKey.GetAdditionalData())
  1170. assert.Empty(t, user.FsConfig.AzBlobConfig.AccountKey.GetKey())
  1171. // test user without access key and access secret (sas)
  1172. user.FsConfig.Provider = dataprovider.AzureBlobFilesystemProvider
  1173. user.FsConfig.AzBlobConfig.SASURL = "https://myaccount.blob.core.windows.net/pictures/profile.jpg?sv=2012-02-12&st=2009-02-09&se=2009-02-10&sr=c&sp=r&si=YWJjZGVmZw%3d%3d&sig=dD80ihBh5jfNpymO5Hg1IdiJIEvHcJpCMiCMnN%2fRnbI%3d"
  1174. user.FsConfig.AzBlobConfig.KeyPrefix = "somedir/subdir"
  1175. user.FsConfig.AzBlobConfig.AccountName = ""
  1176. user.FsConfig.AzBlobConfig.AccountKey = kms.NewEmptySecret()
  1177. user.FsConfig.AzBlobConfig.UploadPartSize = 6
  1178. user.FsConfig.AzBlobConfig.UploadConcurrency = 4
  1179. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1180. assert.NoError(t, err)
  1181. assert.True(t, user.FsConfig.AzBlobConfig.AccountKey.IsEmpty())
  1182. _, err = httpd.RemoveUser(user, http.StatusOK)
  1183. assert.NoError(t, err)
  1184. user.Password = defaultPassword
  1185. user.ID = 0
  1186. // sas test for add instead of update
  1187. user, _, err = httpd.AddUser(user, http.StatusOK)
  1188. assert.NoError(t, err)
  1189. assert.True(t, user.FsConfig.AzBlobConfig.AccountKey.IsEmpty())
  1190. _, err = httpd.RemoveUser(user, http.StatusOK)
  1191. assert.NoError(t, err)
  1192. }
  1193. func TestUserCryptFs(t *testing.T) {
  1194. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  1195. assert.NoError(t, err)
  1196. user.FsConfig.Provider = dataprovider.CryptedFilesystemProvider
  1197. user.FsConfig.CryptConfig.Passphrase = kms.NewPlainSecret("crypt passphrase")
  1198. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1199. assert.NoError(t, err)
  1200. initialPayload := user.FsConfig.CryptConfig.Passphrase.GetPayload()
  1201. assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.CryptConfig.Passphrase.GetStatus())
  1202. assert.NotEmpty(t, initialPayload)
  1203. assert.Empty(t, user.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
  1204. assert.Empty(t, user.FsConfig.CryptConfig.Passphrase.GetKey())
  1205. user.FsConfig.CryptConfig.Passphrase.SetStatus(kms.SecretStatusSecretBox)
  1206. user.FsConfig.CryptConfig.Passphrase.SetAdditionalData("data")
  1207. user.FsConfig.CryptConfig.Passphrase.SetKey("fake pass key")
  1208. user, bb, err := httpd.UpdateUser(user, http.StatusOK, "")
  1209. assert.NoError(t, err, string(bb))
  1210. assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.CryptConfig.Passphrase.GetStatus())
  1211. assert.Equal(t, initialPayload, user.FsConfig.CryptConfig.Passphrase.GetPayload())
  1212. assert.Empty(t, user.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
  1213. assert.Empty(t, user.FsConfig.CryptConfig.Passphrase.GetKey())
  1214. _, err = httpd.RemoveUser(user, http.StatusOK)
  1215. assert.NoError(t, err)
  1216. user.Password = defaultPassword
  1217. user.ID = 0
  1218. secret := kms.NewSecret(kms.SecretStatusSecretBox, "invalid encrypted payload", "", "")
  1219. user.FsConfig.CryptConfig.Passphrase = secret
  1220. _, _, err = httpd.AddUser(user, http.StatusOK)
  1221. assert.Error(t, err)
  1222. user.FsConfig.CryptConfig.Passphrase = kms.NewPlainSecret("passphrase test")
  1223. user, _, err = httpd.AddUser(user, http.StatusOK)
  1224. assert.NoError(t, err)
  1225. initialPayload = user.FsConfig.CryptConfig.Passphrase.GetPayload()
  1226. assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.CryptConfig.Passphrase.GetStatus())
  1227. assert.NotEmpty(t, initialPayload)
  1228. assert.Empty(t, user.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
  1229. assert.Empty(t, user.FsConfig.CryptConfig.Passphrase.GetKey())
  1230. user.FsConfig.Provider = dataprovider.CryptedFilesystemProvider
  1231. user.FsConfig.CryptConfig.Passphrase.SetKey("pass")
  1232. user, bb, err = httpd.UpdateUser(user, http.StatusOK, "")
  1233. assert.NoError(t, err, string(bb))
  1234. assert.Equal(t, kms.SecretStatusSecretBox, user.FsConfig.CryptConfig.Passphrase.GetStatus())
  1235. assert.NotEmpty(t, initialPayload)
  1236. assert.Equal(t, initialPayload, user.FsConfig.CryptConfig.Passphrase.GetPayload())
  1237. assert.Empty(t, user.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
  1238. assert.Empty(t, user.FsConfig.CryptConfig.Passphrase.GetKey())
  1239. _, err = httpd.RemoveUser(user, http.StatusOK)
  1240. assert.NoError(t, err)
  1241. }
  1242. func TestUserHiddenFields(t *testing.T) {
  1243. err := dataprovider.Close()
  1244. assert.NoError(t, err)
  1245. err = config.LoadConfig(configDir, "")
  1246. assert.NoError(t, err)
  1247. providerConf := config.GetProviderConf()
  1248. providerConf.PreferDatabaseCredentials = true
  1249. err = dataprovider.Initialize(providerConf, configDir)
  1250. assert.NoError(t, err)
  1251. // sensitive data must be hidden but not deleted from the dataprovider
  1252. usernames := []string{"user1", "user2", "user3", "user4"}
  1253. u1 := getTestUser()
  1254. u1.Username = usernames[0]
  1255. u1.FsConfig.Provider = dataprovider.S3FilesystemProvider
  1256. u1.FsConfig.S3Config.Bucket = "test"
  1257. u1.FsConfig.S3Config.Region = "us-east-1"
  1258. u1.FsConfig.S3Config.AccessKey = "S3-Access-Key"
  1259. u1.FsConfig.S3Config.AccessSecret = kms.NewPlainSecret("S3-Access-Secret")
  1260. user1, _, err := httpd.AddUser(u1, http.StatusOK)
  1261. assert.NoError(t, err)
  1262. u2 := getTestUser()
  1263. u2.Username = usernames[1]
  1264. u2.FsConfig.Provider = dataprovider.GCSFilesystemProvider
  1265. u2.FsConfig.GCSConfig.Bucket = "test"
  1266. u2.FsConfig.GCSConfig.Credentials = kms.NewPlainSecret("fake credentials")
  1267. user2, _, err := httpd.AddUser(u2, http.StatusOK)
  1268. assert.NoError(t, err)
  1269. u3 := getTestUser()
  1270. u3.Username = usernames[2]
  1271. u3.FsConfig.Provider = dataprovider.AzureBlobFilesystemProvider
  1272. u3.FsConfig.AzBlobConfig.Container = "test"
  1273. u3.FsConfig.AzBlobConfig.AccountName = "Server-Account-Name"
  1274. u3.FsConfig.AzBlobConfig.AccountKey = kms.NewPlainSecret("Server-Account-Key")
  1275. user3, _, err := httpd.AddUser(u3, http.StatusOK)
  1276. assert.NoError(t, err)
  1277. u4 := getTestUser()
  1278. u4.Username = usernames[3]
  1279. u4.FsConfig.Provider = dataprovider.CryptedFilesystemProvider
  1280. u4.FsConfig.CryptConfig.Passphrase = kms.NewPlainSecret("test passphrase")
  1281. user4, _, err := httpd.AddUser(u4, http.StatusOK)
  1282. assert.NoError(t, err)
  1283. users, _, err := httpd.GetUsers(0, 0, "", http.StatusOK)
  1284. assert.NoError(t, err)
  1285. assert.GreaterOrEqual(t, len(users), 4)
  1286. for _, username := range usernames {
  1287. users, _, err = httpd.GetUsers(0, 0, username, http.StatusOK)
  1288. assert.NoError(t, err)
  1289. if assert.Len(t, users, 1) {
  1290. user := users[0]
  1291. assert.Empty(t, user.Password)
  1292. }
  1293. }
  1294. user1, _, err = httpd.GetUserByID(user1.ID, http.StatusOK)
  1295. assert.NoError(t, err)
  1296. assert.Empty(t, user1.Password)
  1297. assert.Empty(t, user1.FsConfig.S3Config.AccessSecret.GetKey())
  1298. assert.Empty(t, user1.FsConfig.S3Config.AccessSecret.GetAdditionalData())
  1299. assert.NotEmpty(t, user1.FsConfig.S3Config.AccessSecret.GetStatus())
  1300. assert.NotEmpty(t, user1.FsConfig.S3Config.AccessSecret.GetPayload())
  1301. user2, _, err = httpd.GetUserByID(user2.ID, http.StatusOK)
  1302. assert.NoError(t, err)
  1303. assert.Empty(t, user2.Password)
  1304. assert.Empty(t, user2.FsConfig.GCSConfig.Credentials.GetKey())
  1305. assert.Empty(t, user2.FsConfig.GCSConfig.Credentials.GetAdditionalData())
  1306. assert.NotEmpty(t, user2.FsConfig.GCSConfig.Credentials.GetStatus())
  1307. assert.NotEmpty(t, user2.FsConfig.GCSConfig.Credentials.GetPayload())
  1308. user3, _, err = httpd.GetUserByID(user3.ID, http.StatusOK)
  1309. assert.NoError(t, err)
  1310. assert.Empty(t, user3.Password)
  1311. assert.Empty(t, user3.FsConfig.AzBlobConfig.AccountKey.GetKey())
  1312. assert.Empty(t, user3.FsConfig.AzBlobConfig.AccountKey.GetAdditionalData())
  1313. assert.NotEmpty(t, user3.FsConfig.AzBlobConfig.AccountKey.GetStatus())
  1314. assert.NotEmpty(t, user3.FsConfig.AzBlobConfig.AccountKey.GetPayload())
  1315. user4, _, err = httpd.GetUserByID(user4.ID, http.StatusOK)
  1316. assert.NoError(t, err)
  1317. assert.Empty(t, user4.Password)
  1318. assert.Empty(t, user4.FsConfig.CryptConfig.Passphrase.GetKey())
  1319. assert.Empty(t, user4.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
  1320. assert.NotEmpty(t, user4.FsConfig.CryptConfig.Passphrase.GetStatus())
  1321. assert.NotEmpty(t, user4.FsConfig.CryptConfig.Passphrase.GetPayload())
  1322. // finally check that we have all the data inside the data provider
  1323. user1, err = dataprovider.GetUserByID(user1.ID)
  1324. assert.NoError(t, err)
  1325. assert.NotEmpty(t, user1.Password)
  1326. assert.NotEmpty(t, user1.FsConfig.S3Config.AccessSecret.GetKey())
  1327. assert.NotEmpty(t, user1.FsConfig.S3Config.AccessSecret.GetAdditionalData())
  1328. assert.NotEmpty(t, user1.FsConfig.S3Config.AccessSecret.GetStatus())
  1329. assert.NotEmpty(t, user1.FsConfig.S3Config.AccessSecret.GetPayload())
  1330. err = user1.FsConfig.S3Config.AccessSecret.Decrypt()
  1331. assert.NoError(t, err)
  1332. assert.Equal(t, kms.SecretStatusPlain, user1.FsConfig.S3Config.AccessSecret.GetStatus())
  1333. assert.Equal(t, u1.FsConfig.S3Config.AccessSecret.GetPayload(), user1.FsConfig.S3Config.AccessSecret.GetPayload())
  1334. assert.Empty(t, user1.FsConfig.S3Config.AccessSecret.GetKey())
  1335. assert.Empty(t, user1.FsConfig.S3Config.AccessSecret.GetAdditionalData())
  1336. user2, err = dataprovider.GetUserByID(user2.ID)
  1337. assert.NoError(t, err)
  1338. assert.NotEmpty(t, user2.Password)
  1339. assert.NotEmpty(t, user2.FsConfig.GCSConfig.Credentials.GetKey())
  1340. assert.NotEmpty(t, user2.FsConfig.GCSConfig.Credentials.GetAdditionalData())
  1341. assert.NotEmpty(t, user2.FsConfig.GCSConfig.Credentials.GetStatus())
  1342. assert.NotEmpty(t, user2.FsConfig.GCSConfig.Credentials.GetPayload())
  1343. err = user2.FsConfig.GCSConfig.Credentials.Decrypt()
  1344. assert.NoError(t, err)
  1345. assert.Equal(t, kms.SecretStatusPlain, user2.FsConfig.GCSConfig.Credentials.GetStatus())
  1346. assert.Equal(t, u2.FsConfig.GCSConfig.Credentials.GetPayload(), user2.FsConfig.GCSConfig.Credentials.GetPayload())
  1347. assert.Empty(t, user2.FsConfig.GCSConfig.Credentials.GetKey())
  1348. assert.Empty(t, user2.FsConfig.GCSConfig.Credentials.GetAdditionalData())
  1349. user3, err = dataprovider.GetUserByID(user3.ID)
  1350. assert.NoError(t, err)
  1351. assert.NotEmpty(t, user3.Password)
  1352. assert.NotEmpty(t, user3.FsConfig.AzBlobConfig.AccountKey.GetKey())
  1353. assert.NotEmpty(t, user3.FsConfig.AzBlobConfig.AccountKey.GetAdditionalData())
  1354. assert.NotEmpty(t, user3.FsConfig.AzBlobConfig.AccountKey.GetStatus())
  1355. assert.NotEmpty(t, user3.FsConfig.AzBlobConfig.AccountKey.GetPayload())
  1356. err = user3.FsConfig.AzBlobConfig.AccountKey.Decrypt()
  1357. assert.NoError(t, err)
  1358. assert.Equal(t, kms.SecretStatusPlain, user3.FsConfig.AzBlobConfig.AccountKey.GetStatus())
  1359. assert.Equal(t, u3.FsConfig.AzBlobConfig.AccountKey.GetPayload(), user3.FsConfig.AzBlobConfig.AccountKey.GetPayload())
  1360. assert.Empty(t, user3.FsConfig.AzBlobConfig.AccountKey.GetKey())
  1361. assert.Empty(t, user3.FsConfig.AzBlobConfig.AccountKey.GetAdditionalData())
  1362. user4, err = dataprovider.GetUserByID(user4.ID)
  1363. assert.NoError(t, err)
  1364. assert.NotEmpty(t, user4.Password)
  1365. assert.NotEmpty(t, user4.FsConfig.CryptConfig.Passphrase.GetKey())
  1366. assert.NotEmpty(t, user4.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
  1367. assert.NotEmpty(t, user4.FsConfig.CryptConfig.Passphrase.GetStatus())
  1368. assert.NotEmpty(t, user4.FsConfig.CryptConfig.Passphrase.GetPayload())
  1369. err = user4.FsConfig.CryptConfig.Passphrase.Decrypt()
  1370. assert.NoError(t, err)
  1371. assert.Equal(t, kms.SecretStatusPlain, user4.FsConfig.CryptConfig.Passphrase.GetStatus())
  1372. assert.Equal(t, u4.FsConfig.CryptConfig.Passphrase.GetPayload(), user4.FsConfig.CryptConfig.Passphrase.GetPayload())
  1373. assert.Empty(t, user4.FsConfig.CryptConfig.Passphrase.GetKey())
  1374. assert.Empty(t, user4.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
  1375. _, err = httpd.RemoveUser(user1, http.StatusOK)
  1376. assert.NoError(t, err)
  1377. _, err = httpd.RemoveUser(user2, http.StatusOK)
  1378. assert.NoError(t, err)
  1379. _, err = httpd.RemoveUser(user3, http.StatusOK)
  1380. assert.NoError(t, err)
  1381. _, err = httpd.RemoveUser(user4, http.StatusOK)
  1382. assert.NoError(t, err)
  1383. err = dataprovider.Close()
  1384. assert.NoError(t, err)
  1385. err = config.LoadConfig(configDir, "")
  1386. assert.NoError(t, err)
  1387. providerConf = config.GetProviderConf()
  1388. providerConf.CredentialsPath = credentialsPath
  1389. err = os.RemoveAll(credentialsPath)
  1390. assert.NoError(t, err)
  1391. err = dataprovider.Initialize(providerConf, configDir)
  1392. assert.NoError(t, err)
  1393. }
  1394. func TestSecretObject(t *testing.T) {
  1395. s := kms.NewPlainSecret("test data")
  1396. s.SetAdditionalData("username")
  1397. require.True(t, s.IsValid())
  1398. err := s.Encrypt()
  1399. require.NoError(t, err)
  1400. require.Equal(t, kms.SecretStatusSecretBox, s.GetStatus())
  1401. require.NotEmpty(t, s.GetPayload())
  1402. require.NotEmpty(t, s.GetKey())
  1403. require.True(t, s.IsValid())
  1404. err = s.Decrypt()
  1405. require.NoError(t, err)
  1406. require.Equal(t, kms.SecretStatusPlain, s.GetStatus())
  1407. require.Equal(t, "test data", s.GetPayload())
  1408. require.Empty(t, s.GetKey())
  1409. oldFormat := "$aes$5b97e3a3324a2f53e2357483383367c0$0ed3132b584742ab217866219da633266782b69b13e50ebc6ddfb7c4fbf2f2a414c6d5f813"
  1410. s, err = kms.GetSecretFromCompatString(oldFormat)
  1411. require.NoError(t, err)
  1412. require.True(t, s.IsValid())
  1413. require.Equal(t, kms.SecretStatusPlain, s.GetStatus())
  1414. require.Equal(t, "test data", s.GetPayload())
  1415. require.Empty(t, s.GetKey())
  1416. }
  1417. func TestSecretObjectCompatibility(t *testing.T) {
  1418. // this is manually tested against vault too
  1419. testPayload := "test payload"
  1420. s := kms.NewPlainSecret(testPayload)
  1421. require.True(t, s.IsValid())
  1422. err := s.Encrypt()
  1423. require.NoError(t, err)
  1424. localAsJSON, err := json.Marshal(s)
  1425. assert.NoError(t, err)
  1426. for _, secretStatus := range []string{kms.SecretStatusSecretBox} {
  1427. kmsConfig := config.GetKMSConfig()
  1428. assert.Empty(t, kmsConfig.Secrets.MasterKeyPath)
  1429. if secretStatus == kms.SecretStatusVaultTransit {
  1430. os.Setenv("VAULT_SERVER_URL", "http://127.0.0.1:8200")
  1431. os.Setenv("VAULT_SERVER_TOKEN", "s.9lYGq83MbgG5KR5kfebXVyhJ")
  1432. kmsConfig.Secrets.URL = "hashivault://mykey"
  1433. }
  1434. err := kmsConfig.Initialize()
  1435. assert.NoError(t, err)
  1436. // encrypt without a master key
  1437. secret := kms.NewPlainSecret(testPayload)
  1438. secret.SetAdditionalData("add data")
  1439. err = secret.Encrypt()
  1440. assert.NoError(t, err)
  1441. assert.Equal(t, 0, secret.GetMode())
  1442. secretClone := secret.Clone()
  1443. err = secretClone.Decrypt()
  1444. assert.NoError(t, err)
  1445. assert.Equal(t, testPayload, secretClone.GetPayload())
  1446. if secretStatus == kms.SecretStatusVaultTransit {
  1447. // decrypt the local secret now that the provider is vault
  1448. secretLocal := kms.NewEmptySecret()
  1449. err = json.Unmarshal(localAsJSON, secretLocal)
  1450. assert.NoError(t, err)
  1451. assert.Equal(t, kms.SecretStatusSecretBox, secretLocal.GetStatus())
  1452. assert.Equal(t, 0, secretLocal.GetMode())
  1453. err = secretLocal.Decrypt()
  1454. assert.NoError(t, err)
  1455. assert.Equal(t, testPayload, secretLocal.GetPayload())
  1456. assert.Equal(t, kms.SecretStatusPlain, secretLocal.GetStatus())
  1457. err = secretLocal.Encrypt()
  1458. assert.NoError(t, err)
  1459. assert.Equal(t, kms.SecretStatusSecretBox, secretLocal.GetStatus())
  1460. assert.Equal(t, 0, secretLocal.GetMode())
  1461. }
  1462. asJSON, err := json.Marshal(secret)
  1463. assert.NoError(t, err)
  1464. masterKeyPath := filepath.Join(os.TempDir(), "mkey")
  1465. err = ioutil.WriteFile(masterKeyPath, []byte("test key"), os.ModePerm)
  1466. assert.NoError(t, err)
  1467. config := kms.Configuration{
  1468. Secrets: kms.Secrets{
  1469. MasterKeyPath: masterKeyPath,
  1470. },
  1471. }
  1472. if secretStatus == kms.SecretStatusVaultTransit {
  1473. config.Secrets.URL = "hashivault://mykey"
  1474. }
  1475. err = config.Initialize()
  1476. assert.NoError(t, err)
  1477. // now build the secret from JSON
  1478. secret = kms.NewEmptySecret()
  1479. err = json.Unmarshal(asJSON, secret)
  1480. assert.NoError(t, err)
  1481. assert.Equal(t, 0, secret.GetMode())
  1482. err = secret.Decrypt()
  1483. assert.NoError(t, err)
  1484. assert.Equal(t, testPayload, secret.GetPayload())
  1485. err = secret.Encrypt()
  1486. assert.NoError(t, err)
  1487. assert.Equal(t, 1, secret.GetMode())
  1488. err = secret.Decrypt()
  1489. assert.NoError(t, err)
  1490. assert.Equal(t, testPayload, secret.GetPayload())
  1491. if secretStatus == kms.SecretStatusVaultTransit {
  1492. // decrypt the local secret encryped without a master key now that
  1493. // the provider is vault and a master key is set.
  1494. // The provider will not change, the master key will be used
  1495. secretLocal := kms.NewEmptySecret()
  1496. err = json.Unmarshal(localAsJSON, secretLocal)
  1497. assert.NoError(t, err)
  1498. assert.Equal(t, kms.SecretStatusSecretBox, secretLocal.GetStatus())
  1499. assert.Equal(t, 0, secretLocal.GetMode())
  1500. err = secretLocal.Decrypt()
  1501. assert.NoError(t, err)
  1502. assert.Equal(t, testPayload, secretLocal.GetPayload())
  1503. assert.Equal(t, kms.SecretStatusPlain, secretLocal.GetStatus())
  1504. err = secretLocal.Encrypt()
  1505. assert.NoError(t, err)
  1506. assert.Equal(t, kms.SecretStatusSecretBox, secretLocal.GetStatus())
  1507. assert.Equal(t, 1, secretLocal.GetMode())
  1508. }
  1509. err = kmsConfig.Initialize()
  1510. assert.NoError(t, err)
  1511. err = os.Remove(masterKeyPath)
  1512. assert.NoError(t, err)
  1513. if secretStatus == kms.SecretStatusVaultTransit {
  1514. os.Unsetenv("VAULT_SERVER_URL")
  1515. os.Unsetenv("VAULT_SERVER_TOKEN")
  1516. }
  1517. }
  1518. }
  1519. func TestUpdateUserNoCredentials(t *testing.T) {
  1520. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  1521. assert.NoError(t, err)
  1522. user.Password = ""
  1523. user.PublicKeys = []string{}
  1524. // password and public key will be omitted from json serialization if empty and so they will remain unchanged
  1525. // and no validation error will be raised
  1526. _, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  1527. assert.NoError(t, err)
  1528. _, err = httpd.RemoveUser(user, http.StatusOK)
  1529. assert.NoError(t, err)
  1530. }
  1531. func TestUpdateUserEmptyHomeDir(t *testing.T) {
  1532. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  1533. assert.NoError(t, err)
  1534. user.HomeDir = ""
  1535. _, _, err = httpd.UpdateUser(user, http.StatusBadRequest, "")
  1536. assert.NoError(t, err)
  1537. _, err = httpd.RemoveUser(user, http.StatusOK)
  1538. assert.NoError(t, err)
  1539. }
  1540. func TestUpdateUserInvalidHomeDir(t *testing.T) {
  1541. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  1542. assert.NoError(t, err)
  1543. user.HomeDir = "relative_path"
  1544. _, _, err = httpd.UpdateUser(user, http.StatusBadRequest, "")
  1545. assert.NoError(t, err)
  1546. _, err = httpd.RemoveUser(user, http.StatusOK)
  1547. assert.NoError(t, err)
  1548. }
  1549. func TestUpdateNonExistentUser(t *testing.T) {
  1550. _, _, err := httpd.UpdateUser(getTestUser(), http.StatusNotFound, "")
  1551. assert.NoError(t, err)
  1552. }
  1553. func TestGetNonExistentUser(t *testing.T) {
  1554. _, _, err := httpd.GetUserByID(0, http.StatusNotFound)
  1555. assert.NoError(t, err)
  1556. }
  1557. func TestDeleteNonExistentUser(t *testing.T) {
  1558. _, err := httpd.RemoveUser(getTestUser(), http.StatusNotFound)
  1559. assert.NoError(t, err)
  1560. }
  1561. func TestAddDuplicateUser(t *testing.T) {
  1562. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  1563. assert.NoError(t, err)
  1564. _, _, err = httpd.AddUser(getTestUser(), http.StatusInternalServerError)
  1565. assert.NoError(t, err)
  1566. _, _, err = httpd.AddUser(getTestUser(), http.StatusOK)
  1567. assert.Error(t, err, "adding a duplicate user must fail")
  1568. _, err = httpd.RemoveUser(user, http.StatusOK)
  1569. assert.NoError(t, err)
  1570. }
  1571. func TestGetUsers(t *testing.T) {
  1572. user1, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  1573. assert.NoError(t, err)
  1574. u := getTestUser()
  1575. u.Username = defaultUsername + "1"
  1576. user2, _, err := httpd.AddUser(u, http.StatusOK)
  1577. assert.NoError(t, err)
  1578. users, _, err := httpd.GetUsers(0, 0, "", http.StatusOK)
  1579. assert.NoError(t, err)
  1580. assert.GreaterOrEqual(t, len(users), 2)
  1581. users, _, err = httpd.GetUsers(1, 0, "", http.StatusOK)
  1582. assert.NoError(t, err)
  1583. assert.Equal(t, 1, len(users))
  1584. users, _, err = httpd.GetUsers(1, 1, "", http.StatusOK)
  1585. assert.NoError(t, err)
  1586. assert.Equal(t, 1, len(users))
  1587. _, _, err = httpd.GetUsers(1, 1, "", http.StatusInternalServerError)
  1588. assert.Error(t, err)
  1589. _, err = httpd.RemoveUser(user1, http.StatusOK)
  1590. assert.NoError(t, err)
  1591. _, err = httpd.RemoveUser(user2, http.StatusOK)
  1592. assert.NoError(t, err)
  1593. }
  1594. func TestGetQuotaScans(t *testing.T) {
  1595. _, _, err := httpd.GetQuotaScans(http.StatusOK)
  1596. assert.NoError(t, err)
  1597. _, _, err = httpd.GetQuotaScans(http.StatusInternalServerError)
  1598. assert.Error(t, err)
  1599. _, _, err = httpd.GetFoldersQuotaScans(http.StatusOK)
  1600. assert.NoError(t, err)
  1601. _, _, err = httpd.GetFoldersQuotaScans(http.StatusInternalServerError)
  1602. assert.Error(t, err)
  1603. }
  1604. func TestStartQuotaScan(t *testing.T) {
  1605. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  1606. assert.NoError(t, err)
  1607. _, err = httpd.StartQuotaScan(user, http.StatusAccepted)
  1608. assert.NoError(t, err)
  1609. _, err = httpd.RemoveUser(user, http.StatusOK)
  1610. assert.NoError(t, err)
  1611. folder := vfs.BaseVirtualFolder{
  1612. MappedPath: filepath.Join(os.TempDir(), "folder"),
  1613. }
  1614. _, _, err = httpd.AddFolder(folder, http.StatusOK)
  1615. assert.NoError(t, err)
  1616. _, err = httpd.StartFolderQuotaScan(folder, http.StatusAccepted)
  1617. assert.NoError(t, err)
  1618. for {
  1619. quotaScan, _, err := httpd.GetFoldersQuotaScans(http.StatusOK)
  1620. if !assert.NoError(t, err, "Error getting active scans") {
  1621. break
  1622. }
  1623. if len(quotaScan) == 0 {
  1624. break
  1625. }
  1626. time.Sleep(100 * time.Millisecond)
  1627. }
  1628. _, err = httpd.RemoveFolder(folder, http.StatusOK)
  1629. assert.NoError(t, err)
  1630. }
  1631. func TestUpdateFolderQuotaUsage(t *testing.T) {
  1632. f := vfs.BaseVirtualFolder{
  1633. MappedPath: filepath.Join(os.TempDir(), "folder"),
  1634. }
  1635. usedQuotaFiles := 1
  1636. usedQuotaSize := int64(65535)
  1637. f.UsedQuotaFiles = usedQuotaFiles
  1638. f.UsedQuotaSize = usedQuotaSize
  1639. folder, _, err := httpd.AddFolder(f, http.StatusOK)
  1640. if assert.NoError(t, err) {
  1641. assert.Equal(t, usedQuotaFiles, folder.UsedQuotaFiles)
  1642. assert.Equal(t, usedQuotaSize, folder.UsedQuotaSize)
  1643. }
  1644. _, err = httpd.UpdateFolderQuotaUsage(folder, "invalid mode", http.StatusBadRequest)
  1645. assert.NoError(t, err)
  1646. _, err = httpd.UpdateFolderQuotaUsage(f, "reset", http.StatusOK)
  1647. assert.NoError(t, err)
  1648. folders, _, err := httpd.GetFolders(0, 0, f.MappedPath, http.StatusOK)
  1649. assert.NoError(t, err)
  1650. if assert.Len(t, folders, 1) {
  1651. folder = folders[0]
  1652. assert.Equal(t, usedQuotaFiles, folder.UsedQuotaFiles)
  1653. assert.Equal(t, usedQuotaSize, folder.UsedQuotaSize)
  1654. }
  1655. _, err = httpd.UpdateFolderQuotaUsage(f, "add", http.StatusOK)
  1656. assert.NoError(t, err)
  1657. folders, _, err = httpd.GetFolders(0, 0, f.MappedPath, http.StatusOK)
  1658. assert.NoError(t, err)
  1659. if assert.Len(t, folders, 1) {
  1660. folder = folders[0]
  1661. assert.Equal(t, 2*usedQuotaFiles, folder.UsedQuotaFiles)
  1662. assert.Equal(t, 2*usedQuotaSize, folder.UsedQuotaSize)
  1663. }
  1664. f.UsedQuotaSize = -1
  1665. _, err = httpd.UpdateFolderQuotaUsage(f, "", http.StatusBadRequest)
  1666. assert.NoError(t, err)
  1667. f.UsedQuotaSize = usedQuotaSize
  1668. f.MappedPath = f.MappedPath + "1"
  1669. _, err = httpd.UpdateFolderQuotaUsage(f, "", http.StatusNotFound)
  1670. assert.NoError(t, err)
  1671. _, err = httpd.RemoveFolder(folder, http.StatusOK)
  1672. assert.NoError(t, err)
  1673. }
  1674. func TestGetVersion(t *testing.T) {
  1675. _, _, err := httpd.GetVersion(http.StatusOK)
  1676. assert.NoError(t, err)
  1677. _, _, err = httpd.GetVersion(http.StatusInternalServerError)
  1678. assert.Error(t, err, "get version request must succeed, we requested to check a wrong status code")
  1679. }
  1680. func TestGetProviderStatus(t *testing.T) {
  1681. _, _, err := httpd.GetProviderStatus(http.StatusOK)
  1682. assert.NoError(t, err)
  1683. _, _, err = httpd.GetProviderStatus(http.StatusBadRequest)
  1684. assert.Error(t, err, "get provider status request must succeed, we requested to check a wrong status code")
  1685. }
  1686. func TestGetConnections(t *testing.T) {
  1687. _, _, err := httpd.GetConnections(http.StatusOK)
  1688. assert.NoError(t, err)
  1689. _, _, err = httpd.GetConnections(http.StatusInternalServerError)
  1690. assert.Error(t, err, "get sftp connections request must succeed, we requested to check a wrong status code")
  1691. }
  1692. func TestCloseActiveConnection(t *testing.T) {
  1693. _, err := httpd.CloseConnection("non_existent_id", http.StatusNotFound)
  1694. assert.NoError(t, err)
  1695. user := getTestUser()
  1696. c := common.NewBaseConnection("connID", common.ProtocolSFTP, user, nil)
  1697. fakeConn := &fakeConnection{
  1698. BaseConnection: c,
  1699. }
  1700. common.Connections.Add(fakeConn)
  1701. _, err = httpd.CloseConnection(c.GetID(), http.StatusOK)
  1702. assert.NoError(t, err)
  1703. assert.Len(t, common.Connections.GetStats(), 0)
  1704. }
  1705. func TestCloseConnectionAfterUserUpdateDelete(t *testing.T) {
  1706. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  1707. assert.NoError(t, err)
  1708. c := common.NewBaseConnection("connID", common.ProtocolFTP, user, nil)
  1709. fakeConn := &fakeConnection{
  1710. BaseConnection: c,
  1711. }
  1712. common.Connections.Add(fakeConn)
  1713. c1 := common.NewBaseConnection("connID1", common.ProtocolSFTP, user, nil)
  1714. fakeConn1 := &fakeConnection{
  1715. BaseConnection: c1,
  1716. }
  1717. common.Connections.Add(fakeConn1)
  1718. user, _, err = httpd.UpdateUser(user, http.StatusOK, "0")
  1719. assert.NoError(t, err)
  1720. assert.Len(t, common.Connections.GetStats(), 2)
  1721. user, _, err = httpd.UpdateUser(user, http.StatusOK, "1")
  1722. assert.NoError(t, err)
  1723. assert.Len(t, common.Connections.GetStats(), 0)
  1724. common.Connections.Add(fakeConn)
  1725. common.Connections.Add(fakeConn1)
  1726. assert.Len(t, common.Connections.GetStats(), 2)
  1727. _, err = httpd.RemoveUser(user, http.StatusOK)
  1728. assert.NoError(t, err)
  1729. assert.Len(t, common.Connections.GetStats(), 0)
  1730. }
  1731. func TestUserBaseDir(t *testing.T) {
  1732. err := dataprovider.Close()
  1733. assert.NoError(t, err)
  1734. err = config.LoadConfig(configDir, "")
  1735. assert.NoError(t, err)
  1736. providerConf := config.GetProviderConf()
  1737. providerConf.UsersBaseDir = homeBasePath
  1738. err = dataprovider.Initialize(providerConf, configDir)
  1739. assert.NoError(t, err)
  1740. u := getTestUser()
  1741. u.HomeDir = ""
  1742. user, _, err := httpd.AddUser(u, http.StatusOK)
  1743. if assert.Error(t, err) {
  1744. assert.EqualError(t, err, "HomeDir mismatch")
  1745. }
  1746. assert.Equal(t, filepath.Join(providerConf.UsersBaseDir, u.Username), user.HomeDir)
  1747. _, err = httpd.RemoveUser(user, http.StatusOK)
  1748. assert.NoError(t, err)
  1749. err = dataprovider.Close()
  1750. assert.NoError(t, err)
  1751. err = config.LoadConfig(configDir, "")
  1752. assert.NoError(t, err)
  1753. providerConf = config.GetProviderConf()
  1754. providerConf.CredentialsPath = credentialsPath
  1755. err = os.RemoveAll(credentialsPath)
  1756. assert.NoError(t, err)
  1757. err = dataprovider.Initialize(providerConf, configDir)
  1758. assert.NoError(t, err)
  1759. }
  1760. func TestQuotaTrackingDisabled(t *testing.T) {
  1761. err := dataprovider.Close()
  1762. assert.NoError(t, err)
  1763. err = config.LoadConfig(configDir, "")
  1764. assert.NoError(t, err)
  1765. providerConf := config.GetProviderConf()
  1766. providerConf.TrackQuota = 0
  1767. err = dataprovider.Initialize(providerConf, configDir)
  1768. assert.NoError(t, err)
  1769. // user quota scan must fail
  1770. user, _, err := httpd.AddUser(getTestUser(), http.StatusOK)
  1771. assert.NoError(t, err)
  1772. _, err = httpd.StartQuotaScan(user, http.StatusForbidden)
  1773. assert.NoError(t, err)
  1774. _, err = httpd.UpdateQuotaUsage(user, "", http.StatusForbidden)
  1775. assert.NoError(t, err)
  1776. _, err = httpd.RemoveUser(user, http.StatusOK)
  1777. assert.NoError(t, err)
  1778. // folder quota scan must fail
  1779. folder := vfs.BaseVirtualFolder{
  1780. MappedPath: filepath.Clean(os.TempDir()),
  1781. }
  1782. folder, _, err = httpd.AddFolder(folder, http.StatusOK)
  1783. assert.NoError(t, err)
  1784. _, err = httpd.StartFolderQuotaScan(folder, http.StatusForbidden)
  1785. assert.NoError(t, err)
  1786. _, err = httpd.UpdateFolderQuotaUsage(folder, "", http.StatusForbidden)
  1787. assert.NoError(t, err)
  1788. _, err = httpd.RemoveFolder(folder, http.StatusOK)
  1789. assert.NoError(t, err)
  1790. err = dataprovider.Close()
  1791. assert.NoError(t, err)
  1792. err = config.LoadConfig(configDir, "")
  1793. assert.NoError(t, err)
  1794. providerConf = config.GetProviderConf()
  1795. providerConf.CredentialsPath = credentialsPath
  1796. err = os.RemoveAll(credentialsPath)
  1797. assert.NoError(t, err)
  1798. err = dataprovider.Initialize(providerConf, configDir)
  1799. assert.NoError(t, err)
  1800. }
  1801. func TestProviderErrors(t *testing.T) {
  1802. err := dataprovider.Close()
  1803. assert.NoError(t, err)
  1804. _, _, err = httpd.GetUserByID(0, http.StatusInternalServerError)
  1805. assert.NoError(t, err)
  1806. _, _, err = httpd.GetUsers(1, 0, defaultUsername, http.StatusInternalServerError)
  1807. assert.NoError(t, err)
  1808. _, _, err = httpd.UpdateUser(dataprovider.User{}, http.StatusInternalServerError, "")
  1809. assert.NoError(t, err)
  1810. _, err = httpd.RemoveUser(dataprovider.User{}, http.StatusInternalServerError)
  1811. assert.NoError(t, err)
  1812. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{MappedPath: "apath"}, http.StatusInternalServerError)
  1813. assert.NoError(t, err)
  1814. _, _, err = httpd.GetProviderStatus(http.StatusInternalServerError)
  1815. assert.NoError(t, err)
  1816. _, _, err = httpd.Dumpdata("backup.json", "", http.StatusInternalServerError)
  1817. assert.NoError(t, err)
  1818. _, _, err = httpd.GetFolders(0, 0, "", http.StatusInternalServerError)
  1819. assert.NoError(t, err)
  1820. user := getTestUser()
  1821. user.ID = 1
  1822. backupData := dataprovider.BackupData{}
  1823. backupData.Users = append(backupData.Users, user)
  1824. backupContent, err := json.Marshal(backupData)
  1825. assert.NoError(t, err)
  1826. backupFilePath := filepath.Join(backupsPath, "backup.json")
  1827. err = ioutil.WriteFile(backupFilePath, backupContent, os.ModePerm)
  1828. assert.NoError(t, err)
  1829. _, _, err = httpd.Loaddata(backupFilePath, "", "", http.StatusInternalServerError)
  1830. assert.NoError(t, err)
  1831. backupData.Folders = append(backupData.Folders, vfs.BaseVirtualFolder{MappedPath: os.TempDir()})
  1832. backupContent, err = json.Marshal(backupData)
  1833. assert.NoError(t, err)
  1834. err = ioutil.WriteFile(backupFilePath, backupContent, os.ModePerm)
  1835. assert.NoError(t, err)
  1836. _, _, err = httpd.Loaddata(backupFilePath, "", "", http.StatusInternalServerError)
  1837. assert.NoError(t, err)
  1838. err = os.Remove(backupFilePath)
  1839. assert.NoError(t, err)
  1840. err = config.LoadConfig(configDir, "")
  1841. assert.NoError(t, err)
  1842. providerConf := config.GetProviderConf()
  1843. providerConf.CredentialsPath = credentialsPath
  1844. err = os.RemoveAll(credentialsPath)
  1845. assert.NoError(t, err)
  1846. err = dataprovider.Initialize(providerConf, configDir)
  1847. assert.NoError(t, err)
  1848. }
  1849. func TestFolders(t *testing.T) {
  1850. folder := vfs.BaseVirtualFolder{
  1851. MappedPath: "relative path",
  1852. }
  1853. _, _, err := httpd.AddFolder(folder, http.StatusBadRequest)
  1854. assert.NoError(t, err)
  1855. folder.MappedPath = filepath.Clean(os.TempDir())
  1856. folder1, _, err := httpd.AddFolder(folder, http.StatusOK)
  1857. assert.NoError(t, err)
  1858. assert.Equal(t, folder.MappedPath, folder1.MappedPath)
  1859. assert.Equal(t, 0, folder1.UsedQuotaFiles)
  1860. assert.Equal(t, int64(0), folder1.UsedQuotaSize)
  1861. assert.Equal(t, int64(0), folder1.LastQuotaUpdate)
  1862. // adding a duplicate folder must fail
  1863. _, _, err = httpd.AddFolder(folder, http.StatusOK)
  1864. assert.Error(t, err)
  1865. folder.MappedPath = filepath.Join(os.TempDir(), "vfolder")
  1866. folder.UsedQuotaFiles = 1
  1867. folder.UsedQuotaSize = 345
  1868. folder.LastQuotaUpdate = 10
  1869. folder2, _, err := httpd.AddFolder(folder, http.StatusOK)
  1870. assert.NoError(t, err)
  1871. assert.Equal(t, 1, folder2.UsedQuotaFiles)
  1872. assert.Equal(t, int64(345), folder2.UsedQuotaSize)
  1873. assert.Equal(t, int64(10), folder2.LastQuotaUpdate)
  1874. folders, _, err := httpd.GetFolders(0, 0, "", http.StatusOK)
  1875. assert.NoError(t, err)
  1876. numResults := len(folders)
  1877. assert.GreaterOrEqual(t, numResults, 2)
  1878. folders, _, err = httpd.GetFolders(0, 1, "", http.StatusOK)
  1879. assert.NoError(t, err)
  1880. assert.Len(t, folders, numResults-1)
  1881. folders, _, err = httpd.GetFolders(1, 0, "", http.StatusOK)
  1882. assert.NoError(t, err)
  1883. assert.Len(t, folders, 1)
  1884. folders, _, err = httpd.GetFolders(0, 0, folder1.MappedPath, http.StatusOK)
  1885. assert.NoError(t, err)
  1886. if assert.Len(t, folders, 1) {
  1887. f := folders[0]
  1888. assert.Equal(t, folder1.MappedPath, f.MappedPath)
  1889. }
  1890. folders, _, err = httpd.GetFolders(0, 0, folder2.MappedPath, http.StatusOK)
  1891. assert.NoError(t, err)
  1892. if assert.Len(t, folders, 1) {
  1893. f := folders[0]
  1894. assert.Equal(t, folder2.MappedPath, f.MappedPath)
  1895. }
  1896. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{}, http.StatusBadRequest)
  1897. assert.NoError(t, err)
  1898. _, err = httpd.RemoveFolder(vfs.BaseVirtualFolder{
  1899. MappedPath: "invalid",
  1900. }, http.StatusNotFound)
  1901. assert.NoError(t, err)
  1902. _, err = httpd.RemoveFolder(folder1, http.StatusOK)
  1903. assert.NoError(t, err)
  1904. _, err = httpd.RemoveFolder(folder2, http.StatusOK)
  1905. assert.NoError(t, err)
  1906. }
  1907. func TestDumpdata(t *testing.T) {
  1908. err := dataprovider.Close()
  1909. assert.NoError(t, err)
  1910. err = config.LoadConfig(configDir, "")
  1911. assert.NoError(t, err)
  1912. providerConf := config.GetProviderConf()
  1913. err = dataprovider.Initialize(providerConf, configDir)
  1914. assert.NoError(t, err)
  1915. _, _, err = httpd.Dumpdata("", "", http.StatusBadRequest)
  1916. assert.NoError(t, err)
  1917. _, _, err = httpd.Dumpdata(filepath.Join(backupsPath, "backup.json"), "", http.StatusBadRequest)
  1918. assert.NoError(t, err)
  1919. _, _, err = httpd.Dumpdata("../backup.json", "", http.StatusBadRequest)
  1920. assert.NoError(t, err)
  1921. _, _, err = httpd.Dumpdata("backup.json", "0", http.StatusOK)
  1922. assert.NoError(t, err)
  1923. _, _, err = httpd.Dumpdata("backup.json", "1", http.StatusOK)
  1924. assert.NoError(t, err)
  1925. err = os.Remove(filepath.Join(backupsPath, "backup.json"))
  1926. assert.NoError(t, err)
  1927. if runtime.GOOS != "windows" {
  1928. err = os.Chmod(backupsPath, 0001)
  1929. assert.NoError(t, err)
  1930. _, _, err = httpd.Dumpdata("bck.json", "", http.StatusInternalServerError)
  1931. assert.NoError(t, err)
  1932. // subdir cannot be created
  1933. _, _, err = httpd.Dumpdata(filepath.Join("subdir", "bck.json"), "", http.StatusInternalServerError)
  1934. assert.NoError(t, err)
  1935. err = os.Chmod(backupsPath, 0755)
  1936. assert.NoError(t, err)
  1937. }
  1938. err = dataprovider.Close()
  1939. assert.NoError(t, err)
  1940. err = config.LoadConfig(configDir, "")
  1941. assert.NoError(t, err)
  1942. providerConf = config.GetProviderConf()
  1943. providerConf.CredentialsPath = credentialsPath
  1944. err = os.RemoveAll(credentialsPath)
  1945. assert.NoError(t, err)
  1946. err = dataprovider.Initialize(providerConf, configDir)
  1947. assert.NoError(t, err)
  1948. }
  1949. func TestLoaddata(t *testing.T) {
  1950. mappedPath := filepath.Join(os.TempDir(), "restored_folder")
  1951. user := getTestUser()
  1952. user.ID = 1
  1953. user.Username = "test_user_restore"
  1954. backupData := dataprovider.BackupData{}
  1955. backupData.Users = append(backupData.Users, user)
  1956. backupData.Folders = []vfs.BaseVirtualFolder{
  1957. {
  1958. MappedPath: mappedPath,
  1959. UsedQuotaSize: 123,
  1960. UsedQuotaFiles: 456,
  1961. LastQuotaUpdate: 789,
  1962. Users: []string{"user"},
  1963. },
  1964. {
  1965. MappedPath: mappedPath,
  1966. },
  1967. }
  1968. backupContent, err := json.Marshal(backupData)
  1969. assert.NoError(t, err)
  1970. backupFilePath := filepath.Join(backupsPath, "backup.json")
  1971. err = ioutil.WriteFile(backupFilePath, backupContent, os.ModePerm)
  1972. assert.NoError(t, err)
  1973. _, _, err = httpd.Loaddata(backupFilePath, "a", "", http.StatusBadRequest)
  1974. assert.NoError(t, err)
  1975. _, _, err = httpd.Loaddata(backupFilePath, "", "a", http.StatusBadRequest)
  1976. assert.NoError(t, err)
  1977. _, _, err = httpd.Loaddata("backup.json", "1", "", http.StatusBadRequest)
  1978. assert.NoError(t, err)
  1979. _, _, err = httpd.Loaddata(backupFilePath+"a", "1", "", http.StatusBadRequest)
  1980. assert.NoError(t, err)
  1981. if runtime.GOOS != "windows" {
  1982. err = os.Chmod(backupFilePath, 0111)
  1983. assert.NoError(t, err)
  1984. _, _, err = httpd.Loaddata(backupFilePath, "1", "", http.StatusInternalServerError)
  1985. assert.NoError(t, err)
  1986. err = os.Chmod(backupFilePath, 0644)
  1987. assert.NoError(t, err)
  1988. }
  1989. // add user and folder from backup
  1990. _, _, err = httpd.Loaddata(backupFilePath, "1", "", http.StatusOK)
  1991. assert.NoError(t, err)
  1992. // update user from backup
  1993. _, _, err = httpd.Loaddata(backupFilePath, "2", "", http.StatusOK)
  1994. assert.NoError(t, err)
  1995. users, _, err := httpd.GetUsers(1, 0, user.Username, http.StatusOK)
  1996. assert.NoError(t, err)
  1997. if assert.Len(t, users, 1) {
  1998. user = users[0]
  1999. _, err = httpd.RemoveUser(user, http.StatusOK)
  2000. assert.NoError(t, err)
  2001. }
  2002. folders, _, err := httpd.GetFolders(1, 0, mappedPath, http.StatusOK)
  2003. assert.NoError(t, err)
  2004. if assert.Len(t, folders, 1) {
  2005. folder := folders[0]
  2006. assert.Equal(t, mappedPath, folder.MappedPath)
  2007. assert.Equal(t, int64(123), folder.UsedQuotaSize)
  2008. assert.Equal(t, 456, folder.UsedQuotaFiles)
  2009. assert.Equal(t, int64(789), folder.LastQuotaUpdate)
  2010. assert.Len(t, folder.Users, 0)
  2011. _, err = httpd.RemoveFolder(folder, http.StatusOK)
  2012. assert.NoError(t, err)
  2013. }
  2014. err = os.Remove(backupFilePath)
  2015. assert.NoError(t, err)
  2016. err = createTestFile(backupFilePath, 10485761)
  2017. assert.NoError(t, err)
  2018. _, _, err = httpd.Loaddata(backupFilePath, "1", "0", http.StatusBadRequest)
  2019. assert.NoError(t, err)
  2020. err = os.Remove(backupFilePath)
  2021. assert.NoError(t, err)
  2022. err = createTestFile(backupFilePath, 65535)
  2023. assert.NoError(t, err)
  2024. _, _, err = httpd.Loaddata(backupFilePath, "1", "0", http.StatusBadRequest)
  2025. assert.NoError(t, err)
  2026. err = os.Remove(backupFilePath)
  2027. assert.NoError(t, err)
  2028. }
  2029. func TestLoaddataMode(t *testing.T) {
  2030. user := getTestUser()
  2031. user.ID = 1
  2032. user.Username = "test_user_restore"
  2033. backupData := dataprovider.BackupData{}
  2034. backupData.Users = append(backupData.Users, user)
  2035. backupContent, _ := json.Marshal(backupData)
  2036. backupFilePath := filepath.Join(backupsPath, "backup.json")
  2037. err := ioutil.WriteFile(backupFilePath, backupContent, os.ModePerm)
  2038. assert.NoError(t, err)
  2039. _, _, err = httpd.Loaddata(backupFilePath, "0", "0", http.StatusOK)
  2040. assert.NoError(t, err)
  2041. users, _, err := httpd.GetUsers(1, 0, user.Username, http.StatusOK)
  2042. assert.NoError(t, err)
  2043. assert.Equal(t, 1, len(users))
  2044. user = users[0]
  2045. oldUploadBandwidth := user.UploadBandwidth
  2046. user.UploadBandwidth = oldUploadBandwidth + 128
  2047. user, _, err = httpd.UpdateUser(user, http.StatusOK, "")
  2048. assert.NoError(t, err)
  2049. _, _, err = httpd.Loaddata(backupFilePath, "0", "1", http.StatusOK)
  2050. assert.NoError(t, err)
  2051. c := common.NewBaseConnection("connID", common.ProtocolFTP, user, nil)
  2052. fakeConn := &fakeConnection{
  2053. BaseConnection: c,
  2054. }
  2055. common.Connections.Add(fakeConn)
  2056. assert.Len(t, common.Connections.GetStats(), 1)
  2057. users, _, err = httpd.GetUsers(1, 0, user.Username, http.StatusOK)
  2058. assert.NoError(t, err)
  2059. assert.Equal(t, 1, len(users))
  2060. user = users[0]
  2061. assert.NotEqual(t, oldUploadBandwidth, user.UploadBandwidth)
  2062. _, _, err = httpd.Loaddata(backupFilePath, "0", "2", http.StatusOK)
  2063. assert.NoError(t, err)
  2064. // mode 2 will update the user and close the previous connection
  2065. assert.Len(t, common.Connections.GetStats(), 0)
  2066. users, _, err = httpd.GetUsers(1, 0, user.Username, http.StatusOK)
  2067. assert.NoError(t, err)
  2068. assert.Equal(t, 1, len(users))
  2069. user = users[0]
  2070. assert.Equal(t, oldUploadBandwidth, user.UploadBandwidth)
  2071. _, err = httpd.RemoveUser(user, http.StatusOK)
  2072. assert.NoError(t, err)
  2073. err = os.Remove(backupFilePath)
  2074. assert.NoError(t, err)
  2075. }
  2076. func TestHTTPSConnection(t *testing.T) {
  2077. client := &http.Client{
  2078. Timeout: 5 * time.Second,
  2079. }
  2080. resp, err := client.Get("https://localhost:8443" + metricsPath)
  2081. if assert.Error(t, err) {
  2082. if !strings.Contains(err.Error(), "certificate is not valid") &&
  2083. !strings.Contains(err.Error(), "certificate signed by unknown authority") {
  2084. assert.Fail(t, err.Error())
  2085. }
  2086. } else {
  2087. resp.Body.Close()
  2088. }
  2089. }
  2090. // test using mock http server
  2091. func TestBasicUserHandlingMock(t *testing.T) {
  2092. user := getTestUser()
  2093. userAsJSON := getUserAsJSON(t, user)
  2094. req, err := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  2095. assert.NoError(t, err)
  2096. rr := executeRequest(req)
  2097. checkResponseCode(t, http.StatusOK, rr.Code)
  2098. err = render.DecodeJSON(rr.Body, &user)
  2099. assert.NoError(t, err)
  2100. req, _ = http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  2101. rr = executeRequest(req)
  2102. checkResponseCode(t, http.StatusInternalServerError, rr.Code)
  2103. user.MaxSessions = 10
  2104. user.UploadBandwidth = 128
  2105. user.Permissions["/"] = []string{dataprovider.PermAny, dataprovider.PermDelete, dataprovider.PermDownload}
  2106. userAsJSON = getUserAsJSON(t, user)
  2107. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer(userAsJSON))
  2108. rr = executeRequest(req)
  2109. checkResponseCode(t, http.StatusOK, rr.Code)
  2110. req, _ = http.NewRequest(http.MethodGet, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  2111. rr = executeRequest(req)
  2112. checkResponseCode(t, http.StatusOK, rr.Code)
  2113. var updatedUser dataprovider.User
  2114. err = render.DecodeJSON(rr.Body, &updatedUser)
  2115. assert.NoError(t, err)
  2116. assert.Equal(t, user.MaxSessions, updatedUser.MaxSessions)
  2117. assert.Equal(t, user.UploadBandwidth, updatedUser.UploadBandwidth)
  2118. assert.Equal(t, 1, len(updatedUser.Permissions["/"]))
  2119. assert.True(t, utils.IsStringInSlice(dataprovider.PermAny, updatedUser.Permissions["/"]))
  2120. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  2121. rr = executeRequest(req)
  2122. checkResponseCode(t, http.StatusOK, rr.Code)
  2123. }
  2124. func TestGetUserByIdInvalidParamsMock(t *testing.T) {
  2125. req, _ := http.NewRequest(http.MethodGet, userPath+"/0", nil)
  2126. rr := executeRequest(req)
  2127. checkResponseCode(t, http.StatusNotFound, rr.Code)
  2128. req, _ = http.NewRequest(http.MethodGet, userPath+"/a", nil)
  2129. rr = executeRequest(req)
  2130. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2131. }
  2132. func TestAddUserNoUsernameMock(t *testing.T) {
  2133. user := getTestUser()
  2134. user.Username = ""
  2135. userAsJSON := getUserAsJSON(t, user)
  2136. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  2137. rr := executeRequest(req)
  2138. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2139. }
  2140. func TestAddUserInvalidHomeDirMock(t *testing.T) {
  2141. user := getTestUser()
  2142. user.HomeDir = "relative_path"
  2143. userAsJSON := getUserAsJSON(t, user)
  2144. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  2145. rr := executeRequest(req)
  2146. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2147. }
  2148. func TestAddUserInvalidPermsMock(t *testing.T) {
  2149. user := getTestUser()
  2150. user.Permissions["/"] = []string{}
  2151. userAsJSON := getUserAsJSON(t, user)
  2152. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  2153. rr := executeRequest(req)
  2154. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2155. }
  2156. func TestAddFolderInvalidJsonMock(t *testing.T) {
  2157. req, _ := http.NewRequest(http.MethodPost, folderPath, bytes.NewBuffer([]byte("invalid json")))
  2158. rr := executeRequest(req)
  2159. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2160. }
  2161. func TestAddUserInvalidJsonMock(t *testing.T) {
  2162. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer([]byte("invalid json")))
  2163. rr := executeRequest(req)
  2164. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2165. }
  2166. func TestUpdateUserMock(t *testing.T) {
  2167. user := getTestUser()
  2168. userAsJSON := getUserAsJSON(t, user)
  2169. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  2170. rr := executeRequest(req)
  2171. checkResponseCode(t, http.StatusOK, rr.Code)
  2172. err := render.DecodeJSON(rr.Body, &user)
  2173. assert.NoError(t, err)
  2174. // permissions should not change if empty or nil
  2175. permissions := user.Permissions
  2176. user.Permissions = make(map[string][]string)
  2177. userAsJSON = getUserAsJSON(t, user)
  2178. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer(userAsJSON))
  2179. rr = executeRequest(req)
  2180. checkResponseCode(t, http.StatusOK, rr.Code)
  2181. req, _ = http.NewRequest(http.MethodGet, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  2182. rr = executeRequest(req)
  2183. checkResponseCode(t, http.StatusOK, rr.Code)
  2184. var updatedUser dataprovider.User
  2185. err = render.DecodeJSON(rr.Body, &updatedUser)
  2186. assert.NoError(t, err)
  2187. for dir, perms := range permissions {
  2188. if actualPerms, ok := updatedUser.Permissions[dir]; ok {
  2189. for _, v := range actualPerms {
  2190. assert.True(t, utils.IsStringInSlice(v, perms))
  2191. }
  2192. } else {
  2193. assert.Fail(t, "Permissions directories mismatch")
  2194. }
  2195. }
  2196. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  2197. rr = executeRequest(req)
  2198. checkResponseCode(t, http.StatusOK, rr.Code)
  2199. }
  2200. func TestUpdateUserQuotaUsageMock(t *testing.T) {
  2201. var user dataprovider.User
  2202. u := getTestUser()
  2203. usedQuotaFiles := 1
  2204. usedQuotaSize := int64(65535)
  2205. u.UsedQuotaFiles = usedQuotaFiles
  2206. u.UsedQuotaSize = usedQuotaSize
  2207. userAsJSON := getUserAsJSON(t, u)
  2208. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  2209. rr := executeRequest(req)
  2210. checkResponseCode(t, http.StatusOK, rr.Code)
  2211. err := render.DecodeJSON(rr.Body, &user)
  2212. assert.NoError(t, err)
  2213. req, _ = http.NewRequest(http.MethodPut, updateUsedQuotaPath, bytes.NewBuffer(userAsJSON))
  2214. rr = executeRequest(req)
  2215. checkResponseCode(t, http.StatusOK, rr.Code)
  2216. req, _ = http.NewRequest(http.MethodGet, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  2217. rr = executeRequest(req)
  2218. checkResponseCode(t, http.StatusOK, rr.Code)
  2219. err = render.DecodeJSON(rr.Body, &user)
  2220. assert.NoError(t, err)
  2221. assert.Equal(t, usedQuotaFiles, user.UsedQuotaFiles)
  2222. assert.Equal(t, usedQuotaSize, user.UsedQuotaSize)
  2223. req, _ = http.NewRequest(http.MethodPut, updateUsedQuotaPath, bytes.NewBuffer([]byte("string")))
  2224. rr = executeRequest(req)
  2225. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2226. assert.True(t, common.QuotaScans.AddUserQuotaScan(user.Username))
  2227. req, _ = http.NewRequest(http.MethodPut, updateUsedQuotaPath, bytes.NewBuffer(userAsJSON))
  2228. rr = executeRequest(req)
  2229. checkResponseCode(t, http.StatusConflict, rr.Code)
  2230. assert.True(t, common.QuotaScans.RemoveUserQuotaScan(user.Username))
  2231. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  2232. rr = executeRequest(req)
  2233. checkResponseCode(t, http.StatusOK, rr.Code)
  2234. }
  2235. func TestUserPermissionsMock(t *testing.T) {
  2236. user := getTestUser()
  2237. user.Permissions = make(map[string][]string)
  2238. user.Permissions["/somedir"] = []string{dataprovider.PermAny}
  2239. userAsJSON := getUserAsJSON(t, user)
  2240. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  2241. rr := executeRequest(req)
  2242. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2243. user.Permissions = make(map[string][]string)
  2244. user.Permissions["/"] = []string{dataprovider.PermAny}
  2245. user.Permissions[".."] = []string{dataprovider.PermAny}
  2246. userAsJSON = getUserAsJSON(t, user)
  2247. req, _ = http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  2248. rr = executeRequest(req)
  2249. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2250. user.Permissions = make(map[string][]string)
  2251. user.Permissions["/"] = []string{dataprovider.PermAny}
  2252. userAsJSON = getUserAsJSON(t, user)
  2253. req, _ = http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  2254. rr = executeRequest(req)
  2255. checkResponseCode(t, http.StatusOK, rr.Code)
  2256. err := render.DecodeJSON(rr.Body, &user)
  2257. assert.NoError(t, err)
  2258. user.Permissions["/somedir"] = []string{"invalid"}
  2259. userAsJSON = getUserAsJSON(t, user)
  2260. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer(userAsJSON))
  2261. rr = executeRequest(req)
  2262. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2263. delete(user.Permissions, "/somedir")
  2264. user.Permissions["/somedir/.."] = []string{dataprovider.PermAny}
  2265. userAsJSON = getUserAsJSON(t, user)
  2266. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer(userAsJSON))
  2267. rr = executeRequest(req)
  2268. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2269. delete(user.Permissions, "/somedir/..")
  2270. user.Permissions["not_abs_path"] = []string{dataprovider.PermAny}
  2271. userAsJSON = getUserAsJSON(t, user)
  2272. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer(userAsJSON))
  2273. rr = executeRequest(req)
  2274. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2275. delete(user.Permissions, "not_abs_path")
  2276. user.Permissions["/somedir/../otherdir/"] = []string{dataprovider.PermListItems}
  2277. userAsJSON = getUserAsJSON(t, user)
  2278. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer(userAsJSON))
  2279. rr = executeRequest(req)
  2280. checkResponseCode(t, http.StatusOK, rr.Code)
  2281. req, _ = http.NewRequest(http.MethodGet, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  2282. rr = executeRequest(req)
  2283. checkResponseCode(t, http.StatusOK, rr.Code)
  2284. var updatedUser dataprovider.User
  2285. err = render.DecodeJSON(rr.Body, &updatedUser)
  2286. assert.NoError(t, err)
  2287. if val, ok := updatedUser.Permissions["/otherdir"]; ok {
  2288. assert.True(t, utils.IsStringInSlice(dataprovider.PermListItems, val))
  2289. assert.Equal(t, 1, len(val))
  2290. } else {
  2291. assert.Fail(t, "expected dir not found in permissions")
  2292. }
  2293. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  2294. rr = executeRequest(req)
  2295. checkResponseCode(t, http.StatusOK, rr.Code)
  2296. }
  2297. func TestUpdateUserInvalidJsonMock(t *testing.T) {
  2298. user := getTestUser()
  2299. userAsJSON := getUserAsJSON(t, user)
  2300. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  2301. rr := executeRequest(req)
  2302. checkResponseCode(t, http.StatusOK, rr.Code)
  2303. err := render.DecodeJSON(rr.Body, &user)
  2304. assert.NoError(t, err)
  2305. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer([]byte("Invalid json")))
  2306. rr = executeRequest(req)
  2307. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2308. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  2309. rr = executeRequest(req)
  2310. checkResponseCode(t, http.StatusOK, rr.Code)
  2311. }
  2312. func TestUpdateUserInvalidParamsMock(t *testing.T) {
  2313. user := getTestUser()
  2314. userAsJSON := getUserAsJSON(t, user)
  2315. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  2316. rr := executeRequest(req)
  2317. checkResponseCode(t, http.StatusOK, rr.Code)
  2318. err := render.DecodeJSON(rr.Body, &user)
  2319. assert.NoError(t, err)
  2320. user.HomeDir = ""
  2321. userAsJSON = getUserAsJSON(t, user)
  2322. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer(userAsJSON))
  2323. rr = executeRequest(req)
  2324. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2325. userID := user.ID
  2326. user.ID = 0
  2327. userAsJSON = getUserAsJSON(t, user)
  2328. req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(userID, 10), bytes.NewBuffer(userAsJSON))
  2329. rr = executeRequest(req)
  2330. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2331. user.ID = userID
  2332. req, _ = http.NewRequest(http.MethodPut, userPath+"/0", bytes.NewBuffer(userAsJSON))
  2333. rr = executeRequest(req)
  2334. checkResponseCode(t, http.StatusNotFound, rr.Code)
  2335. req, _ = http.NewRequest(http.MethodPut, userPath+"/a", bytes.NewBuffer(userAsJSON))
  2336. rr = executeRequest(req)
  2337. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2338. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  2339. rr = executeRequest(req)
  2340. checkResponseCode(t, http.StatusOK, rr.Code)
  2341. }
  2342. func TestGetUsersMock(t *testing.T) {
  2343. user := getTestUser()
  2344. userAsJSON := getUserAsJSON(t, user)
  2345. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  2346. rr := executeRequest(req)
  2347. checkResponseCode(t, http.StatusOK, rr.Code)
  2348. err := render.DecodeJSON(rr.Body, &user)
  2349. assert.NoError(t, err)
  2350. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=510&offset=0&order=ASC&username="+defaultUsername, nil)
  2351. rr = executeRequest(req)
  2352. checkResponseCode(t, http.StatusOK, rr.Code)
  2353. var users []dataprovider.User
  2354. err = render.DecodeJSON(rr.Body, &users)
  2355. assert.NoError(t, err)
  2356. assert.Equal(t, 1, len(users))
  2357. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=a&offset=0&order=ASC", nil)
  2358. rr = executeRequest(req)
  2359. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2360. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=a&order=ASC", nil)
  2361. rr = executeRequest(req)
  2362. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2363. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=0&order=ASCa", nil)
  2364. rr = executeRequest(req)
  2365. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2366. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  2367. rr = executeRequest(req)
  2368. checkResponseCode(t, http.StatusOK, rr.Code)
  2369. }
  2370. func TestDeleteUserInvalidParamsMock(t *testing.T) {
  2371. req, _ := http.NewRequest(http.MethodDelete, userPath+"/0", nil)
  2372. rr := executeRequest(req)
  2373. checkResponseCode(t, http.StatusNotFound, rr.Code)
  2374. req, _ = http.NewRequest(http.MethodDelete, userPath+"/a", nil)
  2375. rr = executeRequest(req)
  2376. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2377. }
  2378. func TestGetQuotaScansMock(t *testing.T) {
  2379. req, err := http.NewRequest("GET", quotaScanPath, nil)
  2380. assert.NoError(t, err)
  2381. rr := executeRequest(req)
  2382. checkResponseCode(t, http.StatusOK, rr.Code)
  2383. }
  2384. func TestStartQuotaScanMock(t *testing.T) {
  2385. user := getTestUser()
  2386. userAsJSON := getUserAsJSON(t, user)
  2387. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  2388. rr := executeRequest(req)
  2389. checkResponseCode(t, http.StatusOK, rr.Code)
  2390. err := render.DecodeJSON(rr.Body, &user)
  2391. assert.NoError(t, err)
  2392. _, err = os.Stat(user.HomeDir)
  2393. if err == nil {
  2394. err = os.Remove(user.HomeDir)
  2395. assert.NoError(t, err)
  2396. }
  2397. // simulate a duplicate quota scan
  2398. userAsJSON = getUserAsJSON(t, user)
  2399. common.QuotaScans.AddUserQuotaScan(user.Username)
  2400. req, _ = http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer(userAsJSON))
  2401. rr = executeRequest(req)
  2402. checkResponseCode(t, http.StatusConflict, rr.Code)
  2403. assert.True(t, common.QuotaScans.RemoveUserQuotaScan(user.Username))
  2404. userAsJSON = getUserAsJSON(t, user)
  2405. req, _ = http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer(userAsJSON))
  2406. rr = executeRequest(req)
  2407. checkResponseCode(t, http.StatusAccepted, rr.Code)
  2408. for {
  2409. var scans []common.ActiveQuotaScan
  2410. req, _ = http.NewRequest(http.MethodGet, quotaScanPath, nil)
  2411. rr = executeRequest(req)
  2412. checkResponseCode(t, http.StatusOK, rr.Code)
  2413. err = render.DecodeJSON(rr.Body, &scans)
  2414. if !assert.NoError(t, err, "Error getting active scans") {
  2415. break
  2416. }
  2417. if len(scans) == 0 {
  2418. break
  2419. }
  2420. time.Sleep(100 * time.Millisecond)
  2421. }
  2422. _, err = os.Stat(user.HomeDir)
  2423. if err != nil && os.IsNotExist(err) {
  2424. err = os.MkdirAll(user.HomeDir, os.ModePerm)
  2425. assert.NoError(t, err)
  2426. }
  2427. req, _ = http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer(userAsJSON))
  2428. rr = executeRequest(req)
  2429. checkResponseCode(t, http.StatusAccepted, rr.Code)
  2430. for {
  2431. var scans []common.ActiveQuotaScan
  2432. req, _ = http.NewRequest(http.MethodGet, quotaScanPath, nil)
  2433. rr = executeRequest(req)
  2434. checkResponseCode(t, http.StatusOK, rr.Code)
  2435. err = render.DecodeJSON(rr.Body, &scans)
  2436. if !assert.NoError(t, err) {
  2437. assert.Fail(t, err.Error(), "Error getting active scans")
  2438. break
  2439. }
  2440. if len(scans) == 0 {
  2441. break
  2442. }
  2443. time.Sleep(100 * time.Millisecond)
  2444. }
  2445. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  2446. rr = executeRequest(req)
  2447. checkResponseCode(t, http.StatusOK, rr.Code)
  2448. err = os.RemoveAll(user.GetHomeDir())
  2449. assert.NoError(t, err)
  2450. }
  2451. func TestUpdateFolderQuotaUsageMock(t *testing.T) {
  2452. mappedPath := filepath.Join(os.TempDir(), "vfolder")
  2453. f := vfs.BaseVirtualFolder{
  2454. MappedPath: mappedPath,
  2455. }
  2456. usedQuotaFiles := 1
  2457. usedQuotaSize := int64(65535)
  2458. f.UsedQuotaFiles = usedQuotaFiles
  2459. f.UsedQuotaSize = usedQuotaSize
  2460. var folder vfs.BaseVirtualFolder
  2461. folderAsJSON, err := json.Marshal(f)
  2462. assert.NoError(t, err)
  2463. req, _ := http.NewRequest(http.MethodPost, folderPath, bytes.NewBuffer(folderAsJSON))
  2464. rr := executeRequest(req)
  2465. checkResponseCode(t, http.StatusOK, rr.Code)
  2466. err = render.DecodeJSON(rr.Body, &folder)
  2467. assert.NoError(t, err)
  2468. req, _ = http.NewRequest(http.MethodPut, updateFolderUsedQuotaPath, bytes.NewBuffer(folderAsJSON))
  2469. rr = executeRequest(req)
  2470. checkResponseCode(t, http.StatusOK, rr.Code)
  2471. var folders []vfs.BaseVirtualFolder
  2472. url, err := url.Parse(folderPath)
  2473. assert.NoError(t, err)
  2474. q := url.Query()
  2475. q.Add("folder_path", mappedPath)
  2476. url.RawQuery = q.Encode()
  2477. req, _ = http.NewRequest(http.MethodGet, url.String(), nil)
  2478. rr = executeRequest(req)
  2479. checkResponseCode(t, http.StatusOK, rr.Code)
  2480. err = render.DecodeJSON(rr.Body, &folders)
  2481. assert.NoError(t, err)
  2482. if assert.Len(t, folders, 1) {
  2483. folder = folders[0]
  2484. assert.Equal(t, usedQuotaFiles, folder.UsedQuotaFiles)
  2485. assert.Equal(t, usedQuotaSize, folder.UsedQuotaSize)
  2486. }
  2487. req, _ = http.NewRequest(http.MethodPut, updateFolderUsedQuotaPath, bytes.NewBuffer([]byte("string")))
  2488. rr = executeRequest(req)
  2489. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2490. assert.True(t, common.QuotaScans.AddVFolderQuotaScan(mappedPath))
  2491. req, _ = http.NewRequest(http.MethodPut, updateFolderUsedQuotaPath, bytes.NewBuffer(folderAsJSON))
  2492. rr = executeRequest(req)
  2493. checkResponseCode(t, http.StatusConflict, rr.Code)
  2494. assert.True(t, common.QuotaScans.RemoveVFolderQuotaScan(mappedPath))
  2495. url, err = url.Parse(folderPath)
  2496. assert.NoError(t, err)
  2497. q = url.Query()
  2498. q.Add("folder_path", mappedPath)
  2499. url.RawQuery = q.Encode()
  2500. req, _ = http.NewRequest(http.MethodDelete, url.String(), nil)
  2501. rr = executeRequest(req)
  2502. checkResponseCode(t, http.StatusOK, rr.Code)
  2503. }
  2504. func TestStartFolderQuotaScanMock(t *testing.T) {
  2505. mappedPath := filepath.Join(os.TempDir(), "vfolder")
  2506. folder := vfs.BaseVirtualFolder{
  2507. MappedPath: mappedPath,
  2508. }
  2509. folderAsJSON, err := json.Marshal(folder)
  2510. assert.NoError(t, err)
  2511. req, _ := http.NewRequest(http.MethodPost, folderPath, bytes.NewBuffer(folderAsJSON))
  2512. rr := executeRequest(req)
  2513. checkResponseCode(t, http.StatusOK, rr.Code)
  2514. _, err = os.Stat(mappedPath)
  2515. if err == nil {
  2516. err = os.Remove(mappedPath)
  2517. assert.NoError(t, err)
  2518. }
  2519. // simulate a duplicate quota scan
  2520. common.QuotaScans.AddVFolderQuotaScan(mappedPath)
  2521. req, _ = http.NewRequest(http.MethodPost, quotaScanVFolderPath, bytes.NewBuffer(folderAsJSON))
  2522. rr = executeRequest(req)
  2523. checkResponseCode(t, http.StatusConflict, rr.Code)
  2524. assert.True(t, common.QuotaScans.RemoveVFolderQuotaScan(mappedPath))
  2525. // and now a real quota scan
  2526. _, err = os.Stat(mappedPath)
  2527. if err != nil && os.IsNotExist(err) {
  2528. err = os.MkdirAll(mappedPath, os.ModePerm)
  2529. assert.NoError(t, err)
  2530. }
  2531. req, _ = http.NewRequest(http.MethodPost, quotaScanVFolderPath, bytes.NewBuffer(folderAsJSON))
  2532. rr = executeRequest(req)
  2533. checkResponseCode(t, http.StatusAccepted, rr.Code)
  2534. var scans []common.ActiveVirtualFolderQuotaScan
  2535. for {
  2536. req, _ = http.NewRequest(http.MethodGet, quotaScanVFolderPath, nil)
  2537. rr = executeRequest(req)
  2538. checkResponseCode(t, http.StatusOK, rr.Code)
  2539. err = render.DecodeJSON(rr.Body, &scans)
  2540. if !assert.NoError(t, err, "Error getting active folders scans") {
  2541. break
  2542. }
  2543. if len(scans) == 0 {
  2544. break
  2545. }
  2546. time.Sleep(100 * time.Millisecond)
  2547. }
  2548. // cleanup
  2549. url, err := url.Parse(folderPath)
  2550. assert.NoError(t, err)
  2551. q := url.Query()
  2552. q.Add("folder_path", mappedPath)
  2553. url.RawQuery = q.Encode()
  2554. req, _ = http.NewRequest(http.MethodDelete, url.String(), nil)
  2555. rr = executeRequest(req)
  2556. checkResponseCode(t, http.StatusOK, rr.Code)
  2557. err = os.RemoveAll(folderPath)
  2558. assert.NoError(t, err)
  2559. err = os.RemoveAll(mappedPath)
  2560. assert.NoError(t, err)
  2561. }
  2562. func TestStartQuotaScanNonExistentUserMock(t *testing.T) {
  2563. user := getTestUser()
  2564. userAsJSON := getUserAsJSON(t, user)
  2565. req, _ := http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer(userAsJSON))
  2566. rr := executeRequest(req)
  2567. checkResponseCode(t, http.StatusNotFound, rr.Code)
  2568. }
  2569. func TestStartQuotaScanBadUserMock(t *testing.T) {
  2570. req, _ := http.NewRequest(http.MethodPost, quotaScanPath, bytes.NewBuffer([]byte("invalid json")))
  2571. rr := executeRequest(req)
  2572. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2573. }
  2574. func TestStartQuotaScanBadFolderMock(t *testing.T) {
  2575. req, _ := http.NewRequest(http.MethodPost, quotaScanVFolderPath, bytes.NewBuffer([]byte("invalid json")))
  2576. rr := executeRequest(req)
  2577. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2578. }
  2579. func TestStartQuotaScanNonExistentFolderMock(t *testing.T) {
  2580. folder := vfs.BaseVirtualFolder{
  2581. MappedPath: os.TempDir(),
  2582. }
  2583. folderAsJSON, err := json.Marshal(folder)
  2584. assert.NoError(t, err)
  2585. req, _ := http.NewRequest(http.MethodPost, quotaScanVFolderPath, bytes.NewBuffer(folderAsJSON))
  2586. rr := executeRequest(req)
  2587. checkResponseCode(t, http.StatusNotFound, rr.Code)
  2588. }
  2589. func TestGetFoldersMock(t *testing.T) {
  2590. mappedPath := filepath.Join(os.TempDir(), "vfolder")
  2591. folder := vfs.BaseVirtualFolder{
  2592. MappedPath: mappedPath,
  2593. }
  2594. folderAsJSON, err := json.Marshal(folder)
  2595. assert.NoError(t, err)
  2596. req, _ := http.NewRequest(http.MethodPost, folderPath, bytes.NewBuffer(folderAsJSON))
  2597. rr := executeRequest(req)
  2598. checkResponseCode(t, http.StatusOK, rr.Code)
  2599. err = render.DecodeJSON(rr.Body, &folder)
  2600. assert.NoError(t, err)
  2601. var folders []vfs.BaseVirtualFolder
  2602. url, err := url.Parse(folderPath + "?limit=510&offset=0&order=DESC")
  2603. assert.NoError(t, err)
  2604. q := url.Query()
  2605. q.Add("folder_path", mappedPath)
  2606. url.RawQuery = q.Encode()
  2607. req, _ = http.NewRequest(http.MethodGet, url.String(), nil)
  2608. rr = executeRequest(req)
  2609. checkResponseCode(t, http.StatusOK, rr.Code)
  2610. err = render.DecodeJSON(rr.Body, &folders)
  2611. assert.NoError(t, err)
  2612. assert.Len(t, folders, 1)
  2613. req, _ = http.NewRequest(http.MethodGet, folderPath+"?limit=a&offset=0&order=ASC", nil)
  2614. rr = executeRequest(req)
  2615. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2616. req, _ = http.NewRequest(http.MethodGet, folderPath+"?limit=1&offset=a&order=ASC", nil)
  2617. rr = executeRequest(req)
  2618. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2619. req, _ = http.NewRequest(http.MethodGet, folderPath+"?limit=1&offset=0&order=ASCa", nil)
  2620. rr = executeRequest(req)
  2621. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2622. url, err = url.Parse(folderPath)
  2623. assert.NoError(t, err)
  2624. q = url.Query()
  2625. q.Add("folder_path", mappedPath)
  2626. url.RawQuery = q.Encode()
  2627. req, _ = http.NewRequest(http.MethodDelete, url.String(), nil)
  2628. rr = executeRequest(req)
  2629. checkResponseCode(t, http.StatusOK, rr.Code)
  2630. }
  2631. func TestGetVersionMock(t *testing.T) {
  2632. req, _ := http.NewRequest(http.MethodGet, versionPath, nil)
  2633. rr := executeRequest(req)
  2634. checkResponseCode(t, http.StatusOK, rr.Code)
  2635. }
  2636. func TestGetConnectionsMock(t *testing.T) {
  2637. req, _ := http.NewRequest(http.MethodGet, activeConnectionsPath, nil)
  2638. rr := executeRequest(req)
  2639. checkResponseCode(t, http.StatusOK, rr.Code)
  2640. }
  2641. func TestDeleteActiveConnectionMock(t *testing.T) {
  2642. req, _ := http.NewRequest(http.MethodDelete, activeConnectionsPath+"/connectionID", nil)
  2643. rr := executeRequest(req)
  2644. checkResponseCode(t, http.StatusNotFound, rr.Code)
  2645. }
  2646. func TestNotFoundMock(t *testing.T) {
  2647. req, _ := http.NewRequest(http.MethodGet, "/non/existing/path", nil)
  2648. rr := executeRequest(req)
  2649. checkResponseCode(t, http.StatusNotFound, rr.Code)
  2650. }
  2651. func TestMethodNotAllowedMock(t *testing.T) {
  2652. req, _ := http.NewRequest(http.MethodPost, activeConnectionsPath, nil)
  2653. rr := executeRequest(req)
  2654. checkResponseCode(t, http.StatusMethodNotAllowed, rr.Code)
  2655. }
  2656. func TestMetricsMock(t *testing.T) {
  2657. req, _ := http.NewRequest(http.MethodGet, metricsPath, nil)
  2658. rr := executeRequest(req)
  2659. checkResponseCode(t, http.StatusOK, rr.Code)
  2660. }
  2661. func TestHealthCheck(t *testing.T) {
  2662. req, _ := http.NewRequest(http.MethodGet, "/healthz", nil)
  2663. rr := executeRequest(req)
  2664. checkResponseCode(t, http.StatusOK, rr.Code)
  2665. assert.Equal(t, "ok", rr.Body.String())
  2666. }
  2667. func TestPProfEndPointMock(t *testing.T) {
  2668. req, _ := http.NewRequest(http.MethodGet, pprofPath, nil)
  2669. rr := executeRequest(req)
  2670. checkResponseCode(t, http.StatusOK, rr.Code)
  2671. }
  2672. func TestGetWebRootMock(t *testing.T) {
  2673. req, _ := http.NewRequest(http.MethodGet, "/", nil)
  2674. rr := executeRequest(req)
  2675. checkResponseCode(t, http.StatusMovedPermanently, rr.Code)
  2676. req, _ = http.NewRequest(http.MethodGet, webBasePath, nil)
  2677. rr = executeRequest(req)
  2678. checkResponseCode(t, http.StatusMovedPermanently, rr.Code)
  2679. }
  2680. func TestBasicWebUsersMock(t *testing.T) {
  2681. user := getTestUser()
  2682. userAsJSON := getUserAsJSON(t, user)
  2683. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  2684. rr := executeRequest(req)
  2685. checkResponseCode(t, http.StatusOK, rr.Code)
  2686. err := render.DecodeJSON(rr.Body, &user)
  2687. assert.NoError(t, err)
  2688. user1 := getTestUser()
  2689. user1.Username += "1"
  2690. user1AsJSON := getUserAsJSON(t, user1)
  2691. req, _ = http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(user1AsJSON))
  2692. rr = executeRequest(req)
  2693. checkResponseCode(t, http.StatusOK, rr.Code)
  2694. err = render.DecodeJSON(rr.Body, &user1)
  2695. assert.NoError(t, err)
  2696. req, _ = http.NewRequest(http.MethodGet, webUsersPath, nil)
  2697. rr = executeRequest(req)
  2698. checkResponseCode(t, http.StatusOK, rr.Code)
  2699. req, _ = http.NewRequest(http.MethodGet, webUsersPath+"?qlimit=a", nil)
  2700. rr = executeRequest(req)
  2701. checkResponseCode(t, http.StatusOK, rr.Code)
  2702. req, _ = http.NewRequest(http.MethodGet, webUsersPath+"?qlimit=1", nil)
  2703. rr = executeRequest(req)
  2704. checkResponseCode(t, http.StatusOK, rr.Code)
  2705. req, _ = http.NewRequest(http.MethodGet, webUserPath, nil)
  2706. rr = executeRequest(req)
  2707. checkResponseCode(t, http.StatusOK, rr.Code)
  2708. req, _ = http.NewRequest(http.MethodGet, webUserPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  2709. rr = executeRequest(req)
  2710. checkResponseCode(t, http.StatusOK, rr.Code)
  2711. req, _ = http.NewRequest(http.MethodGet, webUserPath+"/0", nil)
  2712. rr = executeRequest(req)
  2713. checkResponseCode(t, http.StatusNotFound, rr.Code)
  2714. req, _ = http.NewRequest(http.MethodGet, webUserPath+"/a", nil)
  2715. rr = executeRequest(req)
  2716. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2717. form := make(url.Values)
  2718. form.Set("username", user.Username)
  2719. b, contentType, _ := getMultipartFormData(form, "", "")
  2720. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  2721. req.Header.Set("Content-Type", contentType)
  2722. rr = executeRequest(req)
  2723. checkResponseCode(t, http.StatusOK, rr.Code)
  2724. b, contentType, _ = getMultipartFormData(form, "", "")
  2725. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  2726. req.Header.Set("Content-Type", contentType)
  2727. rr = executeRequest(req)
  2728. checkResponseCode(t, http.StatusOK, rr.Code)
  2729. b, contentType, _ = getMultipartFormData(form, "", "")
  2730. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/0", &b)
  2731. req.Header.Set("Content-Type", contentType)
  2732. rr = executeRequest(req)
  2733. checkResponseCode(t, http.StatusNotFound, rr.Code)
  2734. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/a", &b)
  2735. req.Header.Set("Content-Type", contentType)
  2736. rr = executeRequest(req)
  2737. checkResponseCode(t, http.StatusBadRequest, rr.Code)
  2738. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  2739. rr = executeRequest(req)
  2740. checkResponseCode(t, http.StatusOK, rr.Code)
  2741. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user1.ID, 10), nil)
  2742. rr = executeRequest(req)
  2743. checkResponseCode(t, http.StatusOK, rr.Code)
  2744. }
  2745. func TestWebUserAddMock(t *testing.T) {
  2746. user := getTestUser()
  2747. user.UploadBandwidth = 32
  2748. user.DownloadBandwidth = 64
  2749. user.UID = 1000
  2750. user.AdditionalInfo = "info"
  2751. mappedDir := filepath.Join(os.TempDir(), "mapped")
  2752. form := make(url.Values)
  2753. form.Set("username", user.Username)
  2754. form.Set("home_dir", user.HomeDir)
  2755. form.Set("password", user.Password)
  2756. form.Set("status", strconv.Itoa(user.Status))
  2757. form.Set("expiration_date", "")
  2758. form.Set("permissions", "*")
  2759. form.Set("sub_dirs_permissions", " /subdir::list ,download ")
  2760. form.Set("virtual_folders", fmt.Sprintf(" /vdir:: %v :: 2 :: 1024", mappedDir))
  2761. form.Set("allowed_extensions", "/dir2::.jpg,.png\n/dir2::.ico\n/dir1::.rar")
  2762. form.Set("denied_extensions", "/dir2::.webp,.webp\n/dir2::.tiff\n/dir1::.zip")
  2763. form.Set("allowed_patterns", "/dir2::*.jpg,*.png\n/dir1::*.png")
  2764. form.Set("denied_patterns", "/dir1::*.zip\n/dir3::*.rar\n/dir2::*.mkv")
  2765. form.Set("additional_info", user.AdditionalInfo)
  2766. b, contentType, _ := getMultipartFormData(form, "", "")
  2767. // test invalid url escape
  2768. req, _ := http.NewRequest(http.MethodPost, webUserPath+"?a=%2", &b)
  2769. req.Header.Set("Content-Type", contentType)
  2770. rr := executeRequest(req)
  2771. checkResponseCode(t, http.StatusOK, rr.Code)
  2772. form.Set("public_keys", testPubKey)
  2773. form.Set("uid", strconv.FormatInt(int64(user.UID), 10))
  2774. form.Set("gid", "a")
  2775. b, contentType, _ = getMultipartFormData(form, "", "")
  2776. // test invalid gid
  2777. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  2778. req.Header.Set("Content-Type", contentType)
  2779. rr = executeRequest(req)
  2780. checkResponseCode(t, http.StatusOK, rr.Code)
  2781. form.Set("gid", "0")
  2782. form.Set("max_sessions", "a")
  2783. b, contentType, _ = getMultipartFormData(form, "", "")
  2784. // test invalid max sessions
  2785. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  2786. req.Header.Set("Content-Type", contentType)
  2787. rr = executeRequest(req)
  2788. checkResponseCode(t, http.StatusOK, rr.Code)
  2789. form.Set("max_sessions", "0")
  2790. form.Set("quota_size", "a")
  2791. b, contentType, _ = getMultipartFormData(form, "", "")
  2792. // test invalid quota size
  2793. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  2794. req.Header.Set("Content-Type", contentType)
  2795. rr = executeRequest(req)
  2796. checkResponseCode(t, http.StatusOK, rr.Code)
  2797. form.Set("quota_size", "0")
  2798. form.Set("quota_files", "a")
  2799. b, contentType, _ = getMultipartFormData(form, "", "")
  2800. // test invalid quota files
  2801. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  2802. req.Header.Set("Content-Type", contentType)
  2803. rr = executeRequest(req)
  2804. checkResponseCode(t, http.StatusOK, rr.Code)
  2805. form.Set("quota_files", "0")
  2806. form.Set("upload_bandwidth", "a")
  2807. b, contentType, _ = getMultipartFormData(form, "", "")
  2808. // test invalid upload bandwidth
  2809. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  2810. req.Header.Set("Content-Type", contentType)
  2811. rr = executeRequest(req)
  2812. checkResponseCode(t, http.StatusOK, rr.Code)
  2813. form.Set("upload_bandwidth", strconv.FormatInt(user.UploadBandwidth, 10))
  2814. form.Set("download_bandwidth", "a")
  2815. b, contentType, _ = getMultipartFormData(form, "", "")
  2816. // test invalid download bandwidth
  2817. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  2818. req.Header.Set("Content-Type", contentType)
  2819. rr = executeRequest(req)
  2820. checkResponseCode(t, http.StatusOK, rr.Code)
  2821. form.Set("download_bandwidth", strconv.FormatInt(user.DownloadBandwidth, 10))
  2822. form.Set("status", "a")
  2823. b, contentType, _ = getMultipartFormData(form, "", "")
  2824. // test invalid status
  2825. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  2826. req.Header.Set("Content-Type", contentType)
  2827. rr = executeRequest(req)
  2828. checkResponseCode(t, http.StatusOK, rr.Code)
  2829. form.Set("status", strconv.Itoa(user.Status))
  2830. form.Set("expiration_date", "123")
  2831. b, contentType, _ = getMultipartFormData(form, "", "")
  2832. // test invalid expiration date
  2833. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  2834. req.Header.Set("Content-Type", contentType)
  2835. rr = executeRequest(req)
  2836. checkResponseCode(t, http.StatusOK, rr.Code)
  2837. form.Set("expiration_date", "")
  2838. form.Set("allowed_ip", "invalid,ip")
  2839. b, contentType, _ = getMultipartFormData(form, "", "")
  2840. // test invalid allowed_ip
  2841. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  2842. req.Header.Set("Content-Type", contentType)
  2843. rr = executeRequest(req)
  2844. checkResponseCode(t, http.StatusOK, rr.Code)
  2845. form.Set("allowed_ip", "")
  2846. form.Set("denied_ip", "192.168.1.2") // it should be 192.168.1.2/32
  2847. b, contentType, _ = getMultipartFormData(form, "", "")
  2848. // test invalid denied_ip
  2849. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  2850. req.Header.Set("Content-Type", contentType)
  2851. rr = executeRequest(req)
  2852. checkResponseCode(t, http.StatusOK, rr.Code)
  2853. form.Set("denied_ip", "")
  2854. // test invalid max file upload size
  2855. form.Set("max_upload_file_size", "a")
  2856. b, contentType, _ = getMultipartFormData(form, "", "")
  2857. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  2858. req.Header.Set("Content-Type", contentType)
  2859. rr = executeRequest(req)
  2860. checkResponseCode(t, http.StatusOK, rr.Code)
  2861. form.Set("max_upload_file_size", "1000")
  2862. b, contentType, _ = getMultipartFormData(form, "", "")
  2863. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  2864. req.Header.Set("Content-Type", contentType)
  2865. rr = executeRequest(req)
  2866. checkResponseCode(t, http.StatusSeeOther, rr.Code)
  2867. // the user already exists, was created with the above request
  2868. b, contentType, _ = getMultipartFormData(form, "", "")
  2869. req, _ = http.NewRequest(http.MethodPost, webUserPath, &b)
  2870. req.Header.Set("Content-Type", contentType)
  2871. rr = executeRequest(req)
  2872. checkResponseCode(t, http.StatusOK, rr.Code)
  2873. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=0&order=ASC&username="+user.Username, nil)
  2874. rr = executeRequest(req)
  2875. checkResponseCode(t, http.StatusOK, rr.Code)
  2876. var users []dataprovider.User
  2877. err := render.DecodeJSON(rr.Body, &users)
  2878. assert.NoError(t, err)
  2879. assert.Equal(t, 1, len(users))
  2880. newUser := users[0]
  2881. assert.Equal(t, user.UID, newUser.UID)
  2882. assert.Equal(t, user.UploadBandwidth, newUser.UploadBandwidth)
  2883. assert.Equal(t, user.DownloadBandwidth, newUser.DownloadBandwidth)
  2884. assert.Equal(t, int64(1000), newUser.Filters.MaxUploadFileSize)
  2885. assert.Equal(t, user.AdditionalInfo, newUser.AdditionalInfo)
  2886. assert.True(t, utils.IsStringInSlice(testPubKey, newUser.PublicKeys))
  2887. if val, ok := newUser.Permissions["/subdir"]; ok {
  2888. assert.True(t, utils.IsStringInSlice(dataprovider.PermListItems, val))
  2889. assert.True(t, utils.IsStringInSlice(dataprovider.PermDownload, val))
  2890. } else {
  2891. assert.Fail(t, "user permissions must contain /somedir", "actual: %v", newUser.Permissions)
  2892. }
  2893. assert.Len(t, newUser.VirtualFolders, 1)
  2894. for _, v := range newUser.VirtualFolders {
  2895. assert.Equal(t, v.VirtualPath, "/vdir")
  2896. assert.Equal(t, v.MappedPath, mappedDir)
  2897. assert.Equal(t, v.QuotaFiles, 2)
  2898. assert.Equal(t, v.QuotaSize, int64(1024))
  2899. }
  2900. assert.Len(t, newUser.Filters.FileExtensions, 2)
  2901. for _, filter := range newUser.Filters.FileExtensions {
  2902. if filter.Path == "/dir1" {
  2903. assert.Len(t, filter.DeniedExtensions, 1)
  2904. assert.Len(t, filter.AllowedExtensions, 1)
  2905. assert.True(t, utils.IsStringInSlice(".zip", filter.DeniedExtensions))
  2906. assert.True(t, utils.IsStringInSlice(".rar", filter.AllowedExtensions))
  2907. }
  2908. if filter.Path == "/dir2" {
  2909. assert.Len(t, filter.DeniedExtensions, 2)
  2910. assert.Len(t, filter.AllowedExtensions, 3)
  2911. assert.True(t, utils.IsStringInSlice(".jpg", filter.AllowedExtensions))
  2912. assert.True(t, utils.IsStringInSlice(".png", filter.AllowedExtensions))
  2913. assert.True(t, utils.IsStringInSlice(".ico", filter.AllowedExtensions))
  2914. assert.True(t, utils.IsStringInSlice(".webp", filter.DeniedExtensions))
  2915. assert.True(t, utils.IsStringInSlice(".tiff", filter.DeniedExtensions))
  2916. }
  2917. }
  2918. assert.Len(t, newUser.Filters.FilePatterns, 3)
  2919. for _, filter := range newUser.Filters.FilePatterns {
  2920. if filter.Path == "/dir1" {
  2921. assert.Len(t, filter.DeniedPatterns, 1)
  2922. assert.Len(t, filter.AllowedPatterns, 1)
  2923. assert.True(t, utils.IsStringInSlice("*.png", filter.AllowedPatterns))
  2924. assert.True(t, utils.IsStringInSlice("*.zip", filter.DeniedPatterns))
  2925. }
  2926. if filter.Path == "/dir2" {
  2927. assert.Len(t, filter.DeniedPatterns, 1)
  2928. assert.Len(t, filter.AllowedPatterns, 2)
  2929. assert.True(t, utils.IsStringInSlice("*.jpg", filter.AllowedPatterns))
  2930. assert.True(t, utils.IsStringInSlice("*.png", filter.AllowedPatterns))
  2931. assert.True(t, utils.IsStringInSlice("*.mkv", filter.DeniedPatterns))
  2932. }
  2933. if filter.Path == "/dir3" {
  2934. assert.Len(t, filter.DeniedPatterns, 1)
  2935. assert.Len(t, filter.AllowedPatterns, 0)
  2936. assert.True(t, utils.IsStringInSlice("*.rar", filter.DeniedPatterns))
  2937. }
  2938. }
  2939. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(newUser.ID, 10), nil)
  2940. rr = executeRequest(req)
  2941. checkResponseCode(t, http.StatusOK, rr.Code)
  2942. url, err := url.Parse(folderPath)
  2943. assert.NoError(t, err)
  2944. q := url.Query()
  2945. q.Add("folder_path", mappedDir)
  2946. url.RawQuery = q.Encode()
  2947. req, _ = http.NewRequest(http.MethodDelete, url.String(), nil)
  2948. rr = executeRequest(req)
  2949. checkResponseCode(t, http.StatusOK, rr.Code)
  2950. }
  2951. func TestWebUserUpdateMock(t *testing.T) {
  2952. user := getTestUser()
  2953. userAsJSON := getUserAsJSON(t, user)
  2954. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  2955. rr := executeRequest(req)
  2956. checkResponseCode(t, http.StatusOK, rr.Code)
  2957. err := render.DecodeJSON(rr.Body, &user)
  2958. assert.NoError(t, err)
  2959. user.MaxSessions = 1
  2960. user.QuotaFiles = 2
  2961. user.QuotaSize = 3
  2962. user.GID = 1000
  2963. user.AdditionalInfo = "new additional info"
  2964. form := make(url.Values)
  2965. form.Set("username", user.Username)
  2966. form.Set("home_dir", user.HomeDir)
  2967. form.Set("uid", "0")
  2968. form.Set("gid", strconv.FormatInt(int64(user.GID), 10))
  2969. form.Set("max_sessions", strconv.FormatInt(int64(user.MaxSessions), 10))
  2970. form.Set("quota_size", strconv.FormatInt(user.QuotaSize, 10))
  2971. form.Set("quota_files", strconv.FormatInt(int64(user.QuotaFiles), 10))
  2972. form.Set("upload_bandwidth", "0")
  2973. form.Set("download_bandwidth", "0")
  2974. form.Set("permissions", "*")
  2975. form.Set("sub_dirs_permissions", "/otherdir :: list ,upload ")
  2976. form.Set("status", strconv.Itoa(user.Status))
  2977. form.Set("expiration_date", "2020-01-01 00:00:00")
  2978. form.Set("allowed_ip", " 192.168.1.3/32, 192.168.2.0/24 ")
  2979. form.Set("denied_ip", " 10.0.0.2/32 ")
  2980. form.Set("denied_extensions", "/dir1::.zip")
  2981. form.Set("ssh_login_methods", dataprovider.SSHLoginMethodKeyboardInteractive)
  2982. form.Set("denied_protocols", common.ProtocolFTP)
  2983. form.Set("max_upload_file_size", "100")
  2984. form.Set("disconnect", "1")
  2985. form.Set("additional_info", user.AdditionalInfo)
  2986. b, contentType, _ := getMultipartFormData(form, "", "")
  2987. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  2988. req.Header.Set("Content-Type", contentType)
  2989. rr = executeRequest(req)
  2990. checkResponseCode(t, http.StatusSeeOther, rr.Code)
  2991. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=0&order=ASC&username="+user.Username, nil)
  2992. rr = executeRequest(req)
  2993. checkResponseCode(t, http.StatusOK, rr.Code)
  2994. var users []dataprovider.User
  2995. err = render.DecodeJSON(rr.Body, &users)
  2996. assert.NoError(t, err)
  2997. assert.Equal(t, 1, len(users))
  2998. updateUser := users[0]
  2999. assert.Equal(t, user.HomeDir, updateUser.HomeDir)
  3000. assert.Equal(t, user.MaxSessions, updateUser.MaxSessions)
  3001. assert.Equal(t, user.QuotaFiles, updateUser.QuotaFiles)
  3002. assert.Equal(t, user.QuotaSize, updateUser.QuotaSize)
  3003. assert.Equal(t, user.UID, updateUser.UID)
  3004. assert.Equal(t, user.GID, updateUser.GID)
  3005. assert.Equal(t, user.AdditionalInfo, updateUser.AdditionalInfo)
  3006. assert.Equal(t, int64(100), updateUser.Filters.MaxUploadFileSize)
  3007. if val, ok := updateUser.Permissions["/otherdir"]; ok {
  3008. assert.True(t, utils.IsStringInSlice(dataprovider.PermListItems, val))
  3009. assert.True(t, utils.IsStringInSlice(dataprovider.PermUpload, val))
  3010. } else {
  3011. assert.Fail(t, "user permissions must contains /otherdir", "actual: %v", updateUser.Permissions)
  3012. }
  3013. assert.True(t, utils.IsStringInSlice("192.168.1.3/32", updateUser.Filters.AllowedIP))
  3014. assert.True(t, utils.IsStringInSlice("10.0.0.2/32", updateUser.Filters.DeniedIP))
  3015. assert.True(t, utils.IsStringInSlice(dataprovider.SSHLoginMethodKeyboardInteractive, updateUser.Filters.DeniedLoginMethods))
  3016. assert.True(t, utils.IsStringInSlice(common.ProtocolFTP, updateUser.Filters.DeniedProtocols))
  3017. assert.True(t, utils.IsStringInSlice(".zip", updateUser.Filters.FileExtensions[0].DeniedExtensions))
  3018. req, err = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  3019. assert.NoError(t, err)
  3020. rr = executeRequest(req)
  3021. checkResponseCode(t, http.StatusOK, rr.Code)
  3022. }
  3023. func TestWebUserS3Mock(t *testing.T) {
  3024. user := getTestUser()
  3025. userAsJSON := getUserAsJSON(t, user)
  3026. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  3027. rr := executeRequest(req)
  3028. checkResponseCode(t, http.StatusOK, rr.Code)
  3029. err := render.DecodeJSON(rr.Body, &user)
  3030. assert.NoError(t, err)
  3031. user.FsConfig.Provider = dataprovider.S3FilesystemProvider
  3032. user.FsConfig.S3Config.Bucket = "test"
  3033. user.FsConfig.S3Config.Region = "eu-west-1"
  3034. user.FsConfig.S3Config.AccessKey = "access-key"
  3035. user.FsConfig.S3Config.AccessSecret = kms.NewPlainSecret("access-secret")
  3036. user.FsConfig.S3Config.Endpoint = "http://127.0.0.1:9000/path?a=b"
  3037. user.FsConfig.S3Config.StorageClass = "Standard"
  3038. user.FsConfig.S3Config.KeyPrefix = "somedir/subdir/"
  3039. user.FsConfig.S3Config.UploadPartSize = 5
  3040. user.FsConfig.S3Config.UploadConcurrency = 4
  3041. form := make(url.Values)
  3042. form.Set("username", user.Username)
  3043. form.Set("home_dir", user.HomeDir)
  3044. form.Set("uid", "0")
  3045. form.Set("gid", strconv.FormatInt(int64(user.GID), 10))
  3046. form.Set("max_sessions", strconv.FormatInt(int64(user.MaxSessions), 10))
  3047. form.Set("quota_size", strconv.FormatInt(user.QuotaSize, 10))
  3048. form.Set("quota_files", strconv.FormatInt(int64(user.QuotaFiles), 10))
  3049. form.Set("upload_bandwidth", "0")
  3050. form.Set("download_bandwidth", "0")
  3051. form.Set("permissions", "*")
  3052. form.Set("sub_dirs_permissions", "")
  3053. form.Set("status", strconv.Itoa(user.Status))
  3054. form.Set("expiration_date", "2020-01-01 00:00:00")
  3055. form.Set("allowed_ip", "")
  3056. form.Set("denied_ip", "")
  3057. form.Set("fs_provider", "1")
  3058. form.Set("s3_bucket", user.FsConfig.S3Config.Bucket)
  3059. form.Set("s3_region", user.FsConfig.S3Config.Region)
  3060. form.Set("s3_access_key", user.FsConfig.S3Config.AccessKey)
  3061. form.Set("s3_access_secret", user.FsConfig.S3Config.AccessSecret.GetPayload())
  3062. form.Set("s3_storage_class", user.FsConfig.S3Config.StorageClass)
  3063. form.Set("s3_endpoint", user.FsConfig.S3Config.Endpoint)
  3064. form.Set("s3_key_prefix", user.FsConfig.S3Config.KeyPrefix)
  3065. form.Set("allowed_extensions", "/dir1::.jpg,.png")
  3066. form.Set("denied_extensions", "/dir2::.zip")
  3067. form.Set("max_upload_file_size", "0")
  3068. // test invalid s3_upload_part_size
  3069. form.Set("s3_upload_part_size", "a")
  3070. b, contentType, _ := getMultipartFormData(form, "", "")
  3071. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  3072. req.Header.Set("Content-Type", contentType)
  3073. rr = executeRequest(req)
  3074. checkResponseCode(t, http.StatusOK, rr.Code)
  3075. // test invalid s3_concurrency
  3076. form.Set("s3_upload_part_size", strconv.FormatInt(user.FsConfig.S3Config.UploadPartSize, 10))
  3077. form.Set("s3_upload_concurrency", "a")
  3078. b, contentType, _ = getMultipartFormData(form, "", "")
  3079. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  3080. req.Header.Set("Content-Type", contentType)
  3081. rr = executeRequest(req)
  3082. checkResponseCode(t, http.StatusOK, rr.Code)
  3083. // now add the user
  3084. form.Set("s3_upload_concurrency", strconv.Itoa(user.FsConfig.S3Config.UploadConcurrency))
  3085. b, contentType, _ = getMultipartFormData(form, "", "")
  3086. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  3087. req.Header.Set("Content-Type", contentType)
  3088. rr = executeRequest(req)
  3089. checkResponseCode(t, http.StatusSeeOther, rr.Code)
  3090. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=0&order=ASC&username="+user.Username, nil)
  3091. rr = executeRequest(req)
  3092. checkResponseCode(t, http.StatusOK, rr.Code)
  3093. var users []dataprovider.User
  3094. err = render.DecodeJSON(rr.Body, &users)
  3095. assert.NoError(t, err)
  3096. assert.Equal(t, 1, len(users))
  3097. updateUser := users[0]
  3098. assert.Equal(t, int64(1577836800000), updateUser.ExpirationDate)
  3099. assert.Equal(t, updateUser.FsConfig.S3Config.Bucket, user.FsConfig.S3Config.Bucket)
  3100. assert.Equal(t, updateUser.FsConfig.S3Config.Region, user.FsConfig.S3Config.Region)
  3101. assert.Equal(t, updateUser.FsConfig.S3Config.AccessKey, user.FsConfig.S3Config.AccessKey)
  3102. assert.Equal(t, updateUser.FsConfig.S3Config.StorageClass, user.FsConfig.S3Config.StorageClass)
  3103. assert.Equal(t, updateUser.FsConfig.S3Config.Endpoint, user.FsConfig.S3Config.Endpoint)
  3104. assert.Equal(t, updateUser.FsConfig.S3Config.KeyPrefix, user.FsConfig.S3Config.KeyPrefix)
  3105. assert.Equal(t, updateUser.FsConfig.S3Config.UploadPartSize, user.FsConfig.S3Config.UploadPartSize)
  3106. assert.Equal(t, updateUser.FsConfig.S3Config.UploadConcurrency, user.FsConfig.S3Config.UploadConcurrency)
  3107. assert.Equal(t, 2, len(updateUser.Filters.FileExtensions))
  3108. assert.Equal(t, kms.SecretStatusSecretBox, updateUser.FsConfig.S3Config.AccessSecret.GetStatus())
  3109. assert.NotEmpty(t, updateUser.FsConfig.S3Config.AccessSecret.GetPayload())
  3110. assert.Empty(t, updateUser.FsConfig.S3Config.AccessSecret.GetKey())
  3111. assert.Empty(t, updateUser.FsConfig.S3Config.AccessSecret.GetAdditionalData())
  3112. // now check that a redacted password is not saved
  3113. form.Set("s3_access_secret", "[**redacted**] ")
  3114. b, contentType, _ = getMultipartFormData(form, "", "")
  3115. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  3116. req.Header.Set("Content-Type", contentType)
  3117. rr = executeRequest(req)
  3118. checkResponseCode(t, http.StatusSeeOther, rr.Code)
  3119. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=0&order=ASC&username="+user.Username, nil)
  3120. rr = executeRequest(req)
  3121. checkResponseCode(t, http.StatusOK, rr.Code)
  3122. users = nil
  3123. err = render.DecodeJSON(rr.Body, &users)
  3124. assert.NoError(t, err)
  3125. assert.Equal(t, 1, len(users))
  3126. lastUpdatedUser := users[0]
  3127. assert.Equal(t, kms.SecretStatusSecretBox, lastUpdatedUser.FsConfig.S3Config.AccessSecret.GetStatus())
  3128. assert.Equal(t, updateUser.FsConfig.S3Config.AccessSecret.GetPayload(), lastUpdatedUser.FsConfig.S3Config.AccessSecret.GetPayload())
  3129. assert.Empty(t, lastUpdatedUser.FsConfig.S3Config.AccessSecret.GetKey())
  3130. assert.Empty(t, lastUpdatedUser.FsConfig.S3Config.AccessSecret.GetAdditionalData())
  3131. // now clear credentials
  3132. form.Set("s3_access_key", "")
  3133. form.Set("s3_access_secret", "")
  3134. b, contentType, _ = getMultipartFormData(form, "", "")
  3135. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  3136. req.Header.Set("Content-Type", contentType)
  3137. rr = executeRequest(req)
  3138. checkResponseCode(t, http.StatusSeeOther, rr.Code)
  3139. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=0&order=ASC&username="+user.Username, nil)
  3140. rr = executeRequest(req)
  3141. checkResponseCode(t, http.StatusOK, rr.Code)
  3142. users = nil
  3143. err = render.DecodeJSON(rr.Body, &users)
  3144. assert.NoError(t, err)
  3145. assert.Equal(t, 1, len(users))
  3146. assert.True(t, users[0].FsConfig.S3Config.AccessSecret.IsEmpty())
  3147. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  3148. rr = executeRequest(req)
  3149. checkResponseCode(t, http.StatusOK, rr.Code)
  3150. }
  3151. func TestWebUserGCSMock(t *testing.T) {
  3152. user := getTestUser()
  3153. userAsJSON := getUserAsJSON(t, user)
  3154. req, err := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  3155. assert.NoError(t, err)
  3156. rr := executeRequest(req)
  3157. checkResponseCode(t, http.StatusOK, rr.Code)
  3158. err = render.DecodeJSON(rr.Body, &user)
  3159. assert.NoError(t, err)
  3160. credentialsFilePath := filepath.Join(os.TempDir(), "gcs.json")
  3161. err = createTestFile(credentialsFilePath, 0)
  3162. assert.NoError(t, err)
  3163. user.FsConfig.Provider = dataprovider.GCSFilesystemProvider
  3164. user.FsConfig.GCSConfig.Bucket = "test"
  3165. user.FsConfig.GCSConfig.KeyPrefix = "somedir/subdir/"
  3166. user.FsConfig.GCSConfig.StorageClass = "standard"
  3167. form := make(url.Values)
  3168. form.Set("username", user.Username)
  3169. form.Set("home_dir", user.HomeDir)
  3170. form.Set("uid", "0")
  3171. form.Set("gid", strconv.FormatInt(int64(user.GID), 10))
  3172. form.Set("max_sessions", strconv.FormatInt(int64(user.MaxSessions), 10))
  3173. form.Set("quota_size", strconv.FormatInt(user.QuotaSize, 10))
  3174. form.Set("quota_files", strconv.FormatInt(int64(user.QuotaFiles), 10))
  3175. form.Set("upload_bandwidth", "0")
  3176. form.Set("download_bandwidth", "0")
  3177. form.Set("permissions", "*")
  3178. form.Set("sub_dirs_permissions", "")
  3179. form.Set("status", strconv.Itoa(user.Status))
  3180. form.Set("expiration_date", "2020-01-01 00:00:00")
  3181. form.Set("allowed_ip", "")
  3182. form.Set("denied_ip", "")
  3183. form.Set("fs_provider", "2")
  3184. form.Set("gcs_bucket", user.FsConfig.GCSConfig.Bucket)
  3185. form.Set("gcs_storage_class", user.FsConfig.GCSConfig.StorageClass)
  3186. form.Set("gcs_key_prefix", user.FsConfig.GCSConfig.KeyPrefix)
  3187. form.Set("allowed_extensions", "/dir1::.jpg,.png")
  3188. form.Set("max_upload_file_size", "0")
  3189. b, contentType, _ := getMultipartFormData(form, "", "")
  3190. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  3191. req.Header.Set("Content-Type", contentType)
  3192. rr = executeRequest(req)
  3193. checkResponseCode(t, http.StatusOK, rr.Code)
  3194. b, contentType, _ = getMultipartFormData(form, "gcs_credential_file", credentialsFilePath)
  3195. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  3196. req.Header.Set("Content-Type", contentType)
  3197. rr = executeRequest(req)
  3198. checkResponseCode(t, http.StatusOK, rr.Code)
  3199. err = createTestFile(credentialsFilePath, 4096)
  3200. assert.NoError(t, err)
  3201. b, contentType, _ = getMultipartFormData(form, "gcs_credential_file", credentialsFilePath)
  3202. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  3203. req.Header.Set("Content-Type", contentType)
  3204. rr = executeRequest(req)
  3205. checkResponseCode(t, http.StatusSeeOther, rr.Code)
  3206. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=0&order=ASC&username="+user.Username, nil)
  3207. rr = executeRequest(req)
  3208. checkResponseCode(t, http.StatusOK, rr.Code)
  3209. var users []dataprovider.User
  3210. err = render.DecodeJSON(rr.Body, &users)
  3211. assert.NoError(t, err)
  3212. assert.Equal(t, 1, len(users))
  3213. updateUser := users[0]
  3214. assert.Equal(t, int64(1577836800000), updateUser.ExpirationDate)
  3215. assert.Equal(t, user.FsConfig.Provider, updateUser.FsConfig.Provider)
  3216. assert.Equal(t, user.FsConfig.GCSConfig.Bucket, updateUser.FsConfig.GCSConfig.Bucket)
  3217. assert.Equal(t, user.FsConfig.GCSConfig.StorageClass, updateUser.FsConfig.GCSConfig.StorageClass)
  3218. assert.Equal(t, user.FsConfig.GCSConfig.KeyPrefix, updateUser.FsConfig.GCSConfig.KeyPrefix)
  3219. assert.Equal(t, "/dir1", updateUser.Filters.FileExtensions[0].Path)
  3220. form.Set("gcs_auto_credentials", "on")
  3221. b, contentType, _ = getMultipartFormData(form, "", "")
  3222. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  3223. req.Header.Set("Content-Type", contentType)
  3224. rr = executeRequest(req)
  3225. checkResponseCode(t, http.StatusSeeOther, rr.Code)
  3226. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=0&order=ASC&username="+user.Username, nil)
  3227. rr = executeRequest(req)
  3228. checkResponseCode(t, http.StatusOK, rr.Code)
  3229. err = render.DecodeJSON(rr.Body, &users)
  3230. assert.NoError(t, err)
  3231. assert.Equal(t, 1, len(users))
  3232. updateUser = users[0]
  3233. assert.Equal(t, 1, updateUser.FsConfig.GCSConfig.AutomaticCredentials)
  3234. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  3235. rr = executeRequest(req)
  3236. checkResponseCode(t, http.StatusOK, rr.Code)
  3237. err = os.Remove(credentialsFilePath)
  3238. assert.NoError(t, err)
  3239. }
  3240. func TestWebUserAzureBlobMock(t *testing.T) {
  3241. user := getTestUser()
  3242. userAsJSON := getUserAsJSON(t, user)
  3243. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  3244. rr := executeRequest(req)
  3245. checkResponseCode(t, http.StatusOK, rr.Code)
  3246. err := render.DecodeJSON(rr.Body, &user)
  3247. assert.NoError(t, err)
  3248. user.FsConfig.Provider = dataprovider.AzureBlobFilesystemProvider
  3249. user.FsConfig.AzBlobConfig.Container = "container"
  3250. user.FsConfig.AzBlobConfig.AccountName = "aname"
  3251. user.FsConfig.AzBlobConfig.AccountKey = kms.NewPlainSecret("access-skey")
  3252. user.FsConfig.AzBlobConfig.Endpoint = "http://127.0.0.1:9000/path?b=c"
  3253. user.FsConfig.AzBlobConfig.KeyPrefix = "somedir/subdir/"
  3254. user.FsConfig.AzBlobConfig.UploadPartSize = 5
  3255. user.FsConfig.AzBlobConfig.UploadConcurrency = 4
  3256. user.FsConfig.AzBlobConfig.UseEmulator = true
  3257. form := make(url.Values)
  3258. form.Set("username", user.Username)
  3259. form.Set("home_dir", user.HomeDir)
  3260. form.Set("uid", "0")
  3261. form.Set("gid", strconv.FormatInt(int64(user.GID), 10))
  3262. form.Set("max_sessions", strconv.FormatInt(int64(user.MaxSessions), 10))
  3263. form.Set("quota_size", strconv.FormatInt(user.QuotaSize, 10))
  3264. form.Set("quota_files", strconv.FormatInt(int64(user.QuotaFiles), 10))
  3265. form.Set("upload_bandwidth", "0")
  3266. form.Set("download_bandwidth", "0")
  3267. form.Set("permissions", "*")
  3268. form.Set("sub_dirs_permissions", "")
  3269. form.Set("status", strconv.Itoa(user.Status))
  3270. form.Set("expiration_date", "2020-01-01 00:00:00")
  3271. form.Set("allowed_ip", "")
  3272. form.Set("denied_ip", "")
  3273. form.Set("fs_provider", "3")
  3274. form.Set("az_container", user.FsConfig.AzBlobConfig.Container)
  3275. form.Set("az_account_name", user.FsConfig.AzBlobConfig.AccountName)
  3276. form.Set("az_account_key", user.FsConfig.AzBlobConfig.AccountKey.GetPayload())
  3277. form.Set("az_sas_url", user.FsConfig.AzBlobConfig.SASURL)
  3278. form.Set("az_endpoint", user.FsConfig.AzBlobConfig.Endpoint)
  3279. form.Set("az_key_prefix", user.FsConfig.AzBlobConfig.KeyPrefix)
  3280. form.Set("az_use_emulator", "checked")
  3281. form.Set("allowed_extensions", "/dir1::.jpg,.png")
  3282. form.Set("denied_extensions", "/dir2::.zip")
  3283. form.Set("max_upload_file_size", "0")
  3284. // test invalid az_upload_part_size
  3285. form.Set("az_upload_part_size", "a")
  3286. b, contentType, _ := getMultipartFormData(form, "", "")
  3287. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  3288. req.Header.Set("Content-Type", contentType)
  3289. rr = executeRequest(req)
  3290. checkResponseCode(t, http.StatusOK, rr.Code)
  3291. // test invalid az_upload_concurrency
  3292. form.Set("az_upload_part_size", strconv.FormatInt(user.FsConfig.AzBlobConfig.UploadPartSize, 10))
  3293. form.Set("az_upload_concurrency", "a")
  3294. b, contentType, _ = getMultipartFormData(form, "", "")
  3295. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  3296. req.Header.Set("Content-Type", contentType)
  3297. rr = executeRequest(req)
  3298. checkResponseCode(t, http.StatusOK, rr.Code)
  3299. // now add the user
  3300. form.Set("az_upload_concurrency", strconv.Itoa(user.FsConfig.AzBlobConfig.UploadConcurrency))
  3301. b, contentType, _ = getMultipartFormData(form, "", "")
  3302. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  3303. req.Header.Set("Content-Type", contentType)
  3304. rr = executeRequest(req)
  3305. checkResponseCode(t, http.StatusSeeOther, rr.Code)
  3306. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=0&order=ASC&username="+user.Username, nil)
  3307. rr = executeRequest(req)
  3308. checkResponseCode(t, http.StatusOK, rr.Code)
  3309. var users []dataprovider.User
  3310. err = render.DecodeJSON(rr.Body, &users)
  3311. assert.NoError(t, err)
  3312. assert.Equal(t, 1, len(users))
  3313. updateUser := users[0]
  3314. assert.Equal(t, int64(1577836800000), updateUser.ExpirationDate)
  3315. assert.Equal(t, updateUser.FsConfig.AzBlobConfig.Container, user.FsConfig.AzBlobConfig.Container)
  3316. assert.Equal(t, updateUser.FsConfig.AzBlobConfig.AccountName, user.FsConfig.AzBlobConfig.AccountName)
  3317. assert.Equal(t, updateUser.FsConfig.AzBlobConfig.Endpoint, user.FsConfig.AzBlobConfig.Endpoint)
  3318. assert.Equal(t, updateUser.FsConfig.AzBlobConfig.SASURL, user.FsConfig.AzBlobConfig.SASURL)
  3319. assert.Equal(t, updateUser.FsConfig.AzBlobConfig.KeyPrefix, user.FsConfig.AzBlobConfig.KeyPrefix)
  3320. assert.Equal(t, updateUser.FsConfig.AzBlobConfig.UploadPartSize, user.FsConfig.AzBlobConfig.UploadPartSize)
  3321. assert.Equal(t, updateUser.FsConfig.AzBlobConfig.UploadConcurrency, user.FsConfig.AzBlobConfig.UploadConcurrency)
  3322. assert.Equal(t, 2, len(updateUser.Filters.FileExtensions))
  3323. assert.Equal(t, kms.SecretStatusSecretBox, updateUser.FsConfig.AzBlobConfig.AccountKey.GetStatus())
  3324. assert.NotEmpty(t, updateUser.FsConfig.AzBlobConfig.AccountKey.GetPayload())
  3325. assert.Empty(t, updateUser.FsConfig.AzBlobConfig.AccountKey.GetKey())
  3326. assert.Empty(t, updateUser.FsConfig.AzBlobConfig.AccountKey.GetAdditionalData())
  3327. // now check that a redacted password is not saved
  3328. form.Set("az_account_key", "[**redacted**] ")
  3329. b, contentType, _ = getMultipartFormData(form, "", "")
  3330. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  3331. req.Header.Set("Content-Type", contentType)
  3332. rr = executeRequest(req)
  3333. checkResponseCode(t, http.StatusSeeOther, rr.Code)
  3334. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=0&order=ASC&username="+user.Username, nil)
  3335. rr = executeRequest(req)
  3336. checkResponseCode(t, http.StatusOK, rr.Code)
  3337. users = nil
  3338. err = render.DecodeJSON(rr.Body, &users)
  3339. assert.NoError(t, err)
  3340. assert.Equal(t, 1, len(users))
  3341. lastUpdatedUser := users[0]
  3342. assert.Equal(t, kms.SecretStatusSecretBox, lastUpdatedUser.FsConfig.AzBlobConfig.AccountKey.GetStatus())
  3343. assert.Equal(t, updateUser.FsConfig.AzBlobConfig.AccountKey.GetPayload(), lastUpdatedUser.FsConfig.AzBlobConfig.AccountKey.GetPayload())
  3344. assert.Empty(t, lastUpdatedUser.FsConfig.AzBlobConfig.AccountKey.GetKey())
  3345. assert.Empty(t, lastUpdatedUser.FsConfig.AzBlobConfig.AccountKey.GetAdditionalData())
  3346. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  3347. rr = executeRequest(req)
  3348. checkResponseCode(t, http.StatusOK, rr.Code)
  3349. }
  3350. func TestWebUserCryptMock(t *testing.T) {
  3351. user := getTestUser()
  3352. userAsJSON := getUserAsJSON(t, user)
  3353. req, _ := http.NewRequest(http.MethodPost, userPath, bytes.NewBuffer(userAsJSON))
  3354. rr := executeRequest(req)
  3355. checkResponseCode(t, http.StatusOK, rr.Code)
  3356. err := render.DecodeJSON(rr.Body, &user)
  3357. assert.NoError(t, err)
  3358. user.FsConfig.Provider = dataprovider.CryptedFilesystemProvider
  3359. user.FsConfig.CryptConfig.Passphrase = kms.NewPlainSecret("crypted passphrase")
  3360. form := make(url.Values)
  3361. form.Set("username", user.Username)
  3362. form.Set("home_dir", user.HomeDir)
  3363. form.Set("uid", "0")
  3364. form.Set("gid", strconv.FormatInt(int64(user.GID), 10))
  3365. form.Set("max_sessions", strconv.FormatInt(int64(user.MaxSessions), 10))
  3366. form.Set("quota_size", strconv.FormatInt(user.QuotaSize, 10))
  3367. form.Set("quota_files", strconv.FormatInt(int64(user.QuotaFiles), 10))
  3368. form.Set("upload_bandwidth", "0")
  3369. form.Set("download_bandwidth", "0")
  3370. form.Set("permissions", "*")
  3371. form.Set("sub_dirs_permissions", "")
  3372. form.Set("status", strconv.Itoa(user.Status))
  3373. form.Set("expiration_date", "2020-01-01 00:00:00")
  3374. form.Set("allowed_ip", "")
  3375. form.Set("denied_ip", "")
  3376. form.Set("fs_provider", "4")
  3377. form.Set("crypt_passphrase", "")
  3378. form.Set("allowed_extensions", "/dir1::.jpg,.png")
  3379. form.Set("denied_extensions", "/dir2::.zip")
  3380. form.Set("max_upload_file_size", "0")
  3381. // passphrase cannot be empty
  3382. b, contentType, _ := getMultipartFormData(form, "", "")
  3383. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  3384. req.Header.Set("Content-Type", contentType)
  3385. rr = executeRequest(req)
  3386. checkResponseCode(t, http.StatusOK, rr.Code)
  3387. form.Set("crypt_passphrase", user.FsConfig.CryptConfig.Passphrase.GetPayload())
  3388. b, contentType, _ = getMultipartFormData(form, "", "")
  3389. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  3390. req.Header.Set("Content-Type", contentType)
  3391. rr = executeRequest(req)
  3392. checkResponseCode(t, http.StatusSeeOther, rr.Code)
  3393. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=0&order=ASC&username="+user.Username, nil)
  3394. rr = executeRequest(req)
  3395. checkResponseCode(t, http.StatusOK, rr.Code)
  3396. var users []dataprovider.User
  3397. err = render.DecodeJSON(rr.Body, &users)
  3398. assert.NoError(t, err)
  3399. assert.Equal(t, 1, len(users))
  3400. updateUser := users[0]
  3401. assert.Equal(t, int64(1577836800000), updateUser.ExpirationDate)
  3402. assert.Equal(t, 2, len(updateUser.Filters.FileExtensions))
  3403. assert.Equal(t, kms.SecretStatusSecretBox, updateUser.FsConfig.CryptConfig.Passphrase.GetStatus())
  3404. assert.NotEmpty(t, updateUser.FsConfig.CryptConfig.Passphrase.GetPayload())
  3405. assert.Empty(t, updateUser.FsConfig.CryptConfig.Passphrase.GetKey())
  3406. assert.Empty(t, updateUser.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
  3407. // now check that a redacted password is not saved
  3408. form.Set("crypt_passphrase", "[**redacted**] ")
  3409. b, contentType, _ = getMultipartFormData(form, "", "")
  3410. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/"+strconv.FormatInt(user.ID, 10), &b)
  3411. req.Header.Set("Content-Type", contentType)
  3412. rr = executeRequest(req)
  3413. checkResponseCode(t, http.StatusSeeOther, rr.Code)
  3414. req, _ = http.NewRequest(http.MethodGet, userPath+"?limit=1&offset=0&order=ASC&username="+user.Username, nil)
  3415. rr = executeRequest(req)
  3416. checkResponseCode(t, http.StatusOK, rr.Code)
  3417. users = nil
  3418. err = render.DecodeJSON(rr.Body, &users)
  3419. assert.NoError(t, err)
  3420. assert.Equal(t, 1, len(users))
  3421. lastUpdatedUser := users[0]
  3422. assert.Equal(t, kms.SecretStatusSecretBox, lastUpdatedUser.FsConfig.CryptConfig.Passphrase.GetStatus())
  3423. assert.Equal(t, updateUser.FsConfig.CryptConfig.Passphrase.GetPayload(), lastUpdatedUser.FsConfig.CryptConfig.Passphrase.GetPayload())
  3424. assert.Empty(t, lastUpdatedUser.FsConfig.CryptConfig.Passphrase.GetKey())
  3425. assert.Empty(t, lastUpdatedUser.FsConfig.CryptConfig.Passphrase.GetAdditionalData())
  3426. req, _ = http.NewRequest(http.MethodDelete, userPath+"/"+strconv.FormatInt(user.ID, 10), nil)
  3427. rr = executeRequest(req)
  3428. checkResponseCode(t, http.StatusOK, rr.Code)
  3429. }
  3430. func TestAddWebFoldersMock(t *testing.T) {
  3431. mappedPath := filepath.Clean(os.TempDir())
  3432. form := make(url.Values)
  3433. form.Set("mapped_path", mappedPath)
  3434. req, err := http.NewRequest(http.MethodPost, webFolderPath, strings.NewReader(form.Encode()))
  3435. assert.NoError(t, err)
  3436. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  3437. rr := executeRequest(req)
  3438. checkResponseCode(t, http.StatusSeeOther, rr.Code)
  3439. // adding the same folder will fail since the path must be unique
  3440. req, err = http.NewRequest(http.MethodPost, webFolderPath, strings.NewReader(form.Encode()))
  3441. assert.NoError(t, err)
  3442. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  3443. rr = executeRequest(req)
  3444. checkResponseCode(t, http.StatusOK, rr.Code)
  3445. // invalid form
  3446. req, err = http.NewRequest(http.MethodPost, webFolderPath, strings.NewReader(form.Encode()))
  3447. assert.NoError(t, err)
  3448. req.Header.Set("Content-Type", "text/plain; boundary=")
  3449. rr = executeRequest(req)
  3450. checkResponseCode(t, http.StatusOK, rr.Code)
  3451. // now render the add folder page
  3452. req, err = http.NewRequest(http.MethodGet, webFolderPath, nil)
  3453. assert.NoError(t, err)
  3454. rr = executeRequest(req)
  3455. checkResponseCode(t, http.StatusOK, rr.Code)
  3456. var folders []vfs.BaseVirtualFolder
  3457. url, err := url.Parse(folderPath)
  3458. assert.NoError(t, err)
  3459. q := url.Query()
  3460. q.Add("folder_path", mappedPath)
  3461. url.RawQuery = q.Encode()
  3462. req, _ = http.NewRequest(http.MethodGet, url.String(), nil)
  3463. rr = executeRequest(req)
  3464. checkResponseCode(t, http.StatusOK, rr.Code)
  3465. err = render.DecodeJSON(rr.Body, &folders)
  3466. assert.NoError(t, err)
  3467. if assert.Len(t, folders, 1) {
  3468. folder := folders[0]
  3469. assert.Equal(t, mappedPath, folder.MappedPath)
  3470. }
  3471. // cleanup
  3472. url, err = url.Parse(folderPath)
  3473. assert.NoError(t, err)
  3474. q = url.Query()
  3475. q.Add("folder_path", mappedPath)
  3476. url.RawQuery = q.Encode()
  3477. req, _ = http.NewRequest(http.MethodDelete, url.String(), nil)
  3478. rr = executeRequest(req)
  3479. checkResponseCode(t, http.StatusOK, rr.Code)
  3480. }
  3481. func TestWebFoldersMock(t *testing.T) {
  3482. mappedPath1 := filepath.Join(os.TempDir(), "vfolder1")
  3483. mappedPath2 := filepath.Join(os.TempDir(), "vfolder2")
  3484. folders := []vfs.BaseVirtualFolder{
  3485. {
  3486. MappedPath: mappedPath1,
  3487. },
  3488. {
  3489. MappedPath: mappedPath2,
  3490. },
  3491. }
  3492. for _, folder := range folders {
  3493. folderAsJSON, err := json.Marshal(folder)
  3494. assert.NoError(t, err)
  3495. req, _ := http.NewRequest(http.MethodPost, folderPath, bytes.NewBuffer(folderAsJSON))
  3496. rr := executeRequest(req)
  3497. checkResponseCode(t, http.StatusOK, rr.Code)
  3498. }
  3499. req, err := http.NewRequest(http.MethodGet, webFoldersPath, nil)
  3500. assert.NoError(t, err)
  3501. rr := executeRequest(req)
  3502. checkResponseCode(t, http.StatusOK, rr.Code)
  3503. req, err = http.NewRequest(http.MethodGet, webFoldersPath+"?qlimit=a", nil)
  3504. assert.NoError(t, err)
  3505. rr = executeRequest(req)
  3506. checkResponseCode(t, http.StatusOK, rr.Code)
  3507. req, err = http.NewRequest(http.MethodGet, webFoldersPath+"?qlimit=1", nil)
  3508. assert.NoError(t, err)
  3509. rr = executeRequest(req)
  3510. checkResponseCode(t, http.StatusOK, rr.Code)
  3511. for _, folder := range folders {
  3512. url, err := url.Parse(folderPath)
  3513. assert.NoError(t, err)
  3514. q := url.Query()
  3515. q.Add("folder_path", folder.MappedPath)
  3516. url.RawQuery = q.Encode()
  3517. req, _ := http.NewRequest(http.MethodDelete, url.String(), nil)
  3518. rr := executeRequest(req)
  3519. checkResponseCode(t, http.StatusOK, rr.Code)
  3520. }
  3521. }
  3522. func TestProviderClosedMock(t *testing.T) {
  3523. dataprovider.Close()
  3524. req, _ := http.NewRequest(http.MethodGet, webFoldersPath, nil)
  3525. rr := executeRequest(req)
  3526. checkResponseCode(t, http.StatusInternalServerError, rr.Code)
  3527. req, _ = http.NewRequest(http.MethodGet, webUsersPath, nil)
  3528. rr = executeRequest(req)
  3529. checkResponseCode(t, http.StatusInternalServerError, rr.Code)
  3530. req, _ = http.NewRequest(http.MethodGet, webUserPath+"/0", nil)
  3531. rr = executeRequest(req)
  3532. checkResponseCode(t, http.StatusInternalServerError, rr.Code)
  3533. form := make(url.Values)
  3534. form.Set("username", "test")
  3535. req, _ = http.NewRequest(http.MethodPost, webUserPath+"/0", strings.NewReader(form.Encode()))
  3536. rr = executeRequest(req)
  3537. checkResponseCode(t, http.StatusInternalServerError, rr.Code)
  3538. err := config.LoadConfig(configDir, "")
  3539. assert.NoError(t, err)
  3540. providerConf := config.GetProviderConf()
  3541. providerConf.CredentialsPath = credentialsPath
  3542. err = os.RemoveAll(credentialsPath)
  3543. assert.NoError(t, err)
  3544. err = dataprovider.Initialize(providerConf, configDir)
  3545. assert.NoError(t, err)
  3546. }
  3547. func TestGetWebConnectionsMock(t *testing.T) {
  3548. req, _ := http.NewRequest(http.MethodGet, webConnectionsPath, nil)
  3549. rr := executeRequest(req)
  3550. checkResponseCode(t, http.StatusOK, rr.Code)
  3551. }
  3552. func TestStaticFilesMock(t *testing.T) {
  3553. req, _ := http.NewRequest(http.MethodGet, "/static/favicon.ico", nil)
  3554. rr := executeRequest(req)
  3555. checkResponseCode(t, http.StatusOK, rr.Code)
  3556. }
  3557. func waitTCPListening(address string) {
  3558. for {
  3559. conn, err := net.Dial("tcp", address)
  3560. if err != nil {
  3561. logger.WarnToConsole("tcp server %v not listening: %v\n", address, err)
  3562. time.Sleep(100 * time.Millisecond)
  3563. continue
  3564. }
  3565. logger.InfoToConsole("tcp server %v now listening\n", address)
  3566. conn.Close()
  3567. break
  3568. }
  3569. }
  3570. func getTestUser() dataprovider.User {
  3571. user := dataprovider.User{
  3572. Username: defaultUsername,
  3573. Password: defaultPassword,
  3574. HomeDir: filepath.Join(homeBasePath, defaultUsername),
  3575. Status: 1,
  3576. }
  3577. user.Permissions = make(map[string][]string)
  3578. user.Permissions["/"] = defaultPerms
  3579. return user
  3580. }
  3581. func getUserAsJSON(t *testing.T, user dataprovider.User) []byte {
  3582. json, err := json.Marshal(user)
  3583. assert.NoError(t, err)
  3584. return json
  3585. }
  3586. func executeRequest(req *http.Request) *httptest.ResponseRecorder {
  3587. rr := httptest.NewRecorder()
  3588. testServer.Config.Handler.ServeHTTP(rr, req)
  3589. return rr
  3590. }
  3591. func checkResponseCode(t *testing.T, expected, actual int) {
  3592. assert.Equal(t, expected, actual)
  3593. }
  3594. func createTestFile(path string, size int64) error {
  3595. baseDir := filepath.Dir(path)
  3596. if _, err := os.Stat(baseDir); os.IsNotExist(err) {
  3597. err = os.MkdirAll(baseDir, os.ModePerm)
  3598. if err != nil {
  3599. return err
  3600. }
  3601. }
  3602. content := make([]byte, size)
  3603. if size > 0 {
  3604. _, err := rand.Read(content)
  3605. if err != nil {
  3606. return err
  3607. }
  3608. }
  3609. return ioutil.WriteFile(path, content, os.ModePerm)
  3610. }
  3611. func getMultipartFormData(values url.Values, fileFieldName, filePath string) (bytes.Buffer, string, error) {
  3612. var b bytes.Buffer
  3613. w := multipart.NewWriter(&b)
  3614. for k, v := range values {
  3615. for _, s := range v {
  3616. if err := w.WriteField(k, s); err != nil {
  3617. return b, "", err
  3618. }
  3619. }
  3620. }
  3621. if len(fileFieldName) > 0 && len(filePath) > 0 {
  3622. fw, err := w.CreateFormFile(fileFieldName, filepath.Base(filePath))
  3623. if err != nil {
  3624. return b, "", err
  3625. }
  3626. f, err := os.Open(filePath)
  3627. if err != nil {
  3628. return b, "", err
  3629. }
  3630. defer f.Close()
  3631. if _, err = io.Copy(fw, f); err != nil {
  3632. return b, "", err
  3633. }
  3634. }
  3635. err := w.Close()
  3636. return b, w.FormDataContentType(), err
  3637. }
  3638. func BenchmarkSecretDecryption(b *testing.B) {
  3639. s := kms.NewPlainSecret("test data")
  3640. s.SetAdditionalData("username")
  3641. err := s.Encrypt()
  3642. require.NoError(b, err)
  3643. for i := 0; i < b.N; i++ {
  3644. err = s.Clone().Decrypt()
  3645. require.NoError(b, err)
  3646. }
  3647. }