protocol_test.go 214 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491
  1. // Copyright (C) 2019-2022 Nicola Murino
  2. //
  3. // This program is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU Affero General Public License as published
  5. // by the Free Software Foundation, version 3.
  6. //
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU Affero General Public License for more details.
  11. //
  12. // You should have received a copy of the GNU Affero General Public License
  13. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. package common_test
  15. import (
  16. "bufio"
  17. "bytes"
  18. "crypto/rand"
  19. "encoding/json"
  20. "errors"
  21. "fmt"
  22. "io"
  23. "math"
  24. "net"
  25. "net/http"
  26. "os"
  27. "path"
  28. "path/filepath"
  29. "runtime"
  30. "strings"
  31. "sync"
  32. "testing"
  33. "time"
  34. _ "github.com/go-sql-driver/mysql"
  35. _ "github.com/jackc/pgx/v5/stdlib"
  36. _ "github.com/mattn/go-sqlite3"
  37. "github.com/mhale/smtpd"
  38. "github.com/minio/sio"
  39. "github.com/pkg/sftp"
  40. "github.com/pquerna/otp"
  41. "github.com/pquerna/otp/totp"
  42. "github.com/rs/xid"
  43. "github.com/rs/zerolog"
  44. "github.com/sftpgo/sdk"
  45. "github.com/stretchr/testify/assert"
  46. "github.com/stretchr/testify/require"
  47. "golang.org/x/crypto/ssh"
  48. "github.com/drakkan/sftpgo/v2/internal/common"
  49. "github.com/drakkan/sftpgo/v2/internal/config"
  50. "github.com/drakkan/sftpgo/v2/internal/dataprovider"
  51. "github.com/drakkan/sftpgo/v2/internal/httpclient"
  52. "github.com/drakkan/sftpgo/v2/internal/httpdtest"
  53. "github.com/drakkan/sftpgo/v2/internal/kms"
  54. "github.com/drakkan/sftpgo/v2/internal/logger"
  55. "github.com/drakkan/sftpgo/v2/internal/mfa"
  56. "github.com/drakkan/sftpgo/v2/internal/sftpd"
  57. "github.com/drakkan/sftpgo/v2/internal/smtp"
  58. "github.com/drakkan/sftpgo/v2/internal/util"
  59. "github.com/drakkan/sftpgo/v2/internal/vfs"
  60. )
  61. const (
  62. httpAddr = "127.0.0.1:9999"
  63. httpProxyAddr = "127.0.0.1:7777"
  64. sftpServerAddr = "127.0.0.1:4022"
  65. smtpServerAddr = "127.0.0.1:2525"
  66. defaultUsername = "test_common_sftp"
  67. defaultPassword = "test_password"
  68. defaultSFTPUsername = "test_common_sftpfs_user"
  69. osWindows = "windows"
  70. testFileName = "test_file_common_sftp.dat"
  71. testDir = "test_dir_common"
  72. )
  73. var (
  74. configDir = filepath.Join(".", "..", "..")
  75. allPerms = []string{dataprovider.PermAny}
  76. homeBasePath string
  77. logFilePath string
  78. backupsPath string
  79. testFileContent = []byte("test data")
  80. lastReceivedEmail receivedEmail
  81. )
  82. func TestMain(m *testing.M) {
  83. homeBasePath = os.TempDir()
  84. logFilePath = filepath.Join(configDir, "common_test.log")
  85. backupsPath = filepath.Join(os.TempDir(), "backups")
  86. logger.InitLogger(logFilePath, 5, 1, 28, false, false, zerolog.DebugLevel)
  87. os.Setenv("SFTPGO_DATA_PROVIDER__CREATE_DEFAULT_ADMIN", "1")
  88. os.Setenv("SFTPGO_COMMON__ALLOW_SELF_CONNECTIONS", "1")
  89. os.Setenv("SFTPGO_DEFAULT_ADMIN_USERNAME", "admin")
  90. os.Setenv("SFTPGO_DEFAULT_ADMIN_PASSWORD", "password")
  91. err := config.LoadConfig(configDir, "")
  92. if err != nil {
  93. logger.ErrorToConsole("error loading configuration: %v", err)
  94. os.Exit(1)
  95. }
  96. providerConf := config.GetProviderConf()
  97. providerConf.BackupsPath = backupsPath
  98. logger.InfoToConsole("Starting COMMON tests, provider: %v", providerConf.Driver)
  99. err = common.Initialize(config.GetCommonConfig(), 0)
  100. if err != nil {
  101. logger.WarnToConsole("error initializing common: %v", err)
  102. os.Exit(1)
  103. }
  104. err = dataprovider.Initialize(providerConf, configDir, true)
  105. if err != nil {
  106. logger.ErrorToConsole("error initializing data provider: %v", err)
  107. os.Exit(1)
  108. }
  109. httpConfig := config.GetHTTPConfig()
  110. httpConfig.Timeout = 5
  111. httpConfig.RetryMax = 0
  112. httpConfig.Initialize(configDir) //nolint:errcheck
  113. kmsConfig := config.GetKMSConfig()
  114. err = kmsConfig.Initialize()
  115. if err != nil {
  116. logger.ErrorToConsole("error initializing kms: %v", err)
  117. os.Exit(1)
  118. }
  119. mfaConfig := config.GetMFAConfig()
  120. err = mfaConfig.Initialize()
  121. if err != nil {
  122. logger.ErrorToConsole("error initializing MFA: %v", err)
  123. os.Exit(1)
  124. }
  125. sftpdConf := config.GetSFTPDConfig()
  126. sftpdConf.Bindings[0].Port = 4022
  127. sftpdConf.Bindings = append(sftpdConf.Bindings, sftpd.Binding{
  128. Port: 4024,
  129. })
  130. sftpdConf.KeyboardInteractiveAuthentication = true
  131. httpdConf := config.GetHTTPDConfig()
  132. httpdConf.Bindings[0].Port = 4080
  133. httpdtest.SetBaseURL("http://127.0.0.1:4080")
  134. go func() {
  135. if err := sftpdConf.Initialize(configDir); err != nil {
  136. logger.ErrorToConsole("could not start SFTP server: %v", err)
  137. os.Exit(1)
  138. }
  139. }()
  140. go func() {
  141. if err := httpdConf.Initialize(configDir, 0); err != nil {
  142. logger.ErrorToConsole("could not start HTTP server: %v", err)
  143. os.Exit(1)
  144. }
  145. }()
  146. waitTCPListening(sftpdConf.Bindings[0].GetAddress())
  147. waitTCPListening(httpdConf.Bindings[0].GetAddress())
  148. go func() {
  149. // start a test HTTP server to receive action notifications
  150. http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  151. fmt.Fprintf(w, "OK\n")
  152. })
  153. http.HandleFunc("/404", func(w http.ResponseWriter, r *http.Request) {
  154. w.WriteHeader(http.StatusNotFound)
  155. fmt.Fprintf(w, "Not found\n")
  156. })
  157. http.HandleFunc("/multipart", func(w http.ResponseWriter, r *http.Request) {
  158. err := r.ParseMultipartForm(1048576)
  159. if err != nil {
  160. w.WriteHeader(http.StatusInternalServerError)
  161. fmt.Fprintf(w, "KO\n")
  162. return
  163. }
  164. defer r.MultipartForm.RemoveAll() //nolint:errcheck
  165. fmt.Fprintf(w, "OK\n")
  166. })
  167. if err := http.ListenAndServe(httpAddr, nil); err != nil {
  168. logger.ErrorToConsole("could not start HTTP notification server: %v", err)
  169. os.Exit(1)
  170. }
  171. }()
  172. go func() {
  173. common.Config.ProxyProtocol = 2
  174. listener, err := net.Listen("tcp", httpProxyAddr)
  175. if err != nil {
  176. logger.ErrorToConsole("error creating listener for proxy protocol server: %v", err)
  177. os.Exit(1)
  178. }
  179. proxyListener, err := common.Config.GetProxyListener(listener)
  180. if err != nil {
  181. logger.ErrorToConsole("error creating proxy protocol listener: %v", err)
  182. os.Exit(1)
  183. }
  184. common.Config.ProxyProtocol = 0
  185. s := &http.Server{}
  186. if err := s.Serve(proxyListener); err != nil {
  187. logger.ErrorToConsole("could not start HTTP proxy protocol server: %v", err)
  188. os.Exit(1)
  189. }
  190. }()
  191. go func() {
  192. if err := smtpd.ListenAndServe(smtpServerAddr, func(remoteAddr net.Addr, from string, to []string, data []byte) error {
  193. lastReceivedEmail.set(from, to, data)
  194. return nil
  195. }, "SFTPGo test", "localhost"); err != nil {
  196. logger.ErrorToConsole("could not start SMTP server: %v", err)
  197. os.Exit(1)
  198. }
  199. }()
  200. waitTCPListening(httpAddr)
  201. waitTCPListening(httpProxyAddr)
  202. waitTCPListening(smtpServerAddr)
  203. exitCode := m.Run()
  204. os.Remove(logFilePath)
  205. os.RemoveAll(backupsPath)
  206. os.Exit(exitCode)
  207. }
  208. func TestBaseConnection(t *testing.T) {
  209. u := getTestUser()
  210. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  211. assert.NoError(t, err)
  212. err = os.RemoveAll(user.GetHomeDir())
  213. assert.NoError(t, err)
  214. conn, client, err := getSftpClient(user)
  215. if assert.NoError(t, err) {
  216. defer conn.Close()
  217. defer client.Close()
  218. assert.NoError(t, checkBasicSFTP(client))
  219. _, err = client.ReadDir(testDir)
  220. assert.ErrorIs(t, err, os.ErrNotExist)
  221. err = client.RemoveDirectory(testDir)
  222. assert.ErrorIs(t, err, os.ErrNotExist)
  223. err = client.Mkdir(testDir)
  224. assert.NoError(t, err)
  225. err = client.Mkdir(testDir)
  226. assert.Error(t, err)
  227. info, err := client.Stat(testDir)
  228. if assert.NoError(t, err) {
  229. assert.True(t, info.IsDir())
  230. }
  231. err = client.Rename(testDir, testDir)
  232. if assert.Error(t, err) {
  233. assert.Contains(t, err.Error(), "the rename source and target cannot be the same")
  234. }
  235. err = client.RemoveDirectory(testDir)
  236. assert.NoError(t, err)
  237. err = client.Remove(testFileName)
  238. assert.ErrorIs(t, err, os.ErrNotExist)
  239. f, err := client.Create(testFileName)
  240. assert.NoError(t, err)
  241. _, err = f.Write(testFileContent)
  242. assert.NoError(t, err)
  243. err = f.Close()
  244. assert.NoError(t, err)
  245. linkName := testFileName + ".link"
  246. err = client.Rename(testFileName, testFileName)
  247. if assert.Error(t, err) {
  248. assert.Contains(t, err.Error(), "the rename source and target cannot be the same")
  249. }
  250. err = client.Symlink(testFileName, linkName)
  251. assert.NoError(t, err)
  252. err = client.Symlink(testFileName, testFileName)
  253. assert.Error(t, err)
  254. info, err = client.Stat(testFileName)
  255. if assert.NoError(t, err) {
  256. assert.Equal(t, int64(len(testFileContent)), info.Size())
  257. assert.False(t, info.IsDir())
  258. }
  259. info, err = client.Lstat(linkName)
  260. if assert.NoError(t, err) {
  261. assert.NotEqual(t, int64(7), info.Size())
  262. assert.True(t, info.Mode()&os.ModeSymlink != 0)
  263. assert.False(t, info.IsDir())
  264. }
  265. err = client.RemoveDirectory(linkName)
  266. if assert.Error(t, err) {
  267. assert.Contains(t, err.Error(), "SSH_FX_FAILURE")
  268. }
  269. err = client.Remove(testFileName)
  270. assert.NoError(t, err)
  271. err = client.Remove(linkName)
  272. assert.NoError(t, err)
  273. err = client.Rename(testFileName, "test")
  274. assert.ErrorIs(t, err, os.ErrNotExist)
  275. f, err = client.Create(testFileName)
  276. assert.NoError(t, err)
  277. err = f.Close()
  278. assert.NoError(t, err)
  279. err = client.Rename(testFileName, testFileName+"1")
  280. assert.NoError(t, err)
  281. err = client.Remove(testFileName + "1")
  282. assert.NoError(t, err)
  283. err = client.RemoveDirectory("missing")
  284. assert.Error(t, err)
  285. } else {
  286. printLatestLogs(10)
  287. }
  288. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  289. assert.NoError(t, err)
  290. err = os.RemoveAll(user.GetHomeDir())
  291. assert.NoError(t, err)
  292. }
  293. func TestRelativeSymlinks(t *testing.T) {
  294. u := getTestUser()
  295. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  296. assert.NoError(t, err)
  297. err = os.RemoveAll(user.GetHomeDir())
  298. assert.NoError(t, err)
  299. conn, client, err := getSftpClient(user)
  300. if assert.NoError(t, err) {
  301. defer conn.Close()
  302. defer client.Close()
  303. linkName := testFileName + "_link"
  304. err = client.Symlink("non-existent-file", linkName)
  305. assert.NoError(t, err)
  306. err = client.Remove(linkName)
  307. assert.NoError(t, err)
  308. testDir := "sub"
  309. err = client.Mkdir(testDir)
  310. assert.NoError(t, err)
  311. f, err := client.Create(path.Join(testDir, testFileName))
  312. assert.NoError(t, err)
  313. _, err = f.Write(testFileContent)
  314. assert.NoError(t, err)
  315. err = f.Close()
  316. assert.NoError(t, err)
  317. err = client.Symlink(path.Join(testDir, testFileName), linkName)
  318. assert.NoError(t, err)
  319. _, err = client.Stat(linkName)
  320. assert.NoError(t, err)
  321. p, err := client.ReadLink(linkName)
  322. assert.NoError(t, err)
  323. assert.Equal(t, path.Join("/", testDir, testFileName), p)
  324. err = client.Remove(linkName)
  325. assert.NoError(t, err)
  326. err = client.Symlink(testFileName, path.Join(testDir, linkName))
  327. assert.NoError(t, err)
  328. _, err = client.Stat(path.Join(testDir, linkName))
  329. assert.NoError(t, err)
  330. p, err = client.ReadLink(path.Join(testDir, linkName))
  331. assert.NoError(t, err)
  332. assert.Equal(t, path.Join("/", testDir, testFileName), p)
  333. f, err = client.Create(testFileName)
  334. assert.NoError(t, err)
  335. _, err = f.Write(testFileContent)
  336. assert.NoError(t, err)
  337. err = f.Close()
  338. assert.NoError(t, err)
  339. err = client.Symlink(testFileName, linkName)
  340. assert.NoError(t, err)
  341. _, err = client.Stat(linkName)
  342. assert.NoError(t, err)
  343. p, err = client.ReadLink(linkName)
  344. assert.NoError(t, err)
  345. assert.Equal(t, path.Join("/", testFileName), p)
  346. }
  347. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  348. assert.NoError(t, err)
  349. err = os.RemoveAll(user.GetHomeDir())
  350. assert.NoError(t, err)
  351. }
  352. func TestCheckFsAfterUpdate(t *testing.T) {
  353. u := getTestUser()
  354. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  355. assert.NoError(t, err)
  356. conn, client, err := getSftpClient(user)
  357. if assert.NoError(t, err) {
  358. defer conn.Close()
  359. defer client.Close()
  360. err = checkBasicSFTP(client)
  361. assert.NoError(t, err)
  362. }
  363. // remove the home dir, it will not be re-created
  364. err = os.RemoveAll(user.GetHomeDir())
  365. assert.NoError(t, err)
  366. conn, client, err = getSftpClient(user)
  367. if assert.NoError(t, err) {
  368. defer conn.Close()
  369. defer client.Close()
  370. err = checkBasicSFTP(client)
  371. assert.Error(t, err)
  372. } else {
  373. printLatestLogs(10)
  374. }
  375. // update the user and login again, this time the home dir will be created
  376. _, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  377. assert.NoError(t, err)
  378. conn, client, err = getSftpClient(user)
  379. if assert.NoError(t, err) {
  380. defer conn.Close()
  381. defer client.Close()
  382. err = checkBasicSFTP(client)
  383. assert.NoError(t, err)
  384. }
  385. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  386. assert.NoError(t, err)
  387. err = os.RemoveAll(user.GetHomeDir())
  388. assert.NoError(t, err)
  389. }
  390. func TestSetStat(t *testing.T) {
  391. u := getTestUser()
  392. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  393. assert.NoError(t, err)
  394. err = os.RemoveAll(user.GetHomeDir())
  395. assert.NoError(t, err)
  396. conn, client, err := getSftpClient(user)
  397. if assert.NoError(t, err) {
  398. defer conn.Close()
  399. defer client.Close()
  400. f, err := client.Create(testFileName)
  401. assert.NoError(t, err)
  402. _, err = f.Write(testFileContent)
  403. assert.NoError(t, err)
  404. err = f.Close()
  405. assert.NoError(t, err)
  406. acmodTime := time.Now().Add(36 * time.Hour)
  407. err = client.Chtimes(testFileName, acmodTime, acmodTime)
  408. assert.NoError(t, err)
  409. newFi, err := client.Lstat(testFileName)
  410. assert.NoError(t, err)
  411. diff := math.Abs(newFi.ModTime().Sub(acmodTime).Seconds())
  412. assert.LessOrEqual(t, diff, float64(1))
  413. if runtime.GOOS != osWindows {
  414. err = client.Chown(testFileName, os.Getuid(), os.Getgid())
  415. assert.NoError(t, err)
  416. }
  417. newPerm := os.FileMode(0666)
  418. err = client.Chmod(testFileName, newPerm)
  419. assert.NoError(t, err)
  420. newFi, err = client.Lstat(testFileName)
  421. if assert.NoError(t, err) {
  422. assert.Equal(t, newPerm, newFi.Mode().Perm())
  423. }
  424. err = client.Truncate(testFileName, 2)
  425. assert.NoError(t, err)
  426. info, err := client.Stat(testFileName)
  427. if assert.NoError(t, err) {
  428. assert.Equal(t, int64(2), info.Size())
  429. }
  430. err = client.Remove(testFileName)
  431. assert.NoError(t, err)
  432. err = client.Truncate(testFileName, 0)
  433. assert.ErrorIs(t, err, os.ErrNotExist)
  434. err = client.Chtimes(testFileName, acmodTime, acmodTime)
  435. assert.ErrorIs(t, err, os.ErrNotExist)
  436. if runtime.GOOS != osWindows {
  437. err = client.Chown(testFileName, os.Getuid(), os.Getgid())
  438. assert.ErrorIs(t, err, os.ErrNotExist)
  439. }
  440. err = client.Chmod(testFileName, newPerm)
  441. assert.ErrorIs(t, err, os.ErrNotExist)
  442. }
  443. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  444. assert.NoError(t, err)
  445. err = os.RemoveAll(user.GetHomeDir())
  446. assert.NoError(t, err)
  447. }
  448. func TestCryptFsUserUploadErrorOverwrite(t *testing.T) {
  449. u := getCryptFsUser()
  450. u.QuotaSize = 6000
  451. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  452. assert.NoError(t, err)
  453. var buf []byte
  454. for i := 0; i < 4000; i++ {
  455. buf = append(buf, []byte("a")...)
  456. }
  457. bufSize := int64(len(buf))
  458. reader := bytes.NewReader(buf)
  459. conn, client, err := getSftpClient(user)
  460. if assert.NoError(t, err) {
  461. defer conn.Close()
  462. defer client.Close()
  463. f, err := client.Create(testFileName + "_big")
  464. assert.NoError(t, err)
  465. n, err := io.Copy(f, reader)
  466. assert.NoError(t, err)
  467. assert.Equal(t, bufSize, n)
  468. err = f.Close()
  469. assert.NoError(t, err)
  470. encryptedSize, err := getEncryptedFileSize(bufSize)
  471. assert.NoError(t, err)
  472. expectedSize := encryptedSize
  473. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  474. assert.NoError(t, err)
  475. assert.Equal(t, 1, user.UsedQuotaFiles)
  476. assert.Equal(t, expectedSize, user.UsedQuotaSize)
  477. // now write a small file
  478. f, err = client.Create(testFileName)
  479. assert.NoError(t, err)
  480. _, err = f.Write(testFileContent)
  481. assert.NoError(t, err)
  482. err = f.Close()
  483. assert.NoError(t, err)
  484. encryptedSize, err = getEncryptedFileSize(int64(len(testFileContent)))
  485. assert.NoError(t, err)
  486. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  487. assert.NoError(t, err)
  488. assert.Equal(t, 2, user.UsedQuotaFiles)
  489. assert.Equal(t, expectedSize+encryptedSize, user.UsedQuotaSize)
  490. // try to overwrite this file with a big one, this cause an overquota error
  491. // the partial file is deleted and the quota updated
  492. _, err = reader.Seek(0, io.SeekStart)
  493. assert.NoError(t, err)
  494. f, err = client.Create(testFileName)
  495. assert.NoError(t, err)
  496. _, err = io.Copy(f, reader)
  497. assert.Error(t, err)
  498. err = f.Close()
  499. assert.Error(t, err)
  500. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  501. assert.NoError(t, err)
  502. assert.Equal(t, 1, user.UsedQuotaFiles)
  503. assert.Equal(t, expectedSize, user.UsedQuotaSize)
  504. }
  505. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  506. assert.NoError(t, err)
  507. err = os.RemoveAll(user.GetHomeDir())
  508. assert.NoError(t, err)
  509. }
  510. func TestChtimesOpenHandle(t *testing.T) {
  511. localUser, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  512. assert.NoError(t, err)
  513. sftpUser, _, err := httpdtest.AddUser(getTestSFTPUser(), http.StatusCreated)
  514. assert.NoError(t, err)
  515. u := getCryptFsUser()
  516. cryptFsUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  517. assert.NoError(t, err)
  518. for _, user := range []dataprovider.User{localUser, sftpUser, cryptFsUser} {
  519. conn, client, err := getSftpClient(user)
  520. if assert.NoError(t, err) {
  521. defer conn.Close()
  522. defer client.Close()
  523. f, err := client.Create(testFileName)
  524. assert.NoError(t, err, "user %v", user.Username)
  525. f1, err := client.Create(testFileName + "1")
  526. assert.NoError(t, err, "user %v", user.Username)
  527. acmodTime := time.Now().Add(36 * time.Hour)
  528. err = client.Chtimes(testFileName, acmodTime, acmodTime)
  529. assert.NoError(t, err, "user %v", user.Username)
  530. _, err = f.Write(testFileContent)
  531. assert.NoError(t, err, "user %v", user.Username)
  532. err = f.Close()
  533. assert.NoError(t, err, "user %v", user.Username)
  534. err = f1.Close()
  535. assert.NoError(t, err, "user %v", user.Username)
  536. info, err := client.Lstat(testFileName)
  537. assert.NoError(t, err, "user %v", user.Username)
  538. diff := math.Abs(info.ModTime().Sub(acmodTime).Seconds())
  539. assert.LessOrEqual(t, diff, float64(1), "user %v", user.Username)
  540. info1, err := client.Lstat(testFileName + "1")
  541. assert.NoError(t, err, "user %v", user.Username)
  542. diff = math.Abs(info1.ModTime().Sub(acmodTime).Seconds())
  543. assert.Greater(t, diff, float64(86400), "user %v", user.Username)
  544. }
  545. }
  546. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  547. assert.NoError(t, err)
  548. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  549. assert.NoError(t, err)
  550. err = os.RemoveAll(localUser.GetHomeDir())
  551. assert.NoError(t, err)
  552. _, err = httpdtest.RemoveUser(cryptFsUser, http.StatusOK)
  553. assert.NoError(t, err)
  554. err = os.RemoveAll(cryptFsUser.GetHomeDir())
  555. assert.NoError(t, err)
  556. }
  557. func TestCheckParentDirs(t *testing.T) {
  558. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  559. assert.NoError(t, err)
  560. testDir := "/path/to/sub/dir"
  561. conn, client, err := getSftpClient(user)
  562. if assert.NoError(t, err) {
  563. defer conn.Close()
  564. defer client.Close()
  565. _, err = client.Stat(testDir)
  566. assert.ErrorIs(t, err, os.ErrNotExist)
  567. c := common.NewBaseConnection(xid.New().String(), common.ProtocolSFTP, "", "", user)
  568. err = c.CheckParentDirs(testDir)
  569. assert.NoError(t, err)
  570. _, err = client.Stat(testDir)
  571. assert.NoError(t, err)
  572. err = c.CheckParentDirs(testDir)
  573. assert.NoError(t, err)
  574. }
  575. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  576. assert.NoError(t, err)
  577. err = os.RemoveAll(user.GetHomeDir())
  578. assert.NoError(t, err)
  579. u := getTestUser()
  580. u.Permissions["/"] = []string{dataprovider.PermUpload, dataprovider.PermListItems, dataprovider.PermDownload}
  581. user, _, err = httpdtest.AddUser(u, http.StatusCreated)
  582. assert.NoError(t, err)
  583. conn, client, err = getSftpClient(user)
  584. if assert.NoError(t, err) {
  585. defer conn.Close()
  586. defer client.Close()
  587. c := common.NewBaseConnection(xid.New().String(), common.ProtocolSFTP, "", "", user)
  588. err = c.CheckParentDirs(testDir)
  589. assert.ErrorIs(t, err, sftp.ErrSSHFxPermissionDenied)
  590. }
  591. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  592. assert.NoError(t, err)
  593. err = os.RemoveAll(user.GetHomeDir())
  594. assert.NoError(t, err)
  595. }
  596. func TestPermissionErrors(t *testing.T) {
  597. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  598. assert.NoError(t, err)
  599. u := getTestSFTPUser()
  600. subDir := "/sub"
  601. u.Permissions[subDir] = nil
  602. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  603. assert.NoError(t, err)
  604. conn, client, err := getSftpClient(user)
  605. if assert.NoError(t, err) {
  606. defer conn.Close()
  607. defer client.Close()
  608. err = client.MkdirAll(path.Join(subDir, subDir))
  609. assert.NoError(t, err)
  610. f, err := client.Create(path.Join(subDir, subDir, testFileName))
  611. if assert.NoError(t, err) {
  612. _, err = f.Write(testFileContent)
  613. assert.NoError(t, err)
  614. err = f.Close()
  615. assert.NoError(t, err)
  616. }
  617. }
  618. conn, client, err = getSftpClient(sftpUser)
  619. if assert.NoError(t, err) {
  620. defer conn.Close()
  621. defer client.Close()
  622. assert.NoError(t, checkBasicSFTP(client))
  623. _, err = client.ReadDir(subDir)
  624. assert.ErrorIs(t, err, os.ErrPermission)
  625. err = client.Mkdir(path.Join(subDir, subDir))
  626. assert.ErrorIs(t, err, os.ErrPermission)
  627. err = client.RemoveDirectory(path.Join(subDir, subDir))
  628. assert.ErrorIs(t, err, os.ErrPermission)
  629. err = client.Symlink("test", path.Join(subDir, subDir))
  630. assert.ErrorIs(t, err, os.ErrPermission)
  631. err = client.Chmod(path.Join(subDir, subDir), os.ModePerm)
  632. assert.ErrorIs(t, err, os.ErrPermission)
  633. err = client.Chown(path.Join(subDir, subDir), os.Getuid(), os.Getgid())
  634. assert.ErrorIs(t, err, os.ErrPermission)
  635. err = client.Chtimes(path.Join(subDir, subDir), time.Now(), time.Now())
  636. assert.ErrorIs(t, err, os.ErrPermission)
  637. err = client.Truncate(path.Join(subDir, subDir), 0)
  638. assert.ErrorIs(t, err, os.ErrPermission)
  639. err = client.Remove(path.Join(subDir, subDir, testFileName))
  640. assert.ErrorIs(t, err, os.ErrPermission)
  641. }
  642. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  643. assert.NoError(t, err)
  644. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  645. assert.NoError(t, err)
  646. err = os.RemoveAll(user.GetHomeDir())
  647. assert.NoError(t, err)
  648. }
  649. func TestHiddenPatternFilter(t *testing.T) {
  650. deniedDir := "/denied_hidden"
  651. u := getTestUser()
  652. u.Filters.FilePatterns = []sdk.PatternsFilter{
  653. {
  654. Path: deniedDir,
  655. DeniedPatterns: []string{"*.txt", "beta*"},
  656. DenyPolicy: sdk.DenyPolicyHide,
  657. },
  658. }
  659. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  660. assert.NoError(t, err)
  661. dirName := "beta"
  662. subDirName := "testDir"
  663. testFile := filepath.Join(u.GetHomeDir(), deniedDir, "file.txt")
  664. testFile1 := filepath.Join(u.GetHomeDir(), deniedDir, "beta.txt")
  665. testHiddenFile := filepath.Join(u.GetHomeDir(), deniedDir, dirName, subDirName, "hidden.jpg")
  666. err = os.MkdirAll(filepath.Join(u.GetHomeDir(), deniedDir), os.ModePerm)
  667. assert.NoError(t, err)
  668. err = os.WriteFile(testFile, testFileContent, os.ModePerm)
  669. assert.NoError(t, err)
  670. err = os.WriteFile(testFile1, testFileContent, os.ModePerm)
  671. assert.NoError(t, err)
  672. err = os.MkdirAll(filepath.Join(u.GetHomeDir(), deniedDir, dirName, subDirName), os.ModePerm)
  673. assert.NoError(t, err)
  674. err = os.WriteFile(testHiddenFile, testFileContent, os.ModePerm)
  675. assert.NoError(t, err)
  676. conn, client, err := getSftpClient(user)
  677. if assert.NoError(t, err) {
  678. defer conn.Close()
  679. defer client.Close()
  680. files, err := client.ReadDir(deniedDir)
  681. assert.NoError(t, err)
  682. assert.Len(t, files, 0)
  683. err = client.Remove(path.Join(deniedDir, filepath.Base(testFile)))
  684. assert.ErrorIs(t, err, os.ErrNotExist)
  685. err = client.Chtimes(path.Join(deniedDir, filepath.Base(testFile)), time.Now(), time.Now())
  686. assert.ErrorIs(t, err, os.ErrNotExist)
  687. _, err = client.Stat(path.Join(deniedDir, filepath.Base(testFile1)))
  688. assert.ErrorIs(t, err, os.ErrNotExist)
  689. err = client.RemoveDirectory(path.Join(deniedDir, dirName))
  690. assert.ErrorIs(t, err, os.ErrNotExist)
  691. err = client.Rename(path.Join(deniedDir, dirName), path.Join(deniedDir, "newname"))
  692. assert.ErrorIs(t, err, os.ErrPermission)
  693. err = client.Mkdir(path.Join(deniedDir, "beta1"))
  694. assert.ErrorIs(t, err, os.ErrPermission)
  695. err = writeSFTPFile(path.Join(deniedDir, "afile.txt"), 1024, client)
  696. assert.ErrorIs(t, err, os.ErrPermission)
  697. err = writeSFTPFile(path.Join(deniedDir, dirName, subDirName, "afile.jpg"), 1024, client)
  698. assert.ErrorIs(t, err, os.ErrPermission)
  699. _, err = client.Open(path.Join(deniedDir, dirName, subDirName, filepath.Base(testHiddenFile)))
  700. assert.ErrorIs(t, err, os.ErrNotExist)
  701. err = client.Symlink(path.Join(deniedDir, dirName), dirName)
  702. assert.ErrorIs(t, err, os.ErrNotExist)
  703. err = writeSFTPFile(path.Join(deniedDir, testFileName), 1024, client)
  704. assert.NoError(t, err)
  705. err = client.Symlink(path.Join(deniedDir, testFileName), path.Join(deniedDir, "symlink.txt"))
  706. assert.ErrorIs(t, err, os.ErrPermission)
  707. files, err = client.ReadDir(deniedDir)
  708. assert.NoError(t, err)
  709. assert.Len(t, files, 1)
  710. }
  711. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  712. assert.NoError(t, err)
  713. u.Filters.FilePatterns = []sdk.PatternsFilter{
  714. {
  715. Path: deniedDir,
  716. DeniedPatterns: []string{"*.txt", "beta*"},
  717. DenyPolicy: sdk.DenyPolicyDefault,
  718. },
  719. }
  720. user, _, err = httpdtest.AddUser(u, http.StatusCreated)
  721. assert.NoError(t, err)
  722. conn, client, err = getSftpClient(user)
  723. if assert.NoError(t, err) {
  724. defer conn.Close()
  725. defer client.Close()
  726. files, err := client.ReadDir(deniedDir)
  727. assert.NoError(t, err)
  728. assert.Len(t, files, 4)
  729. _, err = client.Stat(path.Join(deniedDir, filepath.Base(testFile)))
  730. assert.NoError(t, err)
  731. err = client.Chtimes(path.Join(deniedDir, filepath.Base(testFile)), time.Now(), time.Now())
  732. assert.ErrorIs(t, err, os.ErrPermission)
  733. err = client.Mkdir(path.Join(deniedDir, "beta2"))
  734. assert.ErrorIs(t, err, os.ErrPermission)
  735. err = writeSFTPFile(path.Join(deniedDir, "afile2.txt"), 1024, client)
  736. assert.ErrorIs(t, err, os.ErrPermission)
  737. err = client.Symlink(path.Join(deniedDir, testFileName), path.Join(deniedDir, "link.txt"))
  738. assert.ErrorIs(t, err, os.ErrPermission)
  739. err = writeSFTPFile(path.Join(deniedDir, dirName, subDirName, "afile.jpg"), 1024, client)
  740. assert.NoError(t, err)
  741. f, err := client.Open(path.Join(deniedDir, dirName, subDirName, filepath.Base(testHiddenFile)))
  742. assert.NoError(t, err)
  743. err = f.Close()
  744. assert.NoError(t, err)
  745. }
  746. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  747. assert.NoError(t, err)
  748. err = os.RemoveAll(user.GetHomeDir())
  749. assert.NoError(t, err)
  750. }
  751. func TestFileNotAllowedErrors(t *testing.T) {
  752. deniedDir := "/denied"
  753. u := getTestUser()
  754. u.Filters.FilePatterns = []sdk.PatternsFilter{
  755. {
  756. Path: deniedDir,
  757. DeniedPatterns: []string{"*.txt"},
  758. },
  759. }
  760. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  761. assert.NoError(t, err)
  762. conn, client, err := getSftpClient(user)
  763. if assert.NoError(t, err) {
  764. defer conn.Close()
  765. defer client.Close()
  766. testFile := filepath.Join(u.GetHomeDir(), deniedDir, "file.txt")
  767. err = os.MkdirAll(filepath.Join(u.GetHomeDir(), deniedDir), os.ModePerm)
  768. assert.NoError(t, err)
  769. err = os.WriteFile(testFile, testFileContent, os.ModePerm)
  770. assert.NoError(t, err)
  771. err = client.Remove(path.Join(deniedDir, "file.txt"))
  772. assert.ErrorIs(t, err, os.ErrPermission)
  773. err = client.Rename(path.Join(deniedDir, "file.txt"), path.Join(deniedDir, "file1.txt"))
  774. assert.ErrorIs(t, err, os.ErrPermission)
  775. }
  776. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  777. assert.NoError(t, err)
  778. err = os.RemoveAll(user.GetHomeDir())
  779. assert.NoError(t, err)
  780. }
  781. func TestRootDirVirtualFolder(t *testing.T) {
  782. u := getTestUser()
  783. u.QuotaFiles = 1000
  784. u.UploadDataTransfer = 1000
  785. u.DownloadDataTransfer = 5000
  786. mappedPath1 := filepath.Join(os.TempDir(), "mapped1")
  787. folderName1 := filepath.Base(mappedPath1)
  788. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  789. BaseVirtualFolder: vfs.BaseVirtualFolder{
  790. Name: folderName1,
  791. MappedPath: mappedPath1,
  792. FsConfig: vfs.Filesystem{
  793. Provider: sdk.CryptedFilesystemProvider,
  794. CryptConfig: vfs.CryptFsConfig{
  795. Passphrase: kms.NewPlainSecret("cryptsecret"),
  796. },
  797. },
  798. },
  799. VirtualPath: "/",
  800. QuotaFiles: 1000,
  801. })
  802. mappedPath2 := filepath.Join(os.TempDir(), "mapped2")
  803. folderName2 := filepath.Base(mappedPath2)
  804. vdirPath2 := "/vmapped"
  805. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  806. BaseVirtualFolder: vfs.BaseVirtualFolder{
  807. Name: folderName2,
  808. MappedPath: mappedPath2,
  809. },
  810. VirtualPath: vdirPath2,
  811. QuotaFiles: -1,
  812. QuotaSize: -1,
  813. })
  814. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  815. assert.NoError(t, err)
  816. f, err := user.GetVirtualFolderForPath("/")
  817. assert.NoError(t, err)
  818. assert.Equal(t, "/", f.VirtualPath)
  819. conn, client, err := getSftpClient(user)
  820. if assert.NoError(t, err) {
  821. defer conn.Close()
  822. defer client.Close()
  823. err = checkBasicSFTP(client)
  824. assert.NoError(t, err)
  825. f, err := client.Create(testFileName)
  826. if assert.NoError(t, err) {
  827. _, err = f.Write(testFileContent)
  828. assert.NoError(t, err)
  829. err = f.Close()
  830. assert.NoError(t, err)
  831. }
  832. assert.NoFileExists(t, filepath.Join(user.HomeDir, testFileName))
  833. assert.FileExists(t, filepath.Join(mappedPath1, testFileName))
  834. entries, err := client.ReadDir(".")
  835. if assert.NoError(t, err) {
  836. assert.Len(t, entries, 2)
  837. }
  838. user, _, err := httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  839. assert.NoError(t, err)
  840. assert.Equal(t, 0, user.UsedQuotaFiles)
  841. folder, _, err := httpdtest.GetFolderByName(folderName1, http.StatusOK)
  842. assert.NoError(t, err)
  843. assert.Equal(t, 1, folder.UsedQuotaFiles)
  844. f, err = client.Create(path.Join(vdirPath2, testFileName))
  845. if assert.NoError(t, err) {
  846. _, err = f.Write(testFileContent)
  847. assert.NoError(t, err)
  848. err = f.Close()
  849. assert.NoError(t, err)
  850. }
  851. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  852. assert.NoError(t, err)
  853. assert.Equal(t, 1, user.UsedQuotaFiles)
  854. folder, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
  855. assert.NoError(t, err)
  856. assert.Equal(t, 1, folder.UsedQuotaFiles)
  857. err = client.Rename(testFileName, path.Join(vdirPath2, testFileName+"_rename"))
  858. assert.Error(t, err)
  859. err = client.Rename(path.Join(vdirPath2, testFileName), testFileName+"_rename")
  860. assert.Error(t, err)
  861. err = client.Rename(testFileName, testFileName+"_rename")
  862. assert.NoError(t, err)
  863. err = client.Rename(path.Join(vdirPath2, testFileName), path.Join(vdirPath2, testFileName+"_rename"))
  864. assert.NoError(t, err)
  865. }
  866. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  867. assert.NoError(t, err)
  868. err = os.RemoveAll(user.GetHomeDir())
  869. assert.NoError(t, err)
  870. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName1}, http.StatusOK)
  871. assert.NoError(t, err)
  872. err = os.RemoveAll(mappedPath1)
  873. assert.NoError(t, err)
  874. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName2}, http.StatusOK)
  875. assert.NoError(t, err)
  876. err = os.RemoveAll(mappedPath2)
  877. assert.NoError(t, err)
  878. }
  879. func TestTruncateQuotaLimits(t *testing.T) {
  880. u := getTestUser()
  881. u.QuotaSize = 20
  882. u.UploadDataTransfer = 1000
  883. u.DownloadDataTransfer = 5000
  884. mappedPath1 := filepath.Join(os.TempDir(), "mapped1")
  885. folderName1 := filepath.Base(mappedPath1)
  886. vdirPath1 := "/vmapped1"
  887. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  888. BaseVirtualFolder: vfs.BaseVirtualFolder{
  889. Name: folderName1,
  890. MappedPath: mappedPath1,
  891. },
  892. VirtualPath: vdirPath1,
  893. QuotaFiles: 10,
  894. })
  895. mappedPath2 := filepath.Join(os.TempDir(), "mapped2")
  896. folderName2 := filepath.Base(mappedPath2)
  897. vdirPath2 := "/vmapped2"
  898. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  899. BaseVirtualFolder: vfs.BaseVirtualFolder{
  900. Name: folderName2,
  901. MappedPath: mappedPath2,
  902. },
  903. VirtualPath: vdirPath2,
  904. QuotaFiles: -1,
  905. QuotaSize: -1,
  906. })
  907. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  908. assert.NoError(t, err)
  909. u = getTestSFTPUser()
  910. u.QuotaSize = 20
  911. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  912. assert.NoError(t, err)
  913. for _, user := range []dataprovider.User{localUser, sftpUser} {
  914. conn, client, err := getSftpClient(user)
  915. if assert.NoError(t, err) {
  916. defer conn.Close()
  917. defer client.Close()
  918. f, err := client.OpenFile(testFileName, os.O_WRONLY|os.O_CREATE)
  919. if assert.NoError(t, err) {
  920. n, err := f.Write(testFileContent)
  921. assert.NoError(t, err)
  922. assert.Equal(t, len(testFileContent), n)
  923. err = f.Truncate(2)
  924. assert.NoError(t, err)
  925. expectedQuotaFiles := 0
  926. expectedQuotaSize := int64(2)
  927. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  928. assert.NoError(t, err)
  929. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  930. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  931. _, err = f.Seek(expectedQuotaSize, io.SeekStart)
  932. assert.NoError(t, err)
  933. n, err = f.Write(testFileContent)
  934. assert.NoError(t, err)
  935. assert.Equal(t, len(testFileContent), n)
  936. err = f.Truncate(5)
  937. assert.NoError(t, err)
  938. expectedQuotaSize = int64(5)
  939. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  940. assert.NoError(t, err)
  941. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  942. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  943. _, err = f.Seek(expectedQuotaSize, io.SeekStart)
  944. assert.NoError(t, err)
  945. n, err = f.Write(testFileContent)
  946. assert.NoError(t, err)
  947. assert.Equal(t, len(testFileContent), n)
  948. err = f.Close()
  949. assert.NoError(t, err)
  950. expectedQuotaFiles = 1
  951. expectedQuotaSize = int64(5) + int64(len(testFileContent))
  952. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  953. assert.NoError(t, err)
  954. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  955. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  956. }
  957. // now truncate by path
  958. err = client.Truncate(testFileName, 5)
  959. assert.NoError(t, err)
  960. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  961. assert.NoError(t, err)
  962. assert.Equal(t, 1, user.UsedQuotaFiles)
  963. assert.Equal(t, int64(5), user.UsedQuotaSize)
  964. // now open an existing file without truncate it, quota should not change
  965. f, err = client.OpenFile(testFileName, os.O_WRONLY)
  966. if assert.NoError(t, err) {
  967. err = f.Close()
  968. assert.NoError(t, err)
  969. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  970. assert.NoError(t, err)
  971. assert.Equal(t, 1, user.UsedQuotaFiles)
  972. assert.Equal(t, int64(5), user.UsedQuotaSize)
  973. }
  974. // open the file truncating it
  975. f, err = client.OpenFile(testFileName, os.O_WRONLY|os.O_TRUNC)
  976. if assert.NoError(t, err) {
  977. err = f.Close()
  978. assert.NoError(t, err)
  979. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  980. assert.NoError(t, err)
  981. assert.Equal(t, 1, user.UsedQuotaFiles)
  982. assert.Equal(t, int64(0), user.UsedQuotaSize)
  983. }
  984. // now test max write size
  985. f, err = client.OpenFile(testFileName, os.O_WRONLY)
  986. if assert.NoError(t, err) {
  987. n, err := f.Write(testFileContent)
  988. assert.NoError(t, err)
  989. assert.Equal(t, len(testFileContent), n)
  990. err = f.Truncate(11)
  991. assert.NoError(t, err)
  992. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  993. assert.NoError(t, err)
  994. assert.Equal(t, 1, user.UsedQuotaFiles)
  995. assert.Equal(t, int64(11), user.UsedQuotaSize)
  996. _, err = f.Seek(int64(11), io.SeekStart)
  997. assert.NoError(t, err)
  998. n, err = f.Write(testFileContent)
  999. assert.NoError(t, err)
  1000. assert.Equal(t, len(testFileContent), n)
  1001. err = f.Truncate(5)
  1002. assert.NoError(t, err)
  1003. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1004. assert.NoError(t, err)
  1005. assert.Equal(t, 1, user.UsedQuotaFiles)
  1006. assert.Equal(t, int64(5), user.UsedQuotaSize)
  1007. _, err = f.Seek(int64(5), io.SeekStart)
  1008. assert.NoError(t, err)
  1009. n, err = f.Write(testFileContent)
  1010. assert.NoError(t, err)
  1011. assert.Equal(t, len(testFileContent), n)
  1012. err = f.Truncate(12)
  1013. assert.NoError(t, err)
  1014. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1015. assert.NoError(t, err)
  1016. assert.Equal(t, 1, user.UsedQuotaFiles)
  1017. assert.Equal(t, int64(12), user.UsedQuotaSize)
  1018. _, err = f.Seek(int64(12), io.SeekStart)
  1019. assert.NoError(t, err)
  1020. _, err = f.Write(testFileContent)
  1021. if assert.Error(t, err) {
  1022. assert.Contains(t, err.Error(), common.ErrQuotaExceeded.Error())
  1023. }
  1024. err = f.Close()
  1025. assert.Error(t, err)
  1026. // the file is deleted
  1027. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1028. assert.NoError(t, err)
  1029. assert.Equal(t, 0, user.UsedQuotaFiles)
  1030. assert.Equal(t, int64(0), user.UsedQuotaSize)
  1031. }
  1032. if user.Username == defaultUsername {
  1033. // basic test inside a virtual folder
  1034. vfileName1 := path.Join(vdirPath1, testFileName)
  1035. f, err = client.OpenFile(vfileName1, os.O_WRONLY|os.O_CREATE)
  1036. if assert.NoError(t, err) {
  1037. n, err := f.Write(testFileContent)
  1038. assert.NoError(t, err)
  1039. assert.Equal(t, len(testFileContent), n)
  1040. err = f.Truncate(2)
  1041. assert.NoError(t, err)
  1042. expectedQuotaFiles := 0
  1043. expectedQuotaSize := int64(2)
  1044. fold, _, err := httpdtest.GetFolderByName(folderName1, http.StatusOK)
  1045. assert.NoError(t, err)
  1046. assert.Equal(t, expectedQuotaSize, fold.UsedQuotaSize)
  1047. assert.Equal(t, expectedQuotaFiles, fold.UsedQuotaFiles)
  1048. err = f.Close()
  1049. assert.NoError(t, err)
  1050. expectedQuotaFiles = 1
  1051. fold, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
  1052. assert.NoError(t, err)
  1053. assert.Equal(t, expectedQuotaSize, fold.UsedQuotaSize)
  1054. assert.Equal(t, expectedQuotaFiles, fold.UsedQuotaFiles)
  1055. }
  1056. err = client.Truncate(vfileName1, 1)
  1057. assert.NoError(t, err)
  1058. fold, _, err := httpdtest.GetFolderByName(folderName1, http.StatusOK)
  1059. assert.NoError(t, err)
  1060. assert.Equal(t, int64(1), fold.UsedQuotaSize)
  1061. assert.Equal(t, 1, fold.UsedQuotaFiles)
  1062. // now test on vdirPath2, the folder quota is included in the user's quota
  1063. vfileName2 := path.Join(vdirPath2, testFileName)
  1064. f, err = client.OpenFile(vfileName2, os.O_WRONLY|os.O_CREATE)
  1065. if assert.NoError(t, err) {
  1066. n, err := f.Write(testFileContent)
  1067. assert.NoError(t, err)
  1068. assert.Equal(t, len(testFileContent), n)
  1069. err = f.Truncate(3)
  1070. assert.NoError(t, err)
  1071. expectedQuotaFiles := 0
  1072. expectedQuotaSize := int64(3)
  1073. fold, _, err := httpdtest.GetFolderByName(folderName2, http.StatusOK)
  1074. assert.NoError(t, err)
  1075. assert.Equal(t, expectedQuotaSize, fold.UsedQuotaSize)
  1076. assert.Equal(t, expectedQuotaFiles, fold.UsedQuotaFiles)
  1077. err = f.Close()
  1078. assert.NoError(t, err)
  1079. expectedQuotaFiles = 1
  1080. fold, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  1081. assert.NoError(t, err)
  1082. assert.Equal(t, expectedQuotaSize, fold.UsedQuotaSize)
  1083. assert.Equal(t, expectedQuotaFiles, fold.UsedQuotaFiles)
  1084. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1085. assert.NoError(t, err)
  1086. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  1087. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  1088. }
  1089. // cleanup
  1090. err = os.RemoveAll(user.GetHomeDir())
  1091. assert.NoError(t, err)
  1092. if user.Username == defaultUsername {
  1093. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1094. assert.NoError(t, err)
  1095. user.Password = defaultPassword
  1096. user.QuotaSize = 0
  1097. user.ID = 0
  1098. user.CreatedAt = 0
  1099. _, resp, err := httpdtest.AddUser(user, http.StatusCreated)
  1100. assert.NoError(t, err, string(resp))
  1101. }
  1102. }
  1103. }
  1104. }
  1105. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  1106. assert.NoError(t, err)
  1107. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  1108. assert.NoError(t, err)
  1109. err = os.RemoveAll(localUser.GetHomeDir())
  1110. assert.NoError(t, err)
  1111. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName1}, http.StatusOK)
  1112. assert.NoError(t, err)
  1113. err = os.RemoveAll(mappedPath1)
  1114. assert.NoError(t, err)
  1115. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName2}, http.StatusOK)
  1116. assert.NoError(t, err)
  1117. err = os.RemoveAll(mappedPath2)
  1118. assert.NoError(t, err)
  1119. }
  1120. func TestVirtualFoldersQuotaRenameOverwrite(t *testing.T) {
  1121. testFileSize := int64(131072)
  1122. testFileSize1 := int64(65537)
  1123. testFileName1 := "test_file1.dat" //nolint:goconst
  1124. u := getTestUser()
  1125. u.QuotaFiles = 0
  1126. u.QuotaSize = 0
  1127. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  1128. folderName1 := filepath.Base(mappedPath1)
  1129. vdirPath1 := "/vdir1" //nolint:goconst
  1130. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  1131. folderName2 := filepath.Base(mappedPath2)
  1132. vdirPath2 := "/vdir2" //nolint:goconst
  1133. mappedPath3 := filepath.Join(os.TempDir(), "vdir3")
  1134. folderName3 := filepath.Base(mappedPath3)
  1135. vdirPath3 := "/vdir3"
  1136. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1137. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1138. Name: folderName1,
  1139. MappedPath: mappedPath1,
  1140. },
  1141. VirtualPath: vdirPath1,
  1142. QuotaFiles: 2,
  1143. QuotaSize: 0,
  1144. })
  1145. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1146. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1147. MappedPath: mappedPath2,
  1148. Name: folderName2,
  1149. },
  1150. VirtualPath: vdirPath2,
  1151. QuotaFiles: 0,
  1152. QuotaSize: testFileSize + testFileSize1 + 1,
  1153. })
  1154. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1155. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1156. Name: folderName3,
  1157. MappedPath: mappedPath3,
  1158. },
  1159. VirtualPath: vdirPath3,
  1160. QuotaFiles: 2,
  1161. QuotaSize: testFileSize * 2,
  1162. })
  1163. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1164. assert.NoError(t, err)
  1165. conn, client, err := getSftpClient(user)
  1166. if assert.NoError(t, err) {
  1167. defer conn.Close()
  1168. defer client.Close()
  1169. err = writeSFTPFile(path.Join(vdirPath1, testFileName), testFileSize, client)
  1170. assert.NoError(t, err)
  1171. f, err := client.Open(path.Join(vdirPath1, testFileName))
  1172. assert.NoError(t, err)
  1173. contents, err := io.ReadAll(f)
  1174. assert.NoError(t, err)
  1175. err = f.Close()
  1176. assert.NoError(t, err)
  1177. assert.Len(t, contents, int(testFileSize))
  1178. err = writeSFTPFile(path.Join(vdirPath2, testFileName), testFileSize, client)
  1179. assert.NoError(t, err)
  1180. err = writeSFTPFile(path.Join(vdirPath1, testFileName1), testFileSize1, client)
  1181. assert.NoError(t, err)
  1182. err = writeSFTPFile(path.Join(vdirPath2, testFileName1), testFileSize1, client)
  1183. assert.NoError(t, err)
  1184. err = writeSFTPFile(testFileName, testFileSize, client)
  1185. assert.NoError(t, err)
  1186. err = writeSFTPFile(testFileName1, testFileSize1, client)
  1187. assert.NoError(t, err)
  1188. err = writeSFTPFile(path.Join(vdirPath3, testFileName), testFileSize, client)
  1189. assert.NoError(t, err)
  1190. err = writeSFTPFile(path.Join(vdirPath3, testFileName+"1"), testFileSize, client)
  1191. assert.NoError(t, err)
  1192. err = client.Rename(testFileName, path.Join(vdirPath1, testFileName+".rename"))
  1193. assert.Error(t, err)
  1194. // we overwrite an existing file and we have unlimited size
  1195. err = client.Rename(testFileName, path.Join(vdirPath1, testFileName))
  1196. assert.NoError(t, err)
  1197. // we have no space and we try to overwrite a bigger file with a smaller one, this should succeed
  1198. err = client.Rename(testFileName1, path.Join(vdirPath2, testFileName))
  1199. assert.NoError(t, err)
  1200. err = writeSFTPFile(path.Join(vdirPath2, testFileName), testFileSize, client)
  1201. assert.NoError(t, err)
  1202. err = writeSFTPFile(testFileName, testFileSize, client)
  1203. assert.NoError(t, err)
  1204. // we have no space and we try to overwrite a smaller file with a bigger one, this should fail
  1205. err = client.Rename(testFileName, path.Join(vdirPath2, testFileName1))
  1206. assert.Error(t, err)
  1207. fi, err := client.Stat(path.Join(vdirPath1, testFileName1))
  1208. if assert.NoError(t, err) {
  1209. assert.Equal(t, testFileSize1, fi.Size())
  1210. }
  1211. // we are overquota inside vdir3 size 2/2 and size 262144/262144
  1212. err = client.Rename(path.Join(vdirPath1, testFileName1), path.Join(vdirPath3, testFileName1+".rename"))
  1213. assert.Error(t, err)
  1214. // we overwrite an existing file and we have enough size
  1215. err = client.Rename(path.Join(vdirPath1, testFileName1), path.Join(vdirPath3, testFileName))
  1216. assert.NoError(t, err)
  1217. testFileName2 := "test_file2.dat"
  1218. err = writeSFTPFile(testFileName2, testFileSize+testFileSize1, client)
  1219. assert.NoError(t, err)
  1220. // we overwrite an existing file and we haven't enough size
  1221. err = client.Rename(testFileName2, path.Join(vdirPath3, testFileName))
  1222. assert.Error(t, err)
  1223. // now remove a file from vdir3, create a dir with 2 files and try to rename it in vdir3
  1224. // this will fail since the rename will result in 3 files inside vdir3 and quota limits only
  1225. // allow 2 total files there
  1226. err = client.Remove(path.Join(vdirPath3, testFileName+"1"))
  1227. assert.NoError(t, err)
  1228. aDir := "a dir"
  1229. err = client.Mkdir(aDir)
  1230. assert.NoError(t, err)
  1231. err = writeSFTPFile(path.Join(aDir, testFileName1), testFileSize1, client)
  1232. assert.NoError(t, err)
  1233. err = writeSFTPFile(path.Join(aDir, testFileName1+"1"), testFileSize1, client)
  1234. assert.NoError(t, err)
  1235. err = client.Rename(aDir, path.Join(vdirPath3, aDir))
  1236. assert.Error(t, err)
  1237. }
  1238. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1239. assert.NoError(t, err)
  1240. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName1}, http.StatusOK)
  1241. assert.NoError(t, err)
  1242. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName2}, http.StatusOK)
  1243. assert.NoError(t, err)
  1244. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName3}, http.StatusOK)
  1245. assert.NoError(t, err)
  1246. err = os.RemoveAll(user.GetHomeDir())
  1247. assert.NoError(t, err)
  1248. err = os.RemoveAll(mappedPath1)
  1249. assert.NoError(t, err)
  1250. err = os.RemoveAll(mappedPath2)
  1251. assert.NoError(t, err)
  1252. err = os.RemoveAll(mappedPath3)
  1253. assert.NoError(t, err)
  1254. }
  1255. func TestQuotaRenameOverwrite(t *testing.T) {
  1256. u := getTestUser()
  1257. u.QuotaFiles = 100
  1258. u.Filters.DataTransferLimits = []sdk.DataTransferLimit{
  1259. {
  1260. Sources: []string{"10.8.0.0/8"},
  1261. TotalDataTransfer: 1,
  1262. },
  1263. }
  1264. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1265. assert.NoError(t, err)
  1266. conn, client, err := getSftpClient(user)
  1267. if assert.NoError(t, err) {
  1268. defer conn.Close()
  1269. defer client.Close()
  1270. testFileSize := int64(131072)
  1271. testFileSize1 := int64(65537)
  1272. testFileName1 := "test_file1.dat"
  1273. err = writeSFTPFile(testFileName, testFileSize, client)
  1274. assert.NoError(t, err)
  1275. f, err := client.Open(testFileName)
  1276. assert.NoError(t, err)
  1277. contents := make([]byte, testFileSize)
  1278. n, err := io.ReadFull(f, contents)
  1279. assert.NoError(t, err)
  1280. assert.Equal(t, int(testFileSize), n)
  1281. err = f.Close()
  1282. assert.NoError(t, err)
  1283. err = writeSFTPFile(testFileName1, testFileSize1, client)
  1284. assert.NoError(t, err)
  1285. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1286. assert.NoError(t, err)
  1287. assert.Equal(t, int64(0), user.UsedDownloadDataTransfer)
  1288. assert.Equal(t, int64(0), user.UsedUploadDataTransfer)
  1289. assert.Equal(t, 2, user.UsedQuotaFiles)
  1290. assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
  1291. err = client.Rename(testFileName, testFileName1)
  1292. assert.NoError(t, err)
  1293. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1294. assert.NoError(t, err)
  1295. assert.Equal(t, int64(0), user.UsedDownloadDataTransfer)
  1296. assert.Equal(t, int64(0), user.UsedUploadDataTransfer)
  1297. assert.Equal(t, 1, user.UsedQuotaFiles)
  1298. assert.Equal(t, testFileSize, user.UsedQuotaSize)
  1299. err = client.Remove(testFileName1)
  1300. assert.NoError(t, err)
  1301. err = writeSFTPFile(testFileName, testFileSize, client)
  1302. assert.NoError(t, err)
  1303. err = writeSFTPFile(testFileName1, testFileSize1, client)
  1304. assert.NoError(t, err)
  1305. err = client.Rename(testFileName1, testFileName)
  1306. assert.NoError(t, err)
  1307. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1308. assert.NoError(t, err)
  1309. assert.Equal(t, 1, user.UsedQuotaFiles)
  1310. assert.Equal(t, testFileSize1, user.UsedQuotaSize)
  1311. }
  1312. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1313. assert.NoError(t, err)
  1314. err = os.RemoveAll(user.GetHomeDir())
  1315. assert.NoError(t, err)
  1316. }
  1317. func TestVirtualFoldersQuotaValues(t *testing.T) {
  1318. u := getTestUser()
  1319. u.QuotaFiles = 100
  1320. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  1321. vdirPath1 := "/vdir1"
  1322. folderName1 := filepath.Base(mappedPath1)
  1323. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  1324. vdirPath2 := "/vdir2"
  1325. folderName2 := filepath.Base(mappedPath2)
  1326. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1327. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1328. Name: folderName1,
  1329. MappedPath: mappedPath1,
  1330. },
  1331. VirtualPath: vdirPath1,
  1332. // quota is included in the user's one
  1333. QuotaFiles: -1,
  1334. QuotaSize: -1,
  1335. })
  1336. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1337. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1338. Name: folderName2,
  1339. MappedPath: mappedPath2,
  1340. },
  1341. VirtualPath: vdirPath2,
  1342. // quota is unlimited and excluded from user's one
  1343. QuotaFiles: 0,
  1344. QuotaSize: 0,
  1345. })
  1346. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1347. assert.NoError(t, err)
  1348. conn, client, err := getSftpClient(user)
  1349. if assert.NoError(t, err) {
  1350. defer conn.Close()
  1351. defer client.Close()
  1352. testFileSize := int64(131072)
  1353. err = writeSFTPFile(testFileName, testFileSize, client)
  1354. assert.NoError(t, err)
  1355. // we copy the same file two times to test quota update on file overwrite
  1356. err = writeSFTPFile(path.Join(vdirPath1, testFileName), testFileSize, client)
  1357. assert.NoError(t, err)
  1358. err = writeSFTPFile(path.Join(vdirPath1, testFileName), testFileSize, client)
  1359. assert.NoError(t, err)
  1360. err = writeSFTPFile(path.Join(vdirPath2, testFileName), testFileSize, client)
  1361. assert.NoError(t, err)
  1362. err = writeSFTPFile(path.Join(vdirPath2, testFileName), testFileSize, client)
  1363. assert.NoError(t, err)
  1364. expectedQuotaFiles := 2
  1365. expectedQuotaSize := testFileSize * 2
  1366. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1367. assert.NoError(t, err)
  1368. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  1369. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  1370. f, _, err := httpdtest.GetFolderByName(folderName1, http.StatusOK)
  1371. assert.NoError(t, err)
  1372. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  1373. assert.Equal(t, 1, f.UsedQuotaFiles)
  1374. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  1375. assert.NoError(t, err)
  1376. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  1377. assert.Equal(t, 1, f.UsedQuotaFiles)
  1378. err = client.Remove(path.Join(vdirPath1, testFileName))
  1379. assert.NoError(t, err)
  1380. err = client.Remove(path.Join(vdirPath2, testFileName))
  1381. assert.NoError(t, err)
  1382. f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
  1383. assert.NoError(t, err)
  1384. assert.Equal(t, int64(0), f.UsedQuotaSize)
  1385. assert.Equal(t, 0, f.UsedQuotaFiles)
  1386. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  1387. assert.NoError(t, err)
  1388. assert.Equal(t, int64(0), f.UsedQuotaSize)
  1389. assert.Equal(t, 0, f.UsedQuotaFiles)
  1390. }
  1391. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1392. assert.NoError(t, err)
  1393. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName1}, http.StatusOK)
  1394. assert.NoError(t, err)
  1395. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName2}, http.StatusOK)
  1396. assert.NoError(t, err)
  1397. err = os.RemoveAll(user.GetHomeDir())
  1398. assert.NoError(t, err)
  1399. err = os.RemoveAll(mappedPath1)
  1400. assert.NoError(t, err)
  1401. err = os.RemoveAll(mappedPath2)
  1402. assert.NoError(t, err)
  1403. }
  1404. func TestQuotaRenameInsideSameVirtualFolder(t *testing.T) {
  1405. u := getTestUser()
  1406. u.QuotaFiles = 100
  1407. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  1408. vdirPath1 := "/vdir1"
  1409. folderName1 := filepath.Base(mappedPath1)
  1410. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  1411. vdirPath2 := "/vdir2"
  1412. folderName2 := filepath.Base(mappedPath2)
  1413. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1414. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1415. Name: folderName1,
  1416. MappedPath: mappedPath1,
  1417. },
  1418. VirtualPath: vdirPath1,
  1419. // quota is included in the user's one
  1420. QuotaFiles: -1,
  1421. QuotaSize: -1,
  1422. })
  1423. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1424. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1425. Name: folderName2,
  1426. MappedPath: mappedPath2,
  1427. },
  1428. VirtualPath: vdirPath2,
  1429. // quota is unlimited and excluded from user's one
  1430. QuotaFiles: 0,
  1431. QuotaSize: 0,
  1432. })
  1433. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1434. assert.NoError(t, err)
  1435. conn, client, err := getSftpClient(user)
  1436. if assert.NoError(t, err) {
  1437. defer conn.Close()
  1438. defer client.Close()
  1439. testFileName1 := "test_file1.dat"
  1440. testFileSize := int64(131072)
  1441. testFileSize1 := int64(65535)
  1442. dir1 := "dir1" //nolint:goconst
  1443. dir2 := "dir2" //nolint:goconst
  1444. assert.NoError(t, err)
  1445. err = client.Mkdir(path.Join(vdirPath1, dir1))
  1446. assert.NoError(t, err)
  1447. err = client.Mkdir(path.Join(vdirPath1, dir2))
  1448. assert.NoError(t, err)
  1449. err = client.Mkdir(path.Join(vdirPath2, dir1))
  1450. assert.NoError(t, err)
  1451. err = client.Mkdir(path.Join(vdirPath2, dir2))
  1452. assert.NoError(t, err)
  1453. err = writeSFTPFile(path.Join(vdirPath1, dir1, testFileName), testFileSize, client)
  1454. assert.NoError(t, err)
  1455. err = writeSFTPFile(path.Join(vdirPath1, dir2, testFileName1), testFileSize1, client)
  1456. assert.NoError(t, err)
  1457. err = writeSFTPFile(path.Join(vdirPath2, dir1, testFileName), testFileSize, client)
  1458. assert.NoError(t, err)
  1459. err = writeSFTPFile(path.Join(vdirPath2, dir2, testFileName1), testFileSize1, client)
  1460. assert.NoError(t, err)
  1461. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1462. assert.NoError(t, err)
  1463. assert.Equal(t, 2, user.UsedQuotaFiles)
  1464. assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
  1465. f, _, err := httpdtest.GetFolderByName(folderName1, http.StatusOK)
  1466. assert.NoError(t, err)
  1467. assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
  1468. assert.Equal(t, 2, f.UsedQuotaFiles)
  1469. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  1470. assert.NoError(t, err)
  1471. assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
  1472. assert.Equal(t, 2, f.UsedQuotaFiles)
  1473. // initial files:
  1474. // - vdir1/dir1/testFileName
  1475. // - vdir1/dir2/testFileName1
  1476. // - vdir2/dir1/testFileName
  1477. // - vdir2/dir2/testFileName1
  1478. //
  1479. // rename a file inside vdir1 it is included inside user quota, so we have:
  1480. // - vdir1/dir1/testFileName.rename
  1481. // - vdir1/dir2/testFileName1
  1482. // - vdir2/dir1/testFileName
  1483. // - vdir2/dir2/testFileName1
  1484. err = client.Rename(path.Join(vdirPath1, dir1, testFileName), path.Join(vdirPath1, dir1, testFileName+".rename"))
  1485. assert.NoError(t, err)
  1486. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1487. assert.NoError(t, err)
  1488. assert.Equal(t, 2, user.UsedQuotaFiles)
  1489. assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
  1490. f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
  1491. assert.NoError(t, err)
  1492. assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
  1493. assert.Equal(t, 2, f.UsedQuotaFiles)
  1494. // rename a file inside vdir2, it isn't included inside user quota, so we have:
  1495. // - vdir1/dir1/testFileName.rename
  1496. // - vdir1/dir2/testFileName1
  1497. // - vdir2/dir1/testFileName.rename
  1498. // - vdir2/dir2/testFileName1
  1499. err = client.Rename(path.Join(vdirPath2, dir1, testFileName), path.Join(vdirPath2, dir1, testFileName+".rename"))
  1500. assert.NoError(t, err)
  1501. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1502. assert.NoError(t, err)
  1503. assert.Equal(t, 2, user.UsedQuotaFiles)
  1504. assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
  1505. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  1506. assert.NoError(t, err)
  1507. assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
  1508. assert.Equal(t, 2, f.UsedQuotaFiles)
  1509. f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
  1510. assert.NoError(t, err)
  1511. assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
  1512. assert.Equal(t, 2, f.UsedQuotaFiles)
  1513. // rename a file inside vdir2 overwriting an existing, we now have:
  1514. // - vdir1/dir1/testFileName.rename
  1515. // - vdir1/dir2/testFileName1
  1516. // - vdir2/dir1/testFileName.rename (initial testFileName1)
  1517. err = client.Rename(path.Join(vdirPath2, dir2, testFileName1), path.Join(vdirPath2, dir1, testFileName+".rename"))
  1518. assert.NoError(t, err)
  1519. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1520. assert.NoError(t, err)
  1521. assert.Equal(t, 2, user.UsedQuotaFiles)
  1522. assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
  1523. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  1524. assert.NoError(t, err)
  1525. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  1526. assert.Equal(t, 1, f.UsedQuotaFiles)
  1527. f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
  1528. assert.NoError(t, err)
  1529. assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
  1530. assert.Equal(t, 2, f.UsedQuotaFiles)
  1531. // rename a file inside vdir1 overwriting an existing, we now have:
  1532. // - vdir1/dir1/testFileName.rename (initial testFileName1)
  1533. // - vdir2/dir1/testFileName.rename (initial testFileName1)
  1534. err = client.Rename(path.Join(vdirPath1, dir2, testFileName1), path.Join(vdirPath1, dir1, testFileName+".rename"))
  1535. assert.NoError(t, err)
  1536. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1537. assert.NoError(t, err)
  1538. assert.Equal(t, 1, user.UsedQuotaFiles)
  1539. assert.Equal(t, testFileSize1, user.UsedQuotaSize)
  1540. f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
  1541. assert.NoError(t, err)
  1542. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  1543. assert.Equal(t, 1, f.UsedQuotaFiles)
  1544. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  1545. assert.NoError(t, err)
  1546. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  1547. assert.Equal(t, 1, f.UsedQuotaFiles)
  1548. // rename a directory inside the same virtual folder, quota should not change
  1549. err = client.RemoveDirectory(path.Join(vdirPath1, dir2))
  1550. assert.NoError(t, err)
  1551. err = client.RemoveDirectory(path.Join(vdirPath2, dir2))
  1552. assert.NoError(t, err)
  1553. err = client.Rename(path.Join(vdirPath1, dir1), path.Join(vdirPath1, dir2))
  1554. assert.NoError(t, err)
  1555. err = client.Rename(path.Join(vdirPath2, dir1), path.Join(vdirPath2, dir2))
  1556. assert.NoError(t, err)
  1557. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1558. assert.NoError(t, err)
  1559. assert.Equal(t, 1, user.UsedQuotaFiles)
  1560. assert.Equal(t, testFileSize1, user.UsedQuotaSize)
  1561. f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
  1562. assert.NoError(t, err)
  1563. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  1564. assert.Equal(t, 1, f.UsedQuotaFiles)
  1565. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  1566. assert.NoError(t, err)
  1567. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  1568. assert.Equal(t, 1, f.UsedQuotaFiles)
  1569. }
  1570. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1571. assert.NoError(t, err)
  1572. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName1}, http.StatusOK)
  1573. assert.NoError(t, err)
  1574. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName2}, http.StatusOK)
  1575. assert.NoError(t, err)
  1576. err = os.RemoveAll(user.GetHomeDir())
  1577. assert.NoError(t, err)
  1578. err = os.RemoveAll(mappedPath1)
  1579. assert.NoError(t, err)
  1580. err = os.RemoveAll(mappedPath2)
  1581. assert.NoError(t, err)
  1582. }
  1583. func TestQuotaRenameBetweenVirtualFolder(t *testing.T) {
  1584. u := getTestUser()
  1585. u.QuotaFiles = 100
  1586. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  1587. folderName1 := filepath.Base(mappedPath1)
  1588. vdirPath1 := "/vdir1"
  1589. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  1590. folderName2 := filepath.Base(mappedPath2)
  1591. vdirPath2 := "/vdir2"
  1592. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1593. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1594. Name: folderName1,
  1595. MappedPath: mappedPath1,
  1596. },
  1597. VirtualPath: vdirPath1,
  1598. // quota is included in the user's one
  1599. QuotaFiles: -1,
  1600. QuotaSize: -1,
  1601. })
  1602. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1603. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1604. Name: folderName2,
  1605. MappedPath: mappedPath2,
  1606. },
  1607. VirtualPath: vdirPath2,
  1608. // quota is unlimited and excluded from user's one
  1609. QuotaFiles: 0,
  1610. QuotaSize: 0,
  1611. })
  1612. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1613. assert.NoError(t, err)
  1614. conn, client, err := getSftpClient(user)
  1615. if assert.NoError(t, err) {
  1616. defer conn.Close()
  1617. defer client.Close()
  1618. testFileName1 := "test_file1.dat"
  1619. testFileSize := int64(131072)
  1620. testFileSize1 := int64(65535)
  1621. dir1 := "dir1"
  1622. dir2 := "dir2"
  1623. err = client.Mkdir(path.Join(vdirPath1, dir1))
  1624. assert.NoError(t, err)
  1625. err = client.Mkdir(path.Join(vdirPath1, dir2))
  1626. assert.NoError(t, err)
  1627. err = client.Mkdir(path.Join(vdirPath2, dir1))
  1628. assert.NoError(t, err)
  1629. err = client.Mkdir(path.Join(vdirPath2, dir2))
  1630. assert.NoError(t, err)
  1631. err = writeSFTPFile(path.Join(vdirPath1, dir1, testFileName), testFileSize, client)
  1632. assert.NoError(t, err)
  1633. err = writeSFTPFile(path.Join(vdirPath1, dir2, testFileName1), testFileSize1, client)
  1634. assert.NoError(t, err)
  1635. err = writeSFTPFile(path.Join(vdirPath2, dir1, testFileName), testFileSize, client)
  1636. assert.NoError(t, err)
  1637. err = writeSFTPFile(path.Join(vdirPath2, dir2, testFileName1), testFileSize1, client)
  1638. assert.NoError(t, err)
  1639. // initial files:
  1640. // - vdir1/dir1/testFileName
  1641. // - vdir1/dir2/testFileName1
  1642. // - vdir2/dir1/testFileName
  1643. // - vdir2/dir2/testFileName1
  1644. //
  1645. // rename a file from vdir1 to vdir2, vdir1 is included inside user quota, so we have:
  1646. // - vdir1/dir1/testFileName
  1647. // - vdir2/dir1/testFileName
  1648. // - vdir2/dir2/testFileName1
  1649. // - vdir2/dir1/testFileName1.rename
  1650. err = client.Rename(path.Join(vdirPath1, dir2, testFileName1), path.Join(vdirPath2, dir1, testFileName1+".rename"))
  1651. assert.NoError(t, err)
  1652. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1653. assert.NoError(t, err)
  1654. assert.Equal(t, 1, user.UsedQuotaFiles)
  1655. assert.Equal(t, testFileSize, user.UsedQuotaSize)
  1656. f, _, err := httpdtest.GetFolderByName(folderName1, http.StatusOK)
  1657. assert.NoError(t, err)
  1658. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  1659. assert.Equal(t, 1, f.UsedQuotaFiles)
  1660. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  1661. assert.NoError(t, err)
  1662. assert.Equal(t, testFileSize+testFileSize1+testFileSize1, f.UsedQuotaSize)
  1663. assert.Equal(t, 3, f.UsedQuotaFiles)
  1664. // rename a file from vdir2 to vdir1, vdir2 is not included inside user quota, so we have:
  1665. // - vdir1/dir1/testFileName
  1666. // - vdir1/dir2/testFileName.rename
  1667. // - vdir2/dir2/testFileName1
  1668. // - vdir2/dir1/testFileName1.rename
  1669. err = client.Rename(path.Join(vdirPath2, dir1, testFileName), path.Join(vdirPath1, dir2, testFileName+".rename"))
  1670. assert.NoError(t, err)
  1671. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1672. assert.NoError(t, err)
  1673. assert.Equal(t, 2, user.UsedQuotaFiles)
  1674. assert.Equal(t, testFileSize*2, user.UsedQuotaSize)
  1675. f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
  1676. assert.NoError(t, err)
  1677. assert.Equal(t, testFileSize*2, f.UsedQuotaSize)
  1678. assert.Equal(t, 2, f.UsedQuotaFiles)
  1679. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  1680. assert.NoError(t, err)
  1681. assert.Equal(t, testFileSize1*2, f.UsedQuotaSize)
  1682. assert.Equal(t, 2, f.UsedQuotaFiles)
  1683. // rename a file from vdir1 to vdir2 overwriting an existing file, vdir1 is included inside user quota, so we have:
  1684. // - vdir1/dir2/testFileName.rename
  1685. // - vdir2/dir2/testFileName1 (is the initial testFileName)
  1686. // - vdir2/dir1/testFileName1.rename
  1687. err = client.Rename(path.Join(vdirPath1, dir1, testFileName), path.Join(vdirPath2, dir2, testFileName1))
  1688. assert.NoError(t, err)
  1689. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1690. assert.NoError(t, err)
  1691. assert.Equal(t, 1, user.UsedQuotaFiles)
  1692. assert.Equal(t, testFileSize, user.UsedQuotaSize)
  1693. f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
  1694. assert.NoError(t, err)
  1695. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  1696. assert.Equal(t, 1, f.UsedQuotaFiles)
  1697. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  1698. assert.NoError(t, err)
  1699. assert.Equal(t, testFileSize1+testFileSize, f.UsedQuotaSize)
  1700. assert.Equal(t, 2, f.UsedQuotaFiles)
  1701. // rename a file from vdir2 to vdir1 overwriting an existing file, vdir2 is not included inside user quota, so we have:
  1702. // - vdir1/dir2/testFileName.rename (is the initial testFileName1)
  1703. // - vdir2/dir2/testFileName1 (is the initial testFileName)
  1704. err = client.Rename(path.Join(vdirPath2, dir1, testFileName1+".rename"), path.Join(vdirPath1, dir2, testFileName+".rename"))
  1705. assert.NoError(t, err)
  1706. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1707. assert.NoError(t, err)
  1708. assert.Equal(t, 1, user.UsedQuotaFiles)
  1709. assert.Equal(t, testFileSize1, user.UsedQuotaSize)
  1710. f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
  1711. assert.NoError(t, err)
  1712. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  1713. assert.Equal(t, 1, f.UsedQuotaFiles)
  1714. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  1715. assert.NoError(t, err)
  1716. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  1717. assert.Equal(t, 1, f.UsedQuotaFiles)
  1718. err = writeSFTPFile(path.Join(vdirPath1, dir2, testFileName), testFileSize, client)
  1719. assert.NoError(t, err)
  1720. err = writeSFTPFile(path.Join(vdirPath2, dir2, testFileName), testFileSize1, client)
  1721. assert.NoError(t, err)
  1722. err = writeSFTPFile(path.Join(vdirPath2, dir2, testFileName+"1.dupl"), testFileSize1, client)
  1723. assert.NoError(t, err)
  1724. err = client.RemoveDirectory(path.Join(vdirPath1, dir1))
  1725. assert.NoError(t, err)
  1726. err = client.RemoveDirectory(path.Join(vdirPath2, dir1))
  1727. assert.NoError(t, err)
  1728. // - vdir1/dir2/testFileName.rename (initial testFileName1)
  1729. // - vdir1/dir2/testFileName
  1730. // - vdir2/dir2/testFileName1 (initial testFileName)
  1731. // - vdir2/dir2/testFileName (initial testFileName1)
  1732. // - vdir2/dir2/testFileName1.dupl
  1733. // rename directories between the two virtual folders
  1734. err = client.Rename(path.Join(vdirPath2, dir2), path.Join(vdirPath1, dir1))
  1735. assert.NoError(t, err)
  1736. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1737. assert.NoError(t, err)
  1738. assert.Equal(t, 5, user.UsedQuotaFiles)
  1739. assert.Equal(t, testFileSize1*3+testFileSize*2, user.UsedQuotaSize)
  1740. f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
  1741. assert.NoError(t, err)
  1742. assert.Equal(t, testFileSize1*3+testFileSize*2, f.UsedQuotaSize)
  1743. assert.Equal(t, 5, f.UsedQuotaFiles)
  1744. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  1745. assert.NoError(t, err)
  1746. assert.Equal(t, int64(0), f.UsedQuotaSize)
  1747. assert.Equal(t, 0, f.UsedQuotaFiles)
  1748. // now move on vpath2
  1749. err = client.Rename(path.Join(vdirPath1, dir2), path.Join(vdirPath2, dir1))
  1750. assert.NoError(t, err)
  1751. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1752. assert.NoError(t, err)
  1753. assert.Equal(t, 3, user.UsedQuotaFiles)
  1754. assert.Equal(t, testFileSize1*2+testFileSize, user.UsedQuotaSize)
  1755. f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
  1756. assert.NoError(t, err)
  1757. assert.Equal(t, testFileSize1*2+testFileSize, f.UsedQuotaSize)
  1758. assert.Equal(t, 3, f.UsedQuotaFiles)
  1759. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  1760. assert.NoError(t, err)
  1761. assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
  1762. assert.Equal(t, 2, f.UsedQuotaFiles)
  1763. }
  1764. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1765. assert.NoError(t, err)
  1766. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName1}, http.StatusOK)
  1767. assert.NoError(t, err)
  1768. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName2}, http.StatusOK)
  1769. assert.NoError(t, err)
  1770. err = os.RemoveAll(user.GetHomeDir())
  1771. assert.NoError(t, err)
  1772. err = os.RemoveAll(mappedPath1)
  1773. assert.NoError(t, err)
  1774. err = os.RemoveAll(mappedPath2)
  1775. assert.NoError(t, err)
  1776. }
  1777. func TestQuotaRenameFromVirtualFolder(t *testing.T) {
  1778. u := getTestUser()
  1779. u.QuotaFiles = 100
  1780. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  1781. folderName1 := filepath.Base(mappedPath1)
  1782. vdirPath1 := "/vdir1"
  1783. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  1784. folderName2 := filepath.Base(mappedPath2)
  1785. vdirPath2 := "/vdir2"
  1786. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1787. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1788. Name: folderName1,
  1789. MappedPath: mappedPath1,
  1790. },
  1791. VirtualPath: vdirPath1,
  1792. // quota is included in the user's one
  1793. QuotaFiles: -1,
  1794. QuotaSize: -1,
  1795. })
  1796. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1797. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1798. Name: folderName2,
  1799. MappedPath: mappedPath2,
  1800. },
  1801. VirtualPath: vdirPath2,
  1802. // quota is unlimited and excluded from user's one
  1803. QuotaFiles: 0,
  1804. QuotaSize: 0,
  1805. })
  1806. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  1807. assert.NoError(t, err)
  1808. conn, client, err := getSftpClient(user)
  1809. if assert.NoError(t, err) {
  1810. defer conn.Close()
  1811. defer client.Close()
  1812. testFileName1 := "test_file1.dat"
  1813. testFileSize := int64(131072)
  1814. testFileSize1 := int64(65535)
  1815. dir1 := "dir1"
  1816. dir2 := "dir2"
  1817. err = client.Mkdir(path.Join(vdirPath1, dir1))
  1818. assert.NoError(t, err)
  1819. err = client.Mkdir(path.Join(vdirPath1, dir2))
  1820. assert.NoError(t, err)
  1821. err = client.Mkdir(path.Join(vdirPath2, dir1))
  1822. assert.NoError(t, err)
  1823. err = client.Mkdir(path.Join(vdirPath2, dir2))
  1824. assert.NoError(t, err)
  1825. err = writeSFTPFile(path.Join(vdirPath1, dir1, testFileName), testFileSize, client)
  1826. assert.NoError(t, err)
  1827. err = writeSFTPFile(path.Join(vdirPath1, dir2, testFileName1), testFileSize1, client)
  1828. assert.NoError(t, err)
  1829. err = writeSFTPFile(path.Join(vdirPath2, dir1, testFileName), testFileSize, client)
  1830. assert.NoError(t, err)
  1831. err = writeSFTPFile(path.Join(vdirPath2, dir2, testFileName1), testFileSize1, client)
  1832. assert.NoError(t, err)
  1833. // initial files:
  1834. // - vdir1/dir1/testFileName
  1835. // - vdir1/dir2/testFileName1
  1836. // - vdir2/dir1/testFileName
  1837. // - vdir2/dir2/testFileName1
  1838. //
  1839. // rename a file from vdir1 to the user home dir, vdir1 is included in user quota so we have:
  1840. // - testFileName
  1841. // - vdir1/dir2/testFileName1
  1842. // - vdir2/dir1/testFileName
  1843. // - vdir2/dir2/testFileName1
  1844. err = client.Rename(path.Join(vdirPath1, dir1, testFileName), path.Join(testFileName))
  1845. assert.NoError(t, err)
  1846. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1847. assert.NoError(t, err)
  1848. assert.Equal(t, 2, user.UsedQuotaFiles)
  1849. assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
  1850. f, _, err := httpdtest.GetFolderByName(folderName1, http.StatusOK)
  1851. assert.NoError(t, err)
  1852. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  1853. assert.Equal(t, 1, f.UsedQuotaFiles)
  1854. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  1855. assert.NoError(t, err)
  1856. assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
  1857. assert.Equal(t, 2, f.UsedQuotaFiles)
  1858. // rename a file from vdir2 to the user home dir, vdir2 is not included in user quota so we have:
  1859. // - testFileName
  1860. // - testFileName1
  1861. // - vdir1/dir2/testFileName1
  1862. // - vdir2/dir1/testFileName
  1863. err = client.Rename(path.Join(vdirPath2, dir2, testFileName1), path.Join(testFileName1))
  1864. assert.NoError(t, err)
  1865. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1866. assert.NoError(t, err)
  1867. assert.Equal(t, 3, user.UsedQuotaFiles)
  1868. assert.Equal(t, testFileSize+testFileSize1+testFileSize1, user.UsedQuotaSize)
  1869. f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
  1870. assert.NoError(t, err)
  1871. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  1872. assert.Equal(t, 1, f.UsedQuotaFiles)
  1873. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  1874. assert.NoError(t, err)
  1875. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  1876. assert.Equal(t, 1, f.UsedQuotaFiles)
  1877. // rename a file from vdir1 to the user home dir overwriting an existing file, vdir1 is included in user quota so we have:
  1878. // - testFileName (initial testFileName1)
  1879. // - testFileName1
  1880. // - vdir2/dir1/testFileName
  1881. err = client.Rename(path.Join(vdirPath1, dir2, testFileName1), path.Join(testFileName))
  1882. assert.NoError(t, err)
  1883. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1884. assert.NoError(t, err)
  1885. assert.Equal(t, 2, user.UsedQuotaFiles)
  1886. assert.Equal(t, testFileSize1+testFileSize1, user.UsedQuotaSize)
  1887. f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
  1888. assert.NoError(t, err)
  1889. assert.Equal(t, int64(0), f.UsedQuotaSize)
  1890. assert.Equal(t, 0, f.UsedQuotaFiles)
  1891. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  1892. assert.NoError(t, err)
  1893. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  1894. assert.Equal(t, 1, f.UsedQuotaFiles)
  1895. // rename a file from vdir2 to the user home dir overwriting an existing file, vdir2 is not included in user quota so we have:
  1896. // - testFileName (initial testFileName1)
  1897. // - testFileName1 (initial testFileName)
  1898. err = client.Rename(path.Join(vdirPath2, dir1, testFileName), path.Join(testFileName1))
  1899. assert.NoError(t, err)
  1900. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1901. assert.NoError(t, err)
  1902. assert.Equal(t, 2, user.UsedQuotaFiles)
  1903. assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
  1904. f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
  1905. assert.NoError(t, err)
  1906. assert.Equal(t, int64(0), f.UsedQuotaSize)
  1907. assert.Equal(t, 0, f.UsedQuotaFiles)
  1908. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  1909. assert.NoError(t, err)
  1910. assert.Equal(t, int64(0), f.UsedQuotaSize)
  1911. assert.Equal(t, 0, f.UsedQuotaFiles)
  1912. // dir rename
  1913. err = writeSFTPFile(path.Join(vdirPath1, dir1, testFileName), testFileSize, client)
  1914. assert.NoError(t, err)
  1915. err = writeSFTPFile(path.Join(vdirPath1, dir1, testFileName1), testFileSize1, client)
  1916. assert.NoError(t, err)
  1917. err = writeSFTPFile(path.Join(vdirPath2, dir1, testFileName), testFileSize, client)
  1918. assert.NoError(t, err)
  1919. err = writeSFTPFile(path.Join(vdirPath2, dir1, testFileName1), testFileSize1, client)
  1920. assert.NoError(t, err)
  1921. // - testFileName (initial testFileName1)
  1922. // - testFileName1 (initial testFileName)
  1923. // - vdir1/dir1/testFileName
  1924. // - vdir1/dir1/testFileName1
  1925. // - dir1/testFileName
  1926. // - dir1/testFileName1
  1927. err = client.Rename(path.Join(vdirPath2, dir1), dir1)
  1928. assert.NoError(t, err)
  1929. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1930. assert.NoError(t, err)
  1931. assert.Equal(t, 6, user.UsedQuotaFiles)
  1932. assert.Equal(t, testFileSize*3+testFileSize1*3, user.UsedQuotaSize)
  1933. f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
  1934. assert.NoError(t, err)
  1935. assert.Equal(t, testFileSize+testFileSize1, f.UsedQuotaSize)
  1936. assert.Equal(t, 2, f.UsedQuotaFiles)
  1937. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  1938. assert.NoError(t, err)
  1939. assert.Equal(t, int64(0), f.UsedQuotaSize)
  1940. assert.Equal(t, 0, f.UsedQuotaFiles)
  1941. // - testFileName (initial testFileName1)
  1942. // - testFileName1 (initial testFileName)
  1943. // - dir2/testFileName
  1944. // - dir2/testFileName1
  1945. // - dir1/testFileName
  1946. // - dir1/testFileName1
  1947. err = client.Rename(path.Join(vdirPath1, dir1), dir2)
  1948. assert.NoError(t, err)
  1949. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  1950. assert.NoError(t, err)
  1951. assert.Equal(t, 6, user.UsedQuotaFiles)
  1952. assert.Equal(t, testFileSize*3+testFileSize1*3, user.UsedQuotaSize)
  1953. f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
  1954. assert.NoError(t, err)
  1955. assert.Equal(t, int64(0), f.UsedQuotaSize)
  1956. assert.Equal(t, 0, f.UsedQuotaFiles)
  1957. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  1958. assert.NoError(t, err)
  1959. assert.Equal(t, int64(0), f.UsedQuotaSize)
  1960. assert.Equal(t, 0, f.UsedQuotaFiles)
  1961. }
  1962. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  1963. assert.NoError(t, err)
  1964. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName1}, http.StatusOK)
  1965. assert.NoError(t, err)
  1966. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName2}, http.StatusOK)
  1967. assert.NoError(t, err)
  1968. err = os.RemoveAll(user.GetHomeDir())
  1969. assert.NoError(t, err)
  1970. err = os.RemoveAll(mappedPath1)
  1971. assert.NoError(t, err)
  1972. err = os.RemoveAll(mappedPath2)
  1973. assert.NoError(t, err)
  1974. }
  1975. func TestQuotaRenameToVirtualFolder(t *testing.T) {
  1976. u := getTestUser()
  1977. u.QuotaFiles = 100
  1978. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  1979. folderName1 := filepath.Base(mappedPath1)
  1980. vdirPath1 := "/vdir1"
  1981. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  1982. folderName2 := filepath.Base(mappedPath2)
  1983. vdirPath2 := "/vdir2"
  1984. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1985. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1986. Name: folderName1,
  1987. MappedPath: mappedPath1,
  1988. },
  1989. VirtualPath: vdirPath1,
  1990. // quota is included in the user's one
  1991. QuotaFiles: -1,
  1992. QuotaSize: -1,
  1993. })
  1994. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  1995. BaseVirtualFolder: vfs.BaseVirtualFolder{
  1996. Name: folderName2,
  1997. MappedPath: mappedPath2,
  1998. },
  1999. VirtualPath: vdirPath2,
  2000. // quota is unlimited and excluded from user's one
  2001. QuotaFiles: 0,
  2002. QuotaSize: 0,
  2003. })
  2004. u.Permissions[vdirPath1] = []string{dataprovider.PermListItems, dataprovider.PermDownload, dataprovider.PermUpload,
  2005. dataprovider.PermOverwrite, dataprovider.PermDelete, dataprovider.PermCreateSymlinks, dataprovider.PermCreateDirs,
  2006. dataprovider.PermRename}
  2007. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2008. assert.NoError(t, err)
  2009. conn, client, err := getSftpClient(user)
  2010. if assert.NoError(t, err) {
  2011. defer conn.Close()
  2012. defer client.Close()
  2013. testFileName1 := "test_file1.dat"
  2014. testFileSize := int64(131072)
  2015. testFileSize1 := int64(65535)
  2016. dir1 := "dir1"
  2017. dir2 := "dir2"
  2018. err = client.Mkdir(path.Join(vdirPath1, dir1))
  2019. assert.NoError(t, err)
  2020. err = client.Mkdir(path.Join(vdirPath1, dir2))
  2021. assert.NoError(t, err)
  2022. err = client.Mkdir(path.Join(vdirPath2, dir1))
  2023. assert.NoError(t, err)
  2024. err = client.Mkdir(path.Join(vdirPath2, dir2))
  2025. assert.NoError(t, err)
  2026. err = writeSFTPFile(testFileName, testFileSize, client)
  2027. assert.NoError(t, err)
  2028. err = writeSFTPFile(testFileName1, testFileSize1, client)
  2029. assert.NoError(t, err)
  2030. // initial files:
  2031. // - testFileName
  2032. // - testFileName1
  2033. //
  2034. // rename a file from user home dir to vdir1, vdir1 is included in user quota so we have:
  2035. // - testFileName
  2036. // - /vdir1/dir1/testFileName1
  2037. err = client.Rename(testFileName1, path.Join(vdirPath1, dir1, testFileName1))
  2038. assert.NoError(t, err)
  2039. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  2040. assert.NoError(t, err)
  2041. assert.Equal(t, 2, user.UsedQuotaFiles)
  2042. assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
  2043. f, _, err := httpdtest.GetFolderByName(folderName1, http.StatusOK)
  2044. assert.NoError(t, err)
  2045. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  2046. assert.Equal(t, 1, f.UsedQuotaFiles)
  2047. // rename a file from user home dir to vdir2, vdir2 is not included in user quota so we have:
  2048. // - /vdir2/dir1/testFileName
  2049. // - /vdir1/dir1/testFileName1
  2050. err = client.Rename(testFileName, path.Join(vdirPath2, dir1, testFileName))
  2051. assert.NoError(t, err)
  2052. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  2053. assert.NoError(t, err)
  2054. assert.Equal(t, 1, user.UsedQuotaFiles)
  2055. assert.Equal(t, testFileSize1, user.UsedQuotaSize)
  2056. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  2057. assert.NoError(t, err)
  2058. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  2059. assert.Equal(t, 1, f.UsedQuotaFiles)
  2060. // upload two new files to the user home dir so we have:
  2061. // - testFileName
  2062. // - testFileName1
  2063. // - /vdir1/dir1/testFileName1
  2064. // - /vdir2/dir1/testFileName
  2065. err = writeSFTPFile(testFileName, testFileSize, client)
  2066. assert.NoError(t, err)
  2067. err = writeSFTPFile(testFileName1, testFileSize1, client)
  2068. assert.NoError(t, err)
  2069. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  2070. assert.NoError(t, err)
  2071. assert.Equal(t, 3, user.UsedQuotaFiles)
  2072. assert.Equal(t, testFileSize+testFileSize1+testFileSize1, user.UsedQuotaSize)
  2073. // rename a file from user home dir to vdir1 overwriting an existing file, vdir1 is included in user quota so we have:
  2074. // - testFileName1
  2075. // - /vdir1/dir1/testFileName1 (initial testFileName)
  2076. // - /vdir2/dir1/testFileName
  2077. err = client.Rename(testFileName, path.Join(vdirPath1, dir1, testFileName1))
  2078. assert.NoError(t, err)
  2079. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  2080. assert.NoError(t, err)
  2081. assert.Equal(t, 2, user.UsedQuotaFiles)
  2082. assert.Equal(t, testFileSize+testFileSize1, user.UsedQuotaSize)
  2083. f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
  2084. assert.NoError(t, err)
  2085. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  2086. assert.Equal(t, 1, f.UsedQuotaFiles)
  2087. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  2088. assert.NoError(t, err)
  2089. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  2090. assert.Equal(t, 1, f.UsedQuotaFiles)
  2091. // rename a file from user home dir to vdir2 overwriting an existing file, vdir2 is not included in user quota so we have:
  2092. // - /vdir1/dir1/testFileName1 (initial testFileName)
  2093. // - /vdir2/dir1/testFileName (initial testFileName1)
  2094. err = client.Rename(testFileName1, path.Join(vdirPath2, dir1, testFileName))
  2095. assert.NoError(t, err)
  2096. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  2097. assert.NoError(t, err)
  2098. assert.Equal(t, 1, user.UsedQuotaFiles)
  2099. assert.Equal(t, testFileSize, user.UsedQuotaSize)
  2100. f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
  2101. assert.NoError(t, err)
  2102. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  2103. assert.Equal(t, 1, f.UsedQuotaFiles)
  2104. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  2105. assert.NoError(t, err)
  2106. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  2107. assert.Equal(t, 1, f.UsedQuotaFiles)
  2108. err = client.Mkdir(dir1)
  2109. assert.NoError(t, err)
  2110. err = writeSFTPFile(path.Join(dir1, testFileName), testFileSize, client)
  2111. assert.NoError(t, err)
  2112. err = writeSFTPFile(path.Join(dir1, testFileName1), testFileSize1, client)
  2113. assert.NoError(t, err)
  2114. // - /dir1/testFileName
  2115. // - /dir1/testFileName1
  2116. // - /vdir1/dir1/testFileName1 (initial testFileName)
  2117. // - /vdir2/dir1/testFileName (initial testFileName1)
  2118. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  2119. assert.NoError(t, err)
  2120. assert.Equal(t, 3, user.UsedQuotaFiles)
  2121. assert.Equal(t, testFileSize*2+testFileSize1, user.UsedQuotaSize)
  2122. f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
  2123. assert.NoError(t, err)
  2124. assert.Equal(t, testFileSize, f.UsedQuotaSize)
  2125. assert.Equal(t, 1, f.UsedQuotaFiles)
  2126. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  2127. assert.NoError(t, err)
  2128. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  2129. assert.Equal(t, 1, f.UsedQuotaFiles)
  2130. // - /vdir1/adir/testFileName
  2131. // - /vdir1/adir/testFileName1
  2132. // - /vdir1/dir1/testFileName1 (initial testFileName)
  2133. // - /vdir2/dir1/testFileName (initial testFileName1)
  2134. err = client.Rename(dir1, path.Join(vdirPath1, "adir"))
  2135. assert.NoError(t, err)
  2136. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  2137. assert.NoError(t, err)
  2138. assert.Equal(t, 3, user.UsedQuotaFiles)
  2139. assert.Equal(t, testFileSize*2+testFileSize1, user.UsedQuotaSize)
  2140. f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
  2141. assert.NoError(t, err)
  2142. assert.Equal(t, testFileSize*2+testFileSize1, f.UsedQuotaSize)
  2143. assert.Equal(t, 3, f.UsedQuotaFiles)
  2144. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  2145. assert.NoError(t, err)
  2146. assert.Equal(t, testFileSize1, f.UsedQuotaSize)
  2147. assert.Equal(t, 1, f.UsedQuotaFiles)
  2148. err = client.Mkdir(dir1)
  2149. assert.NoError(t, err)
  2150. err = writeSFTPFile(path.Join(dir1, testFileName), testFileSize, client)
  2151. assert.NoError(t, err)
  2152. err = writeSFTPFile(path.Join(dir1, testFileName1), testFileSize1, client)
  2153. assert.NoError(t, err)
  2154. // - /vdir1/adir/testFileName
  2155. // - /vdir1/adir/testFileName1
  2156. // - /vdir1/dir1/testFileName1 (initial testFileName)
  2157. // - /vdir2/dir1/testFileName (initial testFileName1)
  2158. // - /vdir2/adir/testFileName
  2159. // - /vdir2/adir/testFileName1
  2160. err = client.Rename(dir1, path.Join(vdirPath2, "adir"))
  2161. assert.NoError(t, err)
  2162. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  2163. assert.NoError(t, err)
  2164. assert.Equal(t, 3, user.UsedQuotaFiles)
  2165. assert.Equal(t, testFileSize*2+testFileSize1, user.UsedQuotaSize)
  2166. f, _, err = httpdtest.GetFolderByName(folderName1, http.StatusOK)
  2167. assert.NoError(t, err)
  2168. assert.Equal(t, testFileSize*2+testFileSize1, f.UsedQuotaSize)
  2169. assert.Equal(t, 3, f.UsedQuotaFiles)
  2170. f, _, err = httpdtest.GetFolderByName(folderName2, http.StatusOK)
  2171. assert.NoError(t, err)
  2172. assert.Equal(t, testFileSize1*2+testFileSize, f.UsedQuotaSize)
  2173. assert.Equal(t, 3, f.UsedQuotaFiles)
  2174. }
  2175. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2176. assert.NoError(t, err)
  2177. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName1}, http.StatusOK)
  2178. assert.NoError(t, err)
  2179. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName2}, http.StatusOK)
  2180. assert.NoError(t, err)
  2181. err = os.RemoveAll(user.GetHomeDir())
  2182. assert.NoError(t, err)
  2183. err = os.RemoveAll(mappedPath1)
  2184. assert.NoError(t, err)
  2185. err = os.RemoveAll(mappedPath2)
  2186. assert.NoError(t, err)
  2187. }
  2188. func TestTransferQuotaLimits(t *testing.T) {
  2189. u := getTestUser()
  2190. u.TotalDataTransfer = 1
  2191. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2192. assert.NoError(t, err)
  2193. conn, client, err := getSftpClient(user)
  2194. if assert.NoError(t, err) {
  2195. defer conn.Close()
  2196. defer client.Close()
  2197. testFileSize := int64(524288)
  2198. err = writeSFTPFile(testFileName, testFileSize, client)
  2199. assert.NoError(t, err)
  2200. f, err := client.Open(testFileName)
  2201. assert.NoError(t, err)
  2202. contents := make([]byte, testFileSize)
  2203. n, err := io.ReadFull(f, contents)
  2204. assert.NoError(t, err)
  2205. assert.Equal(t, int(testFileSize), n)
  2206. assert.Len(t, contents, int(testFileSize))
  2207. err = f.Close()
  2208. assert.NoError(t, err)
  2209. _, err = client.Open(testFileName)
  2210. if assert.Error(t, err) {
  2211. assert.Contains(t, err.Error(), "SSH_FX_FAILURE")
  2212. assert.Contains(t, err.Error(), common.ErrReadQuotaExceeded.Error())
  2213. }
  2214. err = writeSFTPFile(testFileName, testFileSize, client)
  2215. if assert.Error(t, err) {
  2216. assert.Contains(t, err.Error(), "SSH_FX_FAILURE")
  2217. assert.Contains(t, err.Error(), common.ErrQuotaExceeded.Error())
  2218. }
  2219. }
  2220. // test the limit while uploading/downloading
  2221. user.TotalDataTransfer = 0
  2222. user.UploadDataTransfer = 1
  2223. user.DownloadDataTransfer = 1
  2224. _, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  2225. assert.NoError(t, err)
  2226. conn, client, err = getSftpClient(user)
  2227. if assert.NoError(t, err) {
  2228. defer conn.Close()
  2229. defer client.Close()
  2230. testFileSize := int64(450000)
  2231. err = writeSFTPFile(testFileName, testFileSize, client)
  2232. assert.NoError(t, err)
  2233. f, err := client.Open(testFileName)
  2234. if assert.NoError(t, err) {
  2235. _, err = io.Copy(io.Discard, f)
  2236. assert.NoError(t, err)
  2237. err = f.Close()
  2238. assert.NoError(t, err)
  2239. }
  2240. f, err = client.Open(testFileName)
  2241. if assert.NoError(t, err) {
  2242. _, err = io.Copy(io.Discard, f)
  2243. if assert.Error(t, err) {
  2244. assert.Contains(t, err.Error(), "SSH_FX_FAILURE")
  2245. assert.Contains(t, err.Error(), common.ErrReadQuotaExceeded.Error())
  2246. }
  2247. err = f.Close()
  2248. assert.Error(t, err)
  2249. }
  2250. err = writeSFTPFile(testFileName, testFileSize, client)
  2251. if assert.Error(t, err) {
  2252. assert.Contains(t, err.Error(), "SSH_FX_FAILURE")
  2253. assert.Contains(t, err.Error(), common.ErrQuotaExceeded.Error())
  2254. }
  2255. }
  2256. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2257. assert.NoError(t, err)
  2258. err = os.RemoveAll(user.GetHomeDir())
  2259. assert.NoError(t, err)
  2260. }
  2261. func TestVirtualFoldersLink(t *testing.T) {
  2262. u := getTestUser()
  2263. mappedPath1 := filepath.Join(os.TempDir(), "vdir1")
  2264. folderName1 := filepath.Base(mappedPath1)
  2265. vdirPath1 := "/vdir1"
  2266. mappedPath2 := filepath.Join(os.TempDir(), "vdir2")
  2267. folderName2 := filepath.Base(mappedPath2)
  2268. vdirPath2 := "/vdir2"
  2269. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2270. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2271. Name: folderName1,
  2272. MappedPath: mappedPath1,
  2273. },
  2274. VirtualPath: vdirPath1,
  2275. // quota is included in the user's one
  2276. QuotaFiles: -1,
  2277. QuotaSize: -1,
  2278. })
  2279. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2280. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2281. Name: folderName2,
  2282. MappedPath: mappedPath2,
  2283. },
  2284. VirtualPath: vdirPath2,
  2285. // quota is unlimited and excluded from user's one
  2286. QuotaFiles: 0,
  2287. QuotaSize: 0,
  2288. })
  2289. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2290. assert.NoError(t, err)
  2291. conn, client, err := getSftpClient(user)
  2292. if assert.NoError(t, err) {
  2293. defer conn.Close()
  2294. defer client.Close()
  2295. testFileSize := int64(131072)
  2296. testDir := "adir"
  2297. err = writeSFTPFile(testFileName, testFileSize, client)
  2298. assert.NoError(t, err)
  2299. err = writeSFTPFile(path.Join(vdirPath1, testFileName), testFileSize, client)
  2300. assert.NoError(t, err)
  2301. err = writeSFTPFile(path.Join(vdirPath2, testFileName), testFileSize, client)
  2302. assert.NoError(t, err)
  2303. err = client.Mkdir(path.Join(vdirPath1, testDir))
  2304. assert.NoError(t, err)
  2305. err = client.Mkdir(path.Join(vdirPath2, testDir))
  2306. assert.NoError(t, err)
  2307. err = client.Symlink(testFileName, testFileName+".link")
  2308. assert.NoError(t, err)
  2309. err = client.Symlink(path.Join(vdirPath1, testFileName), path.Join(vdirPath1, testFileName+".link"))
  2310. assert.NoError(t, err)
  2311. err = client.Symlink(path.Join(vdirPath1, testFileName), path.Join(vdirPath1, testDir, testFileName+".link"))
  2312. assert.NoError(t, err)
  2313. err = client.Symlink(path.Join(vdirPath2, testFileName), path.Join(vdirPath2, testFileName+".link"))
  2314. assert.NoError(t, err)
  2315. err = client.Symlink(path.Join(vdirPath2, testFileName), path.Join(vdirPath2, testDir, testFileName+".link"))
  2316. assert.NoError(t, err)
  2317. err = client.Symlink(path.Join("/", testFileName), path.Join(vdirPath1, testFileName+".link1"))
  2318. if assert.Error(t, err) {
  2319. assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
  2320. }
  2321. err = client.Symlink(path.Join("/", testFileName), path.Join(vdirPath1, testDir, testFileName+".link1"))
  2322. if assert.Error(t, err) {
  2323. assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
  2324. }
  2325. err = client.Symlink(path.Join("/", testFileName), path.Join(vdirPath2, testFileName+".link1"))
  2326. if assert.Error(t, err) {
  2327. assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
  2328. }
  2329. err = client.Symlink(path.Join("/", testFileName), path.Join(vdirPath2, testDir, testFileName+".link1"))
  2330. if assert.Error(t, err) {
  2331. assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
  2332. }
  2333. err = client.Symlink(path.Join(vdirPath1, testFileName), testFileName+".link1")
  2334. if assert.Error(t, err) {
  2335. assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
  2336. }
  2337. err = client.Symlink(path.Join(vdirPath2, testFileName), testFileName+".link1")
  2338. if assert.Error(t, err) {
  2339. assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
  2340. }
  2341. err = client.Symlink(path.Join(vdirPath1, testFileName), path.Join(vdirPath2, testDir, testFileName+".link1"))
  2342. if assert.Error(t, err) {
  2343. assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
  2344. }
  2345. err = client.Symlink(path.Join(vdirPath2, testFileName), path.Join(vdirPath1, testFileName+".link1"))
  2346. if assert.Error(t, err) {
  2347. assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
  2348. }
  2349. err = client.Symlink("/", "/roolink")
  2350. assert.ErrorIs(t, err, os.ErrPermission)
  2351. err = client.Symlink(testFileName, "/")
  2352. assert.ErrorIs(t, err, os.ErrPermission)
  2353. err = client.Symlink(testFileName, vdirPath1)
  2354. if assert.Error(t, err) {
  2355. assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
  2356. }
  2357. err = client.Symlink(vdirPath1, testFileName+".link2")
  2358. if assert.Error(t, err) {
  2359. assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
  2360. }
  2361. }
  2362. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2363. assert.NoError(t, err)
  2364. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName1}, http.StatusOK)
  2365. assert.NoError(t, err)
  2366. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName2}, http.StatusOK)
  2367. assert.NoError(t, err)
  2368. err = os.RemoveAll(user.GetHomeDir())
  2369. assert.NoError(t, err)
  2370. err = os.RemoveAll(mappedPath1)
  2371. assert.NoError(t, err)
  2372. err = os.RemoveAll(mappedPath2)
  2373. assert.NoError(t, err)
  2374. }
  2375. func TestCrossFolderRename(t *testing.T) {
  2376. folder1 := "folder1"
  2377. folder2 := "folder2"
  2378. folder3 := "folder3"
  2379. folder4 := "folder4"
  2380. folder5 := "folder5"
  2381. folder6 := "folder6"
  2382. folder7 := "folder7"
  2383. baseUser, resp, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  2384. assert.NoError(t, err, string(resp))
  2385. u := getCryptFsUser()
  2386. u.VirtualFolders = []vfs.VirtualFolder{
  2387. {
  2388. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2389. Name: folder1,
  2390. MappedPath: filepath.Join(os.TempDir(), folder1),
  2391. FsConfig: vfs.Filesystem{
  2392. Provider: sdk.CryptedFilesystemProvider,
  2393. CryptConfig: vfs.CryptFsConfig{
  2394. Passphrase: kms.NewPlainSecret(defaultPassword),
  2395. },
  2396. },
  2397. },
  2398. VirtualPath: path.Join("/", folder1),
  2399. QuotaSize: -1,
  2400. QuotaFiles: -1,
  2401. },
  2402. {
  2403. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2404. Name: folder2,
  2405. MappedPath: filepath.Join(os.TempDir(), folder2),
  2406. FsConfig: vfs.Filesystem{
  2407. Provider: sdk.CryptedFilesystemProvider,
  2408. CryptConfig: vfs.CryptFsConfig{
  2409. Passphrase: kms.NewPlainSecret(defaultPassword),
  2410. },
  2411. },
  2412. },
  2413. VirtualPath: path.Join("/", folder2),
  2414. QuotaSize: -1,
  2415. QuotaFiles: -1,
  2416. },
  2417. {
  2418. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2419. Name: folder3,
  2420. MappedPath: filepath.Join(os.TempDir(), folder3),
  2421. FsConfig: vfs.Filesystem{
  2422. Provider: sdk.CryptedFilesystemProvider,
  2423. CryptConfig: vfs.CryptFsConfig{
  2424. Passphrase: kms.NewPlainSecret(defaultPassword + "mod"),
  2425. },
  2426. },
  2427. },
  2428. VirtualPath: path.Join("/", folder3),
  2429. QuotaSize: -1,
  2430. QuotaFiles: -1,
  2431. },
  2432. {
  2433. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2434. Name: folder4,
  2435. MappedPath: filepath.Join(os.TempDir(), folder4),
  2436. FsConfig: vfs.Filesystem{
  2437. Provider: sdk.SFTPFilesystemProvider,
  2438. SFTPConfig: vfs.SFTPFsConfig{
  2439. BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
  2440. Endpoint: sftpServerAddr,
  2441. Username: baseUser.Username,
  2442. Prefix: path.Join("/", folder4),
  2443. },
  2444. Password: kms.NewPlainSecret(defaultPassword),
  2445. },
  2446. },
  2447. },
  2448. VirtualPath: path.Join("/", folder4),
  2449. QuotaSize: -1,
  2450. QuotaFiles: -1,
  2451. },
  2452. {
  2453. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2454. Name: folder5,
  2455. MappedPath: filepath.Join(os.TempDir(), folder5),
  2456. FsConfig: vfs.Filesystem{
  2457. Provider: sdk.SFTPFilesystemProvider,
  2458. SFTPConfig: vfs.SFTPFsConfig{
  2459. BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
  2460. Endpoint: sftpServerAddr,
  2461. Username: baseUser.Username,
  2462. Prefix: path.Join("/", folder5),
  2463. },
  2464. Password: kms.NewPlainSecret(defaultPassword),
  2465. },
  2466. },
  2467. },
  2468. VirtualPath: path.Join("/", folder5),
  2469. QuotaSize: -1,
  2470. QuotaFiles: -1,
  2471. },
  2472. {
  2473. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2474. Name: folder6,
  2475. MappedPath: filepath.Join(os.TempDir(), folder6),
  2476. FsConfig: vfs.Filesystem{
  2477. Provider: sdk.SFTPFilesystemProvider,
  2478. SFTPConfig: vfs.SFTPFsConfig{
  2479. BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
  2480. Endpoint: "127.0.0.1:4024",
  2481. Username: baseUser.Username,
  2482. Prefix: path.Join("/", folder6),
  2483. },
  2484. Password: kms.NewPlainSecret(defaultPassword),
  2485. },
  2486. },
  2487. },
  2488. VirtualPath: path.Join("/", folder6),
  2489. QuotaSize: -1,
  2490. QuotaFiles: -1,
  2491. },
  2492. {
  2493. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2494. Name: folder7,
  2495. MappedPath: filepath.Join(os.TempDir(), folder7),
  2496. FsConfig: vfs.Filesystem{
  2497. Provider: sdk.SFTPFilesystemProvider,
  2498. SFTPConfig: vfs.SFTPFsConfig{
  2499. BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
  2500. Endpoint: sftpServerAddr,
  2501. Username: baseUser.Username,
  2502. Prefix: path.Join("/", folder4),
  2503. },
  2504. Password: kms.NewPlainSecret(defaultPassword),
  2505. },
  2506. },
  2507. },
  2508. VirtualPath: path.Join("/", folder7),
  2509. QuotaSize: -1,
  2510. QuotaFiles: -1,
  2511. },
  2512. }
  2513. user, resp, err := httpdtest.AddUser(u, http.StatusCreated)
  2514. assert.NoError(t, err, string(resp))
  2515. conn, client, err := getSftpClient(user)
  2516. if assert.NoError(t, err) {
  2517. defer conn.Close()
  2518. defer client.Close()
  2519. subDir := "testSubDir"
  2520. err = client.Mkdir(subDir)
  2521. assert.NoError(t, err)
  2522. err = writeSFTPFile(path.Join(subDir, "afile.bin"), 64, client)
  2523. assert.NoError(t, err)
  2524. err = client.Rename(subDir, path.Join("/", folder1, subDir))
  2525. assert.NoError(t, err)
  2526. _, err = client.Stat(path.Join("/", folder1, subDir))
  2527. assert.NoError(t, err)
  2528. _, err = client.Stat(path.Join("/", folder1, subDir, "afile.bin"))
  2529. assert.NoError(t, err)
  2530. err = client.Rename(path.Join("/", folder1, subDir), path.Join("/", folder2, subDir))
  2531. assert.NoError(t, err)
  2532. _, err = client.Stat(path.Join("/", folder2, subDir))
  2533. assert.NoError(t, err)
  2534. _, err = client.Stat(path.Join("/", folder2, subDir, "afile.bin"))
  2535. assert.NoError(t, err)
  2536. err = client.Rename(path.Join("/", folder2, subDir), path.Join("/", folder3, subDir))
  2537. assert.ErrorIs(t, err, os.ErrPermission)
  2538. err = writeSFTPFile(path.Join("/", folder3, "file.bin"), 64, client)
  2539. assert.NoError(t, err)
  2540. err = client.Rename(path.Join("/", folder3, "file.bin"), "/renamed.bin")
  2541. assert.ErrorIs(t, err, os.ErrPermission)
  2542. err = client.Rename(path.Join("/", folder3, "file.bin"), path.Join("/", folder2, "/renamed.bin"))
  2543. assert.ErrorIs(t, err, os.ErrPermission)
  2544. err = client.Rename(path.Join("/", folder3, "file.bin"), path.Join("/", folder3, "/renamed.bin"))
  2545. assert.NoError(t, err)
  2546. err = writeSFTPFile("/afile.bin", 64, client)
  2547. assert.NoError(t, err)
  2548. err = client.Rename("afile.bin", path.Join("/", folder4, "afile_renamed.bin"))
  2549. assert.ErrorIs(t, err, os.ErrPermission)
  2550. err = writeSFTPFile(path.Join("/", folder4, "afile.bin"), 64, client)
  2551. assert.NoError(t, err)
  2552. err = client.Rename(path.Join("/", folder4, "afile.bin"), path.Join("/", folder5, "afile_renamed.bin"))
  2553. assert.NoError(t, err)
  2554. err = client.Rename(path.Join("/", folder5, "afile_renamed.bin"), path.Join("/", folder6, "afile_renamed.bin"))
  2555. assert.ErrorIs(t, err, os.ErrPermission)
  2556. err = writeSFTPFile(path.Join("/", folder4, "afile.bin"), 64, client)
  2557. assert.NoError(t, err)
  2558. _, err = client.Stat(path.Join("/", folder7, "afile.bin"))
  2559. assert.NoError(t, err)
  2560. err = client.Rename(path.Join("/", folder4, "afile.bin"), path.Join("/", folder7, "afile.bin"))
  2561. assert.NoError(t, err)
  2562. }
  2563. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2564. assert.NoError(t, err)
  2565. err = os.RemoveAll(user.GetHomeDir())
  2566. assert.NoError(t, err)
  2567. _, err = httpdtest.RemoveUser(baseUser, http.StatusOK)
  2568. assert.NoError(t, err)
  2569. err = os.RemoveAll(baseUser.GetHomeDir())
  2570. assert.NoError(t, err)
  2571. for _, folderName := range []string{folder1, folder2, folder3, folder4, folder5, folder6, folder7} {
  2572. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName}, http.StatusOK)
  2573. assert.NoError(t, err)
  2574. err = os.RemoveAll(filepath.Join(os.TempDir(), folderName))
  2575. assert.NoError(t, err)
  2576. }
  2577. }
  2578. func TestDirs(t *testing.T) {
  2579. u := getTestUser()
  2580. mappedPath := filepath.Join(os.TempDir(), "vdir")
  2581. folderName := filepath.Base(mappedPath)
  2582. vdirPath := "/path/vdir"
  2583. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2584. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2585. Name: folderName,
  2586. MappedPath: mappedPath,
  2587. },
  2588. VirtualPath: vdirPath,
  2589. })
  2590. u.Permissions["/subdir"] = []string{dataprovider.PermDownload, dataprovider.PermUpload,
  2591. dataprovider.PermDelete, dataprovider.PermCreateDirs, dataprovider.PermRename, dataprovider.PermListItems}
  2592. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2593. assert.NoError(t, err)
  2594. conn, client, err := getSftpClient(user)
  2595. if assert.NoError(t, err) {
  2596. defer conn.Close()
  2597. defer client.Close()
  2598. info, err := client.ReadDir("/")
  2599. if assert.NoError(t, err) {
  2600. if assert.Len(t, info, 1) {
  2601. assert.Equal(t, "path", info[0].Name())
  2602. }
  2603. }
  2604. fi, err := client.Stat(path.Dir(vdirPath))
  2605. if assert.NoError(t, err) {
  2606. assert.True(t, fi.IsDir())
  2607. }
  2608. err = client.RemoveDirectory("/")
  2609. assert.ErrorIs(t, err, os.ErrPermission)
  2610. err = client.RemoveDirectory(vdirPath)
  2611. assert.ErrorIs(t, err, os.ErrPermission)
  2612. err = client.RemoveDirectory(path.Dir(vdirPath))
  2613. if assert.Error(t, err) {
  2614. assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
  2615. }
  2616. err = client.Mkdir(vdirPath)
  2617. assert.ErrorIs(t, err, os.ErrPermission)
  2618. err = client.Mkdir("adir")
  2619. assert.NoError(t, err)
  2620. err = client.Rename("/adir", path.Dir(vdirPath))
  2621. if assert.Error(t, err) {
  2622. assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
  2623. }
  2624. err = client.MkdirAll("/subdir/adir")
  2625. assert.NoError(t, err)
  2626. err = client.Rename("adir", "subdir/adir")
  2627. if assert.Error(t, err) {
  2628. assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
  2629. }
  2630. err = writeSFTPFile("/subdir/afile.bin", 64, client)
  2631. assert.NoError(t, err)
  2632. err = writeSFTPFile("/afile.bin", 32, client)
  2633. assert.NoError(t, err)
  2634. err = client.Rename("afile.bin", "subdir/afile.bin")
  2635. assert.ErrorIs(t, err, os.ErrPermission)
  2636. err = client.Rename("afile.bin", "subdir/afile1.bin")
  2637. assert.NoError(t, err)
  2638. err = client.Rename(path.Dir(vdirPath), "renamed_vdir")
  2639. if assert.Error(t, err) {
  2640. assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
  2641. }
  2642. }
  2643. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2644. assert.NoError(t, err)
  2645. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName}, http.StatusOK)
  2646. assert.NoError(t, err)
  2647. err = os.RemoveAll(user.GetHomeDir())
  2648. assert.NoError(t, err)
  2649. err = os.RemoveAll(mappedPath)
  2650. assert.NoError(t, err)
  2651. }
  2652. func TestCryptFsStat(t *testing.T) {
  2653. user, _, err := httpdtest.AddUser(getCryptFsUser(), http.StatusCreated)
  2654. assert.NoError(t, err)
  2655. conn, client, err := getSftpClient(user)
  2656. if assert.NoError(t, err) {
  2657. defer conn.Close()
  2658. defer client.Close()
  2659. testFileSize := int64(4096)
  2660. err = writeSFTPFile(testFileName, testFileSize, client)
  2661. assert.NoError(t, err)
  2662. info, err := client.Stat(testFileName)
  2663. if assert.NoError(t, err) {
  2664. assert.Equal(t, testFileSize, info.Size())
  2665. }
  2666. info, err = os.Stat(filepath.Join(user.HomeDir, testFileName))
  2667. if assert.NoError(t, err) {
  2668. assert.Greater(t, info.Size(), testFileSize)
  2669. }
  2670. }
  2671. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2672. assert.NoError(t, err)
  2673. err = os.RemoveAll(user.GetHomeDir())
  2674. assert.NoError(t, err)
  2675. }
  2676. func TestFsPermissionErrors(t *testing.T) {
  2677. if runtime.GOOS == osWindows {
  2678. t.Skip("this test is not available on Windows")
  2679. }
  2680. user, _, err := httpdtest.AddUser(getCryptFsUser(), http.StatusCreated)
  2681. assert.NoError(t, err)
  2682. conn, client, err := getSftpClient(user)
  2683. if assert.NoError(t, err) {
  2684. defer conn.Close()
  2685. defer client.Close()
  2686. testDir := "tDir"
  2687. err = client.Mkdir(testDir)
  2688. assert.NoError(t, err)
  2689. err = os.Chmod(user.GetHomeDir(), 0111)
  2690. assert.NoError(t, err)
  2691. err = client.RemoveDirectory(testDir)
  2692. assert.ErrorIs(t, err, os.ErrPermission)
  2693. err = client.Rename(testDir, testDir+"1")
  2694. assert.ErrorIs(t, err, os.ErrPermission)
  2695. err = os.Chmod(user.GetHomeDir(), os.ModePerm)
  2696. assert.NoError(t, err)
  2697. }
  2698. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2699. assert.NoError(t, err)
  2700. err = os.RemoveAll(user.GetHomeDir())
  2701. assert.NoError(t, err)
  2702. }
  2703. func TestRenameErrorOutsideHomeDir(t *testing.T) {
  2704. if runtime.GOOS == osWindows {
  2705. t.Skip("this test is not available on Windows")
  2706. }
  2707. oldUploadMode := common.Config.UploadMode
  2708. oldTempPath := common.Config.TempPath
  2709. common.Config.UploadMode = common.UploadModeAtomicWithResume
  2710. common.Config.TempPath = filepath.Clean(os.TempDir())
  2711. vfs.SetTempPath(common.Config.TempPath)
  2712. u := getTestUser()
  2713. u.QuotaFiles = 1000
  2714. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2715. assert.NoError(t, err)
  2716. conn, client, err := getSftpClient(user)
  2717. if assert.NoError(t, err) {
  2718. defer conn.Close()
  2719. defer client.Close()
  2720. err = os.Chmod(user.GetHomeDir(), 0555)
  2721. assert.NoError(t, err)
  2722. err = checkBasicSFTP(client)
  2723. assert.NoError(t, err)
  2724. f, err := client.Create(testFileName)
  2725. assert.NoError(t, err)
  2726. _, err = f.Write(testFileContent)
  2727. assert.NoError(t, err)
  2728. err = f.Close()
  2729. assert.ErrorIs(t, err, os.ErrPermission)
  2730. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  2731. assert.NoError(t, err)
  2732. assert.Equal(t, 0, user.UsedQuotaFiles)
  2733. assert.Equal(t, int64(0), user.UsedQuotaSize)
  2734. err = os.Chmod(user.GetHomeDir(), os.ModeDir)
  2735. assert.NoError(t, err)
  2736. }
  2737. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2738. assert.NoError(t, err)
  2739. err = os.RemoveAll(user.GetHomeDir())
  2740. assert.NoError(t, err)
  2741. common.Config.UploadMode = oldUploadMode
  2742. common.Config.TempPath = oldTempPath
  2743. vfs.SetTempPath(oldTempPath)
  2744. }
  2745. func TestResolvePathError(t *testing.T) {
  2746. u := getTestUser()
  2747. u.HomeDir = "relative_path"
  2748. conn := common.NewBaseConnection("", common.ProtocolFTP, "", "", u)
  2749. testPath := "apath"
  2750. _, err := conn.ListDir(testPath)
  2751. assert.Error(t, err)
  2752. err = conn.CreateDir(testPath, true)
  2753. assert.Error(t, err)
  2754. err = conn.RemoveDir(testPath)
  2755. assert.Error(t, err)
  2756. err = conn.Rename(testPath, testPath+"1")
  2757. assert.Error(t, err)
  2758. err = conn.CreateSymlink(testPath, testPath+".sym")
  2759. assert.Error(t, err)
  2760. _, err = conn.DoStat(testPath, 0, false)
  2761. assert.Error(t, err)
  2762. err = conn.SetStat(testPath, &common.StatAttributes{
  2763. Atime: time.Now(),
  2764. Mtime: time.Now(),
  2765. })
  2766. assert.Error(t, err)
  2767. u = getTestUser()
  2768. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  2769. BaseVirtualFolder: vfs.BaseVirtualFolder{
  2770. MappedPath: "relative_mapped_path",
  2771. },
  2772. VirtualPath: "/vpath",
  2773. })
  2774. err = os.MkdirAll(u.HomeDir, os.ModePerm)
  2775. assert.NoError(t, err)
  2776. conn.User = u
  2777. err = conn.Rename(testPath, "/vpath/subpath")
  2778. assert.Error(t, err)
  2779. outHomePath := filepath.Join(os.TempDir(), testFileName)
  2780. err = os.WriteFile(outHomePath, testFileContent, os.ModePerm)
  2781. assert.NoError(t, err)
  2782. err = os.Symlink(outHomePath, filepath.Join(u.HomeDir, testFileName+".link"))
  2783. assert.NoError(t, err)
  2784. err = os.WriteFile(filepath.Join(u.HomeDir, testFileName), testFileContent, os.ModePerm)
  2785. assert.NoError(t, err)
  2786. err = conn.CreateSymlink(testFileName, testFileName+".link")
  2787. assert.Error(t, err)
  2788. err = os.RemoveAll(u.GetHomeDir())
  2789. assert.NoError(t, err)
  2790. err = os.Remove(outHomePath)
  2791. assert.NoError(t, err)
  2792. }
  2793. func TestUserPasswordHashing(t *testing.T) {
  2794. if config.GetProviderConf().Driver == dataprovider.MemoryDataProviderName {
  2795. t.Skip("this test is not supported with the memory provider")
  2796. }
  2797. u := getTestUser()
  2798. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2799. assert.NoError(t, err)
  2800. err = dataprovider.Close()
  2801. assert.NoError(t, err)
  2802. err = config.LoadConfig(configDir, "")
  2803. assert.NoError(t, err)
  2804. providerConf := config.GetProviderConf()
  2805. providerConf.PasswordHashing.Algo = dataprovider.HashingAlgoArgon2ID
  2806. err = dataprovider.Initialize(providerConf, configDir, true)
  2807. assert.NoError(t, err)
  2808. currentUser, err := dataprovider.UserExists(user.Username)
  2809. assert.NoError(t, err)
  2810. assert.True(t, strings.HasPrefix(currentUser.Password, "$2a$"))
  2811. conn, client, err := getSftpClient(user)
  2812. if assert.NoError(t, err) {
  2813. defer conn.Close()
  2814. defer client.Close()
  2815. err = checkBasicSFTP(client)
  2816. assert.NoError(t, err)
  2817. }
  2818. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2819. assert.NoError(t, err)
  2820. err = os.RemoveAll(user.GetHomeDir())
  2821. assert.NoError(t, err)
  2822. u = getTestUser()
  2823. user, _, err = httpdtest.AddUser(u, http.StatusCreated)
  2824. assert.NoError(t, err)
  2825. currentUser, err = dataprovider.UserExists(user.Username)
  2826. assert.NoError(t, err)
  2827. assert.True(t, strings.HasPrefix(currentUser.Password, "$argon2id$"))
  2828. conn, client, err = getSftpClient(user)
  2829. if assert.NoError(t, err) {
  2830. defer conn.Close()
  2831. defer client.Close()
  2832. err = checkBasicSFTP(client)
  2833. assert.NoError(t, err)
  2834. }
  2835. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2836. assert.NoError(t, err)
  2837. err = os.RemoveAll(user.GetHomeDir())
  2838. assert.NoError(t, err)
  2839. err = dataprovider.Close()
  2840. assert.NoError(t, err)
  2841. err = config.LoadConfig(configDir, "")
  2842. assert.NoError(t, err)
  2843. providerConf = config.GetProviderConf()
  2844. err = dataprovider.Initialize(providerConf, configDir, true)
  2845. assert.NoError(t, err)
  2846. }
  2847. func TestDbDefenderErrors(t *testing.T) {
  2848. if !isDbDefenderSupported() {
  2849. t.Skip("this test is not supported with the current database provider")
  2850. }
  2851. configCopy := common.Config
  2852. common.Config.DefenderConfig.Enabled = true
  2853. common.Config.DefenderConfig.Driver = common.DefenderDriverProvider
  2854. err := common.Initialize(common.Config, 0)
  2855. assert.NoError(t, err)
  2856. testIP := "127.1.1.1"
  2857. hosts, err := common.GetDefenderHosts()
  2858. assert.NoError(t, err)
  2859. assert.Len(t, hosts, 0)
  2860. common.AddDefenderEvent(testIP, common.HostEventLimitExceeded)
  2861. hosts, err = common.GetDefenderHosts()
  2862. assert.NoError(t, err)
  2863. assert.Len(t, hosts, 1)
  2864. score, err := common.GetDefenderScore(testIP)
  2865. assert.NoError(t, err)
  2866. assert.Equal(t, 3, score)
  2867. banTime, err := common.GetDefenderBanTime(testIP)
  2868. assert.NoError(t, err)
  2869. assert.Nil(t, banTime)
  2870. err = dataprovider.Close()
  2871. assert.NoError(t, err)
  2872. common.AddDefenderEvent(testIP, common.HostEventLimitExceeded)
  2873. _, err = common.GetDefenderHosts()
  2874. assert.Error(t, err)
  2875. _, err = common.GetDefenderHost(testIP)
  2876. assert.Error(t, err)
  2877. _, err = common.GetDefenderBanTime(testIP)
  2878. assert.Error(t, err)
  2879. _, err = common.GetDefenderScore(testIP)
  2880. assert.Error(t, err)
  2881. err = config.LoadConfig(configDir, "")
  2882. assert.NoError(t, err)
  2883. providerConf := config.GetProviderConf()
  2884. err = dataprovider.Initialize(providerConf, configDir, true)
  2885. assert.NoError(t, err)
  2886. err = dataprovider.CleanupDefender(util.GetTimeAsMsSinceEpoch(time.Now().Add(1 * time.Hour)))
  2887. assert.NoError(t, err)
  2888. common.Config = configCopy
  2889. err = common.Initialize(common.Config, 0)
  2890. assert.NoError(t, err)
  2891. }
  2892. func TestDelayedQuotaUpdater(t *testing.T) {
  2893. err := dataprovider.Close()
  2894. assert.NoError(t, err)
  2895. err = config.LoadConfig(configDir, "")
  2896. assert.NoError(t, err)
  2897. providerConf := config.GetProviderConf()
  2898. providerConf.DelayedQuotaUpdate = 120
  2899. err = dataprovider.Initialize(providerConf, configDir, true)
  2900. assert.NoError(t, err)
  2901. u := getTestUser()
  2902. u.QuotaFiles = 100
  2903. u.TotalDataTransfer = 2000
  2904. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  2905. assert.NoError(t, err)
  2906. err = dataprovider.UpdateUserQuota(&user, 10, 6000, false)
  2907. assert.NoError(t, err)
  2908. err = dataprovider.UpdateUserTransferQuota(&user, 100, 200, false)
  2909. assert.NoError(t, err)
  2910. files, size, ulSize, dlSize, err := dataprovider.GetUsedQuota(user.Username)
  2911. assert.NoError(t, err)
  2912. assert.Equal(t, 10, files)
  2913. assert.Equal(t, int64(6000), size)
  2914. assert.Equal(t, int64(100), ulSize)
  2915. assert.Equal(t, int64(200), dlSize)
  2916. userGet, err := dataprovider.UserExists(user.Username)
  2917. assert.NoError(t, err)
  2918. assert.Equal(t, 0, userGet.UsedQuotaFiles)
  2919. assert.Equal(t, int64(0), userGet.UsedQuotaSize)
  2920. assert.Equal(t, int64(0), userGet.UsedUploadDataTransfer)
  2921. assert.Equal(t, int64(0), userGet.UsedDownloadDataTransfer)
  2922. err = dataprovider.UpdateUserQuota(&user, 10, 6000, true)
  2923. assert.NoError(t, err)
  2924. err = dataprovider.UpdateUserTransferQuota(&user, 100, 200, true)
  2925. assert.NoError(t, err)
  2926. files, size, ulSize, dlSize, err = dataprovider.GetUsedQuota(user.Username)
  2927. assert.NoError(t, err)
  2928. assert.Equal(t, 10, files)
  2929. assert.Equal(t, int64(6000), size)
  2930. assert.Equal(t, int64(100), ulSize)
  2931. assert.Equal(t, int64(200), dlSize)
  2932. userGet, err = dataprovider.UserExists(user.Username)
  2933. assert.NoError(t, err)
  2934. assert.Equal(t, 10, userGet.UsedQuotaFiles)
  2935. assert.Equal(t, int64(6000), userGet.UsedQuotaSize)
  2936. assert.Equal(t, int64(100), userGet.UsedUploadDataTransfer)
  2937. assert.Equal(t, int64(200), userGet.UsedDownloadDataTransfer)
  2938. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  2939. assert.NoError(t, err)
  2940. err = os.RemoveAll(user.GetHomeDir())
  2941. assert.NoError(t, err)
  2942. folder := vfs.BaseVirtualFolder{
  2943. Name: "folder",
  2944. MappedPath: filepath.Join(os.TempDir(), "p"),
  2945. }
  2946. err = dataprovider.AddFolder(&folder, "", "")
  2947. assert.NoError(t, err)
  2948. err = dataprovider.UpdateVirtualFolderQuota(&folder, 10, 6000, false)
  2949. assert.NoError(t, err)
  2950. files, size, err = dataprovider.GetUsedVirtualFolderQuota(folder.Name)
  2951. assert.NoError(t, err)
  2952. assert.Equal(t, 10, files)
  2953. assert.Equal(t, int64(6000), size)
  2954. folderGet, err := dataprovider.GetFolderByName(folder.Name)
  2955. assert.NoError(t, err)
  2956. assert.Equal(t, 0, folderGet.UsedQuotaFiles)
  2957. assert.Equal(t, int64(0), folderGet.UsedQuotaSize)
  2958. err = dataprovider.UpdateVirtualFolderQuota(&folder, 10, 6000, true)
  2959. assert.NoError(t, err)
  2960. files, size, err = dataprovider.GetUsedVirtualFolderQuota(folder.Name)
  2961. assert.NoError(t, err)
  2962. assert.Equal(t, 10, files)
  2963. assert.Equal(t, int64(6000), size)
  2964. folderGet, err = dataprovider.GetFolderByName(folder.Name)
  2965. assert.NoError(t, err)
  2966. assert.Equal(t, 10, folderGet.UsedQuotaFiles)
  2967. assert.Equal(t, int64(6000), folderGet.UsedQuotaSize)
  2968. err = dataprovider.DeleteFolder(folder.Name, "", "")
  2969. assert.NoError(t, err)
  2970. err = dataprovider.Close()
  2971. assert.NoError(t, err)
  2972. err = config.LoadConfig(configDir, "")
  2973. assert.NoError(t, err)
  2974. providerConf = config.GetProviderConf()
  2975. err = dataprovider.Initialize(providerConf, configDir, true)
  2976. assert.NoError(t, err)
  2977. }
  2978. func TestPasswordCaching(t *testing.T) {
  2979. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  2980. assert.NoError(t, err)
  2981. found, match := dataprovider.CheckCachedPassword(user.Username, defaultPassword)
  2982. assert.False(t, found)
  2983. assert.False(t, match)
  2984. user.Password = "wrong"
  2985. _, _, err = getSftpClient(user)
  2986. assert.Error(t, err)
  2987. found, match = dataprovider.CheckCachedPassword(user.Username, defaultPassword)
  2988. assert.False(t, found)
  2989. assert.False(t, match)
  2990. user.Password = ""
  2991. conn, client, err := getSftpClient(user)
  2992. if assert.NoError(t, err) {
  2993. defer conn.Close()
  2994. defer client.Close()
  2995. err = checkBasicSFTP(client)
  2996. assert.NoError(t, err)
  2997. }
  2998. found, match = dataprovider.CheckCachedPassword(user.Username, defaultPassword)
  2999. assert.True(t, found)
  3000. assert.True(t, match)
  3001. found, match = dataprovider.CheckCachedPassword(user.Username, defaultPassword+"_")
  3002. assert.True(t, found)
  3003. assert.False(t, match)
  3004. found, match = dataprovider.CheckCachedPassword(user.Username+"_", defaultPassword)
  3005. assert.False(t, found)
  3006. assert.False(t, match)
  3007. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  3008. assert.NoError(t, err)
  3009. found, match = dataprovider.CheckCachedPassword(user.Username, defaultPassword)
  3010. assert.False(t, found)
  3011. assert.False(t, match)
  3012. conn, client, err = getSftpClient(user)
  3013. if assert.NoError(t, err) {
  3014. defer conn.Close()
  3015. defer client.Close()
  3016. err = checkBasicSFTP(client)
  3017. assert.NoError(t, err)
  3018. }
  3019. found, match = dataprovider.CheckCachedPassword(user.Username, defaultPassword)
  3020. assert.True(t, found)
  3021. assert.True(t, match)
  3022. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  3023. assert.NoError(t, err)
  3024. err = os.RemoveAll(user.GetHomeDir())
  3025. assert.NoError(t, err)
  3026. found, match = dataprovider.CheckCachedPassword(user.Username, defaultPassword)
  3027. assert.False(t, found)
  3028. assert.False(t, match)
  3029. }
  3030. func TestEventRule(t *testing.T) {
  3031. if runtime.GOOS == osWindows {
  3032. t.Skip("this test is not available on Windows")
  3033. }
  3034. smtpCfg := smtp.Config{
  3035. Host: "127.0.0.1",
  3036. Port: 2525,
  3037. From: "notification@example.com",
  3038. TemplatesPath: "templates",
  3039. }
  3040. err := smtpCfg.Initialize(configDir)
  3041. require.NoError(t, err)
  3042. a1 := dataprovider.BaseEventAction{
  3043. Name: "action1",
  3044. Type: dataprovider.ActionTypeHTTP,
  3045. Options: dataprovider.BaseEventActionOptions{
  3046. HTTPConfig: dataprovider.EventActionHTTPConfig{
  3047. Endpoint: "http://localhost",
  3048. Timeout: 20,
  3049. Method: http.MethodGet,
  3050. },
  3051. },
  3052. }
  3053. a2 := dataprovider.BaseEventAction{
  3054. Name: "action2",
  3055. Type: dataprovider.ActionTypeEmail,
  3056. Options: dataprovider.BaseEventActionOptions{
  3057. EmailConfig: dataprovider.EventActionEmailConfig{
  3058. Recipients: []string{"test1@example.com", "test2@example.com"},
  3059. Subject: `New "{{Event}}" from "{{Name}}" status {{StatusString}}`,
  3060. Body: "Fs path {{FsPath}}, size: {{FileSize}}, protocol: {{Protocol}}, IP: {{IP}} Data: {{ObjectData}} {{ErrorString}}",
  3061. },
  3062. },
  3063. }
  3064. a3 := dataprovider.BaseEventAction{
  3065. Name: "action3",
  3066. Type: dataprovider.ActionTypeEmail,
  3067. Options: dataprovider.BaseEventActionOptions{
  3068. EmailConfig: dataprovider.EventActionEmailConfig{
  3069. Recipients: []string{"failure@example.com"},
  3070. Subject: `Failed "{{Event}}" from "{{Name}}"`,
  3071. Body: "Fs path {{FsPath}}, protocol: {{Protocol}}, IP: {{IP}} {{ErrorString}}",
  3072. },
  3073. },
  3074. }
  3075. action1, _, err := httpdtest.AddEventAction(a1, http.StatusCreated)
  3076. assert.NoError(t, err)
  3077. action2, _, err := httpdtest.AddEventAction(a2, http.StatusCreated)
  3078. assert.NoError(t, err)
  3079. action3, _, err := httpdtest.AddEventAction(a3, http.StatusCreated)
  3080. assert.NoError(t, err)
  3081. r1 := dataprovider.EventRule{
  3082. Name: "test rule1",
  3083. Trigger: dataprovider.EventTriggerFsEvent,
  3084. Conditions: dataprovider.EventConditions{
  3085. FsEvents: []string{"upload"},
  3086. Options: dataprovider.ConditionOptions{
  3087. FsPaths: []dataprovider.ConditionPattern{
  3088. {
  3089. Pattern: "/subdir/*.dat",
  3090. },
  3091. {
  3092. Pattern: "*.txt",
  3093. },
  3094. },
  3095. },
  3096. },
  3097. Actions: []dataprovider.EventAction{
  3098. {
  3099. BaseEventAction: dataprovider.BaseEventAction{
  3100. Name: action1.Name,
  3101. },
  3102. Order: 1,
  3103. Options: dataprovider.EventActionOptions{
  3104. ExecuteSync: true,
  3105. StopOnFailure: true,
  3106. },
  3107. },
  3108. {
  3109. BaseEventAction: dataprovider.BaseEventAction{
  3110. Name: action2.Name,
  3111. },
  3112. Order: 2,
  3113. },
  3114. {
  3115. BaseEventAction: dataprovider.BaseEventAction{
  3116. Name: action3.Name,
  3117. },
  3118. Order: 3,
  3119. Options: dataprovider.EventActionOptions{
  3120. IsFailureAction: true,
  3121. },
  3122. },
  3123. },
  3124. }
  3125. rule1, _, err := httpdtest.AddEventRule(r1, http.StatusCreated)
  3126. assert.NoError(t, err)
  3127. r2 := dataprovider.EventRule{
  3128. Name: "test rule2",
  3129. Trigger: dataprovider.EventTriggerFsEvent,
  3130. Conditions: dataprovider.EventConditions{
  3131. FsEvents: []string{"download"},
  3132. Options: dataprovider.ConditionOptions{
  3133. FsPaths: []dataprovider.ConditionPattern{
  3134. {
  3135. Pattern: "*.dat",
  3136. },
  3137. },
  3138. },
  3139. },
  3140. Actions: []dataprovider.EventAction{
  3141. {
  3142. BaseEventAction: dataprovider.BaseEventAction{
  3143. Name: action2.Name,
  3144. },
  3145. Order: 1,
  3146. },
  3147. {
  3148. BaseEventAction: dataprovider.BaseEventAction{
  3149. Name: action3.Name,
  3150. },
  3151. Order: 2,
  3152. Options: dataprovider.EventActionOptions{
  3153. IsFailureAction: true,
  3154. },
  3155. },
  3156. },
  3157. }
  3158. rule2, _, err := httpdtest.AddEventRule(r2, http.StatusCreated)
  3159. assert.NoError(t, err)
  3160. r3 := dataprovider.EventRule{
  3161. Name: "test rule3",
  3162. Trigger: dataprovider.EventTriggerProviderEvent,
  3163. Conditions: dataprovider.EventConditions{
  3164. ProviderEvents: []string{"delete"},
  3165. },
  3166. Actions: []dataprovider.EventAction{
  3167. {
  3168. BaseEventAction: dataprovider.BaseEventAction{
  3169. Name: action2.Name,
  3170. },
  3171. Order: 1,
  3172. },
  3173. },
  3174. }
  3175. rule3, _, err := httpdtest.AddEventRule(r3, http.StatusCreated)
  3176. assert.NoError(t, err)
  3177. uploadScriptPath := filepath.Join(os.TempDir(), "upload.sh")
  3178. u := getTestUser()
  3179. u.DownloadDataTransfer = 1
  3180. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  3181. assert.NoError(t, err)
  3182. movedFileName := "moved.dat"
  3183. movedPath := filepath.Join(user.HomeDir, movedFileName)
  3184. err = os.WriteFile(uploadScriptPath, getUploadScriptContent(movedPath, "", 0), 0755)
  3185. assert.NoError(t, err)
  3186. action1.Type = dataprovider.ActionTypeCommand
  3187. action1.Options = dataprovider.BaseEventActionOptions{
  3188. CmdConfig: dataprovider.EventActionCommandConfig{
  3189. Cmd: uploadScriptPath,
  3190. Timeout: 10,
  3191. EnvVars: []dataprovider.KeyValue{
  3192. {
  3193. Key: "SFTPGO_ACTION_PATH",
  3194. Value: "{{FsPath}}",
  3195. },
  3196. {
  3197. Key: "CUSTOM_ENV_VAR",
  3198. Value: "value",
  3199. },
  3200. },
  3201. },
  3202. }
  3203. action1, _, err = httpdtest.UpdateEventAction(action1, http.StatusOK)
  3204. assert.NoError(t, err)
  3205. dirName := "subdir"
  3206. conn, client, err := getSftpClient(user)
  3207. if assert.NoError(t, err) {
  3208. defer conn.Close()
  3209. defer client.Close()
  3210. size := int64(32768)
  3211. // rule conditions does not match
  3212. err = writeSFTPFileNoCheck(testFileName, size, client)
  3213. assert.NoError(t, err)
  3214. info, err := client.Stat(testFileName)
  3215. if assert.NoError(t, err) {
  3216. assert.Equal(t, size, info.Size())
  3217. }
  3218. err = client.Mkdir(dirName)
  3219. assert.NoError(t, err)
  3220. err = client.Mkdir("subdir1")
  3221. assert.NoError(t, err)
  3222. // rule conditions match
  3223. lastReceivedEmail.reset()
  3224. err = writeSFTPFileNoCheck(path.Join(dirName, testFileName), size, client)
  3225. assert.NoError(t, err)
  3226. _, err = client.Stat(path.Join(dirName, testFileName))
  3227. assert.Error(t, err)
  3228. info, err = client.Stat(movedFileName)
  3229. if assert.NoError(t, err) {
  3230. assert.Equal(t, size, info.Size())
  3231. }
  3232. assert.Eventually(t, func() bool {
  3233. return lastReceivedEmail.get().From != ""
  3234. }, 3000*time.Millisecond, 100*time.Millisecond)
  3235. email := lastReceivedEmail.get()
  3236. assert.Len(t, email.To, 2)
  3237. assert.True(t, util.Contains(email.To, "test1@example.com"))
  3238. assert.True(t, util.Contains(email.To, "test2@example.com"))
  3239. assert.Contains(t, email.Data, fmt.Sprintf(`Subject: New "upload" from "%s" status OK`, user.Username))
  3240. // test the failure action, we download a file that exceeds the transfer quota limit
  3241. err = writeSFTPFileNoCheck(path.Join("subdir1", testFileName), 1*1024*1024+65535, client)
  3242. assert.NoError(t, err)
  3243. lastReceivedEmail.reset()
  3244. f, err := client.Open(path.Join("subdir1", testFileName))
  3245. assert.NoError(t, err)
  3246. _, err = io.ReadAll(f)
  3247. if assert.Error(t, err) {
  3248. assert.Contains(t, err.Error(), common.ErrReadQuotaExceeded.Error())
  3249. }
  3250. err = f.Close()
  3251. assert.Error(t, err)
  3252. assert.Eventually(t, func() bool {
  3253. return lastReceivedEmail.get().From != ""
  3254. }, 3000*time.Millisecond, 100*time.Millisecond)
  3255. email = lastReceivedEmail.get()
  3256. assert.Len(t, email.To, 2)
  3257. assert.True(t, util.Contains(email.To, "test1@example.com"))
  3258. assert.True(t, util.Contains(email.To, "test2@example.com"))
  3259. assert.Contains(t, email.Data, fmt.Sprintf(`Subject: New "download" from "%s" status KO`, user.Username))
  3260. assert.Contains(t, email.Data, `"download" failed`)
  3261. assert.Contains(t, email.Data, common.ErrReadQuotaExceeded.Error())
  3262. _, err = httpdtest.UpdateTransferQuotaUsage(user, "", http.StatusOK)
  3263. assert.NoError(t, err)
  3264. // remove the upload script to test the failure action
  3265. err = os.Remove(uploadScriptPath)
  3266. assert.NoError(t, err)
  3267. lastReceivedEmail.reset()
  3268. err = writeSFTPFileNoCheck(path.Join(dirName, testFileName), size, client)
  3269. assert.Error(t, err)
  3270. assert.Eventually(t, func() bool {
  3271. return lastReceivedEmail.get().From != ""
  3272. }, 3000*time.Millisecond, 100*time.Millisecond)
  3273. email = lastReceivedEmail.get()
  3274. assert.Len(t, email.To, 1)
  3275. assert.True(t, util.Contains(email.To, "failure@example.com"))
  3276. assert.Contains(t, email.Data, fmt.Sprintf(`Subject: Failed "upload" from "%s"`, user.Username))
  3277. assert.Contains(t, email.Data, fmt.Sprintf(`action %q failed`, action1.Name))
  3278. // now test the download rule
  3279. lastReceivedEmail.reset()
  3280. f, err = client.Open(movedFileName)
  3281. assert.NoError(t, err)
  3282. contents, err := io.ReadAll(f)
  3283. assert.NoError(t, err)
  3284. err = f.Close()
  3285. assert.NoError(t, err)
  3286. assert.Len(t, contents, int(size))
  3287. assert.Eventually(t, func() bool {
  3288. return lastReceivedEmail.get().From != ""
  3289. }, 3000*time.Millisecond, 100*time.Millisecond)
  3290. email = lastReceivedEmail.get()
  3291. assert.Len(t, email.To, 2)
  3292. assert.True(t, util.Contains(email.To, "test1@example.com"))
  3293. assert.True(t, util.Contains(email.To, "test2@example.com"))
  3294. assert.Contains(t, email.Data, fmt.Sprintf(`Subject: New "download" from "%s"`, user.Username))
  3295. }
  3296. // test upload action command with arguments
  3297. action1.Options.CmdConfig.Args = []string{"{{Event}}", "{{VirtualPath}}", "custom_arg"}
  3298. action1, _, err = httpdtest.UpdateEventAction(action1, http.StatusOK)
  3299. assert.NoError(t, err)
  3300. uploadLogFilePath := filepath.Join(os.TempDir(), "upload.log")
  3301. err = os.WriteFile(uploadScriptPath, getUploadScriptContent(movedPath, uploadLogFilePath, 0), 0755)
  3302. assert.NoError(t, err)
  3303. conn, client, err = getSftpClient(user)
  3304. if assert.NoError(t, err) {
  3305. defer conn.Close()
  3306. defer client.Close()
  3307. err = writeSFTPFileNoCheck(path.Join(dirName, testFileName), 123, client)
  3308. assert.NoError(t, err)
  3309. logContent, err := os.ReadFile(uploadLogFilePath)
  3310. assert.NoError(t, err)
  3311. assert.Equal(t, fmt.Sprintf("upload %s custom_arg", util.CleanPath(path.Join(dirName, testFileName))),
  3312. strings.TrimSpace(string(logContent)))
  3313. err = os.Remove(uploadLogFilePath)
  3314. assert.NoError(t, err)
  3315. }
  3316. _, err = httpdtest.RemoveEventRule(rule1, http.StatusOK)
  3317. assert.NoError(t, err)
  3318. _, err = httpdtest.RemoveEventRule(rule2, http.StatusOK)
  3319. assert.NoError(t, err)
  3320. assert.Eventually(t, func() bool {
  3321. return lastReceivedEmail.get().From != ""
  3322. }, 3000*time.Millisecond, 100*time.Millisecond)
  3323. email := lastReceivedEmail.get()
  3324. assert.Len(t, email.To, 2)
  3325. assert.True(t, util.Contains(email.To, "test1@example.com"))
  3326. assert.True(t, util.Contains(email.To, "test2@example.com"))
  3327. assert.Contains(t, email.Data, `Subject: New "delete" from "admin"`)
  3328. _, err = httpdtest.RemoveEventRule(rule3, http.StatusOK)
  3329. assert.NoError(t, err)
  3330. _, err = httpdtest.RemoveEventAction(action1, http.StatusOK)
  3331. assert.NoError(t, err)
  3332. _, err = httpdtest.RemoveEventAction(action2, http.StatusOK)
  3333. assert.NoError(t, err)
  3334. _, err = httpdtest.RemoveEventAction(action3, http.StatusOK)
  3335. assert.NoError(t, err)
  3336. lastReceivedEmail.reset()
  3337. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  3338. assert.NoError(t, err)
  3339. err = os.RemoveAll(user.GetHomeDir())
  3340. assert.NoError(t, err)
  3341. smtpCfg = smtp.Config{}
  3342. err = smtpCfg.Initialize(configDir)
  3343. require.NoError(t, err)
  3344. }
  3345. func TestEventRuleProviderEvents(t *testing.T) {
  3346. if runtime.GOOS == osWindows {
  3347. t.Skip("this test is not available on Windows")
  3348. }
  3349. smtpCfg := smtp.Config{
  3350. Host: "127.0.0.1",
  3351. Port: 2525,
  3352. From: "notification@example.com",
  3353. TemplatesPath: "templates",
  3354. }
  3355. err := smtpCfg.Initialize(configDir)
  3356. require.NoError(t, err)
  3357. saveObjectScriptPath := filepath.Join(os.TempDir(), "provider.sh")
  3358. outPath := filepath.Join(os.TempDir(), "provider_out.json")
  3359. err = os.WriteFile(saveObjectScriptPath, getSaveProviderObjectScriptContent(outPath, 0), 0755)
  3360. assert.NoError(t, err)
  3361. a1 := dataprovider.BaseEventAction{
  3362. Name: "a1",
  3363. Type: dataprovider.ActionTypeCommand,
  3364. Options: dataprovider.BaseEventActionOptions{
  3365. CmdConfig: dataprovider.EventActionCommandConfig{
  3366. Cmd: saveObjectScriptPath,
  3367. Timeout: 10,
  3368. EnvVars: []dataprovider.KeyValue{
  3369. {
  3370. Key: "SFTPGO_OBJECT_DATA",
  3371. Value: "{{ObjectData}}",
  3372. },
  3373. },
  3374. },
  3375. },
  3376. }
  3377. a2 := dataprovider.BaseEventAction{
  3378. Name: "a2",
  3379. Type: dataprovider.ActionTypeEmail,
  3380. Options: dataprovider.BaseEventActionOptions{
  3381. EmailConfig: dataprovider.EventActionEmailConfig{
  3382. Recipients: []string{"test3@example.com"},
  3383. Subject: `New "{{Event}}" from "{{Name}}"`,
  3384. Body: "Object name: {{ObjectName}} object type: {{ObjectType}} Data: {{ObjectData}}",
  3385. },
  3386. },
  3387. }
  3388. a3 := dataprovider.BaseEventAction{
  3389. Name: "a3",
  3390. Type: dataprovider.ActionTypeEmail,
  3391. Options: dataprovider.BaseEventActionOptions{
  3392. EmailConfig: dataprovider.EventActionEmailConfig{
  3393. Recipients: []string{"failure@example.com"},
  3394. Subject: `Failed "{{Event}}" from "{{Name}}"`,
  3395. Body: "Object name: {{ObjectName}} object type: {{ObjectType}}, IP: {{IP}}",
  3396. },
  3397. },
  3398. }
  3399. action1, _, err := httpdtest.AddEventAction(a1, http.StatusCreated)
  3400. assert.NoError(t, err)
  3401. action2, _, err := httpdtest.AddEventAction(a2, http.StatusCreated)
  3402. assert.NoError(t, err)
  3403. action3, _, err := httpdtest.AddEventAction(a3, http.StatusCreated)
  3404. assert.NoError(t, err)
  3405. r := dataprovider.EventRule{
  3406. Name: "rule",
  3407. Trigger: dataprovider.EventTriggerProviderEvent,
  3408. Conditions: dataprovider.EventConditions{
  3409. ProviderEvents: []string{"update"},
  3410. },
  3411. Actions: []dataprovider.EventAction{
  3412. {
  3413. BaseEventAction: dataprovider.BaseEventAction{
  3414. Name: action1.Name,
  3415. },
  3416. Order: 1,
  3417. Options: dataprovider.EventActionOptions{
  3418. StopOnFailure: true,
  3419. },
  3420. },
  3421. {
  3422. BaseEventAction: dataprovider.BaseEventAction{
  3423. Name: action2.Name,
  3424. },
  3425. Order: 2,
  3426. },
  3427. {
  3428. BaseEventAction: dataprovider.BaseEventAction{
  3429. Name: action3.Name,
  3430. },
  3431. Order: 3,
  3432. Options: dataprovider.EventActionOptions{
  3433. IsFailureAction: true,
  3434. StopOnFailure: true,
  3435. },
  3436. },
  3437. },
  3438. }
  3439. rule, _, err := httpdtest.AddEventRule(r, http.StatusCreated)
  3440. assert.NoError(t, err)
  3441. lastReceivedEmail.reset()
  3442. // create and update a folder to trigger the rule
  3443. folder := vfs.BaseVirtualFolder{
  3444. Name: "ftest rule",
  3445. MappedPath: filepath.Join(os.TempDir(), "p"),
  3446. }
  3447. folder, _, err = httpdtest.AddFolder(folder, http.StatusCreated)
  3448. assert.NoError(t, err)
  3449. // no action is triggered on add
  3450. assert.NoFileExists(t, outPath)
  3451. // update the folder
  3452. _, _, err = httpdtest.UpdateFolder(folder, http.StatusOK)
  3453. assert.NoError(t, err)
  3454. if assert.Eventually(t, func() bool {
  3455. _, err := os.Stat(outPath)
  3456. return err == nil
  3457. }, 2*time.Second, 100*time.Millisecond) {
  3458. content, err := os.ReadFile(outPath)
  3459. assert.NoError(t, err)
  3460. var folderGet vfs.BaseVirtualFolder
  3461. err = json.Unmarshal(content, &folderGet)
  3462. assert.NoError(t, err)
  3463. assert.Equal(t, folder, folderGet)
  3464. err = os.Remove(outPath)
  3465. assert.NoError(t, err)
  3466. assert.Eventually(t, func() bool {
  3467. return lastReceivedEmail.get().From != ""
  3468. }, 3000*time.Millisecond, 100*time.Millisecond)
  3469. email := lastReceivedEmail.get()
  3470. assert.Len(t, email.To, 1)
  3471. assert.True(t, util.Contains(email.To, "test3@example.com"))
  3472. assert.Contains(t, email.Data, `Subject: New "update" from "admin"`)
  3473. }
  3474. // now delete the script to generate an error
  3475. lastReceivedEmail.reset()
  3476. err = os.Remove(saveObjectScriptPath)
  3477. assert.NoError(t, err)
  3478. _, _, err = httpdtest.UpdateFolder(folder, http.StatusOK)
  3479. assert.NoError(t, err)
  3480. assert.NoFileExists(t, outPath)
  3481. assert.Eventually(t, func() bool {
  3482. return lastReceivedEmail.get().From != ""
  3483. }, 3000*time.Millisecond, 100*time.Millisecond)
  3484. email := lastReceivedEmail.get()
  3485. assert.Len(t, email.To, 1)
  3486. assert.True(t, util.Contains(email.To, "failure@example.com"))
  3487. assert.Contains(t, email.Data, `Subject: Failed "update" from "admin"`)
  3488. assert.Contains(t, email.Data, fmt.Sprintf("Object name: %s object type: folder", folder.Name))
  3489. lastReceivedEmail.reset()
  3490. // generate an error for the failure action
  3491. smtpCfg = smtp.Config{}
  3492. err = smtpCfg.Initialize(configDir)
  3493. require.NoError(t, err)
  3494. _, _, err = httpdtest.UpdateFolder(folder, http.StatusOK)
  3495. assert.NoError(t, err)
  3496. assert.NoFileExists(t, outPath)
  3497. email = lastReceivedEmail.get()
  3498. assert.Len(t, email.To, 0)
  3499. _, err = httpdtest.RemoveFolder(folder, http.StatusOK)
  3500. assert.NoError(t, err)
  3501. _, err = httpdtest.RemoveEventRule(rule, http.StatusOK)
  3502. assert.NoError(t, err)
  3503. _, err = httpdtest.RemoveEventAction(action1, http.StatusOK)
  3504. assert.NoError(t, err)
  3505. _, err = httpdtest.RemoveEventAction(action2, http.StatusOK)
  3506. assert.NoError(t, err)
  3507. _, err = httpdtest.RemoveEventAction(action3, http.StatusOK)
  3508. assert.NoError(t, err)
  3509. }
  3510. func TestEventRuleFsActions(t *testing.T) {
  3511. dirsToCreate := []string{
  3512. "/basedir/1",
  3513. "/basedir/sub/2",
  3514. "/basedir/3",
  3515. }
  3516. a1 := dataprovider.BaseEventAction{
  3517. Name: "a1",
  3518. Type: dataprovider.ActionTypeFilesystem,
  3519. Options: dataprovider.BaseEventActionOptions{
  3520. FsConfig: dataprovider.EventActionFilesystemConfig{
  3521. Type: dataprovider.FilesystemActionMkdirs,
  3522. MkDirs: dirsToCreate,
  3523. },
  3524. },
  3525. }
  3526. a2 := dataprovider.BaseEventAction{
  3527. Name: "a2",
  3528. Type: dataprovider.ActionTypeFilesystem,
  3529. Options: dataprovider.BaseEventActionOptions{
  3530. FsConfig: dataprovider.EventActionFilesystemConfig{
  3531. Type: dataprovider.FilesystemActionRename,
  3532. Renames: []dataprovider.KeyValue{
  3533. {
  3534. Key: "/{{VirtualPath}}",
  3535. Value: "/{{ObjectName}}_renamed",
  3536. },
  3537. },
  3538. },
  3539. },
  3540. }
  3541. a3 := dataprovider.BaseEventAction{
  3542. Name: "a3",
  3543. Type: dataprovider.ActionTypeFilesystem,
  3544. Options: dataprovider.BaseEventActionOptions{
  3545. FsConfig: dataprovider.EventActionFilesystemConfig{
  3546. Type: dataprovider.FilesystemActionDelete,
  3547. Deletes: []string{"/{{ObjectName}}_renamed"},
  3548. },
  3549. },
  3550. }
  3551. a4 := dataprovider.BaseEventAction{
  3552. Name: "a4",
  3553. Type: dataprovider.ActionTypeFolderQuotaReset,
  3554. }
  3555. a5 := dataprovider.BaseEventAction{
  3556. Name: "a5",
  3557. Type: dataprovider.ActionTypeUserQuotaReset,
  3558. }
  3559. a6 := dataprovider.BaseEventAction{
  3560. Name: "a6",
  3561. Type: dataprovider.ActionTypeFilesystem,
  3562. Options: dataprovider.BaseEventActionOptions{
  3563. FsConfig: dataprovider.EventActionFilesystemConfig{
  3564. Type: dataprovider.FilesystemActionExist,
  3565. Exist: []string{"/{{VirtualPath}}"},
  3566. },
  3567. },
  3568. }
  3569. action1, resp, err := httpdtest.AddEventAction(a1, http.StatusCreated)
  3570. assert.NoError(t, err, string(resp))
  3571. action2, resp, err := httpdtest.AddEventAction(a2, http.StatusCreated)
  3572. assert.NoError(t, err, string(resp))
  3573. action3, resp, err := httpdtest.AddEventAction(a3, http.StatusCreated)
  3574. assert.NoError(t, err, string(resp))
  3575. action4, resp, err := httpdtest.AddEventAction(a4, http.StatusCreated)
  3576. assert.NoError(t, err, string(resp))
  3577. action5, resp, err := httpdtest.AddEventAction(a5, http.StatusCreated)
  3578. assert.NoError(t, err, string(resp))
  3579. action6, resp, err := httpdtest.AddEventAction(a6, http.StatusCreated)
  3580. assert.NoError(t, err, string(resp))
  3581. r1 := dataprovider.EventRule{
  3582. Name: "r1",
  3583. Trigger: dataprovider.EventTriggerProviderEvent,
  3584. Conditions: dataprovider.EventConditions{
  3585. ProviderEvents: []string{"add"},
  3586. },
  3587. Actions: []dataprovider.EventAction{
  3588. {
  3589. BaseEventAction: dataprovider.BaseEventAction{
  3590. Name: action1.Name,
  3591. },
  3592. Order: 1,
  3593. },
  3594. },
  3595. }
  3596. r2 := dataprovider.EventRule{
  3597. Name: "r2",
  3598. Trigger: dataprovider.EventTriggerFsEvent,
  3599. Conditions: dataprovider.EventConditions{
  3600. FsEvents: []string{"upload"},
  3601. },
  3602. Actions: []dataprovider.EventAction{
  3603. {
  3604. BaseEventAction: dataprovider.BaseEventAction{
  3605. Name: action2.Name,
  3606. },
  3607. Order: 1,
  3608. Options: dataprovider.EventActionOptions{
  3609. ExecuteSync: true,
  3610. },
  3611. },
  3612. {
  3613. BaseEventAction: dataprovider.BaseEventAction{
  3614. Name: action5.Name,
  3615. },
  3616. Order: 2,
  3617. },
  3618. },
  3619. }
  3620. r3 := dataprovider.EventRule{
  3621. Name: "r3",
  3622. Trigger: dataprovider.EventTriggerFsEvent,
  3623. Conditions: dataprovider.EventConditions{
  3624. FsEvents: []string{"mkdir"},
  3625. },
  3626. Actions: []dataprovider.EventAction{
  3627. {
  3628. BaseEventAction: dataprovider.BaseEventAction{
  3629. Name: action3.Name,
  3630. },
  3631. Order: 1,
  3632. },
  3633. {
  3634. BaseEventAction: dataprovider.BaseEventAction{
  3635. Name: action6.Name,
  3636. },
  3637. Order: 2,
  3638. },
  3639. },
  3640. }
  3641. r4 := dataprovider.EventRule{
  3642. Name: "r4",
  3643. Trigger: dataprovider.EventTriggerFsEvent,
  3644. Conditions: dataprovider.EventConditions{
  3645. FsEvents: []string{"rmdir"},
  3646. },
  3647. Actions: []dataprovider.EventAction{
  3648. {
  3649. BaseEventAction: dataprovider.BaseEventAction{
  3650. Name: action4.Name,
  3651. },
  3652. Order: 1,
  3653. },
  3654. },
  3655. }
  3656. r5 := dataprovider.EventRule{
  3657. Name: "r5",
  3658. Trigger: dataprovider.EventTriggerProviderEvent,
  3659. Conditions: dataprovider.EventConditions{
  3660. ProviderEvents: []string{"add"},
  3661. },
  3662. Actions: []dataprovider.EventAction{
  3663. {
  3664. BaseEventAction: dataprovider.BaseEventAction{
  3665. Name: action4.Name,
  3666. },
  3667. Order: 1,
  3668. },
  3669. },
  3670. }
  3671. rule1, _, err := httpdtest.AddEventRule(r1, http.StatusCreated)
  3672. assert.NoError(t, err)
  3673. rule2, _, err := httpdtest.AddEventRule(r2, http.StatusCreated)
  3674. assert.NoError(t, err)
  3675. rule3, _, err := httpdtest.AddEventRule(r3, http.StatusCreated)
  3676. assert.NoError(t, err)
  3677. rule4, _, err := httpdtest.AddEventRule(r4, http.StatusCreated)
  3678. assert.NoError(t, err)
  3679. rule5, _, err := httpdtest.AddEventRule(r5, http.StatusCreated)
  3680. assert.NoError(t, err)
  3681. folderMappedPath := filepath.Join(os.TempDir(), "folder")
  3682. err = os.MkdirAll(folderMappedPath, os.ModePerm)
  3683. assert.NoError(t, err)
  3684. err = os.WriteFile(filepath.Join(folderMappedPath, "file.txt"), []byte("1"), 0666)
  3685. assert.NoError(t, err)
  3686. folder, _, err := httpdtest.AddFolder(vfs.BaseVirtualFolder{
  3687. Name: "test folder",
  3688. MappedPath: folderMappedPath,
  3689. }, http.StatusCreated)
  3690. assert.NoError(t, err)
  3691. assert.Eventually(t, func() bool {
  3692. folderGet, _, err := httpdtest.GetFolderByName(folder.Name, http.StatusOK)
  3693. if err != nil {
  3694. return false
  3695. }
  3696. return folderGet.UsedQuotaFiles == 1 && folderGet.UsedQuotaSize == 1
  3697. }, 2*time.Second, 100*time.Millisecond)
  3698. u := getTestUser()
  3699. u.Filters.DisableFsChecks = true
  3700. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  3701. assert.NoError(t, err)
  3702. conn, client, err := getSftpClient(user)
  3703. if assert.NoError(t, err) {
  3704. defer conn.Close()
  3705. defer client.Close()
  3706. // check initial directories creation
  3707. for _, dir := range dirsToCreate {
  3708. assert.Eventually(t, func() bool {
  3709. _, err := client.Stat(dir)
  3710. return err == nil
  3711. }, 2*time.Second, 100*time.Millisecond)
  3712. }
  3713. // upload a file and check the sync rename
  3714. size := int64(32768)
  3715. err = writeSFTPFileNoCheck(path.Join("basedir", testFileName), size, client)
  3716. assert.NoError(t, err)
  3717. _, err = client.Stat(path.Join("basedir", testFileName))
  3718. assert.Error(t, err)
  3719. info, err := client.Stat(testFileName + "_renamed")
  3720. if assert.NoError(t, err) {
  3721. assert.Equal(t, size, info.Size())
  3722. }
  3723. assert.NoError(t, err)
  3724. assert.Eventually(t, func() bool {
  3725. userGet, _, err := httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  3726. if err != nil {
  3727. return false
  3728. }
  3729. return userGet.UsedQuotaFiles == 1 && userGet.UsedQuotaSize == size
  3730. }, 2*time.Second, 100*time.Millisecond)
  3731. for i := 0; i < 2; i++ {
  3732. err = client.Mkdir(testFileName)
  3733. assert.NoError(t, err)
  3734. assert.Eventually(t, func() bool {
  3735. _, err = client.Stat(testFileName + "_renamed")
  3736. return err != nil
  3737. }, 2*time.Second, 100*time.Millisecond)
  3738. err = client.RemoveDirectory(testFileName)
  3739. assert.NoError(t, err)
  3740. }
  3741. err = client.Mkdir(testFileName + "_renamed")
  3742. assert.NoError(t, err)
  3743. err = client.Mkdir(testFileName)
  3744. assert.NoError(t, err)
  3745. assert.Eventually(t, func() bool {
  3746. _, err = client.Stat(testFileName + "_renamed")
  3747. return err != nil
  3748. }, 2*time.Second, 100*time.Millisecond)
  3749. }
  3750. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  3751. assert.NoError(t, err)
  3752. err = os.RemoveAll(user.GetHomeDir())
  3753. assert.NoError(t, err)
  3754. _, err = httpdtest.RemoveFolder(folder, http.StatusOK)
  3755. assert.NoError(t, err)
  3756. err = os.RemoveAll(folderMappedPath)
  3757. assert.NoError(t, err)
  3758. _, err = httpdtest.RemoveEventRule(rule1, http.StatusOK)
  3759. assert.NoError(t, err)
  3760. _, err = httpdtest.RemoveEventRule(rule2, http.StatusOK)
  3761. assert.NoError(t, err)
  3762. _, err = httpdtest.RemoveEventRule(rule3, http.StatusOK)
  3763. assert.NoError(t, err)
  3764. _, err = httpdtest.RemoveEventRule(rule4, http.StatusOK)
  3765. assert.NoError(t, err)
  3766. _, err = httpdtest.RemoveEventRule(rule5, http.StatusOK)
  3767. assert.NoError(t, err)
  3768. _, err = httpdtest.RemoveEventAction(action1, http.StatusOK)
  3769. assert.NoError(t, err)
  3770. _, err = httpdtest.RemoveEventAction(action2, http.StatusOK)
  3771. assert.NoError(t, err)
  3772. _, err = httpdtest.RemoveEventAction(action3, http.StatusOK)
  3773. assert.NoError(t, err)
  3774. _, err = httpdtest.RemoveEventAction(action4, http.StatusOK)
  3775. assert.NoError(t, err)
  3776. _, err = httpdtest.RemoveEventAction(action5, http.StatusOK)
  3777. assert.NoError(t, err)
  3778. _, err = httpdtest.RemoveEventAction(action6, http.StatusOK)
  3779. assert.NoError(t, err)
  3780. }
  3781. func TestEventFsActionsGroupFilters(t *testing.T) {
  3782. smtpCfg := smtp.Config{
  3783. Host: "127.0.0.1",
  3784. Port: 2525,
  3785. From: "notification@example.com",
  3786. TemplatesPath: "templates",
  3787. }
  3788. err := smtpCfg.Initialize(configDir)
  3789. require.NoError(t, err)
  3790. a1 := dataprovider.BaseEventAction{
  3791. Name: "a1",
  3792. Type: dataprovider.ActionTypeEmail,
  3793. Options: dataprovider.BaseEventActionOptions{
  3794. EmailConfig: dataprovider.EventActionEmailConfig{
  3795. Recipients: []string{"example@example.net"},
  3796. Subject: `New "{{Event}}" from "{{Name}}" status {{StatusString}}`,
  3797. Body: "Fs path {{FsPath}}, size: {{FileSize}}, protocol: {{Protocol}}, IP: {{IP}} {{ErrorString}}",
  3798. },
  3799. },
  3800. }
  3801. action1, _, err := httpdtest.AddEventAction(a1, http.StatusCreated)
  3802. assert.NoError(t, err)
  3803. r1 := dataprovider.EventRule{
  3804. Name: "rule1",
  3805. Trigger: dataprovider.EventTriggerFsEvent,
  3806. Conditions: dataprovider.EventConditions{
  3807. FsEvents: []string{"upload"},
  3808. Options: dataprovider.ConditionOptions{
  3809. GroupNames: []dataprovider.ConditionPattern{
  3810. {
  3811. Pattern: "group*",
  3812. },
  3813. },
  3814. },
  3815. },
  3816. Actions: []dataprovider.EventAction{
  3817. {
  3818. BaseEventAction: dataprovider.BaseEventAction{
  3819. Name: action1.Name,
  3820. },
  3821. Order: 1,
  3822. Options: dataprovider.EventActionOptions{
  3823. ExecuteSync: true,
  3824. },
  3825. },
  3826. },
  3827. }
  3828. rule1, _, err := httpdtest.AddEventRule(r1, http.StatusCreated)
  3829. assert.NoError(t, err)
  3830. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  3831. assert.NoError(t, err)
  3832. conn, client, err := getSftpClient(user)
  3833. if assert.NoError(t, err) {
  3834. defer conn.Close()
  3835. defer client.Close()
  3836. // the user has no group, so the rule does not match
  3837. lastReceivedEmail.reset()
  3838. err = writeSFTPFile(testFileName, 32, client)
  3839. assert.NoError(t, err)
  3840. assert.Empty(t, lastReceivedEmail.get().From)
  3841. }
  3842. g1 := dataprovider.Group{
  3843. BaseGroup: sdk.BaseGroup{
  3844. Name: "agroup1",
  3845. },
  3846. }
  3847. group1, _, err := httpdtest.AddGroup(g1, http.StatusCreated)
  3848. assert.NoError(t, err)
  3849. g2 := dataprovider.Group{
  3850. BaseGroup: sdk.BaseGroup{
  3851. Name: "group2",
  3852. },
  3853. }
  3854. group2, _, err := httpdtest.AddGroup(g2, http.StatusCreated)
  3855. assert.NoError(t, err)
  3856. user.Groups = []sdk.GroupMapping{
  3857. {
  3858. Name: group1.Name,
  3859. Type: sdk.GroupTypePrimary,
  3860. },
  3861. }
  3862. _, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  3863. assert.NoError(t, err)
  3864. conn, client, err = getSftpClient(user)
  3865. if assert.NoError(t, err) {
  3866. defer conn.Close()
  3867. defer client.Close()
  3868. // the group does not match
  3869. lastReceivedEmail.reset()
  3870. err = writeSFTPFile(testFileName, 32, client)
  3871. assert.NoError(t, err)
  3872. assert.Empty(t, lastReceivedEmail.get().From)
  3873. }
  3874. user.Groups = append(user.Groups, sdk.GroupMapping{
  3875. Name: group2.Name,
  3876. Type: sdk.GroupTypeSecondary,
  3877. })
  3878. _, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  3879. assert.NoError(t, err)
  3880. conn, client, err = getSftpClient(user)
  3881. if assert.NoError(t, err) {
  3882. defer conn.Close()
  3883. defer client.Close()
  3884. // the group matches
  3885. lastReceivedEmail.reset()
  3886. err = writeSFTPFile(testFileName, 32, client)
  3887. assert.NoError(t, err)
  3888. assert.NotEmpty(t, lastReceivedEmail.get().From)
  3889. }
  3890. _, err = httpdtest.RemoveEventRule(rule1, http.StatusOK)
  3891. assert.NoError(t, err)
  3892. _, err = httpdtest.RemoveEventAction(action1, http.StatusOK)
  3893. assert.NoError(t, err)
  3894. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  3895. assert.NoError(t, err)
  3896. err = os.RemoveAll(user.GetHomeDir())
  3897. assert.NoError(t, err)
  3898. _, err = httpdtest.RemoveGroup(group1, http.StatusOK)
  3899. assert.NoError(t, err)
  3900. _, err = httpdtest.RemoveGroup(group2, http.StatusOK)
  3901. assert.NoError(t, err)
  3902. smtpCfg = smtp.Config{}
  3903. err = smtpCfg.Initialize(configDir)
  3904. require.NoError(t, err)
  3905. }
  3906. func TestEventActionHTTPMultipart(t *testing.T) {
  3907. a1 := dataprovider.BaseEventAction{
  3908. Name: "action1",
  3909. Type: dataprovider.ActionTypeHTTP,
  3910. Options: dataprovider.BaseEventActionOptions{
  3911. HTTPConfig: dataprovider.EventActionHTTPConfig{
  3912. Endpoint: fmt.Sprintf("http://%s/multipart", httpAddr),
  3913. Method: http.MethodPut,
  3914. Parts: []dataprovider.HTTPPart{
  3915. {
  3916. Name: "part1",
  3917. Headers: []dataprovider.KeyValue{
  3918. {
  3919. Key: "Content-Type",
  3920. Value: "application/json",
  3921. },
  3922. },
  3923. Body: `{"FilePath": "{{VirtualPath}}"}`,
  3924. },
  3925. {
  3926. Name: "file",
  3927. Filepath: "/{{VirtualPath}}",
  3928. },
  3929. },
  3930. },
  3931. },
  3932. }
  3933. action1, resp, err := httpdtest.AddEventAction(a1, http.StatusCreated)
  3934. assert.NoError(t, err, string(resp))
  3935. r1 := dataprovider.EventRule{
  3936. Name: "test http multipart",
  3937. Trigger: dataprovider.EventTriggerFsEvent,
  3938. Conditions: dataprovider.EventConditions{
  3939. FsEvents: []string{"upload"},
  3940. },
  3941. Actions: []dataprovider.EventAction{
  3942. {
  3943. BaseEventAction: dataprovider.BaseEventAction{
  3944. Name: action1.Name,
  3945. },
  3946. Options: dataprovider.EventActionOptions{
  3947. ExecuteSync: true,
  3948. },
  3949. Order: 1,
  3950. },
  3951. },
  3952. }
  3953. rule1, _, err := httpdtest.AddEventRule(r1, http.StatusCreated)
  3954. assert.NoError(t, err)
  3955. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  3956. assert.NoError(t, err)
  3957. conn, client, err := getSftpClient(user)
  3958. if assert.NoError(t, err) {
  3959. defer conn.Close()
  3960. defer client.Close()
  3961. f, err := client.Create(testFileName)
  3962. assert.NoError(t, err)
  3963. _, err = f.Write(testFileContent)
  3964. assert.NoError(t, err)
  3965. err = f.Close()
  3966. assert.NoError(t, err)
  3967. // now add an missing file to the http multipart action
  3968. action1.Options.HTTPConfig.Parts = append(action1.Options.HTTPConfig.Parts, dataprovider.HTTPPart{
  3969. Name: "file1",
  3970. Filepath: "/missing",
  3971. })
  3972. _, resp, err = httpdtest.UpdateEventAction(action1, http.StatusOK)
  3973. assert.NoError(t, err, string(resp))
  3974. f, err = client.Create("testfile.txt")
  3975. assert.NoError(t, err)
  3976. _, err = f.Write(testFileContent)
  3977. assert.NoError(t, err)
  3978. err = f.Close()
  3979. assert.Error(t, err)
  3980. }
  3981. _, err = httpdtest.RemoveEventRule(rule1, http.StatusOK)
  3982. assert.NoError(t, err)
  3983. _, err = httpdtest.RemoveEventAction(action1, http.StatusOK)
  3984. assert.NoError(t, err)
  3985. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  3986. assert.NoError(t, err)
  3987. err = os.RemoveAll(user.GetHomeDir())
  3988. assert.NoError(t, err)
  3989. }
  3990. func TestEventActionCompress(t *testing.T) {
  3991. a1 := dataprovider.BaseEventAction{
  3992. Name: "action1",
  3993. Type: dataprovider.ActionTypeFilesystem,
  3994. Options: dataprovider.BaseEventActionOptions{
  3995. FsConfig: dataprovider.EventActionFilesystemConfig{
  3996. Type: dataprovider.FilesystemActionCompress,
  3997. Compress: dataprovider.EventActionFsCompress{
  3998. Name: "/{{VirtualPath}}.zip",
  3999. Paths: []string{"/{{VirtualPath}}"},
  4000. },
  4001. },
  4002. },
  4003. }
  4004. action1, _, err := httpdtest.AddEventAction(a1, http.StatusCreated)
  4005. assert.NoError(t, err)
  4006. r1 := dataprovider.EventRule{
  4007. Name: "test compress",
  4008. Trigger: dataprovider.EventTriggerFsEvent,
  4009. Conditions: dataprovider.EventConditions{
  4010. FsEvents: []string{"upload"},
  4011. },
  4012. Actions: []dataprovider.EventAction{
  4013. {
  4014. BaseEventAction: dataprovider.BaseEventAction{
  4015. Name: action1.Name,
  4016. },
  4017. Order: 1,
  4018. Options: dataprovider.EventActionOptions{
  4019. ExecuteSync: true,
  4020. },
  4021. },
  4022. },
  4023. }
  4024. rule1, _, err := httpdtest.AddEventRule(r1, http.StatusCreated)
  4025. assert.NoError(t, err)
  4026. u := getTestUser()
  4027. u.QuotaFiles = 1000
  4028. localUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  4029. assert.NoError(t, err)
  4030. u = getTestSFTPUser()
  4031. u.FsConfig.SFTPConfig.BufferSize = 1
  4032. u.QuotaFiles = 1000
  4033. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  4034. assert.NoError(t, err)
  4035. u = getCryptFsUser()
  4036. u.QuotaFiles = 1000
  4037. cryptFsUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  4038. assert.NoError(t, err)
  4039. for _, user := range []dataprovider.User{localUser, sftpUser, cryptFsUser} {
  4040. // cleanup home dir
  4041. err = os.RemoveAll(user.GetHomeDir())
  4042. assert.NoError(t, err)
  4043. rule1.Conditions.Options.Names = []dataprovider.ConditionPattern{
  4044. {
  4045. Pattern: user.Username,
  4046. },
  4047. }
  4048. _, _, err = httpdtest.UpdateEventRule(rule1, http.StatusOK)
  4049. assert.NoError(t, err)
  4050. conn, client, err := getSftpClient(user)
  4051. if assert.NoError(t, err) {
  4052. defer conn.Close()
  4053. defer client.Close()
  4054. expectedQuotaSize := int64(len(testFileContent))
  4055. expectedQuotaFiles := 1
  4056. if user.Username == cryptFsUser.Username {
  4057. encryptedFileSize, err := getEncryptedFileSize(expectedQuotaSize)
  4058. assert.NoError(t, err)
  4059. expectedQuotaSize = encryptedFileSize
  4060. }
  4061. f, err := client.Create(testFileName)
  4062. assert.NoError(t, err)
  4063. _, err = f.Write(testFileContent)
  4064. assert.NoError(t, err)
  4065. err = f.Close()
  4066. assert.NoError(t, err)
  4067. info, err := client.Stat(testFileName + ".zip")
  4068. if assert.NoError(t, err) {
  4069. assert.Greater(t, info.Size(), int64(0))
  4070. // check quota
  4071. archiveSize := info.Size()
  4072. if user.Username == cryptFsUser.Username {
  4073. encryptedFileSize, err := getEncryptedFileSize(archiveSize)
  4074. assert.NoError(t, err)
  4075. archiveSize = encryptedFileSize
  4076. }
  4077. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  4078. assert.NoError(t, err)
  4079. assert.Equal(t, expectedQuotaFiles+1, user.UsedQuotaFiles,
  4080. "quota file does no match for user %q", user.Username)
  4081. assert.Equal(t, expectedQuotaSize+archiveSize, user.UsedQuotaSize,
  4082. "quota size does no match for user %q", user.Username)
  4083. }
  4084. // now overwrite the same file
  4085. f, err = client.Create(testFileName)
  4086. assert.NoError(t, err)
  4087. _, err = f.Write(testFileContent)
  4088. assert.NoError(t, err)
  4089. err = f.Close()
  4090. assert.NoError(t, err)
  4091. info, err = client.Stat(testFileName + ".zip")
  4092. if assert.NoError(t, err) {
  4093. assert.Greater(t, info.Size(), int64(0))
  4094. archiveSize := info.Size()
  4095. if user.Username == cryptFsUser.Username {
  4096. encryptedFileSize, err := getEncryptedFileSize(archiveSize)
  4097. assert.NoError(t, err)
  4098. archiveSize = encryptedFileSize
  4099. }
  4100. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  4101. assert.NoError(t, err)
  4102. assert.Equal(t, expectedQuotaFiles+1, user.UsedQuotaFiles,
  4103. "quota file after overwrite does no match for user %q", user.Username)
  4104. assert.Equal(t, expectedQuotaSize+archiveSize, user.UsedQuotaSize,
  4105. "quota size after overwrite does no match for user %q", user.Username)
  4106. }
  4107. }
  4108. if user.Username == localUser.Username {
  4109. err = os.RemoveAll(user.GetHomeDir())
  4110. assert.NoError(t, err)
  4111. }
  4112. }
  4113. _, err = httpdtest.RemoveEventRule(rule1, http.StatusOK)
  4114. assert.NoError(t, err)
  4115. _, err = httpdtest.RemoveEventAction(action1, http.StatusOK)
  4116. assert.NoError(t, err)
  4117. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  4118. assert.NoError(t, err)
  4119. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  4120. assert.NoError(t, err)
  4121. err = os.RemoveAll(localUser.GetHomeDir())
  4122. assert.NoError(t, err)
  4123. _, err = httpdtest.RemoveUser(cryptFsUser, http.StatusOK)
  4124. assert.NoError(t, err)
  4125. err = os.RemoveAll(cryptFsUser.GetHomeDir())
  4126. assert.NoError(t, err)
  4127. }
  4128. func TestEventActionCompressQuotaFolder(t *testing.T) {
  4129. testDir := "/folder"
  4130. a1 := dataprovider.BaseEventAction{
  4131. Name: "action1",
  4132. Type: dataprovider.ActionTypeFilesystem,
  4133. Options: dataprovider.BaseEventActionOptions{
  4134. FsConfig: dataprovider.EventActionFilesystemConfig{
  4135. Type: dataprovider.FilesystemActionCompress,
  4136. Compress: dataprovider.EventActionFsCompress{
  4137. Name: "/{{VirtualPath}}.zip",
  4138. Paths: []string{"/{{VirtualPath}}", testDir},
  4139. },
  4140. },
  4141. },
  4142. }
  4143. action1, _, err := httpdtest.AddEventAction(a1, http.StatusCreated)
  4144. assert.NoError(t, err)
  4145. r1 := dataprovider.EventRule{
  4146. Name: "test compress",
  4147. Trigger: dataprovider.EventTriggerFsEvent,
  4148. Conditions: dataprovider.EventConditions{
  4149. FsEvents: []string{"upload"},
  4150. },
  4151. Actions: []dataprovider.EventAction{
  4152. {
  4153. BaseEventAction: dataprovider.BaseEventAction{
  4154. Name: action1.Name,
  4155. },
  4156. Order: 1,
  4157. Options: dataprovider.EventActionOptions{
  4158. ExecuteSync: true,
  4159. },
  4160. },
  4161. },
  4162. }
  4163. rule1, _, err := httpdtest.AddEventRule(r1, http.StatusCreated)
  4164. assert.NoError(t, err)
  4165. u := getTestUser()
  4166. u.QuotaFiles = 1000
  4167. mappedPath := filepath.Join(os.TempDir(), "virtualpath")
  4168. folderName := filepath.Base(mappedPath)
  4169. vdirPath := "/virtualpath"
  4170. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  4171. BaseVirtualFolder: vfs.BaseVirtualFolder{
  4172. Name: folderName,
  4173. MappedPath: mappedPath,
  4174. },
  4175. VirtualPath: vdirPath,
  4176. QuotaSize: -1,
  4177. QuotaFiles: -1,
  4178. })
  4179. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  4180. assert.NoError(t, err)
  4181. conn, client, err := getSftpClient(user)
  4182. if assert.NoError(t, err) {
  4183. defer conn.Close()
  4184. defer client.Close()
  4185. err = client.Mkdir(testDir)
  4186. assert.NoError(t, err)
  4187. expectedQuotaSize := int64(len(testFileContent))
  4188. expectedQuotaFiles := 1
  4189. err = client.Symlink(path.Join(testDir, testFileName), path.Join(testDir, testFileName+"_link"))
  4190. assert.NoError(t, err)
  4191. f, err := client.Create(path.Join(testDir, testFileName))
  4192. assert.NoError(t, err)
  4193. _, err = f.Write(testFileContent)
  4194. assert.NoError(t, err)
  4195. err = f.Close()
  4196. assert.NoError(t, err)
  4197. info, err := client.Stat(path.Join(testDir, testFileName) + ".zip")
  4198. if assert.NoError(t, err) {
  4199. assert.Greater(t, info.Size(), int64(0))
  4200. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  4201. assert.NoError(t, err)
  4202. expectedQuotaFiles++
  4203. expectedQuotaSize += info.Size()
  4204. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  4205. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  4206. }
  4207. vfolder, _, err := httpdtest.GetFolderByName(folderName, http.StatusOK)
  4208. assert.NoError(t, err)
  4209. assert.Equal(t, 0, vfolder.UsedQuotaFiles)
  4210. assert.Equal(t, int64(0), vfolder.UsedQuotaSize)
  4211. // upload in the virtual path
  4212. f, err = client.Create(path.Join(vdirPath, testFileName))
  4213. assert.NoError(t, err)
  4214. _, err = f.Write(testFileContent)
  4215. assert.NoError(t, err)
  4216. err = f.Close()
  4217. assert.NoError(t, err)
  4218. info, err = client.Stat(path.Join(vdirPath, testFileName) + ".zip")
  4219. if assert.NoError(t, err) {
  4220. assert.Greater(t, info.Size(), int64(0))
  4221. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  4222. assert.NoError(t, err)
  4223. expectedQuotaFiles += 2
  4224. expectedQuotaSize += info.Size() + int64(len(testFileContent))
  4225. assert.Equal(t, expectedQuotaFiles, user.UsedQuotaFiles)
  4226. assert.Equal(t, expectedQuotaSize, user.UsedQuotaSize)
  4227. vfolder, _, err := httpdtest.GetFolderByName(folderName, http.StatusOK)
  4228. assert.NoError(t, err)
  4229. assert.Equal(t, 2, vfolder.UsedQuotaFiles)
  4230. assert.Equal(t, info.Size()+int64(len(testFileContent)), vfolder.UsedQuotaSize)
  4231. }
  4232. }
  4233. _, err = httpdtest.RemoveEventRule(rule1, http.StatusOK)
  4234. assert.NoError(t, err)
  4235. _, err = httpdtest.RemoveEventAction(action1, http.StatusOK)
  4236. assert.NoError(t, err)
  4237. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  4238. assert.NoError(t, err)
  4239. err = os.RemoveAll(user.GetHomeDir())
  4240. assert.NoError(t, err)
  4241. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName}, http.StatusOK)
  4242. assert.NoError(t, err)
  4243. err = os.RemoveAll(mappedPath)
  4244. assert.NoError(t, err)
  4245. }
  4246. func TestEventActionCompressErrors(t *testing.T) {
  4247. a1 := dataprovider.BaseEventAction{
  4248. Name: "action1",
  4249. Type: dataprovider.ActionTypeFilesystem,
  4250. Options: dataprovider.BaseEventActionOptions{
  4251. FsConfig: dataprovider.EventActionFilesystemConfig{
  4252. Type: dataprovider.FilesystemActionCompress,
  4253. Compress: dataprovider.EventActionFsCompress{
  4254. Name: "/{{VirtualPath}}.zip",
  4255. Paths: []string{"/{{VirtualPath}}.zip"}, // cannot compress itself
  4256. },
  4257. },
  4258. },
  4259. }
  4260. action1, _, err := httpdtest.AddEventAction(a1, http.StatusCreated)
  4261. assert.NoError(t, err)
  4262. r1 := dataprovider.EventRule{
  4263. Name: "test compress",
  4264. Trigger: dataprovider.EventTriggerFsEvent,
  4265. Conditions: dataprovider.EventConditions{
  4266. FsEvents: []string{"upload"},
  4267. },
  4268. Actions: []dataprovider.EventAction{
  4269. {
  4270. BaseEventAction: dataprovider.BaseEventAction{
  4271. Name: action1.Name,
  4272. },
  4273. Order: 1,
  4274. Options: dataprovider.EventActionOptions{
  4275. ExecuteSync: true,
  4276. },
  4277. },
  4278. },
  4279. }
  4280. rule1, _, err := httpdtest.AddEventRule(r1, http.StatusCreated)
  4281. assert.NoError(t, err)
  4282. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  4283. assert.NoError(t, err)
  4284. conn, client, err := getSftpClient(user)
  4285. if assert.NoError(t, err) {
  4286. defer conn.Close()
  4287. defer client.Close()
  4288. f, err := client.Create(testFileName)
  4289. assert.NoError(t, err)
  4290. _, err = f.Write(testFileContent)
  4291. assert.NoError(t, err)
  4292. err = f.Close()
  4293. assert.Error(t, err)
  4294. }
  4295. // try to compress a missing file
  4296. action1.Options.FsConfig.Compress.Paths = []string{"/missing file"}
  4297. _, _, err = httpdtest.UpdateEventAction(action1, http.StatusOK)
  4298. assert.NoError(t, err)
  4299. conn, client, err = getSftpClient(user)
  4300. if assert.NoError(t, err) {
  4301. defer conn.Close()
  4302. defer client.Close()
  4303. f, err := client.Create(testFileName)
  4304. assert.NoError(t, err)
  4305. _, err = f.Write(testFileContent)
  4306. assert.NoError(t, err)
  4307. err = f.Close()
  4308. assert.Error(t, err)
  4309. }
  4310. // try to overwrite a directory
  4311. testDir := "/adir"
  4312. action1.Options.FsConfig.Compress.Name = testDir
  4313. action1.Options.FsConfig.Compress.Paths = []string{"/{{VirtualPath}}"}
  4314. _, _, err = httpdtest.UpdateEventAction(action1, http.StatusOK)
  4315. assert.NoError(t, err)
  4316. conn, client, err = getSftpClient(user)
  4317. if assert.NoError(t, err) {
  4318. defer conn.Close()
  4319. defer client.Close()
  4320. err = client.Mkdir(testDir)
  4321. assert.NoError(t, err)
  4322. f, err := client.Create(testFileName)
  4323. assert.NoError(t, err)
  4324. _, err = f.Write(testFileContent)
  4325. assert.NoError(t, err)
  4326. err = f.Close()
  4327. assert.Error(t, err)
  4328. }
  4329. // try to write to a missing directory
  4330. action1.Options.FsConfig.Compress.Name = "/subdir/missing/path/file.zip"
  4331. _, _, err = httpdtest.UpdateEventAction(action1, http.StatusOK)
  4332. assert.NoError(t, err)
  4333. conn, client, err = getSftpClient(user)
  4334. if assert.NoError(t, err) {
  4335. defer conn.Close()
  4336. defer client.Close()
  4337. f, err := client.Create(testFileName)
  4338. assert.NoError(t, err)
  4339. _, err = f.Write(testFileContent)
  4340. assert.NoError(t, err)
  4341. err = f.Close()
  4342. assert.Error(t, err)
  4343. }
  4344. _, err = httpdtest.RemoveEventRule(rule1, http.StatusOK)
  4345. assert.NoError(t, err)
  4346. _, err = httpdtest.RemoveEventAction(action1, http.StatusOK)
  4347. assert.NoError(t, err)
  4348. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  4349. assert.NoError(t, err)
  4350. err = os.RemoveAll(user.GetHomeDir())
  4351. assert.NoError(t, err)
  4352. }
  4353. func TestEventActionEmailAttachments(t *testing.T) {
  4354. smtpCfg := smtp.Config{
  4355. Host: "127.0.0.1",
  4356. Port: 2525,
  4357. From: "notify@example.com",
  4358. TemplatesPath: "templates",
  4359. }
  4360. err := smtpCfg.Initialize(configDir)
  4361. require.NoError(t, err)
  4362. a1 := dataprovider.BaseEventAction{
  4363. Name: "action1",
  4364. Type: dataprovider.ActionTypeFilesystem,
  4365. Options: dataprovider.BaseEventActionOptions{
  4366. FsConfig: dataprovider.EventActionFilesystemConfig{
  4367. Type: dataprovider.FilesystemActionCompress,
  4368. Compress: dataprovider.EventActionFsCompress{
  4369. Name: "/{{VirtualPath}}.zip",
  4370. Paths: []string{"/{{VirtualPath}}"},
  4371. },
  4372. },
  4373. },
  4374. }
  4375. action1, _, err := httpdtest.AddEventAction(a1, http.StatusCreated)
  4376. assert.NoError(t, err)
  4377. a2 := dataprovider.BaseEventAction{
  4378. Name: "action2",
  4379. Type: dataprovider.ActionTypeEmail,
  4380. Options: dataprovider.BaseEventActionOptions{
  4381. EmailConfig: dataprovider.EventActionEmailConfig{
  4382. Recipients: []string{"test@example.com"},
  4383. Subject: `"{{Event}}" from "{{Name}}"`,
  4384. Body: "Fs path {{FsPath}}, size: {{FileSize}}, protocol: {{Protocol}}, IP: {{IP}}",
  4385. Attachments: []string{"/{{VirtualPath}}.zip"},
  4386. },
  4387. },
  4388. }
  4389. action2, _, err := httpdtest.AddEventAction(a2, http.StatusCreated)
  4390. assert.NoError(t, err)
  4391. r1 := dataprovider.EventRule{
  4392. Name: "test email with attachment",
  4393. Trigger: dataprovider.EventTriggerFsEvent,
  4394. Conditions: dataprovider.EventConditions{
  4395. FsEvents: []string{"upload"},
  4396. },
  4397. Actions: []dataprovider.EventAction{
  4398. {
  4399. BaseEventAction: dataprovider.BaseEventAction{
  4400. Name: action1.Name,
  4401. },
  4402. Order: 1,
  4403. },
  4404. {
  4405. BaseEventAction: dataprovider.BaseEventAction{
  4406. Name: action2.Name,
  4407. },
  4408. Order: 2,
  4409. },
  4410. },
  4411. }
  4412. rule1, _, err := httpdtest.AddEventRule(r1, http.StatusCreated)
  4413. assert.NoError(t, err)
  4414. localUser, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  4415. assert.NoError(t, err)
  4416. u := getTestSFTPUser()
  4417. u.FsConfig.SFTPConfig.BufferSize = 1
  4418. sftpUser, _, err := httpdtest.AddUser(u, http.StatusCreated)
  4419. assert.NoError(t, err)
  4420. cryptFsUser, _, err := httpdtest.AddUser(getCryptFsUser(), http.StatusCreated)
  4421. assert.NoError(t, err)
  4422. for _, user := range []dataprovider.User{localUser, sftpUser, cryptFsUser} {
  4423. conn, client, err := getSftpClient(user)
  4424. if assert.NoError(t, err) {
  4425. defer conn.Close()
  4426. defer client.Close()
  4427. lastReceivedEmail.reset()
  4428. f, err := client.Create(testFileName)
  4429. assert.NoError(t, err)
  4430. _, err = f.Write(testFileContent)
  4431. assert.NoError(t, err)
  4432. err = f.Close()
  4433. assert.NoError(t, err)
  4434. assert.Eventually(t, func() bool {
  4435. return lastReceivedEmail.get().From != ""
  4436. }, 1500*time.Millisecond, 100*time.Millisecond)
  4437. email := lastReceivedEmail.get()
  4438. assert.Len(t, email.To, 1)
  4439. assert.True(t, util.Contains(email.To, "test@example.com"))
  4440. assert.Contains(t, email.Data, `Subject: "upload" from`)
  4441. assert.Contains(t, email.Data, "Content-Disposition: attachment")
  4442. }
  4443. }
  4444. _, err = httpdtest.RemoveEventRule(rule1, http.StatusOK)
  4445. assert.NoError(t, err)
  4446. _, err = httpdtest.RemoveEventAction(action1, http.StatusOK)
  4447. assert.NoError(t, err)
  4448. _, err = httpdtest.RemoveEventAction(action2, http.StatusOK)
  4449. assert.NoError(t, err)
  4450. _, err = httpdtest.RemoveUser(sftpUser, http.StatusOK)
  4451. assert.NoError(t, err)
  4452. _, err = httpdtest.RemoveUser(localUser, http.StatusOK)
  4453. assert.NoError(t, err)
  4454. err = os.RemoveAll(localUser.GetHomeDir())
  4455. assert.NoError(t, err)
  4456. _, err = httpdtest.RemoveUser(cryptFsUser, http.StatusOK)
  4457. assert.NoError(t, err)
  4458. err = os.RemoveAll(cryptFsUser.GetHomeDir())
  4459. assert.NoError(t, err)
  4460. smtpCfg = smtp.Config{}
  4461. err = smtpCfg.Initialize(configDir)
  4462. require.NoError(t, err)
  4463. }
  4464. func TestEventActionsRetentionReports(t *testing.T) {
  4465. smtpCfg := smtp.Config{
  4466. Host: "127.0.0.1",
  4467. Port: 2525,
  4468. From: "notify@example.com",
  4469. TemplatesPath: "templates",
  4470. }
  4471. err := smtpCfg.Initialize(configDir)
  4472. require.NoError(t, err)
  4473. testDir := "/d"
  4474. a1 := dataprovider.BaseEventAction{
  4475. Name: "action1",
  4476. Type: dataprovider.ActionTypeDataRetentionCheck,
  4477. Options: dataprovider.BaseEventActionOptions{
  4478. RetentionConfig: dataprovider.EventActionDataRetentionConfig{
  4479. Folders: []dataprovider.FolderRetention{
  4480. {
  4481. Path: testDir,
  4482. Retention: 1,
  4483. DeleteEmptyDirs: true,
  4484. IgnoreUserPermissions: true,
  4485. },
  4486. },
  4487. },
  4488. },
  4489. }
  4490. action1, _, err := httpdtest.AddEventAction(a1, http.StatusCreated)
  4491. assert.NoError(t, err)
  4492. a2 := dataprovider.BaseEventAction{
  4493. Name: "action2",
  4494. Type: dataprovider.ActionTypeEmail,
  4495. Options: dataprovider.BaseEventActionOptions{
  4496. EmailConfig: dataprovider.EventActionEmailConfig{
  4497. Recipients: []string{"test@example.com"},
  4498. Subject: `"{{Event}}" from "{{Name}}"`,
  4499. Body: "Fs path {{FsPath}}, size: {{FileSize}}, protocol: {{Protocol}}, IP: {{IP}}",
  4500. Attachments: []string{dataprovider.RetentionReportPlaceHolder},
  4501. },
  4502. },
  4503. }
  4504. action2, _, err := httpdtest.AddEventAction(a2, http.StatusCreated)
  4505. assert.NoError(t, err)
  4506. a3 := dataprovider.BaseEventAction{
  4507. Name: "action3",
  4508. Type: dataprovider.ActionTypeHTTP,
  4509. Options: dataprovider.BaseEventActionOptions{
  4510. HTTPConfig: dataprovider.EventActionHTTPConfig{
  4511. Endpoint: fmt.Sprintf("http://%s/", httpAddr),
  4512. Timeout: 20,
  4513. Method: http.MethodPost,
  4514. Body: dataprovider.RetentionReportPlaceHolder,
  4515. },
  4516. },
  4517. }
  4518. action3, _, err := httpdtest.AddEventAction(a3, http.StatusCreated)
  4519. assert.NoError(t, err)
  4520. a4 := dataprovider.BaseEventAction{
  4521. Name: "action4",
  4522. Type: dataprovider.ActionTypeHTTP,
  4523. Options: dataprovider.BaseEventActionOptions{
  4524. HTTPConfig: dataprovider.EventActionHTTPConfig{
  4525. Endpoint: fmt.Sprintf("http://%s/multipart", httpAddr),
  4526. Timeout: 20,
  4527. Method: http.MethodPost,
  4528. Parts: []dataprovider.HTTPPart{
  4529. {
  4530. Name: "reports.zip",
  4531. Filepath: dataprovider.RetentionReportPlaceHolder,
  4532. },
  4533. },
  4534. },
  4535. },
  4536. }
  4537. action4, _, err := httpdtest.AddEventAction(a4, http.StatusCreated)
  4538. assert.NoError(t, err)
  4539. r1 := dataprovider.EventRule{
  4540. Name: "test rule1",
  4541. Trigger: dataprovider.EventTriggerFsEvent,
  4542. Conditions: dataprovider.EventConditions{
  4543. FsEvents: []string{"upload"},
  4544. },
  4545. Actions: []dataprovider.EventAction{
  4546. {
  4547. BaseEventAction: dataprovider.BaseEventAction{
  4548. Name: action1.Name,
  4549. },
  4550. Order: 1,
  4551. Options: dataprovider.EventActionOptions{
  4552. ExecuteSync: true,
  4553. StopOnFailure: true,
  4554. },
  4555. },
  4556. {
  4557. BaseEventAction: dataprovider.BaseEventAction{
  4558. Name: action2.Name,
  4559. },
  4560. Order: 2,
  4561. Options: dataprovider.EventActionOptions{
  4562. ExecuteSync: true,
  4563. StopOnFailure: true,
  4564. },
  4565. },
  4566. {
  4567. BaseEventAction: dataprovider.BaseEventAction{
  4568. Name: action3.Name,
  4569. },
  4570. Order: 3,
  4571. Options: dataprovider.EventActionOptions{
  4572. ExecuteSync: true,
  4573. StopOnFailure: true,
  4574. },
  4575. },
  4576. {
  4577. BaseEventAction: dataprovider.BaseEventAction{
  4578. Name: action4.Name,
  4579. },
  4580. Order: 4,
  4581. Options: dataprovider.EventActionOptions{
  4582. ExecuteSync: true,
  4583. StopOnFailure: true,
  4584. },
  4585. },
  4586. },
  4587. }
  4588. rule1, _, err := httpdtest.AddEventRule(r1, http.StatusCreated)
  4589. assert.NoError(t, err)
  4590. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  4591. assert.NoError(t, err)
  4592. conn, client, err := getSftpClient(user)
  4593. if assert.NoError(t, err) {
  4594. defer conn.Close()
  4595. defer client.Close()
  4596. subdir := path.Join(testDir, "sub")
  4597. err = client.MkdirAll(subdir)
  4598. assert.NoError(t, err)
  4599. lastReceivedEmail.reset()
  4600. f, err := client.Create(testFileName)
  4601. assert.NoError(t, err)
  4602. _, err = f.Write(testFileContent)
  4603. assert.NoError(t, err)
  4604. err = f.Close()
  4605. assert.NoError(t, err)
  4606. email := lastReceivedEmail.get()
  4607. assert.Len(t, email.To, 1)
  4608. assert.True(t, util.Contains(email.To, "test@example.com"))
  4609. assert.Contains(t, email.Data, fmt.Sprintf(`Subject: "upload" from "%s"`, user.Username))
  4610. assert.Contains(t, email.Data, "Content-Disposition: attachment")
  4611. _, err = client.Stat(testDir)
  4612. assert.NoError(t, err)
  4613. _, err = client.Stat(subdir)
  4614. assert.ErrorIs(t, err, os.ErrNotExist)
  4615. err = client.Mkdir(subdir)
  4616. assert.NoError(t, err)
  4617. newName := path.Join(testDir, testFileName)
  4618. err = client.Rename(testFileName, newName)
  4619. assert.NoError(t, err)
  4620. err = client.Chtimes(newName, time.Now().Add(-24*time.Hour), time.Now().Add(-24*time.Hour))
  4621. assert.NoError(t, err)
  4622. lastReceivedEmail.reset()
  4623. f, err = client.Create(testFileName)
  4624. assert.NoError(t, err)
  4625. _, err = f.Write(testFileContent)
  4626. assert.NoError(t, err)
  4627. err = f.Close()
  4628. assert.NoError(t, err)
  4629. email = lastReceivedEmail.get()
  4630. assert.Len(t, email.To, 1)
  4631. _, err = client.Stat(subdir)
  4632. assert.ErrorIs(t, err, os.ErrNotExist)
  4633. _, err = client.Stat(subdir)
  4634. assert.ErrorIs(t, err, os.ErrNotExist)
  4635. }
  4636. // now remove the retention check to test errors
  4637. rule1.Actions = []dataprovider.EventAction{
  4638. {
  4639. BaseEventAction: dataprovider.BaseEventAction{
  4640. Name: action2.Name,
  4641. },
  4642. Order: 2,
  4643. Options: dataprovider.EventActionOptions{
  4644. ExecuteSync: true,
  4645. StopOnFailure: false,
  4646. },
  4647. },
  4648. {
  4649. BaseEventAction: dataprovider.BaseEventAction{
  4650. Name: action3.Name,
  4651. },
  4652. Order: 3,
  4653. Options: dataprovider.EventActionOptions{
  4654. ExecuteSync: true,
  4655. StopOnFailure: false,
  4656. },
  4657. },
  4658. {
  4659. BaseEventAction: dataprovider.BaseEventAction{
  4660. Name: action4.Name,
  4661. },
  4662. Order: 4,
  4663. Options: dataprovider.EventActionOptions{
  4664. ExecuteSync: true,
  4665. StopOnFailure: false,
  4666. },
  4667. },
  4668. }
  4669. _, _, err = httpdtest.UpdateEventRule(rule1, http.StatusOK)
  4670. assert.NoError(t, err)
  4671. conn, client, err = getSftpClient(user)
  4672. if assert.NoError(t, err) {
  4673. defer conn.Close()
  4674. defer client.Close()
  4675. f, err := client.Create(testFileName)
  4676. assert.NoError(t, err)
  4677. _, err = f.Write(testFileContent)
  4678. assert.NoError(t, err)
  4679. err = f.Close()
  4680. assert.Error(t, err)
  4681. }
  4682. _, err = httpdtest.RemoveEventRule(rule1, http.StatusOK)
  4683. assert.NoError(t, err)
  4684. _, err = httpdtest.RemoveEventAction(action1, http.StatusOK)
  4685. assert.NoError(t, err)
  4686. _, err = httpdtest.RemoveEventAction(action2, http.StatusOK)
  4687. assert.NoError(t, err)
  4688. _, err = httpdtest.RemoveEventAction(action3, http.StatusOK)
  4689. assert.NoError(t, err)
  4690. _, err = httpdtest.RemoveEventAction(action4, http.StatusOK)
  4691. assert.NoError(t, err)
  4692. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  4693. assert.NoError(t, err)
  4694. err = os.RemoveAll(user.GetHomeDir())
  4695. assert.NoError(t, err)
  4696. smtpCfg = smtp.Config{}
  4697. err = smtpCfg.Initialize(configDir)
  4698. require.NoError(t, err)
  4699. }
  4700. func TestEventRuleFirstUploadDownloadActions(t *testing.T) {
  4701. smtpCfg := smtp.Config{
  4702. Host: "127.0.0.1",
  4703. Port: 2525,
  4704. From: "notify@example.com",
  4705. TemplatesPath: "templates",
  4706. }
  4707. err := smtpCfg.Initialize(configDir)
  4708. require.NoError(t, err)
  4709. a1 := dataprovider.BaseEventAction{
  4710. Name: "action1",
  4711. Type: dataprovider.ActionTypeEmail,
  4712. Options: dataprovider.BaseEventActionOptions{
  4713. EmailConfig: dataprovider.EventActionEmailConfig{
  4714. Recipients: []string{"test@example.com"},
  4715. Subject: `"{{Event}}" from "{{Name}}"`,
  4716. Body: "Fs path {{FsPath}}, size: {{FileSize}}, protocol: {{Protocol}}, IP: {{IP}}",
  4717. },
  4718. },
  4719. }
  4720. action1, _, err := httpdtest.AddEventAction(a1, http.StatusCreated)
  4721. assert.NoError(t, err)
  4722. r1 := dataprovider.EventRule{
  4723. Name: "test first upload rule",
  4724. Trigger: dataprovider.EventTriggerFsEvent,
  4725. Conditions: dataprovider.EventConditions{
  4726. FsEvents: []string{"first-upload"},
  4727. },
  4728. Actions: []dataprovider.EventAction{
  4729. {
  4730. BaseEventAction: dataprovider.BaseEventAction{
  4731. Name: action1.Name,
  4732. },
  4733. Order: 1,
  4734. },
  4735. },
  4736. }
  4737. rule1, _, err := httpdtest.AddEventRule(r1, http.StatusCreated)
  4738. assert.NoError(t, err)
  4739. r2 := dataprovider.EventRule{
  4740. Name: "test first download rule",
  4741. Trigger: dataprovider.EventTriggerFsEvent,
  4742. Conditions: dataprovider.EventConditions{
  4743. FsEvents: []string{"first-download"},
  4744. },
  4745. Actions: []dataprovider.EventAction{
  4746. {
  4747. BaseEventAction: dataprovider.BaseEventAction{
  4748. Name: action1.Name,
  4749. },
  4750. Order: 1,
  4751. },
  4752. },
  4753. }
  4754. rule2, _, err := httpdtest.AddEventRule(r2, http.StatusCreated)
  4755. assert.NoError(t, err)
  4756. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  4757. assert.NoError(t, err)
  4758. conn, client, err := getSftpClient(user)
  4759. if assert.NoError(t, err) {
  4760. defer conn.Close()
  4761. defer client.Close()
  4762. testFileSize := int64(32768)
  4763. lastReceivedEmail.reset()
  4764. err = writeSFTPFileNoCheck(testFileName, testFileSize, client)
  4765. assert.NoError(t, err)
  4766. assert.Eventually(t, func() bool {
  4767. return lastReceivedEmail.get().From != ""
  4768. }, 1500*time.Millisecond, 100*time.Millisecond)
  4769. email := lastReceivedEmail.get()
  4770. assert.Len(t, email.To, 1)
  4771. assert.True(t, util.Contains(email.To, "test@example.com"))
  4772. assert.Contains(t, email.Data, fmt.Sprintf(`Subject: "first-upload" from "%s"`, user.Username))
  4773. lastReceivedEmail.reset()
  4774. // a new upload will not produce a new notification
  4775. err = writeSFTPFileNoCheck(testFileName+"_1", 32768, client)
  4776. assert.NoError(t, err)
  4777. assert.Never(t, func() bool {
  4778. return lastReceivedEmail.get().From != ""
  4779. }, 1000*time.Millisecond, 100*time.Millisecond)
  4780. // the same for download
  4781. f, err := client.Open(testFileName)
  4782. assert.NoError(t, err)
  4783. contents := make([]byte, testFileSize)
  4784. n, err := io.ReadFull(f, contents)
  4785. assert.NoError(t, err)
  4786. assert.Equal(t, int(testFileSize), n)
  4787. err = f.Close()
  4788. assert.NoError(t, err)
  4789. assert.Eventually(t, func() bool {
  4790. return lastReceivedEmail.get().From != ""
  4791. }, 1500*time.Millisecond, 100*time.Millisecond)
  4792. email = lastReceivedEmail.get()
  4793. assert.Len(t, email.To, 1)
  4794. assert.True(t, util.Contains(email.To, "test@example.com"))
  4795. assert.Contains(t, email.Data, fmt.Sprintf(`Subject: "first-download" from "%s"`, user.Username))
  4796. // download again
  4797. lastReceivedEmail.reset()
  4798. f, err = client.Open(testFileName)
  4799. assert.NoError(t, err)
  4800. contents = make([]byte, testFileSize)
  4801. n, err = io.ReadFull(f, contents)
  4802. assert.NoError(t, err)
  4803. assert.Equal(t, int(testFileSize), n)
  4804. err = f.Close()
  4805. assert.NoError(t, err)
  4806. assert.Never(t, func() bool {
  4807. return lastReceivedEmail.get().From != ""
  4808. }, 1000*time.Millisecond, 100*time.Millisecond)
  4809. }
  4810. _, err = httpdtest.RemoveEventRule(rule1, http.StatusOK)
  4811. assert.NoError(t, err)
  4812. _, err = httpdtest.RemoveEventRule(rule2, http.StatusOK)
  4813. assert.NoError(t, err)
  4814. _, err = httpdtest.RemoveEventAction(action1, http.StatusOK)
  4815. assert.NoError(t, err)
  4816. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  4817. assert.NoError(t, err)
  4818. err = os.RemoveAll(user.GetHomeDir())
  4819. assert.NoError(t, err)
  4820. smtpCfg = smtp.Config{}
  4821. err = smtpCfg.Initialize(configDir)
  4822. require.NoError(t, err)
  4823. }
  4824. func TestEventRuleCertificate(t *testing.T) {
  4825. smtpCfg := smtp.Config{
  4826. Host: "127.0.0.1",
  4827. Port: 2525,
  4828. From: "notify@example.com",
  4829. TemplatesPath: "templates",
  4830. }
  4831. err := smtpCfg.Initialize(configDir)
  4832. require.NoError(t, err)
  4833. lastReceivedEmail.reset()
  4834. a1 := dataprovider.BaseEventAction{
  4835. Name: "action1",
  4836. Type: dataprovider.ActionTypeEmail,
  4837. Options: dataprovider.BaseEventActionOptions{
  4838. EmailConfig: dataprovider.EventActionEmailConfig{
  4839. Recipients: []string{"test@example.com"},
  4840. Subject: `"{{Event}} {{StatusString}}"`,
  4841. Body: "Domain: {{Name}} Timestamp: {{Timestamp}} {{ErrorString}}",
  4842. },
  4843. },
  4844. }
  4845. action1, _, err := httpdtest.AddEventAction(a1, http.StatusCreated)
  4846. assert.NoError(t, err)
  4847. a2 := dataprovider.BaseEventAction{
  4848. Name: "action2",
  4849. Type: dataprovider.ActionTypeFolderQuotaReset,
  4850. }
  4851. action2, _, err := httpdtest.AddEventAction(a2, http.StatusCreated)
  4852. assert.NoError(t, err)
  4853. r1 := dataprovider.EventRule{
  4854. Name: "test rule certificate",
  4855. Trigger: dataprovider.EventTriggerCertificate,
  4856. Actions: []dataprovider.EventAction{
  4857. {
  4858. BaseEventAction: dataprovider.BaseEventAction{
  4859. Name: action1.Name,
  4860. },
  4861. Order: 1,
  4862. },
  4863. },
  4864. }
  4865. rule1, _, err := httpdtest.AddEventRule(r1, http.StatusCreated)
  4866. assert.NoError(t, err)
  4867. r2 := dataprovider.EventRule{
  4868. Name: "test rule 2",
  4869. Trigger: dataprovider.EventTriggerCertificate,
  4870. Actions: []dataprovider.EventAction{
  4871. {
  4872. BaseEventAction: dataprovider.BaseEventAction{
  4873. Name: action1.Name,
  4874. },
  4875. Order: 1,
  4876. },
  4877. {
  4878. BaseEventAction: dataprovider.BaseEventAction{
  4879. Name: action2.Name,
  4880. },
  4881. Order: 2,
  4882. },
  4883. },
  4884. }
  4885. rule2, _, err := httpdtest.AddEventRule(r2, http.StatusCreated)
  4886. assert.NoError(t, err)
  4887. renewalEvent := "Certificate renewal"
  4888. common.HandleCertificateEvent(common.EventParams{
  4889. Name: "example.com",
  4890. Timestamp: time.Now().UnixNano(),
  4891. Status: 1,
  4892. Event: renewalEvent,
  4893. })
  4894. assert.Eventually(t, func() bool {
  4895. return lastReceivedEmail.get().From != ""
  4896. }, 3000*time.Millisecond, 100*time.Millisecond)
  4897. email := lastReceivedEmail.get()
  4898. assert.Len(t, email.To, 1)
  4899. assert.True(t, util.Contains(email.To, "test@example.com"))
  4900. assert.Contains(t, email.Data, fmt.Sprintf(`Subject: "%s OK"`, renewalEvent))
  4901. assert.Contains(t, email.Data, `Domain: example.com Timestamp`)
  4902. lastReceivedEmail.reset()
  4903. params := common.EventParams{
  4904. Name: "example.com",
  4905. Timestamp: time.Now().UnixNano(),
  4906. Status: 2,
  4907. Event: renewalEvent,
  4908. }
  4909. errRenew := errors.New("generic renew error")
  4910. params.AddError(errRenew)
  4911. common.HandleCertificateEvent(params)
  4912. assert.Eventually(t, func() bool {
  4913. return lastReceivedEmail.get().From != ""
  4914. }, 3000*time.Millisecond, 100*time.Millisecond)
  4915. email = lastReceivedEmail.get()
  4916. assert.Len(t, email.To, 1)
  4917. assert.True(t, util.Contains(email.To, "test@example.com"))
  4918. assert.Contains(t, email.Data, fmt.Sprintf(`Subject: "%s KO"`, renewalEvent))
  4919. assert.Contains(t, email.Data, `Domain: example.com Timestamp`)
  4920. assert.Contains(t, email.Data, errRenew.Error())
  4921. _, err = httpdtest.RemoveEventRule(rule1, http.StatusOK)
  4922. assert.NoError(t, err)
  4923. _, err = httpdtest.RemoveEventRule(rule2, http.StatusOK)
  4924. assert.NoError(t, err)
  4925. _, err = httpdtest.RemoveEventAction(action1, http.StatusOK)
  4926. assert.NoError(t, err)
  4927. _, err = httpdtest.RemoveEventAction(action2, http.StatusOK)
  4928. assert.NoError(t, err)
  4929. // ignored no more certificate rules
  4930. common.HandleCertificateEvent(common.EventParams{
  4931. Name: "example.com",
  4932. Timestamp: time.Now().UnixNano(),
  4933. Status: 1,
  4934. Event: renewalEvent,
  4935. })
  4936. smtpCfg = smtp.Config{}
  4937. err = smtpCfg.Initialize(configDir)
  4938. require.NoError(t, err)
  4939. }
  4940. func TestEventRuleIPBlocked(t *testing.T) {
  4941. oldConfig := config.GetCommonConfig()
  4942. cfg := config.GetCommonConfig()
  4943. cfg.DefenderConfig.Enabled = true
  4944. cfg.DefenderConfig.Threshold = 3
  4945. cfg.DefenderConfig.ScoreLimitExceeded = 2
  4946. err := common.Initialize(cfg, 0)
  4947. assert.NoError(t, err)
  4948. smtpCfg := smtp.Config{
  4949. Host: "127.0.0.1",
  4950. Port: 2525,
  4951. From: "notification@example.com",
  4952. TemplatesPath: "templates",
  4953. }
  4954. err = smtpCfg.Initialize(configDir)
  4955. require.NoError(t, err)
  4956. a1 := dataprovider.BaseEventAction{
  4957. Name: "action1",
  4958. Type: dataprovider.ActionTypeEmail,
  4959. Options: dataprovider.BaseEventActionOptions{
  4960. EmailConfig: dataprovider.EventActionEmailConfig{
  4961. Recipients: []string{"test3@example.com", "test4@example.com"},
  4962. Subject: `New "{{Event}}"`,
  4963. Body: "IP: {{IP}} Timestamp: {{Timestamp}}",
  4964. },
  4965. },
  4966. }
  4967. action1, _, err := httpdtest.AddEventAction(a1, http.StatusCreated)
  4968. assert.NoError(t, err)
  4969. a2 := dataprovider.BaseEventAction{
  4970. Name: "action2",
  4971. Type: dataprovider.ActionTypeFolderQuotaReset,
  4972. }
  4973. action2, _, err := httpdtest.AddEventAction(a2, http.StatusCreated)
  4974. assert.NoError(t, err)
  4975. r1 := dataprovider.EventRule{
  4976. Name: "test rule ip blocked",
  4977. Trigger: dataprovider.EventTriggerIPBlocked,
  4978. Actions: []dataprovider.EventAction{
  4979. {
  4980. BaseEventAction: dataprovider.BaseEventAction{
  4981. Name: action1.Name,
  4982. },
  4983. Order: 1,
  4984. },
  4985. },
  4986. }
  4987. rule1, _, err := httpdtest.AddEventRule(r1, http.StatusCreated)
  4988. assert.NoError(t, err)
  4989. r2 := dataprovider.EventRule{
  4990. Name: "test rule 2",
  4991. Trigger: dataprovider.EventTriggerIPBlocked,
  4992. Actions: []dataprovider.EventAction{
  4993. {
  4994. BaseEventAction: dataprovider.BaseEventAction{
  4995. Name: action1.Name,
  4996. },
  4997. Order: 1,
  4998. },
  4999. {
  5000. BaseEventAction: dataprovider.BaseEventAction{
  5001. Name: action2.Name,
  5002. },
  5003. Order: 2,
  5004. },
  5005. },
  5006. }
  5007. rule2, _, err := httpdtest.AddEventRule(r2, http.StatusCreated)
  5008. assert.NoError(t, err)
  5009. u := getTestUser()
  5010. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  5011. assert.NoError(t, err)
  5012. lastReceivedEmail.reset()
  5013. time.Sleep(300 * time.Millisecond)
  5014. assert.Empty(t, lastReceivedEmail.get().From, lastReceivedEmail.get().Data)
  5015. for i := 0; i < 3; i++ {
  5016. user.Password = "wrong_pwd"
  5017. _, _, err = getSftpClient(user)
  5018. assert.Error(t, err)
  5019. }
  5020. // the client is now banned
  5021. user.Password = defaultPassword
  5022. _, _, err = getSftpClient(user)
  5023. assert.Error(t, err)
  5024. // check the email notification
  5025. assert.Eventually(t, func() bool {
  5026. return lastReceivedEmail.get().From != ""
  5027. }, 3000*time.Millisecond, 100*time.Millisecond)
  5028. email := lastReceivedEmail.get()
  5029. assert.Len(t, email.To, 2)
  5030. assert.True(t, util.Contains(email.To, "test3@example.com"))
  5031. assert.True(t, util.Contains(email.To, "test4@example.com"))
  5032. assert.Contains(t, email.Data, `Subject: New "IP Blocked"`)
  5033. err = dataprovider.DeleteEventRule(rule1.Name, "", "")
  5034. assert.NoError(t, err)
  5035. err = dataprovider.DeleteEventRule(rule2.Name, "", "")
  5036. assert.NoError(t, err)
  5037. err = dataprovider.DeleteEventAction(action1.Name, "", "")
  5038. assert.NoError(t, err)
  5039. err = dataprovider.DeleteEventAction(action2.Name, "", "")
  5040. assert.NoError(t, err)
  5041. err = dataprovider.DeleteUser(user.Username, "", "")
  5042. assert.NoError(t, err)
  5043. err = os.RemoveAll(user.GetHomeDir())
  5044. assert.NoError(t, err)
  5045. smtpCfg = smtp.Config{}
  5046. err = smtpCfg.Initialize(configDir)
  5047. require.NoError(t, err)
  5048. err = common.Initialize(oldConfig, 0)
  5049. assert.NoError(t, err)
  5050. }
  5051. func TestSyncUploadAction(t *testing.T) {
  5052. if runtime.GOOS == osWindows {
  5053. t.Skip("this test is not available on Windows")
  5054. }
  5055. uploadScriptPath := filepath.Join(os.TempDir(), "upload.sh")
  5056. common.Config.Actions.ExecuteOn = []string{"upload"}
  5057. common.Config.Actions.ExecuteSync = []string{"upload"}
  5058. common.Config.Actions.Hook = uploadScriptPath
  5059. u := getTestUser()
  5060. u.QuotaFiles = 1000
  5061. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  5062. assert.NoError(t, err)
  5063. movedFileName := "moved.dat"
  5064. movedPath := filepath.Join(user.HomeDir, movedFileName)
  5065. err = os.WriteFile(uploadScriptPath, getUploadScriptContent(movedPath, "", 0), 0755)
  5066. assert.NoError(t, err)
  5067. conn, client, err := getSftpClient(user)
  5068. if assert.NoError(t, err) {
  5069. defer conn.Close()
  5070. defer client.Close()
  5071. size := int64(32768)
  5072. err = writeSFTPFileNoCheck(testFileName, size, client)
  5073. assert.NoError(t, err)
  5074. _, err = client.Stat(testFileName)
  5075. assert.Error(t, err)
  5076. info, err := client.Stat(movedFileName)
  5077. if assert.NoError(t, err) {
  5078. assert.Equal(t, size, info.Size())
  5079. }
  5080. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  5081. assert.NoError(t, err)
  5082. assert.Equal(t, 1, user.UsedQuotaFiles)
  5083. assert.Equal(t, size, user.UsedQuotaSize)
  5084. // test some hook failure
  5085. // the uploaded file is moved and the hook fails, it will be not removed from the quota
  5086. err = os.WriteFile(uploadScriptPath, getUploadScriptContent(movedPath, "", 1), 0755)
  5087. assert.NoError(t, err)
  5088. err = writeSFTPFileNoCheck(testFileName+"_1", size, client)
  5089. assert.Error(t, err)
  5090. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  5091. assert.NoError(t, err)
  5092. assert.Equal(t, 2, user.UsedQuotaFiles)
  5093. assert.Equal(t, size*2, user.UsedQuotaSize)
  5094. // the uploaded file is not moved and the hook fails, the uploaded file will be deleted
  5095. // and removed from the quota
  5096. movedPath = filepath.Join(user.HomeDir, "missing dir", movedFileName)
  5097. err = os.WriteFile(uploadScriptPath, getUploadScriptContent(movedPath, "", 1), 0755)
  5098. assert.NoError(t, err)
  5099. err = writeSFTPFileNoCheck(testFileName+"_2", size, client)
  5100. assert.Error(t, err)
  5101. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  5102. assert.NoError(t, err)
  5103. assert.Equal(t, 2, user.UsedQuotaFiles)
  5104. assert.Equal(t, size*2, user.UsedQuotaSize)
  5105. // overwrite an existing file
  5106. _, err = client.Stat(movedFileName)
  5107. assert.NoError(t, err)
  5108. err = writeSFTPFileNoCheck(movedFileName, size, client)
  5109. assert.Error(t, err)
  5110. _, err = client.Stat(movedFileName)
  5111. assert.Error(t, err)
  5112. user, _, err = httpdtest.GetUserByUsername(user.Username, http.StatusOK)
  5113. assert.NoError(t, err)
  5114. assert.Equal(t, 1, user.UsedQuotaFiles)
  5115. assert.Equal(t, size, user.UsedQuotaSize)
  5116. }
  5117. err = os.Remove(uploadScriptPath)
  5118. assert.NoError(t, err)
  5119. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  5120. assert.NoError(t, err)
  5121. err = os.RemoveAll(user.GetHomeDir())
  5122. assert.NoError(t, err)
  5123. common.Config.Actions.ExecuteOn = nil
  5124. common.Config.Actions.ExecuteSync = nil
  5125. common.Config.Actions.Hook = uploadScriptPath
  5126. }
  5127. func TestQuotaTrackDisabled(t *testing.T) {
  5128. err := dataprovider.Close()
  5129. assert.NoError(t, err)
  5130. err = config.LoadConfig(configDir, "")
  5131. assert.NoError(t, err)
  5132. providerConf := config.GetProviderConf()
  5133. providerConf.TrackQuota = 0
  5134. err = dataprovider.Initialize(providerConf, configDir, true)
  5135. assert.NoError(t, err)
  5136. user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  5137. assert.NoError(t, err)
  5138. conn, client, err := getSftpClient(user)
  5139. if assert.NoError(t, err) {
  5140. defer conn.Close()
  5141. defer client.Close()
  5142. err = writeSFTPFile(testFileName, 32, client)
  5143. assert.NoError(t, err)
  5144. err = client.Rename(testFileName, testFileName+"1")
  5145. assert.NoError(t, err)
  5146. }
  5147. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  5148. assert.NoError(t, err)
  5149. err = os.RemoveAll(user.GetHomeDir())
  5150. assert.NoError(t, err)
  5151. err = dataprovider.Close()
  5152. assert.NoError(t, err)
  5153. err = config.LoadConfig(configDir, "")
  5154. assert.NoError(t, err)
  5155. providerConf = config.GetProviderConf()
  5156. err = dataprovider.Initialize(providerConf, configDir, true)
  5157. assert.NoError(t, err)
  5158. }
  5159. func TestGetQuotaError(t *testing.T) {
  5160. if dataprovider.GetProviderStatus().Driver == "memory" {
  5161. t.Skip("this test is not available with the memory provider")
  5162. }
  5163. u := getTestUser()
  5164. u.TotalDataTransfer = 2000
  5165. mappedPath := filepath.Join(os.TempDir(), "vdir")
  5166. folderName := filepath.Base(mappedPath)
  5167. vdirPath := "/vpath"
  5168. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  5169. BaseVirtualFolder: vfs.BaseVirtualFolder{
  5170. Name: folderName,
  5171. MappedPath: mappedPath,
  5172. },
  5173. VirtualPath: vdirPath,
  5174. QuotaSize: 0,
  5175. QuotaFiles: 10,
  5176. })
  5177. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  5178. assert.NoError(t, err)
  5179. conn, client, err := getSftpClient(user)
  5180. if assert.NoError(t, err) {
  5181. defer conn.Close()
  5182. defer client.Close()
  5183. err = writeSFTPFile(testFileName, 32, client)
  5184. assert.NoError(t, err)
  5185. err = dataprovider.Close()
  5186. assert.NoError(t, err)
  5187. err = client.Rename(testFileName, path.Join(vdirPath, testFileName))
  5188. assert.Error(t, err)
  5189. err = config.LoadConfig(configDir, "")
  5190. assert.NoError(t, err)
  5191. providerConf := config.GetProviderConf()
  5192. err = dataprovider.Initialize(providerConf, configDir, true)
  5193. assert.NoError(t, err)
  5194. }
  5195. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  5196. assert.NoError(t, err)
  5197. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName}, http.StatusOK)
  5198. assert.NoError(t, err)
  5199. err = os.RemoveAll(user.GetHomeDir())
  5200. assert.NoError(t, err)
  5201. err = os.RemoveAll(mappedPath)
  5202. assert.NoError(t, err)
  5203. }
  5204. func TestRetentionAPI(t *testing.T) {
  5205. u := getTestUser()
  5206. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  5207. assert.NoError(t, err)
  5208. uploadPath := path.Join(testDir, testFileName)
  5209. conn, client, err := getSftpClient(user)
  5210. if assert.NoError(t, err) {
  5211. defer conn.Close()
  5212. defer client.Close()
  5213. err = client.Mkdir(testDir)
  5214. assert.NoError(t, err)
  5215. err = writeSFTPFile(uploadPath, 32, client)
  5216. assert.NoError(t, err)
  5217. folderRetention := []dataprovider.FolderRetention{
  5218. {
  5219. Path: "/",
  5220. Retention: 24,
  5221. DeleteEmptyDirs: true,
  5222. },
  5223. }
  5224. _, err = httpdtest.StartRetentionCheck(user.Username, folderRetention, http.StatusAccepted)
  5225. assert.NoError(t, err)
  5226. assert.Eventually(t, func() bool {
  5227. return len(common.RetentionChecks.Get()) == 0
  5228. }, 1000*time.Millisecond, 50*time.Millisecond)
  5229. _, err = client.Stat(uploadPath)
  5230. assert.NoError(t, err)
  5231. err = client.Chtimes(uploadPath, time.Now().Add(-48*time.Hour), time.Now().Add(-48*time.Hour))
  5232. assert.NoError(t, err)
  5233. _, err = httpdtest.StartRetentionCheck(user.Username, folderRetention, http.StatusAccepted)
  5234. assert.NoError(t, err)
  5235. assert.Eventually(t, func() bool {
  5236. return len(common.RetentionChecks.Get()) == 0
  5237. }, 1000*time.Millisecond, 50*time.Millisecond)
  5238. _, err = client.Stat(uploadPath)
  5239. assert.ErrorIs(t, err, os.ErrNotExist)
  5240. _, err = client.Stat(testDir)
  5241. assert.ErrorIs(t, err, os.ErrNotExist)
  5242. err = client.Mkdir(testDir)
  5243. assert.NoError(t, err)
  5244. err = writeSFTPFile(uploadPath, 32, client)
  5245. assert.NoError(t, err)
  5246. folderRetention[0].DeleteEmptyDirs = false
  5247. err = client.Chtimes(uploadPath, time.Now().Add(-48*time.Hour), time.Now().Add(-48*time.Hour))
  5248. assert.NoError(t, err)
  5249. _, err = httpdtest.StartRetentionCheck(user.Username, folderRetention, http.StatusAccepted)
  5250. assert.NoError(t, err)
  5251. assert.Eventually(t, func() bool {
  5252. return len(common.RetentionChecks.Get()) == 0
  5253. }, 1000*time.Millisecond, 50*time.Millisecond)
  5254. _, err = client.Stat(uploadPath)
  5255. assert.ErrorIs(t, err, os.ErrNotExist)
  5256. _, err = client.Stat(testDir)
  5257. assert.NoError(t, err)
  5258. err = writeSFTPFile(uploadPath, 32, client)
  5259. assert.NoError(t, err)
  5260. err = client.Chtimes(uploadPath, time.Now().Add(-48*time.Hour), time.Now().Add(-48*time.Hour))
  5261. assert.NoError(t, err)
  5262. }
  5263. // remove delete permissions to the user
  5264. user.Permissions["/"+testDir] = []string{dataprovider.PermListItems, dataprovider.PermUpload,
  5265. dataprovider.PermCreateDirs, dataprovider.PermChtimes}
  5266. user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "")
  5267. assert.NoError(t, err)
  5268. conn, client, err = getSftpClient(user)
  5269. if assert.NoError(t, err) {
  5270. defer conn.Close()
  5271. defer client.Close()
  5272. innerUploadFilePath := path.Join("/"+testDir, testDir, testFileName)
  5273. err = client.Mkdir(path.Join(testDir, testDir))
  5274. assert.NoError(t, err)
  5275. err = writeSFTPFile(innerUploadFilePath, 32, client)
  5276. assert.NoError(t, err)
  5277. err = client.Chtimes(innerUploadFilePath, time.Now().Add(-48*time.Hour), time.Now().Add(-48*time.Hour))
  5278. assert.NoError(t, err)
  5279. folderRetention := []dataprovider.FolderRetention{
  5280. {
  5281. Path: "/missing",
  5282. Retention: 24,
  5283. },
  5284. {
  5285. Path: "/" + testDir,
  5286. Retention: 24,
  5287. DeleteEmptyDirs: true,
  5288. },
  5289. {
  5290. Path: path.Dir(innerUploadFilePath),
  5291. Retention: 0,
  5292. IgnoreUserPermissions: true,
  5293. },
  5294. }
  5295. _, err = httpdtest.StartRetentionCheck(user.Username, folderRetention, http.StatusAccepted)
  5296. assert.NoError(t, err)
  5297. assert.Eventually(t, func() bool {
  5298. return len(common.RetentionChecks.Get()) == 0
  5299. }, 1000*time.Millisecond, 50*time.Millisecond)
  5300. _, err = client.Stat(uploadPath)
  5301. assert.NoError(t, err)
  5302. _, err = client.Stat(innerUploadFilePath)
  5303. assert.NoError(t, err)
  5304. folderRetention[1].IgnoreUserPermissions = true
  5305. _, err = httpdtest.StartRetentionCheck(user.Username, folderRetention, http.StatusAccepted)
  5306. assert.NoError(t, err)
  5307. assert.Eventually(t, func() bool {
  5308. return len(common.RetentionChecks.Get()) == 0
  5309. }, 1000*time.Millisecond, 50*time.Millisecond)
  5310. _, err = client.Stat(uploadPath)
  5311. assert.ErrorIs(t, err, os.ErrNotExist)
  5312. _, err = client.Stat(innerUploadFilePath)
  5313. assert.NoError(t, err)
  5314. folderRetention = []dataprovider.FolderRetention{
  5315. {
  5316. Path: "/" + testDir,
  5317. Retention: 24,
  5318. DeleteEmptyDirs: true,
  5319. IgnoreUserPermissions: true,
  5320. },
  5321. }
  5322. _, err = httpdtest.StartRetentionCheck(user.Username, folderRetention, http.StatusAccepted)
  5323. assert.NoError(t, err)
  5324. assert.Eventually(t, func() bool {
  5325. return len(common.RetentionChecks.Get()) == 0
  5326. }, 1000*time.Millisecond, 50*time.Millisecond)
  5327. _, err = client.Stat(innerUploadFilePath)
  5328. assert.ErrorIs(t, err, os.ErrNotExist)
  5329. }
  5330. // finally test some errors removing files or folders
  5331. if runtime.GOOS != osWindows {
  5332. dirPath := filepath.Join(user.HomeDir, "adir", "sub")
  5333. err := os.MkdirAll(dirPath, os.ModePerm)
  5334. assert.NoError(t, err)
  5335. filePath := filepath.Join(dirPath, "f.dat")
  5336. err = os.WriteFile(filePath, nil, os.ModePerm)
  5337. assert.NoError(t, err)
  5338. err = os.Chtimes(filePath, time.Now().Add(-72*time.Hour), time.Now().Add(-72*time.Hour))
  5339. assert.NoError(t, err)
  5340. err = os.Chmod(dirPath, 0001)
  5341. assert.NoError(t, err)
  5342. folderRetention := []dataprovider.FolderRetention{
  5343. {
  5344. Path: "/adir",
  5345. Retention: 24,
  5346. DeleteEmptyDirs: true,
  5347. IgnoreUserPermissions: true,
  5348. },
  5349. }
  5350. _, err = httpdtest.StartRetentionCheck(user.Username, folderRetention, http.StatusAccepted)
  5351. assert.NoError(t, err)
  5352. assert.Eventually(t, func() bool {
  5353. return len(common.RetentionChecks.Get()) == 0
  5354. }, 1000*time.Millisecond, 50*time.Millisecond)
  5355. err = os.Chmod(dirPath, 0555)
  5356. assert.NoError(t, err)
  5357. _, err = httpdtest.StartRetentionCheck(user.Username, folderRetention, http.StatusAccepted)
  5358. assert.NoError(t, err)
  5359. assert.Eventually(t, func() bool {
  5360. return len(common.RetentionChecks.Get()) == 0
  5361. }, 1000*time.Millisecond, 50*time.Millisecond)
  5362. err = os.Chmod(dirPath, os.ModePerm)
  5363. assert.NoError(t, err)
  5364. _, err = httpdtest.StartRetentionCheck(user.Username, folderRetention, http.StatusAccepted)
  5365. assert.NoError(t, err)
  5366. assert.Eventually(t, func() bool {
  5367. return len(common.RetentionChecks.Get()) == 0
  5368. }, 1000*time.Millisecond, 50*time.Millisecond)
  5369. assert.NoDirExists(t, dirPath)
  5370. }
  5371. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  5372. assert.NoError(t, err)
  5373. err = os.RemoveAll(user.GetHomeDir())
  5374. assert.NoError(t, err)
  5375. }
  5376. func TestRenameDir(t *testing.T) {
  5377. u := getTestUser()
  5378. testDir := "/dir-to-rename"
  5379. u.Permissions[testDir] = []string{dataprovider.PermListItems, dataprovider.PermUpload}
  5380. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  5381. assert.NoError(t, err)
  5382. conn, client, err := getSftpClient(user)
  5383. if assert.NoError(t, err) {
  5384. defer conn.Close()
  5385. defer client.Close()
  5386. err = client.Mkdir(testDir)
  5387. assert.NoError(t, err)
  5388. err = writeSFTPFile(path.Join(testDir, testFileName), 32, client)
  5389. assert.NoError(t, err)
  5390. err = client.Rename(testDir, testDir+"_rename")
  5391. assert.ErrorIs(t, err, os.ErrPermission)
  5392. }
  5393. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  5394. assert.NoError(t, err)
  5395. err = os.RemoveAll(user.GetHomeDir())
  5396. assert.NoError(t, err)
  5397. }
  5398. func TestBuiltinKeyboardInteractiveAuthentication(t *testing.T) {
  5399. u := getTestUser()
  5400. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  5401. assert.NoError(t, err)
  5402. authMethods := []ssh.AuthMethod{
  5403. ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) ([]string, error) {
  5404. return []string{defaultPassword}, nil
  5405. }),
  5406. }
  5407. conn, client, err := getCustomAuthSftpClient(user, authMethods)
  5408. if assert.NoError(t, err) {
  5409. defer conn.Close()
  5410. defer client.Close()
  5411. assert.NoError(t, checkBasicSFTP(client))
  5412. err = writeSFTPFile(testFileName, 4096, client)
  5413. assert.NoError(t, err)
  5414. }
  5415. // add multi-factor authentication
  5416. configName, _, secret, _, err := mfa.GenerateTOTPSecret(mfa.GetAvailableTOTPConfigNames()[0], user.Username)
  5417. assert.NoError(t, err)
  5418. user.Password = defaultPassword
  5419. user.Filters.TOTPConfig = dataprovider.UserTOTPConfig{
  5420. Enabled: true,
  5421. ConfigName: configName,
  5422. Secret: kms.NewPlainSecret(secret),
  5423. Protocols: []string{common.ProtocolSSH},
  5424. }
  5425. err = dataprovider.UpdateUser(&user, "", "")
  5426. assert.NoError(t, err)
  5427. passcode, err := generateTOTPPasscode(secret, otp.AlgorithmSHA1)
  5428. assert.NoError(t, err)
  5429. passwordAsked := false
  5430. passcodeAsked := false
  5431. authMethods = []ssh.AuthMethod{
  5432. ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) ([]string, error) {
  5433. var answers []string
  5434. if strings.HasPrefix(questions[0], "Password") {
  5435. answers = append(answers, defaultPassword)
  5436. passwordAsked = true
  5437. } else {
  5438. answers = append(answers, passcode)
  5439. passcodeAsked = true
  5440. }
  5441. return answers, nil
  5442. }),
  5443. }
  5444. conn, client, err = getCustomAuthSftpClient(user, authMethods)
  5445. if assert.NoError(t, err) {
  5446. defer conn.Close()
  5447. defer client.Close()
  5448. assert.NoError(t, checkBasicSFTP(client))
  5449. err = writeSFTPFile(testFileName, 4096, client)
  5450. assert.NoError(t, err)
  5451. }
  5452. assert.True(t, passwordAsked)
  5453. assert.True(t, passcodeAsked)
  5454. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  5455. assert.NoError(t, err)
  5456. err = os.RemoveAll(user.GetHomeDir())
  5457. assert.NoError(t, err)
  5458. }
  5459. func TestRenameSymlink(t *testing.T) {
  5460. u := getTestUser()
  5461. testDir := "/dir-no-create-links"
  5462. otherDir := "otherdir"
  5463. u.Permissions[testDir] = []string{dataprovider.PermListItems, dataprovider.PermUpload, dataprovider.PermDelete,
  5464. dataprovider.PermCreateDirs}
  5465. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  5466. assert.NoError(t, err)
  5467. conn, client, err := getSftpClient(user)
  5468. if assert.NoError(t, err) {
  5469. defer conn.Close()
  5470. defer client.Close()
  5471. err = client.Mkdir(otherDir)
  5472. assert.NoError(t, err)
  5473. err = client.Symlink(otherDir, otherDir+".link")
  5474. assert.NoError(t, err)
  5475. err = client.Rename(otherDir+".link", path.Join(testDir, "symlink"))
  5476. assert.ErrorIs(t, err, os.ErrPermission)
  5477. err = client.Rename(otherDir+".link", "allowed_link")
  5478. assert.NoError(t, err)
  5479. }
  5480. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  5481. assert.NoError(t, err)
  5482. err = os.RemoveAll(user.GetHomeDir())
  5483. assert.NoError(t, err)
  5484. }
  5485. func TestSplittedDeletePerms(t *testing.T) {
  5486. u := getTestUser()
  5487. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermUpload, dataprovider.PermDeleteDirs,
  5488. dataprovider.PermCreateDirs}
  5489. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  5490. assert.NoError(t, err)
  5491. conn, client, err := getSftpClient(user)
  5492. if assert.NoError(t, err) {
  5493. defer conn.Close()
  5494. defer client.Close()
  5495. err = writeSFTPFile(testFileName, 4096, client)
  5496. assert.NoError(t, err)
  5497. err = client.Remove(testFileName)
  5498. assert.Error(t, err)
  5499. err = client.Mkdir(testDir)
  5500. assert.NoError(t, err)
  5501. err = client.RemoveDirectory(testDir)
  5502. assert.NoError(t, err)
  5503. }
  5504. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermUpload, dataprovider.PermDeleteFiles,
  5505. dataprovider.PermCreateDirs, dataprovider.PermOverwrite}
  5506. _, _, err = httpdtest.UpdateUser(u, http.StatusOK, "")
  5507. assert.NoError(t, err)
  5508. conn, client, err = getSftpClient(user)
  5509. if assert.NoError(t, err) {
  5510. defer conn.Close()
  5511. defer client.Close()
  5512. err = writeSFTPFile(testFileName, 4096, client)
  5513. assert.NoError(t, err)
  5514. err = client.Remove(testFileName)
  5515. assert.NoError(t, err)
  5516. err = client.Mkdir(testDir)
  5517. assert.NoError(t, err)
  5518. err = client.RemoveDirectory(testDir)
  5519. assert.Error(t, err)
  5520. }
  5521. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  5522. assert.NoError(t, err)
  5523. err = os.RemoveAll(user.GetHomeDir())
  5524. assert.NoError(t, err)
  5525. }
  5526. func TestSplittedRenamePerms(t *testing.T) {
  5527. u := getTestUser()
  5528. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermUpload, dataprovider.PermRenameDirs,
  5529. dataprovider.PermCreateDirs}
  5530. user, _, err := httpdtest.AddUser(u, http.StatusCreated)
  5531. assert.NoError(t, err)
  5532. conn, client, err := getSftpClient(user)
  5533. if assert.NoError(t, err) {
  5534. defer conn.Close()
  5535. defer client.Close()
  5536. err = writeSFTPFile(testFileName, 4096, client)
  5537. assert.NoError(t, err)
  5538. err = client.Mkdir(testDir)
  5539. assert.NoError(t, err)
  5540. err = client.Rename(testFileName, testFileName+"_renamed")
  5541. assert.Error(t, err)
  5542. err = client.Rename(testDir, testDir+"_renamed")
  5543. assert.NoError(t, err)
  5544. }
  5545. u.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermUpload, dataprovider.PermRenameFiles,
  5546. dataprovider.PermCreateDirs, dataprovider.PermOverwrite}
  5547. _, _, err = httpdtest.UpdateUser(u, http.StatusOK, "")
  5548. assert.NoError(t, err)
  5549. conn, client, err = getSftpClient(user)
  5550. if assert.NoError(t, err) {
  5551. defer conn.Close()
  5552. defer client.Close()
  5553. err = writeSFTPFile(testFileName, 4096, client)
  5554. assert.NoError(t, err)
  5555. err = client.Mkdir(testDir)
  5556. assert.NoError(t, err)
  5557. err = client.Rename(testFileName, testFileName+"_renamed")
  5558. assert.NoError(t, err)
  5559. err = client.Rename(testDir, testDir+"_renamed")
  5560. assert.Error(t, err)
  5561. }
  5562. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  5563. assert.NoError(t, err)
  5564. err = os.RemoveAll(user.GetHomeDir())
  5565. assert.NoError(t, err)
  5566. }
  5567. func TestSFTPLoopError(t *testing.T) {
  5568. smtpCfg := smtp.Config{
  5569. Host: "127.0.0.1",
  5570. Port: 2525,
  5571. From: "notification@example.com",
  5572. TemplatesPath: "templates",
  5573. }
  5574. err := smtpCfg.Initialize(configDir)
  5575. require.NoError(t, err)
  5576. user1 := getTestUser()
  5577. user2 := getTestUser()
  5578. user1.Username += "1"
  5579. user2.Username += "2"
  5580. // user1 is a local account with a virtual SFTP folder to user2
  5581. // user2 has user1 as SFTP fs
  5582. user1.VirtualFolders = append(user1.VirtualFolders, vfs.VirtualFolder{
  5583. BaseVirtualFolder: vfs.BaseVirtualFolder{
  5584. Name: "sftp",
  5585. FsConfig: vfs.Filesystem{
  5586. Provider: sdk.SFTPFilesystemProvider,
  5587. SFTPConfig: vfs.SFTPFsConfig{
  5588. BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
  5589. Endpoint: sftpServerAddr,
  5590. Username: user2.Username,
  5591. },
  5592. Password: kms.NewPlainSecret(defaultPassword),
  5593. },
  5594. },
  5595. },
  5596. VirtualPath: "/vdir",
  5597. })
  5598. user2.FsConfig.Provider = sdk.SFTPFilesystemProvider
  5599. user2.FsConfig.SFTPConfig = vfs.SFTPFsConfig{
  5600. BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
  5601. Endpoint: sftpServerAddr,
  5602. Username: user1.Username,
  5603. },
  5604. Password: kms.NewPlainSecret(defaultPassword),
  5605. }
  5606. user1, resp, err := httpdtest.AddUser(user1, http.StatusCreated)
  5607. assert.NoError(t, err, string(resp))
  5608. user2, resp, err = httpdtest.AddUser(user2, http.StatusCreated)
  5609. assert.NoError(t, err, string(resp))
  5610. // test metadata check event error
  5611. a1 := dataprovider.BaseEventAction{
  5612. Name: "a1",
  5613. Type: dataprovider.ActionTypeMetadataCheck,
  5614. }
  5615. action1, _, err := httpdtest.AddEventAction(a1, http.StatusCreated)
  5616. assert.NoError(t, err)
  5617. a2 := dataprovider.BaseEventAction{
  5618. Name: "a2",
  5619. Type: dataprovider.ActionTypeEmail,
  5620. Options: dataprovider.BaseEventActionOptions{
  5621. EmailConfig: dataprovider.EventActionEmailConfig{
  5622. Recipients: []string{"failure@example.com"},
  5623. Subject: `Failed action"`,
  5624. Body: "Test body",
  5625. },
  5626. },
  5627. }
  5628. action2, _, err := httpdtest.AddEventAction(a2, http.StatusCreated)
  5629. assert.NoError(t, err)
  5630. r1 := dataprovider.EventRule{
  5631. Name: "rule1",
  5632. Trigger: dataprovider.EventTriggerProviderEvent,
  5633. Conditions: dataprovider.EventConditions{
  5634. ProviderEvents: []string{"update"},
  5635. },
  5636. Actions: []dataprovider.EventAction{
  5637. {
  5638. BaseEventAction: dataprovider.BaseEventAction{
  5639. Name: action1.Name,
  5640. },
  5641. Order: 1,
  5642. },
  5643. {
  5644. BaseEventAction: dataprovider.BaseEventAction{
  5645. Name: action2.Name,
  5646. },
  5647. Order: 2,
  5648. Options: dataprovider.EventActionOptions{
  5649. IsFailureAction: true,
  5650. },
  5651. },
  5652. },
  5653. }
  5654. rule1, _, err := httpdtest.AddEventRule(r1, http.StatusCreated)
  5655. assert.NoError(t, err)
  5656. lastReceivedEmail.reset()
  5657. _, _, err = httpdtest.UpdateUser(user2, http.StatusOK, "")
  5658. assert.NoError(t, err)
  5659. assert.Eventually(t, func() bool {
  5660. return lastReceivedEmail.get().From != ""
  5661. }, 3000*time.Millisecond, 100*time.Millisecond)
  5662. email := lastReceivedEmail.get()
  5663. assert.Len(t, email.To, 1)
  5664. assert.True(t, util.Contains(email.To, "failure@example.com"))
  5665. assert.Contains(t, email.Data, `Subject: Failed action`)
  5666. user1.VirtualFolders[0].FsConfig.SFTPConfig.Password = kms.NewPlainSecret(defaultPassword)
  5667. user2.FsConfig.SFTPConfig.Password = kms.NewPlainSecret(defaultPassword)
  5668. conn := common.NewBaseConnection("", common.ProtocolWebDAV, "", "", user1)
  5669. _, _, err = conn.GetFsAndResolvedPath(user1.VirtualFolders[0].VirtualPath)
  5670. assert.ErrorIs(t, err, os.ErrPermission)
  5671. conn = common.NewBaseConnection("", common.ProtocolSFTP, "", "", user1)
  5672. _, _, err = conn.GetFsAndResolvedPath(user1.VirtualFolders[0].VirtualPath)
  5673. if assert.Error(t, err) {
  5674. assert.Contains(t, err.Error(), "SFTP loop")
  5675. }
  5676. conn = common.NewBaseConnection("", common.ProtocolFTP, "", "", user1)
  5677. _, _, err = conn.GetFsAndResolvedPath(user1.VirtualFolders[0].VirtualPath)
  5678. if assert.Error(t, err) {
  5679. assert.Contains(t, err.Error(), "SFTP loop")
  5680. }
  5681. _, err = httpdtest.RemoveEventRule(rule1, http.StatusOK)
  5682. assert.NoError(t, err)
  5683. _, err = httpdtest.RemoveEventAction(action1, http.StatusOK)
  5684. assert.NoError(t, err)
  5685. _, err = httpdtest.RemoveEventAction(action2, http.StatusOK)
  5686. assert.NoError(t, err)
  5687. _, err = httpdtest.RemoveUser(user1, http.StatusOK)
  5688. assert.NoError(t, err)
  5689. err = os.RemoveAll(user1.GetHomeDir())
  5690. assert.NoError(t, err)
  5691. _, err = httpdtest.RemoveUser(user2, http.StatusOK)
  5692. assert.NoError(t, err)
  5693. err = os.RemoveAll(user2.GetHomeDir())
  5694. assert.NoError(t, err)
  5695. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: "sftp"}, http.StatusOK)
  5696. assert.NoError(t, err)
  5697. smtpCfg = smtp.Config{}
  5698. err = smtpCfg.Initialize(configDir)
  5699. require.NoError(t, err)
  5700. }
  5701. func TestNonLocalCrossRename(t *testing.T) {
  5702. baseUser, resp, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  5703. assert.NoError(t, err, string(resp))
  5704. u := getTestUser()
  5705. u.HomeDir += "_folders"
  5706. u.Username += "_folders"
  5707. mappedPathSFTP := filepath.Join(os.TempDir(), "sftp")
  5708. folderNameSFTP := filepath.Base(mappedPathSFTP)
  5709. vdirSFTPPath := "/vdir/sftp"
  5710. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  5711. BaseVirtualFolder: vfs.BaseVirtualFolder{
  5712. Name: folderNameSFTP,
  5713. FsConfig: vfs.Filesystem{
  5714. Provider: sdk.SFTPFilesystemProvider,
  5715. SFTPConfig: vfs.SFTPFsConfig{
  5716. BaseSFTPFsConfig: sdk.BaseSFTPFsConfig{
  5717. Endpoint: sftpServerAddr,
  5718. Username: baseUser.Username,
  5719. },
  5720. Password: kms.NewPlainSecret(defaultPassword),
  5721. },
  5722. },
  5723. },
  5724. VirtualPath: vdirSFTPPath,
  5725. })
  5726. mappedPathCrypt := filepath.Join(os.TempDir(), "crypt")
  5727. folderNameCrypt := filepath.Base(mappedPathCrypt)
  5728. vdirCryptPath := "/vdir/crypt"
  5729. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  5730. BaseVirtualFolder: vfs.BaseVirtualFolder{
  5731. Name: folderNameCrypt,
  5732. FsConfig: vfs.Filesystem{
  5733. Provider: sdk.CryptedFilesystemProvider,
  5734. CryptConfig: vfs.CryptFsConfig{
  5735. Passphrase: kms.NewPlainSecret(defaultPassword),
  5736. },
  5737. },
  5738. MappedPath: mappedPathCrypt,
  5739. },
  5740. VirtualPath: vdirCryptPath,
  5741. })
  5742. user, resp, err := httpdtest.AddUser(u, http.StatusCreated)
  5743. assert.NoError(t, err, string(resp))
  5744. conn, client, err := getSftpClient(user)
  5745. if assert.NoError(t, err) {
  5746. defer conn.Close()
  5747. defer client.Close()
  5748. assert.NoError(t, checkBasicSFTP(client))
  5749. err = writeSFTPFile(testFileName, 4096, client)
  5750. assert.NoError(t, err)
  5751. err = writeSFTPFile(path.Join(vdirSFTPPath, testFileName), 8192, client)
  5752. assert.NoError(t, err)
  5753. err = writeSFTPFile(path.Join(vdirCryptPath, testFileName), 16384, client)
  5754. assert.NoError(t, err)
  5755. err = client.Rename(path.Join(vdirSFTPPath, testFileName), path.Join(vdirCryptPath, testFileName+".rename"))
  5756. assert.ErrorIs(t, err, os.ErrPermission)
  5757. err = client.Rename(path.Join(vdirCryptPath, testFileName), path.Join(vdirSFTPPath, testFileName+".rename"))
  5758. assert.ErrorIs(t, err, os.ErrPermission)
  5759. err = client.Rename(testFileName, path.Join(vdirCryptPath, testFileName+".rename"))
  5760. assert.ErrorIs(t, err, os.ErrPermission)
  5761. err = client.Rename(testFileName, path.Join(vdirSFTPPath, testFileName+".rename"))
  5762. assert.ErrorIs(t, err, os.ErrPermission)
  5763. err = client.Rename(path.Join(vdirSFTPPath, testFileName), testFileName+".rename")
  5764. assert.ErrorIs(t, err, os.ErrPermission)
  5765. err = client.Rename(path.Join(vdirCryptPath, testFileName), testFileName+".rename")
  5766. assert.ErrorIs(t, err, os.ErrPermission)
  5767. // rename on local fs or on the same folder must work
  5768. err = client.Rename(testFileName, testFileName+".rename")
  5769. assert.NoError(t, err)
  5770. err = client.Rename(path.Join(vdirSFTPPath, testFileName), path.Join(vdirSFTPPath, testFileName+"_rename"))
  5771. assert.NoError(t, err)
  5772. err = client.Rename(path.Join(vdirCryptPath, testFileName), path.Join(vdirCryptPath, testFileName+"_rename"))
  5773. assert.NoError(t, err)
  5774. // renaming a virtual folder is not allowed
  5775. err = client.Rename(vdirSFTPPath, vdirSFTPPath+"_rename")
  5776. assert.ErrorIs(t, err, os.ErrPermission)
  5777. err = client.Rename(vdirCryptPath, vdirCryptPath+"_rename")
  5778. assert.ErrorIs(t, err, os.ErrPermission)
  5779. err = client.Rename(vdirCryptPath, path.Join(vdirCryptPath, "rename"))
  5780. assert.ErrorIs(t, err, os.ErrPermission)
  5781. err = client.Mkdir(path.Join(vdirCryptPath, "subcryptdir"))
  5782. assert.NoError(t, err)
  5783. err = client.Rename(path.Join(vdirCryptPath, "subcryptdir"), vdirCryptPath)
  5784. assert.ErrorIs(t, err, os.ErrPermission)
  5785. // renaming root folder is not allowed
  5786. err = client.Rename("/", "new_name")
  5787. assert.ErrorIs(t, err, os.ErrPermission)
  5788. // renaming a path to a virtual folder is not allowed
  5789. err = client.Rename("/vdir", "new_vdir")
  5790. if assert.Error(t, err) {
  5791. assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
  5792. }
  5793. }
  5794. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  5795. assert.NoError(t, err)
  5796. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderNameCrypt}, http.StatusOK)
  5797. assert.NoError(t, err)
  5798. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderNameSFTP}, http.StatusOK)
  5799. assert.NoError(t, err)
  5800. _, err = httpdtest.RemoveUser(baseUser, http.StatusOK)
  5801. assert.NoError(t, err)
  5802. err = os.RemoveAll(user.GetHomeDir())
  5803. assert.NoError(t, err)
  5804. err = os.RemoveAll(baseUser.GetHomeDir())
  5805. assert.NoError(t, err)
  5806. err = os.RemoveAll(mappedPathCrypt)
  5807. assert.NoError(t, err)
  5808. err = os.RemoveAll(mappedPathSFTP)
  5809. assert.NoError(t, err)
  5810. }
  5811. func TestNonLocalCrossRenameNonLocalBaseUser(t *testing.T) {
  5812. baseUser, resp, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
  5813. assert.NoError(t, err, string(resp))
  5814. u := getTestSFTPUser()
  5815. mappedPathLocal := filepath.Join(os.TempDir(), "local")
  5816. folderNameLocal := filepath.Base(mappedPathLocal)
  5817. vdirLocalPath := "/vdir/local"
  5818. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  5819. BaseVirtualFolder: vfs.BaseVirtualFolder{
  5820. Name: folderNameLocal,
  5821. MappedPath: mappedPathLocal,
  5822. },
  5823. VirtualPath: vdirLocalPath,
  5824. })
  5825. mappedPathCrypt := filepath.Join(os.TempDir(), "crypt")
  5826. folderNameCrypt := filepath.Base(mappedPathCrypt)
  5827. vdirCryptPath := "/vdir/crypt"
  5828. u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
  5829. BaseVirtualFolder: vfs.BaseVirtualFolder{
  5830. Name: folderNameCrypt,
  5831. FsConfig: vfs.Filesystem{
  5832. Provider: sdk.CryptedFilesystemProvider,
  5833. CryptConfig: vfs.CryptFsConfig{
  5834. Passphrase: kms.NewPlainSecret(defaultPassword),
  5835. },
  5836. },
  5837. MappedPath: mappedPathCrypt,
  5838. },
  5839. VirtualPath: vdirCryptPath,
  5840. })
  5841. user, resp, err := httpdtest.AddUser(u, http.StatusCreated)
  5842. assert.NoError(t, err, string(resp))
  5843. conn, client, err := getSftpClient(user)
  5844. if assert.NoError(t, err) {
  5845. defer conn.Close()
  5846. defer client.Close()
  5847. assert.NoError(t, checkBasicSFTP(client))
  5848. err = writeSFTPFile(testFileName, 4096, client)
  5849. assert.NoError(t, err)
  5850. err = writeSFTPFile(path.Join(vdirLocalPath, testFileName), 8192, client)
  5851. assert.NoError(t, err)
  5852. err = writeSFTPFile(path.Join(vdirCryptPath, testFileName), 16384, client)
  5853. assert.NoError(t, err)
  5854. err = client.Rename(path.Join(vdirLocalPath, testFileName), path.Join(vdirCryptPath, testFileName+".rename"))
  5855. assert.ErrorIs(t, err, os.ErrPermission)
  5856. err = client.Rename(path.Join(vdirCryptPath, testFileName), path.Join(vdirLocalPath, testFileName+".rename"))
  5857. assert.ErrorIs(t, err, os.ErrPermission)
  5858. err = client.Rename(testFileName, path.Join(vdirCryptPath, testFileName+".rename"))
  5859. assert.ErrorIs(t, err, os.ErrPermission)
  5860. err = client.Rename(testFileName, path.Join(vdirLocalPath, testFileName+".rename"))
  5861. assert.ErrorIs(t, err, os.ErrPermission)
  5862. err = client.Rename(path.Join(vdirLocalPath, testFileName), testFileName+".rename")
  5863. assert.ErrorIs(t, err, os.ErrPermission)
  5864. err = client.Rename(path.Join(vdirCryptPath, testFileName), testFileName+".rename")
  5865. assert.ErrorIs(t, err, os.ErrPermission)
  5866. // rename on local fs or on the same folder must work
  5867. err = client.Rename(testFileName, testFileName+".rename")
  5868. assert.NoError(t, err)
  5869. err = client.Rename(path.Join(vdirLocalPath, testFileName), path.Join(vdirLocalPath, testFileName+"_rename"))
  5870. assert.NoError(t, err)
  5871. err = client.Rename(path.Join(vdirCryptPath, testFileName), path.Join(vdirCryptPath, testFileName+"_rename"))
  5872. assert.NoError(t, err)
  5873. // renaming a virtual folder is not allowed
  5874. err = client.Rename(vdirLocalPath, vdirLocalPath+"_rename")
  5875. assert.ErrorIs(t, err, os.ErrPermission)
  5876. err = client.Rename(vdirCryptPath, vdirCryptPath+"_rename")
  5877. assert.ErrorIs(t, err, os.ErrPermission)
  5878. // renaming root folder is not allowed
  5879. err = client.Rename("/", "new_name")
  5880. assert.ErrorIs(t, err, os.ErrPermission)
  5881. // renaming a path to a virtual folder is not allowed
  5882. err = client.Rename("/vdir", "new_vdir")
  5883. if assert.Error(t, err) {
  5884. assert.Contains(t, err.Error(), "SSH_FX_OP_UNSUPPORTED")
  5885. }
  5886. }
  5887. _, err = httpdtest.RemoveUser(user, http.StatusOK)
  5888. assert.NoError(t, err)
  5889. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderNameCrypt}, http.StatusOK)
  5890. assert.NoError(t, err)
  5891. _, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderNameLocal}, http.StatusOK)
  5892. assert.NoError(t, err)
  5893. _, err = httpdtest.RemoveUser(baseUser, http.StatusOK)
  5894. assert.NoError(t, err)
  5895. err = os.RemoveAll(user.GetHomeDir())
  5896. assert.NoError(t, err)
  5897. err = os.RemoveAll(baseUser.GetHomeDir())
  5898. assert.NoError(t, err)
  5899. err = os.RemoveAll(mappedPathCrypt)
  5900. assert.NoError(t, err)
  5901. err = os.RemoveAll(mappedPathLocal)
  5902. assert.NoError(t, err)
  5903. }
  5904. func TestProxyProtocol(t *testing.T) {
  5905. resp, err := httpclient.Get(fmt.Sprintf("http://%v", httpProxyAddr))
  5906. if assert.NoError(t, err) {
  5907. defer resp.Body.Close()
  5908. assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
  5909. }
  5910. }
  5911. func TestSetProtocol(t *testing.T) {
  5912. conn := common.NewBaseConnection("id", "sshd_exec", "", "", dataprovider.User{BaseUser: sdk.BaseUser{HomeDir: os.TempDir()}})
  5913. conn.SetProtocol(common.ProtocolSCP)
  5914. require.Equal(t, "SCP_id", conn.GetID())
  5915. }
  5916. func TestGetFsError(t *testing.T) {
  5917. u := getTestUser()
  5918. u.FsConfig.Provider = sdk.GCSFilesystemProvider
  5919. u.FsConfig.GCSConfig.Bucket = "test"
  5920. u.FsConfig.GCSConfig.Credentials = kms.NewPlainSecret("invalid JSON for credentials")
  5921. conn := common.NewBaseConnection("", common.ProtocolFTP, "", "", u)
  5922. _, _, err := conn.GetFsAndResolvedPath("/vpath")
  5923. assert.Error(t, err)
  5924. }
  5925. func waitTCPListening(address string) {
  5926. for {
  5927. conn, err := net.Dial("tcp", address)
  5928. if err != nil {
  5929. logger.WarnToConsole("tcp server %v not listening: %v", address, err)
  5930. time.Sleep(100 * time.Millisecond)
  5931. continue
  5932. }
  5933. logger.InfoToConsole("tcp server %v now listening", address)
  5934. conn.Close()
  5935. break
  5936. }
  5937. }
  5938. func checkBasicSFTP(client *sftp.Client) error {
  5939. _, err := client.Getwd()
  5940. if err != nil {
  5941. return err
  5942. }
  5943. _, err = client.ReadDir(".")
  5944. return err
  5945. }
  5946. func getCustomAuthSftpClient(user dataprovider.User, authMethods []ssh.AuthMethod) (*ssh.Client, *sftp.Client, error) {
  5947. var sftpClient *sftp.Client
  5948. config := &ssh.ClientConfig{
  5949. User: user.Username,
  5950. HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
  5951. return nil
  5952. },
  5953. Auth: authMethods,
  5954. }
  5955. conn, err := ssh.Dial("tcp", sftpServerAddr, config)
  5956. if err != nil {
  5957. return conn, sftpClient, err
  5958. }
  5959. sftpClient, err = sftp.NewClient(conn)
  5960. if err != nil {
  5961. conn.Close()
  5962. }
  5963. return conn, sftpClient, err
  5964. }
  5965. func getSftpClient(user dataprovider.User) (*ssh.Client, *sftp.Client, error) {
  5966. var sftpClient *sftp.Client
  5967. config := &ssh.ClientConfig{
  5968. User: user.Username,
  5969. HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
  5970. return nil
  5971. },
  5972. }
  5973. if user.Password != "" {
  5974. config.Auth = []ssh.AuthMethod{ssh.Password(user.Password)}
  5975. } else {
  5976. config.Auth = []ssh.AuthMethod{ssh.Password(defaultPassword)}
  5977. }
  5978. conn, err := ssh.Dial("tcp", sftpServerAddr, config)
  5979. if err != nil {
  5980. return conn, sftpClient, err
  5981. }
  5982. sftpClient, err = sftp.NewClient(conn)
  5983. if err != nil {
  5984. conn.Close()
  5985. }
  5986. return conn, sftpClient, err
  5987. }
  5988. func getTestUser() dataprovider.User {
  5989. user := dataprovider.User{
  5990. BaseUser: sdk.BaseUser{
  5991. Username: defaultUsername,
  5992. Password: defaultPassword,
  5993. HomeDir: filepath.Join(homeBasePath, defaultUsername),
  5994. Status: 1,
  5995. ExpirationDate: 0,
  5996. },
  5997. }
  5998. user.Permissions = make(map[string][]string)
  5999. user.Permissions["/"] = allPerms
  6000. return user
  6001. }
  6002. func getTestSFTPUser() dataprovider.User {
  6003. u := getTestUser()
  6004. u.Username = defaultSFTPUsername
  6005. u.FsConfig.Provider = sdk.SFTPFilesystemProvider
  6006. u.FsConfig.SFTPConfig.Endpoint = sftpServerAddr
  6007. u.FsConfig.SFTPConfig.Username = defaultUsername
  6008. u.FsConfig.SFTPConfig.Password = kms.NewPlainSecret(defaultPassword)
  6009. return u
  6010. }
  6011. func getCryptFsUser() dataprovider.User {
  6012. u := getTestUser()
  6013. u.Username += "_crypt"
  6014. u.FsConfig.Provider = sdk.CryptedFilesystemProvider
  6015. u.FsConfig.CryptConfig.Passphrase = kms.NewPlainSecret(defaultPassword)
  6016. return u
  6017. }
  6018. func writeSFTPFile(name string, size int64, client *sftp.Client) error {
  6019. err := writeSFTPFileNoCheck(name, size, client)
  6020. if err != nil {
  6021. return err
  6022. }
  6023. info, err := client.Stat(name)
  6024. if err != nil {
  6025. return err
  6026. }
  6027. if info.Size() != size {
  6028. return fmt.Errorf("file size mismatch, wanted %v, actual %v", size, info.Size())
  6029. }
  6030. return nil
  6031. }
  6032. func writeSFTPFileNoCheck(name string, size int64, client *sftp.Client) error {
  6033. content := make([]byte, size)
  6034. _, err := rand.Read(content)
  6035. if err != nil {
  6036. return err
  6037. }
  6038. f, err := client.Create(name)
  6039. if err != nil {
  6040. return err
  6041. }
  6042. _, err = io.Copy(f, bytes.NewBuffer(content))
  6043. if err != nil {
  6044. f.Close()
  6045. return err
  6046. }
  6047. return f.Close()
  6048. }
  6049. func getUploadScriptContent(movedPath, logFilePath string, exitStatus int) []byte {
  6050. content := []byte("#!/bin/sh\n\n")
  6051. content = append(content, []byte("sleep 1\n")...)
  6052. if logFilePath != "" {
  6053. content = append(content, []byte(fmt.Sprintf("echo $@ > %v\n", logFilePath))...)
  6054. }
  6055. content = append(content, []byte(fmt.Sprintf("mv ${SFTPGO_ACTION_PATH} %v\n", movedPath))...)
  6056. content = append(content, []byte(fmt.Sprintf("exit %d", exitStatus))...)
  6057. return content
  6058. }
  6059. func getSaveProviderObjectScriptContent(outFilePath string, exitStatus int) []byte {
  6060. content := []byte("#!/bin/sh\n\n")
  6061. content = append(content, []byte(fmt.Sprintf("echo ${SFTPGO_OBJECT_DATA} > %v\n", outFilePath))...)
  6062. content = append(content, []byte(fmt.Sprintf("exit %d", exitStatus))...)
  6063. return content
  6064. }
  6065. func generateTOTPPasscode(secret string, algo otp.Algorithm) (string, error) {
  6066. return totp.GenerateCodeCustom(secret, time.Now(), totp.ValidateOpts{
  6067. Period: 30,
  6068. Skew: 1,
  6069. Digits: otp.DigitsSix,
  6070. Algorithm: algo,
  6071. })
  6072. }
  6073. func isDbDefenderSupported() bool {
  6074. // SQLite shares the implementation with other SQL-based provider but it makes no sense
  6075. // to use it outside test cases
  6076. switch dataprovider.GetProviderStatus().Driver {
  6077. case dataprovider.MySQLDataProviderName, dataprovider.PGSQLDataProviderName,
  6078. dataprovider.CockroachDataProviderName, dataprovider.SQLiteDataProviderName:
  6079. return true
  6080. default:
  6081. return false
  6082. }
  6083. }
  6084. func getEncryptedFileSize(size int64) (int64, error) {
  6085. encSize, err := sio.EncryptedSize(uint64(size))
  6086. return int64(encSize) + 33, err
  6087. }
  6088. func printLatestLogs(maxNumberOfLines int) {
  6089. var lines []string
  6090. f, err := os.Open(logFilePath)
  6091. if err != nil {
  6092. return
  6093. }
  6094. defer f.Close()
  6095. scanner := bufio.NewScanner(f)
  6096. for scanner.Scan() {
  6097. lines = append(lines, scanner.Text()+"\r\n")
  6098. for len(lines) > maxNumberOfLines {
  6099. lines = lines[1:]
  6100. }
  6101. }
  6102. if scanner.Err() != nil {
  6103. logger.WarnToConsole("Unable to print latest logs: %v", scanner.Err())
  6104. return
  6105. }
  6106. for _, line := range lines {
  6107. logger.DebugToConsole(line)
  6108. }
  6109. }
  6110. type receivedEmail struct {
  6111. sync.RWMutex
  6112. From string
  6113. To []string
  6114. Data string
  6115. }
  6116. func (e *receivedEmail) set(from string, to []string, data []byte) {
  6117. e.Lock()
  6118. defer e.Unlock()
  6119. e.From = from
  6120. e.To = to
  6121. e.Data = strings.ReplaceAll(string(data), "=\r\n", "")
  6122. }
  6123. func (e *receivedEmail) reset() {
  6124. e.Lock()
  6125. defer e.Unlock()
  6126. e.From = ""
  6127. e.To = nil
  6128. e.Data = ""
  6129. }
  6130. func (e *receivedEmail) get() receivedEmail {
  6131. e.RLock()
  6132. defer e.RUnlock()
  6133. return receivedEmail{
  6134. From: e.From,
  6135. To: e.To,
  6136. Data: e.Data,
  6137. }
  6138. }