test_pagure_flask_ui_repo.py 244 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014
  1. # -*- coding: utf-8 -*-
  2. """
  3. (c) 2015-2017 - Copyright Red Hat Inc
  4. Authors:
  5. Pierre-Yves Chibon <pingou@pingoured.fr>
  6. """
  7. from __future__ import unicode_literals
  8. __requires__ = ['SQLAlchemy >= 0.8']
  9. import pkg_resources
  10. import datetime
  11. import json
  12. import unittest
  13. import re
  14. import shutil
  15. import sys
  16. import tempfile
  17. import time
  18. import os
  19. import pygit2
  20. from mock import ANY, patch, MagicMock
  21. sys.path.insert(0, os.path.join(os.path.dirname(
  22. os.path.abspath(__file__)), '..'))
  23. import pagure.lib.query
  24. import tests
  25. from pagure.lib.repo import PagureRepo
  26. class PagureFlaskRepotests(tests.Modeltests):
  27. """ Tests for flask app controller of pagure """
  28. def setUp(self):
  29. """ Set up the environnment, ran before every tests. """
  30. super(PagureFlaskRepotests, self).setUp()
  31. pagure.config.config['VIRUS_SCAN_ATTACHMENTS'] = False
  32. pagure.config.config['UPLOAD_FOLDER_URL'] = '/releases/'
  33. pagure.config.config['UPLOAD_FOLDER_PATH'] = os.path.join(
  34. self.path, 'releases')
  35. @patch('pagure.decorators.admin_session_timedout')
  36. def test_add_user_when_user_mngt_off(self, ast):
  37. """ Test the add_user endpoint when user management is turned off
  38. in the pagure instance """
  39. pagure.config.config['ENABLE_USER_MNGT'] = False
  40. ast.return_value = False
  41. # No Git repo
  42. output = self.app.get('/foo/adduser')
  43. self.assertEqual(output.status_code, 404)
  44. tests.create_projects(self.session)
  45. tests.create_projects_git(os.path.join(self.path, 'repos'))
  46. # User not logged in
  47. output = self.app.get('/test/adduser')
  48. self.assertEqual(output.status_code, 302)
  49. user = tests.FakeUser(username='pingou')
  50. with tests.user_set(self.app.application, user):
  51. output = self.app.get('/test/adduser')
  52. self.assertEqual(output.status_code, 404)
  53. #just get the csrf token
  54. pagure.config.config['ENABLE_USER_MNGT'] = True
  55. output = self.app.get('/test/adduser')
  56. output_text = output.get_data(as_text=True)
  57. csrf_token = output_text.split(
  58. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  59. pagure.config.config['ENABLE_USER_MNGT'] = False
  60. data = {
  61. 'user': 'ralph',
  62. }
  63. output = self.app.post('/test/adduser', data=data)
  64. self.assertEqual(output.status_code, 404)
  65. data['csrf_token'] = csrf_token
  66. output = self.app.post('/test/adduser', data=data)
  67. self.assertEqual(output.status_code, 404)
  68. data['user'] = 'foo'
  69. tests.create_projects_git(os.path.join(self.path, 'repos'))
  70. output = self.app.post(
  71. '/test/adduser', data=data, follow_redirects=True)
  72. self.assertEqual(output.status_code, 404)
  73. pagure.config.config['ENABLE_USER_MNGT'] = True
  74. @patch('pagure.decorators.admin_session_timedout')
  75. def test_add_deploykey(self, ast):
  76. """ Test the add_deploykey endpoint. """
  77. ast.return_value = False
  78. # No git repo
  79. output = self.app.get('/foo/adddeploykey')
  80. self.assertEqual(output.status_code, 404)
  81. tests.create_projects(self.session)
  82. tests.create_projects_git(os.path.join(self.path, 'repos'))
  83. # User not logged in
  84. output = self.app.get('/test/adddeploykey')
  85. self.assertEqual(output.status_code, 302)
  86. user = tests.FakeUser()
  87. with tests.user_set(self.app.application, user):
  88. output = self.app.get('/test/adddeploykey')
  89. self.assertEqual(output.status_code, 403)
  90. ast.return_value = True
  91. output = self.app.get('/test/adddeploykey')
  92. self.assertEqual(output.status_code, 302)
  93. # Redirect also happens for POST request
  94. output = self.app.post('/test/adddeploykey')
  95. self.assertEqual(output.status_code, 302)
  96. # Need to do this un-authentified since our fake user isn't in the DB
  97. # Check the message flashed during the redirect
  98. output = self.app.get('/', follow_redirects=True)
  99. self.assertEqual(output.status_code, 200)
  100. output_text = output.get_data(as_text=True)
  101. self.assertIn(
  102. 'Action canceled, try it '
  103. 'again', output_text)
  104. ast.return_value = False
  105. user.username = 'pingou'
  106. with tests.user_set(self.app.application, user):
  107. output = self.app.get('/test/adddeploykey')
  108. self.assertEqual(output.status_code, 200)
  109. output_text = output.get_data(as_text=True)
  110. self.assertIn('<strong>Add deploy key to the', output_text)
  111. csrf_token = output_text.split(
  112. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  113. data = {
  114. 'ssh_key': 'asdf',
  115. 'pushaccess': 'false'
  116. }
  117. # No CSRF token
  118. output = self.app.post('/test/adddeploykey', data=data)
  119. self.assertEqual(output.status_code, 200)
  120. output_text = output.get_data(as_text=True)
  121. self.assertIn('<strong>Add deploy key to the', output_text)
  122. data['csrf_token'] = csrf_token
  123. # First, invalid SSH key
  124. output = self.app.post('/test/adddeploykey', data=data)
  125. self.assertEqual(output.status_code, 200)
  126. output_text = output.get_data(as_text=True)
  127. self.assertIn('<strong>Add deploy key to the', output_text)
  128. self.assertIn('SSH key invalid', output_text)
  129. # Next up, multiple SSH keys
  130. data['ssh_key'] = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAzBMSIlvPRaEiLOTVInErkRIw9CzQQcnslDekAn1jFnGf+SNa1acvbTiATbCX71AA03giKrPxPH79dxcC7aDXerc6zRcKjJs6MAL9PrCjnbyxCKXRNNZU5U9X/DLaaL1b3caB+WD6OoorhS3LTEtKPX8xyjOzhf3OQSzNjhJp5Q==\nssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAzBMSIlvPRaEiLOTVInErkRIw9CzQQcnslDekAn1jFnGf+SNa1acvbTiATbCX71AA03giKrPxPH79dxcC7aDXerc6zRcKjJs6MAL9PrCjnbyxCKXRNNZU5U9X/DLaaL1b3caB+WD6OoorhS3LTEtKPX8xyjOzhf3OQSzNjhJp5Q=='
  131. output = self.app.post(
  132. '/test/adddeploykey', data=data, follow_redirects=True)
  133. self.assertEqual(output.status_code, 200)
  134. output_text = output.get_data(as_text=True)
  135. self.assertIn('Please add single SSH keys.', output_text)
  136. # Now, a valid SSH key
  137. data['ssh_key'] = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAzBMSIlvPRaEiLOTVInErkRIw9CzQQcnslDekAn1jFnGf+SNa1acvbTiATbCX71AA03giKrPxPH79dxcC7aDXerc6zRcKjJs6MAL9PrCjnbyxCKXRNNZU5U9X/DLaaL1b3caB+WD6OoorhS3LTEtKPX8xyjOzhf3OQSzNjhJp5Q=='
  138. output = self.app.post(
  139. '/test/adddeploykey', data=data, follow_redirects=True)
  140. self.assertEqual(output.status_code, 200)
  141. output_text = output.get_data(as_text=True)
  142. self.assertIn(
  143. '<title>Settings - test - Pagure</title>', output_text)
  144. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  145. self.assertIn('SSH key added', output_text)
  146. self.assertNotIn('Push Access', output_text)
  147. # And now, adding the same key
  148. output = self.app.post(
  149. '/test/adddeploykey', data=data, follow_redirects=True)
  150. self.assertEqual(output.status_code, 200)
  151. output_text = output.get_data(as_text=True)
  152. self.assertIn('SSH key already exists', output_text)
  153. # And next, a key with push access
  154. data['ssh_key'] = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC9Xwc2RDzPBhlEDARfHldGjudIVoa04tqT1JVKGQmyllTFz7Rb8CngQL3e7zyNzotnhwYKHdoiLlPkVEiDee4dWMUe48ilqId+FJZQGhyv8fu4BoFdE1AJUVylzmltbLg14VqG5gjTpXgtlrEva9arKwBMHJjRYc8ScaSn3OgyQw=='
  155. data['pushaccess'] = 'true'
  156. output = self.app.post(
  157. '/test/adddeploykey', data=data, follow_redirects=True)
  158. self.assertEqual(output.status_code, 200)
  159. output_text = output.get_data(as_text=True)
  160. self.assertIn(
  161. '<title>Settings - test - Pagure</title>', output_text)
  162. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  163. self.assertIn('SSH key added', output_text)
  164. self.assertIn('Push Access', output_text)
  165. @patch('pagure.decorators.admin_session_timedout')
  166. @patch.dict('pagure.config.config', {'DEPLOY_KEY': False})
  167. def test_add_deploykey_disabled(self, ast):
  168. """ Test the add_deploykey endpoint when it's disabled in the config.
  169. """
  170. ast.return_value = False
  171. tests.create_projects(self.session)
  172. tests.create_projects_git(os.path.join(self.path, 'repos'))
  173. user = tests.FakeUser(username='pingou')
  174. with tests.user_set(self.app.application, user):
  175. output = self.app.get('/test/adddeploykey')
  176. self.assertEqual(output.status_code, 404)
  177. output = self.app.post('/test/adddeploykey')
  178. self.assertEqual(output.status_code, 404)
  179. @patch('pagure.decorators.admin_session_timedout')
  180. @patch('pagure.lib.notify.log')
  181. def test_add_user(self, mock_log, ast):
  182. """ Test the add_user endpoint. """
  183. ast.return_value = False
  184. # No git repo
  185. output = self.app.get('/foo/adduser')
  186. self.assertEqual(output.status_code, 404)
  187. tests.create_projects(self.session)
  188. tests.create_projects_git(os.path.join(self.path, 'repos'))
  189. # User not logged in
  190. output = self.app.get('/test/adduser')
  191. self.assertEqual(output.status_code, 302)
  192. user = tests.FakeUser()
  193. with tests.user_set(self.app.application, user):
  194. output = self.app.get('/test/adduser')
  195. self.assertEqual(output.status_code, 403)
  196. ast.return_value = True
  197. output = self.app.get('/test/adduser')
  198. self.assertEqual(output.status_code, 302)
  199. # Redirect also happens for POST request
  200. output = self.app.post('/test/adduser')
  201. self.assertEqual(output.status_code, 302)
  202. # Need to do this un-authentified since our fake user isn't in the DB
  203. # Check the message flashed during the redirect
  204. output = self.app.get('/', follow_redirects=True)
  205. self.assertEqual(output.status_code, 200)
  206. output_text = output.get_data(as_text=True)
  207. self.assertIn(
  208. 'Action canceled, try it '
  209. 'again', output_text)
  210. ast.return_value = False
  211. user.username = 'pingou'
  212. with tests.user_set(self.app.application, user):
  213. output = self.app.get('/test/adduser')
  214. self.assertEqual(output.status_code, 200)
  215. output_text = output.get_data(as_text=True)
  216. self.assertIn('<strong>Add user to the', output_text)
  217. csrf_token = output_text.split(
  218. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  219. data = {
  220. 'user': 'ralph',
  221. }
  222. # Missing access and no CSRF
  223. output = self.app.post('/test/adduser', data=data)
  224. self.assertEqual(output.status_code, 200)
  225. output_text = output.get_data(as_text=True)
  226. self.assertIn(
  227. '<title>Add user - test - Pagure</title>', output_text)
  228. self.assertIn('<strong>Add user to the', output_text)
  229. # No CSRF
  230. output = self.app.post('/test/adduser', data=data)
  231. self.assertEqual(output.status_code, 200)
  232. output_text = output.get_data(as_text=True)
  233. self.assertIn(
  234. '<title>Add user - test - Pagure</title>', output_text)
  235. # Missing access
  236. data['csrf_token'] = csrf_token
  237. output = self.app.post('/test/adduser', data=data)
  238. self.assertEqual(output.status_code, 200)
  239. output_text = output.get_data(as_text=True)
  240. self.assertIn(
  241. '<title>Add user - test - Pagure</title>', output_text)
  242. self.assertIn('<strong>Add user to the', output_text)
  243. # Unknown user
  244. data['access'] = 'commit'
  245. output = self.app.post('/test/adduser', data=data)
  246. self.assertEqual(output.status_code, 200)
  247. output_text = output.get_data(as_text=True)
  248. self.assertIn(
  249. '<title>Add user - test - Pagure</title>', output_text)
  250. self.assertIn('<strong>Add user to the', output_text)
  251. self.assertIn(
  252. 'No user &#34;ralph&#34; found',
  253. output_text)
  254. # All correct
  255. data['user'] = 'foo'
  256. output = self.app.post(
  257. '/test/adduser', data=data, follow_redirects=True)
  258. self.assertEqual(output.status_code, 200)
  259. output_text = output.get_data(as_text=True)
  260. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  261. self.assertIn(
  262. 'User added', output_text)
  263. mock_log.assert_called_with(ANY, topic='project.user.added', msg=ANY)
  264. @patch('pagure.decorators.admin_session_timedout')
  265. def test_add_group_project_when_user_mngt_off(self, ast):
  266. """ Test the add_group_project endpoint when user management is
  267. turned off in the pagure instance"""
  268. pagure.config.config['ENABLE_USER_MNGT'] = False
  269. ast.return_value = False
  270. # No Git repo
  271. output = self.app.get('/foo/addgroup')
  272. self.assertEqual(output.status_code, 404)
  273. tests.create_projects(self.session)
  274. tests.create_projects_git(os.path.join(self.path, 'repos'))
  275. # User not logged in
  276. output = self.app.get('/test/addgroup')
  277. self.assertEqual(output.status_code, 302)
  278. msg = pagure.lib.query.add_group(
  279. self.session,
  280. group_name='foo',
  281. group_type='bar',
  282. display_name='foo group',
  283. description=None,
  284. user='pingou',
  285. is_admin=False,
  286. blacklist=pagure.config.config['BLACKLISTED_GROUPS'],
  287. )
  288. self.session.commit()
  289. self.assertEqual(msg, 'User `pingou` added to the group `foo`.')
  290. user = tests.FakeUser(username='pingou')
  291. with tests.user_set(self.app.application, user):
  292. #just get the csrf token
  293. pagure.config.config['ENABLE_USER_MNGT'] = True
  294. output = self.app.get('/test/addgroup')
  295. output_text = output.get_data(as_text=True)
  296. csrf_token = output_text.split(
  297. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  298. pagure.config.config['ENABLE_USER_MNGT'] = False
  299. data = {
  300. 'group': 'ralph',
  301. }
  302. output = self.app.post('/test/addgroup', data=data)
  303. self.assertEqual(output.status_code, 404)
  304. data['csrf_token'] = csrf_token
  305. output = self.app.post('/test/addgroup', data=data)
  306. self.assertEqual(output.status_code, 404)
  307. data['group'] = 'foo'
  308. output = self.app.post(
  309. '/test/addgroup', data=data, follow_redirects=True)
  310. self.assertEqual(output.status_code, 404)
  311. pagure.config.config['ENABLE_USER_MNGT'] = True
  312. @patch.dict('pagure.config.config', {'ENABLE_GROUP_MNGT': False})
  313. @patch('pagure.decorators.admin_session_timedout')
  314. def test_add_group_project_grp_mngt_off(self, ast):
  315. """ Test the add_group_project endpoint when group management is
  316. turned off in the pagure instance"""
  317. ast.return_value = False
  318. tests.create_projects(self.session)
  319. tests.create_projects_git(os.path.join(self.path, 'repos'))
  320. user = tests.FakeUser(username='pingou')
  321. with tests.user_set(self.app.application, user):
  322. data = {
  323. 'group': 'ralph',
  324. 'access': 'ticket',
  325. 'csrf_token': self.get_csrf(),
  326. }
  327. output = self.app.post(
  328. '/test/addgroup', data=data, follow_redirects=True)
  329. self.assertEqual(output.status_code, 200)
  330. output_text = output.get_data(as_text=True)
  331. self.assertIn(
  332. '<title>Add group - test - Pagure</title>',
  333. output_text)
  334. self.assertIn('No group ralph found.', output_text)
  335. @patch('pagure.decorators.admin_session_timedout')
  336. def test_add_group_project(self, ast):
  337. """ Test the add_group_project endpoint. """
  338. ast.return_value = False
  339. # No Git repo
  340. output = self.app.get('/foo/addgroup')
  341. self.assertEqual(output.status_code, 404)
  342. tests.create_projects(self.session)
  343. tests.create_projects_git(os.path.join(self.path, 'repos'))
  344. # User not logged in
  345. output = self.app.get('/test/addgroup')
  346. self.assertEqual(output.status_code, 302)
  347. user = tests.FakeUser()
  348. with tests.user_set(self.app.application, user):
  349. output = self.app.get('/test/addgroup')
  350. self.assertEqual(output.status_code, 403)
  351. ast.return_value = True
  352. output = self.app.get('/test/addgroup')
  353. self.assertEqual(output.status_code, 302)
  354. # Redirect also happens for POST request
  355. output = self.app.post('/test/addgroup')
  356. self.assertEqual(output.status_code, 302)
  357. # Need to do this un-authentified since our fake user isn't in the DB
  358. # Check the message flashed during the redirect
  359. output = self.app.get('/', follow_redirects=True)
  360. self.assertEqual(output.status_code, 200)
  361. output_text = output.get_data(as_text=True)
  362. self.assertIn(
  363. 'Action canceled, try it '
  364. 'again', output_text)
  365. ast.return_value = False
  366. msg = pagure.lib.query.add_group(
  367. self.session,
  368. group_name='foo',
  369. display_name='foo group',
  370. description=None,
  371. group_type='bar',
  372. user='pingou',
  373. is_admin=False,
  374. blacklist=pagure.config.config['BLACKLISTED_GROUPS'],
  375. )
  376. self.session.commit()
  377. self.assertEqual(msg, 'User `pingou` added to the group `foo`.')
  378. user.username = 'pingou'
  379. with tests.user_set(self.app.application, user):
  380. output = self.app.get('/test/addgroup')
  381. self.assertEqual(output.status_code, 200)
  382. output_text = output.get_data(as_text=True)
  383. self.assertIn('<strong>Add group to the', output_text)
  384. csrf_token = output_text.split(
  385. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  386. data = {
  387. 'group': 'ralph',
  388. }
  389. # Missing CSRF
  390. output = self.app.post('/test/addgroup', data=data)
  391. self.assertEqual(output.status_code, 200)
  392. output_text = output.get_data(as_text=True)
  393. self.assertIn(
  394. '<title>Add group - test - Pagure</title>', output_text)
  395. self.assertIn('<strong>Add group to the', output_text)
  396. # Missing access
  397. data['csrf_token'] = csrf_token
  398. output = self.app.post('/test/addgroup', data=data)
  399. self.assertEqual(output.status_code, 200)
  400. output_text = output.get_data(as_text=True)
  401. self.assertIn(
  402. '<title>Add group - test - Pagure</title>', output_text)
  403. self.assertIn('<strong>Add group to the', output_text)
  404. # All good
  405. data['access'] = 'ticket'
  406. output = self.app.post(
  407. '/test/addgroup', data=data, follow_redirects=True)
  408. self.assertEqual(output.status_code, 200)
  409. output_text = output.get_data(as_text=True)
  410. self.assertIn(
  411. '<title>Settings - test - Pagure</title>', output_text)
  412. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  413. self.assertIn(
  414. 'Group added', output_text)
  415. @patch('pagure.decorators.admin_session_timedout')
  416. def test_remove_user_when_user_mngt_off(self, ast):
  417. """ Test the remove_user endpoint when user management is turned
  418. off in the pagure instance"""
  419. pagure.config.config['ENABLE_USER_MNGT'] = False
  420. ast.return_value = False
  421. # Git repo not found
  422. output = self.app.post('/foo/dropuser/1')
  423. self.assertEqual(output.status_code, 404)
  424. user = tests.FakeUser(username='pingou')
  425. with tests.user_set(self.app.application, user):
  426. tests.create_projects(self.session)
  427. tests.create_projects_git(os.path.join(self.path, 'repos'))
  428. output = self.app.post('/test/settings')
  429. output_text = output.get_data(as_text=True)
  430. csrf_token = output_text.split(
  431. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  432. data = {'csrf_token': csrf_token}
  433. output = self.app.post(
  434. '/test/dropuser/2', data=data, follow_redirects=True)
  435. self.assertEqual(output.status_code, 404)
  436. # User not logged in
  437. output = self.app.post('/test/dropuser/1')
  438. self.assertEqual(output.status_code, 302)
  439. # Add an user to a project
  440. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  441. msg = pagure.lib.query.add_user_to_project(
  442. session=self.session,
  443. project=repo,
  444. new_user='foo',
  445. user='pingou',
  446. )
  447. self.session.commit()
  448. self.assertEqual(msg, 'User added')
  449. with tests.user_set(self.app.application, user):
  450. output = self.app.post('/test/dropuser/2', follow_redirects=True)
  451. self.assertEqual(output.status_code, 404)
  452. data = {'csrf_token': csrf_token}
  453. output = self.app.post(
  454. '/test/dropuser/2', data=data, follow_redirects=True)
  455. self.assertEqual(output.status_code, 404)
  456. pagure.config.config['ENABLE_USER_MNGT'] = True
  457. @patch('pagure.decorators.admin_session_timedout')
  458. def test_remove_deploykey(self, ast):
  459. """ Test the remove_deploykey endpoint. """
  460. ast.return_value = False
  461. # Git repo not found
  462. output = self.app.post('/foo/dropdeploykey/1')
  463. self.assertEqual(output.status_code, 404)
  464. user = tests.FakeUser()
  465. with tests.user_set(self.app.application, user):
  466. output = self.app.post('/foo/dropdeploykey/1')
  467. self.assertEqual(output.status_code, 404)
  468. tests.create_projects(self.session)
  469. tests.create_projects_git(os.path.join(self.path, 'repos'))
  470. output = self.app.post('/test/dropdeploykey/1')
  471. self.assertEqual(output.status_code, 403)
  472. ast.return_value = True
  473. output = self.app.post('/test/dropdeploykey/1')
  474. self.assertEqual(output.status_code, 302)
  475. ast.return_value = False
  476. # User not logged in
  477. output = self.app.post('/test/dropdeploykey/1')
  478. self.assertEqual(output.status_code, 302)
  479. user.username = 'pingou'
  480. with tests.user_set(self.app.application, user):
  481. output = self.app.post('/test/settings')
  482. output_text = output.get_data(as_text=True)
  483. csrf_token = output_text.split(
  484. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  485. data = {'csrf_token': csrf_token}
  486. output = self.app.post(
  487. '/test/dropdeploykey/1', data=data, follow_redirects=True)
  488. self.assertEqual(output.status_code, 200)
  489. output_text = output.get_data(as_text=True)
  490. self.assertIn(
  491. '<title>Settings - test - Pagure</title>', output_text)
  492. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  493. self.assertIn('Deploy key does not exist in project', output_text)
  494. # Add a deploy key to a project
  495. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  496. pingou = pagure.lib.query.get_user(self.session, 'pingou')
  497. msg = pagure.lib.query.add_sshkey_to_project_or_user(
  498. session=self.session,
  499. project=repo,
  500. ssh_key='ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAzBMSIlvPRaEiLOTVInErkRIw9CzQQcnslDekAn1jFnGf+SNa1acvbTiATbCX71AA03giKrPxPH79dxcC7aDXerc6zRcKjJs6MAL9PrCjnbyxCKXRNNZU5U9X/DLaaL1b3caB+WD6OoorhS3LTEtKPX8xyjOzhf3OQSzNjhJp5Q==',
  501. pushaccess=True,
  502. creator=pingou,
  503. )
  504. self.session.commit()
  505. self.assertEqual(msg, 'SSH key added')
  506. with tests.user_set(self.app.application, user):
  507. output = self.app.post('/test/dropdeploykey/1', follow_redirects=True)
  508. self.assertEqual(output.status_code, 200)
  509. output_text = output.get_data(as_text=True)
  510. self.assertIn(
  511. '<title>Settings - test - Pagure</title>', output_text)
  512. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  513. self.assertNotIn('Deploy key removed', output_text)
  514. data = {'csrf_token': csrf_token}
  515. output = self.app.post(
  516. '/test/dropdeploykey/1', data=data, follow_redirects=True)
  517. self.assertEqual(output.status_code, 200)
  518. output_text = output.get_data(as_text=True)
  519. self.assertIn(
  520. '<title>Settings - test - Pagure</title>', output_text)
  521. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  522. self.assertIn('Deploy key removed', output_text)
  523. @patch('pagure.decorators.admin_session_timedout')
  524. @patch.dict('pagure.config.config', {'DEPLOY_KEY': False})
  525. def test_remove_deploykey_disabled(self, ast):
  526. """ Test the remove_deploykey endpoint when it's disabled in the
  527. config.
  528. """
  529. ast.return_value = False
  530. tests.create_projects(self.session)
  531. tests.create_projects_git(os.path.join(self.path, 'repos'))
  532. user = tests.FakeUser(username='pingou')
  533. with tests.user_set(self.app.application, user):
  534. output = self.app.post('/test/dropdeploykey/1')
  535. self.assertEqual(output.status_code, 404)
  536. @patch('pagure.decorators.admin_session_timedout')
  537. @patch('pagure.lib.notify.log')
  538. def test_remove_user(self, mock_log, ast):
  539. """ Test the remove_user endpoint. """
  540. ast.return_value = False
  541. # Git repo not found
  542. output = self.app.post('/foo/dropuser/1')
  543. self.assertEqual(output.status_code, 404)
  544. user = tests.FakeUser()
  545. with tests.user_set(self.app.application, user):
  546. output = self.app.post('/foo/dropuser/1')
  547. self.assertEqual(output.status_code, 404)
  548. tests.create_projects(self.session)
  549. tests.create_projects_git(os.path.join(self.path, 'repos'))
  550. output = self.app.post('/test/dropuser/1')
  551. self.assertEqual(output.status_code, 403)
  552. ast.return_value = True
  553. output = self.app.post('/test/dropuser/1')
  554. self.assertEqual(output.status_code, 302)
  555. ast.return_value = False
  556. # User not logged in
  557. output = self.app.post('/test/dropuser/1')
  558. self.assertEqual(output.status_code, 302)
  559. user.username = 'pingou'
  560. with tests.user_set(self.app.application, user):
  561. output = self.app.post('/test/settings')
  562. output_text = output.get_data(as_text=True)
  563. csrf_token = output_text.split(
  564. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  565. data = {'csrf_token': csrf_token}
  566. output = self.app.post(
  567. '/test/dropuser/2', data=data, follow_redirects=True)
  568. self.assertEqual(output.status_code, 200)
  569. output_text = output.get_data(as_text=True)
  570. self.assertIn(
  571. '<title>Settings - test - Pagure</title>', output_text)
  572. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  573. self.assertIn(
  574. 'User does not have any '
  575. 'access on the repo', output_text)
  576. # Add an user to a project
  577. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  578. self.assertEqual(len(repo.users), 0)
  579. msg = pagure.lib.query.add_user_to_project(
  580. session=self.session,
  581. project=repo,
  582. new_user='foo',
  583. user='pingou',
  584. )
  585. self.session.commit()
  586. self.assertEqual(msg, 'User added')
  587. self.assertEqual(len(repo.users), 1)
  588. with tests.user_set(self.app.application, user):
  589. output = self.app.post('/test/dropuser/2', follow_redirects=True)
  590. self.assertEqual(output.status_code, 200)
  591. output_text = output.get_data(as_text=True)
  592. self.assertIn(
  593. '<title>Settings - test - Pagure</title>', output_text)
  594. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  595. self.assertNotIn(
  596. 'User removed', output_text)
  597. self.assertIn('action="/test/dropuser/2">', output_text)
  598. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  599. self.assertEqual(len(repo.users), 1)
  600. data = {'csrf_token': csrf_token}
  601. output = self.app.post(
  602. '/test/dropuser/2', data=data, follow_redirects=True)
  603. self.assertEqual(output.status_code, 200)
  604. output_text = output.get_data(as_text=True)
  605. self.assertIn(
  606. '<title>Settings - test - Pagure</title>', output_text)
  607. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  608. self.assertIn(
  609. 'User removed', output_text)
  610. self.assertNotIn('action="/test/dropuser/2">', output_text)
  611. self.session.commit()
  612. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  613. self.assertEqual(len(repo.users), 0)
  614. mock_log.assert_called_with(ANY, topic='project.user.removed', msg=ANY)
  615. @patch('pagure.decorators.admin_session_timedout')
  616. @patch('pagure.lib.notify.log')
  617. def test_remove_user_self(self, mock_log, ast):
  618. """ Test the remove_user endpoint when removing themselves. """
  619. ast.return_value = False
  620. tests.create_projects(self.session)
  621. tests.create_projects_git(os.path.join(self.path, 'repos'))
  622. # Add an user to a project
  623. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  624. self.assertEqual(len(repo.users), 0)
  625. msg = pagure.lib.query.add_user_to_project(
  626. session=self.session,
  627. project=repo,
  628. new_user='foo',
  629. user='pingou',
  630. )
  631. self.session.commit()
  632. self.assertEqual(msg, 'User added')
  633. self.assertEqual(len(repo.users), 1)
  634. # Let user foo remove themselves
  635. user = tests.FakeUser(username='foo')
  636. with tests.user_set(self.app.application, user):
  637. csrf_token = self.get_csrf()
  638. data = {'csrf_token': csrf_token}
  639. output = self.app.post(
  640. '/test/dropuser/2', data=data, follow_redirects=True)
  641. self.assertEqual(output.status_code, 200)
  642. output_text = output.get_data(as_text=True)
  643. self.assertIn(
  644. '<title>Overview - test - Pagure</title>', output_text)
  645. self.assertIn(
  646. '<h3 class="mb-0">\n<a href="/test"><strong>test</strong>'
  647. '</a>\n </h3>',
  648. output_text)
  649. self.assertIn(
  650. 'User removed', output_text)
  651. self.session.commit()
  652. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  653. self.assertEqual(len(repo.users), 0)
  654. mock_log.assert_called_with(ANY, topic='project.user.removed', msg=ANY)
  655. @patch('pagure.decorators.admin_session_timedout')
  656. def test_remove_group_project_when_user_mngt_off(self, ast):
  657. """ Test the remove_group_project endpoint when user management is
  658. turned off in the pagure instance"""
  659. pagure.config.config['ENABLE_USER_MNGT'] = False
  660. ast.return_value = False
  661. # No Git repo
  662. output = self.app.post('/foo/dropgroup/1')
  663. self.assertEqual(output.status_code, 404)
  664. tests.create_projects(self.session)
  665. tests.create_projects_git(os.path.join(self.path, 'repos'))
  666. # User not logged in
  667. output = self.app.post('/test/dropgroup/1')
  668. self.assertEqual(output.status_code, 302)
  669. user = tests.FakeUser()
  670. user.username = 'pingou'
  671. with tests.user_set(self.app.application, user):
  672. output = self.app.post('/test/settings')
  673. output_text = output.get_data(as_text=True)
  674. csrf_token = output_text.split(
  675. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  676. data = {'csrf_token': csrf_token}
  677. output = self.app.post(
  678. '/test/dropgroup/2', data=data, follow_redirects=True)
  679. self.assertEqual(output.status_code, 404)
  680. # Create the new group
  681. msg = pagure.lib.query.add_group(
  682. session=self.session,
  683. group_name='testgrp',
  684. group_type='user',
  685. display_name='testgrp group',
  686. description=None,
  687. user='pingou',
  688. is_admin=False,
  689. blacklist=[],
  690. )
  691. self.assertEqual(msg, 'User `pingou` added to the group `testgrp`.')
  692. self.session.commit()
  693. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  694. # Add the group to a project
  695. msg = pagure.lib.query.add_group_to_project(
  696. session=self.session,
  697. project=repo,
  698. new_group='testgrp',
  699. user='pingou',
  700. )
  701. self.session.commit()
  702. self.assertEqual(msg, 'Group added')
  703. with tests.user_set(self.app.application, user):
  704. output = self.app.post('/test/dropgroup/1', follow_redirects=True)
  705. self.assertEqual(output.status_code, 404)
  706. data = {'csrf_token': csrf_token}
  707. output = self.app.post(
  708. '/test/dropgroup/1', data=data, follow_redirects=True)
  709. self.assertEqual(output.status_code, 404)
  710. pagure.config.config['ENABLE_USER_MNGT'] = True
  711. @patch('pagure.decorators.admin_session_timedout')
  712. def test_remove_group_project(self, ast):
  713. """ Test the remove_group_project endpoint. """
  714. ast.return_value = False
  715. # No Git repo
  716. output = self.app.post('/foo/dropgroup/1')
  717. self.assertEqual(output.status_code, 404)
  718. user = tests.FakeUser()
  719. with tests.user_set(self.app.application, user):
  720. output = self.app.post('/foo/dropgroup/1')
  721. self.assertEqual(output.status_code, 404)
  722. tests.create_projects(self.session)
  723. tests.create_projects_git(os.path.join(self.path, 'repos'))
  724. output = self.app.post('/test/dropgroup/1')
  725. self.assertEqual(output.status_code, 403)
  726. ast.return_value = True
  727. output = self.app.post('/test/dropgroup/1')
  728. self.assertEqual(output.status_code, 302)
  729. ast.return_value = False
  730. # User not logged in
  731. output = self.app.post('/test/dropgroup/1')
  732. self.assertEqual(output.status_code, 302)
  733. user.username = 'pingou'
  734. with tests.user_set(self.app.application, user):
  735. output = self.app.post('/test/settings')
  736. output_text = output.get_data(as_text=True)
  737. csrf_token = output_text.split(
  738. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  739. data = {'csrf_token': csrf_token}
  740. output = self.app.post(
  741. '/test/dropgroup/2', data=data, follow_redirects=True)
  742. self.assertEqual(output.status_code, 200)
  743. output_text = output.get_data(as_text=True)
  744. self.assertIn(
  745. '<title>Settings - test - Pagure</title>', output_text)
  746. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  747. self.assertIn(
  748. ''
  749. 'Group does not seem to be part of this project',
  750. output_text)
  751. # Create the new group
  752. msg = pagure.lib.query.add_group(
  753. session=self.session,
  754. group_name='testgrp',
  755. group_type='user',
  756. display_name='testgrp group',
  757. description=None,
  758. user='pingou',
  759. is_admin=False,
  760. blacklist=[],
  761. )
  762. self.assertEqual(msg, 'User `pingou` added to the group `testgrp`.')
  763. self.session.commit()
  764. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  765. # Add the group to a project
  766. msg = pagure.lib.query.add_group_to_project(
  767. session=self.session,
  768. project=repo,
  769. new_group='testgrp',
  770. user='pingou',
  771. )
  772. self.session.commit()
  773. self.assertEqual(msg, 'Group added')
  774. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  775. self.assertEqual(len(repo.groups), 1)
  776. with tests.user_set(self.app.application, user):
  777. output = self.app.post('/test/dropgroup/1', follow_redirects=True)
  778. self.assertEqual(output.status_code, 200)
  779. output_text = output.get_data(as_text=True)
  780. self.assertIn(
  781. '<title>Settings - test - Pagure</title>', output_text)
  782. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  783. self.assertIn('action="/test/dropgroup/1">', output_text)
  784. self.assertNotIn(
  785. 'Group removed',
  786. output_text)
  787. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  788. self.assertEqual(len(repo.groups), 1)
  789. data = {'csrf_token': csrf_token}
  790. output = self.app.post(
  791. '/test/dropgroup/1', data=data, follow_redirects=True)
  792. self.assertEqual(output.status_code, 200)
  793. output_text = output.get_data(as_text=True)
  794. self.assertIn(
  795. '<title>Settings - test - Pagure</title>', output_text)
  796. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  797. self.assertIn(
  798. 'Group removed',
  799. output_text)
  800. self.assertNotIn('action="/test/dropgroup/1">', output_text)
  801. self.session.commit()
  802. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  803. self.assertEqual(len(repo.groups), 0)
  804. @patch('pagure.decorators.admin_session_timedout')
  805. def test_update_project(self, ast):
  806. """ Test the update_project endpoint. """
  807. ast.return_value = True
  808. # Git repo not found
  809. output = self.app.post('/foo/update')
  810. self.assertEqual(output.status_code, 404)
  811. user = tests.FakeUser()
  812. with tests.user_set(self.app.application, user):
  813. # Project does not exist
  814. output = self.app.post('/foo/update')
  815. self.assertEqual(output.status_code, 404)
  816. tests.create_projects(self.session)
  817. tests.create_projects_git(os.path.join(self.path, 'repos'))
  818. # Session timed-out
  819. output = self.app.post('/test/update')
  820. self.assertEqual(output.status_code, 302)
  821. ast.return_value = False
  822. # Not allowed
  823. output = self.app.post('/test/update')
  824. self.assertEqual(output.status_code, 403)
  825. # User not logged in
  826. output = self.app.post('/test/update')
  827. self.assertEqual(output.status_code, 302)
  828. user.username = 'pingou'
  829. with tests.user_set(self.app.application, user):
  830. output = self.app.post('/test/update', follow_redirects=True)
  831. self.assertEqual(output.status_code, 200)
  832. output_text = output.get_data(as_text=True)
  833. self.assertIn(
  834. '<title>Settings - test - Pagure</title>', output_text)
  835. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  836. csrf_token = output_text.split(
  837. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  838. data = {
  839. 'description': 'new description for test project #1',
  840. 'csrf_token': csrf_token,
  841. }
  842. output = self.app.post(
  843. '/test/update', data=data, follow_redirects=True)
  844. self.assertEqual(output.status_code, 200)
  845. output_text = output.get_data(as_text=True)
  846. self.assertIn(
  847. '<title>Settings - test - Pagure</title>', output_text)
  848. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  849. self.assertIn(
  850. '<input class="form-control" name="avatar_email" value="" />', output_text)
  851. self.assertIn(
  852. 'Project updated',
  853. output_text)
  854. # Edit the avatar_email
  855. data = {
  856. 'description': 'new description for test project #1',
  857. 'avatar_email': 'pingou@fp.o',
  858. 'csrf_token': csrf_token,
  859. }
  860. output = self.app.post(
  861. '/test/update', data=data, follow_redirects=True)
  862. self.assertEqual(output.status_code, 200)
  863. output_text = output.get_data(as_text=True)
  864. self.assertIn(
  865. '<title>Settings - test - Pagure</title>', output_text)
  866. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  867. self.assertIn(
  868. '<input class="form-control" name="avatar_email" value="pingou@fp.o" />',
  869. output_text)
  870. self.assertIn(
  871. 'Project updated',
  872. output_text)
  873. # Reset the avatar_email
  874. data = {
  875. 'description': 'new description for test project #1',
  876. 'avatar_email': '',
  877. 'csrf_token': csrf_token,
  878. }
  879. output = self.app.post(
  880. '/test/update', data=data, follow_redirects=True)
  881. self.assertEqual(output.status_code, 200)
  882. output_text = output.get_data(as_text=True)
  883. self.assertIn(
  884. '<title>Settings - test - Pagure</title>', output_text)
  885. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  886. self.assertIn(
  887. '<input class="form-control" name="avatar_email" value="" />', output_text)
  888. self.assertIn(
  889. 'Project updated',
  890. output_text)
  891. @patch('pagure.decorators.admin_session_timedout')
  892. def test_update_project_update_tag(self, ast):
  893. """ Test the view_settings endpoint when updating the project's tags.
  894. We had an issue where when you add an existing tag to a project we
  895. were querying the wrong table in the database. It would thus not find
  896. the tag, would try to add it, and (rightfully) complain about duplicated
  897. content.
  898. This test ensure we are behaving properly.
  899. """
  900. ast.return_value = False
  901. tests.create_projects(self.session)
  902. tests.create_projects_git(os.path.join(self.path, 'repos'))
  903. user = tests.FakeUser(username='pingou')
  904. with tests.user_set(self.app.application, user):
  905. output = self.app.get('/test/settings')
  906. self.assertEqual(output.status_code, 200)
  907. output_text = output.get_data(as_text=True)
  908. self.assertIn(
  909. '<title>Settings - test - Pagure</title>', output_text)
  910. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  911. csrf_token = output_text.split(
  912. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  913. # Add tag to a project so that they are added to the database
  914. data = {
  915. 'csrf_token': csrf_token,
  916. 'description': 'Test project',
  917. 'tags': 'test,pagure,tag',
  918. }
  919. output = self.app.post(
  920. '/test/update', data=data, follow_redirects=True)
  921. self.assertEqual(output.status_code, 200)
  922. output_text = output.get_data(as_text=True)
  923. self.assertIn(
  924. '<title>Settings - test - Pagure</title>', output_text)
  925. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  926. self.assertIn(
  927. 'Project updated',
  928. output_text)
  929. # Remove two of the tags of the project, they will still be in
  930. # the DB but not associated to this project
  931. data = {
  932. 'csrf_token': csrf_token,
  933. 'description': 'Test project',
  934. 'tags': 'tag',
  935. }
  936. output = self.app.post(
  937. '/test/update', data=data, follow_redirects=True)
  938. self.assertEqual(output.status_code, 200)
  939. output_text = output.get_data(as_text=True)
  940. self.assertIn(
  941. '<title>Settings - test - Pagure</title>', output_text)
  942. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  943. self.assertIn(
  944. 'Project updated',
  945. output_text)
  946. # Try re-adding the two tags, this used to fail before we fixed
  947. # it
  948. data = {
  949. 'csrf_token': csrf_token,
  950. 'description': 'Test project',
  951. 'tags': 'test,pagure,tag',
  952. }
  953. output = self.app.post(
  954. '/test/update', data=data, follow_redirects=True)
  955. self.assertEqual(output.status_code, 200)
  956. output_text = output.get_data(as_text=True)
  957. self.assertIn(
  958. '<title>Settings - test - Pagure</title>', output_text)
  959. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  960. self.assertIn(
  961. 'Project updated',
  962. output_text)
  963. @patch('pagure.decorators.admin_session_timedout')
  964. def test_view_settings(self, ast):
  965. """ Test the view_settings endpoint. """
  966. ast.return_value = False
  967. # No Git repo
  968. output = self.app.get('/foo/settings')
  969. self.assertEqual(output.status_code, 404)
  970. user = tests.FakeUser()
  971. with tests.user_set(self.app.application, user):
  972. output = self.app.get('/foo/settings')
  973. self.assertEqual(output.status_code, 404)
  974. tests.create_projects(self.session)
  975. tests.create_projects_git(os.path.join(self.path, 'repos'))
  976. output = self.app.get('/test/settings')
  977. self.assertEqual(output.status_code, 403)
  978. # User not logged in
  979. output = self.app.get('/test/settings')
  980. self.assertEqual(output.status_code, 302)
  981. user.username = 'pingou'
  982. with tests.user_set(self.app.application, user):
  983. ast.return_value = True
  984. output = self.app.get('/test/settings')
  985. self.assertEqual(output.status_code, 302)
  986. ast.return_value = False
  987. output = self.app.get('/test/settings')
  988. self.assertEqual(output.status_code, 200)
  989. output_text = output.get_data(as_text=True)
  990. self.assertIn(
  991. '<title>Settings - test - Pagure</title>', output_text)
  992. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  993. # Both checkbox checked before
  994. self.assertIn(
  995. '<input id="pull_requests" type="checkbox" value="y" '
  996. 'name="pull_requests" checked=""/>', output_text)
  997. self.assertIn(
  998. '<input id="issue_tracker" type="checkbox" value="y" '
  999. 'name="issue_tracker" checked=""/>', output_text)
  1000. csrf_token = output_text.split(
  1001. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  1002. data = {}
  1003. output = self.app.post(
  1004. '/test/settings', data=data, follow_redirects=True)
  1005. self.assertEqual(output.status_code, 200)
  1006. output_text = output.get_data(as_text=True)
  1007. self.assertIn(
  1008. '<title>Settings - test - Pagure</title>', output_text)
  1009. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  1010. # Both checkbox are still checked
  1011. output = self.app.get('/test/settings', follow_redirects=True)
  1012. self.assertEqual(output.status_code, 200)
  1013. output_text = output.get_data(as_text=True)
  1014. self.assertIn(
  1015. '<title>Settings - test - Pagure</title>', output_text)
  1016. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  1017. self.assertIn(
  1018. '<input id="pull_requests" type="checkbox" value="y" '
  1019. 'name="pull_requests" checked=""/>', output_text)
  1020. self.assertIn(
  1021. '<input id="issue_tracker" type="checkbox" value="y" '
  1022. 'name="issue_tracker" checked=""/>', output_text)
  1023. data = {'csrf_token': csrf_token}
  1024. output = self.app.post(
  1025. '/test/settings', data=data, follow_redirects=True)
  1026. self.assertEqual(output.status_code, 200)
  1027. output_text = output.get_data(as_text=True)
  1028. self.assertIn(
  1029. '<title>Overview - test - Pagure</title>', output_text)
  1030. self.assertIn(
  1031. 'Edited successfully '
  1032. 'settings of repo: test', output_text)
  1033. # Both checkbox are now un-checked
  1034. output = self.app.get('/test/settings', follow_redirects=True)
  1035. self.assertEqual(output.status_code, 200)
  1036. output_text = output.get_data(as_text=True)
  1037. self.assertIn(
  1038. '<title>Settings - test - Pagure</title>', output_text)
  1039. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  1040. self.assertIn(
  1041. '<input id="pull_requests" type="checkbox" value="y" '
  1042. 'name="pull_requests" />', output_text)
  1043. self.assertIn(
  1044. '<input id="issue_tracker" type="checkbox" value="y" '
  1045. 'name="issue_tracker" />', output_text)
  1046. data = {
  1047. 'csrf_token': csrf_token,
  1048. 'pull_requests': 'y',
  1049. 'issue_tracker': 'y',
  1050. }
  1051. output = self.app.post(
  1052. '/test/settings', data=data, follow_redirects=True)
  1053. self.assertEqual(output.status_code, 200)
  1054. output_text = output.get_data(as_text=True)
  1055. self.assertIn(
  1056. '<title>Overview - test - Pagure</title>', output_text)
  1057. self.assertIn(
  1058. 'Edited successfully '
  1059. 'settings of repo: test', output_text)
  1060. # Both checkbox are again checked
  1061. output = self.app.get('/test/settings', follow_redirects=True)
  1062. self.assertEqual(output.status_code, 200)
  1063. output_text = output.get_data(as_text=True)
  1064. self.assertIn(
  1065. '<title>Settings - test - Pagure</title>', output_text)
  1066. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  1067. self.assertIn(
  1068. '<input id="pull_requests" type="checkbox" value="y" '
  1069. 'name="pull_requests" checked=""/>', output_text)
  1070. self.assertIn(
  1071. '<input id="issue_tracker" type="checkbox" value="y" '
  1072. 'name="issue_tracker" checked=""/>', output_text)
  1073. @patch('pagure.decorators.admin_session_timedout',
  1074. MagicMock(return_value=False))
  1075. def test_view_settings_custom_fields(self):
  1076. """ Test the view_settings endpoint when the project has some custom
  1077. field for issues. """
  1078. tests.create_projects(self.session)
  1079. tests.create_projects_git(os.path.join(self.path, 'repos'))
  1080. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  1081. msg = pagure.lib.query.set_custom_key_fields(
  1082. self.session, repo,
  1083. ['bugzilla', 'upstream', 'reviewstatus'],
  1084. ['link', 'boolean', 'list'],
  1085. ['unused data for non-list type', '', 'ack', 'nack', 'needs review'],
  1086. [None, None, None])
  1087. self.session.commit()
  1088. self.assertEqual(msg, 'List of custom fields updated')
  1089. self.assertIsNotNone(repo.issue_keys)
  1090. user = tests.FakeUser(username='pingou')
  1091. with tests.user_set(self.app.application, user):
  1092. output = self.app.get('/test/settings')
  1093. self.assertEqual(output.status_code, 200)
  1094. @patch('pagure.lib.git.generate_gitolite_acls')
  1095. @patch('pagure.decorators.admin_session_timedout')
  1096. def test_view_settings_pr_only(self, ast, gen_acl):
  1097. """ Test the view_settings endpoint when turning on PR only. """
  1098. ast.return_value = False
  1099. tests.create_projects(self.session)
  1100. tests.create_projects_git(os.path.join(self.path, 'repos'))
  1101. user = tests.FakeUser(username='pingou')
  1102. with tests.user_set(self.app.application, user):
  1103. output = self.app.get('/test/settings')
  1104. self.assertEqual(output.status_code, 200)
  1105. output_text = output.get_data(as_text=True)
  1106. self.assertIn(
  1107. '<title>Settings - test - Pagure</title>', output_text)
  1108. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  1109. csrf_token = self.get_csrf(output=output)
  1110. data = {
  1111. 'csrf_token': csrf_token,
  1112. 'pull_requests': 'y',
  1113. 'issue_tracker': 'y',
  1114. 'pull_request_access_only': 'y',
  1115. }
  1116. output = self.app.post(
  1117. '/test/settings', data=data, follow_redirects=True)
  1118. self.assertEqual(output.status_code, 200)
  1119. output_text = output.get_data(as_text=True)
  1120. self.assertIn(
  1121. '<title>Overview - test - Pagure</title>', output_text)
  1122. self.assertIn(
  1123. 'Edited successfully '
  1124. 'settings of repo: test', output_text)
  1125. # Both checkbox are again checked
  1126. output = self.app.get('/test/settings', follow_redirects=True)
  1127. self.assertEqual(output.status_code, 200)
  1128. output_text = output.get_data(as_text=True)
  1129. self.assertIn(
  1130. '<title>Settings - test - Pagure</title>', output_text)
  1131. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  1132. self.assertIn(
  1133. '<input id="pull_requests" type="checkbox" value="y" '
  1134. 'name="pull_requests" checked=""/>', output_text)
  1135. self.assertIn(
  1136. '<input id="issue_tracker" type="checkbox" value="y" '
  1137. 'name="issue_tracker" checked=""/>', output_text)
  1138. self.assertIn(
  1139. '<input id="pull_request_access_only" type="checkbox" '
  1140. 'value="y" name="pull_request_access_only" checked=""/>',
  1141. output_text)
  1142. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  1143. self.assertEqual(gen_acl.call_count, 1)
  1144. args = gen_acl.call_args
  1145. self.assertEqual(args[0], tuple())
  1146. self.assertListEqual(list(args[1]), ['project'])
  1147. self.assertEqual(args[1]['project'].fullname, 'test')
  1148. @patch('pagure.decorators.admin_session_timedout')
  1149. def test_fields_in_view_settings(self, ast):
  1150. """ Test the default fields in view_settings endpoint. """
  1151. ast.return_value = False
  1152. # No Git repo
  1153. output = self.app.get('/foo/settings')
  1154. self.assertEqual(output.status_code, 404)
  1155. user = tests.FakeUser()
  1156. with tests.user_set(self.app.application, user):
  1157. output = self.app.get('/foo/settings')
  1158. self.assertEqual(output.status_code, 404)
  1159. item = pagure.lib.model.Project(
  1160. user_id=1, # pingou
  1161. name='test',
  1162. description='test project #1',
  1163. hook_token='aaabbbccc',
  1164. )
  1165. self.session.add(item)
  1166. self.session.commit()
  1167. tests.create_projects_git(os.path.join(self.path, 'repos'))
  1168. output = self.app.get('/test/settings')
  1169. self.assertEqual(output.status_code, 403)
  1170. # User not logged in
  1171. output = self.app.get('/test/settings')
  1172. self.assertEqual(output.status_code, 302)
  1173. user.username = 'pingou'
  1174. with tests.user_set(self.app.application, user):
  1175. ast.return_value = True
  1176. output = self.app.get('/test/settings')
  1177. self.assertEqual(output.status_code, 302)
  1178. ast.return_value = False
  1179. output = self.app.get('/test/settings')
  1180. self.assertEqual(output.status_code, 200)
  1181. output_text = output.get_data(as_text=True)
  1182. self.assertIn(
  1183. '<title>Settings - test - Pagure</title>', output_text)
  1184. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  1185. # Check that the priorities have their empty fields
  1186. self.assertIn(
  1187. '''<div class="form-group settings-field-rows" id="priorities-list">
  1188. <div class="row hidden blank-field">
  1189. <div class="col-sm-2" >
  1190. <input type="text" name="priority_weigth"
  1191. value="" size="3" class="form-control"/>
  1192. </div>
  1193. <div class="col-sm-9">
  1194. <input type="text" name="priority_title"
  1195. value="" class="form-control"/>
  1196. </div>''', output_text)
  1197. # Check that the milestones have their empty fields
  1198. self.assertIn(
  1199. '''<div id="milestones">
  1200. <div class="row p-t-1 milestone" id="milestone_1">
  1201. <input type="hidden" name="milestones" value="1">
  1202. <div class="col-sm-4 p-r-0">
  1203. <input type="text" name="milestone_1_name"
  1204. value="" size="3" class="form-control"/>
  1205. </div>
  1206. <div class="col-sm-4 p-r-0">
  1207. <input type="text" name="milestone_1_date"
  1208. value="" class="form-control"/>
  1209. </div>
  1210. <div class="col-sm-2 p-r-0" >
  1211. <span class="fa fa-long-arrow-up milestone_order_up"
  1212. data-stone="1"></span>
  1213. <span class="fa fa-long-arrow-down milestone_order_bottom"
  1214. data-stone="1"></span>
  1215. </div>
  1216. <div class="col-sm-1 p-r-0" >
  1217. <input type="checkbox" name="milestone_1_active" />
  1218. </div>
  1219. </div>''', output_text)
  1220. # Check that the close_status have its empty field
  1221. self.assertIn(
  1222. '''<div class="form-group settings-field-rows" id="status-list">
  1223. <div class="row hidden blank-field">
  1224. <div class="col-sm-11" >
  1225. <input type="text" name="close_status"
  1226. value="" class="form-control"/>
  1227. </div>''', output_text)
  1228. # Check that the custom fields have their empty fields
  1229. self.assertIn(
  1230. '''<div class="form-group settings-field-rows" id="customfields-list">
  1231. <div class="row hidden blank-field">
  1232. <div class="col-sm-2 pr-0">
  1233. <input type="text" name="custom_keys"
  1234. value="" class="form-control"/>
  1235. </div>
  1236. <div class="col-sm-2 pr-0">
  1237. <select name="custom_keys_type" class="form-control custom-keys">
  1238. <option value="text">Text</option>
  1239. <option value="boolean">Boolean</option>
  1240. <option value="link">Link</option>
  1241. <option value="list">List</option>
  1242. <option value="date">Date</option>
  1243. </select>
  1244. </div>
  1245. <div class="col-sm-6 pr-0">
  1246. <input title="Comma separated list items" type="text" name="custom_keys_data" value="" class="form-control custom-keys-list hidden" id="custom_keys_list"/>
  1247. </div>
  1248. <div class="col-sm-1 pr-0">
  1249. <input type="checkbox" name="custom_keys_notify" title="Trigger email notification when updated" class="form-control"/>
  1250. </div>''', output_text)
  1251. def test_view_forks(self):
  1252. """ Test the view_forks endpoint. """
  1253. output = self.app.get('/foo/forks', follow_redirects=True)
  1254. self.assertEqual(output.status_code, 404)
  1255. tests.create_projects(self.session)
  1256. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  1257. output = self.app.get('/test/forks', follow_redirects=True)
  1258. self.assertEqual(output.status_code, 200)
  1259. output_text = output.get_data(as_text=True)
  1260. self.assertIn('This project has not been forked.', output_text)
  1261. @patch.dict('pagure.config.config', {'CASE_SENSITIVE': True})
  1262. def test_view_repo_case_sensitive(self):
  1263. """ Test the view_repo endpoint. """
  1264. tests.create_projects(self.session)
  1265. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  1266. output = self.app.get('/test')
  1267. self.assertEqual(output.status_code, 200)
  1268. output_text = output.get_data(as_text=True)
  1269. self.assertIn('<p>This repo is brand new!</p>', output_text)
  1270. output = self.app.get('/TEST')
  1271. self.assertEqual(output.status_code, 404)
  1272. def test_view_repo_more_button_absent_no_auth(self):
  1273. """ Test the view_repo endpoint and check if the "more" button is
  1274. absent when not logged in. """
  1275. tests.create_projects(self.session)
  1276. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  1277. output = self.app.get('/test')
  1278. self.assertEqual(output.status_code, 200)
  1279. output_text = output.get_data(as_text=True)
  1280. self.assertNotIn(
  1281. '<span class="pull-xs-right"><a data-toggle="collapse" '
  1282. 'href="#moregiturls"', output_text)
  1283. self.assertIn('<p>This repo is brand new!</p>', output_text)
  1284. self.assertIn(
  1285. '<title>Overview - test - Pagure</title>', output_text)
  1286. self.assertIn(
  1287. '<span class="d-none d-md-inline">Stats</span>',
  1288. output_text)
  1289. self.perfMaxWalks(0, 0)
  1290. self.perfReset()
  1291. def test_view_repo_more_button_present(self):
  1292. """ Test the view_repo endpoint and check if the "more" button is
  1293. present when it should be. """
  1294. tests.create_projects(self.session)
  1295. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  1296. pingou = pagure.lib.query.get_user(self.session, 'pingou')
  1297. pagure.lib.query.add_sshkey_to_project_or_user(
  1298. session=self.session,
  1299. user=pingou,
  1300. ssh_key='ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAzBMSIlvPRaEiLOTVInErkRIw9CzQQcnslDekAn1jFnGf+SNa1acvbTiATbCX71AA03giKrPxPH79dxcC7aDXerc6zRcKjJs6MAL9PrCjnbyxCKXRNNZU5U9X/DLaaL1b3caB+WD6OoorhS3LTEtKPX8xyjOzhf3OQSzNjhJp5Q==',
  1301. pushaccess=True,
  1302. creator=pingou,
  1303. )
  1304. self.session.commit()
  1305. repo = pagure.lib.query._get_project(self.session, 'test')
  1306. pagure.lib.query.update_read_only_mode(self.session, repo, read_only=False)
  1307. self.session.commit()
  1308. user = tests.FakeUser(username='pingou')
  1309. with tests.user_set(self.app.application, user):
  1310. output = self.app.get('/test')
  1311. self.assertEqual(output.status_code, 200)
  1312. output_text = output.get_data(as_text=True)
  1313. self.assertIn(
  1314. '<input class="form-control bg-white" type="text" '
  1315. 'value="ssh://git@localhost.localdomain/tickets/test.git" readonly>',
  1316. output_text)
  1317. self.assertIn('<p>This repo is brand new!</p>', output_text)
  1318. self.assertIn(
  1319. '<title>Overview - test - Pagure</title>', output_text)
  1320. self.assertIn(
  1321. '<span class="d-none d-md-inline">Stats</span>',
  1322. output_text)
  1323. self.perfMaxWalks(0, 0)
  1324. self.perfReset()
  1325. def test_view_repo_more_button_absent_no_access(self):
  1326. """ Test the view_repo endpoint and check if the "more" button is
  1327. absent if the user doesn't have access to the project. """
  1328. tests.create_projects(self.session)
  1329. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  1330. user = tests.FakeUser(username='foo')
  1331. with tests.user_set(self.app.application, user):
  1332. output = self.app.get('/test')
  1333. self.assertEqual(output.status_code, 200)
  1334. output_text = output.get_data(as_text=True)
  1335. self.assertNotIn(
  1336. '<input class="form-control bg-white" type="text" '
  1337. 'value="ssh://git@localhost.localdomain/tickets/test.git" readonly>',
  1338. output_text)
  1339. self.assertIn('<p>This repo is brand new!</p>', output_text)
  1340. self.assertIn(
  1341. '<title>Overview - test - Pagure</title>', output_text)
  1342. self.assertIn(
  1343. '<span class="d-none d-md-inline">Stats</span>',
  1344. output_text)
  1345. self.perfMaxWalks(0, 0)
  1346. self.perfReset()
  1347. def test_view_repo_ssh_key_not_uploaded_no_ssh_url(self):
  1348. """ Test viewing repo when user hasn't uploaded SSH key yet
  1349. and thus should see a message instead of url for SSH cloning. """
  1350. tests.create_projects(self.session)
  1351. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  1352. user = tests.FakeUser(username='pingou')
  1353. with tests.user_set(self.app.application, user):
  1354. output = self.app.get('/test')
  1355. self.assertEqual(output.status_code, 200)
  1356. output_text = output.get_data(as_text=True)
  1357. self.assertIn(
  1358. 'You need to upload SSH key to be able to clone over SSH',
  1359. output_text)
  1360. def test_view_repo_read_only_no_ssh_url(self):
  1361. """ Test viewing repo that is still readonly and thus user
  1362. should see a message instead of url for SSH cloning. """
  1363. tests.create_projects(self.session)
  1364. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  1365. repo = pagure.lib.query._get_project(self.session, 'test')
  1366. pagure.lib.query.update_read_only_mode(self.session, repo, read_only=True)
  1367. pingou = pagure.lib.query.get_user(self.session, 'pingou')
  1368. pagure.lib.query.add_sshkey_to_project_or_user(
  1369. session=self.session,
  1370. user=pingou,
  1371. ssh_key='ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAzBMSIlvPRaEiLOTVInErkRIw9CzQQcnslDekAn1jFnGf+SNa1acvbTiATbCX71AA03giKrPxPH79dxcC7aDXerc6zRcKjJs6MAL9PrCjnbyxCKXRNNZU5U9X/DLaaL1b3caB+WD6OoorhS3LTEtKPX8xyjOzhf3OQSzNjhJp5Q==',
  1372. pushaccess=True,
  1373. creator=pingou,
  1374. )
  1375. self.session.commit()
  1376. user = tests.FakeUser(username='pingou')
  1377. with tests.user_set(self.app.application, user):
  1378. output = self.app.get('/test')
  1379. self.assertEqual(output.status_code, 200)
  1380. output_text = output.get_data(as_text=True)
  1381. self.assertIn(
  1382. 'Cloning over SSH is disabled.',
  1383. output_text)
  1384. def test_view_repo(self):
  1385. """ Test the view_repo endpoint. """
  1386. output = self.app.get('/foo')
  1387. # No project registered in the DB
  1388. self.assertEqual(output.status_code, 404)
  1389. tests.create_projects(self.session)
  1390. output = self.app.get('/test')
  1391. # No git repo associated
  1392. self.assertEqual(output.status_code, 404)
  1393. self.perfMaxWalks(0, 0)
  1394. self.perfReset()
  1395. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  1396. output = self.app.get('/test')
  1397. self.assertEqual(output.status_code, 200)
  1398. output_text = output.get_data(as_text=True)
  1399. self.assertIn('<p>This repo is brand new!</p>', output_text)
  1400. self.assertIn(
  1401. '<title>Overview - test - Pagure</title>', output_text)
  1402. self.assertIn(
  1403. '<a class="nav-link" href="/test/stats">\n '
  1404. '<i class="fa fa-line-chart fa-fw text-muted"></i>\n '
  1405. '<span class="d-none d-md-inline">Stats</span>\n </a>',
  1406. output_text)
  1407. self.perfMaxWalks(0, 0)
  1408. self.perfReset()
  1409. output = self.app.get('/test/')
  1410. self.assertEqual(output.status_code, 200)
  1411. output_text = output.get_data(as_text=True)
  1412. self.assertIn('<p>This repo is brand new!</p>', output_text)
  1413. self.assertIn(
  1414. '<title>Overview - test - Pagure</title>', output_text)
  1415. self.perfMaxWalks(0, 0)
  1416. self.perfReset()
  1417. # Add some content to the git repo
  1418. tests.add_content_git_repo(os.path.join(self.path, 'repos',
  1419. 'test.git'))
  1420. tests.add_readme_git_repo(os.path.join(self.path, 'repos', 'test.git'))
  1421. tests.add_readme_git_repo(os.path.join(self.path, 'repos', 'test.git'), 'README.txt')
  1422. tests.add_readme_git_repo(os.path.join(self.path, 'repos', 'test.git'), 'README.dummy')
  1423. self.perfReset()
  1424. # Authenticated, the Fork button appears
  1425. user = tests.FakeUser(username='pingou')
  1426. with tests.user_set(self.app.application, user):
  1427. output = self.app.get('/test')
  1428. self.assertEqual(output.status_code, 200)
  1429. output_text = output.get_data(as_text=True)
  1430. self.assertIn(
  1431. '<i class="fa fa-code-fork fa-fw"></i> Fork</button>',
  1432. output_text)
  1433. self.assertFalse('<p>This repo is brand new!</p>' in output_text)
  1434. self.assertNotIn('Forked from', output_text)
  1435. self.assertNotIn('README.txt', output_text)
  1436. self.assertNotIn('README.dummy', output_text)
  1437. self.assertIn(
  1438. '<title>Overview - test - Pagure</title>', output_text)
  1439. self.perfMaxWalks(3, 8) # Target: (1, 3)
  1440. self.perfReset()
  1441. # Non-authenticated, the Fork button does not appear
  1442. output = self.app.get('/test')
  1443. self.assertEqual(output.status_code, 200)
  1444. output_text = output.get_data(as_text=True)
  1445. self.assertNotIn(
  1446. '<i class="fa fa-code-fork"></i>Fork</button>',
  1447. output_text)
  1448. self.assertNotIn('<p>This repo is brand new!</p>', output_text)
  1449. self.assertNotIn('Forked from', output_text)
  1450. self.assertNotIn('README.txt', output_text)
  1451. self.assertNotIn('README.dummy', output_text)
  1452. self.assertIn(
  1453. '<title>Overview - test - Pagure</title>', output_text)
  1454. self.perfMaxWalks(3, 8) # Target: (1, 3)
  1455. self.perfReset()
  1456. # Turn that repo into a fork
  1457. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  1458. repo.parent_id = 2
  1459. repo.is_fork = True
  1460. self.session.add(repo)
  1461. self.session.commit()
  1462. # View the repo in the UI
  1463. output = self.app.get('/test')
  1464. self.assertEqual(output.status_code, 404)
  1465. # Add some content to the git repo
  1466. tests.add_content_git_repo(
  1467. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test.git'))
  1468. tests.add_readme_git_repo(
  1469. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test.git'))
  1470. # Authenticated and already have a fork, the View Fork button appears
  1471. user = tests.FakeUser(username='pingou')
  1472. with tests.user_set(self.app.application, user):
  1473. output = self.app.get('/fork/pingou/test')
  1474. self.assertEqual(output.status_code, 200)
  1475. output_text = output.get_data(as_text=True)
  1476. self.assertNotIn('<p>This repo is brand new!</p>', output_text)
  1477. self.assertIn(
  1478. '<title>Overview - test - Pagure</title>', output_text)
  1479. self.assertIn('Forked from', output_text)
  1480. self.assertNotIn(
  1481. '<i class="fa fa-code-fork fa-fw"></i> Fork</button>',
  1482. output_text)
  1483. self.assertIn(
  1484. '<i class="fa fa-code-fork fa-fw"></i> View Upstream',
  1485. output_text)
  1486. self.perfMaxWalks(1, 3)
  1487. self.perfReset()
  1488. # Authenticated, the Fork button appears
  1489. user = tests.FakeUser(username='foo')
  1490. with tests.user_set(self.app.application, user):
  1491. output = self.app.get('/fork/pingou/test')
  1492. self.assertEqual(output.status_code, 200)
  1493. output_text = output.get_data(as_text=True)
  1494. self.assertNotIn('<p>This repo is brand new!</p>', output_text)
  1495. self.assertIn(
  1496. '<title>Overview - test - Pagure</title>', output_text)
  1497. self.assertIn('Forked from', output_text)
  1498. self.assertNotIn(
  1499. '<i class="fa fa-code-fork fa-fw"></i> View Upstream',
  1500. output_text)
  1501. self.assertIn(
  1502. '<i class="fa fa-code-fork fa-fw"></i> Fork</button>',
  1503. output_text)
  1504. self.perfMaxWalks(1, 3)
  1505. self.perfReset()
  1506. # Non-authenticated, the Fork button does not appear
  1507. output = self.app.get('/fork/pingou/test')
  1508. self.assertEqual(output.status_code, 200)
  1509. output_text = output.get_data(as_text=True)
  1510. self.assertNotIn('<p>This repo is brand new!</p>', output_text)
  1511. self.assertIn(
  1512. '<title>Overview - test - Pagure</title>', output_text)
  1513. self.assertIn('Forked from', output_text)
  1514. self.assertNotIn(
  1515. '<i class="fa fa-code-fork"></i> View Fork',
  1516. output_text)
  1517. self.assertNotIn(
  1518. '<i class="fa fa-code-fork"></i>Fork</button>',
  1519. output_text)
  1520. self.perfMaxWalks(1, 3)
  1521. self.perfReset()
  1522. # Add a fork of a fork
  1523. item = pagure.lib.model.Project(
  1524. user_id=1, # pingou
  1525. name='test3',
  1526. description='test project #3',
  1527. is_fork=True,
  1528. parent_id=1,
  1529. hook_token='aaabbbmmm',
  1530. )
  1531. self.session.add(item)
  1532. self.session.commit()
  1533. tests.add_content_git_repo(
  1534. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test3.git'))
  1535. tests.add_readme_git_repo(
  1536. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test3.git'))
  1537. tests.add_commit_git_repo(
  1538. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test3.git'),
  1539. ncommits=10)
  1540. output = self.app.get('/fork/pingou/test3')
  1541. self.assertEqual(output.status_code, 200)
  1542. output_text = output.get_data(as_text=True)
  1543. self.assertNotIn('<p>This repo is brand new!</p>', output_text)
  1544. self.assertIn(
  1545. '<title>Overview - test3 - Pagure</title>', output_text)
  1546. self.assertIn('Forked from', output_text)
  1547. self.perfMaxWalks(3, 18) # Ideal: (1, 3)
  1548. self.perfReset()
  1549. def test_view_repo_empty(self):
  1550. """ Test the view_repo endpoint on a repo w/o master branch. """
  1551. tests.create_projects(self.session)
  1552. # Create a git repo to play with
  1553. gitrepo = os.path.join(self.path, 'repos', 'test.git')
  1554. pygit2.init_repository(gitrepo, bare=True)
  1555. # Create a fork of this repo
  1556. newpath = tempfile.mkdtemp(prefix='pagure-viewrepo-test')
  1557. new_repo = pygit2.clone_repository(gitrepo, newpath)
  1558. # Edit the sources file again
  1559. with open(os.path.join(newpath, 'sources'), 'w') as stream:
  1560. stream.write('foo\n bar\nbaz\n boose')
  1561. new_repo.index.add('sources')
  1562. new_repo.index.write()
  1563. # Commits the files added
  1564. tree = new_repo.index.write_tree()
  1565. author = pygit2.Signature(
  1566. 'Alice Author', 'alice@authors.tld')
  1567. committer = pygit2.Signature(
  1568. 'Cecil Committer', 'cecil@committers.tld')
  1569. new_repo.create_commit(
  1570. 'refs/heads/feature',
  1571. author,
  1572. committer,
  1573. 'A commit on branch feature',
  1574. tree,
  1575. []
  1576. )
  1577. refname = 'refs/heads/feature'
  1578. ori_remote = new_repo.remotes[0]
  1579. PagureRepo.push(ori_remote, refname)
  1580. output = self.app.get('/test')
  1581. self.assertEqual(output.status_code, 200)
  1582. output_text = output.get_data(as_text=True)
  1583. self.assertNotIn('<p>This repo is brand new!</p>', output_text)
  1584. self.assertNotIn('Forked from', output_text)
  1585. self.assertIn(
  1586. '<title>Overview - test - Pagure</title>', output_text)
  1587. self.assertEqual(
  1588. output_text.count('<span class="commitid">'), 0)
  1589. shutil.rmtree(newpath)
  1590. '''
  1591. def test_view_repo_branch(self):
  1592. """ Test the view_repo_branch endpoint. """
  1593. output = self.app.get('/foo/branch/master')
  1594. # No project registered in the DB
  1595. self.assertEqual(output.status_code, 404)
  1596. tests.create_projects(self.session)
  1597. output = self.app.get('/test/branch/master')
  1598. # No git repo associated
  1599. self.assertEqual(output.status_code, 404)
  1600. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  1601. output = self.app.get('/test/branch/master')
  1602. self.assertEqual(output.status_code, 404)
  1603. # Add some content to the git repo
  1604. tests.add_content_git_repo(os.path.join(self.path, 'repos',
  1605. 'test.git'))
  1606. tests.add_readme_git_repo(os.path.join(self.path, 'repos', 'test.git'))
  1607. # Turn that repo into a fork
  1608. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  1609. repo.parent_id = 2
  1610. repo.is_fork = True
  1611. self.session.add(repo)
  1612. self.session.commit()
  1613. # Add some content to the git repo
  1614. tests.add_content_git_repo(
  1615. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test.git'))
  1616. tests.add_readme_git_repo(
  1617. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test.git'))
  1618. output = self.app.get('/fork/pingou/test/')
  1619. self.assertEqual(output.status_code, 200)
  1620. output_text = output.get_data(as_text=True)
  1621. self.assertNotIn('<p>This repo is brand new!</p>', output_text)
  1622. self.assertIn('Forked from', output_text)
  1623. # Add a fork of a fork
  1624. item = pagure.lib.model.Project(
  1625. user_id=1, # pingou
  1626. name='test3',
  1627. description='test project #3',
  1628. is_fork=True,
  1629. parent_id=1,
  1630. hook_token='aaabbbnnn',
  1631. )
  1632. self.session.add(item)
  1633. self.session.commit()
  1634. tests.add_content_git_repo(
  1635. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test3.git'))
  1636. tests.add_readme_git_repo(
  1637. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test3.git'))
  1638. tests.add_commit_git_repo(
  1639. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test3.git'),
  1640. ncommits=10)
  1641. output = self.app.get('/fork/pingou/test3/')
  1642. self.assertEqual(output.status_code, 200)
  1643. output_text = output.get_data(as_text=True)
  1644. self.assertNotIn('<p>This repo is brand new!</p>', output_text)
  1645. self.assertIn('Forked from', output_text)
  1646. '''
  1647. def test_view_commits(self):
  1648. """ Test the view_commits endpoint. """
  1649. output = self.app.get('/foo/commits')
  1650. # No project registered in the DB
  1651. self.assertEqual(output.status_code, 404)
  1652. tests.create_projects(self.session)
  1653. output = self.app.get('/test/commits')
  1654. # No git repo associated
  1655. self.assertEqual(output.status_code, 404)
  1656. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  1657. output = self.app.get('/test/commits')
  1658. self.assertEqual(output.status_code, 200)
  1659. output_text = output.get_data(as_text=True)
  1660. self.assertIn('<p>This repo is brand new!</p>', output_text)
  1661. self.assertIn(
  1662. '<title>Commits - test - Pagure</title>', output_text)
  1663. # Add some content to the git repo
  1664. tests.add_content_git_repo(os.path.join(self.path, 'repos',
  1665. 'test.git'))
  1666. tests.add_readme_git_repo(os.path.join(self.path, 'repos', 'test.git'))
  1667. output = self.app.get('/test/commits')
  1668. self.assertEqual(output.status_code, 200)
  1669. output_text = output.get_data(as_text=True)
  1670. self.assertNotIn('<p>This repo is brand new!</p>', output_text)
  1671. self.assertNotIn('Forked from', output_text)
  1672. self.assertIn('<title>Commits - test - Pagure</title>', output_text)
  1673. output = self.app.get('/test/commits/master')
  1674. self.assertEqual(output.status_code, 200)
  1675. output_text = output.get_data(as_text=True)
  1676. self.assertNotIn('<p>This repo is brand new!</p>', output_text)
  1677. self.assertNotIn('Forked from', output_text)
  1678. self.assertIn(
  1679. '<title>Commits - test - Pagure</title>', output_text)
  1680. # Turn that repo into a fork
  1681. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  1682. repo.parent_id = 2
  1683. repo.is_fork = True
  1684. self.session.add(repo)
  1685. self.session.commit()
  1686. # View the repo in the UI
  1687. output = self.app.get('/test/commits')
  1688. self.assertEqual(output.status_code, 404)
  1689. # Add some content to the git repo
  1690. tests.add_content_git_repo(
  1691. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test.git'))
  1692. tests.add_readme_git_repo(
  1693. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test.git'))
  1694. output = self.app.get('/fork/pingou/test/commits?page=abc')
  1695. self.assertEqual(output.status_code, 200)
  1696. output_text = output.get_data(as_text=True)
  1697. self.assertNotIn('<p>This repo is brand new!</p>', output_text)
  1698. self.assertIn(
  1699. '<title>Commits - test - Pagure</title>', output_text)
  1700. self.assertIn('Forked from', output_text)
  1701. # Add a fork of a fork
  1702. item = pagure.lib.model.Project(
  1703. user_id=1, # pingou
  1704. name='test3',
  1705. description='test project #3',
  1706. is_fork=True,
  1707. parent_id=1,
  1708. hook_token='aaabbbooo',
  1709. )
  1710. self.session.add(item)
  1711. self.session.commit()
  1712. tests.add_content_git_repo(
  1713. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test3.git'))
  1714. tests.add_readme_git_repo(
  1715. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test3.git'))
  1716. tests.add_commit_git_repo(
  1717. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test3.git'),
  1718. ncommits=10)
  1719. # list is empty
  1720. output = self.app.get('/fork/pingou/test3/commits/fobranch')
  1721. self.assertEqual(output.status_code, 200)
  1722. output_text = output.get_data(as_text=True)
  1723. self.assertIn(
  1724. '<div class="list-group my-2">\n\n\n </div>',
  1725. output_text)
  1726. self.assertIn(
  1727. 'Commits <span class="badge badge-secondary"> 0</span>',
  1728. output_text)
  1729. output = self.app.get('/fork/pingou/test3/commits')
  1730. self.assertEqual(output.status_code, 200)
  1731. output_text = output.get_data(as_text=True)
  1732. self.assertNotIn('<p>This repo is brand new!</p>', output_text)
  1733. self.assertIn(
  1734. '<title>Commits - test3 - Pagure</title>', output_text)
  1735. self.assertIn('Forked from', output_text)
  1736. def test_view_commits_from_tag(self):
  1737. """ Test the view_commits endpoint given a tag. """
  1738. tests.create_projects(self.session)
  1739. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  1740. # Add a README to the git repo - First commit
  1741. tests.add_readme_git_repo(os.path.join(self.path, 'repos', 'test.git'))
  1742. repo = pygit2.Repository(os.path.join(self.path, 'repos', 'test.git'))
  1743. first_commit = repo.revparse_single('HEAD')
  1744. tagger = pygit2.Signature('Alice Doe', 'adoe@example.com', 12347, 0)
  1745. repo.create_tag(
  1746. "0.0.1", first_commit.oid.hex, pygit2.GIT_OBJ_COMMIT, tagger,
  1747. "Release 0.0.1")
  1748. tests.add_readme_git_repo(os.path.join(self.path, 'repos', 'test.git'))
  1749. repo = pygit2.Repository(os.path.join(self.path, 'repos', 'test.git'))
  1750. latest_commit = repo.revparse_single('HEAD')
  1751. output = self.app.get('/test/commits/0.0.1')
  1752. self.assertEqual(output.status_code, 200)
  1753. output_text = output.get_data(as_text=True)
  1754. self.assertIn(first_commit.oid.hex, output_text)
  1755. self.assertNotIn(latest_commit.oid.hex, output_text)
  1756. self.assertIn('<title>Commits - test - Pagure</title>', output_text)
  1757. self.assertEqual(
  1758. output_text.count('<span id="commit-actions">'), 1)
  1759. def test_compare_commits(self):
  1760. """ Test the compare_commits endpoint. """
  1761. # First two commits comparison
  1762. def compare_first_two(c1, c2):
  1763. # View commits comparison
  1764. output = self.app.get('/test/c/%s..%s' % (c2.oid.hex, c1.oid.hex))
  1765. self.assertEqual(output.status_code, 200)
  1766. output_text = output.get_data(as_text=True)
  1767. self.assertIn(
  1768. '<title>Diff from %s to %s - test\n - Pagure</title>'
  1769. % (c2.oid.hex, c1.oid.hex),
  1770. output_text)
  1771. self.assertIn(
  1772. ' <span class="badge-light border border-secondary badge">%s</span>\n ..\n <span class="badge-light border border-secondary badge">%s</span>\n' %
  1773. (c2.oid.hex, c1.oid.hex),
  1774. output_text)
  1775. self.assertNotIn(
  1776. 'id="show_hidden_commits"',
  1777. output_text)
  1778. self.assertIn('<pre class="alert-danger"><code>- Row 0</code></pre>', output_text)
  1779. # View inverse commits comparison
  1780. output = self.app.get('/test/c/%s..%s' % (c1.oid.hex, c2.oid.hex))
  1781. self.assertEqual(output.status_code, 200)
  1782. output_text = output.get_data(as_text=True)
  1783. self.assertIn(
  1784. '<title>Diff from %s to %s - test\n - Pagure</title>' %
  1785. (c1.oid.hex, c2.oid.hex),
  1786. output_text)
  1787. self.assertNotIn(
  1788. 'id="show_hidden_commits"',
  1789. output_text)
  1790. self.assertIn(
  1791. ' <span class="badge-light border border-secondary badge">%s</span>\n ..\n <span class="badge-light border border-secondary badge">%s</span>\n' %
  1792. (c1.oid.hex, c2.oid.hex),
  1793. output_text)
  1794. self.assertIn('<pre class="alert-success"><code>+ Row 0</code></pre>', output_text)
  1795. def compare_all(c1, c3):
  1796. # View commits comparison
  1797. output = self.app.get('/test/c/%s..%s' % (c1.oid.hex, c3.oid.hex))
  1798. self.assertEqual(output.status_code, 200)
  1799. output_text = output.get_data(as_text=True)
  1800. self.assertIn(
  1801. '<title>Diff from %s to %s - test\n - Pagure</title>' %
  1802. (c1.oid.hex, c3.oid.hex), output_text)
  1803. self.assertIn(
  1804. ' <span class="badge-light border border-secondary badge">%s</span>\n ..\n <span class="badge-light border border-secondary badge">%s</span>\n' %
  1805. (c1.oid.hex, c3.oid.hex),
  1806. output_text)
  1807. self.assertIn('<pre class="alert-success"><code>+ Row 0</code></pre>', output_text)
  1808. self.assertEqual(
  1809. output_text.count('<pre class="alert-success"><code>+ Row 0</code></pre>'), 2)
  1810. self.assertIn(
  1811. '<a href="javascript:void(0)">1 more commits...',
  1812. output_text)
  1813. self.assertIn(
  1814. 'title="View file as of 4829cf">Šource</a>',
  1815. output_text
  1816. )
  1817. self.assertIn(
  1818. '<div class="btn btn-outline-success disabled opacity-100 border-0 font-weight-bold">\n'
  1819. ' file added\n', output_text)
  1820. # View inverse commits comparison
  1821. output = self.app.get(
  1822. '/test/c/%s..%s' % (c3.oid.hex, c1.oid.hex))
  1823. self.assertEqual(output.status_code, 200)
  1824. output_text = output.get_data(as_text=True)
  1825. self.assertIn(
  1826. '<title>Diff from %s to %s - test\n - Pagure</title>' %
  1827. (c3.oid.hex, c1.oid.hex), output_text)
  1828. self.assertIn(
  1829. ' <span class="badge-light border border-secondary badge">%s</span>\n ..\n <span class="badge-light border border-secondary badge">%s</span>\n' %
  1830. (c3.oid.hex, c1.oid.hex),
  1831. output_text)
  1832. self.assertIn(
  1833. '<pre class="text-muted"><code>@@ -1,2 +1,1 @@</code></pre>', output_text)
  1834. self.assertIn('<pre class="alert-danger"><code>- Row 0</code></pre>', output_text)
  1835. self.assertIn(
  1836. '<a href="javascript:void(0)">1 more commits...',
  1837. output_text)
  1838. self.assertIn(
  1839. 'title="View file as of 000000">Šource</a>',
  1840. output_text
  1841. )
  1842. self.assertIn(
  1843. '<div class="btn btn-outline-danger disabled opacity-100 border-0 font-weight-bold">\n'
  1844. ' file removed\n', output_text)
  1845. output = self.app.get('/foo/bar')
  1846. # No project registered in the DB
  1847. self.assertEqual(output.status_code, 404)
  1848. tests.create_projects(self.session)
  1849. output = self.app.get('/test/bar')
  1850. # No git repo associated
  1851. self.assertEqual(output.status_code, 404)
  1852. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  1853. output = self.app.get('/test/bar')
  1854. self.assertEqual(output.status_code, 404)
  1855. repo = pygit2.Repository(os.path.join(self.path, 'repos', 'test.git'))
  1856. # Add one commit to git repo
  1857. tests.add_commit_git_repo(
  1858. os.path.join(self.path, 'repos', 'test.git'), ncommits=1)
  1859. c1 = repo.revparse_single('HEAD')
  1860. time.sleep(1)
  1861. # Add another commit to git repo
  1862. tests.add_commit_git_repo(
  1863. os.path.join(self.path, 'repos', 'test.git'), ncommits=1)
  1864. c2 = repo.revparse_single('HEAD')
  1865. time.sleep(1)
  1866. # Add one more commit to git repo
  1867. tests.add_commit_git_repo(
  1868. os.path.join(self.path, 'repos', 'test.git'),
  1869. ncommits=1, filename='Šource')
  1870. c3 = repo.revparse_single('HEAD')
  1871. compare_first_two(c1, c2)
  1872. compare_all(c1, c3)
  1873. user = tests.FakeUser()
  1874. # Set user logged in
  1875. with tests.user_set(self.app.application, user):
  1876. compare_first_two(c1, c2)
  1877. compare_all(c1, c3)
  1878. def test_view_file(self):
  1879. """ Test the view_file endpoint. """
  1880. output = self.app.get('/foo/blob/foo/f/sources')
  1881. # No project registered in the DB
  1882. self.assertEqual(output.status_code, 404)
  1883. tests.create_projects(self.session)
  1884. output = self.app.get('/test/blob/foo/f/sources')
  1885. # No git repo associated
  1886. self.assertEqual(output.status_code, 404)
  1887. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  1888. output = self.app.get('/test/blob/foo/f/sources')
  1889. self.assertEqual(output.status_code, 404)
  1890. # Add some content to the git repo
  1891. tests.add_content_git_repo(os.path.join(self.path, 'repos',
  1892. 'test.git'))
  1893. tests.add_readme_git_repo(os.path.join(self.path, 'repos', 'test.git'))
  1894. tests.add_binary_git_repo(
  1895. os.path.join(self.path, 'repos', 'test.git'), 'test.jpg')
  1896. tests.add_binary_git_repo(
  1897. os.path.join(self.path, 'repos', 'test.git'), 'test_binary')
  1898. output = self.app.get('/test/blob/master/foofile')
  1899. self.assertEqual(output.status_code, 404)
  1900. # View in a branch
  1901. output = self.app.get('/test/blob/master/f/sources')
  1902. self.assertEqual(output.status_code, 200)
  1903. output_text = output.get_data(as_text=True)
  1904. self.assertIn(
  1905. '<pre class="syntaxhighlightblock"><code>foo\n bar</code></pre>',
  1906. output_text)
  1907. # Empty files should also be displayed
  1908. tests.add_content_to_git(
  1909. os.path.join(self.path, 'repos', 'test.git'),
  1910. filename="emptyfile.md",
  1911. content="")
  1912. output = self.app.get('/test/blob/master/f/emptyfile.md')
  1913. self.assertEqual(output.status_code, 200)
  1914. output_text = output.get_data(as_text=True)
  1915. self.assertIn(
  1916. '<a class="btn btn-secondary btn-sm" '
  1917. 'href="/test/raw/master/f/emptyfile.md" '
  1918. 'title="View as raw">Raw</a>', output_text)
  1919. self.assertIn(
  1920. '<div class="m-2">\n'
  1921. ' \n </div>', output_text)
  1922. # View what's supposed to be an image
  1923. output = self.app.get('/test/blob/master/f/test.jpg')
  1924. self.assertEqual(output.status_code, 200)
  1925. output_text = output.get_data(as_text=True)
  1926. self.assertIn(
  1927. 'Binary files cannot be rendered.<br/>', output_text)
  1928. self.assertIn(
  1929. '<a href="/test/raw/master/f/test.jpg">view the raw version',
  1930. output_text)
  1931. # View by commit id
  1932. repo = pygit2.Repository(os.path.join(self.path, 'repos', 'test.git'))
  1933. commit = repo.revparse_single('HEAD')
  1934. output = self.app.get('/test/blob/%s/f/test.jpg' % commit.oid.hex)
  1935. self.assertEqual(output.status_code, 200)
  1936. output_text = output.get_data(as_text=True)
  1937. self.assertIn(
  1938. 'Binary files cannot be rendered.<br/>', output_text)
  1939. self.assertIn('/f/test.jpg">view the raw version', output_text)
  1940. # View by image name -- somehow we support this
  1941. output = self.app.get('/test/blob/sources/f/test.jpg')
  1942. self.assertEqual(output.status_code, 200)
  1943. output_text = output.get_data(as_text=True)
  1944. self.assertIn(
  1945. 'Binary files cannot be rendered.<br/>', output_text)
  1946. self.assertIn('/f/test.jpg">view the raw version', output_text)
  1947. # View binary file
  1948. output = self.app.get('/test/blob/sources/f/test_binary')
  1949. self.assertEqual(output.status_code, 200)
  1950. output_text = output.get_data(as_text=True)
  1951. self.assertIn('/f/test_binary">view the raw version', output_text)
  1952. self.assertIn(
  1953. 'Binary files cannot be rendered.<br/>', output_text)
  1954. # View folder
  1955. output = self.app.get('/test/blob/master/f/folder1')
  1956. self.assertEqual(output.status_code, 200)
  1957. output_text = output.get_data(as_text=True)
  1958. self.assertIn(
  1959. '<li class="active breadcrumb-item">\n '
  1960. '<span class="fa fa-folder" data-glyph="">\n '
  1961. '</span>&nbsp; folder1\n </li>',
  1962. output_text)
  1963. self.assertIn('<title>Tree - test - Pagure</title>', output_text)
  1964. self.assertIn(
  1965. '<a href="/test/blob/master/f/folder1/folder2">', output_text)
  1966. # Verify the nav links correctly when viewing a nested folder/file.
  1967. output = self.app.get('/test/blob/master/f/folder1/folder2/file')
  1968. self.assertEqual(output.status_code, 200)
  1969. output_text = output.get_data(as_text=True)
  1970. self.assertIn(
  1971. '<li class="breadcrumb-item"><a href="/test/blob/master/f/folder1/folder2">'
  1972. '\n <span class="fa fa-folder"></span>&nbsp; folder2</a>\n'
  1973. ' </li>', output_text)
  1974. # View by image name -- with a non-existant file
  1975. output = self.app.get('/test/blob/sources/f/testfoo.jpg')
  1976. self.assertEqual(output.status_code, 404)
  1977. output = self.app.get('/test/blob/master/f/folder1/testfoo.jpg')
  1978. self.assertEqual(output.status_code, 404)
  1979. # View file with a non-ascii name
  1980. tests.add_commit_git_repo(
  1981. os.path.join(self.path, 'repos', 'test.git'),
  1982. ncommits=1, filename='Šource')
  1983. output = self.app.get('/test/blob/master/f/Šource')
  1984. self.assertEqual(output.status_code, 200)
  1985. output_text = output.get_data(as_text=True)
  1986. self.assertEqual(output.headers['Content-Type'].lower(),
  1987. 'text/html; charset=utf-8')
  1988. self.assertIn(
  1989. '</span>&nbsp; Šource',
  1990. output_text)
  1991. self.assertIn(
  1992. '<pre class="syntaxhighlightblock"><code>Row 0\n</code></pre>',
  1993. output_text
  1994. )
  1995. # Add a fork of a fork
  1996. item = pagure.lib.model.Project(
  1997. user_id=1, # pingou
  1998. name='test3',
  1999. description='test project #3',
  2000. is_fork=True,
  2001. parent_id=1,
  2002. hook_token='aaabbbppp',
  2003. )
  2004. self.session.add(item)
  2005. self.session.commit()
  2006. tests.add_content_git_repo(
  2007. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test3.git'))
  2008. tests.add_readme_git_repo(
  2009. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test3.git'))
  2010. tests.add_commit_git_repo(
  2011. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test3.git'),
  2012. ncommits=10)
  2013. # Verify the nav links correctly when viewing a file/folder in a fork.
  2014. output = self.app.get(
  2015. '/fork/pingou/test3/blob/master/f/folder1/folder2/file')
  2016. self.assertEqual(output.status_code, 200)
  2017. output_text = output.get_data(as_text=True)
  2018. self.assertIn(
  2019. '<li class="breadcrumb-item">'
  2020. '<a href="/fork/pingou/test3/blob/master/f/folder1/folder2">'
  2021. '\n <span class="fa fa-folder"></span>'
  2022. '&nbsp; folder2</a>\n </li>', output_text)
  2023. output = self.app.get('/fork/pingou/test3/blob/master/f/sources')
  2024. self.assertEqual(output.status_code, 200)
  2025. output_text = output.get_data(as_text=True)
  2026. self.assertIn(
  2027. '<pre class="syntaxhighlightblock"><code>foo\n barRow 0\n'
  2028. 'Row 1\nRow 2\nRow 3\nRow 4\nRow 5\nRow 6\nRow 7\nRow 8\n'
  2029. 'Row 9\n</code></pre>', output_text)
  2030. @patch(
  2031. 'pagure.lib.encoding_utils.decode',
  2032. MagicMock(side_effect=pagure.exceptions.PagureException))
  2033. def test_view_file_with_wrong_encoding(self):
  2034. """ Test the view_file endpoint. """
  2035. tests.create_projects(self.session)
  2036. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  2037. # Add some content to the git repo
  2038. tests.add_content_git_repo(os.path.join(self.path, 'repos',
  2039. 'test.git'))
  2040. tests.add_readme_git_repo(os.path.join(self.path, 'repos', 'test.git'))
  2041. tests.add_binary_git_repo(
  2042. os.path.join(self.path, 'repos', 'test.git'), 'test.jpg')
  2043. tests.add_binary_git_repo(
  2044. os.path.join(self.path, 'repos', 'test.git'), 'test_binary')
  2045. # View file
  2046. output = self.app.get('/test/blob/master/f/sources')
  2047. self.assertEqual(output.status_code, 200)
  2048. output_text = output.get_data(as_text=True)
  2049. self.assertIn('Binary files cannot be rendered.<br/>', output_text)
  2050. def test_view_raw_file(self):
  2051. """ Test the view_raw_file endpoint. """
  2052. output = self.app.get('/foo/raw/foo/sources')
  2053. # No project registered in the DB
  2054. self.assertEqual(output.status_code, 404)
  2055. tests.create_projects(self.session)
  2056. output = self.app.get('/test/raw/foo/sources')
  2057. # No git repo associated
  2058. self.assertEqual(output.status_code, 404)
  2059. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  2060. output = self.app.get('/test/raw/foo/sources')
  2061. self.assertEqual(output.status_code, 404)
  2062. # Add some content to the git repo
  2063. tests.add_readme_git_repo(os.path.join(self.path, 'repos', 'test.git'))
  2064. # View first commit
  2065. output = self.app.get('/test/raw/master')
  2066. self.assertEqual(output.status_code, 200)
  2067. output_text = output.get_data(as_text=True)
  2068. self.assertEqual(output.headers['Content-Type'].lower(),
  2069. 'text/plain; charset=ascii')
  2070. self.assertIn(':Author: Pierre-Yves Chibon', output_text)
  2071. # Add some more content to the repo
  2072. tests.add_content_git_repo(os.path.join(self.path, 'repos',
  2073. 'test.git'))
  2074. tests.add_binary_git_repo(
  2075. os.path.join(self.path, 'repos', 'test.git'), 'test.jpg')
  2076. tests.add_binary_git_repo(
  2077. os.path.join(self.path, 'repos', 'test.git'), 'test_binary')
  2078. output = self.app.get('/test/raw/master/f/foofile')
  2079. self.assertEqual(output.status_code, 404)
  2080. # View in a branch
  2081. output = self.app.get('/test/raw/master/f/sources')
  2082. self.assertEqual(output.headers['Content-Type'].lower(),
  2083. 'text/plain; charset=ascii')
  2084. self.assertEqual(output.status_code, 200)
  2085. output_text = output.get_data(as_text=True)
  2086. self.assertIn('foo\n bar', output_text)
  2087. # View what's supposed to be an image
  2088. output = self.app.get('/test/raw/master/f/test.jpg')
  2089. self.assertEqual(output.status_code, 200)
  2090. output_text = output.get_data()
  2091. self.assertTrue(output_text.startswith(b'\x00\x00\x01\x00'))
  2092. # View by commit id
  2093. repo = pygit2.Repository(os.path.join(self.path, 'repos', 'test.git'))
  2094. commit = repo.revparse_single('HEAD')
  2095. output = self.app.get('/test/raw/%s/f/test.jpg' % commit.oid.hex)
  2096. self.assertEqual(output.status_code, 200)
  2097. output_text = output.get_data()
  2098. self.assertTrue(output_text.startswith(b'\x00\x00\x01\x00'))
  2099. # View by image name -- somehow we support this
  2100. output = self.app.get('/test/raw/sources/f/test.jpg')
  2101. self.assertEqual(output.status_code, 200)
  2102. output_text = output.get_data()
  2103. self.assertTrue(output_text.startswith(b'\x00\x00\x01\x00'))
  2104. # View binary file
  2105. output = self.app.get('/test/raw/sources/f/test_binary')
  2106. self.assertEqual(output.status_code, 200)
  2107. output_text = output.get_data()
  2108. self.assertEqual(output.headers['Content-Type'].lower(),
  2109. 'application/octet-stream')
  2110. self.assertTrue(output_text.startswith(b'\x00\x00\x01\x00'))
  2111. # View folder
  2112. output = self.app.get('/test/raw/master/f/folder1')
  2113. self.assertEqual(output.status_code, 404)
  2114. # View by image name -- with a non-existant file
  2115. output = self.app.get('/test/raw/sources/f/testfoo.jpg')
  2116. self.assertEqual(output.status_code, 404)
  2117. output = self.app.get('/test/raw/master/f/folder1/testfoo.jpg')
  2118. self.assertEqual(output.status_code, 404)
  2119. output = self.app.get('/test/raw/master/f/')
  2120. self.assertEqual(output.status_code, 404)
  2121. output = self.app.get('/test/raw/master')
  2122. self.assertEqual(output.status_code, 200)
  2123. output_text = output.get_data(as_text=True)
  2124. self.assertEqual(output.headers['Content-Type'].lower(),
  2125. 'text/plain; charset=ascii')
  2126. self.assertTrue(output_text.startswith(
  2127. 'diff --git a/test_binary b/test_binary\n'))
  2128. output = self.app.get('/test/raw/%s' % commit.oid.hex)
  2129. self.assertEqual(output.status_code, 200)
  2130. output_text = output.get_data(as_text=True)
  2131. self.assertTrue(output_text.startswith(
  2132. 'diff --git a/test_binary b/test_binary\n'))
  2133. # Add a fork of a fork
  2134. item = pagure.lib.model.Project(
  2135. user_id=1, # pingou
  2136. name='test3',
  2137. description='test project #3',
  2138. is_fork=True,
  2139. parent_id=1,
  2140. hook_token='aaabbbqqq',
  2141. )
  2142. self.session.add(item)
  2143. self.session.commit()
  2144. tests.add_content_git_repo(
  2145. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test3.git'))
  2146. tests.add_readme_git_repo(
  2147. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test3.git'))
  2148. tests.add_commit_git_repo(
  2149. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test3.git'),
  2150. ncommits=10)
  2151. output = self.app.get('/fork/pingou/test3/raw/master/f/sources')
  2152. self.assertEqual(output.status_code, 200)
  2153. output_text = output.get_data(as_text=True)
  2154. self.assertEqual(output.headers['Content-Type'].lower(),
  2155. 'text/plain; charset=ascii')
  2156. self.assertIn('foo\n bar', output_text)
  2157. def test_view_blame_file(self):
  2158. """ Test the view_blame_file endpoint. """
  2159. output = self.app.get('/foo/blame/sources')
  2160. # No project registered in the DB
  2161. self.assertEqual(output.status_code, 404)
  2162. tests.create_projects(self.session)
  2163. output = self.app.get('/test/blame/sources')
  2164. # No git repo associated
  2165. self.assertEqual(output.status_code, 404)
  2166. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  2167. output = self.app.get('/test/blame/sources')
  2168. self.assertEqual(output.status_code, 404)
  2169. # Add some content to the git repo
  2170. tests.add_content_git_repo(
  2171. os.path.join(self.path, 'repos', 'test.git'))
  2172. tests.add_content_git_repo(
  2173. os.path.join(self.path, 'repos', 'test.git'),
  2174. branch='feature')
  2175. tests.add_readme_git_repo(os.path.join(self.path, 'repos', 'test.git'))
  2176. tests.add_binary_git_repo(
  2177. os.path.join(self.path, 'repos', 'test.git'), 'test.jpg')
  2178. tests.add_binary_git_repo(
  2179. os.path.join(self.path, 'repos', 'test.git'), 'test_binary')
  2180. output = self.app.get('/test/blame/foofile')
  2181. self.assertEqual(output.status_code, 404)
  2182. regex = re.compile(r'>(\w+)</a></td>\n<td class="cell2">')
  2183. # View in master branch
  2184. output = self.app.get('/test/blame/sources')
  2185. self.assertEqual(output.status_code, 200)
  2186. output_text = output.get_data(as_text=True)
  2187. self.assertIn('<table class="code_table">', output_text)
  2188. self.assertIn(
  2189. '<tr><td class="cell1"><a id="1" href="#1" '
  2190. 'data-line-number="1"></a></td>', output_text)
  2191. self.assertIn(
  2192. '<td class="cell2"><pre><code> bar</code></pre></td>', output_text)
  2193. data = regex.findall(output_text)
  2194. self.assertEqual(len(data), 2)
  2195. # View for a commit
  2196. repo_obj = pygit2.Repository(
  2197. os.path.join(self.path, 'repos', 'test.git'))
  2198. commit = repo_obj[repo_obj.head.target]
  2199. parent = commit.parents[0].oid.hex
  2200. output = self.app.get('/test/blame/sources?identifier=%s' % parent)
  2201. self.assertEqual(output.status_code, 200)
  2202. output_text = output.get_data(as_text=True)
  2203. self.assertIn('<table class="code_table">', output_text)
  2204. self.assertIn(
  2205. '<tr><td class="cell1"><a id="1" href="#1" '
  2206. 'data-line-number="1"></a></td>', output_text)
  2207. self.assertIn(
  2208. '<td class="cell2"><pre><code> bar</code></pre></td>', output_text)
  2209. data1 = regex.findall(output_text)
  2210. self.assertEqual(len(data1), 2)
  2211. self.assertEqual(data, data1)
  2212. # View in feature branch
  2213. output = self.app.get('/test/blame/sources?identifier=feature')
  2214. self.assertEqual(output.status_code, 200)
  2215. output_text = output.get_data(as_text=True)
  2216. self.assertIn('<table class="code_table">', output_text)
  2217. self.assertIn(
  2218. '<tr><td class="cell1"><a id="1" href="#1" '
  2219. 'data-line-number="1"></a></td>', output_text)
  2220. self.assertIn(
  2221. '<td class="cell2"><pre><code> bar</code></pre></td>', output_text)
  2222. data2 = regex.findall(output_text)
  2223. self.assertEqual(len(data2), 3)
  2224. self.assertEqual(data[0], data2[0])
  2225. self.assertNotEqual(data2[0], data2[1])
  2226. self.assertEqual(data2[1], data2[2])
  2227. # View what's supposed to be an image
  2228. output = self.app.get('/test/blame/test.jpg')
  2229. self.assertEqual(output.status_code, 400)
  2230. output_text = output.get_data(as_text=True)
  2231. self.assertIn(
  2232. '<title>400 Bad Request</title>', output_text)
  2233. self.assertIn(
  2234. '<p>Binary files cannot be blamed</p>', output_text)
  2235. # View folder
  2236. output = self.app.get('/test/blame/folder1')
  2237. self.assertEqual(output.status_code, 404)
  2238. output_text = output.get_data(as_text=True)
  2239. self.assertIn("<title>Page not found :'( - Pagure</title>", output_text)
  2240. self.assertIn(
  2241. '<h2>Page not found (404)</h2>', output_text)
  2242. # View by image name -- with a non-existant file
  2243. output = self.app.get('/test/blame/testfoo.jpg')
  2244. self.assertEqual(output.status_code, 404)
  2245. output = self.app.get('/test/blame/folder1/testfoo.jpg')
  2246. self.assertEqual(output.status_code, 404)
  2247. # View file with a non-ascii name
  2248. tests.add_commit_git_repo(
  2249. os.path.join(self.path, 'repos', 'test.git'),
  2250. ncommits=1, filename='Šource')
  2251. output = self.app.get('/test/blame/Šource')
  2252. self.assertEqual(output.status_code, 200)
  2253. output_text = output.get_data(as_text=True)
  2254. self.assertEqual(output.headers['Content-Type'].lower(),
  2255. 'text/html; charset=utf-8')
  2256. self.assertIn(
  2257. '</span>&nbsp; Šource',
  2258. output_text
  2259. )
  2260. self.assertIn(
  2261. '<table class="code_table">', output_text)
  2262. self.assertIn(
  2263. '<tr><td class="cell1"><a id="1" href="#1" '
  2264. 'data-line-number="1"></a></td>', output_text)
  2265. self.assertIn(
  2266. '<td class="cell2"><pre><code>Row 0</code></pre></td>',
  2267. output_text
  2268. )
  2269. # Add a fork of a fork
  2270. item = pagure.lib.model.Project(
  2271. user_id=1, # pingou
  2272. name='test3',
  2273. description='test project #3',
  2274. is_fork=True,
  2275. parent_id=1,
  2276. hook_token='aaabbbppp',
  2277. )
  2278. self.session.add(item)
  2279. self.session.commit()
  2280. tests.add_content_git_repo(
  2281. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test3.git'))
  2282. tests.add_readme_git_repo(
  2283. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test3.git'))
  2284. tests.add_commit_git_repo(
  2285. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test3.git'),
  2286. ncommits=10)
  2287. tests.add_content_to_git(
  2288. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test3.git'),
  2289. content='✨☃🍰☃✨')
  2290. output = self.app.get('/fork/pingou/test3/blame/sources')
  2291. self.assertEqual(output.status_code, 200)
  2292. output_text = output.get_data(as_text=True)
  2293. self.assertIn('<table class="code_table">', output_text)
  2294. self.assertIn(
  2295. '<tr><td class="cell1"><a id="1" href="#1" '
  2296. 'data-line-number="1"></a></td>', output_text)
  2297. self.assertIn(
  2298. '<td class="cell2"><pre><code> barRow 0</code></pre></td>',
  2299. output_text)
  2300. def test_view_blame_file_on_tag(self):
  2301. """ Test the view_blame_file endpoint. """
  2302. regex = re.compile(r'>(\w+)</a></td>\n<td class="cell2">')
  2303. tests.create_projects(self.session)
  2304. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  2305. # Add some content to the git repo
  2306. tests.add_content_git_repo(
  2307. os.path.join(self.path, 'repos', 'test.git'))
  2308. tests.add_readme_git_repo(
  2309. os.path.join(self.path, 'repos', 'test.git'))
  2310. # add a tag to the git repo
  2311. repo = pygit2.Repository(
  2312. os.path.join(self.path, 'repos', 'test.git'))
  2313. commit = repo[repo.head.target]
  2314. tagger = pygit2.Signature('Alice Doe', 'adoe@example.com', 12347, 0)
  2315. repo.create_tag(
  2316. 'v1.0', commit.oid.hex, pygit2.GIT_OBJ_COMMIT, tagger,
  2317. "Release v1.0")
  2318. # View for tag v1.0
  2319. output = self.app.get('/test/blame/sources?identifier=v1.0')
  2320. self.assertEqual(output.status_code, 200)
  2321. output_text = output.get_data(as_text=True)
  2322. self.assertIn('<table class="code_table">', output_text)
  2323. self.assertIn(
  2324. '<tr><td class="cell1"><a id="1" href="#1" '
  2325. 'data-line-number="1"></a></td>', output_text)
  2326. self.assertIn(
  2327. '<td class="cell2"><pre><code> bar</code></pre></td>', output_text)
  2328. data = regex.findall(output_text)
  2329. self.assertEqual(len(data), 2)
  2330. def test_view_commit(self):
  2331. """ Test the view_commit endpoint. """
  2332. output = self.app.get('/foo/c/bar')
  2333. # No project registered in the DB
  2334. self.assertEqual(output.status_code, 404)
  2335. tests.create_projects(self.session)
  2336. output = self.app.get('/test/c/bar')
  2337. # No git repo associated
  2338. self.assertEqual(output.status_code, 404)
  2339. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  2340. output = self.app.get('/test/c/bar')
  2341. self.assertEqual(output.status_code, 404)
  2342. # Add a README to the git repo - First commit
  2343. tests.add_readme_git_repo(os.path.join(self.path, 'repos', 'test.git'))
  2344. repo = pygit2.Repository(os.path.join(self.path, 'repos', 'test.git'))
  2345. commit = repo.revparse_single('HEAD')
  2346. # View first commit
  2347. output = self.app.get('/test/c/%s' % commit.oid.hex)
  2348. self.assertEqual(output.status_code, 200)
  2349. output_text = output.get_data(as_text=True)
  2350. self.assertIn(
  2351. '#commit-overview-collapse',
  2352. output_text)
  2353. self.assertIn('Merged by Alice Author', output_text)
  2354. self.assertIn('Committed by Cecil Committer', output_text)
  2355. self.assertIn(
  2356. '<div class="btn btn-outline-success disabled opacity-100 '
  2357. 'border-0 font-weight-bold">file added</div>', output_text)
  2358. # View first commit - with the old URL scheme disabled - default
  2359. output = self.app.get(
  2360. '/test/%s' % commit.oid.hex, follow_redirects=True)
  2361. self.assertEqual(output.status_code, 404)
  2362. output_text = output.get_data(as_text=True)
  2363. self.assertIn('<p>Project not found</p>', output_text)
  2364. # Add some content to the git repo
  2365. tests.add_content_git_repo(os.path.join(self.path, 'repos',
  2366. 'test.git'))
  2367. repo = pygit2.Repository(os.path.join(self.path, 'repos', 'test.git'))
  2368. commit = repo.revparse_single('HEAD')
  2369. # View another commit
  2370. output = self.app.get('/test/c/%s' % commit.oid.hex)
  2371. self.assertEqual(output.status_code, 200)
  2372. output_text = output.get_data(as_text=True)
  2373. self.assertIn(
  2374. '#commit-overview-collapse',
  2375. output_text)
  2376. self.assertIn('Authored by Alice Author', output_text)
  2377. self.assertIn('Committed by Cecil Committer', output_text)
  2378. #View the commit when branch name is provided
  2379. output = self.app.get('/test/c/%s?branch=master' % commit.oid.hex)
  2380. self.assertEqual(output.status_code, 200)
  2381. output_text = output.get_data(as_text=True)
  2382. self.assertIn(
  2383. '<a class=\n "nav-link nowrap\n active"\n '
  2384. 'href="/test/commits/master">\n <i class="fa fa-list-alt '
  2385. 'text-muted fa-fw" data-glyph="spreadsheet"></i>&nbsp;Commits'
  2386. '\n </a>', output_text)
  2387. #View the commit when branch name is wrong, show the commit
  2388. output = self.app.get('/test/c/%s?branch=abcxyz' % commit.oid.hex)
  2389. self.assertEqual(output.status_code, 200)
  2390. output_text = output.get_data(as_text=True)
  2391. self.assertIn(
  2392. '<a class=\n "nav-link nowrap\n active"\n '
  2393. 'href="/test/commits">\n <i class="fa fa-list-alt '
  2394. 'text-muted fa-fw" data-glyph="spreadsheet"></i>&nbsp;Commits'
  2395. '\n </a>', output_text)
  2396. # Add a fork of a fork
  2397. item = pagure.lib.model.Project(
  2398. user_id=1, # pingou
  2399. name='test3',
  2400. description='test project #3',
  2401. is_fork=True,
  2402. parent_id=1,
  2403. hook_token='aaabbbkkk',
  2404. )
  2405. self.session.add(item)
  2406. self.session.commit()
  2407. forkedgit = os.path.join(
  2408. self.path, 'repos', 'forks', 'pingou', 'test3.git')
  2409. tests.add_content_git_repo(forkedgit)
  2410. tests.add_readme_git_repo(forkedgit)
  2411. repo = pygit2.Repository(forkedgit)
  2412. commit = repo.revparse_single('HEAD')
  2413. # Commit does not exist in anothe repo :)
  2414. output = self.app.get('/test/c/%s' % commit.oid.hex)
  2415. self.assertEqual(output.status_code, 404)
  2416. # View commit of fork
  2417. output = self.app.get(
  2418. '/fork/pingou/test3/c/%s' % commit.oid.hex)
  2419. self.assertEqual(output.status_code, 200)
  2420. output_text = output.get_data(as_text=True)
  2421. self.assertIn(
  2422. '#commit-overview-collapse',
  2423. output_text)
  2424. self.assertIn('Authored by Alice Author', output_text)
  2425. self.assertIn('Committed by Cecil Committer', output_text)
  2426. # Try the old URL scheme with a short hash
  2427. output = self.app.get(
  2428. '/fork/pingou/test3/%s' % commit.oid.hex[:10],
  2429. follow_redirects=True)
  2430. self.assertEqual(output.status_code, 404)
  2431. output_text = output.get_data(as_text=True)
  2432. self.assertIn('<p>Project not found</p>', output_text)
  2433. #View the commit of the fork when branch name is provided
  2434. output = self.app.get('/fork/pingou/test3/c/%s?branch=master' % commit.oid.hex)
  2435. self.assertEqual(output.status_code, 200)
  2436. output_text = output.get_data(as_text=True)
  2437. self.assertIn(
  2438. '<a class=\n "nav-link nowrap\n active"\n '
  2439. 'href="/fork/pingou/test3/commits/master">\n '
  2440. '<i class="fa fa-list-alt '
  2441. 'text-muted fa-fw" data-glyph="spreadsheet"></i>&nbsp;Commits'
  2442. '\n </a>', output_text)
  2443. #View the commit of the fork when branch name is wrong
  2444. output = self.app.get('/fork/pingou/test3/c/%s?branch=abcxyz' % commit.oid.hex)
  2445. self.assertEqual(output.status_code, 200)
  2446. output_text = output.get_data(as_text=True)
  2447. self.assertIn(
  2448. '<a class=\n "nav-link nowrap\n active"\n '
  2449. 'href="/fork/pingou/test3/commits">\n <i class="fa fa-list-alt '
  2450. 'text-muted fa-fw" data-glyph="spreadsheet"></i>&nbsp;Commits'
  2451. '\n </a>', output_text)
  2452. def test_view_commit_with_full_link(self):
  2453. """ Test the view_commit endpoint when the commit message includes
  2454. an url. """
  2455. tests.create_projects(self.session)
  2456. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  2457. folder = os.path.join(self.path, 'repos', 'test.git')
  2458. # Add a README to the git repo - First commit
  2459. tests.add_readme_git_repo(folder)
  2460. tests.create_projects_git(folder, bare=True)
  2461. # Add a commit with an url in the commit message
  2462. tests.add_content_to_git(
  2463. folder, branch='master', filename='sources', content='foo',
  2464. message='Test commit message\n\n'
  2465. 'Fixes http://example.com/pagure/issue/2'
  2466. )
  2467. # Add a README to the git repo - First commit
  2468. repo = pygit2.Repository(os.path.join(self.path, 'repos', 'test.git'))
  2469. commit = repo.revparse_single('HEAD')
  2470. # View first commit
  2471. output = self.app.get('/test/c/%s' % commit.oid.hex)
  2472. self.assertEqual(output.status_code, 200)
  2473. output_text = output.get_data(as_text=True)
  2474. self.assertIn(
  2475. '#commit-overview-collapse',
  2476. output_text)
  2477. self.assertIn(
  2478. '<pre class="commit_message_body">\n '
  2479. 'Test commit message\n \n '
  2480. 'Fixes <a href="http://example.com/pagure/issue/2" '
  2481. 'rel="nofollow">http://example.com/pagure/issue/2</a>\n '
  2482. '</pre>', output_text)
  2483. self.assertIn(
  2484. '<div class="btn btn-outline-success disabled opacity-100 '
  2485. 'border-0 font-weight-bold">file added</div>', output_text)
  2486. def test_view_commit_with_short_link(self):
  2487. """ Test the view_commit endpoint when the commit message includes
  2488. an url. """
  2489. tests.create_projects(self.session)
  2490. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  2491. folder = os.path.join(self.path, 'repos', 'test.git')
  2492. # Add a README to the git repo - First commit
  2493. tests.add_readme_git_repo(folder)
  2494. tests.create_projects_git(folder, bare=True)
  2495. # Add a commit with an url in the commit message
  2496. tests.add_content_to_git(
  2497. folder, branch='master', filename='sources', content='foo',
  2498. message='Test commit message\n\nFixes #2'
  2499. )
  2500. # Add a README to the git repo - First commit
  2501. repo = pygit2.Repository(os.path.join(self.path, 'repos', 'test.git'))
  2502. commit = repo.revparse_single('HEAD')
  2503. # View first commit
  2504. output = self.app.get('/test/c/%s' % commit.oid.hex)
  2505. self.assertEqual(output.status_code, 200)
  2506. output_text = output.get_data(as_text=True)
  2507. self.assertIn(
  2508. '#commit-overview-collapse',
  2509. output_text)
  2510. self.assertIn(
  2511. '<pre class="commit_message_body">\n '
  2512. 'Test commit message\n \n '
  2513. 'Fixes #2\n </pre>', output_text)
  2514. self.assertIn(
  2515. '<div class="btn btn-outline-success disabled opacity-100 '
  2516. 'border-0 font-weight-bold">file added</div>', output_text)
  2517. def test_view_commit_patch(self):
  2518. """ Test the view_commit_patch endpoint. """
  2519. # No project registered in the DB
  2520. output = self.app.get('/foo/c/bar.patch')
  2521. self.assertEqual(output.status_code, 404)
  2522. tests.create_projects(self.session)
  2523. output = self.app.get('/test/c/bar.patch')
  2524. # No git repo associated
  2525. self.assertEqual(output.status_code, 404)
  2526. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  2527. output = self.app.get('/test/c/bar.patch')
  2528. self.assertEqual(output.status_code, 404)
  2529. # Add a README to the git repo - First commit
  2530. tests.add_readme_git_repo(os.path.join(self.path, 'repos', 'test.git'))
  2531. repo = pygit2.Repository(os.path.join(self.path, 'repos', 'test.git'))
  2532. commit = repo.revparse_single('HEAD')
  2533. # View first commit
  2534. output = self.app.get('/test/c/%s.patch' % commit.oid.hex)
  2535. self.assertEqual(output.status_code, 200)
  2536. output_text = output.get_data(as_text=True)
  2537. self.assertIn(r'''diff --git a/README.rst b/README.rst
  2538. new file mode 100644
  2539. index 0000000..fb7093d
  2540. --- /dev/null
  2541. +++ b/README.rst
  2542. @@ -0,0 +1,16 @@
  2543. +Pagure
  2544. +======
  2545. +
  2546. +:Author: Pierre-Yves Chibon <pingou@pingoured.fr>
  2547. +
  2548. +
  2549. +Pagure is a light-weight git-centered forge based on pygit2.
  2550. +
  2551. +Currently, Pagure offers a web-interface for git repositories, a ticket
  2552. +system and possibilities to create new projects, fork existing ones and
  2553. +create/merge pull-requests across or within projects.
  2554. +
  2555. +
  2556. +Homepage: https://github.com/pypingou/pagure
  2557. +
  2558. +Dev instance: http://209.132.184.222/ (/!\ May change unexpectedly, it's a dev instance ;-))
  2559. ''', output_text)
  2560. self.assertIn('Subject: Add a README file', output_text)
  2561. # Add some content to the git repo
  2562. tests.add_content_git_repo(os.path.join(self.path, 'repos',
  2563. 'test.git'))
  2564. repo = pygit2.Repository(os.path.join(self.path, 'repos', 'test.git'))
  2565. commit = repo.revparse_single('HEAD')
  2566. # View another commit
  2567. output = self.app.get('/test/c/%s.patch' % commit.oid.hex)
  2568. self.assertEqual(output.status_code, 200)
  2569. output_text = output.get_data(as_text=True)
  2570. self.assertIn(
  2571. 'Subject: Add some directory and a file for more testing',
  2572. output_text)
  2573. self.assertIn(r'''diff --git a/folder1/folder2/file b/folder1/folder2/file
  2574. new file mode 100644
  2575. index 0000000..11980b1
  2576. --- /dev/null
  2577. +++ b/folder1/folder2/file
  2578. @@ -0,0 +1,3 @@
  2579. +foo
  2580. + bar
  2581. +baz
  2582. \ No newline at end of file
  2583. ''', output_text)
  2584. # Add a fork of a fork
  2585. item = pagure.lib.model.Project(
  2586. user_id=1, # pingou
  2587. name='test3',
  2588. description='test project #3',
  2589. is_fork=True,
  2590. parent_id=1,
  2591. hook_token='aaabbblll',
  2592. )
  2593. self.session.add(item)
  2594. self.session.commit()
  2595. forkedgit = os.path.join(self.path, 'repos', 'forks', 'pingou',
  2596. 'test3.git')
  2597. tests.add_content_git_repo(forkedgit)
  2598. tests.add_readme_git_repo(forkedgit)
  2599. repo = pygit2.Repository(forkedgit)
  2600. commit = repo.revparse_single('HEAD')
  2601. # Commit does not exist in anothe repo :)
  2602. output = self.app.get('/test/c/%s.patch' % commit.oid.hex)
  2603. self.assertEqual(output.status_code, 404)
  2604. # View commit of fork
  2605. output = self.app.get(
  2606. '/fork/pingou/test3/c/%s.patch' % commit.oid.hex)
  2607. self.assertEqual(output.status_code, 200)
  2608. output_text = output.get_data(as_text=True)
  2609. self.assertIn(r'''diff --git a/README.rst b/README.rst
  2610. new file mode 100644
  2611. index 0000000..fb7093d
  2612. --- /dev/null
  2613. +++ b/README.rst
  2614. @@ -0,0 +1,16 @@
  2615. +Pagure
  2616. +======
  2617. +
  2618. +:Author: Pierre-Yves Chibon <pingou@pingoured.fr>
  2619. +
  2620. +
  2621. +Pagure is a light-weight git-centered forge based on pygit2.
  2622. +
  2623. +Currently, Pagure offers a web-interface for git repositories, a ticket
  2624. +system and possibilities to create new projects, fork existing ones and
  2625. +create/merge pull-requests across or within projects.
  2626. +
  2627. +
  2628. +Homepage: https://github.com/pypingou/pagure
  2629. +
  2630. +Dev instance: http://209.132.184.222/ (/!\ May change unexpectedly, it's a dev instance ;-))
  2631. ''', output_text)
  2632. def test_view_commit_diff(self):
  2633. """ Test the view_commit_diff endpoint. """
  2634. # No project registered in the DB
  2635. output = self.app.get('/foo/c/bar.diff')
  2636. self.assertEqual(output.status_code, 404)
  2637. tests.create_projects(self.session)
  2638. output = self.app.get('/test/c/bar.diff')
  2639. # No git repo associated
  2640. self.assertEqual(output.status_code, 404)
  2641. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  2642. output = self.app.get('/test/c/bar.diff')
  2643. self.assertEqual(output.status_code, 404)
  2644. # Add a README to the git repo - First commit
  2645. tests.add_readme_git_repo(os.path.join(self.path, 'repos', 'test.git'))
  2646. repo = pygit2.Repository(os.path.join(self.path, 'repos', 'test.git'))
  2647. commit = repo.revparse_single('HEAD')
  2648. # View first commit
  2649. output = self.app.get('/test/c/%s.diff' % commit.oid.hex)
  2650. self.assertEqual(output.status_code, 200)
  2651. output_text = output.get_data(as_text=True)
  2652. self.assertEqual(r'''diff --git a/README.rst b/README.rst
  2653. new file mode 100644
  2654. index 0000000..fb7093d
  2655. --- /dev/null
  2656. +++ b/README.rst
  2657. @@ -0,0 +1,16 @@
  2658. +Pagure
  2659. +======
  2660. +
  2661. +:Author: Pierre-Yves Chibon <pingou@pingoured.fr>
  2662. +
  2663. +
  2664. +Pagure is a light-weight git-centered forge based on pygit2.
  2665. +
  2666. +Currently, Pagure offers a web-interface for git repositories, a ticket
  2667. +system and possibilities to create new projects, fork existing ones and
  2668. +create/merge pull-requests across or within projects.
  2669. +
  2670. +
  2671. +Homepage: https://github.com/pypingou/pagure
  2672. +
  2673. +Dev instance: http://209.132.184.222/ (/!\ May change unexpectedly, it's a dev instance ;-))
  2674. ''', output_text)
  2675. def test_view_tree(self):
  2676. """ Test the view_tree endpoint. """
  2677. output = self.app.get('/foo/tree/')
  2678. # No project registered in the DB
  2679. self.assertEqual(output.status_code, 404)
  2680. tests.create_projects(self.session)
  2681. output = self.app.get('/test/tree/')
  2682. # No git repo associated
  2683. self.assertEqual(output.status_code, 404)
  2684. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  2685. output = self.app.get('/test/tree/')
  2686. self.assertEqual(output.status_code, 200)
  2687. output_text = output.get_data(as_text=True)
  2688. self.assertIn(
  2689. '''<ol class="breadcrumb p-0 bg-transparent mb-0">
  2690. <li class="breadcrumb-item">
  2691. <a href="/test/tree">
  2692. <span class="fa fa-random">
  2693. </span>&nbsp; None
  2694. </a>
  2695. </li>
  2696. </ol>''', output_text)
  2697. self.assertIn(
  2698. 'No content found in this repository', output_text)
  2699. # Add a README to the git repo - First commit
  2700. tests.add_readme_git_repo(os.path.join(self.path, 'repos', 'test.git'))
  2701. repo = pygit2.Repository(os.path.join(self.path, 'repos', 'test.git'))
  2702. commit = repo.revparse_single('HEAD')
  2703. # View first commit
  2704. output = self.app.get('/test/tree/%s' % commit.oid.hex)
  2705. self.assertEqual(output.status_code, 200)
  2706. output_text = output.get_data(as_text=True)
  2707. self.assertIn('<title>Tree - test - Pagure</title>', output_text)
  2708. self.assertIn('README.rst', output_text)
  2709. self.assertFalse(
  2710. 'No content found in this repository' in output_text)
  2711. # View tree by branch
  2712. output = self.app.get('/test/tree/master')
  2713. self.assertEqual(output.status_code, 200)
  2714. output_text = output.get_data(as_text=True)
  2715. self.assertIn('<title>Tree - test - Pagure</title>', output_text)
  2716. self.assertIn('README.rst', output_text)
  2717. self.assertNotIn(
  2718. 'No content found in this repository', output_text)
  2719. # Add a fork of a fork
  2720. item = pagure.lib.model.Project(
  2721. user_id=1, # pingou
  2722. name='test3',
  2723. description='test project #3',
  2724. is_fork=True,
  2725. parent_id=1,
  2726. hook_token='aaabbbfff',
  2727. )
  2728. self.session.add(item)
  2729. self.session.commit()
  2730. forkedgit = os.path.join(self.path, 'repos', 'forks', 'pingou',
  2731. 'test3.git')
  2732. tests.add_content_git_repo(forkedgit)
  2733. output = self.app.get('/fork/pingou/test3/tree/')
  2734. self.assertEqual(output.status_code, 200)
  2735. output_text = output.get_data(as_text=True)
  2736. self.assertIn('<title>Tree - test3 - Pagure</title>', output_text)
  2737. self.assertIn(
  2738. '<a href="/fork/pingou/test3/blob/master/f/folder1">',
  2739. output_text)
  2740. self.assertIn(
  2741. '<a href="/fork/pingou/test3/blob/master/f/sources">',
  2742. output_text)
  2743. self.assertNotIn(
  2744. 'No content found in this repository', output_text)
  2745. output = self.app.get(
  2746. '/fork/pingou/test3/blob/master/f/folder1/folder2')
  2747. self.assertEqual(output.status_code, 200)
  2748. output_text = output.get_data(as_text=True)
  2749. self.assertIn(
  2750. '<a href="/fork/pingou/test3/blob/master/'
  2751. 'f/folder1/folder2/file%C5%A0">', output_text)
  2752. @patch.dict('pagure.config.config', {'ENABLE_DEL_PROJECTS': False})
  2753. @patch('pagure.lib.notify.send_email')
  2754. @patch('pagure.decorators.admin_session_timedout')
  2755. def test_delete_repo_when_turned_off(self, ast, send_email):
  2756. """ Test the delete_repo endpoint when deletion of a repo is
  2757. turned off in the pagure instance """
  2758. ast.return_value = False
  2759. send_email.return_value = True
  2760. # No Git repo
  2761. output = self.app.post('/foo/delete')
  2762. self.assertEqual(output.status_code, 404)
  2763. user = tests.FakeUser(username='pingou')
  2764. with tests.user_set(self.app.application, user):
  2765. tests.create_projects(self.session)
  2766. tests.create_projects_git(os.path.join(self.path, 'repos'))
  2767. output = self.app.post('/test/delete', follow_redirects=True)
  2768. self.assertEqual(output.status_code, 404)
  2769. # User not logged in
  2770. output = self.app.post('/test/delete')
  2771. self.assertEqual(output.status_code, 302)
  2772. # Ensure the project isn't read-only
  2773. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  2774. repo.read_only = False
  2775. self.session.add(repo)
  2776. self.session.commit()
  2777. with tests.user_set(self.app.application, user):
  2778. # Only git repo
  2779. output = self.app.post('/test/delete', follow_redirects=True)
  2780. self.assertEqual(output.status_code, 404)
  2781. # Only git and doc repo
  2782. tests.create_projects_git(os.path.join(self.path, 'repos'))
  2783. tests.create_projects_git(os.path.join(self.path, 'docs'))
  2784. output = self.app.post('/test/delete', follow_redirects=True)
  2785. self.assertEqual(output.status_code, 404)
  2786. # Create all the git repos
  2787. tests.create_projects_git(os.path.join(self.path, 'repos'))
  2788. tests.create_projects_git(os.path.join(self.path, 'docs'))
  2789. tests.create_projects_git(
  2790. os.path.join(self.path, 'tickets'), bare=True)
  2791. tests.create_projects_git(
  2792. os.path.join(self.path, 'requests'), bare=True)
  2793. # Check repo was created
  2794. output = self.app.get('/', follow_redirects=True)
  2795. self.assertEqual(output.status_code, 200)
  2796. output_text = output.get_data(as_text=True)
  2797. self.assertIn(
  2798. '<span class="btn btn-outline-secondary disabled opacity-100 '
  2799. 'border-0 ml-auto font-weight-bold">3 Projects</span>', output_text)
  2800. self.assertNotIn(
  2801. '<span class="d-none d-md-inline">Forks&nbsp;</span>',
  2802. output_text)
  2803. # add issues
  2804. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  2805. msg = pagure.lib.query.new_issue(
  2806. session=self.session,
  2807. repo=repo,
  2808. title='Test issue',
  2809. content='We should work on this',
  2810. user='pingou',
  2811. )
  2812. self.session.commit()
  2813. self.assertEqual(msg.title, 'Test issue')
  2814. msg = pagure.lib.query.new_issue(
  2815. session=self.session,
  2816. repo=repo,
  2817. title='Test issue #2',
  2818. content='We should work on this, really',
  2819. user='pingou',
  2820. )
  2821. self.session.commit()
  2822. self.assertEqual(msg.title, 'Test issue #2')
  2823. # Add a comment to an issue
  2824. issue = pagure.lib.query.search_issues(self.session, repo, issueid=1)
  2825. msg = pagure.lib.query.add_issue_comment(
  2826. session=self.session,
  2827. issue=issue,
  2828. comment='Hey look a comment!',
  2829. user='foo',
  2830. )
  2831. self.session.commit()
  2832. self.assertEqual(msg, 'Comment added')
  2833. # add pull-requests
  2834. req = pagure.lib.query.new_pull_request(
  2835. session=self.session,
  2836. repo_from=repo,
  2837. branch_from='feature',
  2838. repo_to=repo,
  2839. branch_to='master',
  2840. title='test pull-request',
  2841. user='pingou',
  2842. )
  2843. self.session.commit()
  2844. self.assertEqual(req.id, 3)
  2845. self.assertEqual(req.title, 'test pull-request')
  2846. req = pagure.lib.query.new_pull_request(
  2847. session=self.session,
  2848. repo_from=repo,
  2849. branch_from='feature2',
  2850. repo_to=repo,
  2851. branch_to='master',
  2852. title='test pull-request',
  2853. user='pingou',
  2854. )
  2855. self.session.commit()
  2856. self.assertEqual(req.id, 4)
  2857. self.assertEqual(req.title, 'test pull-request')
  2858. # Add comment on a pull-request
  2859. request = pagure.lib.query.search_pull_requests(
  2860. self.session, requestid=3)
  2861. msg = pagure.lib.query.add_pull_request_comment(
  2862. session=self.session,
  2863. request=request,
  2864. commit='commithash',
  2865. tree_id=None,
  2866. filename='file',
  2867. row=None,
  2868. comment='This is awesome, I got to remember it!',
  2869. user='foo',
  2870. )
  2871. self.assertEqual(msg, 'Comment added')
  2872. # Check before deleting the project
  2873. output = self.app.get('/', follow_redirects=True)
  2874. self.assertEqual(output.status_code, 200)
  2875. output_text = output.get_data(as_text=True)
  2876. self.assertIn(
  2877. '<span class="btn btn-outline-secondary disabled opacity-100 '
  2878. 'border-0 ml-auto font-weight-bold">3 Projects</span>', output_text)
  2879. self.assertNotIn(
  2880. '<span class="d-none d-md-inline">Forks&nbsp;</span>',
  2881. output_text)
  2882. output = self.app.post('/test/delete', follow_redirects=True)
  2883. self.assertEqual(output.status_code, 404)
  2884. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  2885. self.assertNotEqual(repo, None)
  2886. repo = pagure.lib.query.get_authorized_project(self.session, 'test2')
  2887. self.assertNotEqual(repo, None)
  2888. # Add a fork of a fork
  2889. item = pagure.lib.model.Project(
  2890. user_id=1, # pingou
  2891. name='test3',
  2892. description='test project #3',
  2893. is_fork=True,
  2894. parent_id=2,
  2895. hook_token='aaabbbjjj',
  2896. )
  2897. self.session.add(item)
  2898. self.session.commit()
  2899. tests.add_content_git_repo(
  2900. os.path.join(self.path, 'repos', 'forks', 'pingou',
  2901. 'test3.git'))
  2902. tests.add_content_git_repo(
  2903. os.path.join(self.path, 'docs', 'pingou', 'test3.git'))
  2904. tests.add_content_git_repo(
  2905. os.path.join(self.path, 'tickets', 'pingou', 'test3.git'))
  2906. # Check before deleting the fork
  2907. output = self.app.get('/', follow_redirects=True)
  2908. self.assertEqual(output.status_code, 200)
  2909. output_text = output.get_data(as_text=True)
  2910. self.assertIn(
  2911. '<span class="btn btn-outline-secondary disabled opacity-100 '
  2912. 'border-0 ml-auto font-weight-bold">3 Projects</span>', output_text)
  2913. self.assertIn(
  2914. """<span>
  2915. <i class="fa fa-fw text-muted fa-code-fork"></i>
  2916. <span class="d-none d-md-inline">Forks&nbsp;</span>
  2917. </span>
  2918. <div class="ml-auto">
  2919. <span class="badge badge-secondary">
  2920. 1
  2921. </span>
  2922. </div>""", output_text)
  2923. output = self.app.post(
  2924. '/fork/pingou/test3/delete', follow_redirects=True)
  2925. self.assertEqual(output.status_code, 404)
  2926. @patch('pagure.lib.notify.send_email')
  2927. @patch('pagure.decorators.admin_session_timedout')
  2928. def test_delete_read_only_repo(self, ast, send_email):
  2929. """ Test the delete_repo endpoint when the repo is read_only """
  2930. ast.return_value = False
  2931. send_email.return_value = True
  2932. tests.create_projects(self.session)
  2933. tests.create_projects_git(os.path.join(self.path, 'repos'))
  2934. # Create all the git repos
  2935. tests.create_projects_git(os.path.join(self.path, 'repos'))
  2936. tests.create_projects_git(os.path.join(self.path, 'docs'))
  2937. tests.create_projects_git(
  2938. os.path.join(self.path, 'tickets'), bare=True)
  2939. tests.create_projects_git(
  2940. os.path.join(self.path, 'requests'), bare=True)
  2941. user = tests.FakeUser(username='pingou')
  2942. with tests.user_set(self.app.application, user):
  2943. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  2944. self.assertNotEqual(repo, None)
  2945. repo.read_only = True
  2946. self.session.add(repo)
  2947. self.session.commit()
  2948. output = self.app.post('/test/delete', follow_redirects=True)
  2949. self.assertEqual(output.status_code, 200)
  2950. output_text = output.get_data(as_text=True)
  2951. self.assertIn(
  2952. '<title>Settings - test - Pagure</title>', output_text)
  2953. self.assertIn(
  2954. 'The ACLs of this project are being refreshed in the '
  2955. 'backend this prevents the project from being deleted. '
  2956. 'Please wait for this task to finish before trying again. '
  2957. 'Thanks!', output_text)
  2958. self.assertIn(
  2959. 'title="Action disabled while project\'s ACLs are being refreshed">',
  2960. output_text)
  2961. @patch('pagure.lib.notify.send_email', MagicMock(return_value=True))
  2962. @patch('pagure.decorators.admin_session_timedout')
  2963. def test_delete_repo(self, ast):
  2964. """ Test the delete_repo endpoint. """
  2965. ast.return_value = False
  2966. # No Git repo
  2967. output = self.app.post('/foo/delete')
  2968. self.assertEqual(output.status_code, 404)
  2969. user = tests.FakeUser()
  2970. with tests.user_set(self.app.application, user):
  2971. tests.create_projects(self.session)
  2972. tests.create_projects_git(os.path.join(self.path, 'repos'))
  2973. # No project registered in the DB (no git repo)
  2974. output = self.app.post('/foo/delete')
  2975. self.assertEqual(output.status_code, 404)
  2976. # User not allowed
  2977. output = self.app.post('/test/delete')
  2978. self.assertEqual(output.status_code, 403)
  2979. # User not logged in
  2980. output = self.app.post('/test/delete')
  2981. self.assertEqual(output.status_code, 302)
  2982. # Ensure the project isn't read-only
  2983. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  2984. repo.read_only = False
  2985. self.session.add(repo)
  2986. self.session.commit()
  2987. user = tests.FakeUser(username='pingou')
  2988. with tests.user_set(self.app.application, user):
  2989. tests.create_projects_git(os.path.join(self.path, 'repos'))
  2990. ast.return_value = True
  2991. output = self.app.post('/test/delete')
  2992. self.assertEqual(output.status_code, 302)
  2993. ast.return_value = False
  2994. output = self.app.post('/test/delete', follow_redirects=True)
  2995. self.assertEqual(output.status_code, 200)
  2996. output_text = output.get_data(as_text=True)
  2997. self.assertIn(
  2998. """<span>
  2999. <i class="fa fa-fw text-muted fa-calendar-o fa-rotate-270"></i>
  3000. <span class="d-none d-md-inline">Projects&nbsp;</span>
  3001. </span>
  3002. <div class="ml-auto">
  3003. <span class="badge badge-secondary">
  3004. 2
  3005. </span>
  3006. </div>""", output_text)
  3007. self.assertIn(
  3008. """<span>
  3009. <i class="fa fa-fw text-muted fa-code-fork"></i>
  3010. <span class="d-none d-md-inline">Forks&nbsp;</span>
  3011. </span>
  3012. <div class="ml-auto">
  3013. <span class="badge badge-secondary">
  3014. 0
  3015. </span>
  3016. </div>""", output_text)
  3017. # Only git repo
  3018. item = pagure.lib.model.Project(
  3019. user_id=1, # pingou
  3020. name='test',
  3021. description='test project #1',
  3022. hook_token='aaabbbggg',
  3023. read_only=False,
  3024. )
  3025. self.session.add(item)
  3026. self.session.commit()
  3027. tests.create_projects_git(os.path.join(self.path, 'repos'))
  3028. output = self.app.post('/test/delete', follow_redirects=True)
  3029. self.assertEqual(output.status_code, 200)
  3030. output_text = output.get_data(as_text=True)
  3031. self.assertIn(
  3032. """<span>
  3033. <i class="fa fa-fw text-muted fa-calendar-o fa-rotate-270"></i>
  3034. <span class="d-none d-md-inline">Projects&nbsp;</span>
  3035. </span>
  3036. <div class="ml-auto">
  3037. <span class="badge badge-secondary">
  3038. 2
  3039. </span>
  3040. </div>""", output_text)
  3041. self.assertIn(
  3042. """<span>
  3043. <i class="fa fa-fw text-muted fa-code-fork"></i>
  3044. <span class="d-none d-md-inline">Forks&nbsp;</span>
  3045. </span>
  3046. <div class="ml-auto">
  3047. <span class="badge badge-secondary">
  3048. 0
  3049. </span>
  3050. </div>""", output_text)
  3051. # Only git and doc repo
  3052. item = pagure.lib.model.Project(
  3053. user_id=1, # pingou
  3054. name='test',
  3055. description='test project #1',
  3056. hook_token='aaabbbhhh',
  3057. read_only=False,
  3058. )
  3059. self.session.add(item)
  3060. self.session.commit()
  3061. tests.create_projects_git(os.path.join(self.path, 'repos'))
  3062. tests.create_projects_git(os.path.join(self.path, 'docs'))
  3063. output = self.app.post('/test/delete', follow_redirects=True)
  3064. self.assertEqual(output.status_code, 200)
  3065. output_text = output.get_data(as_text=True)
  3066. self.assertIn(
  3067. """<span>
  3068. <i class="fa fa-fw text-muted fa-calendar-o fa-rotate-270"></i>
  3069. <span class="d-none d-md-inline">Projects&nbsp;</span>
  3070. </span>
  3071. <div class="ml-auto">
  3072. <span class="badge badge-secondary">
  3073. 2
  3074. </span>
  3075. </div>""", output_text)
  3076. self.assertIn(
  3077. """<span>
  3078. <i class="fa fa-fw text-muted fa-code-fork"></i>
  3079. <span class="d-none d-md-inline">Forks&nbsp;</span>
  3080. </span>
  3081. <div class="ml-auto">
  3082. <span class="badge badge-secondary">
  3083. 0
  3084. </span>
  3085. </div>""", output_text)
  3086. # All repo there
  3087. item = pagure.lib.model.Project(
  3088. user_id=1, # pingou
  3089. name='test',
  3090. description='test project #1',
  3091. hook_token='aaabbbiii',
  3092. read_only=False,
  3093. )
  3094. self.session.add(item)
  3095. self.session.commit()
  3096. # Create all the git repos
  3097. tests.create_projects_git(os.path.join(self.path, 'repos'))
  3098. tests.create_projects_git(os.path.join(self.path, 'docs'))
  3099. tests.create_projects_git(
  3100. os.path.join(self.path, 'tickets'), bare=True)
  3101. tests.create_projects_git(
  3102. os.path.join(self.path, 'requests'), bare=True)
  3103. # Check repo was created
  3104. output = self.app.get('/', follow_redirects=True)
  3105. self.assertEqual(output.status_code, 200)
  3106. output_text = output.get_data(as_text=True)
  3107. self.assertIn(
  3108. """<span>
  3109. <i class="fa fa-calendar-o fa-rotate-270 fa-fw text-muted"></i>
  3110. <span class="d-none d-md-inline">Projects&nbsp;</span>
  3111. </span>
  3112. <div class="ml-auto">
  3113. <span class="badge badge-secondary">
  3114. 3
  3115. </span>
  3116. </div>""", output_text)
  3117. self.assertNotIn(
  3118. """<span class="d-none d-md-inline">Forks&nbsp;</span>""",
  3119. output_text)
  3120. # add issues
  3121. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  3122. msg = pagure.lib.query.new_issue(
  3123. session=self.session,
  3124. repo=repo,
  3125. title='Test issue',
  3126. content='We should work on this',
  3127. user='pingou',
  3128. )
  3129. self.session.commit()
  3130. self.assertEqual(msg.title, 'Test issue')
  3131. msg = pagure.lib.query.new_issue(
  3132. session=self.session,
  3133. repo=repo,
  3134. title='Test issue #2',
  3135. content='We should work on this, really',
  3136. user='pingou',
  3137. )
  3138. self.session.commit()
  3139. self.assertEqual(msg.title, 'Test issue #2')
  3140. # Add a comment to an issue
  3141. issue = pagure.lib.query.search_issues(self.session, repo, issueid=1)
  3142. msg = pagure.lib.query.add_issue_comment(
  3143. session=self.session,
  3144. issue=issue,
  3145. comment='Hey look a comment!',
  3146. user='foo',
  3147. )
  3148. self.session.commit()
  3149. self.assertEqual(msg, 'Comment added')
  3150. # add pull-requests
  3151. req = pagure.lib.query.new_pull_request(
  3152. session=self.session,
  3153. repo_from=repo,
  3154. branch_from='feature',
  3155. repo_to=repo,
  3156. branch_to='master',
  3157. title='test pull-request',
  3158. user='pingou',
  3159. )
  3160. self.session.commit()
  3161. self.assertEqual(req.id, 3)
  3162. self.assertEqual(req.title, 'test pull-request')
  3163. req = pagure.lib.query.new_pull_request(
  3164. session=self.session,
  3165. repo_from=repo,
  3166. branch_from='feature2',
  3167. repo_to=repo,
  3168. branch_to='master',
  3169. title='test pull-request',
  3170. user='pingou',
  3171. )
  3172. self.session.commit()
  3173. self.assertEqual(req.id, 4)
  3174. self.assertEqual(req.title, 'test pull-request')
  3175. # Add comment on a pull-request
  3176. request = pagure.lib.query.search_pull_requests(
  3177. self.session, requestid=3)
  3178. msg = pagure.lib.query.add_pull_request_comment(
  3179. session=self.session,
  3180. request=request,
  3181. commit='commithash',
  3182. tree_id=None,
  3183. filename='file',
  3184. row=None,
  3185. comment='This is awesome, I got to remember it!',
  3186. user='foo',
  3187. )
  3188. self.assertEqual(msg, 'Comment added')
  3189. # Check before deleting the project
  3190. output = self.app.get('/', follow_redirects=True)
  3191. self.assertEqual(output.status_code, 200)
  3192. output_text = output.get_data(as_text=True)
  3193. self.assertIn(
  3194. """<span>
  3195. <i class="fa fa-calendar-o fa-rotate-270 fa-fw text-muted"></i>
  3196. <span class="d-none d-md-inline">Projects&nbsp;</span>
  3197. </span>
  3198. <div class="ml-auto">
  3199. <span class="badge badge-secondary">
  3200. 3
  3201. </span>
  3202. </div>""", output_text)
  3203. self.assertNotIn(
  3204. """<span class="d-none d-md-inline">Forks&nbsp;</span>""",
  3205. output_text)
  3206. output = self.app.post('/test/delete', follow_redirects=True)
  3207. self.assertEqual(output.status_code, 200)
  3208. output_text = output.get_data(as_text=True)
  3209. self.assertIn(
  3210. """<span>
  3211. <i class="fa fa-fw text-muted fa-calendar-o fa-rotate-270"></i>
  3212. <span class="d-none d-md-inline">Projects&nbsp;</span>
  3213. </span>
  3214. <div class="ml-auto">
  3215. <span class="badge badge-secondary">
  3216. 2
  3217. </span>
  3218. </div>""", output_text)
  3219. self.assertIn(
  3220. """<span>
  3221. <i class="fa fa-fw text-muted fa-code-fork"></i>
  3222. <span class="d-none d-md-inline">Forks&nbsp;</span>
  3223. </span>
  3224. <div class="ml-auto">
  3225. <span class="badge badge-secondary">
  3226. 0
  3227. </span>
  3228. </div>""", output_text)
  3229. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  3230. self.assertEqual(repo, None)
  3231. repo = pagure.lib.query.get_authorized_project(self.session, 'test2')
  3232. self.assertNotEqual(repo, None)
  3233. # Add a fork of a fork
  3234. item = pagure.lib.model.Project(
  3235. user_id=1, # pingou
  3236. name='test3',
  3237. description='test project #3',
  3238. is_fork=True,
  3239. parent_id=2,
  3240. hook_token='aaabbbjjj',
  3241. read_only=False,
  3242. )
  3243. self.session.add(item)
  3244. self.session.commit()
  3245. tests.add_content_git_repo(
  3246. os.path.join(self.path, 'repos', 'forks', 'pingou',
  3247. 'test3.git'))
  3248. tests.add_content_git_repo(
  3249. os.path.join(self.path, 'docs', 'pingou', 'test3.git'))
  3250. tests.add_content_git_repo(
  3251. os.path.join(self.path, 'tickets', 'pingou', 'test3.git'))
  3252. # Check before deleting the fork
  3253. output = self.app.get('/', follow_redirects=True)
  3254. self.assertEqual(output.status_code, 200)
  3255. output_text = output.get_data(as_text=True)
  3256. self.assertIn(
  3257. """<span>
  3258. <i class="fa fa-calendar-o fa-rotate-270 fa-fw text-muted"></i>
  3259. <span class="d-none d-md-inline">Projects&nbsp;</span>
  3260. </span>
  3261. <div class="ml-auto">
  3262. <span class="badge badge-secondary">
  3263. 2
  3264. </span>
  3265. </div>""", output_text)
  3266. self.assertIn(
  3267. """<span>
  3268. <i class="fa fa-fw text-muted fa-code-fork"></i>
  3269. <span class="d-none d-md-inline">Forks&nbsp;</span>
  3270. </span>
  3271. <div class="ml-auto">
  3272. <span class="badge badge-secondary">
  3273. 1
  3274. </span>
  3275. </div>""", output_text)
  3276. output = self.app.post(
  3277. '/fork/pingou/test3/delete', follow_redirects=True)
  3278. self.assertEqual(output.status_code, 200)
  3279. output_text = output.get_data(as_text=True)
  3280. self.assertIn(
  3281. """<span>
  3282. <i class="fa fa-fw text-muted fa-calendar-o fa-rotate-270"></i>
  3283. <span class="d-none d-md-inline">Projects&nbsp;</span>
  3284. </span>
  3285. <div class="ml-auto">
  3286. <span class="badge badge-secondary">
  3287. 2
  3288. </span>
  3289. </div>""", output_text)
  3290. self.assertIn(
  3291. """<span>
  3292. <i class="fa fa-fw text-muted fa-code-fork"></i>
  3293. <span class="d-none d-md-inline">Forks&nbsp;</span>
  3294. </span>
  3295. <div class="ml-auto">
  3296. <span class="badge badge-secondary">
  3297. 0
  3298. </span>
  3299. </div>""", output_text)
  3300. @patch.dict('pagure.config.config', {'TICKETS_FOLDER': None})
  3301. @patch('pagure.lib.notify.send_email', MagicMock(return_value=True))
  3302. @patch('pagure.decorators.admin_session_timedout', MagicMock(return_value=False))
  3303. def test_delete_repo_no_ticket(self):
  3304. """ Test the delete_repo endpoint when tickets aren't enabled in
  3305. this pagure instance. """
  3306. tests.create_projects(self.session)
  3307. tests.create_projects_git(os.path.join(self.path, 'repos'))
  3308. # Ensure the project isn't read-only
  3309. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  3310. repo.read_only = False
  3311. self.session.add(repo)
  3312. self.session.commit()
  3313. user = tests.FakeUser(username='pingou')
  3314. with tests.user_set(self.app.application, user):
  3315. # Check before deleting the project
  3316. output = self.app.get('/', follow_redirects=True)
  3317. self.assertEqual(output.status_code, 200)
  3318. output_text = output.get_data(as_text=True)
  3319. self.assertIn(
  3320. """<span>
  3321. <i class="fa fa-calendar-o fa-rotate-270 fa-fw text-muted"></i>
  3322. <span class="d-none d-md-inline">Projects&nbsp;</span>
  3323. </span>
  3324. <div class="ml-auto">
  3325. <span class="badge badge-secondary">
  3326. 3
  3327. </span>
  3328. </div>""", output_text)
  3329. self.assertNotIn(
  3330. """<span class="d-none d-md-inline">Forks&nbsp;</span>""",
  3331. output_text)
  3332. # Delete the project
  3333. output = self.app.post('/test/delete', follow_redirects=True)
  3334. self.assertEqual(output.status_code, 200)
  3335. output_text = output.get_data(as_text=True)
  3336. # Check deletion worked
  3337. self.assertIn(
  3338. """<span>
  3339. <i class="fa fa-fw text-muted fa-calendar-o fa-rotate-270"></i>
  3340. <span class="d-none d-md-inline">Projects&nbsp;</span>
  3341. </span>
  3342. <div class="ml-auto">
  3343. <span class="badge badge-secondary">
  3344. 2
  3345. </span>
  3346. </div>""", output_text)
  3347. self.assertIn(
  3348. """<span>
  3349. <i class="fa fa-fw text-muted fa-code-fork"></i>
  3350. <span class="d-none d-md-inline">Forks&nbsp;</span>
  3351. </span>
  3352. <div class="ml-auto">
  3353. <span class="badge badge-secondary">
  3354. 0
  3355. </span>
  3356. </div>""", output_text)
  3357. @patch('pagure.lib.notify.send_email')
  3358. @patch('pagure.decorators.admin_session_timedout')
  3359. def test_delete_repo_with_users(self, ast, send_email):
  3360. """ Test the delete_repo endpoint. """
  3361. ast.return_value = False
  3362. send_email.return_value = True
  3363. user = tests.FakeUser()
  3364. user = tests.FakeUser(username='pingou')
  3365. with tests.user_set(self.app.application, user):
  3366. # Create new project
  3367. item = pagure.lib.model.Project(
  3368. user_id=1, # pingou
  3369. name='test',
  3370. description='test project #1',
  3371. hook_token='aaabbbiii',
  3372. read_only=False,
  3373. )
  3374. self.session.add(item)
  3375. self.session.commit()
  3376. # Create all the git repos
  3377. tests.create_projects_git(os.path.join(self.path, 'repos'))
  3378. tests.create_projects_git(
  3379. os.path.join(self.path, 'docs'), bare=True)
  3380. tests.create_projects_git(
  3381. os.path.join(self.path, 'tickets'), bare=True)
  3382. tests.create_projects_git(
  3383. os.path.join(self.path, 'requests'), bare=True)
  3384. # Check repo was created
  3385. output = self.app.get('/', follow_redirects=True)
  3386. self.assertEqual(output.status_code, 200)
  3387. output_text = output.get_data(as_text=True)
  3388. self.assertIn(
  3389. '<span class="btn btn-outline-secondary disabled opacity-100 '
  3390. 'border-0 ml-auto font-weight-bold">1 Projects</span>', output_text)
  3391. self.assertNotIn(
  3392. '<span class="d-none d-md-inline">Forks&nbsp;</span>',
  3393. output_text)
  3394. # add user
  3395. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  3396. msg = pagure.lib.query.add_user_to_project(
  3397. session=self.session,
  3398. project=repo,
  3399. new_user='foo',
  3400. user='pingou',
  3401. )
  3402. self.session.commit()
  3403. self.assertEqual(msg, 'User added')
  3404. # Ensure the project isn't read-only (because adding an user
  3405. # will trigger an ACL refresh, thus read-only)
  3406. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  3407. repo.read_only = False
  3408. self.session.add(repo)
  3409. self.session.commit()
  3410. # Check before deleting the project
  3411. output = self.app.get('/', follow_redirects=True)
  3412. self.assertEqual(output.status_code, 200)
  3413. output_text = output.get_data(as_text=True)
  3414. self.assertIn(
  3415. '<span class="btn btn-outline-secondary disabled opacity-100 '
  3416. 'border-0 ml-auto font-weight-bold">1 Projects</span>', output_text)
  3417. self.assertNotIn(
  3418. '<span class="d-none d-md-inline">Forks&nbsp;</span>',
  3419. output_text)
  3420. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  3421. self.assertNotEqual(repo, None)
  3422. repo = pagure.lib.query.get_authorized_project(self.session, 'test2')
  3423. self.assertEqual(repo, None)
  3424. # Delete the project
  3425. output = self.app.post('/test/delete', follow_redirects=True)
  3426. self.assertEqual(output.status_code, 200)
  3427. output_text = output.get_data(as_text=True)
  3428. self.assertIn(
  3429. """<span>
  3430. <i class="fa fa-fw text-muted fa-calendar-o fa-rotate-270"></i>
  3431. <span class="d-none d-md-inline">Projects&nbsp;</span>
  3432. </span>
  3433. <div class="ml-auto">
  3434. <span class="badge badge-secondary">
  3435. 0
  3436. </span>
  3437. </div>""", output_text)
  3438. self.assertIn(
  3439. """<span>
  3440. <i class="fa fa-fw text-muted fa-code-fork"></i>
  3441. <span class="d-none d-md-inline">Forks&nbsp;</span>
  3442. </span>
  3443. <div class="ml-auto">
  3444. <span class="badge badge-secondary">
  3445. 0
  3446. </span>
  3447. </div>""", output_text)
  3448. # Check after
  3449. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  3450. self.assertEqual(repo, None)
  3451. repo = pagure.lib.query.get_authorized_project(self.session, 'test2')
  3452. self.assertEqual(repo, None)
  3453. @patch('pagure.lib.notify.send_email')
  3454. @patch('pagure.decorators.admin_session_timedout')
  3455. def test_delete_repo_with_group(self, ast, send_email):
  3456. """ Test the delete_repo endpoint. """
  3457. ast.return_value = False
  3458. send_email.return_value = True
  3459. user = tests.FakeUser()
  3460. user = tests.FakeUser(username='pingou')
  3461. with tests.user_set(self.app.application, user):
  3462. # Create new project
  3463. item = pagure.lib.model.Project(
  3464. user_id=1, # pingou
  3465. name='test',
  3466. description='test project #1',
  3467. hook_token='aaabbbiii',
  3468. read_only=False,
  3469. )
  3470. self.session.add(item)
  3471. self.session.commit()
  3472. # Create all the git repos
  3473. tests.create_projects_git(os.path.join(self.path, 'repos'))
  3474. tests.create_projects_git(
  3475. os.path.join(self.path, 'docs'), bare=True)
  3476. tests.create_projects_git(
  3477. os.path.join(self.path, 'tickets'), bare=True)
  3478. tests.create_projects_git(
  3479. os.path.join(self.path, 'requests'), bare=True)
  3480. # Check repo was created
  3481. output = self.app.get('/', follow_redirects=True)
  3482. self.assertEqual(output.status_code, 200)
  3483. output_text = output.get_data(as_text=True)
  3484. self.assertIn(
  3485. '<span class="btn btn-outline-secondary disabled opacity-100 '
  3486. 'border-0 ml-auto font-weight-bold">1 Projects</span>', output_text)
  3487. self.assertNotIn(
  3488. '<span class="d-none d-md-inline">Forks&nbsp;</span>',
  3489. output_text)
  3490. # Create group
  3491. msg = pagure.lib.query.add_group(
  3492. self.session,
  3493. group_name='foo',
  3494. display_name='foo group',
  3495. description=None,
  3496. group_type='bar',
  3497. user='pingou',
  3498. is_admin=False,
  3499. blacklist=[],
  3500. )
  3501. self.session.commit()
  3502. self.assertEqual(msg, 'User `pingou` added to the group `foo`.')
  3503. # Add group to the project
  3504. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  3505. msg = pagure.lib.query.add_group_to_project(
  3506. session=self.session,
  3507. project=repo,
  3508. new_group='foo',
  3509. user='pingou',
  3510. )
  3511. self.session.commit()
  3512. self.assertEqual(msg, 'Group added')
  3513. # Ensure the project isn't read-only (because adding a group
  3514. # will trigger an ACL refresh, thus read-only)
  3515. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  3516. repo.read_only = False
  3517. self.session.add(repo)
  3518. self.session.commit()
  3519. # check if group where we expect it
  3520. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  3521. self.assertEqual(len(repo.projects_groups), 1)
  3522. # Check before deleting the project
  3523. output = self.app.get('/', follow_redirects=True)
  3524. self.assertEqual(output.status_code, 200)
  3525. output_text = output.get_data(as_text=True)
  3526. self.assertIn(
  3527. '<span class="btn btn-outline-secondary disabled opacity-100 '
  3528. 'border-0 ml-auto font-weight-bold">1 Projects</span>', output_text)
  3529. self.assertNotIn(
  3530. '<span class="d-none d-md-inline">Forks&nbsp;</span>',
  3531. output_text)
  3532. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  3533. self.assertNotEqual(repo, None)
  3534. # Delete the project
  3535. output = self.app.post('/test/delete', follow_redirects=True)
  3536. self.assertEqual(output.status_code, 200)
  3537. output_text = output.get_data(as_text=True)
  3538. self.assertIn(
  3539. """<span>
  3540. <i class="fa fa-fw text-muted fa-calendar-o fa-rotate-270"></i>
  3541. <span class="d-none d-md-inline">Projects&nbsp;</span>
  3542. </span>
  3543. <div class="ml-auto">
  3544. <span class="badge badge-secondary">
  3545. 0
  3546. </span>
  3547. </div>""", output_text)
  3548. self.assertIn(
  3549. """<span>
  3550. <i class="fa fa-fw text-muted fa-code-fork"></i>
  3551. <span class="d-none d-md-inline">Forks&nbsp;</span>
  3552. </span>
  3553. <div class="ml-auto">
  3554. <span class="badge badge-secondary">
  3555. 0
  3556. </span>
  3557. </div>""", output_text)
  3558. # Check after
  3559. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  3560. self.assertEqual(repo, None)
  3561. @patch('pagure.lib.notify.send_email')
  3562. @patch('pagure.decorators.admin_session_timedout')
  3563. def test_delete_repo_with_coloredtag(self, ast, send_email):
  3564. """ Test the delete_repo endpoint. """
  3565. ast.return_value = False
  3566. send_email.return_value = True
  3567. user = tests.FakeUser()
  3568. user = tests.FakeUser(username='pingou')
  3569. with tests.user_set(self.app.application, user):
  3570. # Create new project
  3571. item = pagure.lib.model.Project(
  3572. user_id=1, # pingou
  3573. name='test',
  3574. description='test project #1',
  3575. hook_token='aaabbbiii',
  3576. read_only=False,
  3577. )
  3578. self.session.add(item)
  3579. self.session.commit()
  3580. # Create all the git repos
  3581. tests.create_projects_git(os.path.join(self.path, 'repos'))
  3582. tests.create_projects_git(
  3583. os.path.join(self.path, 'docs'), bare=True)
  3584. tests.create_projects_git(
  3585. os.path.join(self.path, 'tickets'), bare=True)
  3586. tests.create_projects_git(
  3587. os.path.join(self.path, 'requests'), bare=True)
  3588. # Check repo was created
  3589. output = self.app.get('/', follow_redirects=True)
  3590. self.assertEqual(output.status_code, 200)
  3591. output_text = output.get_data(as_text=True)
  3592. self.assertIn(
  3593. '<span class="btn btn-outline-secondary disabled opacity-100 '
  3594. 'border-0 ml-auto font-weight-bold">1 Projects</span>', output_text)
  3595. self.assertNotIn(
  3596. '<span class="d-none d-md-inline">Forks&nbsp;</span>',
  3597. output_text)
  3598. # Create the issue
  3599. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  3600. msg = pagure.lib.query.new_issue(
  3601. session=self.session,
  3602. repo=repo,
  3603. title='Test issue',
  3604. content='We should work on this',
  3605. user='pingou',
  3606. )
  3607. self.session.commit()
  3608. self.assertEqual(msg.title, 'Test issue')
  3609. # Add a tag to the issue
  3610. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  3611. issue = pagure.lib.query.search_issues(self.session, repo, issueid=1)
  3612. msg = pagure.lib.query.add_tag_obj(
  3613. session=self.session,
  3614. obj=issue,
  3615. tags='tag1',
  3616. user='pingou',
  3617. )
  3618. self.session.commit()
  3619. self.assertEqual(msg, 'Issue tagged with: tag1')
  3620. # Check before deleting the project
  3621. output = self.app.get('/', follow_redirects=True)
  3622. self.assertEqual(output.status_code, 200)
  3623. output_text = output.get_data(as_text=True)
  3624. self.assertIn(
  3625. '<span class="btn btn-outline-secondary disabled opacity-100 '
  3626. 'border-0 ml-auto font-weight-bold">1 Projects</span>', output_text)
  3627. self.assertNotIn(
  3628. '<span class="d-none d-md-inline">Forks&nbsp;</span>',
  3629. output_text)
  3630. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  3631. self.assertNotEqual(repo, None)
  3632. repo = pagure.lib.query.get_authorized_project(self.session, 'test2')
  3633. self.assertEqual(repo, None)
  3634. # Delete the project
  3635. output = self.app.post('/test/delete', follow_redirects=True)
  3636. self.assertEqual(output.status_code, 200)
  3637. output_text = output.get_data(as_text=True)
  3638. self.assertIn(
  3639. """<span>
  3640. <i class="fa fa-fw text-muted fa-calendar-o fa-rotate-270"></i>
  3641. <span class="d-none d-md-inline">Projects&nbsp;</span>
  3642. </span>
  3643. <div class="ml-auto">
  3644. <span class="badge badge-secondary">
  3645. 0
  3646. </span>
  3647. </div>""", output_text)
  3648. self.assertIn(
  3649. """<span>
  3650. <i class="fa fa-fw text-muted fa-code-fork"></i>
  3651. <span class="d-none d-md-inline">Forks&nbsp;</span>
  3652. </span>
  3653. <div class="ml-auto">
  3654. <span class="badge badge-secondary">
  3655. 0
  3656. </span>
  3657. </div>""", output_text)
  3658. # Check after
  3659. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  3660. self.assertEqual(repo, None)
  3661. repo = pagure.lib.query.get_authorized_project(self.session, 'test2')
  3662. self.assertEqual(repo, None)
  3663. @patch('pagure.decorators.admin_session_timedout')
  3664. def test_new_repo_hook_token(self, ast):
  3665. """ Test the new_repo_hook_token endpoint. """
  3666. ast.return_value = False
  3667. tests.create_projects(self.session)
  3668. tests.create_projects_git(os.path.join(self.path, 'repos'))
  3669. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  3670. self.assertEqual(repo.hook_token, 'aaabbbccc')
  3671. user = tests.FakeUser()
  3672. with tests.user_set(self.app.application, user):
  3673. pagure.config.config['WEBHOOK'] = True
  3674. output = self.app.get('/new/')
  3675. self.assertEqual(output.status_code, 200)
  3676. output_text = output.get_data(as_text=True)
  3677. self.assertIn('<strong>Create new Project</strong>', output_text)
  3678. csrf_token = output_text.split(
  3679. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  3680. output = self.app.post('/foo/hook_token')
  3681. self.assertEqual(output.status_code, 404)
  3682. output = self.app.post('/test/hook_token')
  3683. self.assertEqual(output.status_code, 403)
  3684. ast.return_value = True
  3685. output = self.app.post('/test/hook_token')
  3686. self.assertEqual(output.status_code, 302)
  3687. ast.return_value = False
  3688. pagure.config.config['WEBHOOK'] = False
  3689. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  3690. self.assertEqual(repo.hook_token, 'aaabbbccc')
  3691. user.username = 'pingou'
  3692. with tests.user_set(self.app.application, user):
  3693. pagure.config.config['WEBHOOK'] = True
  3694. output = self.app.post('/test/hook_token')
  3695. self.assertEqual(output.status_code, 400)
  3696. data = {'csrf_token': csrf_token}
  3697. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  3698. self.assertEqual(repo.hook_token, 'aaabbbccc')
  3699. output = self.app.post(
  3700. '/test/hook_token', data=data, follow_redirects=True)
  3701. self.assertEqual(output.status_code, 200)
  3702. output_text = output.get_data(as_text=True)
  3703. self.assertIn(
  3704. 'New hook token generated',
  3705. output_text)
  3706. pagure.config.config['WEBHOOK'] = False
  3707. self.session.commit()
  3708. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  3709. self.assertNotEqual(repo.hook_token, 'aaabbbccc')
  3710. @patch('pagure.lib.notify.send_email')
  3711. @patch('pagure.decorators.admin_session_timedout')
  3712. @patch('pagure.lib.git.update_git')
  3713. def test_regenerate_git(self, upgit, ast, sendmail):
  3714. """ Test the regenerate_git endpoint. """
  3715. ast.return_value = False
  3716. upgit.return_value = True
  3717. sendmail.return_value = True
  3718. tests.create_projects(self.session)
  3719. tests.create_projects_git(os.path.join(self.path, 'repos'))
  3720. user = tests.FakeUser()
  3721. with tests.user_set(self.app.application, user):
  3722. output = self.app.get('/new/')
  3723. self.assertEqual(output.status_code, 200)
  3724. output_text = output.get_data(as_text=True)
  3725. self.assertIn('<strong>Create new Project</strong>', output_text)
  3726. csrf_token = output_text.split(
  3727. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  3728. output = self.app.post('/foo/regenerate')
  3729. self.assertEqual(output.status_code, 404)
  3730. output = self.app.post('/test/regenerate')
  3731. self.assertEqual(output.status_code, 403)
  3732. ast.return_value = True
  3733. output = self.app.post('/test/regenerate')
  3734. self.assertEqual(output.status_code, 302)
  3735. ast.return_value = False
  3736. user.username = 'pingou'
  3737. with tests.user_set(self.app.application, user):
  3738. output = self.app.post('/test/regenerate')
  3739. self.assertEqual(output.status_code, 400)
  3740. data = {'csrf_token': csrf_token}
  3741. output = self.app.post('/test/regenerate', data=data)
  3742. self.assertEqual(output.status_code, 400)
  3743. data['regenerate'] = 'ticket'
  3744. output = self.app.post('/test/regenerate', data=data)
  3745. self.assertEqual(output.status_code, 400)
  3746. # Create an issue to play with
  3747. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  3748. msg = pagure.lib.query.new_issue(
  3749. session=self.session,
  3750. repo=repo,
  3751. title='Test issue',
  3752. content='We should work on this',
  3753. user='pingou',
  3754. )
  3755. self.session.commit()
  3756. self.assertEqual(msg.title, 'Test issue')
  3757. data['regenerate'] = 'tickets'
  3758. output = self.app.post(
  3759. '/test/regenerate', data=data, follow_redirects=True)
  3760. self.assertEqual(output.status_code, 200)
  3761. output_text = output.get_data(as_text=True)
  3762. self.assertIn(
  3763. 'Tickets git repo updated',
  3764. output_text)
  3765. # Create a request to play with
  3766. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  3767. msg = pagure.lib.query.new_pull_request(
  3768. session=self.session,
  3769. repo_from=repo,
  3770. branch_from='branch',
  3771. repo_to=repo,
  3772. branch_to='master',
  3773. title='Test pull-request',
  3774. user='pingou',
  3775. )
  3776. self.session.commit()
  3777. self.assertEqual(msg.title, 'Test pull-request')
  3778. data['regenerate'] = 'requests'
  3779. output = self.app.post(
  3780. '/test/regenerate', data=data, follow_redirects=True)
  3781. self.assertEqual(output.status_code, 200)
  3782. output_text = output.get_data(as_text=True)
  3783. self.assertIn(
  3784. 'Requests git repo updated',
  3785. output_text)
  3786. def test_view_tags(self):
  3787. """ Test the view_tags endpoint. """
  3788. output = self.app.get('/foo/releases')
  3789. # No project registered in the DB
  3790. self.assertEqual(output.status_code, 404)
  3791. tests.create_projects(self.session)
  3792. output = self.app.get('/test/releases')
  3793. # No git repo associated
  3794. self.assertEqual(output.status_code, 404)
  3795. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  3796. output = self.app.get('/test/releases')
  3797. self.assertEqual(output.status_code, 200)
  3798. output_text = output.get_data(as_text=True)
  3799. self.assertIn('This project has not been tagged.', output_text)
  3800. # Add a README to the git repo - First commit
  3801. tests.add_readme_git_repo(os.path.join(self.path, 'repos', 'test.git'))
  3802. repo = pygit2.Repository(os.path.join(self.path, 'repos', 'test.git'))
  3803. first_commit = repo.revparse_single('HEAD')
  3804. tagger = pygit2.Signature('Alice Doe', 'adoe@example.com', 12347, 0)
  3805. repo.create_tag(
  3806. "0.0.1", first_commit.oid.hex, pygit2.GIT_OBJ_COMMIT, tagger,
  3807. "Release 0.0.1")
  3808. output = self.app.get('/test/releases')
  3809. self.assertEqual(output.status_code, 200)
  3810. output_text = output.get_data(as_text=True)
  3811. self.assertIn('0.0.1', output_text)
  3812. self.assertIn('<section class="tag_list">', output_text)
  3813. self.assertEqual(
  3814. output_text.count('<i class="fa fa-calendar-o fa-rotate-270 text-muted"></i>'),
  3815. 1)
  3816. def test_edit_file_no_signed_off(self):
  3817. """ Test the edit_file endpoint when signed-off isn't enforced. """
  3818. tests.create_projects(self.session)
  3819. tests.create_projects_git(
  3820. os.path.join(self.path, 'repos'), bare=True)
  3821. user = tests.FakeUser()
  3822. user.username = 'pingou'
  3823. with tests.user_set(self.app.application, user):
  3824. # Add some content to the git repo
  3825. tests.add_content_git_repo(
  3826. os.path.join(self.path, 'repos', 'test.git'))
  3827. output = self.app.get('/test/edit/master/f/sources')
  3828. self.assertEqual(output.status_code, 200)
  3829. output_text = output.get_data(as_text=True)
  3830. self.assertIn(
  3831. '<li><a href="/test/tree/master"><span class="fa fa-random">'
  3832. '</span>&nbsp; master</a></li><li class="active">'
  3833. '<span class="fa fa-file"></span>&nbsp; sources</li>',
  3834. output_text)
  3835. self.assertIn(
  3836. '<textarea id="textareaCode" name="content">foo\n bar</textarea>',
  3837. output_text)
  3838. self.assertIn(
  3839. '<textarea rows="5" class="form-control" type="text" '
  3840. 'id="commit_message"\n name="commit_message" '
  3841. 'placeholder="An optional description of the change">'
  3842. '</textarea>', output_text
  3843. )
  3844. def test_edit_file_signed_off(self):
  3845. """ Test the edit_file endpoint when signed-off is enforced. """
  3846. tests.create_projects(self.session)
  3847. tests.create_projects_git(
  3848. os.path.join(self.path, 'repos'), bare=True)
  3849. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  3850. settings = repo.settings
  3851. settings['Enforce_signed-off_commits_in_pull-request'] = True
  3852. repo.settings = settings
  3853. self.session.add(repo)
  3854. self.session.commit()
  3855. user = tests.FakeUser()
  3856. user.username = 'pingou'
  3857. with tests.user_set(self.app.application, user):
  3858. # Add some content to the git repo
  3859. tests.add_content_git_repo(
  3860. os.path.join(self.path, 'repos', 'test.git'))
  3861. output = self.app.get('/test/edit/master/f/sources')
  3862. self.assertEqual(output.status_code, 200)
  3863. output_text = output.get_data(as_text=True)
  3864. self.assertIn(
  3865. '<li><a href="/test/tree/master"><span class="fa fa-random">'
  3866. '</span>&nbsp; master</a></li><li class="active">'
  3867. '<span class="fa fa-file"></span>&nbsp; sources</li>',
  3868. output_text)
  3869. self.assertIn(
  3870. '<textarea id="textareaCode" name="content">foo\n bar</textarea>',
  3871. output_text)
  3872. self.assertIn(
  3873. '<textarea rows="5" class="form-control" type="text" '
  3874. 'id="commit_message"\n name="commit_message" '
  3875. 'placeholder="An optional description of the change">'
  3876. 'Signed-off-by: pingou <bar@pingou.com></textarea>', output_text
  3877. )
  3878. def test_edit_file(self):
  3879. """ Test the edit_file endpoint. """
  3880. # No Git repo
  3881. output = self.app.get('/foo/edit/foo/f/sources')
  3882. self.assertEqual(output.status_code, 404)
  3883. user = tests.FakeUser()
  3884. with tests.user_set(self.app.application, user):
  3885. # No project registered in the DB
  3886. output = self.app.get('/foo/edit/foo/f/sources')
  3887. self.assertEqual(output.status_code, 404)
  3888. tests.create_projects(self.session)
  3889. tests.create_projects_git(os.path.join(self.path, 'repos'),
  3890. bare=True)
  3891. # No a repo admin
  3892. output = self.app.get('/test/edit/foo/f/sources')
  3893. self.assertEqual(output.status_code, 403)
  3894. # User not logged in
  3895. output = self.app.get('/test/edit/foo/f/sources')
  3896. self.assertEqual(output.status_code, 302)
  3897. user.username = 'pingou'
  3898. with tests.user_set(self.app.application, user):
  3899. # No such file
  3900. output = self.app.get('/test/edit/foo/f/sources')
  3901. self.assertEqual(output.status_code, 404)
  3902. # Add some content to the git repo
  3903. tests.add_content_git_repo(os.path.join(self.path, 'repos',
  3904. 'test.git'))
  3905. tests.add_readme_git_repo(os.path.join(self.path, 'repos',
  3906. 'test.git'))
  3907. tests.add_binary_git_repo(
  3908. os.path.join(self.path, 'repos', 'test.git'), 'test.jpg')
  3909. tests.add_binary_git_repo(
  3910. os.path.join(self.path, 'repos', 'test.git'), 'test_binary')
  3911. output = self.app.get('/test/edit/master/foofile')
  3912. self.assertEqual(output.status_code, 404)
  3913. # Edit page
  3914. output = self.app.get('/test/edit/master/f/sources')
  3915. self.assertEqual(output.status_code, 200)
  3916. output_text = output.get_data(as_text=True)
  3917. self.assertIn(
  3918. '<li><a href="/test/tree/master"><span class="fa fa-random">'
  3919. '</span>&nbsp; master</a></li><li class="active">'
  3920. '<span class="fa fa-file"></span>&nbsp; sources</li>',
  3921. output_text)
  3922. self.assertIn(
  3923. '<textarea id="textareaCode" name="content">foo\n bar</textarea>',
  3924. output_text)
  3925. # Verify the nav links correctly when editing a file.
  3926. output = self.app.get('/test/blob/master/f/folder1/folder2/file')
  3927. self.assertEqual(output.status_code, 200)
  3928. output_text = output.get_data(as_text=True)
  3929. self.assertIn(
  3930. '<li class="breadcrumb-item"><a href="/test/blob/master/f/folder1/folder2">'
  3931. '\n <span class="fa fa-folder"></span>&nbsp; folder2</a>\n'
  3932. ' </li>', output_text)
  3933. csrf_token = output_text.split(
  3934. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  3935. # View what's supposed to be an image
  3936. output = self.app.get('/test/edit/master/f/test.jpg')
  3937. self.assertEqual(output.status_code, 400)
  3938. output_text = output.get_data(as_text=True)
  3939. self.assertIn('<p>Cannot edit binary files</p>', output_text)
  3940. # Check file before the commit:
  3941. output = self.app.get('/test/raw/master/f/sources')
  3942. self.assertEqual(output.status_code, 200)
  3943. output_text = output.get_data(as_text=True)
  3944. self.assertEqual(output_text, 'foo\n bar')
  3945. # No CSRF Token
  3946. data = {
  3947. 'content': 'foo\n bar\n baz',
  3948. 'commit_title': 'test commit',
  3949. 'commit_message': 'Online commits from the gure.lib.get',
  3950. }
  3951. output = self.app.post('/test/edit/master/f/sources', data=data)
  3952. self.assertEqual(output.status_code, 200)
  3953. output_text = output.get_data(as_text=True)
  3954. self.assertIn(
  3955. '<title>Edit - test - Pagure</title>', output_text)
  3956. # Check that nothing changed
  3957. output = self.app.get('/test/raw/master/f/sources')
  3958. self.assertEqual(output.status_code, 200)
  3959. output_text = output.get_data(as_text=True)
  3960. self.assertEqual(output_text, 'foo\n bar')
  3961. # Missing email
  3962. data['csrf_token'] = csrf_token
  3963. output = self.app.post('/test/edit/master/f/sources', data=data)
  3964. self.assertEqual(output.status_code, 200)
  3965. output_text = output.get_data(as_text=True)
  3966. self.assertIn(
  3967. '<title>Edit - test - Pagure</title>', output_text)
  3968. # Invalid email
  3969. data['email'] = 'pingou@fp.o'
  3970. output = self.app.post('/test/edit/master/f/sources', data=data)
  3971. output_text = output.get_data(as_text=True)
  3972. self.assertIn(
  3973. '<title>Edit - test - Pagure</title>', output_text)
  3974. # Works
  3975. data['email'] = 'bar@pingou.com'
  3976. data['branch'] = 'master'
  3977. output = self.app.post(
  3978. '/test/edit/master/f/sources', data=data,
  3979. follow_redirects=True)
  3980. self.assertEqual(output.status_code, 200)
  3981. output_text = output.get_data(as_text=True)
  3982. self.assertIn(
  3983. '<title>Commits - test - Pagure</title>', output_text)
  3984. self.assertIn('test commit', output_text)
  3985. # Check file after the commit:
  3986. output = self.app.get('/test/raw/master/f/sources')
  3987. self.assertEqual(output.status_code, 200)
  3988. output_text = output.get_data(as_text=True)
  3989. self.assertEqual(output_text, 'foo\n bar\n baz')
  3990. # Add a fork of a fork
  3991. item = pagure.lib.model.Project(
  3992. user_id=1, # pingou
  3993. name='test3',
  3994. description='test project #3',
  3995. is_fork=True,
  3996. parent_id=1,
  3997. hook_token='aaabbbppp',
  3998. )
  3999. self.session.add(item)
  4000. self.session.commit()
  4001. tests.add_content_git_repo(
  4002. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test3.git'))
  4003. tests.add_readme_git_repo(
  4004. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test3.git'))
  4005. tests.add_commit_git_repo(
  4006. os.path.join(self.path, 'repos', 'forks', 'pingou', 'test3.git'),
  4007. ncommits=10)
  4008. # Verify the nav links correctly when editing a file in a fork.
  4009. output = self.app.get(
  4010. '/fork/pingou/test3/edit/master/f/folder1/folder2/file')
  4011. self.assertEqual(output.status_code, 200)
  4012. output_text = output.get_data(as_text=True)
  4013. self.assertIn(
  4014. '<li><a\n href="/fork/pingou/test3/blob/master/f/folder1/folder2"\n'
  4015. ' ><span class="fa fa-folder"></span>&nbsp; folder2</a>\n'
  4016. ' </li>', output_text)
  4017. output = self.app.get('/fork/pingou/test3/edit/master/f/sources')
  4018. self.assertEqual(output.status_code, 200)
  4019. output_text = output.get_data(as_text=True)
  4020. self.assertIn(
  4021. '<li><a href="/fork/pingou/test3/tree/master">'
  4022. '<span class="fa fa-random">'
  4023. '</span>&nbsp; master</a></li><li class="active">'
  4024. '<span class="fa fa-file"></span>&nbsp; sources</li>',
  4025. output_text)
  4026. self.assertIn(
  4027. '<textarea id="textareaCode" name="content">foo\n barRow 0\n',
  4028. output_text)
  4029. # Empty the file - no `content` provided
  4030. data = {
  4031. 'commit_title': 'test commit',
  4032. 'commit_message': 'Online commits from the gure.lib.get',
  4033. 'csrf_token': csrf_token,
  4034. 'email': 'bar@pingou.com',
  4035. 'branch': 'master',
  4036. }
  4037. output = self.app.post(
  4038. '/test/edit/master/f/sources', data=data,
  4039. follow_redirects=True)
  4040. self.assertEqual(output.status_code, 200)
  4041. output_text = output.get_data(as_text=True)
  4042. self.assertIn(
  4043. '<title>Commits - test - Pagure</title>', output_text)
  4044. self.assertIn('test commit', output_text)
  4045. # Check file after the commit:
  4046. output = self.app.get('/test/raw/master/f/sources')
  4047. self.assertEqual(output.status_code, 404)
  4048. output_text = output.get_data(as_text=True)
  4049. self.assertIn(
  4050. '<p>No content found</p>', output_text)
  4051. def test_edit_file_default_email(self):
  4052. """ Test the default email shown by the edit_file endpoint. """
  4053. tests.create_projects(self.session)
  4054. tests.create_projects_git(
  4055. os.path.join(self.path, 'repos'), bare=True)
  4056. # Add some content to the git repo
  4057. tests.add_content_git_repo(
  4058. os.path.join(self.path, 'repos', 'test.git'))
  4059. tests.add_readme_git_repo(
  4060. os.path.join(self.path, 'repos', 'test.git'))
  4061. user = pagure.lib.query.search_user(self.session, username='pingou')
  4062. self.assertEquals(len(user.emails), 2)
  4063. self.assertEquals(user.default_email, 'bar@pingou.com')
  4064. user = tests.FakeUser(username='pingou')
  4065. with tests.user_set(self.app.application, user):
  4066. # Edit page
  4067. output = self.app.get('/test/edit/master/f/sources')
  4068. self.assertEqual(output.status_code, 200)
  4069. output_text = output.get_data(as_text=True)
  4070. self.assertIn(
  4071. '<li><a href="/test/tree/master"><span class="fa fa-random">'
  4072. '</span>&nbsp; master</a></li><li class="active">'
  4073. '<span class="fa fa-file"></span>&nbsp; sources</li>',
  4074. output_text)
  4075. self.assertIn(
  4076. '<textarea id="textareaCode" name="content">foo\n bar</textarea>',
  4077. output_text)
  4078. self.assertIn(
  4079. '<option value="bar@pingou.com" selected>bar@pingou.com'
  4080. '</option>', output_text)
  4081. self.assertIn(
  4082. '<option value="foo@pingou.com" >foo@pingou.com</option>',
  4083. output_text)
  4084. @patch('pagure.decorators.admin_session_timedout')
  4085. def test_change_ref_head(self,ast):
  4086. """ Test the change_ref_head endpoint. """
  4087. ast.return_value = True
  4088. # No Git repo
  4089. output = self.app.post('/foo/default/branch/')
  4090. self.assertEqual(output.status_code, 404)
  4091. user = tests.FakeUser()
  4092. with tests.user_set(self.app.application, user):
  4093. output = self.app.post('/foo/default/branch/')
  4094. self.assertEqual(output.status_code, 404)
  4095. ast.return_value = False
  4096. output = self.app.post('/foo/default/branch/')
  4097. self.assertEqual(output.status_code, 404)
  4098. tests.create_projects(self.session)
  4099. repos = tests.create_projects_git(os.path.join(self.path, 'repos'))
  4100. output = self.app.post('/test/default/branch/')
  4101. self.assertEqual(output.status_code, 403)
  4102. # User no logged in
  4103. output = self.app.post('/test/default/branch/')
  4104. self.assertEqual(output.status_code, 302)
  4105. user.username = 'pingou'
  4106. with tests.user_set(self.app.application, user):
  4107. output = self.app.post('/test/default/branch/',
  4108. follow_redirects=True) # without git branch
  4109. self.assertEqual(output.status_code, 200)
  4110. output_text = output.get_data(as_text=True)
  4111. self.assertIn(
  4112. '<title>Settings - test - Pagure</title>', output_text)
  4113. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  4114. if self.get_wtforms_version() >= (2, 2):
  4115. self.assertIn(
  4116. '<select class="c-select" id="branches" name="branches" '
  4117. 'required></select>', output_text)
  4118. else:
  4119. self.assertIn(
  4120. '<select class="c-select" id="branches" name="branches">'
  4121. '</select>', output_text)
  4122. csrf_token = output_text.split(
  4123. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  4124. repo_obj = pygit2.Repository(repos[0])
  4125. tree = repo_obj.index.write_tree()
  4126. author = pygit2.Signature(
  4127. 'Alice Author', 'alice@authors.tld')
  4128. committer = pygit2.Signature(
  4129. 'Cecil Committer', 'cecil@committers.tld')
  4130. repo_obj.create_commit(
  4131. 'refs/heads/master', # the name of the reference to update
  4132. author,
  4133. committer,
  4134. 'Add sources file for testing',
  4135. # binary string representing the tree object ID
  4136. tree,
  4137. # list of binary strings representing parents of the new commit
  4138. []
  4139. )
  4140. repo_obj.create_branch("feature",repo_obj.head.get_object())
  4141. data = {
  4142. 'branches': 'feature',
  4143. 'csrf_token': csrf_token,
  4144. }
  4145. # changing head to feature branch
  4146. output = self.app.post('/test/default/branch/',
  4147. data=data,
  4148. follow_redirects=True)
  4149. self.assertEqual(output.status_code, 200)
  4150. output_text = output.get_data(as_text=True)
  4151. self.assertIn(
  4152. '<title>Settings - test - Pagure</title>', output_text)
  4153. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  4154. if self.get_wtforms_version() >= (2, 2):
  4155. self.assertIn(
  4156. '<select class="c-select" id="branches" name="branches" '
  4157. 'required>'
  4158. '<option selected value="feature">feature</option>'
  4159. '<option value="master">master</option>'
  4160. '</select>', output_text)
  4161. else:
  4162. self.assertIn(
  4163. '<select class="c-select" id="branches" name="branches">'
  4164. '<option selected value="feature">feature</option>'
  4165. '<option value="master">master</option>'
  4166. '</select>', output_text)
  4167. self.assertIn(
  4168. 'Default branch updated '
  4169. 'to feature', output_text)
  4170. data = {
  4171. 'branches': 'master',
  4172. 'csrf_token': csrf_token,
  4173. }
  4174. # changing head to master branch
  4175. output = self.app.post('/test/default/branch/',
  4176. data=data,
  4177. follow_redirects=True)
  4178. self.assertEqual(output.status_code, 200)
  4179. output_text = output.get_data(as_text=True)
  4180. self.assertIn(
  4181. '<title>Settings - test - Pagure</title>', output_text)
  4182. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  4183. if self.get_wtforms_version() >= (2, 2):
  4184. self.assertIn(
  4185. '<select class="c-select" id="branches" name="branches" '
  4186. 'required>'
  4187. '<option value="feature">feature</option>'
  4188. '<option selected value="master">master</option>'
  4189. '</select>', output_text)
  4190. else:
  4191. self.assertIn(
  4192. '<select class="c-select" id="branches" name="branches">'
  4193. '<option value="feature">feature</option>'
  4194. '<option selected value="master">master</option>'
  4195. '</select>', output_text)
  4196. self.assertIn(
  4197. 'Default branch updated '
  4198. 'to master', output_text)
  4199. def test_new_release(self):
  4200. """ Test the new_release endpoint. """
  4201. # No Git repo
  4202. output = self.app.post('/foo/upload/')
  4203. self.assertEqual(output.status_code, 404)
  4204. user = tests.FakeUser()
  4205. with tests.user_set(self.app.application, user):
  4206. output = self.app.post('/foo/upload/')
  4207. self.assertEqual(output.status_code, 404)
  4208. tests.create_projects(self.session)
  4209. repo = tests.create_projects_git(os.path.join(self.path, 'repos'))
  4210. output = self.app.post('/test/upload/')
  4211. self.assertEqual(output.status_code, 403)
  4212. # User not logged in
  4213. output = self.app.post('/test/upload/')
  4214. self.assertEqual(output.status_code, 302)
  4215. user.username = 'pingou'
  4216. with tests.user_set(self.app.application, user):
  4217. img = os.path.join(os.path.abspath(os.path.dirname(__file__)),
  4218. 'placebo.png')
  4219. # Missing CSRF Token
  4220. with open(img, mode='rb') as stream:
  4221. data = {'filestream': stream}
  4222. output = self.app.post('/test/upload/', data=data)
  4223. self.assertEqual(output.status_code, 200)
  4224. output_text = output.get_data(as_text=True)
  4225. self.assertIn('<h2>Upload a new release</h2>', output_text)
  4226. csrf_token = output_text.split(
  4227. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  4228. upload_dir = os.path.join(self.path, 'releases')
  4229. self.assertEqual(os.listdir(upload_dir), [])
  4230. # Upload successful
  4231. with open(img, mode='rb') as stream:
  4232. data = {'filestream': stream, 'csrf_token': csrf_token}
  4233. output = self.app.post(
  4234. '/test/upload/', data=data, follow_redirects=True)
  4235. self.assertEqual(output.status_code, 200)
  4236. output_text = output.get_data(as_text=True)
  4237. self.assertIn(
  4238. 'File', output_text)
  4239. self.assertIn(
  4240. 'uploaded', output_text)
  4241. self.assertIn('This project has not been tagged.', output_text)
  4242. self.assertEqual(os.listdir(upload_dir), ['test'])
  4243. folder = os.path.join(upload_dir, 'test')
  4244. checksum_file = os.path.join(folder, 'CHECKSUMS')
  4245. # Wait for the worker to create the checksums file
  4246. cnt = 0
  4247. while not os.path.exists(checksum_file):
  4248. print(os.listdir(os.path.join(upload_dir, 'test')))
  4249. cnt += 1
  4250. if cnt == 40:
  4251. raise ValueError(
  4252. 'The worker did not create the checksums file '
  4253. 'in a timely manner')
  4254. time.sleep(0.5)
  4255. self.assertEqual(len(os.listdir(folder)), 2)
  4256. self.assertTrue(os.path.exists(checksum_file))
  4257. # Check the content of the checksums file
  4258. with open(checksum_file) as stream:
  4259. data = stream.readlines()
  4260. self.assertEqual(len(data), 3)
  4261. self.assertEqual(data[0], '# Generated and updated by pagure\n')
  4262. self.assertTrue(data[1].startswith('SHA256 ('))
  4263. self.assertTrue(data[1].endswith(
  4264. 'tests_placebo.png) = 8a06845923010b27bfd8e7e75acff'
  4265. '7badc40d1021b4994e01f5e11ca40bc3abe\n'))
  4266. self.assertTrue(data[2].startswith('SHA512 ('))
  4267. self.assertTrue(data[2].endswith(
  4268. 'tests_placebo.png) = 65a4458df0acb29dc3c5ad4a3620e'
  4269. '98841d1fcf3f8df358f5348fdeddd1a86706491ac6e416768e'
  4270. '9f218aae8147d6ac524a59d3eb91fb925fdcb5c489e55ccbb\n'))
  4271. # Try uploading the same file -- fails
  4272. with open(img, mode='rb') as stream:
  4273. data = {'filestream': stream, 'csrf_token': csrf_token}
  4274. output = self.app.post(
  4275. '/test/upload/', data=data, follow_redirects=True)
  4276. self.assertEqual(output.status_code, 200)
  4277. output_text = output.get_data(as_text=True)
  4278. self.assertIn(
  4279. 'This tarball has already '
  4280. 'been uploaded', output_text)
  4281. self.assertIn('This project has not been tagged.', output_text)
  4282. def test_new_release_two_files(self):
  4283. """ Test the new_release endpoint when uploading two files. """
  4284. tests.create_projects(self.session)
  4285. repo = tests.create_projects_git(os.path.join(self.path, 'repos'))
  4286. user = tests.FakeUser(username='pingou')
  4287. with tests.user_set(self.app.application, user):
  4288. img = os.path.join(
  4289. os.path.abspath(os.path.dirname(__file__)), 'placebo.png')
  4290. img2 = os.path.join(
  4291. os.path.abspath(os.path.dirname(__file__)), 'pagure.png')
  4292. csrf_token = self.get_csrf()
  4293. upload_dir = os.path.join(self.path, 'releases')
  4294. self.assertEqual(os.listdir(upload_dir), [])
  4295. # Upload successful
  4296. with open(img, mode='rb') as stream:
  4297. with open(img2, mode='rb') as stream2:
  4298. data = {
  4299. 'filestream': [stream, stream2],
  4300. 'csrf_token': csrf_token
  4301. }
  4302. output = self.app.post(
  4303. '/test/upload/', data=data, follow_redirects=True)
  4304. self.assertEqual(output.status_code, 200)
  4305. output_text = output.get_data(as_text=True)
  4306. self.assertIn(
  4307. '<i class="fa fa-fw fa-info-circle"></i> File', output_text)
  4308. self.assertIn('pagure.png&#34; uploaded</div>\n', output_text)
  4309. # self.assertTrue(0)
  4310. self.assertEqual(os.listdir(upload_dir), ['test'])
  4311. folder = os.path.join(upload_dir, 'test')
  4312. checksum_file = os.path.join(folder, 'CHECKSUMS')
  4313. # Wait for the worker to create the checksums file
  4314. cnt = 0
  4315. while not os.path.exists(checksum_file):
  4316. cnt += 1
  4317. if cnt == 40:
  4318. raise ValueError(
  4319. 'The worker did not create the checksums file '
  4320. 'in a timely manner')
  4321. time.sleep(0.5)
  4322. self.assertEqual(len(os.listdir(folder)), 3)
  4323. self.assertTrue(os.path.exists(checksum_file))
  4324. # Check the content of the checksums file
  4325. with open(checksum_file) as stream:
  4326. data = stream.readlines()
  4327. self.assertEqual(len(data), 5)
  4328. self.assertEqual(data[0], '# Generated and updated by pagure\n')
  4329. self.assertTrue(data[1].startswith('SHA256 ('))
  4330. self.assertTrue(data[1].endswith(
  4331. 'tests_placebo.png) = 8a06845923010b27bfd8e7e75acff'
  4332. '7badc40d1021b4994e01f5e11ca40bc3abe\n'))
  4333. self.assertTrue(data[2].startswith('SHA512 ('))
  4334. self.assertTrue(data[2].endswith(
  4335. 'tests_placebo.png) = 65a4458df0acb29dc3c5ad4a3620e'
  4336. '98841d1fcf3f8df358f5348fdeddd1a86706491ac6e416768e'
  4337. '9f218aae8147d6ac524a59d3eb91fb925fdcb5c489e55ccbb\n'))
  4338. self.assertTrue(data[3].startswith('SHA256 ('))
  4339. self.assertTrue(data[3].endswith(
  4340. 'tests_pagure.png) = 6498a2de405546200b6144da56fc25'
  4341. 'd0a3976ae688dbfccaca609c8b4480523e\n'))
  4342. self.assertTrue(data[4].startswith('SHA512 ('))
  4343. self.assertTrue(data[4].endswith(
  4344. 'tests_pagure.png) = 15458775e5d73cd74de7da7224597f6'
  4345. '7f8b23d62d3affb8abba4f5db74d33235642a0f744de2265cca7'
  4346. 'd2b5866782c45e1fdeb32dd2822ae33e97995d4879afd\n'))
  4347. @patch('pagure.decorators.admin_session_timedout')
  4348. def test_add_token_all_tokens(self, ast):
  4349. """ Test the add_token endpoint. """
  4350. ast.return_value = False
  4351. tests.create_projects(self.session)
  4352. tests.create_projects_git(
  4353. os.path.join(self.path, 'repos'), bare=True)
  4354. user = tests.FakeUser(username='pingou')
  4355. with tests.user_set(self.app.application, user):
  4356. output = self.app.get('/test/token/new/')
  4357. self.assertEqual(output.status_code, 200)
  4358. output_text = output.get_data(as_text=True)
  4359. self.assertIn('<strong>Create a new token</strong>', output_text)
  4360. self.assertEqual(
  4361. output_text.count('<label class="c-input c-checkbox">'),
  4362. len(pagure.config.config['ACLS'].keys()) - 2
  4363. )
  4364. @patch.dict('pagure.config.config', {'USER_ACLS': ['create_project']})
  4365. @patch('pagure.decorators.admin_session_timedout')
  4366. def test_add_token_one_token(self, ast):
  4367. """ Test the add_token endpoint. """
  4368. ast.return_value = False
  4369. tests.create_projects(self.session)
  4370. tests.create_projects_git(
  4371. os.path.join(self.path, 'repos'), bare=True)
  4372. user = tests.FakeUser(username='pingou')
  4373. with tests.user_set(self.app.application, user):
  4374. output = self.app.get('/test/token/new/')
  4375. self.assertEqual(output.status_code, 200)
  4376. output_text = output.get_data(as_text=True)
  4377. self.assertIn('<strong>Create a new token</strong>', output_text)
  4378. self.assertEqual(
  4379. output_text.count('<label class="c-input c-checkbox">'),
  4380. 1
  4381. )
  4382. @patch('pagure.decorators.admin_session_timedout')
  4383. def test_add_token(self, ast):
  4384. """ Test the add_token endpoint. """
  4385. ast.return_value = False
  4386. # No Git repo
  4387. output = self.app.get('/foo/token/new/')
  4388. self.assertEqual(output.status_code, 404)
  4389. user = tests.FakeUser()
  4390. with tests.user_set(self.app.application, user):
  4391. output = self.app.get('/foo/token/new/')
  4392. self.assertEqual(output.status_code, 404)
  4393. tests.create_projects(self.session)
  4394. tests.create_projects_git(os.path.join(self.path, 'repos'),
  4395. bare=True)
  4396. output = self.app.get('/test/token/new/')
  4397. self.assertEqual(output.status_code, 403)
  4398. # User not logged in
  4399. output = self.app.get('/test/token/new/')
  4400. self.assertEqual(output.status_code, 302)
  4401. user.username = 'pingou'
  4402. with tests.user_set(self.app.application, user):
  4403. output = self.app.get('/test/token/new/')
  4404. self.assertEqual(output.status_code, 200)
  4405. output_text = output.get_data(as_text=True)
  4406. self.assertIn('<strong>Create a new token</strong>', output_text)
  4407. csrf_token = output_text.split(
  4408. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  4409. data = {'csrf_token': csrf_token}
  4410. ast.return_value = True
  4411. # Test when the session timed-out
  4412. output = self.app.post('/test/token/new/', data=data)
  4413. self.assertEqual(output.status_code, 302)
  4414. output = self.app.get('/', follow_redirects=True)
  4415. self.assertEqual(output.status_code, 200)
  4416. output_text = output.get_data(as_text=True)
  4417. self.assertIn(
  4418. 'Action canceled, try it '
  4419. 'again', output_text)
  4420. ast.return_value = False
  4421. # Missing acls
  4422. output = self.app.post('/test/token/new/', data=data)
  4423. self.assertEqual(output.status_code, 200)
  4424. output_text = output.get_data(as_text=True)
  4425. self.assertIn('<strong>Create a new token</strong>', output_text)
  4426. self.assertIn(
  4427. 'You must select at least '
  4428. 'one permission.', output_text)
  4429. data = {
  4430. 'csrf_token': csrf_token,
  4431. 'acls': ['issue_create'],
  4432. 'description': 'Test token',
  4433. }
  4434. # New token created
  4435. output = self.app.post(
  4436. '/test/token/new/', data=data, follow_redirects=True)
  4437. self.assertEqual(output.status_code, 200)
  4438. output_text = output.get_data(as_text=True)
  4439. self.assertIn(
  4440. 'Token created', output_text)
  4441. self.assertIn(
  4442. '<title>Settings - test - Pagure</title>', output_text)
  4443. self.assertIn('<h5 class="pl-2 font-weight-bold text-muted">Project Settings</h5>', output_text)
  4444. self.assertIn('<strong> Test token</strong>', output_text)
  4445. self.assertIn(
  4446. '<span class="input-group-text text-success">'
  4447. '\n <small class="font-weight-bold">'
  4448. 'Active until', output_text)
  4449. @patch('pagure.decorators.admin_session_timedout')
  4450. def test_revoke_api_token(self, ast):
  4451. """ Test the revoke_api_token endpoint. """
  4452. ast.return_value = False
  4453. # No Git repo
  4454. output = self.app.post('/foo/token/revoke/123')
  4455. self.assertEqual(output.status_code, 404)
  4456. user = tests.FakeUser()
  4457. with tests.user_set(self.app.application, user):
  4458. output = self.app.post('/foo/token/revoke/123')
  4459. self.assertEqual(output.status_code, 404)
  4460. tests.create_projects(self.session)
  4461. tests.create_projects_git(os.path.join(self.path, 'repos'),
  4462. bare=True)
  4463. output = self.app.post('/test/token/revoke/123')
  4464. self.assertEqual(output.status_code, 403)
  4465. # User not logged in
  4466. output = self.app.post('/test/token/revoke/123')
  4467. self.assertEqual(output.status_code, 302)
  4468. user.username = 'pingou'
  4469. with tests.user_set(self.app.application, user):
  4470. output = self.app.get('/test/token/new')
  4471. self.assertEqual(output.status_code, 200)
  4472. output_text = output.get_data(as_text=True)
  4473. self.assertIn('<strong>Create a new token</strong>', output_text)
  4474. csrf_token = output_text.split(
  4475. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  4476. data = {'csrf_token': csrf_token}
  4477. ast.return_value = True
  4478. # Test when the session timed-out
  4479. output = self.app.post('/test/token/revoke/123', data=data)
  4480. self.assertEqual(output.status_code, 302)
  4481. output = self.app.get('/', follow_redirects=True)
  4482. self.assertEqual(output.status_code, 200)
  4483. output_text = output.get_data(as_text=True)
  4484. self.assertIn(
  4485. 'Action canceled, try it again',
  4486. output_text)
  4487. ast.return_value = False
  4488. output = self.app.post('/test/token/revoke/123', data=data)
  4489. self.assertEqual(output.status_code, 404)
  4490. output_text = output.get_data(as_text=True)
  4491. self.assertIn('<p>Token not found</p>', output_text)
  4492. # Create a token to revoke
  4493. data = {'csrf_token': csrf_token, 'acls': ['issue_create']}
  4494. output = self.app.post(
  4495. '/test/token/new/', data=data, follow_redirects=True)
  4496. self.assertEqual(output.status_code, 200)
  4497. output_text = output.get_data(as_text=True)
  4498. self.assertIn(
  4499. 'Token created',
  4500. output_text)
  4501. # Existing token will expire in 60 days
  4502. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  4503. self.assertEqual(
  4504. repo.tokens[0].expiration.date(),
  4505. datetime.datetime.utcnow().date() + datetime.timedelta(days=60))
  4506. token = repo.tokens[0].id
  4507. output = self.app.post(
  4508. '/test/token/revoke/%s' % token,
  4509. data=data,
  4510. follow_redirects=True)
  4511. output_text = output.get_data(as_text=True)
  4512. self.assertIn(
  4513. '<title>Settings - test - Pagure</title>', output_text)
  4514. self.assertIn(
  4515. 'Token revoked',
  4516. output_text)
  4517. self.assertEqual(output_text.count('title="Revoke token">'), 0)
  4518. self.assertEqual(output_text.count('title="Renew token">'), 1)
  4519. # Existing token has been expired
  4520. self.session.commit()
  4521. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  4522. self.assertEqual(
  4523. repo.tokens[0].expiration.date(),
  4524. repo.tokens[0].created.date())
  4525. self.assertEqual(
  4526. repo.tokens[0].expiration.date(),
  4527. datetime.datetime.utcnow().date())
  4528. @patch('pagure.decorators.admin_session_timedout')
  4529. def test_renew_api_token(self, ast):
  4530. """ Test the renew_api_token endpoint. """
  4531. ast.return_value=False
  4532. # No Git repo
  4533. output = self.app.post('/foo/token/renew/123')
  4534. self.assertEqual(output.status_code, 404)
  4535. user = tests.FakeUser()
  4536. with tests.user_set(self.app.application, user):
  4537. # user logged in but still no git repo
  4538. output = self.app.post('/foo/token/renew/123')
  4539. self.assertEqual(output.status_code, 404)
  4540. tests.create_projects(self.session)
  4541. tests.create_projects_git(os.path.join(self.path, 'repos'),
  4542. bare=True)
  4543. # user logged in, git repo present, but user doesn't have access
  4544. output = self.app.post('/test/token/renew/123')
  4545. self.assertEqual(output.status_code, 403)
  4546. # User not logged in
  4547. output = self.app.post('/test/token/renew/123')
  4548. self.assertEqual(output.status_code, 302)
  4549. user.username = 'pingou'
  4550. with tests.user_set(self.app.application, user):
  4551. output = self.app.get('/test/token/new')
  4552. self.assertEqual(output.status_code, 200)
  4553. output_text = output.get_data(as_text=True)
  4554. self.assertIn('<strong>Create a new token</strong>', output_text)
  4555. csrf_token = self.get_csrf(output=output)
  4556. data = {'csrf_token': csrf_token}
  4557. ast.return_value = True
  4558. # Test when the session timed-out
  4559. output = self.app.post('/test/token/renew/123', data=data)
  4560. self.assertEqual(output.status_code, 302)
  4561. output = self.app.get('/', follow_redirects=True)
  4562. self.assertEqual(output.status_code, 200)
  4563. output_text = output.get_data(as_text=True)
  4564. self.assertIn(
  4565. 'Action canceled, try it again',
  4566. output_text)
  4567. ast.return_value = False
  4568. output = self.app.post('/test/token/renew/123', data=data)
  4569. self.assertEqual(output.status_code, 404)
  4570. output_text = output.get_data(as_text=True)
  4571. self.assertIn('<p>Token not found</p>', output_text)
  4572. # Create a token to renew
  4573. data = {'csrf_token': csrf_token, 'acls': ['issue_create']}
  4574. output = self.app.post(
  4575. '/test/token/new/', data=data, follow_redirects=True)
  4576. self.assertEqual(output.status_code, 200)
  4577. output_text = output.get_data(as_text=True)
  4578. self.assertIn(
  4579. 'Token created',
  4580. output_text)
  4581. # 1 token associated with the project, expires in 60 days
  4582. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  4583. self.assertEqual(len(repo.tokens), 1)
  4584. self.assertEqual(
  4585. repo.tokens[0].expiration.date(),
  4586. datetime.datetime.utcnow().date() + datetime.timedelta(days=60))
  4587. token = repo.tokens[0].id
  4588. output = self.app.post(
  4589. '/test/token/renew/%s' % token,
  4590. data=data,
  4591. follow_redirects=True)
  4592. output_text = output.get_data(as_text=True)
  4593. self.assertIn(
  4594. '<title>Settings - test - Pagure</title>', output_text)
  4595. self.assertIn(
  4596. 'Token created',
  4597. output_text)
  4598. self.assertEqual(output_text.count('title="Revoke token">'), 2)
  4599. self.assertEqual(output_text.count('title="Renew token">'), 0)
  4600. # Existing token has been renewed
  4601. self.session.commit()
  4602. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  4603. self.assertEqual(len(repo.tokens), 2)
  4604. self.assertEqual(
  4605. repo.tokens[0].expiration.date(),
  4606. repo.tokens[1].expiration.date())
  4607. self.assertEqual(
  4608. repo.tokens[0].created.date(),
  4609. repo.tokens[1].created.date())
  4610. self.assertEqual(
  4611. repo.tokens[0].acls,
  4612. repo.tokens[1].acls)
  4613. self.assertEqual(
  4614. repo.tokens[0].description,
  4615. repo.tokens[1].description)
  4616. def test_delete_branch(self):
  4617. """ Test the delete_branch endpoint. """
  4618. # No Git repo
  4619. output = self.app.post('/foo/b/master/delete')
  4620. self.assertEqual(output.status_code, 404)
  4621. tests.create_projects(self.session)
  4622. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  4623. # User not logged in
  4624. output = self.app.post('/test/b/master/delete')
  4625. self.assertEqual(output.status_code, 302)
  4626. user = tests.FakeUser()
  4627. with tests.user_set(self.app.application, user):
  4628. # Unknown repo
  4629. output = self.app.post('/foo/b/master/delete')
  4630. self.assertEqual(output.status_code, 404)
  4631. output = self.app.post('/test/b/master/delete')
  4632. self.assertEqual(output.status_code, 403)
  4633. user.username = 'pingou'
  4634. with tests.user_set(self.app.application, user):
  4635. output = self.app.post('/test/b/master/delete')
  4636. self.assertEqual(output.status_code, 403)
  4637. output_text = output.get_data(as_text=True)
  4638. self.assertIn(
  4639. '<p>You are not allowed to delete the master branch</p>',
  4640. output_text)
  4641. output = self.app.post('/test/b/bar/delete')
  4642. self.assertEqual(output.status_code, 404)
  4643. output_text = output.get_data(as_text=True)
  4644. self.assertIn('<p>Branch not found</p>', output_text)
  4645. # Add a branch that we can delete
  4646. path = os.path.join(self.path, 'repos', 'test.git')
  4647. tests.add_content_git_repo(path)
  4648. repo = pygit2.Repository(path)
  4649. repo.create_branch('foo', repo.head.get_object())
  4650. # Check before deletion
  4651. output = self.app.get('/test')
  4652. self.assertEqual(output.status_code, 200)
  4653. output = self.app.get('/test/branches')
  4654. output_text = output.get_data(as_text=True)
  4655. self.assertIn('<form id="delete_branch_form-foo"', output_text)
  4656. # Delete the branch
  4657. output = self.app.post('/test/b/foo/delete', follow_redirects=True)
  4658. self.assertEqual(output.status_code, 200)
  4659. output = self.app.get('/test/branches')
  4660. output_text = output.get_data(as_text=True)
  4661. self.assertNotIn(
  4662. '<form id="delete_branch_form-foo"', output_text)
  4663. # Add a branch with a '/' in its name that we can delete
  4664. path = os.path.join(self.path, 'repos', 'test.git')
  4665. tests.add_content_git_repo(path)
  4666. repo = pygit2.Repository(path)
  4667. repo.create_branch('feature/foo', repo.head.get_object())
  4668. # Check before deletion
  4669. output = self.app.get('/test')
  4670. self.assertEqual(output.status_code, 200)
  4671. output = self.app.get('/test/branches')
  4672. output_text = output.get_data(as_text=True)
  4673. self.assertIn(
  4674. '<form id="delete_branch_form-feature__foo"', output_text)
  4675. # Delete the branch
  4676. output = self.app.post('/test/b/feature/foo/delete', follow_redirects=True)
  4677. self.assertEqual(output.status_code, 200)
  4678. output = self.app.get('/test/branches')
  4679. output_text = output.get_data(as_text=True)
  4680. self.assertNotIn(
  4681. '<form id="delete_branch_form-feature__foo"', output_text)
  4682. @patch.dict('pagure.config.config', {'ALLOW_DELETE_BRANCH': False})
  4683. def test_delete_branch_disabled_in_ui(self):
  4684. """ Test that the delete branch button doesn't show when the feature
  4685. is turned off. """
  4686. tests.create_projects(self.session)
  4687. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  4688. # Add a branch that we can delete
  4689. path = os.path.join(self.path, 'repos', 'test.git')
  4690. tests.add_content_git_repo(path)
  4691. repo = pygit2.Repository(path)
  4692. repo.create_branch('foo', repo.head.get_object())
  4693. user = tests.FakeUser(username = 'pingou')
  4694. with tests.user_set(self.app.application, user):
  4695. # Check that the UI doesn't offer the button
  4696. output = self.app.get('/test')
  4697. self.assertEqual(output.status_code, 200)
  4698. output_text = output.get_data(as_text=True)
  4699. self.assertNotIn('<form id="delete_branch_form-foo"', output_text)
  4700. self.assertNotIn(
  4701. 'Are you sure you want to remove the branch',
  4702. output_text)
  4703. @patch.dict('pagure.config.config', {'ALLOW_DELETE_BRANCH': False})
  4704. def test_delete_branch_disabled(self):
  4705. """ Test the delete_branch endpoint when it's disabled in the entire
  4706. instance. """
  4707. tests.create_projects(self.session)
  4708. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  4709. # Add a branch that we can delete
  4710. path = os.path.join(self.path, 'repos', 'test.git')
  4711. tests.add_content_git_repo(path)
  4712. repo = pygit2.Repository(path)
  4713. repo.create_branch('foo', repo.head.get_object())
  4714. user = tests.FakeUser(username = 'pingou')
  4715. with tests.user_set(self.app.application, user):
  4716. # Check if the delete branch button does not show
  4717. output = self.app.get('/test/branches')
  4718. self.assertEqual(output.status_code, 200)
  4719. self.assertNotIn(
  4720. 'title="Remove branch foo"',
  4721. output.get_data(as_text=True))
  4722. # Delete the branch
  4723. output = self.app.post('/test/b/foo/delete', follow_redirects=True)
  4724. self.assertEqual(output.status_code, 404)
  4725. self.assertIn(
  4726. 'This pagure instance does not allow branch deletion',
  4727. output.get_data(as_text=True))
  4728. @patch.dict('pagure.config.config', {'ALLOW_DELETE_BRANCH': False})
  4729. def test_delete_branch_disabled_fork(self):
  4730. """ Test the delete_branch endpoint when it's disabled in the entire
  4731. instance. """
  4732. item = pagure.lib.model.Project(
  4733. user_id=2, # foo
  4734. name='test',
  4735. description='test project #1',
  4736. hook_token='aaabbb',
  4737. is_fork=True,
  4738. parent_id=1,
  4739. )
  4740. self.session.add(item)
  4741. self.session.commit()
  4742. tests.create_projects_git(
  4743. os.path.join(self.path, 'repos', 'forks', 'foo'), bare=True)
  4744. # Add a branch that we can delete
  4745. path = os.path.join(self.path, 'repos', 'forks', 'foo', 'test.git')
  4746. tests.add_content_git_repo(path)
  4747. repo = pygit2.Repository(path)
  4748. repo.create_branch('foo', repo.head.get_object())
  4749. user = tests.FakeUser(username = 'foo')
  4750. with tests.user_set(self.app.application, user):
  4751. # Check if the delete branch button shows
  4752. output = self.app.get('/fork/foo/test/branches')
  4753. self.assertEqual(output.status_code, 200)
  4754. self.assertIn(
  4755. 'title="Remove branch foo"',
  4756. output.get_data(as_text=True))
  4757. # Delete the branch
  4758. output = self.app.post(
  4759. '/fork/foo/test/b/foo/delete',
  4760. follow_redirects=True)
  4761. self.assertEqual(output.status_code, 200)
  4762. # Check if the delete branch button no longer appears
  4763. output = self.app.get('/fork/foo/test/branches')
  4764. self.assertEqual(output.status_code, 200)
  4765. self.assertNotIn(
  4766. 'title="Remove branch foo"',
  4767. output.get_data(as_text=True))
  4768. def test_view_docs(self):
  4769. """ Test the view_docs endpoint. """
  4770. output = self.app.get('/docs/foo/')
  4771. # No project registered in the DB
  4772. self.assertEqual(output.status_code, 404)
  4773. tests.create_projects(self.session)
  4774. output = self.app.get('/docs/test/')
  4775. # No git repo associated
  4776. self.assertEqual(output.status_code, 404)
  4777. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  4778. output = self.app.get('/docs/test/')
  4779. self.assertEqual(output.status_code, 404)
  4780. def test_view_project_activity(self):
  4781. """ Test the view_project_activity endpoint. """
  4782. tests.create_projects(self.session)
  4783. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  4784. # Project Exists, but No DATAGREPPER_URL set
  4785. output = self.app.get('/test/activity/')
  4786. self.assertEqual(output.status_code, 404)
  4787. # Project Exists, and DATAGREPPER_URL set
  4788. pagure.config.config['DATAGREPPER_URL'] = 'foo'
  4789. output = self.app.get('/test/activity/')
  4790. self.assertEqual(output.status_code, 200)
  4791. output_text = output.get_data(as_text=True)
  4792. self.assertIn(
  4793. '<title>Activity - test - Pagure</title>', output_text)
  4794. self.assertIn(
  4795. 'No activity reported on the test project', output_text)
  4796. # project doesnt exist
  4797. output = self.app.get('/foo/activity/')
  4798. self.assertEqual(output.status_code, 404)
  4799. def test_goimport(self):
  4800. """ Test the go-import tag. """
  4801. tests.create_projects(self.session)
  4802. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  4803. output = self.app.get('/test/')
  4804. self.assertEqual(output.status_code, 200)
  4805. output_text = output.get_data(as_text=True)
  4806. self.assertIn('<meta name="go-import" '
  4807. 'content="localhost.localdomain/test git git://localhost.localdomain/test.git"'
  4808. '>',
  4809. output_text)
  4810. def test_watch_repo(self):
  4811. """ Test the watch_repo endpoint. """
  4812. output = self.app.post('/watch/')
  4813. self.assertEqual(output.status_code, 405)
  4814. tests.create_projects(self.session)
  4815. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  4816. user = tests.FakeUser()
  4817. user.username = 'pingou'
  4818. with tests.user_set(self.app.application, user):
  4819. output = self.app.get('/new/')
  4820. self.assertEqual(output.status_code, 200)
  4821. output_text = output.get_data(as_text=True)
  4822. self.assertIn('<strong>Create new Project</strong>', output_text)
  4823. csrf_token = output_text.split(
  4824. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  4825. data = {
  4826. 'csrf_token':csrf_token
  4827. }
  4828. output = self.app.post(
  4829. '/foo/watch/settings/1', data=data, follow_redirects=True)
  4830. self.assertEqual(output.status_code, 404)
  4831. output = self.app.post(
  4832. '/test/watch/settings/8', data=data, follow_redirects=True)
  4833. self.assertEqual(output.status_code, 400)
  4834. output = self.app.post(
  4835. '/test/watch/settings/0', data=data, follow_redirects=True)
  4836. output_text = output.get_data(as_text=True)
  4837. self.assertIn(
  4838. 'You are no longer'
  4839. ' watching this project', output_text)
  4840. output = self.app.post(
  4841. '/test/watch/settings/1', data=data, follow_redirects=True)
  4842. output_text = output.get_data(as_text=True)
  4843. self.assertIn(
  4844. 'You are now'
  4845. ' watching issues and PRs on this project', output_text)
  4846. output = self.app.post(
  4847. '/test/watch/settings/2', data=data, follow_redirects=True)
  4848. output_text = output.get_data(as_text=True)
  4849. self.assertIn(
  4850. 'You are now'
  4851. ' watching commits on this project', output_text)
  4852. output = self.app.post(
  4853. '/test/watch/settings/3', data=data, follow_redirects=True)
  4854. output_text = output.get_data(as_text=True)
  4855. self.assertIn(
  4856. ('You are now'
  4857. ' watching issues, PRs, and commits on this project'),
  4858. output_text)
  4859. item = pagure.lib.model.Project(
  4860. user_id=2, # foo
  4861. name='test',
  4862. description='foo project #1',
  4863. hook_token='aaabbb',
  4864. is_fork=True,
  4865. parent_id=1,
  4866. )
  4867. self.session.add(item)
  4868. self.session.commit()
  4869. gitrepo = os.path.join(self.path, 'repos', 'forks', 'foo',
  4870. 'test.git')
  4871. pygit2.init_repository(gitrepo, bare=True)
  4872. output = self.app.post(
  4873. '/fork/foo/test/watch/settings/-1', data=data,
  4874. follow_redirects=True)
  4875. output_text = output.get_data(as_text=True)
  4876. self.assertIn(
  4877. 'Watch status is already reset',
  4878. output_text)
  4879. output = self.app.post(
  4880. '/fork/foo/test/watch/settings/0', data=data,
  4881. follow_redirects=True)
  4882. output_text = output.get_data(as_text=True)
  4883. self.assertIn(
  4884. 'You are no longer'
  4885. ' watching this project', output_text)
  4886. output = self.app.get(
  4887. '/test', data=data,
  4888. follow_redirects=True)
  4889. output_text = output.get_data(as_text=True)
  4890. self.assertIn(
  4891. ('<span class="btn btn-sm btn-primary font-weight-bold">1'
  4892. '</span>\n '
  4893. '<div class="dropdown-menu dropdown-menu-right watch-menu">'),
  4894. output_text)
  4895. output = self.app.post(
  4896. '/fork/foo/test/watch/settings/1', data=data,
  4897. follow_redirects=True)
  4898. output_text = output.get_data(as_text=True)
  4899. self.assertIn(
  4900. 'You are now'
  4901. ' watching issues and PRs on this project', output_text)
  4902. output = self.app.get(
  4903. '/test', data=data,
  4904. follow_redirects=True)
  4905. output_text = output.get_data(as_text=True)
  4906. self.assertIn(
  4907. ('<span class="btn btn-sm btn-primary font-weight-bold">1'
  4908. '</span>\n '
  4909. '<div class="dropdown-menu dropdown-menu-right watch-menu">'),
  4910. output_text)
  4911. output = self.app.post(
  4912. '/fork/foo/test/watch/settings/2', data=data,
  4913. follow_redirects=True)
  4914. output_text = output.get_data(as_text=True)
  4915. self.assertIn(
  4916. 'You are now'
  4917. ' watching commits on this project', output_text)
  4918. output = self.app.post(
  4919. '/fork/foo/test/watch/settings/3', data=data,
  4920. follow_redirects=True)
  4921. output_text = output.get_data(as_text=True)
  4922. self.assertIn(
  4923. ('You are now'
  4924. ' watching issues, PRs, and commits on this project'),
  4925. output_text)
  4926. output = self.app.get(
  4927. '/test', data=data,
  4928. follow_redirects=True)
  4929. output_text = output.get_data(as_text=True)
  4930. self.assertIn(
  4931. ('<span class="btn btn-sm btn-primary font-weight-bold">1'
  4932. '</span>\n '
  4933. '<div class="dropdown-menu dropdown-menu-right watch-menu">'),
  4934. output_text)
  4935. project = pagure.lib.query._get_project(self.session, 'test')
  4936. pagure.lib.query.add_user_to_project(
  4937. self.session, project,
  4938. new_user='foo',
  4939. user='pingou',
  4940. access='commit'
  4941. )
  4942. self.session.commit()
  4943. output = self.app.get(
  4944. '/test', data=data,
  4945. follow_redirects=True)
  4946. output_text = output.get_data(as_text=True)
  4947. self.assertIn(
  4948. ('<span class="btn btn-sm btn-primary font-weight-bold">2'
  4949. '</span>\n '
  4950. '<div class="dropdown-menu dropdown-menu-right watch-menu">'),
  4951. output_text)
  4952. output = self.app.post(
  4953. '/fork/foo/test/watch/settings/-1', data=data,
  4954. follow_redirects=True)
  4955. output_text = output.get_data(as_text=True)
  4956. self.assertIn(
  4957. 'Watch status reset',
  4958. output_text)
  4959. output = self.app.get(
  4960. '/test', data=data,
  4961. follow_redirects=True)
  4962. output_text = output.get_data(as_text=True)
  4963. self.assertIn(
  4964. ('<span class="btn btn-sm btn-primary font-weight-bold">2'
  4965. '</span>\n '
  4966. '<div class="dropdown-menu dropdown-menu-right watch-menu">'),
  4967. output_text)
  4968. def test_delete_report(self):
  4969. """ Test the delete_report endpoint. """
  4970. output = self.app.post('/test/delete/report')
  4971. self.assertEqual(output.status_code, 404)
  4972. tests.create_projects(self.session)
  4973. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  4974. user = tests.FakeUser()
  4975. user.username = 'pingou'
  4976. with tests.user_set(self.app.application, user):
  4977. output = self.app.get('/new/')
  4978. self.assertEqual(output.status_code, 200)
  4979. output_text = output.get_data(as_text=True)
  4980. self.assertIn('<strong>Create new Project</strong>', output_text)
  4981. csrf_token = output_text.split(
  4982. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  4983. # No report specified
  4984. data = {
  4985. 'csrf_token':csrf_token
  4986. }
  4987. output = self.app.post(
  4988. '/test/delete/report', data=data, follow_redirects=True)
  4989. self.assertEqual(output.status_code, 200)
  4990. output_text = output.get_data(as_text=True)
  4991. self.assertIn(
  4992. 'Unknown report: None',
  4993. output_text)
  4994. # Report specified not in the project's reports
  4995. data = {
  4996. 'csrf_token':csrf_token,
  4997. 'report': 'foo'
  4998. }
  4999. output = self.app.post(
  5000. '/test/delete/report', data=data, follow_redirects=True)
  5001. self.assertEqual(output.status_code, 200)
  5002. output_text = output.get_data(as_text=True)
  5003. self.assertIn(
  5004. 'Unknown report: foo',
  5005. output_text)
  5006. # Create a report
  5007. project = pagure.lib.query.get_authorized_project(self.session, project_name='test')
  5008. self.assertEqual(project.reports, {})
  5009. name = 'test report'
  5010. url = '?foo=bar&baz=biz'
  5011. pagure.lib.query.save_report(
  5012. self.session,
  5013. repo=project,
  5014. name=name,
  5015. url=url,
  5016. username=None
  5017. )
  5018. self.session.commit()
  5019. project = pagure.lib.query.get_authorized_project(self.session, project_name='test')
  5020. self.assertEqual(
  5021. project.reports,
  5022. {'test report': {'baz': 'biz', 'foo': 'bar'}}
  5023. )
  5024. # Missing CSRF
  5025. data = {
  5026. 'report': 'test report'
  5027. }
  5028. output = self.app.post(
  5029. '/test/delete/report', data=data, follow_redirects=True)
  5030. self.assertEqual(output.status_code, 200)
  5031. output_text = output.get_data(as_text=True)
  5032. self.assertIn(
  5033. '<title>Settings - test - Pagure</title>',
  5034. output_text)
  5035. project = pagure.lib.query.get_authorized_project(self.session, project_name='test')
  5036. self.assertEqual(
  5037. project.reports,
  5038. {'test report': {'baz': 'biz', 'foo': 'bar'}}
  5039. )
  5040. # Delete the report
  5041. data = {
  5042. 'csrf_token':csrf_token,
  5043. 'report': 'test report'
  5044. }
  5045. output = self.app.post(
  5046. '/test/delete/report', data=data, follow_redirects=True)
  5047. self.assertEqual(output.status_code, 200)
  5048. output_text = output.get_data(as_text=True)
  5049. self.assertIn(
  5050. 'List of reports updated',
  5051. output_text)
  5052. self.session.commit()
  5053. project = pagure.lib.query.get_authorized_project(self.session, project_name='test')
  5054. self.assertEqual(project.reports, {})
  5055. def test_delete_report_ns_project(self):
  5056. """ Test the delete_report endpoint on a namespaced project. """
  5057. output = self.app.post('/foo/test/delete/report')
  5058. self.assertEqual(output.status_code, 404)
  5059. tests.create_projects(self.session)
  5060. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  5061. user = tests.FakeUser()
  5062. user.username = 'pingou'
  5063. with tests.user_set(self.app.application, user):
  5064. output = self.app.get('/new/')
  5065. self.assertEqual(output.status_code, 200)
  5066. output_text = output.get_data(as_text=True)
  5067. self.assertIn('<strong>Create new Project</strong>', output_text)
  5068. csrf_token = output_text.split(
  5069. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  5070. item = pagure.lib.model.Project(
  5071. user_id=1, # pingou
  5072. namespace='foo',
  5073. name='test',
  5074. description='foo project #2',
  5075. hook_token='aaabbb',
  5076. )
  5077. self.session.add(item)
  5078. self.session.commit()
  5079. gitrepo = os.path.join(self.path, 'repos', 'foo', 'test.git')
  5080. pygit2.init_repository(gitrepo, bare=True)
  5081. # No report specified
  5082. data = {
  5083. 'csrf_token':csrf_token
  5084. }
  5085. output = self.app.post(
  5086. '/foo/test/delete/report', data=data, follow_redirects=True)
  5087. self.assertEqual(output.status_code, 200)
  5088. output_text = output.get_data(as_text=True)
  5089. self.assertIn(
  5090. 'Unknown report: None',
  5091. output_text)
  5092. # Report specified not in the project's reports
  5093. data = {
  5094. 'csrf_token':csrf_token,
  5095. 'report': 'foo'
  5096. }
  5097. output = self.app.post(
  5098. '/foo/test/delete/report', data=data, follow_redirects=True)
  5099. self.assertEqual(output.status_code, 200)
  5100. output_text = output.get_data(as_text=True)
  5101. self.assertIn(
  5102. 'Unknown report: foo',
  5103. output_text)
  5104. # Create a report
  5105. self.session.commit()
  5106. project = pagure.lib.query.get_authorized_project(
  5107. self.session, project_name='test', namespace='foo')
  5108. self.assertEqual(project.reports, {})
  5109. name = 'test report'
  5110. url = '?foo=bar&baz=biz'
  5111. pagure.lib.query.save_report(
  5112. self.session,
  5113. repo=project,
  5114. name=name,
  5115. url=url,
  5116. username=None
  5117. )
  5118. self.session.commit()
  5119. project = pagure.lib.query.get_authorized_project(
  5120. self.session, project_name='test', namespace='foo')
  5121. self.assertEqual(
  5122. project.reports,
  5123. {'test report': {'baz': 'biz', 'foo': 'bar'}}
  5124. )
  5125. # Missing CSRF
  5126. data = {
  5127. 'report': 'test report'
  5128. }
  5129. output = self.app.post(
  5130. '/foo/test/delete/report', data=data, follow_redirects=True)
  5131. self.assertEqual(output.status_code, 200)
  5132. output_text = output.get_data(as_text=True)
  5133. self.assertIn(
  5134. '<title>Settings - foo/test - Pagure</title>',
  5135. output_text)
  5136. project = pagure.lib.query.get_authorized_project(
  5137. self.session, project_name='test', namespace='foo')
  5138. self.assertEqual(
  5139. project.reports,
  5140. {'test report': {'baz': 'biz', 'foo': 'bar'}}
  5141. )
  5142. # Delete the report
  5143. data = {
  5144. 'csrf_token':csrf_token,
  5145. 'report': 'test report'
  5146. }
  5147. output = self.app.post(
  5148. '/foo/test/delete/report', data=data, follow_redirects=True)
  5149. self.assertEqual(output.status_code, 200)
  5150. output_text = output.get_data(as_text=True)
  5151. self.assertIn(
  5152. 'List of reports updated',
  5153. output_text)
  5154. self.session.commit()
  5155. project = pagure.lib.query.get_authorized_project(
  5156. self.session, project_name='test', namespace='foo')
  5157. self.assertEqual(project.reports, {})
  5158. def test_open_pr_button_empty_repo(self):
  5159. """ Test "Open Pull-Request" button on empty project. """
  5160. tests.create_projects(self.session)
  5161. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  5162. output = self.app.get('/test')
  5163. self.assertEqual(output.status_code, 200)
  5164. output_text = output.get_data(as_text=True)
  5165. self.assertIn('<p>This repo is brand new!</p>', output_text)
  5166. self.assertNotIn(
  5167. 'href="/test/diff/master..master">Open Pull-Request',
  5168. output_text)
  5169. @patch.dict(
  5170. 'pagure.config.config',
  5171. {'UPLOAD_FOLDER_PATH': None, 'UPLOAD_FOLDER_URL': None})
  5172. def test_releases_upload_folder_vars_None(self):
  5173. """ Test that /releases/ page of a repo displays correctly with
  5174. UPLOAD_FOLDER_PATH and UPLOAD_FOLDER_URL set to None
  5175. """
  5176. tests.create_projects(self.session)
  5177. tests.create_projects_git(os.path.join(self.path, 'repos'), bare=True)
  5178. output = self.app.get('/test/releases')
  5179. self.assertEqual(output.status_code, 200)
  5180. self.assertIn(
  5181. 'This project has not been tagged.',
  5182. output.get_data(as_text=True)
  5183. )
  5184. if __name__ == '__main__':
  5185. unittest.main(verbosity=2)