test_pagure_flask_api_project.py 164 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516
  1. # -*- coding: utf-8 -*-
  2. """
  3. (c) 2015-2018 - Copyright Red Hat Inc
  4. Authors:
  5. Pierre-Yves Chibon <pingou@pingoured.fr>
  6. Karsten Hopp <karsten@redhat.com>
  7. """
  8. from __future__ import unicode_literals, absolute_import
  9. import datetime
  10. import json
  11. import unittest
  12. import shutil
  13. import sys
  14. import tempfile
  15. import os
  16. import pygit2
  17. from celery.result import EagerResult
  18. from mock import patch, Mock
  19. sys.path.insert(
  20. 0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")
  21. )
  22. import pagure.flask_app
  23. import pagure.lib.query
  24. import tests
  25. from pagure.lib.repo import PagureRepo
  26. class PagureFlaskApiProjecttests(tests.Modeltests):
  27. """ Tests for the flask API of pagure for issue """
  28. def setUp(self):
  29. super(PagureFlaskApiProjecttests, self).setUp()
  30. self.gga_patcher = patch(
  31. "pagure.lib.tasks.generate_gitolite_acls.delay"
  32. )
  33. self.mock_gen_acls = self.gga_patcher.start()
  34. task_result = EagerResult("abc-1234", True, "SUCCESS")
  35. self.mock_gen_acls.return_value = task_result
  36. def tearDown(self):
  37. self.gga_patcher.stop()
  38. super(PagureFlaskApiProjecttests, self).tearDown()
  39. def test_api_git_tags(self):
  40. """ Test the api_git_tags method of the flask api. """
  41. tests.create_projects(self.session)
  42. # Create a git repo to play with
  43. gitrepo = os.path.join(self.path, "repos", "test.git")
  44. repo = pygit2.init_repository(gitrepo, bare=True)
  45. newpath = tempfile.mkdtemp(prefix="pagure-fork-test")
  46. repopath = os.path.join(newpath, "test")
  47. clone_repo = pygit2.clone_repository(gitrepo, repopath)
  48. # Create a file in that git repo
  49. with open(os.path.join(repopath, "sources"), "w") as stream:
  50. stream.write("foo\n bar")
  51. clone_repo.index.add("sources")
  52. clone_repo.index.write()
  53. # Commits the files added
  54. tree = clone_repo.index.write_tree()
  55. author = pygit2.Signature("Alice Author", "alice@authors.tld")
  56. committer = pygit2.Signature("Cecil Committer", "cecil@committers.tld")
  57. clone_repo.create_commit(
  58. "refs/heads/master", # the name of the reference to update
  59. author,
  60. committer,
  61. "Add sources file for testing",
  62. # binary string representing the tree object ID
  63. tree,
  64. # list of binary strings representing parents of the new commit
  65. [],
  66. )
  67. refname = "refs/heads/master:refs/heads/master"
  68. ori_remote = clone_repo.remotes[0]
  69. PagureRepo.push(ori_remote, refname)
  70. # Tag our first commit
  71. first_commit = repo.revparse_single("HEAD")
  72. tagger = pygit2.Signature("Alice Doe", "adoe@example.com", 12347, 0)
  73. repo.create_tag(
  74. "0.0.1",
  75. first_commit.oid.hex,
  76. pygit2.GIT_OBJ_COMMIT,
  77. tagger,
  78. "Release 0.0.1",
  79. )
  80. # Check tags
  81. output = self.app.get("/api/0/test/git/tags")
  82. self.assertEqual(output.status_code, 200)
  83. data = json.loads(output.get_data(as_text=True))
  84. self.assertDictEqual(data, {"tags": ["0.0.1"], "total_tags": 1})
  85. # Check tags with commits
  86. output = self.app.get("/api/0/test/git/tags?with_commits=True")
  87. self.assertEqual(output.status_code, 200)
  88. data = json.loads(output.get_data(as_text=True))
  89. data["tags"]["0.0.1"] = "bb8fa2aa199da08d6085e1c9badc3d83d188d38c"
  90. self.assertDictEqual(
  91. data,
  92. {
  93. "tags": {"0.0.1": "bb8fa2aa199da08d6085e1c9badc3d83d188d38c"},
  94. "total_tags": 1,
  95. },
  96. )
  97. shutil.rmtree(newpath)
  98. def test_api_git_branches(self):
  99. """ Test the api_git_branches method of the flask api. """
  100. # Create a git repo to add branches to
  101. tests.create_projects(self.session)
  102. repo_path = os.path.join(self.path, "repos", "test.git")
  103. tests.add_content_git_repo(repo_path)
  104. new_repo_path = tempfile.mkdtemp(prefix="pagure-api-git-branches-test")
  105. clone_repo = pygit2.clone_repository(repo_path, new_repo_path)
  106. # Create two other branches based on master
  107. for branch in ["pats-win-49", "pats-win-51"]:
  108. clone_repo.create_branch(branch, clone_repo.head.peel())
  109. refname = "refs/heads/{0}:refs/heads/{0}".format(branch)
  110. PagureRepo.push(clone_repo.remotes[0], refname)
  111. # Check that the branches show up on the API
  112. output = self.app.get("/api/0/test/git/branches")
  113. # Delete the cloned git repo after the API call
  114. shutil.rmtree(new_repo_path)
  115. # Verify the API data
  116. self.assertEqual(output.status_code, 200)
  117. data = json.loads(output.get_data(as_text=True))
  118. self.assertDictEqual(
  119. data,
  120. {
  121. "branches": ["master", "pats-win-49", "pats-win-51"],
  122. "total_branches": 3,
  123. },
  124. )
  125. def test_api_git_branches_with_commits(self):
  126. """ Test the api_git_branches method of the flask api with with_commits=True. """
  127. # Create a git repo to add branches to
  128. tests.create_projects(self.session)
  129. repo_path = os.path.join(self.path, "repos", "test.git")
  130. tests.add_content_git_repo(repo_path)
  131. new_repo_path = tempfile.mkdtemp(prefix="pagure-api-git-branches-test")
  132. clone_repo = pygit2.clone_repository(repo_path, new_repo_path)
  133. # Create two other branches based on master
  134. for branch in ["pats-win-49", "pats-win-51"]:
  135. clone_repo.create_branch(branch, clone_repo.head.peel())
  136. refname = "refs/heads/{0}:refs/heads/{0}".format(branch)
  137. PagureRepo.push(clone_repo.remotes[0], refname)
  138. # Check that the branches show up on the API
  139. output = self.app.get("/api/0/test/git/branches?with_commits=true")
  140. # Delete the cloned git repo after the API call
  141. shutil.rmtree(new_repo_path)
  142. # Get the commit hex
  143. repo_obj = pygit2.Repository(
  144. os.path.join(self.path, "repos", "test.git")
  145. )
  146. commit = repo_obj[repo_obj.head.target]
  147. # Verify the API data
  148. self.assertEqual(output.status_code, 200)
  149. data = json.loads(output.get_data(as_text=True))
  150. self.assertDictEqual(
  151. data,
  152. {
  153. "branches": {
  154. "master": commit.hex,
  155. "pats-win-49": commit.hex,
  156. "pats-win-51": commit.hex,
  157. },
  158. "total_branches": 3,
  159. },
  160. )
  161. def test_api_git_branches_empty_repo(self):
  162. """ Test the api_git_branches method of the flask api when the repo is
  163. empty.
  164. """
  165. # Create a git repo without any branches
  166. tests.create_projects(self.session)
  167. repo_base_path = os.path.join(self.path, "repos")
  168. tests.create_projects_git(repo_base_path)
  169. # Check that no branches show up on the API
  170. output = self.app.get("/api/0/test/git/branches")
  171. self.assertEqual(output.status_code, 200)
  172. data = json.loads(output.get_data(as_text=True))
  173. self.assertDictEqual(data, {"branches": [], "total_branches": 0})
  174. def test_api_git_branches_no_repo(self):
  175. """ Test the api_git_branches method of the flask api when there is no
  176. repo on a project.
  177. """
  178. tests.create_projects(self.session)
  179. output = self.app.get("/api/0/test/git/branches")
  180. self.assertEqual(output.status_code, 404)
  181. def test_api_git_urls(self):
  182. """ Test the api_project_git_urls method of the flask api.
  183. """
  184. tests.create_projects(self.session)
  185. output = self.app.get("/api/0/test/git/urls")
  186. self.assertEqual(output.status_code, 200)
  187. expected_rv = {
  188. "urls": {
  189. "git": "git://localhost.localdomain/test.git",
  190. "ssh": "ssh://git@localhost.localdomain/test.git",
  191. },
  192. "total_urls": 2,
  193. }
  194. data = json.loads(output.get_data(as_text=True))
  195. self.assertDictEqual(data, expected_rv)
  196. def test_api_git_urls_no_project(self):
  197. """ Test the api_project_git_urls method of the flask api when there is
  198. no project.
  199. """
  200. output = self.app.get("/api/0/test1234/git/urls")
  201. self.assertEqual(output.status_code, 404)
  202. expected_rv = {
  203. "error": "Project not found",
  204. "error_code": "ENOPROJECT",
  205. }
  206. data = json.loads(output.get_data(as_text=True))
  207. self.assertDictEqual(data, expected_rv)
  208. @patch.dict("pagure.config.config", {"PRIVATE_PROJECTS": True})
  209. def test_api_git_urls_private_project(self):
  210. """ Test the api_project_git_urls method of the flask api when the
  211. project is private.
  212. """
  213. tests.create_projects(self.session)
  214. tests.create_tokens(self.session)
  215. tests.create_tokens_acl(self.session, "aaabbbcccddd")
  216. headers = {"Authorization": "token aaabbbcccddd"}
  217. test_project = pagure.lib.query._get_project(self.session, "test")
  218. test_project.private = True
  219. self.session.add(test_project)
  220. self.session.commit()
  221. output = self.app.get("/api/0/test/git/urls", headers=headers)
  222. self.assertEqual(output.status_code, 200)
  223. expected_rv = {
  224. "urls": {
  225. "git": "git://localhost.localdomain/test.git",
  226. "ssh": "ssh://git@localhost.localdomain/test.git",
  227. },
  228. "total_urls": 2,
  229. }
  230. data = json.loads(output.get_data(as_text=True))
  231. self.assertDictEqual(data, expected_rv)
  232. @patch.dict("pagure.config.config", {"PRIVATE_PROJECTS": True})
  233. def test_api_git_urls_private_project_no_login(self):
  234. """ Test the api_project_git_urls method of the flask api when the
  235. project is private and the user is not logged in.
  236. """
  237. tests.create_projects(self.session)
  238. test_project = pagure.lib.query._get_project(self.session, "test")
  239. test_project.private = True
  240. self.session.add(test_project)
  241. self.session.commit()
  242. output = self.app.get("/api/0/test/git/urls")
  243. self.assertEqual(output.status_code, 404)
  244. expected_rv = {
  245. "error": "Project not found",
  246. "error_code": "ENOPROJECT",
  247. }
  248. data = json.loads(output.get_data(as_text=True))
  249. self.assertDictEqual(data, expected_rv)
  250. def test_api_projects_pattern(self):
  251. """ Test the api_projects method of the flask api. """
  252. tests.create_projects(self.session)
  253. output = self.app.get("/api/0/projects?pattern=test")
  254. self.assertEqual(output.status_code, 200)
  255. data = json.loads(output.get_data(as_text=True))
  256. data["projects"][0]["date_created"] = "1436527638"
  257. data["projects"][0]["date_modified"] = "1436527638"
  258. del data["pagination"]
  259. expected_data = {
  260. "args": {
  261. "fork": None,
  262. "namespace": None,
  263. "owner": None,
  264. "page": 1,
  265. "pattern": "test",
  266. "per_page": 20,
  267. "short": False,
  268. "tags": [],
  269. "username": None,
  270. },
  271. "projects": [
  272. {
  273. "access_groups": {"admin": [], "commit": [], "ticket": []},
  274. "access_users": {
  275. "admin": [],
  276. "commit": [],
  277. "owner": ["pingou"],
  278. "ticket": [],
  279. },
  280. "close_status": [
  281. "Invalid",
  282. "Insufficient data",
  283. "Fixed",
  284. "Duplicate",
  285. ],
  286. "custom_keys": [],
  287. "date_created": "1436527638",
  288. "date_modified": "1436527638",
  289. "description": "test project #1",
  290. "fullname": "test",
  291. "url_path": "test",
  292. "id": 1,
  293. "milestones": {},
  294. "name": "test",
  295. "namespace": None,
  296. "parent": None,
  297. "priorities": {},
  298. "tags": [],
  299. "user": {
  300. "fullname": "PY C",
  301. "name": "pingou",
  302. "url_path": "user/pingou",
  303. },
  304. }
  305. ],
  306. "total_projects": 1,
  307. }
  308. self.assertDictEqual(data, expected_data)
  309. def test_api_projects_pattern_short(self):
  310. """ Test the api_projects method of the flask api. """
  311. tests.create_projects(self.session)
  312. output = self.app.get("/api/0/projects?pattern=te*&short=1")
  313. self.assertEqual(output.status_code, 200)
  314. data = json.loads(output.get_data(as_text=True))
  315. del data["pagination"]
  316. expected_data = {
  317. "args": {
  318. "fork": None,
  319. "namespace": None,
  320. "owner": None,
  321. "page": 1,
  322. "pattern": "te*",
  323. "per_page": 20,
  324. "short": True,
  325. "tags": [],
  326. "username": None,
  327. },
  328. "projects": [
  329. {
  330. "description": "test project #1",
  331. "fullname": "test",
  332. "name": "test",
  333. "namespace": None,
  334. },
  335. {
  336. "description": "test project #2",
  337. "fullname": "test2",
  338. "name": "test2",
  339. "namespace": None,
  340. },
  341. {
  342. "description": "namespaced test project",
  343. "fullname": "somenamespace/test3",
  344. "name": "test3",
  345. "namespace": "somenamespace",
  346. },
  347. ],
  348. "total_projects": 3,
  349. }
  350. self.maxDiff = None
  351. self.assertDictEqual(data, expected_data)
  352. def test_api_projects_owner(self):
  353. """ Test the api_projects method of the flask api. """
  354. tests.create_projects(self.session)
  355. output = self.app.get("/api/0/projects?owner=foo")
  356. self.assertEqual(output.status_code, 200)
  357. data = json.loads(output.get_data(as_text=True))
  358. del data["pagination"]
  359. expected_data = {
  360. "args": {
  361. "fork": None,
  362. "namespace": None,
  363. "owner": "foo",
  364. "page": 1,
  365. "pattern": None,
  366. "per_page": 20,
  367. "short": False,
  368. "tags": [],
  369. "username": None,
  370. },
  371. "projects": [],
  372. "total_projects": 0,
  373. }
  374. self.maxDiff = None
  375. self.assertDictEqual(data, expected_data)
  376. def test_api_projects_not_owner(self):
  377. """ Test the api_projects method of the flask api. """
  378. tests.create_projects(self.session)
  379. output = self.app.get("/api/0/projects?owner=!foo&short=1")
  380. self.assertEqual(output.status_code, 200)
  381. data = json.loads(output.get_data(as_text=True))
  382. del data["pagination"]
  383. expected_data = {
  384. "args": {
  385. "fork": None,
  386. "namespace": None,
  387. "owner": "!foo",
  388. "page": 1,
  389. "pattern": None,
  390. "per_page": 20,
  391. "short": True,
  392. "tags": [],
  393. "username": None,
  394. },
  395. "projects": [
  396. {
  397. "description": "test project #1",
  398. "fullname": "test",
  399. "name": "test",
  400. "namespace": None,
  401. },
  402. {
  403. "description": "test project #2",
  404. "fullname": "test2",
  405. "name": "test2",
  406. "namespace": None,
  407. },
  408. {
  409. "description": "namespaced test project",
  410. "fullname": "somenamespace/test3",
  411. "name": "test3",
  412. "namespace": "somenamespace",
  413. },
  414. ],
  415. "total_projects": 3,
  416. }
  417. self.maxDiff = None
  418. self.assertDictEqual(data, expected_data)
  419. def test_api_projects(self):
  420. """ Test the api_projects method of the flask api. """
  421. tests.create_projects(self.session)
  422. # Check before adding
  423. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  424. self.assertEqual(repo.tags, [])
  425. # Adding a tag
  426. output = pagure.lib.query.update_tags(
  427. self.session, repo, "infra", "pingou"
  428. )
  429. self.assertEqual(output, ["Project tagged with: infra"])
  430. # Check after adding
  431. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  432. self.assertEqual(len(repo.tags), 1)
  433. self.assertEqual(repo.tags_text, ["infra"])
  434. # Check the API
  435. output = self.app.get("/api/0/projects?tags=inf")
  436. self.assertEqual(output.status_code, 200)
  437. data = json.loads(output.get_data(as_text=True))
  438. null = None
  439. del data["pagination"]
  440. self.assertDictEqual(
  441. data,
  442. {
  443. "total_projects": 0,
  444. "projects": [],
  445. "args": {
  446. "fork": None,
  447. "namespace": None,
  448. "owner": None,
  449. "page": 1,
  450. "pattern": None,
  451. "per_page": 20,
  452. "short": False,
  453. "tags": ["inf"],
  454. "username": None,
  455. },
  456. },
  457. )
  458. output = self.app.get("/api/0/projects?tags=infra")
  459. self.assertEqual(output.status_code, 200)
  460. data = json.loads(output.get_data(as_text=True))
  461. data["projects"][0]["date_created"] = "1436527638"
  462. data["projects"][0]["date_modified"] = "1436527638"
  463. del data["pagination"]
  464. expected_data = {
  465. "args": {
  466. "fork": None,
  467. "namespace": None,
  468. "owner": None,
  469. "page": 1,
  470. "pattern": None,
  471. "per_page": 20,
  472. "short": False,
  473. "tags": ["infra"],
  474. "username": None,
  475. },
  476. "projects": [
  477. {
  478. "access_groups": {"admin": [], "commit": [], "ticket": []},
  479. "access_users": {
  480. "admin": [],
  481. "commit": [],
  482. "owner": ["pingou"],
  483. "ticket": [],
  484. },
  485. "close_status": [
  486. "Invalid",
  487. "Insufficient data",
  488. "Fixed",
  489. "Duplicate",
  490. ],
  491. "custom_keys": [],
  492. "date_created": "1436527638",
  493. "date_modified": "1436527638",
  494. "description": "test project #1",
  495. "fullname": "test",
  496. "url_path": "test",
  497. "id": 1,
  498. "milestones": {},
  499. "name": "test",
  500. "namespace": None,
  501. "parent": None,
  502. "priorities": {},
  503. "tags": ["infra"],
  504. "user": {
  505. "fullname": "PY C",
  506. "name": "pingou",
  507. "url_path": "user/pingou",
  508. },
  509. }
  510. ],
  511. "total_projects": 1,
  512. }
  513. self.assertDictEqual(data, expected_data)
  514. output = self.app.get("/api/0/projects?owner=pingou")
  515. self.assertEqual(output.status_code, 200)
  516. data = json.loads(output.get_data(as_text=True))
  517. data["projects"][0]["date_created"] = "1436527638"
  518. data["projects"][0]["date_modified"] = "1436527638"
  519. data["projects"][1]["date_created"] = "1436527638"
  520. data["projects"][1]["date_modified"] = "1436527638"
  521. data["projects"][2]["date_created"] = "1436527638"
  522. data["projects"][2]["date_modified"] = "1436527638"
  523. del data["pagination"]
  524. expected_data = {
  525. "args": {
  526. "fork": None,
  527. "namespace": None,
  528. "owner": "pingou",
  529. "page": 1,
  530. "pattern": None,
  531. "per_page": 20,
  532. "short": False,
  533. "tags": [],
  534. "username": None,
  535. },
  536. "projects": [
  537. {
  538. "access_groups": {"admin": [], "commit": [], "ticket": []},
  539. "access_users": {
  540. "admin": [],
  541. "commit": [],
  542. "owner": ["pingou"],
  543. "ticket": [],
  544. },
  545. "close_status": [
  546. "Invalid",
  547. "Insufficient data",
  548. "Fixed",
  549. "Duplicate",
  550. ],
  551. "custom_keys": [],
  552. "date_created": "1436527638",
  553. "date_modified": "1436527638",
  554. "description": "test project #1",
  555. "fullname": "test",
  556. "url_path": "test",
  557. "id": 1,
  558. "milestones": {},
  559. "name": "test",
  560. "namespace": None,
  561. "parent": None,
  562. "priorities": {},
  563. "tags": ["infra"],
  564. "user": {
  565. "fullname": "PY C",
  566. "name": "pingou",
  567. "url_path": "user/pingou",
  568. },
  569. },
  570. {
  571. "access_groups": {"admin": [], "commit": [], "ticket": []},
  572. "access_users": {
  573. "admin": [],
  574. "commit": [],
  575. "owner": ["pingou"],
  576. "ticket": [],
  577. },
  578. "close_status": [
  579. "Invalid",
  580. "Insufficient data",
  581. "Fixed",
  582. "Duplicate",
  583. ],
  584. "custom_keys": [],
  585. "date_created": "1436527638",
  586. "date_modified": "1436527638",
  587. "description": "test project #2",
  588. "fullname": "test2",
  589. "url_path": "test2",
  590. "id": 2,
  591. "milestones": {},
  592. "name": "test2",
  593. "namespace": None,
  594. "parent": None,
  595. "priorities": {},
  596. "tags": [],
  597. "user": {
  598. "fullname": "PY C",
  599. "name": "pingou",
  600. "url_path": "user/pingou",
  601. },
  602. },
  603. {
  604. "access_groups": {"admin": [], "commit": [], "ticket": []},
  605. "access_users": {
  606. "admin": [],
  607. "commit": [],
  608. "owner": ["pingou"],
  609. "ticket": [],
  610. },
  611. "close_status": [
  612. "Invalid",
  613. "Insufficient data",
  614. "Fixed",
  615. "Duplicate",
  616. ],
  617. "custom_keys": [],
  618. "date_created": "1436527638",
  619. "date_modified": "1436527638",
  620. "description": "namespaced test project",
  621. "fullname": "somenamespace/test3",
  622. "url_path": "somenamespace/test3",
  623. "id": 3,
  624. "milestones": {},
  625. "name": "test3",
  626. "namespace": "somenamespace",
  627. "parent": None,
  628. "priorities": {},
  629. "tags": [],
  630. "user": {
  631. "fullname": "PY C",
  632. "name": "pingou",
  633. "url_path": "user/pingou",
  634. },
  635. },
  636. ],
  637. "total_projects": 3,
  638. }
  639. self.assertDictEqual(data, expected_data)
  640. output = self.app.get("/api/0/projects?username=pingou")
  641. self.assertEqual(output.status_code, 200)
  642. data = json.loads(output.get_data(as_text=True))
  643. data["projects"][0]["date_created"] = "1436527638"
  644. data["projects"][0]["date_modified"] = "1436527638"
  645. data["projects"][1]["date_created"] = "1436527638"
  646. data["projects"][1]["date_modified"] = "1436527638"
  647. data["projects"][2]["date_created"] = "1436527638"
  648. data["projects"][2]["date_modified"] = "1436527638"
  649. del data["pagination"]
  650. expected_data = {
  651. "args": {
  652. "fork": None,
  653. "namespace": None,
  654. "owner": None,
  655. "page": 1,
  656. "pattern": None,
  657. "per_page": 20,
  658. "short": False,
  659. "tags": [],
  660. "username": "pingou",
  661. },
  662. "projects": [
  663. {
  664. "access_groups": {"admin": [], "commit": [], "ticket": []},
  665. "access_users": {
  666. "admin": [],
  667. "commit": [],
  668. "owner": ["pingou"],
  669. "ticket": [],
  670. },
  671. "close_status": [
  672. "Invalid",
  673. "Insufficient data",
  674. "Fixed",
  675. "Duplicate",
  676. ],
  677. "custom_keys": [],
  678. "date_created": "1436527638",
  679. "date_modified": "1436527638",
  680. "description": "test project #1",
  681. "fullname": "test",
  682. "url_path": "test",
  683. "id": 1,
  684. "milestones": {},
  685. "name": "test",
  686. "namespace": None,
  687. "parent": None,
  688. "priorities": {},
  689. "tags": ["infra"],
  690. "user": {
  691. "fullname": "PY C",
  692. "name": "pingou",
  693. "url_path": "user/pingou",
  694. },
  695. },
  696. {
  697. "access_groups": {"admin": [], "commit": [], "ticket": []},
  698. "access_users": {
  699. "admin": [],
  700. "commit": [],
  701. "owner": ["pingou"],
  702. "ticket": [],
  703. },
  704. "close_status": [
  705. "Invalid",
  706. "Insufficient data",
  707. "Fixed",
  708. "Duplicate",
  709. ],
  710. "custom_keys": [],
  711. "date_created": "1436527638",
  712. "date_modified": "1436527638",
  713. "description": "test project #2",
  714. "fullname": "test2",
  715. "url_path": "test2",
  716. "id": 2,
  717. "milestones": {},
  718. "name": "test2",
  719. "namespace": None,
  720. "parent": None,
  721. "priorities": {},
  722. "tags": [],
  723. "user": {
  724. "fullname": "PY C",
  725. "name": "pingou",
  726. "url_path": "user/pingou",
  727. },
  728. },
  729. {
  730. "access_groups": {"admin": [], "commit": [], "ticket": []},
  731. "access_users": {
  732. "admin": [],
  733. "commit": [],
  734. "owner": ["pingou"],
  735. "ticket": [],
  736. },
  737. "close_status": [
  738. "Invalid",
  739. "Insufficient data",
  740. "Fixed",
  741. "Duplicate",
  742. ],
  743. "custom_keys": [],
  744. "date_created": "1436527638",
  745. "date_modified": "1436527638",
  746. "description": "namespaced test project",
  747. "fullname": "somenamespace/test3",
  748. "url_path": "somenamespace/test3",
  749. "id": 3,
  750. "milestones": {},
  751. "name": "test3",
  752. "namespace": "somenamespace",
  753. "parent": None,
  754. "priorities": {},
  755. "tags": [],
  756. "user": {
  757. "fullname": "PY C",
  758. "name": "pingou",
  759. "url_path": "user/pingou",
  760. },
  761. },
  762. ],
  763. "total_projects": 3,
  764. }
  765. self.assertDictEqual(data, expected_data)
  766. output = self.app.get("/api/0/projects?username=pingou&tags=infra")
  767. self.assertEqual(output.status_code, 200)
  768. data = json.loads(output.get_data(as_text=True))
  769. data["projects"][0]["date_created"] = "1436527638"
  770. data["projects"][0]["date_modified"] = "1436527638"
  771. del data["pagination"]
  772. expected_data = {
  773. "args": {
  774. "fork": None,
  775. "namespace": None,
  776. "owner": None,
  777. "page": 1,
  778. "pattern": None,
  779. "per_page": 20,
  780. "short": False,
  781. "tags": ["infra"],
  782. "username": "pingou",
  783. },
  784. "projects": [
  785. {
  786. "access_groups": {"admin": [], "commit": [], "ticket": []},
  787. "access_users": {
  788. "admin": [],
  789. "commit": [],
  790. "owner": ["pingou"],
  791. "ticket": [],
  792. },
  793. "close_status": [
  794. "Invalid",
  795. "Insufficient data",
  796. "Fixed",
  797. "Duplicate",
  798. ],
  799. "custom_keys": [],
  800. "date_created": "1436527638",
  801. "date_modified": "1436527638",
  802. "description": "test project #1",
  803. "fullname": "test",
  804. "url_path": "test",
  805. "id": 1,
  806. "milestones": {},
  807. "name": "test",
  808. "namespace": None,
  809. "parent": None,
  810. "priorities": {},
  811. "tags": ["infra"],
  812. "user": {
  813. "fullname": "PY C",
  814. "name": "pingou",
  815. "url_path": "user/pingou",
  816. },
  817. }
  818. ],
  819. "total_projects": 1,
  820. }
  821. self.assertDictEqual(data, expected_data)
  822. output = self.app.get("/api/0/projects?namespace=somenamespace")
  823. self.assertEqual(output.status_code, 200)
  824. data = json.loads(output.get_data(as_text=True))
  825. data["projects"][0]["date_created"] = "1436527638"
  826. data["projects"][0]["date_modified"] = "1436527638"
  827. del data["pagination"]
  828. expected_data = {
  829. "args": {
  830. "fork": None,
  831. "owner": None,
  832. "page": 1,
  833. "namespace": "somenamespace",
  834. "per_page": 20,
  835. "pattern": None,
  836. "short": False,
  837. "tags": [],
  838. "username": None,
  839. },
  840. "projects": [
  841. {
  842. "access_groups": {"admin": [], "commit": [], "ticket": []},
  843. "access_users": {
  844. "admin": [],
  845. "commit": [],
  846. "owner": ["pingou"],
  847. "ticket": [],
  848. },
  849. "close_status": [
  850. "Invalid",
  851. "Insufficient data",
  852. "Fixed",
  853. "Duplicate",
  854. ],
  855. "custom_keys": [],
  856. "date_created": "1436527638",
  857. "date_modified": "1436527638",
  858. "description": "namespaced test project",
  859. "fullname": "somenamespace/test3",
  860. "url_path": "somenamespace/test3",
  861. "id": 3,
  862. "milestones": {},
  863. "name": "test3",
  864. "namespace": "somenamespace",
  865. "parent": None,
  866. "priorities": {},
  867. "tags": [],
  868. "user": {
  869. "fullname": "PY C",
  870. "name": "pingou",
  871. "url_path": "user/pingou",
  872. },
  873. }
  874. ],
  875. "total_projects": 1,
  876. }
  877. self.assertDictEqual(data, expected_data)
  878. def test_api_project(self):
  879. """ Test the api_project method of the flask api. """
  880. tests.create_projects(self.session)
  881. # Check before adding
  882. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  883. self.assertEqual(repo.tags, [])
  884. # Adding a tag
  885. output = pagure.lib.query.update_tags(
  886. self.session, repo, "infra", "pingou"
  887. )
  888. self.assertEqual(output, ["Project tagged with: infra"])
  889. # Check after adding
  890. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  891. self.assertEqual(len(repo.tags), 1)
  892. self.assertEqual(repo.tags_text, ["infra"])
  893. # Check the API
  894. # Non-existing project
  895. output = self.app.get("/api/0/random")
  896. self.assertEqual(output.status_code, 404)
  897. data = json.loads(output.get_data(as_text=True))
  898. self.assertDictEqual(
  899. data, {"error_code": "ENOPROJECT", "error": "Project not found"}
  900. )
  901. # Existing project
  902. output = self.app.get("/api/0/test")
  903. self.assertEqual(output.status_code, 200)
  904. data = json.loads(output.get_data(as_text=True))
  905. data["date_created"] = "1436527638"
  906. data["date_modified"] = "1436527638"
  907. expected_data = {
  908. "access_groups": {"admin": [], "commit": [], "ticket": []},
  909. "access_users": {
  910. "admin": [],
  911. "commit": [],
  912. "owner": ["pingou"],
  913. "ticket": [],
  914. },
  915. "close_status": [
  916. "Invalid",
  917. "Insufficient data",
  918. "Fixed",
  919. "Duplicate",
  920. ],
  921. "custom_keys": [],
  922. "date_created": "1436527638",
  923. "date_modified": "1436527638",
  924. "description": "test project #1",
  925. "fullname": "test",
  926. "url_path": "test",
  927. "id": 1,
  928. "milestones": {},
  929. "name": "test",
  930. "namespace": None,
  931. "parent": None,
  932. "priorities": {},
  933. "tags": ["infra"],
  934. "user": {
  935. "fullname": "PY C",
  936. "name": "pingou",
  937. "url_path": "user/pingou",
  938. },
  939. }
  940. self.assertDictEqual(data, expected_data)
  941. def test_api_project_group(self):
  942. """ Test the api_project method of the flask api. """
  943. tests.create_projects(self.session)
  944. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  945. # Adding a tag
  946. output = pagure.lib.query.update_tags(
  947. self.session, repo, "infra", "pingou"
  948. )
  949. self.assertEqual(output, ["Project tagged with: infra"])
  950. # Check after adding
  951. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  952. self.assertEqual(len(repo.tags), 1)
  953. self.assertEqual(repo.tags_text, ["infra"])
  954. # Add a group to the project
  955. msg = pagure.lib.query.add_group(
  956. self.session,
  957. group_name="some_group",
  958. display_name="Some Group",
  959. description=None,
  960. group_type="bar",
  961. user="foo",
  962. is_admin=False,
  963. blacklist=[],
  964. )
  965. self.session.commit()
  966. project = pagure.lib.query.get_authorized_project(self.session, "test")
  967. group = pagure.lib.query.search_groups(
  968. self.session, group_name="some_group"
  969. )
  970. pagure.lib.query.add_group_to_project(
  971. self.session,
  972. project,
  973. new_group="some_group",
  974. user="pingou",
  975. access="commit",
  976. create=False,
  977. is_admin=True,
  978. )
  979. self.session.commit()
  980. # Check the API
  981. # Existing project
  982. output = self.app.get("/api/0/test?expand_group=1")
  983. self.assertEqual(output.status_code, 200)
  984. data = json.loads(output.get_data(as_text=True))
  985. data["date_created"] = "1436527638"
  986. data["date_modified"] = "1436527638"
  987. expected_data = {
  988. "access_groups": {
  989. "admin": [],
  990. "commit": ["some_group"],
  991. "ticket": [],
  992. },
  993. "access_users": {
  994. "admin": [],
  995. "commit": [],
  996. "owner": ["pingou"],
  997. "ticket": [],
  998. },
  999. "close_status": [
  1000. "Invalid",
  1001. "Insufficient data",
  1002. "Fixed",
  1003. "Duplicate",
  1004. ],
  1005. "custom_keys": [],
  1006. "date_created": "1436527638",
  1007. "date_modified": "1436527638",
  1008. "description": "test project #1",
  1009. "fullname": "test",
  1010. "url_path": "test",
  1011. "group_details": {"some_group": ["foo"]},
  1012. "id": 1,
  1013. "milestones": {},
  1014. "name": "test",
  1015. "namespace": None,
  1016. "parent": None,
  1017. "priorities": {},
  1018. "tags": ["infra"],
  1019. "user": {
  1020. "fullname": "PY C",
  1021. "name": "pingou",
  1022. "url_path": "user/pingou",
  1023. },
  1024. }
  1025. self.assertDictEqual(data, expected_data)
  1026. def test_api_project_group_but_no_group(self):
  1027. """ Test the api_project method of the flask api when asking for
  1028. group details while there are none associated.
  1029. """
  1030. tests.create_projects(self.session)
  1031. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1032. # Adding a tag
  1033. output = pagure.lib.query.update_tags(
  1034. self.session, repo, "infra", "pingou"
  1035. )
  1036. self.assertEqual(output, ["Project tagged with: infra"])
  1037. # Check after adding
  1038. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  1039. self.assertEqual(len(repo.tags), 1)
  1040. self.assertEqual(repo.tags_text, ["infra"])
  1041. # Check the API
  1042. # Existing project
  1043. output = self.app.get("/api/0/test?expand_group=0")
  1044. self.assertEqual(output.status_code, 200)
  1045. data = json.loads(output.get_data(as_text=True))
  1046. data["date_created"] = "1436527638"
  1047. data["date_modified"] = "1436527638"
  1048. expected_data = {
  1049. "access_groups": {"admin": [], "commit": [], "ticket": []},
  1050. "access_users": {
  1051. "admin": [],
  1052. "commit": [],
  1053. "owner": ["pingou"],
  1054. "ticket": [],
  1055. },
  1056. "close_status": [
  1057. "Invalid",
  1058. "Insufficient data",
  1059. "Fixed",
  1060. "Duplicate",
  1061. ],
  1062. "custom_keys": [],
  1063. "date_created": "1436527638",
  1064. "date_modified": "1436527638",
  1065. "description": "test project #1",
  1066. "fullname": "test",
  1067. "url_path": "test",
  1068. "id": 1,
  1069. "milestones": {},
  1070. "name": "test",
  1071. "namespace": None,
  1072. "parent": None,
  1073. "priorities": {},
  1074. "tags": ["infra"],
  1075. "user": {
  1076. "fullname": "PY C",
  1077. "name": "pingou",
  1078. "url_path": "user/pingou",
  1079. },
  1080. }
  1081. self.assertDictEqual(data, expected_data)
  1082. def test_api_projects_pagination(self):
  1083. """ Test the api_projects method of the flask api with pagination. """
  1084. tests.create_projects(self.session)
  1085. output = self.app.get("/api/0/projects?page=1")
  1086. self.assertEqual(output.status_code, 200)
  1087. data = json.loads(output.get_data(as_text=True))
  1088. for i in range(3):
  1089. data["projects"][i]["date_created"] = "1436527638"
  1090. data["projects"][i]["date_modified"] = "1436527638"
  1091. expected_data = {
  1092. "args": {
  1093. "fork": None,
  1094. "namespace": None,
  1095. "owner": None,
  1096. "page": 1,
  1097. "per_page": 20,
  1098. "pattern": None,
  1099. "short": False,
  1100. "tags": [],
  1101. "username": None,
  1102. },
  1103. "pagination": {
  1104. "next": None,
  1105. "page": 1,
  1106. "pages": 1,
  1107. "per_page": 20,
  1108. "prev": None,
  1109. },
  1110. "projects": [
  1111. {
  1112. "access_groups": {"admin": [], "commit": [], "ticket": []},
  1113. "access_users": {
  1114. "admin": [],
  1115. "commit": [],
  1116. "owner": ["pingou"],
  1117. "ticket": [],
  1118. },
  1119. "close_status": [
  1120. "Invalid",
  1121. "Insufficient data",
  1122. "Fixed",
  1123. "Duplicate",
  1124. ],
  1125. "custom_keys": [],
  1126. "date_created": "1436527638",
  1127. "date_modified": "1436527638",
  1128. "description": "test project #1",
  1129. "fullname": "test",
  1130. "url_path": "test",
  1131. "id": 1,
  1132. "milestones": {},
  1133. "name": "test",
  1134. "namespace": None,
  1135. "parent": None,
  1136. "priorities": {},
  1137. "tags": [],
  1138. "user": {
  1139. "fullname": "PY C",
  1140. "name": "pingou",
  1141. "url_path": "user/pingou",
  1142. },
  1143. },
  1144. {
  1145. "access_groups": {"admin": [], "commit": [], "ticket": []},
  1146. "access_users": {
  1147. "admin": [],
  1148. "commit": [],
  1149. "owner": ["pingou"],
  1150. "ticket": [],
  1151. },
  1152. "close_status": [
  1153. "Invalid",
  1154. "Insufficient data",
  1155. "Fixed",
  1156. "Duplicate",
  1157. ],
  1158. "custom_keys": [],
  1159. "date_created": "1436527638",
  1160. "date_modified": "1436527638",
  1161. "description": "test project #2",
  1162. "fullname": "test2",
  1163. "url_path": "test2",
  1164. "id": 2,
  1165. "milestones": {},
  1166. "name": "test2",
  1167. "namespace": None,
  1168. "parent": None,
  1169. "priorities": {},
  1170. "tags": [],
  1171. "user": {
  1172. "fullname": "PY C",
  1173. "name": "pingou",
  1174. "url_path": "user/pingou",
  1175. },
  1176. },
  1177. {
  1178. "access_groups": {"admin": [], "commit": [], "ticket": []},
  1179. "access_users": {
  1180. "admin": [],
  1181. "commit": [],
  1182. "owner": ["pingou"],
  1183. "ticket": [],
  1184. },
  1185. "close_status": [
  1186. "Invalid",
  1187. "Insufficient data",
  1188. "Fixed",
  1189. "Duplicate",
  1190. ],
  1191. "custom_keys": [],
  1192. "date_created": "1436527638",
  1193. "date_modified": "1436527638",
  1194. "description": "namespaced test project",
  1195. "fullname": "somenamespace/test3",
  1196. "url_path": "somenamespace/test3",
  1197. "id": 3,
  1198. "milestones": {},
  1199. "name": "test3",
  1200. "namespace": "somenamespace",
  1201. "parent": None,
  1202. "priorities": {},
  1203. "tags": [],
  1204. "user": {
  1205. "fullname": "PY C",
  1206. "name": "pingou",
  1207. "url_path": "user/pingou",
  1208. },
  1209. },
  1210. ],
  1211. "total_projects": 3,
  1212. }
  1213. # Test URLs
  1214. self.assertURLEqual(
  1215. data["pagination"].pop("first"),
  1216. "http://localhost/api/0/projects?per_page=20&page=1",
  1217. )
  1218. self.assertURLEqual(
  1219. data["pagination"].pop("last"),
  1220. "http://localhost/api/0/projects?per_page=20&page=1",
  1221. )
  1222. self.assertDictEqual(data, expected_data)
  1223. def test_api_projects_pagination_per_page(self):
  1224. """ Test the api_projects method of the flask api with pagination and
  1225. the `per_page` argument set. """
  1226. tests.create_projects(self.session)
  1227. output = self.app.get("/api/0/projects?page=2&per_page=2")
  1228. self.assertEqual(output.status_code, 200)
  1229. data = json.loads(output.get_data(as_text=True))
  1230. data["projects"][0]["date_created"] = "1436527638"
  1231. data["projects"][0]["date_modified"] = "1436527638"
  1232. expected_data = {
  1233. "args": {
  1234. "fork": None,
  1235. "namespace": None,
  1236. "owner": None,
  1237. "page": 2,
  1238. "per_page": 2,
  1239. "pattern": None,
  1240. "short": False,
  1241. "tags": [],
  1242. "username": None,
  1243. },
  1244. "pagination": {"next": None, "page": 2, "pages": 2, "per_page": 2},
  1245. "projects": [
  1246. {
  1247. "access_groups": {"admin": [], "commit": [], "ticket": []},
  1248. "access_users": {
  1249. "admin": [],
  1250. "commit": [],
  1251. "owner": ["pingou"],
  1252. "ticket": [],
  1253. },
  1254. "close_status": [
  1255. "Invalid",
  1256. "Insufficient data",
  1257. "Fixed",
  1258. "Duplicate",
  1259. ],
  1260. "custom_keys": [],
  1261. "date_created": "1436527638",
  1262. "date_modified": "1436527638",
  1263. "description": "namespaced test project",
  1264. "fullname": "somenamespace/test3",
  1265. "url_path": "somenamespace/test3",
  1266. "id": 3,
  1267. "milestones": {},
  1268. "name": "test3",
  1269. "namespace": "somenamespace",
  1270. "parent": None,
  1271. "priorities": {},
  1272. "tags": [],
  1273. "user": {
  1274. "fullname": "PY C",
  1275. "name": "pingou",
  1276. "url_path": "user/pingou",
  1277. },
  1278. }
  1279. ],
  1280. "total_projects": 3,
  1281. }
  1282. self.assertURLEqual(
  1283. data["pagination"].pop("first"),
  1284. "http://localhost/api/0/projects?per_page=2&page=1",
  1285. )
  1286. self.assertURLEqual(
  1287. data["pagination"].pop("prev"),
  1288. "http://localhost/api/0/projects?per_page=2&page=1",
  1289. )
  1290. self.assertURLEqual(
  1291. data["pagination"].pop("last"),
  1292. "http://localhost/api/0/projects?per_page=2&page=2",
  1293. )
  1294. self.assertDictEqual(data, expected_data)
  1295. def test_api_projects_pagination_invalid_page(self):
  1296. """ Test the api_projects method of the flask api when an invalid page
  1297. value is entered. """
  1298. tests.create_projects(self.session)
  1299. output = self.app.get("/api/0/projects?page=-3")
  1300. self.assertEqual(output.status_code, 400)
  1301. def test_api_projects_pagination_invalid_page_str(self):
  1302. """ Test the api_projects method of the flask api when an invalid type
  1303. for the page value is entered. """
  1304. tests.create_projects(self.session)
  1305. output = self.app.get("/api/0/projects?page=abcd")
  1306. self.assertEqual(output.status_code, 400)
  1307. def test_api_projects_pagination_invalid_per_page_too_low(self):
  1308. """ Test the api_projects method of the flask api when a per_page
  1309. value is below 1. """
  1310. tests.create_projects(self.session)
  1311. output = self.app.get("/api/0/projects?page=1&per_page=0")
  1312. self.assertEqual(output.status_code, 400)
  1313. error = json.loads(output.get_data(as_text=True))
  1314. self.assertEqual(
  1315. error["error"], "The per_page value must be between 1 and 100"
  1316. )
  1317. def test_api_projects_pagination_invalid_per_page_too_high(self):
  1318. """ Test the api_projects method of the flask api when a per_page
  1319. value is above 100. """
  1320. tests.create_projects(self.session)
  1321. output = self.app.get("/api/0/projects?page=1&per_page=101")
  1322. self.assertEqual(output.status_code, 400)
  1323. error = json.loads(output.get_data(as_text=True))
  1324. self.assertEqual(
  1325. error["error"], "The per_page value must be between 1 and 100"
  1326. )
  1327. def test_api_projects_pagination_invalid_per_page_str(self):
  1328. """ Test the api_projects method of the flask api when an invalid type
  1329. for the per_page value is entered. """
  1330. tests.create_projects(self.session)
  1331. output = self.app.get("/api/0/projects?page=1&per_page=abcd")
  1332. self.assertEqual(output.status_code, 400)
  1333. def test_api_projects_pagination_beyond_last_page(self):
  1334. """ Test the api_projects method of the flask api when a page value
  1335. that is larger than the last page is entered. """
  1336. tests.create_projects(self.session)
  1337. output = self.app.get("/api/0/projects?page=99999")
  1338. self.assertEqual(output.status_code, 200)
  1339. data = json.loads(output.get_data(as_text=True))
  1340. self.assertURLEqual(
  1341. data["pagination"].pop("first"),
  1342. "http://localhost/api/0/projects?per_page=20&page=1",
  1343. )
  1344. self.assertURLEqual(
  1345. data["pagination"].pop("last"),
  1346. "http://localhost/api/0/projects?per_page=20&page=1",
  1347. )
  1348. self.assertURLEqual(
  1349. data["pagination"].pop("prev"),
  1350. "http://localhost/api/0/projects?per_page=20&page=99998",
  1351. )
  1352. self.assertEqual(
  1353. data,
  1354. {
  1355. "args": {
  1356. "fork": None,
  1357. "namespace": None,
  1358. "owner": None,
  1359. "page": 99999,
  1360. "pattern": None,
  1361. "per_page": 20,
  1362. "short": False,
  1363. "tags": [],
  1364. "username": None,
  1365. },
  1366. "pagination": {
  1367. "next": None,
  1368. "page": 99999,
  1369. "pages": 1,
  1370. "per_page": 20,
  1371. },
  1372. "projects": [],
  1373. "total_projects": 3,
  1374. },
  1375. )
  1376. def test_api_modify_project_main_admin(self):
  1377. """ Test the api_modify_project method of the flask api when the
  1378. request is to change the main_admin of the project. """
  1379. tests.create_projects(self.session)
  1380. tests.create_tokens(self.session, project_id=None)
  1381. tests.create_tokens_acl(self.session, "aaabbbcccddd", "modify_project")
  1382. headers = {"Authorization": "token aaabbbcccddd"}
  1383. output = self.app.patch(
  1384. "/api/0/test", headers=headers, data={"main_admin": "foo"}
  1385. )
  1386. self.assertEqual(output.status_code, 200)
  1387. data = json.loads(output.get_data(as_text=True))
  1388. data["date_created"] = "1496338274"
  1389. data["date_modified"] = "1496338274"
  1390. expected_output = {
  1391. "access_groups": {"admin": [], "commit": [], "ticket": []},
  1392. "access_users": {
  1393. "admin": [],
  1394. "commit": [],
  1395. "owner": ["foo"],
  1396. "ticket": [],
  1397. },
  1398. "close_status": [
  1399. "Invalid",
  1400. "Insufficient data",
  1401. "Fixed",
  1402. "Duplicate",
  1403. ],
  1404. "custom_keys": [],
  1405. "date_created": "1496338274",
  1406. "date_modified": "1496338274",
  1407. "description": "test project #1",
  1408. "fullname": "test",
  1409. "url_path": "test",
  1410. "id": 1,
  1411. "milestones": {},
  1412. "name": "test",
  1413. "namespace": None,
  1414. "parent": None,
  1415. "priorities": {},
  1416. "tags": [],
  1417. "user": {
  1418. "default_email": "foo@bar.com",
  1419. "emails": ["foo@bar.com"],
  1420. "fullname": "foo bar",
  1421. "name": "foo",
  1422. "url_path": "user/foo",
  1423. },
  1424. }
  1425. self.assertEqual(data, expected_output)
  1426. def test_api_modify_project_main_admin_retain_access(self):
  1427. """ Test the api_modify_project method of the flask api when the
  1428. request is to change the main_admin of the project and retain_access
  1429. is true. """
  1430. tests.create_projects(self.session)
  1431. tests.create_tokens(self.session, project_id=None)
  1432. tests.create_tokens_acl(self.session, "aaabbbcccddd", "modify_project")
  1433. headers = {"Authorization": "token aaabbbcccddd"}
  1434. output = self.app.patch(
  1435. "/api/0/test",
  1436. headers=headers,
  1437. data={"main_admin": "foo", "retain_access": True},
  1438. )
  1439. self.assertEqual(output.status_code, 200)
  1440. data = json.loads(output.get_data(as_text=True))
  1441. data["date_created"] = "1496338274"
  1442. data["date_modified"] = "1496338274"
  1443. expected_output = {
  1444. "access_groups": {"admin": [], "commit": [], "ticket": []},
  1445. "access_users": {
  1446. "admin": ["pingou"],
  1447. "commit": [],
  1448. "owner": ["foo"],
  1449. "ticket": [],
  1450. },
  1451. "close_status": [
  1452. "Invalid",
  1453. "Insufficient data",
  1454. "Fixed",
  1455. "Duplicate",
  1456. ],
  1457. "custom_keys": [],
  1458. "date_created": "1496338274",
  1459. "date_modified": "1496338274",
  1460. "description": "test project #1",
  1461. "fullname": "test",
  1462. "url_path": "test",
  1463. "id": 1,
  1464. "milestones": {},
  1465. "name": "test",
  1466. "namespace": None,
  1467. "parent": None,
  1468. "priorities": {},
  1469. "tags": [],
  1470. "user": {
  1471. "default_email": "foo@bar.com",
  1472. "emails": ["foo@bar.com"],
  1473. "fullname": "foo bar",
  1474. "name": "foo",
  1475. "url_path": "user/foo",
  1476. },
  1477. }
  1478. self.assertEqual(data, expected_output)
  1479. def test_api_modify_project_main_admin_retain_access_already_user(self):
  1480. """ Test the api_modify_project method of the flask api when the
  1481. request is to change the main_admin of the project and retain_access
  1482. is true and the user becoming the main_admin already has access. """
  1483. tests.create_projects(self.session)
  1484. tests.create_tokens(self.session, project_id=None)
  1485. tests.create_tokens_acl(self.session, "aaabbbcccddd", "modify_project")
  1486. headers = {"Authorization": "token aaabbbcccddd"}
  1487. project = pagure.lib.query._get_project(self.session, "test")
  1488. pagure.lib.query.add_user_to_project(
  1489. self.session,
  1490. project,
  1491. new_user="foo",
  1492. user="pingou",
  1493. access="commit",
  1494. )
  1495. self.session.commit()
  1496. output = self.app.patch(
  1497. "/api/0/test",
  1498. headers=headers,
  1499. data={"main_admin": "foo", "retain_access": True},
  1500. )
  1501. self.assertEqual(output.status_code, 200)
  1502. data = json.loads(output.get_data(as_text=True))
  1503. data["date_created"] = "1496338274"
  1504. data["date_modified"] = "1496338274"
  1505. expected_output = {
  1506. "access_groups": {"admin": [], "commit": [], "ticket": []},
  1507. "access_users": {
  1508. "admin": ["pingou"],
  1509. "commit": [],
  1510. "owner": ["foo"],
  1511. "ticket": [],
  1512. },
  1513. "close_status": [
  1514. "Invalid",
  1515. "Insufficient data",
  1516. "Fixed",
  1517. "Duplicate",
  1518. ],
  1519. "custom_keys": [],
  1520. "date_created": "1496338274",
  1521. "date_modified": "1496338274",
  1522. "description": "test project #1",
  1523. "fullname": "test",
  1524. "url_path": "test",
  1525. "id": 1,
  1526. "milestones": {},
  1527. "name": "test",
  1528. "namespace": None,
  1529. "parent": None,
  1530. "priorities": {},
  1531. "tags": [],
  1532. "user": {
  1533. "default_email": "foo@bar.com",
  1534. "emails": ["foo@bar.com"],
  1535. "fullname": "foo bar",
  1536. "name": "foo",
  1537. "url_path": "user/foo",
  1538. },
  1539. }
  1540. self.assertEqual(data, expected_output)
  1541. def test_api_modify_project_main_admin_json(self):
  1542. """ Test the api_modify_project method of the flask api when the
  1543. request is to change the main_admin of the project using JSON. """
  1544. tests.create_projects(self.session)
  1545. tests.create_tokens(self.session, project_id=None)
  1546. tests.create_tokens_acl(self.session, "aaabbbcccddd", "modify_project")
  1547. headers = {
  1548. "Authorization": "token aaabbbcccddd",
  1549. "Content-Type": "application/json",
  1550. }
  1551. output = self.app.patch(
  1552. "/api/0/test",
  1553. headers=headers,
  1554. data=json.dumps({"main_admin": "foo"}),
  1555. )
  1556. self.assertEqual(output.status_code, 200)
  1557. data = json.loads(output.get_data(as_text=True))
  1558. data["date_created"] = "1496338274"
  1559. data["date_modified"] = "1496338274"
  1560. expected_output = {
  1561. "access_groups": {"admin": [], "commit": [], "ticket": []},
  1562. "access_users": {
  1563. "admin": [],
  1564. "commit": [],
  1565. "owner": ["foo"],
  1566. "ticket": [],
  1567. },
  1568. "close_status": [
  1569. "Invalid",
  1570. "Insufficient data",
  1571. "Fixed",
  1572. "Duplicate",
  1573. ],
  1574. "custom_keys": [],
  1575. "date_created": "1496338274",
  1576. "date_modified": "1496338274",
  1577. "description": "test project #1",
  1578. "fullname": "test",
  1579. "url_path": "test",
  1580. "id": 1,
  1581. "milestones": {},
  1582. "name": "test",
  1583. "namespace": None,
  1584. "parent": None,
  1585. "priorities": {},
  1586. "tags": [],
  1587. "user": {
  1588. "default_email": "foo@bar.com",
  1589. "emails": ["foo@bar.com"],
  1590. "fullname": "foo bar",
  1591. "name": "foo",
  1592. "url_path": "user/foo",
  1593. },
  1594. }
  1595. self.assertEqual(data, expected_output)
  1596. @patch.dict("pagure.config.config", {"PAGURE_ADMIN_USERS": "foo"})
  1597. def test_api_modify_project_main_admin_as_site_admin(self):
  1598. """ Test the api_modify_project method of the flask api when the
  1599. request is to change the main_admin of the project and the user is a
  1600. Pagure site admin. """
  1601. tests.create_projects(self.session)
  1602. tests.create_tokens(self.session, user_id=2, project_id=None)
  1603. tests.create_tokens_acl(self.session, "aaabbbcccddd", "modify_project")
  1604. headers = {"Authorization": "token aaabbbcccddd"}
  1605. # date before:
  1606. project = pagure.lib.query.get_authorized_project(self.session, "test")
  1607. date_before = project.date_modified
  1608. self.assertIsNotNone(date_before)
  1609. output = self.app.patch(
  1610. "/api/0/test", headers=headers, data={"main_admin": "foo"}
  1611. )
  1612. self.assertEqual(output.status_code, 200)
  1613. data = json.loads(output.get_data(as_text=True))
  1614. data["date_created"] = "1496338274"
  1615. data["date_modified"] = "1496338274"
  1616. expected_output = {
  1617. "access_groups": {"admin": [], "commit": [], "ticket": []},
  1618. "access_users": {
  1619. "admin": [],
  1620. "commit": [],
  1621. "owner": ["foo"],
  1622. "ticket": [],
  1623. },
  1624. "close_status": [
  1625. "Invalid",
  1626. "Insufficient data",
  1627. "Fixed",
  1628. "Duplicate",
  1629. ],
  1630. "custom_keys": [],
  1631. "date_created": "1496338274",
  1632. "date_modified": "1496338274",
  1633. "description": "test project #1",
  1634. "fullname": "test",
  1635. "url_path": "test",
  1636. "id": 1,
  1637. "milestones": {},
  1638. "name": "test",
  1639. "namespace": None,
  1640. "parent": None,
  1641. "priorities": {},
  1642. "tags": [],
  1643. "user": {
  1644. "default_email": "foo@bar.com",
  1645. "emails": ["foo@bar.com"],
  1646. "fullname": "foo bar",
  1647. "name": "foo",
  1648. "url_path": "user/foo",
  1649. },
  1650. }
  1651. self.assertEqual(data, expected_output)
  1652. # date after:
  1653. self.session = pagure.lib.query.create_session(self.dbpath)
  1654. project = pagure.lib.query.get_authorized_project(self.session, "test")
  1655. self.assertNotEqual(date_before, project.date_modified)
  1656. def test_api_modify_project_main_admin_not_main_admin(self):
  1657. """ Test the api_modify_project method of the flask api when the
  1658. requester is not the main_admin of the project and requests to change
  1659. the main_admin.
  1660. """
  1661. tests.create_projects(self.session)
  1662. project_user = pagure.lib.query.model.ProjectUser(
  1663. project_id=1, user_id=2, access="admin"
  1664. )
  1665. self.session.add(project_user)
  1666. self.session.commit()
  1667. tests.create_tokens(self.session, project_id=None, user_id=2)
  1668. tests.create_tokens_acl(self.session, "aaabbbcccddd", "modify_project")
  1669. headers = {"Authorization": "token aaabbbcccddd"}
  1670. output = self.app.patch(
  1671. "/api/0/test", headers=headers, data={"main_admin": "foo"}
  1672. )
  1673. self.assertEqual(output.status_code, 401)
  1674. expected_error = {
  1675. "error": (
  1676. "Only the main admin can set the main admin of a " "project"
  1677. ),
  1678. "error_code": "ENOTMAINADMIN",
  1679. }
  1680. self.assertEqual(
  1681. json.loads(output.get_data(as_text=True)), expected_error
  1682. )
  1683. def test_api_modify_project_not_admin(self):
  1684. """ Test the api_modify_project method of the flask api when the
  1685. requester is not an admin of the project.
  1686. """
  1687. tests.create_projects(self.session)
  1688. tests.create_tokens(self.session, project_id=None, user_id=2)
  1689. tests.create_tokens_acl(self.session, "aaabbbcccddd", "modify_project")
  1690. headers = {"Authorization": "token aaabbbcccddd"}
  1691. output = self.app.patch(
  1692. "/api/0/test", headers=headers, data={"main_admin": "foo"}
  1693. )
  1694. self.assertEqual(output.status_code, 401)
  1695. expected_error = {
  1696. "error": "You are not allowed to modify this project",
  1697. "error_code": "EMODIFYPROJECTNOTALLOWED",
  1698. }
  1699. self.assertEqual(
  1700. json.loads(output.get_data(as_text=True)), expected_error
  1701. )
  1702. def test_api_modify_project_invalid_request(self):
  1703. """ Test the api_modify_project method of the flask api when the
  1704. request data is invalid.
  1705. """
  1706. tests.create_projects(self.session)
  1707. tests.create_tokens(self.session, project_id=None)
  1708. tests.create_tokens_acl(self.session, "aaabbbcccddd", "modify_project")
  1709. headers = {"Authorization": "token aaabbbcccddd"}
  1710. output = self.app.patch("/api/0/test", headers=headers, data="invalid")
  1711. self.assertEqual(output.status_code, 400)
  1712. expected_error = {
  1713. "error": "Invalid or incomplete input submitted",
  1714. "error_code": "EINVALIDREQ",
  1715. }
  1716. self.assertEqual(
  1717. json.loads(output.get_data(as_text=True)), expected_error
  1718. )
  1719. def test_api_modify_project_invalid_keys(self):
  1720. """ Test the api_modify_project method of the flask api when the
  1721. request data contains an invalid key.
  1722. """
  1723. tests.create_projects(self.session)
  1724. tests.create_tokens(self.session, project_id=None)
  1725. tests.create_tokens_acl(self.session, "aaabbbcccddd", "modify_project")
  1726. headers = {"Authorization": "token aaabbbcccddd"}
  1727. output = self.app.patch(
  1728. "/api/0/test", headers=headers, data={"invalid": "invalid"}
  1729. )
  1730. self.assertEqual(output.status_code, 400)
  1731. expected_error = {
  1732. "error": "Invalid or incomplete input submitted",
  1733. "error_code": "EINVALIDREQ",
  1734. }
  1735. self.assertEqual(
  1736. json.loads(output.get_data(as_text=True)), expected_error
  1737. )
  1738. def test_api_modify_project_invalid_new_main_admin(self):
  1739. """ Test the api_modify_project method of the flask api when the
  1740. request is to change the main_admin of the project to a main_admin
  1741. that doesn't exist.
  1742. """
  1743. tests.create_projects(self.session)
  1744. tests.create_tokens(self.session, project_id=None)
  1745. tests.create_tokens_acl(self.session, "aaabbbcccddd", "modify_project")
  1746. headers = {"Authorization": "token aaabbbcccddd"}
  1747. output = self.app.patch(
  1748. "/api/0/test", headers=headers, data={"main_admin": "tbrady"}
  1749. )
  1750. self.assertEqual(output.status_code, 400)
  1751. expected_error = {
  1752. "error": "No such user found",
  1753. "error_code": "ENOUSER",
  1754. }
  1755. self.assertEqual(
  1756. json.loads(output.get_data(as_text=True)), expected_error
  1757. )
  1758. def test_api_project_watchers(self):
  1759. """ Test the api_project_watchers method of the flask api. """
  1760. tests.create_projects(self.session)
  1761. # The user is not logged in and the owner is watching issues implicitly
  1762. output = self.app.get("/api/0/test/watchers")
  1763. self.assertEqual(output.status_code, 200)
  1764. expected_data = {
  1765. "total_watchers": 1,
  1766. "watchers": {"pingou": ["issues"]},
  1767. }
  1768. self.assertDictEqual(
  1769. json.loads(output.get_data(as_text=True)), expected_data
  1770. )
  1771. user = tests.FakeUser(username="pingou")
  1772. with tests.user_set(self.app.application, user):
  1773. # Non-existing project
  1774. output = self.app.get("/api/0/random/watchers")
  1775. self.assertEqual(output.status_code, 404)
  1776. data = json.loads(output.get_data(as_text=True))
  1777. self.assertDictEqual(
  1778. data,
  1779. {"error_code": "ENOPROJECT", "error": "Project not found"},
  1780. )
  1781. # The owner is watching issues implicitly
  1782. output = self.app.get("/api/0/test/watchers")
  1783. self.assertEqual(output.status_code, 200)
  1784. expected_data = {
  1785. "total_watchers": 1,
  1786. "watchers": {"pingou": ["issues"]},
  1787. }
  1788. self.assertDictEqual(
  1789. json.loads(output.get_data(as_text=True)), expected_data
  1790. )
  1791. project = pagure.lib.query.get_authorized_project(
  1792. self.session, "test"
  1793. )
  1794. # The owner is watching issues and commits explicitly
  1795. pagure.lib.query.update_watch_status(
  1796. self.session, project, "pingou", "3"
  1797. )
  1798. self.session.commit()
  1799. output = self.app.get("/api/0/test/watchers")
  1800. self.assertEqual(output.status_code, 200)
  1801. expected_data = {
  1802. "total_watchers": 1,
  1803. "watchers": {"pingou": ["issues", "commits"]},
  1804. }
  1805. self.assertDictEqual(
  1806. json.loads(output.get_data(as_text=True)), expected_data
  1807. )
  1808. # The owner is watching issues explicitly
  1809. pagure.lib.query.update_watch_status(
  1810. self.session, project, "pingou", "1"
  1811. )
  1812. self.session.commit()
  1813. output = self.app.get("/api/0/test/watchers")
  1814. self.assertEqual(output.status_code, 200)
  1815. expected_data = {
  1816. "total_watchers": 1,
  1817. "watchers": {"pingou": ["issues"]},
  1818. }
  1819. self.assertDictEqual(
  1820. json.loads(output.get_data(as_text=True)), expected_data
  1821. )
  1822. # The owner is watching commits explicitly
  1823. pagure.lib.query.update_watch_status(
  1824. self.session, project, "pingou", "2"
  1825. )
  1826. self.session.commit()
  1827. output = self.app.get("/api/0/test/watchers")
  1828. self.assertEqual(output.status_code, 200)
  1829. expected_data = {
  1830. "total_watchers": 1,
  1831. "watchers": {"pingou": ["commits"]},
  1832. }
  1833. self.assertDictEqual(
  1834. json.loads(output.get_data(as_text=True)), expected_data
  1835. )
  1836. # The owner is watching commits explicitly and foo is watching
  1837. # issues implicitly
  1838. project_user = pagure.lib.model.ProjectUser(
  1839. project_id=project.id, user_id=2, access="commit"
  1840. )
  1841. pagure.lib.query.update_watch_status(
  1842. self.session, project, "pingou", "2"
  1843. )
  1844. self.session.add(project_user)
  1845. self.session.commit()
  1846. output = self.app.get("/api/0/test/watchers")
  1847. self.assertEqual(output.status_code, 200)
  1848. expected_data = {
  1849. "total_watchers": 2,
  1850. "watchers": {"foo": ["issues"], "pingou": ["commits"]},
  1851. }
  1852. self.assertDictEqual(
  1853. json.loads(output.get_data(as_text=True)), expected_data
  1854. )
  1855. # The owner and foo are watching issues implicitly
  1856. pagure.lib.query.update_watch_status(
  1857. self.session, project, "pingou", "-1"
  1858. )
  1859. self.session.commit()
  1860. output = self.app.get("/api/0/test/watchers")
  1861. self.assertEqual(output.status_code, 200)
  1862. expected_data = {
  1863. "total_watchers": 2,
  1864. "watchers": {"foo": ["issues"], "pingou": ["issues"]},
  1865. }
  1866. self.assertDictEqual(
  1867. json.loads(output.get_data(as_text=True)), expected_data
  1868. )
  1869. # The owner and foo through group membership are watching issues
  1870. # implicitly
  1871. pagure.lib.query.update_watch_status(
  1872. self.session, project, "pingou", "-1"
  1873. )
  1874. project_membership = (
  1875. self.session.query(pagure.lib.model.ProjectUser)
  1876. .filter_by(user_id=2, project_id=project.id)
  1877. .one()
  1878. )
  1879. self.session.delete(project_membership)
  1880. self.session.commit()
  1881. msg = pagure.lib.query.add_group(
  1882. self.session,
  1883. group_name="some_group",
  1884. display_name="Some Group",
  1885. description=None,
  1886. group_type="bar",
  1887. user="pingou",
  1888. is_admin=False,
  1889. blacklist=[],
  1890. )
  1891. self.session.commit()
  1892. project = pagure.lib.query.get_authorized_project(
  1893. self.session, "test"
  1894. )
  1895. group = pagure.lib.query.search_groups(
  1896. self.session, group_name="some_group"
  1897. )
  1898. pagure.lib.query.add_user_to_group(
  1899. self.session, "foo", group, "pingou", False
  1900. )
  1901. pagure.lib.query.add_group_to_project(
  1902. self.session,
  1903. project,
  1904. new_group="some_group",
  1905. user="pingou",
  1906. access="commit",
  1907. create=False,
  1908. is_admin=True,
  1909. )
  1910. self.session.commit()
  1911. output = self.app.get("/api/0/test/watchers")
  1912. self.assertEqual(output.status_code, 200)
  1913. expected_data = {
  1914. "total_watchers": 2,
  1915. "watchers": {"@some_group": ["issues"], "pingou": ["issues"]},
  1916. }
  1917. self.assertDictEqual(
  1918. json.loads(output.get_data(as_text=True)), expected_data
  1919. )
  1920. # The owner is watching issues implicitly and foo will be watching
  1921. # commits explicitly but is in a group with commit access
  1922. pagure.lib.query.update_watch_status(
  1923. self.session, project, "pingou", "-1"
  1924. )
  1925. pagure.lib.query.update_watch_status(
  1926. self.session, project, "foo", "2"
  1927. )
  1928. self.session.commit()
  1929. output = self.app.get("/api/0/test/watchers")
  1930. self.assertEqual(output.status_code, 200)
  1931. expected_data = {
  1932. "total_watchers": 3,
  1933. "watchers": {
  1934. "@some_group": ["issues"],
  1935. "foo": ["commits"],
  1936. "pingou": ["issues"],
  1937. },
  1938. }
  1939. self.assertDictEqual(
  1940. json.loads(output.get_data(as_text=True)), expected_data
  1941. )
  1942. def test_api_new_project(self):
  1943. """ Test the api_new_project method of the flask api. """
  1944. tests.create_projects(self.session)
  1945. tests.create_projects_git(os.path.join(self.path, "tickets"))
  1946. tests.create_tokens(self.session)
  1947. tests.create_tokens_acl(self.session)
  1948. headers = {"Authorization": "token foo_token"}
  1949. # Invalid token
  1950. output = self.app.post("/api/0/new", headers=headers)
  1951. self.assertEqual(output.status_code, 401)
  1952. data = json.loads(output.get_data(as_text=True))
  1953. self.assertEqual(
  1954. sorted(data.keys()), ["error", "error_code", "errors"]
  1955. )
  1956. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data["error"])
  1957. self.assertEqual(
  1958. pagure.api.APIERROR.EINVALIDTOK.name, data["error_code"]
  1959. )
  1960. self.assertEqual(data["errors"], "Missing ACLs: create_project")
  1961. headers = {"Authorization": "token aaabbbcccddd"}
  1962. # No input
  1963. output = self.app.post("/api/0/new", headers=headers)
  1964. self.assertEqual(output.status_code, 400)
  1965. data = json.loads(output.get_data(as_text=True))
  1966. self.assertDictEqual(
  1967. data,
  1968. {
  1969. "error": "Invalid or incomplete input submitted",
  1970. "error_code": "EINVALIDREQ",
  1971. "errors": {
  1972. "name": ["This field is required."],
  1973. "description": ["This field is required."],
  1974. },
  1975. },
  1976. )
  1977. data = {"name": "test"}
  1978. # Incomplete request
  1979. output = self.app.post("/api/0/new", data=data, headers=headers)
  1980. self.assertEqual(output.status_code, 400)
  1981. data = json.loads(output.get_data(as_text=True))
  1982. self.assertDictEqual(
  1983. data,
  1984. {
  1985. "error": "Invalid or incomplete input submitted",
  1986. "error_code": "EINVALIDREQ",
  1987. "errors": {"description": ["This field is required."]},
  1988. },
  1989. )
  1990. data = {"name": "test", "description": "Just a small test project"}
  1991. # Valid request but repo already exists
  1992. output = self.app.post("/api/0/new/", data=data, headers=headers)
  1993. self.assertEqual(output.status_code, 400)
  1994. data = json.loads(output.get_data(as_text=True))
  1995. self.assertDictEqual(
  1996. data,
  1997. {
  1998. "error": 'It is not possible to create the repo "test"',
  1999. "error_code": "ENOCODE",
  2000. },
  2001. )
  2002. data = {
  2003. "name": "api1",
  2004. "description": "Mighty mighty description",
  2005. "avatar_email": 123,
  2006. }
  2007. # invalid avatar_email - number
  2008. output = self.app.post("/api/0/new/", data=data, headers=headers)
  2009. self.assertEqual(output.status_code, 400)
  2010. data = json.loads(output.get_data(as_text=True))
  2011. self.assertDictEqual(
  2012. data,
  2013. {
  2014. "error": "Invalid or incomplete input submitted",
  2015. "error_code": "EINVALIDREQ",
  2016. "errors": {"avatar_email": ["avatar_email must be an email"]},
  2017. },
  2018. )
  2019. data = {
  2020. "name": "api1",
  2021. "description": "Mighty mighty description",
  2022. "avatar_email": [1, 2, 3],
  2023. }
  2024. # invalid avatar_email - list
  2025. output = self.app.post("/api/0/new/", data=data, headers=headers)
  2026. self.assertEqual(output.status_code, 400)
  2027. data = json.loads(output.get_data(as_text=True))
  2028. self.assertDictEqual(
  2029. data,
  2030. {
  2031. "error": "Invalid or incomplete input submitted",
  2032. "error_code": "EINVALIDREQ",
  2033. "errors": {"avatar_email": ["avatar_email must be an email"]},
  2034. },
  2035. )
  2036. data = {
  2037. "name": "api1",
  2038. "description": "Mighty mighty description",
  2039. "avatar_email": True,
  2040. }
  2041. # invalid avatar_email - boolean
  2042. output = self.app.post("/api/0/new/", data=data, headers=headers)
  2043. self.assertEqual(output.status_code, 400)
  2044. data = json.loads(output.get_data(as_text=True))
  2045. self.assertDictEqual(
  2046. data,
  2047. {
  2048. "error": "Invalid or incomplete input submitted",
  2049. "error_code": "EINVALIDREQ",
  2050. "errors": {"avatar_email": ["avatar_email must be an email"]},
  2051. },
  2052. )
  2053. data = {
  2054. "name": "api1",
  2055. "description": "Mighty mighty description",
  2056. "avatar_email": "mighty@email.com",
  2057. }
  2058. # valid avatar_email
  2059. output = self.app.post("/api/0/new/", data=data, headers=headers)
  2060. self.assertEqual(output.status_code, 200)
  2061. data = json.loads(output.get_data(as_text=True))
  2062. self.assertDictEqual(data, {"message": 'Project "api1" created'})
  2063. data = {
  2064. "name": "test_42",
  2065. "description": "Just another small test project",
  2066. }
  2067. # Valid request
  2068. output = self.app.post("/api/0/new/", data=data, headers=headers)
  2069. self.assertEqual(output.status_code, 200)
  2070. data = json.loads(output.get_data(as_text=True))
  2071. self.assertDictEqual(data, {"message": 'Project "test_42" created'})
  2072. @patch.dict(
  2073. "pagure.config.config",
  2074. {
  2075. "PAGURE_ADMIN_USERS": ["pingou"],
  2076. "ALLOW_ADMIN_IGNORE_EXISTING_REPOS": True,
  2077. },
  2078. )
  2079. def test_adopt_repos(self):
  2080. """ Test the new_project endpoint with existing git repo. """
  2081. # Before
  2082. projects = pagure.lib.query.search_projects(self.session)
  2083. self.assertEqual(len(projects), 0)
  2084. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  2085. tests.add_content_git_repo(
  2086. os.path.join(self.path, "repos", "test.git")
  2087. )
  2088. item = pagure.lib.model.Token(
  2089. id="aaabbbcccddd",
  2090. user_id=1,
  2091. project_id=None,
  2092. expiration=datetime.datetime.utcnow()
  2093. + datetime.timedelta(days=10),
  2094. )
  2095. self.session.add(item)
  2096. self.session.commit()
  2097. tests.create_tokens_acl(self.session)
  2098. headers = {"Authorization": "token aaabbbcccddd"}
  2099. user = tests.FakeUser(username="pingou")
  2100. with tests.user_set(self.app.application, user):
  2101. input_data = {"name": "test", "description": "Project #1"}
  2102. # Valid request
  2103. output = self.app.post(
  2104. "/api/0/new/", data=input_data, headers=headers
  2105. )
  2106. self.assertEqual(output.status_code, 400)
  2107. data = json.loads(output.get_data(as_text=True))
  2108. self.assertDictEqual(
  2109. data,
  2110. {
  2111. "error": "The main repo test.git already exists",
  2112. "error_code": "ENOCODE",
  2113. },
  2114. )
  2115. input_data["ignore_existing_repos"] = "y"
  2116. # Valid request
  2117. output = self.app.post(
  2118. "/api/0/new/", data=input_data, headers=headers
  2119. )
  2120. self.assertEqual(output.status_code, 200)
  2121. data = json.loads(output.get_data(as_text=True))
  2122. self.assertDictEqual(data, {"message": 'Project "test" created'})
  2123. @patch.dict("pagure.config.config", {"PRIVATE_PROJECTS": True})
  2124. def test_api_new_project_private(self):
  2125. """ Test the api_new_project method of the flask api to create
  2126. a private project. """
  2127. tests.create_projects(self.session)
  2128. tests.create_projects_git(os.path.join(self.path, "tickets"))
  2129. tests.create_tokens(self.session)
  2130. tests.create_tokens_acl(self.session)
  2131. headers = {"Authorization": "token aaabbbcccddd"}
  2132. data = {
  2133. "name": "test",
  2134. "description": "Just a small test project",
  2135. "private": True,
  2136. }
  2137. # Valid request
  2138. output = self.app.post("/api/0/new/", data=data, headers=headers)
  2139. self.assertEqual(output.status_code, 200)
  2140. data = json.loads(output.get_data(as_text=True))
  2141. self.assertDictEqual(
  2142. data, {"message": 'Project "pingou/test" created'}
  2143. )
  2144. def test_api_new_project_user_token(self):
  2145. """ Test the api_new_project method of the flask api. """
  2146. tests.create_projects(self.session)
  2147. tests.create_projects_git(os.path.join(self.path, "tickets"))
  2148. tests.create_tokens(self.session, project_id=None)
  2149. tests.create_tokens_acl(self.session)
  2150. headers = {"Authorization": "token foo_token"}
  2151. # Invalid token
  2152. output = self.app.post("/api/0/new", headers=headers)
  2153. self.assertEqual(output.status_code, 401)
  2154. data = json.loads(output.get_data(as_text=True))
  2155. self.assertEqual(
  2156. sorted(data.keys()), ["error", "error_code", "errors"]
  2157. )
  2158. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data["error"])
  2159. self.assertEqual(
  2160. pagure.api.APIERROR.EINVALIDTOK.name, data["error_code"]
  2161. )
  2162. self.assertEqual(data["errors"], "Missing ACLs: create_project")
  2163. headers = {"Authorization": "token aaabbbcccddd"}
  2164. # No input
  2165. output = self.app.post("/api/0/new", headers=headers)
  2166. self.assertEqual(output.status_code, 400)
  2167. data = json.loads(output.get_data(as_text=True))
  2168. self.assertDictEqual(
  2169. data,
  2170. {
  2171. "error": "Invalid or incomplete input submitted",
  2172. "error_code": "EINVALIDREQ",
  2173. "errors": {
  2174. "name": ["This field is required."],
  2175. "description": ["This field is required."],
  2176. },
  2177. },
  2178. )
  2179. data = {"name": "test"}
  2180. # Incomplete request
  2181. output = self.app.post("/api/0/new", data=data, headers=headers)
  2182. self.assertEqual(output.status_code, 400)
  2183. data = json.loads(output.get_data(as_text=True))
  2184. self.assertDictEqual(
  2185. data,
  2186. {
  2187. "error": "Invalid or incomplete input submitted",
  2188. "error_code": "EINVALIDREQ",
  2189. "errors": {"description": ["This field is required."]},
  2190. },
  2191. )
  2192. data = {"name": "test", "description": "Just a small test project"}
  2193. # Valid request but repo already exists
  2194. output = self.app.post("/api/0/new/", data=data, headers=headers)
  2195. self.assertEqual(output.status_code, 400)
  2196. data = json.loads(output.get_data(as_text=True))
  2197. self.assertDictEqual(
  2198. data,
  2199. {
  2200. "error": 'It is not possible to create the repo "test"',
  2201. "error_code": "ENOCODE",
  2202. },
  2203. )
  2204. data = {
  2205. "name": "test_42",
  2206. "description": "Just another small test project",
  2207. }
  2208. # Valid request
  2209. output = self.app.post("/api/0/new/", data=data, headers=headers)
  2210. self.assertEqual(output.status_code, 200)
  2211. data = json.loads(output.get_data(as_text=True))
  2212. self.assertDictEqual(data, {"message": 'Project "test_42" created'})
  2213. # Project with a namespace
  2214. pagure.config.config["ALLOWED_PREFIX"] = ["rpms"]
  2215. data = {
  2216. "name": "test_42",
  2217. "namespace": "pingou",
  2218. "description": "Just another small test project",
  2219. }
  2220. # Invalid namespace
  2221. output = self.app.post("/api/0/new/", data=data, headers=headers)
  2222. self.assertEqual(output.status_code, 400)
  2223. data = json.loads(output.get_data(as_text=True))
  2224. self.assertDictEqual(
  2225. data,
  2226. {
  2227. "error": "Invalid or incomplete input submitted",
  2228. "error_code": "EINVALIDREQ",
  2229. "errors": {"namespace": ["Not a valid choice"]},
  2230. },
  2231. )
  2232. data = {
  2233. "name": "test_42",
  2234. "namespace": "rpms",
  2235. "description": "Just another small test project",
  2236. }
  2237. # All good
  2238. output = self.app.post("/api/0/new/", data=data, headers=headers)
  2239. self.assertEqual(output.status_code, 200)
  2240. data = json.loads(output.get_data(as_text=True))
  2241. self.assertDictEqual(
  2242. data, {"message": 'Project "rpms/test_42" created'}
  2243. )
  2244. @patch.dict("pagure.config.config", {"USER_NAMESPACE": True})
  2245. def test_api_new_project_user_ns(self):
  2246. """ Test the api_new_project method of the flask api. """
  2247. tests.create_projects(self.session)
  2248. tests.create_projects_git(os.path.join(self.path, "tickets"))
  2249. tests.create_tokens(self.session)
  2250. tests.create_tokens_acl(self.session)
  2251. headers = {"Authorization": "token aaabbbcccddd"}
  2252. # Create a project with the user namespace feature on
  2253. data = {
  2254. "name": "testproject",
  2255. "description": "Just another small test project",
  2256. }
  2257. # Valid request
  2258. output = self.app.post("/api/0/new/", data=data, headers=headers)
  2259. self.assertEqual(output.status_code, 200)
  2260. data = json.loads(output.get_data(as_text=True))
  2261. self.assertDictEqual(
  2262. data, {"message": 'Project "pingou/testproject" created'}
  2263. )
  2264. # Create a project with a namespace and the user namespace feature on
  2265. data = {
  2266. "name": "testproject2",
  2267. "namespace": "testns",
  2268. "description": "Just another small test project",
  2269. }
  2270. # Valid request
  2271. with patch.dict(
  2272. "pagure.config.config", {"ALLOWED_PREFIX": ["testns"]}
  2273. ):
  2274. output = self.app.post("/api/0/new/", data=data, headers=headers)
  2275. self.assertEqual(output.status_code, 200)
  2276. data = json.loads(output.get_data(as_text=True))
  2277. self.assertDictEqual(
  2278. data, {"message": 'Project "testns/testproject2" created'}
  2279. )
  2280. def test_api_fork_project(self):
  2281. """ Test the api_fork_project method of the flask api. """
  2282. tests.create_projects(self.session)
  2283. for folder in ["docs", "tickets", "requests", "repos"]:
  2284. tests.create_projects_git(
  2285. os.path.join(self.path, folder), bare=True
  2286. )
  2287. tests.create_tokens(self.session)
  2288. tests.create_tokens_acl(self.session)
  2289. headers = {"Authorization": "token foo_token"}
  2290. # Invalid token
  2291. output = self.app.post("/api/0/fork", headers=headers)
  2292. self.assertEqual(output.status_code, 401)
  2293. data = json.loads(output.get_data(as_text=True))
  2294. self.assertEqual(
  2295. sorted(data.keys()), ["error", "error_code", "errors"]
  2296. )
  2297. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data["error"])
  2298. self.assertEqual(
  2299. pagure.api.APIERROR.EINVALIDTOK.name, data["error_code"]
  2300. )
  2301. self.assertEqual(data["errors"], "Missing ACLs: fork_project")
  2302. headers = {"Authorization": "token aaabbbcccddd"}
  2303. # No input
  2304. output = self.app.post("/api/0/fork", headers=headers)
  2305. self.assertEqual(output.status_code, 400)
  2306. data = json.loads(output.get_data(as_text=True))
  2307. self.assertDictEqual(
  2308. data,
  2309. {
  2310. "error": "Invalid or incomplete input submitted",
  2311. "error_code": "EINVALIDREQ",
  2312. "errors": {"repo": ["This field is required."]},
  2313. },
  2314. )
  2315. data = {"name": "test"}
  2316. # Incomplete request
  2317. output = self.app.post("/api/0/fork", data=data, headers=headers)
  2318. self.assertEqual(output.status_code, 400)
  2319. data = json.loads(output.get_data(as_text=True))
  2320. self.assertDictEqual(
  2321. data,
  2322. {
  2323. "error": "Invalid or incomplete input submitted",
  2324. "error_code": "EINVALIDREQ",
  2325. "errors": {"repo": ["This field is required."]},
  2326. },
  2327. )
  2328. data = {"repo": "test"}
  2329. # Valid request
  2330. output = self.app.post("/api/0/fork/", data=data, headers=headers)
  2331. self.assertEqual(output.status_code, 200)
  2332. data = json.loads(output.get_data(as_text=True))
  2333. self.assertDictEqual(
  2334. data, {"message": 'Repo "test" cloned to "pingou/test"'}
  2335. )
  2336. data = {"repo": "test"}
  2337. # project already forked
  2338. output = self.app.post("/api/0/fork/", data=data, headers=headers)
  2339. self.assertEqual(output.status_code, 400)
  2340. data = json.loads(output.get_data(as_text=True))
  2341. self.assertDictEqual(
  2342. data,
  2343. {
  2344. "error": 'Repo "forks/pingou/test" already exists',
  2345. "error_code": "ENOCODE",
  2346. },
  2347. )
  2348. data = {"repo": "test", "username": "pingou"}
  2349. # Fork already exists
  2350. output = self.app.post("/api/0/fork/", data=data, headers=headers)
  2351. self.assertEqual(output.status_code, 400)
  2352. data = json.loads(output.get_data(as_text=True))
  2353. self.assertDictEqual(
  2354. data,
  2355. {
  2356. "error": 'Repo "forks/pingou/test" already exists',
  2357. "error_code": "ENOCODE",
  2358. },
  2359. )
  2360. data = {"repo": "test", "namespace": "pingou"}
  2361. # Repo does not exists
  2362. output = self.app.post("/api/0/fork/", data=data, headers=headers)
  2363. self.assertEqual(output.status_code, 404)
  2364. data = json.loads(output.get_data(as_text=True))
  2365. self.assertDictEqual(
  2366. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  2367. )
  2368. def test_api_fork_project_user_token(self):
  2369. """ Test the api_fork_project method of the flask api. """
  2370. tests.create_projects(self.session)
  2371. for folder in ["docs", "tickets", "requests", "repos"]:
  2372. tests.create_projects_git(
  2373. os.path.join(self.path, folder), bare=True
  2374. )
  2375. tests.create_tokens(self.session, project_id=None)
  2376. tests.create_tokens_acl(self.session)
  2377. headers = {"Authorization": "token foo_token"}
  2378. # Invalid token
  2379. output = self.app.post("/api/0/fork", headers=headers)
  2380. self.assertEqual(output.status_code, 401)
  2381. data = json.loads(output.get_data(as_text=True))
  2382. self.assertEqual(
  2383. sorted(data.keys()), ["error", "error_code", "errors"]
  2384. )
  2385. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data["error"])
  2386. self.assertEqual(
  2387. pagure.api.APIERROR.EINVALIDTOK.name, data["error_code"]
  2388. )
  2389. self.assertEqual(data["errors"], "Missing ACLs: fork_project")
  2390. headers = {"Authorization": "token aaabbbcccddd"}
  2391. # No input
  2392. output = self.app.post("/api/0/fork", headers=headers)
  2393. self.assertEqual(output.status_code, 400)
  2394. data = json.loads(output.get_data(as_text=True))
  2395. self.assertDictEqual(
  2396. data,
  2397. {
  2398. "error": "Invalid or incomplete input submitted",
  2399. "error_code": "EINVALIDREQ",
  2400. "errors": {"repo": ["This field is required."]},
  2401. },
  2402. )
  2403. data = {"name": "test"}
  2404. # Incomplete request
  2405. output = self.app.post("/api/0/fork", data=data, headers=headers)
  2406. self.assertEqual(output.status_code, 400)
  2407. data = json.loads(output.get_data(as_text=True))
  2408. self.assertDictEqual(
  2409. data,
  2410. {
  2411. "error": "Invalid or incomplete input submitted",
  2412. "error_code": "EINVALIDREQ",
  2413. "errors": {"repo": ["This field is required."]},
  2414. },
  2415. )
  2416. data = {"repo": "test"}
  2417. # Valid request
  2418. output = self.app.post("/api/0/fork/", data=data, headers=headers)
  2419. self.assertEqual(output.status_code, 200)
  2420. data = json.loads(output.get_data(as_text=True))
  2421. self.assertDictEqual(
  2422. data, {"message": 'Repo "test" cloned to "pingou/test"'}
  2423. )
  2424. data = {"repo": "test"}
  2425. # project already forked
  2426. output = self.app.post("/api/0/fork/", data=data, headers=headers)
  2427. self.assertEqual(output.status_code, 400)
  2428. data = json.loads(output.get_data(as_text=True))
  2429. self.assertDictEqual(
  2430. data,
  2431. {
  2432. "error": 'Repo "forks/pingou/test" already exists',
  2433. "error_code": "ENOCODE",
  2434. },
  2435. )
  2436. data = {"repo": "test", "username": "pingou"}
  2437. # Fork already exists
  2438. output = self.app.post("/api/0/fork/", data=data, headers=headers)
  2439. self.assertEqual(output.status_code, 400)
  2440. data = json.loads(output.get_data(as_text=True))
  2441. self.assertDictEqual(
  2442. data,
  2443. {
  2444. "error": 'Repo "forks/pingou/test" already exists',
  2445. "error_code": "ENOCODE",
  2446. },
  2447. )
  2448. data = {"repo": "test", "namespace": "pingou"}
  2449. # Repo does not exists
  2450. output = self.app.post("/api/0/fork/", data=data, headers=headers)
  2451. self.assertEqual(output.status_code, 404)
  2452. data = json.loads(output.get_data(as_text=True))
  2453. self.assertDictEqual(
  2454. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  2455. )
  2456. def test_api_generate_acls(self):
  2457. """ Test the api_generate_acls method of the flask api """
  2458. tests.create_projects(self.session)
  2459. tests.create_tokens(self.session, project_id=None)
  2460. tests.create_tokens_acl(
  2461. self.session, "aaabbbcccddd", "generate_acls_project"
  2462. )
  2463. headers = {"Authorization": "token aaabbbcccddd"}
  2464. user = pagure.lib.query.get_user(self.session, "pingou")
  2465. output = self.app.post(
  2466. "/api/0/test/git/generateacls",
  2467. headers=headers,
  2468. data={"wait": False},
  2469. )
  2470. self.assertEqual(output.status_code, 200)
  2471. data = json.loads(output.get_data(as_text=True))
  2472. expected_output = {
  2473. "message": "Project ACL generation queued",
  2474. "taskid": "abc-1234",
  2475. }
  2476. self.assertEqual(data, expected_output)
  2477. self.mock_gen_acls.assert_called_once_with(
  2478. name="test", namespace=None, user=None, group=None
  2479. )
  2480. def test_api_generate_acls_json(self):
  2481. """ Test the api_generate_acls method of the flask api using JSON """
  2482. tests.create_projects(self.session)
  2483. tests.create_tokens(self.session, project_id=None)
  2484. tests.create_tokens_acl(
  2485. self.session, "aaabbbcccddd", "generate_acls_project"
  2486. )
  2487. headers = {
  2488. "Authorization": "token aaabbbcccddd",
  2489. "Content-Type": "application/json",
  2490. }
  2491. user = pagure.lib.query.get_user(self.session, "pingou")
  2492. output = self.app.post(
  2493. "/api/0/test/git/generateacls",
  2494. headers=headers,
  2495. data=json.dumps({"wait": False}),
  2496. )
  2497. self.assertEqual(output.status_code, 200)
  2498. data = json.loads(output.get_data(as_text=True))
  2499. expected_output = {
  2500. "message": "Project ACL generation queued",
  2501. "taskid": "abc-1234",
  2502. }
  2503. self.assertEqual(data, expected_output)
  2504. self.mock_gen_acls.assert_called_once_with(
  2505. name="test", namespace=None, user=None, group=None
  2506. )
  2507. def test_api_generate_acls_wait_true(self):
  2508. """ Test the api_generate_acls method of the flask api when wait is
  2509. set to True """
  2510. tests.create_projects(self.session)
  2511. tests.create_tokens(self.session, project_id=None)
  2512. tests.create_tokens_acl(
  2513. self.session, "aaabbbcccddd", "generate_acls_project"
  2514. )
  2515. headers = {"Authorization": "token aaabbbcccddd"}
  2516. task_result = Mock()
  2517. task_result.id = "abc-1234"
  2518. self.mock_gen_acls.return_value = task_result
  2519. user = pagure.lib.query.get_user(self.session, "pingou")
  2520. output = self.app.post(
  2521. "/api/0/test/git/generateacls",
  2522. headers=headers,
  2523. data={"wait": True},
  2524. )
  2525. self.assertEqual(output.status_code, 200)
  2526. data = json.loads(output.get_data(as_text=True))
  2527. expected_output = {"message": "Project ACLs generated"}
  2528. self.assertEqual(data, expected_output)
  2529. self.mock_gen_acls.assert_called_once_with(
  2530. name="test", namespace=None, user=None, group=None
  2531. )
  2532. self.assertTrue(task_result.get.called)
  2533. def test_api_generate_acls_no_project(self):
  2534. """ Test the api_generate_acls method of the flask api when the project
  2535. doesn't exist """
  2536. tests.create_projects(self.session)
  2537. tests.create_tokens(self.session, project_id=None)
  2538. tests.create_tokens_acl(
  2539. self.session, "aaabbbcccddd", "generate_acls_project"
  2540. )
  2541. headers = {"Authorization": "token aaabbbcccddd"}
  2542. user = pagure.lib.query.get_user(self.session, "pingou")
  2543. output = self.app.post(
  2544. "/api/0/test12345123/git/generateacls",
  2545. headers=headers,
  2546. data={"wait": False},
  2547. )
  2548. self.assertEqual(output.status_code, 404)
  2549. data = json.loads(output.get_data(as_text=True))
  2550. expected_output = {
  2551. "error_code": "ENOPROJECT",
  2552. "error": "Project not found",
  2553. }
  2554. self.assertEqual(data, expected_output)
  2555. def test_api_new_git_branch(self):
  2556. """ Test the api_new_branch method of the flask api """
  2557. tests.create_projects(self.session)
  2558. repo_path = os.path.join(self.path, "repos")
  2559. tests.create_projects_git(repo_path, bare=True)
  2560. tests.add_content_git_repo(os.path.join(repo_path, "test.git"))
  2561. tests.create_tokens(self.session, project_id=None)
  2562. tests.create_tokens_acl(self.session, "aaabbbcccddd", "create_branch")
  2563. headers = {"Authorization": "token aaabbbcccddd"}
  2564. args = {"branch": "test123"}
  2565. output = self.app.post(
  2566. "/api/0/test/git/branch", headers=headers, data=args
  2567. )
  2568. self.assertEqual(output.status_code, 200)
  2569. data = json.loads(output.get_data(as_text=True))
  2570. expected_output = {"message": "Project branch was created"}
  2571. self.assertEqual(data, expected_output)
  2572. git_path = os.path.join(self.path, "repos", "test.git")
  2573. repo_obj = pygit2.Repository(git_path)
  2574. self.assertIn("test123", repo_obj.listall_branches())
  2575. def test_api_new_git_branch_json(self):
  2576. """ Test the api_new_branch method of the flask api """
  2577. tests.create_projects(self.session)
  2578. repo_path = os.path.join(self.path, "repos")
  2579. tests.create_projects_git(repo_path, bare=True)
  2580. tests.add_content_git_repo(os.path.join(repo_path, "test.git"))
  2581. tests.create_tokens(self.session, project_id=None)
  2582. tests.create_tokens_acl(self.session, "aaabbbcccddd", "create_branch")
  2583. headers = {
  2584. "Authorization": "token aaabbbcccddd",
  2585. "Content-Type": "application/json",
  2586. }
  2587. args = {"branch": "test123"}
  2588. output = self.app.post(
  2589. "/api/0/test/git/branch", headers=headers, data=json.dumps(args)
  2590. )
  2591. self.assertEqual(output.status_code, 200)
  2592. data = json.loads(output.get_data(as_text=True))
  2593. expected_output = {"message": "Project branch was created"}
  2594. self.assertEqual(data, expected_output)
  2595. git_path = os.path.join(self.path, "repos", "test.git")
  2596. repo_obj = pygit2.Repository(git_path)
  2597. self.assertIn("test123", repo_obj.listall_branches())
  2598. def test_api_new_git_branch_from_branch(self):
  2599. """ Test the api_new_branch method of the flask api """
  2600. tests.create_projects(self.session)
  2601. repo_path = os.path.join(self.path, "repos")
  2602. tests.create_projects_git(repo_path, bare=True)
  2603. tests.add_content_git_repo(os.path.join(repo_path, "test.git"))
  2604. tests.create_tokens(self.session, project_id=None)
  2605. tests.create_tokens_acl(self.session, "aaabbbcccddd", "create_branch")
  2606. git_path = os.path.join(self.path, "repos", "test.git")
  2607. repo_obj = pygit2.Repository(git_path)
  2608. parent = pagure.lib.git.get_branch_ref(repo_obj, "master").peel()
  2609. repo_obj.create_branch("dev123", parent)
  2610. headers = {"Authorization": "token aaabbbcccddd"}
  2611. args = {"branch": "test123", "from_branch": "dev123"}
  2612. output = self.app.post(
  2613. "/api/0/test/git/branch", headers=headers, data=args
  2614. )
  2615. self.assertEqual(output.status_code, 200)
  2616. data = json.loads(output.get_data(as_text=True))
  2617. expected_output = {"message": "Project branch was created"}
  2618. self.assertEqual(data, expected_output)
  2619. self.assertIn("test123", repo_obj.listall_branches())
  2620. def test_api_new_git_branch_already_exists(self):
  2621. """ Test the api_new_branch method of the flask api when branch already
  2622. exists """
  2623. tests.create_projects(self.session)
  2624. repo_path = os.path.join(self.path, "repos")
  2625. tests.create_projects_git(repo_path, bare=True)
  2626. tests.add_content_git_repo(os.path.join(repo_path, "test.git"))
  2627. tests.create_tokens(self.session, project_id=None)
  2628. tests.create_tokens_acl(self.session, "aaabbbcccddd", "create_branch")
  2629. headers = {"Authorization": "token aaabbbcccddd"}
  2630. args = {"branch": "master"}
  2631. output = self.app.post(
  2632. "/api/0/test/git/branch", headers=headers, data=args
  2633. )
  2634. self.assertEqual(output.status_code, 400)
  2635. data = json.loads(output.get_data(as_text=True))
  2636. expected_output = {
  2637. "error": 'The branch "master" already exists',
  2638. "error_code": "ENOCODE",
  2639. }
  2640. self.assertEqual(data, expected_output)
  2641. def test_api_new_git_branch_from_commit(self):
  2642. """ Test the api_new_branch method of the flask api """
  2643. tests.create_projects(self.session)
  2644. repos_path = os.path.join(self.path, "repos")
  2645. tests.create_projects_git(repos_path, bare=True)
  2646. git_path = os.path.join(repos_path, "test.git")
  2647. tests.add_content_git_repo(git_path)
  2648. tests.create_tokens(self.session, project_id=None)
  2649. tests.create_tokens_acl(self.session, "aaabbbcccddd", "create_branch")
  2650. repo_obj = pygit2.Repository(git_path)
  2651. from_commit = repo_obj.revparse_single("HEAD").oid.hex
  2652. headers = {"Authorization": "token aaabbbcccddd"}
  2653. args = {"branch": "test123", "from_commit": from_commit}
  2654. output = self.app.post(
  2655. "/api/0/test/git/branch", headers=headers, data=args
  2656. )
  2657. self.assertEqual(output.status_code, 200)
  2658. data = json.loads(output.get_data(as_text=True))
  2659. expected_output = {"message": "Project branch was created"}
  2660. self.assertEqual(data, expected_output)
  2661. self.assertIn("test123", repo_obj.listall_branches())
  2662. class PagureFlaskApiProjectFlagtests(tests.Modeltests):
  2663. """ Tests for the flask API of pagure for flagging commit in project
  2664. """
  2665. def setUp(self):
  2666. """ Set up the environnment, ran before every tests. """
  2667. super(PagureFlaskApiProjectFlagtests, self).setUp()
  2668. tests.create_projects(self.session)
  2669. repo_path = os.path.join(self.path, "repos")
  2670. self.git_path = os.path.join(repo_path, "test.git")
  2671. tests.create_projects_git(repo_path, bare=True)
  2672. tests.add_content_git_repo(self.git_path)
  2673. tests.create_tokens(self.session, project_id=None)
  2674. tests.create_tokens_acl(self.session, "aaabbbcccddd", "commit_flag")
  2675. def test_flag_commit_missing_status(self):
  2676. """ Test flagging a commit with missing precentage. """
  2677. repo_obj = pygit2.Repository(self.git_path)
  2678. commit = repo_obj.revparse_single("HEAD")
  2679. headers = {"Authorization": "token aaabbbcccddd"}
  2680. data = {
  2681. "username": "Jenkins",
  2682. "comment": "Tests passed",
  2683. "url": "http://jenkins.cloud.fedoraproject.org/",
  2684. "uid": "jenkins_build_pagure_100+seed",
  2685. }
  2686. output = self.app.post(
  2687. "/api/0/test/c/%s/flag" % commit.oid.hex,
  2688. headers=headers,
  2689. data=data,
  2690. )
  2691. self.assertEqual(output.status_code, 400)
  2692. data = json.loads(output.get_data(as_text=True))
  2693. expected_output = {
  2694. "error": "Invalid or incomplete input submitted",
  2695. "error_code": "EINVALIDREQ",
  2696. "errors": {"status": ["Not a valid choice"]},
  2697. }
  2698. if self.get_wtforms_version() >= (2, 3):
  2699. expected_output["errors"]["status"] = ["This field is required."]
  2700. self.assertEqual(data, expected_output)
  2701. def test_flag_commit_missing_username(self):
  2702. """ Test flagging a commit with missing username. """
  2703. repo_obj = pygit2.Repository(self.git_path)
  2704. commit = repo_obj.revparse_single("HEAD")
  2705. headers = {"Authorization": "token aaabbbcccddd"}
  2706. data = {
  2707. "percent": 100,
  2708. "comment": "Tests passed",
  2709. "url": "http://jenkins.cloud.fedoraproject.org/",
  2710. "uid": "jenkins_build_pagure_100+seed",
  2711. "status": "success",
  2712. }
  2713. output = self.app.post(
  2714. "/api/0/test/c/%s/flag" % commit.oid.hex,
  2715. headers=headers,
  2716. data=data,
  2717. )
  2718. self.assertEqual(output.status_code, 400)
  2719. data = json.loads(output.get_data(as_text=True))
  2720. expected_output = {
  2721. "error": "Invalid or incomplete input submitted",
  2722. "error_code": "EINVALIDREQ",
  2723. "errors": {"username": ["This field is required."]},
  2724. }
  2725. self.assertEqual(data, expected_output)
  2726. def test_flag_commit_missing_comment(self):
  2727. """ Test flagging a commit with missing comment. """
  2728. repo_obj = pygit2.Repository(self.git_path)
  2729. commit = repo_obj.revparse_single("HEAD")
  2730. headers = {"Authorization": "token aaabbbcccddd"}
  2731. data = {
  2732. "username": "Jenkins",
  2733. "percent": 100,
  2734. "url": "http://jenkins.cloud.fedoraproject.org/",
  2735. "uid": "jenkins_build_pagure_100+seed",
  2736. "status": "success",
  2737. }
  2738. output = self.app.post(
  2739. "/api/0/test/c/%s/flag" % commit.oid.hex,
  2740. headers=headers,
  2741. data=data,
  2742. )
  2743. self.assertEqual(output.status_code, 400)
  2744. data = json.loads(output.get_data(as_text=True))
  2745. expected_output = {
  2746. "error": "Invalid or incomplete input submitted",
  2747. "error_code": "EINVALIDREQ",
  2748. "errors": {"comment": ["This field is required."]},
  2749. }
  2750. self.assertEqual(data, expected_output)
  2751. def test_flag_commit_missing_url(self):
  2752. """ Test flagging a commit with missing url. """
  2753. repo_obj = pygit2.Repository(self.git_path)
  2754. commit = repo_obj.revparse_single("HEAD")
  2755. headers = {"Authorization": "token aaabbbcccddd"}
  2756. data = {
  2757. "username": "Jenkins",
  2758. "percent": 100,
  2759. "comment": "Tests passed",
  2760. "uid": "jenkins_build_pagure_100+seed",
  2761. "status": "success",
  2762. }
  2763. output = self.app.post(
  2764. "/api/0/test/c/%s/flag" % commit.oid.hex,
  2765. headers=headers,
  2766. data=data,
  2767. )
  2768. self.assertEqual(output.status_code, 400)
  2769. data = json.loads(output.get_data(as_text=True))
  2770. expected_output = {
  2771. "error": "Invalid or incomplete input submitted",
  2772. "error_code": "EINVALIDREQ",
  2773. "errors": {"url": ["This field is required."]},
  2774. }
  2775. self.assertEqual(data, expected_output)
  2776. def test_flag_commit_invalid_token(self):
  2777. """ Test flagging a commit with missing info. """
  2778. repo_obj = pygit2.Repository(self.git_path)
  2779. commit = repo_obj.revparse_single("HEAD")
  2780. headers = {"Authorization": "token 123"}
  2781. data = {
  2782. "username": "Jenkins",
  2783. "percent": 100,
  2784. "comment": "Tests passed",
  2785. "url": "http://jenkins.cloud.fedoraproject.org/",
  2786. "uid": "jenkins_build_pagure_100+seed",
  2787. }
  2788. output = self.app.post(
  2789. "/api/0/test/c/%s/flag" % commit.oid.hex,
  2790. headers=headers,
  2791. data=data,
  2792. )
  2793. self.assertEqual(output.status_code, 401)
  2794. data = json.loads(output.get_data(as_text=True))
  2795. self.assertEqual(
  2796. sorted(data.keys()), ["error", "error_code", "errors"]
  2797. )
  2798. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data["error"])
  2799. self.assertEqual(
  2800. pagure.api.APIERROR.EINVALIDTOK.name, data["error_code"]
  2801. )
  2802. self.assertEqual(data["errors"], "Invalid token")
  2803. def test_flag_commit_invalid_status(self):
  2804. """ Test flagging a commit with an invalid status. """
  2805. repo_obj = pygit2.Repository(self.git_path)
  2806. commit = repo_obj.revparse_single("HEAD")
  2807. headers = {"Authorization": "token aaabbbcccddd"}
  2808. data = {
  2809. "username": "Jenkins",
  2810. "percent": 100,
  2811. "comment": "Tests passed",
  2812. "url": "http://jenkins.cloud.fedoraproject.org/",
  2813. "status": "foobar",
  2814. }
  2815. output = self.app.post(
  2816. "/api/0/test/c/%s/flag" % commit.oid.hex,
  2817. headers=headers,
  2818. data=data,
  2819. )
  2820. self.assertEqual(output.status_code, 400)
  2821. data = json.loads(output.get_data(as_text=True))
  2822. self.assertEqual(
  2823. data,
  2824. {
  2825. "errors": {"status": ["Not a valid choice"]},
  2826. "error_code": "EINVALIDREQ",
  2827. "error": "Invalid or incomplete input submitted",
  2828. },
  2829. )
  2830. def test_flag_commit_with_uid(self):
  2831. """ Test flagging a commit with provided uid. """
  2832. repo_obj = pygit2.Repository(self.git_path)
  2833. commit = repo_obj.revparse_single("HEAD")
  2834. headers = {"Authorization": "token aaabbbcccddd"}
  2835. data = {
  2836. "username": "Jenkins",
  2837. "percent": 100,
  2838. "comment": "Tests passed",
  2839. "url": "http://jenkins.cloud.fedoraproject.org/",
  2840. "uid": "jenkins_build_pagure_100+seed",
  2841. "status": "success",
  2842. }
  2843. output = self.app.post(
  2844. "/api/0/test/c/%s/flag" % commit.oid.hex,
  2845. headers=headers,
  2846. data=data,
  2847. )
  2848. self.assertEqual(output.status_code, 200)
  2849. data = json.loads(output.get_data(as_text=True))
  2850. data["flag"]["date_created"] = "1510742565"
  2851. data["flag"]["date_updated"] = "1510742565"
  2852. data["flag"]["commit_hash"] = "62b49f00d489452994de5010565fab81"
  2853. expected_output = {
  2854. "flag": {
  2855. "comment": "Tests passed",
  2856. "commit_hash": "62b49f00d489452994de5010565fab81",
  2857. "date_created": "1510742565",
  2858. "date_updated": "1510742565",
  2859. "percent": 100,
  2860. "status": "success",
  2861. "url": "http://jenkins.cloud.fedoraproject.org/",
  2862. "user": {
  2863. "default_email": "bar@pingou.com",
  2864. "emails": ["bar@pingou.com", "foo@pingou.com"],
  2865. "fullname": "PY C",
  2866. "name": "pingou",
  2867. "url_path": "user/pingou",
  2868. },
  2869. "username": "Jenkins",
  2870. },
  2871. "message": "Flag added",
  2872. "uid": "jenkins_build_pagure_100+seed",
  2873. }
  2874. self.assertEqual(data, expected_output)
  2875. @patch("pagure.lib.notify.send_email")
  2876. def test_flag_commit_without_uid(self, mock_email):
  2877. """ Test flagging a commit with missing info.
  2878. Also ensure notifications aren't sent when they are not asked for.
  2879. """
  2880. repo_obj = pygit2.Repository(self.git_path)
  2881. commit = repo_obj.revparse_single("HEAD")
  2882. headers = {"Authorization": "token aaabbbcccddd"}
  2883. data = {
  2884. "username": "Jenkins",
  2885. "percent": 100,
  2886. "comment": "Tests passed",
  2887. "url": "http://jenkins.cloud.fedoraproject.org/",
  2888. "status": "success",
  2889. }
  2890. output = self.app.post(
  2891. "/api/0/test/c/%s/flag" % commit.oid.hex,
  2892. headers=headers,
  2893. data=data,
  2894. )
  2895. self.assertEqual(output.status_code, 200)
  2896. data = json.loads(output.get_data(as_text=True))
  2897. self.assertNotEqual(data["uid"], "jenkins_build_pagure_100+seed")
  2898. data["flag"]["date_created"] = "1510742565"
  2899. data["flag"]["date_updated"] = "1510742565"
  2900. data["uid"] = "b1de8f80defd4a81afe2e09f39678087"
  2901. expected_output = {
  2902. "flag": {
  2903. "comment": "Tests passed",
  2904. "commit_hash": commit.oid.hex,
  2905. "date_created": "1510742565",
  2906. "date_updated": "1510742565",
  2907. "percent": 100,
  2908. "status": "success",
  2909. "url": "http://jenkins.cloud.fedoraproject.org/",
  2910. "user": {
  2911. "default_email": "bar@pingou.com",
  2912. "emails": ["bar@pingou.com", "foo@pingou.com"],
  2913. "fullname": "PY C",
  2914. "name": "pingou",
  2915. "url_path": "user/pingou",
  2916. },
  2917. "username": "Jenkins",
  2918. },
  2919. "message": "Flag added",
  2920. "uid": "b1de8f80defd4a81afe2e09f39678087",
  2921. }
  2922. self.assertEqual(data, expected_output)
  2923. mock_email.assert_not_called()
  2924. @patch("pagure.lib.notify.send_email")
  2925. def test_flag_commit_with_notification(self, mock_email):
  2926. """ Test flagging a commit with notification enabled. """
  2927. # Enable commit notifications
  2928. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  2929. settings = repo.settings
  2930. settings["notify_on_commit_flag"] = True
  2931. repo.settings = settings
  2932. self.session.add(repo)
  2933. self.session.commit()
  2934. repo_obj = pygit2.Repository(self.git_path)
  2935. commit = repo_obj.revparse_single("HEAD")
  2936. headers = {"Authorization": "token aaabbbcccddd"}
  2937. data = {
  2938. "username": "Jenkins",
  2939. "percent": 100,
  2940. "comment": "Tests passed",
  2941. "url": "http://jenkins.cloud.fedoraproject.org/",
  2942. "status": "success",
  2943. }
  2944. output = self.app.post(
  2945. "/api/0/test/c/%s/flag" % commit.oid.hex,
  2946. headers=headers,
  2947. data=data,
  2948. )
  2949. self.assertEqual(output.status_code, 200)
  2950. data = json.loads(output.get_data(as_text=True))
  2951. self.assertNotEqual(data["uid"], "jenkins_build_pagure_100+seed")
  2952. data["flag"]["date_created"] = "1510742565"
  2953. data["flag"]["date_updated"] = "1510742565"
  2954. data["uid"] = "b1de8f80defd4a81afe2e09f39678087"
  2955. expected_output = {
  2956. "flag": {
  2957. "comment": "Tests passed",
  2958. "commit_hash": commit.oid.hex,
  2959. "date_created": "1510742565",
  2960. "date_updated": "1510742565",
  2961. "percent": 100,
  2962. "status": "success",
  2963. "url": "http://jenkins.cloud.fedoraproject.org/",
  2964. "user": {
  2965. "default_email": "bar@pingou.com",
  2966. "emails": ["bar@pingou.com", "foo@pingou.com"],
  2967. "fullname": "PY C",
  2968. "name": "pingou",
  2969. "url_path": "user/pingou",
  2970. },
  2971. "username": "Jenkins",
  2972. },
  2973. "message": "Flag added",
  2974. "uid": "b1de8f80defd4a81afe2e09f39678087",
  2975. }
  2976. self.assertEqual(data, expected_output)
  2977. mock_email.assert_called_once_with(
  2978. "\nJenkins flagged the commit "
  2979. "`" + commit.oid.hex + "` as success: "
  2980. "Tests passed\n\n"
  2981. "http://localhost.localdomain/test/c/" + commit.oid.hex + "\n",
  2982. "Commit #" + commit.oid.hex + " - Jenkins: success",
  2983. "bar@pingou.com",
  2984. in_reply_to="test-project-1",
  2985. mail_id="test-commit-1-1",
  2986. project_name="test",
  2987. user_from="Jenkins",
  2988. )
  2989. @patch.dict(
  2990. "pagure.config.config",
  2991. {
  2992. "FLAG_STATUSES_LABELS": {
  2993. "pend!": "label-info",
  2994. "succeed!": "label-success",
  2995. "fail!": "label-danger",
  2996. "what?": "label-warning",
  2997. },
  2998. "FLAG_PENDING": "pend!",
  2999. "FLAG_SUCCESS": "succeed!",
  3000. "FLAG_FAILURE": "fail!",
  3001. },
  3002. )
  3003. def test_flag_commit_with_custom_flags(self):
  3004. """ Test flagging when custom flags are set up
  3005. """
  3006. repo_obj = pygit2.Repository(self.git_path)
  3007. commit = repo_obj.revparse_single("HEAD")
  3008. headers = {"Authorization": "token aaabbbcccddd"}
  3009. send_data = {
  3010. "username": "Jenkins",
  3011. "percent": 100,
  3012. "comment": "Tests passed",
  3013. "url": "http://jenkins.cloud.fedoraproject.org/",
  3014. "status": "succeed!",
  3015. }
  3016. output = self.app.post(
  3017. "/api/0/test/c/%s/flag" % commit.oid.hex,
  3018. headers=headers,
  3019. data=send_data,
  3020. )
  3021. self.assertEqual(output.status_code, 200)
  3022. data = json.loads(output.get_data(as_text=True))
  3023. self.assertEqual(data["flag"]["status"], "succeed!")
  3024. # Try invalid flag status
  3025. send_data["status"] = "nooooo...."
  3026. output = self.app.post(
  3027. "/api/0/test/c/%s/flag" % commit.oid.hex,
  3028. headers=headers,
  3029. data=send_data,
  3030. )
  3031. self.assertEqual(output.status_code, 400)
  3032. data = json.loads(output.get_data(as_text=True))
  3033. self.assertEqual(
  3034. data,
  3035. {
  3036. "errors": {"status": ["Not a valid choice"]},
  3037. "error_code": "EINVALIDREQ",
  3038. "error": "Invalid or incomplete input submitted",
  3039. },
  3040. )
  3041. def test_commit_flags(self):
  3042. """ Test retrieving commit flags. """
  3043. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  3044. repo_obj = pygit2.Repository(self.git_path)
  3045. commit = repo_obj.revparse_single("HEAD")
  3046. # test with no flags
  3047. output = self.app.get("/api/0/test/c/%s/flag" % commit.oid.hex)
  3048. self.assertEqual(
  3049. json.loads(output.get_data(as_text=True)),
  3050. {"total_flags": 0, "flags": []},
  3051. )
  3052. self.assertEqual(output.status_code, 200)
  3053. # add some flags and retrieve them
  3054. pagure.lib.query.add_commit_flag(
  3055. session=self.session,
  3056. repo=repo,
  3057. commit_hash=commit.oid.hex,
  3058. username="simple-koji-ci",
  3059. status="pending",
  3060. percent=None,
  3061. comment="Build is running",
  3062. url="https://koji.fp.o/koji...",
  3063. uid="uid",
  3064. user="foo",
  3065. token="aaabbbcccddd",
  3066. )
  3067. pagure.lib.query.add_commit_flag(
  3068. session=self.session,
  3069. repo=repo,
  3070. commit_hash=commit.oid.hex,
  3071. username="complex-koji-ci",
  3072. status="success",
  3073. percent=None,
  3074. comment="Build succeeded",
  3075. url="https://koji.fp.o/koji...",
  3076. uid="uid2",
  3077. user="foo",
  3078. token="aaabbbcccddd",
  3079. )
  3080. self.session.commit()
  3081. output = self.app.get("/api/0/test/c/%s/flag" % commit.oid.hex)
  3082. data = json.loads(output.get_data(as_text=True))
  3083. for f in data["flags"]:
  3084. f["date_created"] = "1510742565"
  3085. f["date_updated"] = "1510742565"
  3086. f["commit_hash"] = "62b49f00d489452994de5010565fab81"
  3087. expected_output = {
  3088. "flags": [
  3089. {
  3090. "comment": "Build is running",
  3091. "commit_hash": "62b49f00d489452994de5010565fab81",
  3092. "date_created": "1510742565",
  3093. "date_updated": "1510742565",
  3094. "percent": None,
  3095. "status": "pending",
  3096. "url": "https://koji.fp.o/koji...",
  3097. "user": {
  3098. "fullname": "foo bar",
  3099. "name": "foo",
  3100. "url_path": "user/foo",
  3101. },
  3102. "username": "simple-koji-ci",
  3103. },
  3104. {
  3105. "comment": "Build succeeded",
  3106. "commit_hash": "62b49f00d489452994de5010565fab81",
  3107. "date_created": "1510742565",
  3108. "date_updated": "1510742565",
  3109. "percent": None,
  3110. "status": "success",
  3111. "url": "https://koji.fp.o/koji...",
  3112. "user": {
  3113. "fullname": "foo bar",
  3114. "name": "foo",
  3115. "url_path": "user/foo",
  3116. },
  3117. "username": "complex-koji-ci",
  3118. },
  3119. ],
  3120. "total_flags": 2,
  3121. }
  3122. self.assertEqual(data, expected_output)
  3123. class PagureFlaskApiProjectModifyAclTests(tests.Modeltests):
  3124. """ Tests for the flask API of pagure for modifying ACLs in a project
  3125. """
  3126. maxDiff = None
  3127. def setUp(self):
  3128. """ Set up the environnment, ran before every tests. """
  3129. super(PagureFlaskApiProjectModifyAclTests, self).setUp()
  3130. tests.create_projects(self.session)
  3131. tests.create_tokens(self.session, project_id=None)
  3132. tests.create_tokens_acl(self.session, "aaabbbcccddd", "modify_project")
  3133. project = pagure.lib.query._get_project(self.session, "test")
  3134. self.assertEquals(
  3135. project.access_users, {"admin": [], "commit": [], "ticket": []}
  3136. )
  3137. def test_api_modify_acls_no_project(self):
  3138. """ Test the api_modify_acls method of the flask api when the project
  3139. doesn't exist """
  3140. headers = {"Authorization": "token aaabbbcccddd"}
  3141. data = {"user_type": "user", "name": "bar", "acl": "commit"}
  3142. output = self.app.post(
  3143. "/api/0/test12345123/git/modifyacls", headers=headers, data=data
  3144. )
  3145. self.assertEqual(output.status_code, 404)
  3146. data = json.loads(output.get_data(as_text=True))
  3147. expected_output = {
  3148. "error_code": "ENOPROJECT",
  3149. "error": "Project not found",
  3150. }
  3151. self.assertEqual(data, expected_output)
  3152. def test_api_modify_acls_no_user(self):
  3153. """ Test the api_modify_acls method of the flask api when the user
  3154. doesn't exist """
  3155. headers = {"Authorization": "token aaabbbcccddd"}
  3156. data = {"user_type": "user", "name": "nosuchuser", "acl": "commit"}
  3157. output = self.app.post(
  3158. "/api/0/test/git/modifyacls", headers=headers, data=data
  3159. )
  3160. self.assertEqual(output.status_code, 404)
  3161. data = json.loads(output.get_data(as_text=True))
  3162. expected_output = {
  3163. "error": "No such user found",
  3164. "error_code": "ENOUSER",
  3165. }
  3166. self.assertEqual(data, expected_output)
  3167. def test_api_modify_acls_no_group(self):
  3168. """ Test the api_modify_acls method of the flask api when the group
  3169. doesn't exist """
  3170. headers = {"Authorization": "token aaabbbcccddd"}
  3171. data = {"user_type": "group", "name": "nosuchgroup", "acl": "commit"}
  3172. output = self.app.post(
  3173. "/api/0/test/git/modifyacls", headers=headers, data=data
  3174. )
  3175. self.assertEqual(output.status_code, 404)
  3176. data = json.loads(output.get_data(as_text=True))
  3177. expected_output = {
  3178. "error": "Group not found",
  3179. "error_code": "ENOGROUP",
  3180. }
  3181. self.assertEqual(data, expected_output)
  3182. def test_api_modify_acls_no_permission(self):
  3183. """ Test the api_modify_acls method of the flask api when the user
  3184. doesn't have permissions """
  3185. item = pagure.lib.model.Token(
  3186. id="foo_token2",
  3187. user_id=2,
  3188. project_id=None,
  3189. expiration=datetime.datetime.utcnow()
  3190. + datetime.timedelta(days=30),
  3191. )
  3192. self.session.add(item)
  3193. self.session.commit()
  3194. tests.create_tokens_acl(self.session, "foo_token2", "modify_project")
  3195. headers = {"Authorization": "token foo_token2"}
  3196. data = {"user_type": "user", "name": "foo", "acl": "commit"}
  3197. output = self.app.post(
  3198. "/api/0/test/git/modifyacls", headers=headers, data=data
  3199. )
  3200. self.assertEqual(output.status_code, 401)
  3201. data = json.loads(output.get_data(as_text=True))
  3202. expected_output = {
  3203. "error": "You are not allowed to modify this project",
  3204. "error_code": "EMODIFYPROJECTNOTALLOWED",
  3205. }
  3206. self.assertEqual(data, expected_output)
  3207. def test_api_modify_acls_neither_user_nor_group(self):
  3208. """ Test the api_modify_acls method of the flask api when neither
  3209. user nor group was set """
  3210. headers = {"Authorization": "token aaabbbcccddd"}
  3211. data = {"acl": "commit"}
  3212. output = self.app.post(
  3213. "/api/0/test/git/modifyacls", headers=headers, data=data
  3214. )
  3215. self.assertEqual(output.status_code, 400)
  3216. data = json.loads(output.get_data(as_text=True))
  3217. expected_output = {
  3218. "error": "Invalid or incomplete input submitted",
  3219. "error_code": "EINVALIDREQ",
  3220. "errors": {
  3221. "name": ["This field is required."],
  3222. "user_type": ["Not a valid choice"],
  3223. },
  3224. }
  3225. if self.get_wtforms_version() >= (2, 3):
  3226. expected_output["errors"]["user_type"] = [
  3227. "This field is required."
  3228. ]
  3229. self.assertEqual(data, expected_output)
  3230. def test_api_modify_acls_invalid_acl(self):
  3231. """ Test the api_modify_acls method of the flask api when the ACL
  3232. doesn't exist. Must be one of ticket, commit or admin. """
  3233. headers = {"Authorization": "token aaabbbcccddd"}
  3234. data = {"user_type": "user", "name": "bar", "acl": "invalidacl"}
  3235. output = self.app.post(
  3236. "/api/0/test/git/modifyacls", headers=headers, data=data
  3237. )
  3238. self.assertEqual(output.status_code, 400)
  3239. data = json.loads(output.get_data(as_text=True))
  3240. expected_output = {
  3241. "error": "Invalid or incomplete input submitted",
  3242. "error_code": "EINVALIDREQ",
  3243. "errors": {"acl": ["Not a valid choice"]},
  3244. }
  3245. self.assertEqual(data, expected_output)
  3246. def test_api_modify_acls_user(self):
  3247. """ Test the api_modify_acls method of the flask api for
  3248. setting an ACL for a user. """
  3249. headers = {"Authorization": "token aaabbbcccddd"}
  3250. data = {"user_type": "user", "name": "foo", "acl": "commit"}
  3251. output = self.app.post(
  3252. "/api/0/test/git/modifyacls", headers=headers, data=data
  3253. )
  3254. self.assertEqual(output.status_code, 200)
  3255. data = json.loads(output.get_data(as_text=True))
  3256. data["date_created"] = "1510742565"
  3257. data["date_modified"] = "1510742566"
  3258. expected_output = {
  3259. "access_groups": {"admin": [], "commit": [], "ticket": []},
  3260. "access_users": {
  3261. "admin": [],
  3262. "commit": ["foo"],
  3263. "owner": ["pingou"],
  3264. "ticket": [],
  3265. },
  3266. "close_status": [
  3267. "Invalid",
  3268. "Insufficient data",
  3269. "Fixed",
  3270. "Duplicate",
  3271. ],
  3272. "custom_keys": [],
  3273. "date_created": "1510742565",
  3274. "date_modified": "1510742566",
  3275. "description": "test project #1",
  3276. "fullname": "test",
  3277. "id": 1,
  3278. "milestones": {},
  3279. "name": "test",
  3280. "namespace": None,
  3281. "parent": None,
  3282. "priorities": {},
  3283. "tags": [],
  3284. "url_path": "test",
  3285. "user": {
  3286. "fullname": "PY C",
  3287. "name": "pingou",
  3288. "url_path": "user/pingou",
  3289. },
  3290. }
  3291. self.assertEqual(data, expected_output)
  3292. def test_api_modify_acls_group(self):
  3293. """ Test the api_modify_acls method of the flask api for
  3294. setting an ACL for a group. """
  3295. headers = {"Authorization": "token aaabbbcccddd"}
  3296. # Create a group
  3297. msg = pagure.lib.query.add_group(
  3298. self.session,
  3299. group_name="baz",
  3300. display_name="baz group",
  3301. description=None,
  3302. group_type="bar",
  3303. user="foo",
  3304. is_admin=False,
  3305. blacklist=[],
  3306. )
  3307. self.session.commit()
  3308. self.assertEqual(msg, "User `foo` added to the group `baz`.")
  3309. data = {"user_type": "group", "name": "baz", "acl": "ticket"}
  3310. output = self.app.post(
  3311. "/api/0/test/git/modifyacls", headers=headers, data=data
  3312. )
  3313. self.assertEqual(output.status_code, 200)
  3314. data = json.loads(output.get_data(as_text=True))
  3315. data["date_created"] = "1510742565"
  3316. data["date_modified"] = "1510742566"
  3317. expected_output = {
  3318. "access_groups": {"admin": [], "commit": [], "ticket": ["baz"]},
  3319. "access_users": {
  3320. "admin": [],
  3321. "commit": [],
  3322. "owner": ["pingou"],
  3323. "ticket": [],
  3324. },
  3325. "close_status": [
  3326. "Invalid",
  3327. "Insufficient data",
  3328. "Fixed",
  3329. "Duplicate",
  3330. ],
  3331. "custom_keys": [],
  3332. "date_created": "1510742565",
  3333. "date_modified": "1510742566",
  3334. "description": "test project #1",
  3335. "fullname": "test",
  3336. "id": 1,
  3337. "milestones": {},
  3338. "name": "test",
  3339. "namespace": None,
  3340. "parent": None,
  3341. "priorities": {},
  3342. "tags": [],
  3343. "url_path": "test",
  3344. "user": {
  3345. "fullname": "PY C",
  3346. "name": "pingou",
  3347. "url_path": "user/pingou",
  3348. },
  3349. }
  3350. self.assertEqual(data, expected_output)
  3351. def test_api_modify_acls_no_acl(self):
  3352. """ Test the api_modify_acls method of the flask api when no ACL
  3353. are specified. """
  3354. headers = {"Authorization": "token aaabbbcccddd"}
  3355. project = pagure.lib.query._get_project(self.session, "test")
  3356. self.assertEquals(
  3357. project.access_users, {"admin": [], "commit": [], "ticket": []}
  3358. )
  3359. data = {"user_type": "user", "name": "foo"}
  3360. output = self.app.post(
  3361. "/api/0/test/git/modifyacls", headers=headers, data=data
  3362. )
  3363. self.assertEqual(output.status_code, 400)
  3364. data = json.loads(output.get_data(as_text=True))
  3365. expected_output = {
  3366. "error": "Invalid or incomplete input submitted",
  3367. "error_code": "EINVALIDREQ",
  3368. "errors": "User does not have any access on the repo",
  3369. }
  3370. self.assertEqual(data, expected_output)
  3371. def test_api_modify_acls_remove_own_acl_no_access(self):
  3372. """ Test the api_modify_acls method of the flask api when no ACL
  3373. are specified, so the user tries to remove their own access but the
  3374. user is the project owner. """
  3375. headers = {"Authorization": "token aaabbbcccddd"}
  3376. data = {"user_type": "user", "name": "pingou"}
  3377. output = self.app.post(
  3378. "/api/0/test/git/modifyacls", headers=headers, data=data
  3379. )
  3380. self.assertEqual(output.status_code, 400)
  3381. data = json.loads(output.get_data(as_text=True))
  3382. expected_output = {
  3383. "error": "Invalid or incomplete input submitted",
  3384. "error_code": "EINVALIDREQ",
  3385. "errors": "User does not have any access on the repo",
  3386. }
  3387. self.assertEqual(data, expected_output)
  3388. def test_api_modify_acls_remove_own_acl_(self):
  3389. """ Test the api_modify_acls method of the flask api when no ACL
  3390. are specified, so the user tries to remove their own access but the
  3391. user is the project owner. """
  3392. # Add the user `foo` to the project
  3393. self.test_api_modify_acls_user()
  3394. # Ensure `foo` was properly added:
  3395. project = pagure.lib.query._get_project(self.session, "test")
  3396. user_foo = pagure.lib.query.search_user(self.session, username="foo")
  3397. self.assertEquals(
  3398. project.access_users,
  3399. {"admin": [], "commit": [user_foo], "ticket": []},
  3400. )
  3401. # Create an API token for `foo` for the project `test`
  3402. item = pagure.lib.model.Token(
  3403. id="foo_test_token",
  3404. user_id=2, # foo
  3405. project_id=1, # test
  3406. expiration=datetime.datetime.utcnow()
  3407. + datetime.timedelta(days=10),
  3408. )
  3409. self.session.add(item)
  3410. self.session.commit()
  3411. tests.create_tokens_acl(
  3412. self.session, "foo_test_token", "modify_project"
  3413. )
  3414. headers = {"Authorization": "token foo_test_token"}
  3415. data = {"user_type": "user", "name": "foo"}
  3416. output = self.app.post(
  3417. "/api/0/test/git/modifyacls", headers=headers, data=data
  3418. )
  3419. self.assertEqual(output.status_code, 200)
  3420. data = json.loads(output.get_data(as_text=True))
  3421. data["date_created"] = "1510742565"
  3422. data["date_modified"] = "1510742566"
  3423. expected_output = {
  3424. "access_groups": {"admin": [], "commit": [], "ticket": []},
  3425. "access_users": {
  3426. "admin": [],
  3427. "commit": [],
  3428. "owner": ["pingou"],
  3429. "ticket": [],
  3430. },
  3431. "close_status": [
  3432. "Invalid",
  3433. "Insufficient data",
  3434. "Fixed",
  3435. "Duplicate",
  3436. ],
  3437. "custom_keys": [],
  3438. "date_created": "1510742565",
  3439. "date_modified": "1510742566",
  3440. "description": "test project #1",
  3441. "fullname": "test",
  3442. "id": 1,
  3443. "milestones": {},
  3444. "name": "test",
  3445. "namespace": None,
  3446. "parent": None,
  3447. "priorities": {},
  3448. "tags": [],
  3449. "url_path": "test",
  3450. "user": {
  3451. "fullname": "PY C",
  3452. "name": "pingou",
  3453. "url_path": "user/pingou",
  3454. },
  3455. }
  3456. self.assertEqual(data, expected_output)
  3457. # Ensure `foo` was properly removed
  3458. self.session = pagure.lib.query.create_session(self.dbpath)
  3459. project = pagure.lib.query._get_project(self.session, "test")
  3460. self.assertEquals(
  3461. project.access_users, {"admin": [], "commit": [], "ticket": []}
  3462. )
  3463. def test_api_modify_acls_remove_someone_else_acl(self):
  3464. """ Test the api_modify_acls method of the flask api an admin tries
  3465. to remove access from someone else. """
  3466. # Add the user `foo` to the project
  3467. self.test_api_modify_acls_user()
  3468. # Ensure `foo` was properly added:
  3469. project = pagure.lib.query._get_project(self.session, "test")
  3470. user_foo = pagure.lib.query.search_user(self.session, username="foo")
  3471. self.assertEquals(
  3472. project.access_users,
  3473. {"admin": [], "commit": [user_foo], "ticket": []},
  3474. )
  3475. headers = {"Authorization": "token aaabbbcccddd"}
  3476. data = {"user_type": "user", "name": "foo"}
  3477. output = self.app.post(
  3478. "/api/0/test/git/modifyacls", headers=headers, data=data
  3479. )
  3480. self.assertEqual(output.status_code, 200)
  3481. data = json.loads(output.get_data(as_text=True))
  3482. data["date_created"] = "1510742565"
  3483. data["date_modified"] = "1510742566"
  3484. expected_output = {
  3485. "access_groups": {"admin": [], "commit": [], "ticket": []},
  3486. "access_users": {
  3487. "admin": [],
  3488. "commit": [],
  3489. "owner": ["pingou"],
  3490. "ticket": [],
  3491. },
  3492. "close_status": [
  3493. "Invalid",
  3494. "Insufficient data",
  3495. "Fixed",
  3496. "Duplicate",
  3497. ],
  3498. "custom_keys": [],
  3499. "date_created": "1510742565",
  3500. "date_modified": "1510742566",
  3501. "description": "test project #1",
  3502. "fullname": "test",
  3503. "id": 1,
  3504. "milestones": {},
  3505. "name": "test",
  3506. "namespace": None,
  3507. "parent": None,
  3508. "priorities": {},
  3509. "tags": [],
  3510. "url_path": "test",
  3511. "user": {
  3512. "fullname": "PY C",
  3513. "name": "pingou",
  3514. "url_path": "user/pingou",
  3515. },
  3516. }
  3517. self.assertEqual(data, expected_output)
  3518. # Ensure `foo` was properly removed
  3519. self.session = pagure.lib.query.create_session(self.dbpath)
  3520. project = pagure.lib.query._get_project(self.session, "test")
  3521. self.assertEquals(
  3522. project.access_users, {"admin": [], "commit": [], "ticket": []}
  3523. )
  3524. class PagureFlaskApiProjectOptionsTests(tests.Modeltests):
  3525. """ Tests for the flask API of pagure for modifying options ofs a project
  3526. """
  3527. maxDiff = None
  3528. def setUp(self):
  3529. """ Set up the environnment, ran before every tests. """
  3530. super(PagureFlaskApiProjectOptionsTests, self).setUp()
  3531. tests.create_projects(self.session)
  3532. tests.create_tokens(self.session, project_id=None)
  3533. tests.create_tokens_acl(self.session, "aaabbbcccddd", "modify_project")
  3534. project = pagure.lib.query._get_project(self.session, "test")
  3535. self.assertEquals(
  3536. project.access_users, {"admin": [], "commit": [], "ticket": []}
  3537. )
  3538. def test_api_get_project_options_wrong_project(self):
  3539. """ Test accessing api_get_project_options w/o auth header. """
  3540. headers = {"Authorization": "token aaabbbcccddd"}
  3541. output = self.app.get("/api/0/unknown/options", headers=headers)
  3542. self.assertEqual(output.status_code, 404)
  3543. data = json.loads(output.get_data(as_text=True))
  3544. self.assertEqual(
  3545. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  3546. )
  3547. def test_api_get_project_options_wo_header(self):
  3548. """ Test accessing api_get_project_options w/o auth header. """
  3549. output = self.app.get("/api/0/test/options")
  3550. self.assertEqual(output.status_code, 401)
  3551. data = json.loads(output.get_data(as_text=True))
  3552. self.assertEqual(
  3553. data,
  3554. {
  3555. "error": "Invalid or expired token. Please visit "
  3556. "http://localhost.localdomain/settings#nav-api-tab to get "
  3557. "or renew your API token.",
  3558. "error_code": "EINVALIDTOK",
  3559. "errors": "Invalid token",
  3560. },
  3561. )
  3562. def test_api_get_project_options_w_header(self):
  3563. """ Test accessing api_get_project_options w/ auth header. """
  3564. headers = {"Authorization": "token aaabbbcccddd"}
  3565. output = self.app.get("/api/0/test/options", headers=headers)
  3566. self.assertEqual(output.status_code, 200)
  3567. data = json.loads(output.get_data(as_text=True))
  3568. self.assertEqual(
  3569. data,
  3570. {
  3571. "settings": {
  3572. "Enforce_signed-off_commits_in_pull-request": False,
  3573. "Minimum_score_to_merge_pull-request": -1,
  3574. "Only_assignee_can_merge_pull-request": False,
  3575. "Web-hooks": None,
  3576. "always_merge": False,
  3577. "disable_non_fast-forward_merges": False,
  3578. "fedmsg_notifications": True,
  3579. "issue_tracker": True,
  3580. "issue_tracker_read_only": False,
  3581. "issues_default_to_private": False,
  3582. "mqtt_notifications": True,
  3583. "notify_on_commit_flag": False,
  3584. "notify_on_pull-request_flag": False,
  3585. "open_metadata_access_to_all": False,
  3586. "project_documentation": False,
  3587. "pull_request_access_only": False,
  3588. "pull_requests": True,
  3589. "stomp_notifications": True,
  3590. },
  3591. "status": "ok",
  3592. },
  3593. )
  3594. def test_api_modify_project_options_wrong_project(self):
  3595. """ Test accessing api_modify_project_options w/ an invalid project.
  3596. """
  3597. headers = {"Authorization": "token aaabbbcccddd"}
  3598. output = self.app.post(
  3599. "/api/0/unknown/options/update", headers=headers
  3600. )
  3601. self.assertEqual(output.status_code, 404)
  3602. data = json.loads(output.get_data(as_text=True))
  3603. self.assertEqual(
  3604. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  3605. )
  3606. def test_api_modify_project_options_wo_header(self):
  3607. """ Test accessing api_modify_project_options w/o auth header. """
  3608. output = self.app.post("/api/0/test/options/update")
  3609. self.assertEqual(output.status_code, 401)
  3610. data = json.loads(output.get_data(as_text=True))
  3611. self.assertEqual(
  3612. data,
  3613. {
  3614. "error": "Invalid or expired token. Please visit "
  3615. "http://localhost.localdomain/settings#nav-api-tab to get "
  3616. "or renew your API token.",
  3617. "error_code": "EINVALIDTOK",
  3618. "errors": "Invalid token",
  3619. },
  3620. )
  3621. def test_api_modify_project_options_no_data(self):
  3622. """ Test accessing api_modify_project_options w/ auth header. """
  3623. # check before
  3624. headers = {"Authorization": "token aaabbbcccddd"}
  3625. output = self.app.get("/api/0/test/options", headers=headers)
  3626. self.assertEqual(output.status_code, 200)
  3627. before = json.loads(output.get_data(as_text=True))
  3628. self.assertEqual(
  3629. before,
  3630. {
  3631. "settings": {
  3632. "Enforce_signed-off_commits_in_pull-request": False,
  3633. "Minimum_score_to_merge_pull-request": -1,
  3634. "Only_assignee_can_merge_pull-request": False,
  3635. "Web-hooks": None,
  3636. "always_merge": False,
  3637. "disable_non_fast-forward_merges": False,
  3638. "fedmsg_notifications": True,
  3639. "issue_tracker": True,
  3640. "issue_tracker_read_only": False,
  3641. "issues_default_to_private": False,
  3642. "mqtt_notifications": True,
  3643. "notify_on_commit_flag": False,
  3644. "notify_on_pull-request_flag": False,
  3645. "open_metadata_access_to_all": False,
  3646. "project_documentation": False,
  3647. "pull_request_access_only": False,
  3648. "pull_requests": True,
  3649. "stomp_notifications": True,
  3650. },
  3651. "status": "ok",
  3652. },
  3653. )
  3654. # Do not update anything
  3655. data = {}
  3656. output = self.app.post(
  3657. "/api/0/test/options/update", headers=headers, data=data
  3658. )
  3659. self.assertEqual(output.status_code, 200)
  3660. data = json.loads(output.get_data(as_text=True))
  3661. self.assertEqual(
  3662. data, {"message": "No settings to change", "status": "ok"}
  3663. )
  3664. # check after
  3665. headers = {"Authorization": "token aaabbbcccddd"}
  3666. output = self.app.get("/api/0/test/options", headers=headers)
  3667. self.assertEqual(output.status_code, 200)
  3668. after = json.loads(output.get_data(as_text=True))
  3669. self.assertEqual(after, before)
  3670. def test_api_modify_project_options(self):
  3671. """ Test accessing api_modify_project_options w/ auth header. """
  3672. # check before
  3673. headers = {"Authorization": "token aaabbbcccddd"}
  3674. output = self.app.get("/api/0/test/options", headers=headers)
  3675. self.assertEqual(output.status_code, 200)
  3676. before = json.loads(output.get_data(as_text=True))
  3677. self.assertEqual(
  3678. before,
  3679. {
  3680. "settings": {
  3681. "Enforce_signed-off_commits_in_pull-request": False,
  3682. "Minimum_score_to_merge_pull-request": -1,
  3683. "Only_assignee_can_merge_pull-request": False,
  3684. "Web-hooks": None,
  3685. "always_merge": False,
  3686. "disable_non_fast-forward_merges": False,
  3687. "fedmsg_notifications": True,
  3688. "issue_tracker": True,
  3689. "issue_tracker_read_only": False,
  3690. "issues_default_to_private": False,
  3691. "mqtt_notifications": True,
  3692. "notify_on_commit_flag": False,
  3693. "notify_on_pull-request_flag": False,
  3694. "open_metadata_access_to_all": False,
  3695. "project_documentation": False,
  3696. "pull_request_access_only": False,
  3697. "pull_requests": True,
  3698. "stomp_notifications": True,
  3699. },
  3700. "status": "ok",
  3701. },
  3702. )
  3703. # Update: `issues_default_to_private`.
  3704. data = {"issues_default_to_private": True}
  3705. output = self.app.post(
  3706. "/api/0/test/options/update", headers=headers, data=data
  3707. )
  3708. self.assertEqual(output.status_code, 200)
  3709. data = json.loads(output.get_data(as_text=True))
  3710. self.assertEqual(
  3711. data,
  3712. {
  3713. "message": "Edited successfully settings of repo: test",
  3714. "status": "ok",
  3715. },
  3716. )
  3717. # check after
  3718. headers = {"Authorization": "token aaabbbcccddd"}
  3719. output = self.app.get("/api/0/test/options", headers=headers)
  3720. self.assertEqual(output.status_code, 200)
  3721. after = json.loads(output.get_data(as_text=True))
  3722. self.assertNotEqual(before, after)
  3723. before["settings"]["issues_default_to_private"] = True
  3724. self.assertEqual(after, before)
  3725. class PagureFlaskApiProjectCreateAPITokenTests(tests.Modeltests):
  3726. """ Tests for the flask API of pagure for creating user project API token
  3727. """
  3728. maxDiff = None
  3729. def setUp(self):
  3730. """ Set up the environnment, ran before every tests. """
  3731. super(PagureFlaskApiProjectCreateAPITokenTests, self).setUp()
  3732. tests.create_projects(self.session)
  3733. tests.create_tokens(self.session, project_id=None)
  3734. tests.create_tokens_acl(self.session, "aaabbbcccddd", "modify_project")
  3735. def test_api_createapitoken_as_owner(self):
  3736. """ Test accessing api_project_create_token as owner. """
  3737. headers = {"Authorization": "token aaabbbcccddd"}
  3738. project = pagure.lib.query._get_project(self.session, "test")
  3739. tdescription = "my new token"
  3740. # Call the api with pingou user token and verify content
  3741. data = {
  3742. "description": tdescription,
  3743. "acls": ["pull_request_merge", "pull_request_comment"],
  3744. }
  3745. output = self.app.post(
  3746. "/api/0/test/token/new", headers=headers, data=data
  3747. )
  3748. self.assertEqual(output.status_code, 200)
  3749. data = json.loads(output.get_data(as_text=True))
  3750. tid = pagure.lib.query.search_token(
  3751. self.session, None, description=tdescription
  3752. )[0].id
  3753. self.assertEqual(
  3754. data, {"token": {"description": tdescription, "id": tid}}
  3755. )
  3756. # Create a second token but with faulty acl
  3757. # Call the api with pingou user token and error code
  3758. data = {"description": tdescription, "acl": ["foo", "bar"]}
  3759. output = self.app.post(
  3760. "/api/0/test/token/new", headers=headers, data=data
  3761. )
  3762. self.assertEqual(output.status_code, 400)
  3763. def test_api_createapitoken_as_admin(self):
  3764. """ Test accessing api_project_create_token as admin. """
  3765. project = pagure.lib.query._get_project(self.session, "test")
  3766. # Set the foo user as test project admin
  3767. pagure.lib.query.add_user_to_project(
  3768. self.session,
  3769. project,
  3770. new_user="foo",
  3771. user="pingou",
  3772. access="admin",
  3773. )
  3774. self.session.commit()
  3775. # Create modify_project token for foo user
  3776. exp_date = datetime.date.today() + datetime.timedelta(days=300)
  3777. token = pagure.lib.query.add_token_to_user(
  3778. self.session,
  3779. project=None,
  3780. acls=["modify_project"],
  3781. username="foo",
  3782. expiration_date=exp_date,
  3783. )
  3784. # Call the connector with foo user token and verify content
  3785. headers = {"Authorization": "token %s" % token.id}
  3786. tdescription = "my new token"
  3787. # Call the api with pingou user token and verify content
  3788. data = {
  3789. "description": tdescription,
  3790. "acls": ["pull_request_merge", "pull_request_comment"],
  3791. }
  3792. output = self.app.post(
  3793. "/api/0/test/token/new", headers=headers, data=data
  3794. )
  3795. self.assertEqual(output.status_code, 200)
  3796. data = json.loads(output.get_data(as_text=True))
  3797. tid = pagure.lib.query.search_token(
  3798. self.session, None, user="foo", description=tdescription
  3799. )[0].id
  3800. self.assertEqual(
  3801. data, {"token": {"description": tdescription, "id": tid}}
  3802. )
  3803. def test_api_createapitoken_as_unauthorized(self):
  3804. """ Test accessing api_project_create_token as project admin
  3805. but with unauthorized token ACL.
  3806. """
  3807. project = pagure.lib.query._get_project(self.session, "test")
  3808. # Set the foo user as test project admin
  3809. pagure.lib.query.add_user_to_project(
  3810. self.session,
  3811. project,
  3812. new_user="foo",
  3813. user="pingou",
  3814. access="admin",
  3815. )
  3816. self.session.commit()
  3817. # Create modify_project token for foo user
  3818. exp_date = datetime.date.today() + datetime.timedelta(days=300)
  3819. pagure.lib.query.add_token_to_user(
  3820. self.session,
  3821. project=None,
  3822. acls=["create_branch"],
  3823. username="foo",
  3824. expiration_date=exp_date,
  3825. )
  3826. mtoken = pagure.lib.query.search_token(
  3827. self.session, ["create_branch"], user="foo"
  3828. )[0]
  3829. # Call the connector with foo user token and verify content
  3830. headers = {"Authorization": "token %s" % mtoken.id}
  3831. tdescription = "my new token"
  3832. # Call the api with pingou user token and verify content
  3833. data = {
  3834. "description": tdescription,
  3835. "acls": ["pull_request_merge", "pull_request_comment"],
  3836. }
  3837. output = self.app.post(
  3838. "/api/0/test/token/new", headers=headers, data=data
  3839. )
  3840. self.assertEqual(output.status_code, 401)
  3841. def test_api_createapitoken_as_unauthorized_2(self):
  3842. """ Test accessing api_project_create_token as project user
  3843. with unauthorized token ACL.
  3844. """
  3845. project = pagure.lib.query._get_project(self.session, "test")
  3846. # Set the foo user as test project admin
  3847. pagure.lib.query.add_user_to_project(
  3848. self.session,
  3849. project,
  3850. new_user="foo",
  3851. user="pingou",
  3852. access="commit",
  3853. )
  3854. self.session.commit()
  3855. # Create modify_project token for foo user
  3856. exp_date = datetime.date.today() + datetime.timedelta(days=300)
  3857. pagure.lib.query.add_token_to_user(
  3858. self.session,
  3859. project=None,
  3860. acls=["modify_project"],
  3861. username="foo",
  3862. expiration_date=exp_date,
  3863. )
  3864. mtoken = pagure.lib.query.search_token(
  3865. self.session, ["modify_project"], user="foo"
  3866. )[0]
  3867. # Call the connector with foo user token and verify content
  3868. headers = {"Authorization": "token %s" % mtoken.id}
  3869. tdescription = "my new token"
  3870. # Call the api with pingou user token and verify content
  3871. data = {
  3872. "description": tdescription,
  3873. "acls": ["pull_request_merge", "pull_request_comment"],
  3874. }
  3875. output = self.app.post(
  3876. "/api/0/test/token/new", headers=headers, data=data
  3877. )
  3878. self.assertEqual(output.status_code, 401)
  3879. class PagureFlaskApiProjectConnectorTests(tests.Modeltests):
  3880. """ Tests for the flask API of pagure for getting connector of a project
  3881. """
  3882. maxDiff = None
  3883. def setUp(self):
  3884. """ Set up the environnment, ran before every tests. """
  3885. super(PagureFlaskApiProjectConnectorTests, self).setUp()
  3886. tests.create_projects(self.session)
  3887. tests.create_tokens(self.session, project_id=None)
  3888. tests.create_tokens_acl(self.session, "aaabbbcccddd", "modify_project")
  3889. def test_api_get_project_connector_as_owner(self):
  3890. """ Test accessing api_get_project_connector as project owner. """
  3891. project = pagure.lib.query._get_project(self.session, "test")
  3892. # Create witness project Token for pingou user
  3893. exp_date = datetime.date.today() + datetime.timedelta(days=300)
  3894. pagure.lib.query.add_token_to_user(
  3895. self.session,
  3896. project=project,
  3897. acls=["pull_request_merge"],
  3898. username="pingou",
  3899. expiration_date=exp_date,
  3900. )
  3901. ctokens = pagure.lib.query.search_token(
  3902. self.session, ["pull_request_merge"], user="pingou"
  3903. )
  3904. self.assertEqual(len(ctokens), 1)
  3905. # Call the connector with pingou user token and verify content
  3906. headers = {"Authorization": "token aaabbbcccddd"}
  3907. output = self.app.get("/api/0/test/connector", headers=headers)
  3908. self.assertEqual(output.status_code, 200)
  3909. data = json.loads(output.get_data(as_text=True))
  3910. self.assertEqual(
  3911. data,
  3912. {
  3913. "connector": {
  3914. "hook_token": project.hook_token,
  3915. "api_tokens": [
  3916. {
  3917. "description": t.description,
  3918. "id": t.id,
  3919. "expired": False,
  3920. }
  3921. for t in ctokens
  3922. ],
  3923. },
  3924. "status": "ok",
  3925. },
  3926. )
  3927. def test_api_get_project_connector_as_admin(self):
  3928. """ Test accessing api_get_project_connector as project admin """
  3929. project = pagure.lib.query._get_project(self.session, "test")
  3930. # Set the foo user as test project admin
  3931. pagure.lib.query.add_user_to_project(
  3932. self.session,
  3933. project,
  3934. new_user="foo",
  3935. user="pingou",
  3936. access="admin",
  3937. )
  3938. self.session.commit()
  3939. # Create modify_project token for foo user
  3940. exp_date = datetime.date.today() + datetime.timedelta(days=300)
  3941. pagure.lib.query.add_token_to_user(
  3942. self.session,
  3943. project=None,
  3944. acls=["modify_project"],
  3945. username="foo",
  3946. expiration_date=exp_date,
  3947. )
  3948. mtoken = pagure.lib.query.search_token(
  3949. self.session, ["modify_project"], user="foo"
  3950. )[0]
  3951. # Create witness project Token for foo user
  3952. exp_date = datetime.date.today() + datetime.timedelta(days=300)
  3953. pagure.lib.query.add_token_to_user(
  3954. self.session,
  3955. project=project,
  3956. acls=["pull_request_merge"],
  3957. username="foo",
  3958. expiration_date=exp_date,
  3959. )
  3960. ctokens = pagure.lib.query.search_token(
  3961. self.session, ["pull_request_merge"], user="foo"
  3962. )
  3963. self.assertEqual(len(ctokens), 1)
  3964. # Call the connector with foo user token and verify content
  3965. headers = {"Authorization": "token %s" % mtoken.id}
  3966. output = self.app.get("/api/0/test/connector", headers=headers)
  3967. self.assertEqual(output.status_code, 200)
  3968. data = json.loads(output.get_data(as_text=True))
  3969. self.assertEqual(
  3970. data,
  3971. {
  3972. "connector": {
  3973. "hook_token": project.hook_token,
  3974. "api_tokens": [
  3975. {
  3976. "description": t.description,
  3977. "id": t.id,
  3978. "expired": False,
  3979. }
  3980. for t in ctokens
  3981. ],
  3982. },
  3983. "status": "ok",
  3984. },
  3985. )
  3986. def test_api_get_project_connector_as_unauthorized(self):
  3987. """ Test accessing api_get_project_connector as project admin
  3988. but with unauthorized token ACL
  3989. """
  3990. project = pagure.lib.query._get_project(self.session, "test")
  3991. # Set the foo user as test project admin
  3992. pagure.lib.query.add_user_to_project(
  3993. self.session,
  3994. project,
  3995. new_user="foo",
  3996. user="pingou",
  3997. access="admin",
  3998. )
  3999. self.session.commit()
  4000. # Create modify_project token for foo user
  4001. exp_date = datetime.date.today() + datetime.timedelta(days=300)
  4002. pagure.lib.query.add_token_to_user(
  4003. self.session,
  4004. project=None,
  4005. acls=["create_project"],
  4006. username="foo",
  4007. expiration_date=exp_date,
  4008. )
  4009. mtoken = pagure.lib.query.search_token(
  4010. self.session, ["create_project"], user="foo"
  4011. )[0]
  4012. # Call the connector with foo user token and verify unauthorized
  4013. headers = {"Authorization": "token %s" % mtoken.id}
  4014. output = self.app.get("/api/0/test/connector", headers=headers)
  4015. self.assertEqual(output.status_code, 401)
  4016. def test_api_get_project_connector_as_unauthorized_2(self):
  4017. """ Test accessing api_get_project_connector as project
  4018. but with unauthorized token ACL
  4019. """
  4020. project = pagure.lib.query._get_project(self.session, "test")
  4021. # Set the foo user as test project admin
  4022. pagure.lib.query.add_user_to_project(
  4023. self.session,
  4024. project,
  4025. new_user="foo",
  4026. user="pingou",
  4027. access="commit",
  4028. )
  4029. self.session.commit()
  4030. # Create modify_project token for foo user
  4031. exp_date = datetime.date.today() + datetime.timedelta(days=300)
  4032. pagure.lib.query.add_token_to_user(
  4033. self.session,
  4034. project=None,
  4035. acls=["modify_project"],
  4036. username="foo",
  4037. expiration_date=exp_date,
  4038. )
  4039. mtoken = pagure.lib.query.search_token(
  4040. self.session, ["modify_project"], user="foo"
  4041. )[0]
  4042. # Call the connector with foo user token and verify unauthorized
  4043. headers = {"Authorization": "token %s" % mtoken.id}
  4044. output = self.app.get("/api/0/test/connector", headers=headers)
  4045. self.assertEqual(output.status_code, 401)
  4046. class PagureFlaskApiProjectWebhookTokenTests(tests.Modeltests):
  4047. """ Tests for the flask API of pagure for getting webhook token of a project
  4048. """
  4049. maxDiff = None
  4050. def setUp(self):
  4051. """ Set up the environnment, ran before every tests. """
  4052. super(PagureFlaskApiProjectWebhookTokenTests, self).setUp()
  4053. tests.create_projects(self.session)
  4054. tests.create_tokens(self.session, project_id=None)
  4055. # Set a default ACL to avoid get all rights set on
  4056. tests.create_tokens_acl(self.session, "aaabbbcccddd", "issue_assign")
  4057. def test_api_get_project_webhook_token_as_owner(self):
  4058. """ Test accessing webhook token as project owner. """
  4059. project = pagure.lib.query._get_project(self.session, "test")
  4060. # Call the endpoint with pingou user token and verify content
  4061. headers = {"Authorization": "token aaabbbcccddd"}
  4062. output = self.app.get("/api/0/test/webhook/token", headers=headers)
  4063. self.assertEqual(output.status_code, 200)
  4064. data = json.loads(output.get_data(as_text=True))
  4065. self.assertEqual(
  4066. data, {"webhook": {"token": project.hook_token}, "status": "ok"}
  4067. )
  4068. def test_api_get_project_webhook_token_as_collaborator(self):
  4069. """ Test accessing webhook token as project collaborator. """
  4070. project = pagure.lib.query._get_project(self.session, "test")
  4071. # Set the foo user as test project collaborator ticket access level
  4072. pagure.lib.query.add_user_to_project(
  4073. self.session,
  4074. project,
  4075. new_user="foo",
  4076. user="pingou",
  4077. access="ticket",
  4078. )
  4079. self.session.commit()
  4080. # Create token for foo user with a default ACL
  4081. mtoken = pagure.lib.query.add_token_to_user(
  4082. self.session,
  4083. project=None,
  4084. acls=["issue_assign"],
  4085. username="foo",
  4086. expiration_date=datetime.date.today() + datetime.timedelta(days=1),
  4087. )
  4088. # Call the endpoint with foo user token and verify content
  4089. headers = {"Authorization": "token %s" % mtoken.id}
  4090. output = self.app.get("/api/0/test/webhook/token", headers=headers)
  4091. self.assertEqual(output.status_code, 200)
  4092. data = json.loads(output.get_data(as_text=True))
  4093. self.assertEqual(
  4094. data, {"webhook": {"token": project.hook_token}, "status": "ok"}
  4095. )
  4096. def test_api_get_project_webhook_token_as_not_collaborator(self):
  4097. """ Test accessing webhook token as not a project collaborator. """
  4098. # Create token for foo user with a default ACL
  4099. mtoken = pagure.lib.query.add_token_to_user(
  4100. self.session,
  4101. project=None,
  4102. acls=["issue_assign"],
  4103. username="foo",
  4104. expiration_date=datetime.date.today() + datetime.timedelta(days=1),
  4105. )
  4106. # Call the endpoint with pingou user token and verify content
  4107. headers = {"Authorization": "token %s" % mtoken.id}
  4108. output = self.app.get("/api/0/test/webhook/token", headers=headers)
  4109. self.assertEqual(output.status_code, 401)
  4110. if __name__ == "__main__":
  4111. unittest.main(verbosity=2)