test_pagure_flask_api_ui_private_repo.py 127 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494
  1. # -*- coding: utf-8 -*-
  2. from __future__ import unicode_literals, absolute_import
  3. import datetime
  4. import unittest
  5. import shutil
  6. import sys
  7. import tempfile
  8. import os
  9. import json
  10. import pygit2
  11. from mock import patch, MagicMock
  12. sys.path.insert(
  13. 0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")
  14. )
  15. import pagure.lib.query
  16. import tests
  17. from pagure.lib.repo import PagureRepo
  18. FULL_ISSUE_LIST = [
  19. {
  20. "assignee": None,
  21. "blocks": [],
  22. "close_status": None,
  23. "closed_at": None,
  24. "closed_by": None,
  25. "comments": [],
  26. "content": "We should work on this",
  27. "custom_fields": [],
  28. "date_created": "1431414800",
  29. "depends": [],
  30. "full_url": "http://localhost.localdomain/test4/issue/8",
  31. "id": 8,
  32. "last_updated": "1431414800",
  33. "milestone": None,
  34. "priority": None,
  35. "private": True,
  36. "related_prs": [],
  37. "status": "Open",
  38. "tags": [],
  39. "title": "Test issue",
  40. "user": {
  41. "fullname": "PY C",
  42. "full_url": "http://localhost.localdomain/user/pingou",
  43. "name": "pingou",
  44. "url_path": "user/pingou",
  45. },
  46. },
  47. {
  48. "assignee": None,
  49. "blocks": [],
  50. "close_status": None,
  51. "closed_at": None,
  52. "closed_by": None,
  53. "comments": [],
  54. "content": "This issue needs attention",
  55. "custom_fields": [],
  56. "date_created": "1431414800",
  57. "depends": [],
  58. "full_url": "http://localhost.localdomain/test4/issue/7",
  59. "id": 7,
  60. "last_updated": "1431414800",
  61. "milestone": None,
  62. "priority": None,
  63. "private": True,
  64. "related_prs": [],
  65. "status": "Open",
  66. "tags": [],
  67. "title": "test issue",
  68. "user": {
  69. "fullname": "PY C",
  70. "name": "pingou",
  71. "full_url": "http://localhost.localdomain/user/pingou",
  72. "url_path": "user/pingou",
  73. },
  74. },
  75. {
  76. "assignee": None,
  77. "blocks": [],
  78. "close_status": None,
  79. "closed_at": None,
  80. "closed_by": None,
  81. "comments": [],
  82. "content": "This issue needs attention",
  83. "custom_fields": [],
  84. "date_created": "1431414800",
  85. "depends": [],
  86. "full_url": "http://localhost.localdomain/test4/issue/6",
  87. "id": 6,
  88. "last_updated": "1431414800",
  89. "milestone": None,
  90. "priority": None,
  91. "private": True,
  92. "related_prs": [],
  93. "status": "Open",
  94. "tags": [],
  95. "title": "test issue",
  96. "user": {
  97. "fullname": "PY C",
  98. "name": "pingou",
  99. "full_url": "http://localhost.localdomain/user/pingou",
  100. "url_path": "user/pingou",
  101. },
  102. },
  103. {
  104. "assignee": None,
  105. "blocks": [],
  106. "close_status": None,
  107. "closed_at": None,
  108. "closed_by": None,
  109. "comments": [],
  110. "content": "This issue needs attention",
  111. "custom_fields": [],
  112. "date_created": "1431414800",
  113. "depends": [],
  114. "full_url": "http://localhost.localdomain/test4/issue/5",
  115. "id": 5,
  116. "last_updated": "1431414800",
  117. "milestone": None,
  118. "priority": None,
  119. "private": False,
  120. "related_prs": [],
  121. "status": "Open",
  122. "tags": [],
  123. "title": "test issue",
  124. "user": {
  125. "fullname": "PY C",
  126. "name": "pingou",
  127. "full_url": "http://localhost.localdomain/user/pingou",
  128. "url_path": "user/pingou",
  129. },
  130. },
  131. {
  132. "assignee": None,
  133. "blocks": [],
  134. "close_status": None,
  135. "closed_at": None,
  136. "closed_by": None,
  137. "comments": [],
  138. "content": "This issue needs attention",
  139. "custom_fields": [],
  140. "date_created": "1431414800",
  141. "depends": [],
  142. "full_url": "http://localhost.localdomain/test4/issue/4",
  143. "id": 4,
  144. "last_updated": "1431414800",
  145. "milestone": None,
  146. "priority": None,
  147. "private": False,
  148. "related_prs": [],
  149. "status": "Open",
  150. "tags": [],
  151. "title": "test issue",
  152. "user": {
  153. "fullname": "PY C",
  154. "name": "pingou",
  155. "full_url": "http://localhost.localdomain/user/pingou",
  156. "url_path": "user/pingou",
  157. },
  158. },
  159. {
  160. "assignee": None,
  161. "blocks": [],
  162. "close_status": None,
  163. "closed_at": None,
  164. "closed_by": None,
  165. "comments": [],
  166. "content": "This issue needs attention",
  167. "custom_fields": [],
  168. "date_created": "1431414800",
  169. "depends": [],
  170. "full_url": "http://localhost.localdomain/test4/issue/3",
  171. "id": 3,
  172. "last_updated": "1431414800",
  173. "milestone": None,
  174. "priority": None,
  175. "private": False,
  176. "related_prs": [],
  177. "status": "Open",
  178. "tags": [],
  179. "title": "test issue",
  180. "user": {
  181. "fullname": "PY C",
  182. "name": "pingou",
  183. "full_url": "http://localhost.localdomain/user/pingou",
  184. "url_path": "user/pingou",
  185. },
  186. },
  187. {
  188. "assignee": None,
  189. "blocks": [],
  190. "close_status": None,
  191. "closed_at": None,
  192. "closed_by": None,
  193. "comments": [],
  194. "content": "This issue needs attention",
  195. "custom_fields": [],
  196. "date_created": "1431414800",
  197. "depends": [],
  198. "full_url": "http://localhost.localdomain/test4/issue/2",
  199. "id": 2,
  200. "last_updated": "1431414800",
  201. "milestone": None,
  202. "priority": None,
  203. "private": False,
  204. "related_prs": [],
  205. "status": "Open",
  206. "tags": [],
  207. "title": "test issue",
  208. "user": {
  209. "fullname": "PY C",
  210. "name": "pingou",
  211. "full_url": "http://localhost.localdomain/user/pingou",
  212. "url_path": "user/pingou",
  213. },
  214. },
  215. {
  216. "assignee": None,
  217. "blocks": [],
  218. "close_status": None,
  219. "closed_at": None,
  220. "closed_by": None,
  221. "comments": [],
  222. "content": "This issue needs attention",
  223. "custom_fields": [],
  224. "date_created": "1431414800",
  225. "depends": [],
  226. "full_url": "http://localhost.localdomain/test4/issue/1",
  227. "id": 1,
  228. "last_updated": "1431414800",
  229. "milestone": None,
  230. "priority": None,
  231. "private": False,
  232. "related_prs": [],
  233. "status": "Open",
  234. "tags": [],
  235. "title": "test issue",
  236. "user": {
  237. "fullname": "PY C",
  238. "name": "pingou",
  239. "full_url": "http://localhost.localdomain/user/pingou",
  240. "url_path": "user/pingou",
  241. },
  242. },
  243. ]
  244. class PagurePrivateRepotest(tests.Modeltests):
  245. """Tests for private repo in pagure"""
  246. maxDiff = None
  247. def setUp(self):
  248. """Set up the environnment, ran before every tests."""
  249. super(PagurePrivateRepotest, self).setUp()
  250. pagure.config.config["TESTING"] = True
  251. pagure.config.config["DATAGREPPER_URL"] = None
  252. pagure.config.config["PRIVATE_PROJECTS"] = True
  253. pagure.config.config["VIRUS_SCAN_ATTACHMENTS"] = False
  254. def set_up_git_repo(
  255. self, new_project=None, branch_from="feature", mtype="FF"
  256. ):
  257. """Set up the git repo and create the corresponding PullRequest
  258. object.
  259. """
  260. # Create a git repo to play with
  261. gitrepo = os.path.join(self.path, "repos", "pmc.git")
  262. repo = pygit2.init_repository(gitrepo, bare=True)
  263. newpath = tempfile.mkdtemp(prefix="pagure-private-test")
  264. repopath = os.path.join(newpath, "test")
  265. clone_repo = pygit2.clone_repository(gitrepo, repopath)
  266. # Create a file in that git repo
  267. with open(os.path.join(repopath, "sources"), "w") as stream:
  268. stream.write("foo\n bar")
  269. clone_repo.index.add("sources")
  270. clone_repo.index.write()
  271. # Commits the files added
  272. tree = clone_repo.index.write_tree()
  273. author = pygit2.Signature("Alice Author", "alice@authors.tld")
  274. committer = pygit2.Signature("Cecil Committer", "cecil@committers.tld")
  275. clone_repo.create_commit(
  276. "refs/heads/master", # the name of the reference to update
  277. author,
  278. committer,
  279. "Add sources file for testing",
  280. # binary string representing the tree object ID
  281. tree,
  282. # list of binary strings representing parents of the new commit
  283. [],
  284. )
  285. refname = "refs/heads/master:refs/heads/master"
  286. ori_remote = clone_repo.remotes[0]
  287. PagureRepo.push(ori_remote, refname)
  288. first_commit = repo.revparse_single("HEAD")
  289. if mtype == "merge":
  290. with open(os.path.join(repopath, ".gitignore"), "w") as stream:
  291. stream.write("*~")
  292. clone_repo.index.add(".gitignore")
  293. clone_repo.index.write()
  294. # Commits the files added
  295. tree = clone_repo.index.write_tree()
  296. author = pygit2.Signature("Alice Äuthòr", "alice@äuthòrs.tld")
  297. committer = pygit2.Signature(
  298. "Cecil Cõmmîttër", "cecil@cõmmîttërs.tld"
  299. )
  300. clone_repo.create_commit(
  301. "refs/heads/master",
  302. author,
  303. committer,
  304. "Add .gitignore file for testing",
  305. # binary string representing the tree object ID
  306. tree,
  307. # list of binary strings representing parents of the new commit
  308. [first_commit.oid.hex],
  309. )
  310. refname = "refs/heads/master:refs/heads/master"
  311. ori_remote = clone_repo.remotes[0]
  312. PagureRepo.push(ori_remote, refname)
  313. if mtype == "conflicts":
  314. with open(os.path.join(repopath, "sources"), "w") as stream:
  315. stream.write("foo\n bar\nbaz")
  316. clone_repo.index.add("sources")
  317. clone_repo.index.write()
  318. # Commits the files added
  319. tree = clone_repo.index.write_tree()
  320. author = pygit2.Signature("Alice Author", "alice@authors.tld")
  321. committer = pygit2.Signature(
  322. "Cecil Committer", "cecil@committers.tld"
  323. )
  324. clone_repo.create_commit(
  325. "refs/heads/master",
  326. author,
  327. committer,
  328. "Add sources conflicting",
  329. # binary string representing the tree object ID
  330. tree,
  331. # list of binary strings representing parents of the new commit
  332. [first_commit.oid.hex],
  333. )
  334. refname = "refs/heads/master:refs/heads/master"
  335. ori_remote = clone_repo.remotes[0]
  336. PagureRepo.push(ori_remote, refname)
  337. # Set the second repo
  338. new_gitrepo = repopath
  339. if new_project:
  340. # Create a new git repo to play with
  341. new_gitrepo = os.path.join(newpath, new_project.fullname)
  342. if not os.path.exists(new_gitrepo):
  343. os.makedirs(new_gitrepo)
  344. new_repo = pygit2.clone_repository(gitrepo, new_gitrepo)
  345. repo = pygit2.Repository(new_gitrepo)
  346. if mtype != "nochanges":
  347. # Edit the sources file again
  348. with open(os.path.join(new_gitrepo, "sources"), "w") as stream:
  349. stream.write("foo\n bar\nbaz\n boose")
  350. repo.index.add("sources")
  351. repo.index.write()
  352. # Commits the files added
  353. tree = repo.index.write_tree()
  354. author = pygit2.Signature("Alice Author", "alice@authors.tld")
  355. committer = pygit2.Signature(
  356. "Cecil Committer", "cecil@committers.tld"
  357. )
  358. repo.create_commit(
  359. "refs/heads/%s" % branch_from,
  360. author,
  361. committer,
  362. "A commit on branch %s" % branch_from,
  363. tree,
  364. [first_commit.oid.hex],
  365. )
  366. refname = "refs/heads/%s" % (branch_from)
  367. ori_remote = repo.remotes[0]
  368. PagureRepo.push(ori_remote, refname)
  369. # Create a PR for these changes
  370. project = pagure.lib.query._get_project(self.session, "pmc")
  371. req = pagure.lib.query.new_pull_request(
  372. session=self.session,
  373. repo_from=project,
  374. branch_from=branch_from,
  375. repo_to=project,
  376. branch_to="master",
  377. title="PR from the %s branch" % branch_from,
  378. user="pingou",
  379. )
  380. self.session.commit()
  381. self.assertEqual(req.id, 1)
  382. self.assertEqual(req.title, "PR from the %s branch" % branch_from)
  383. shutil.rmtree(newpath)
  384. def test_index(self):
  385. """Test the index endpoint."""
  386. output = self.app.get("/")
  387. self.assertEqual(output.status_code, 200)
  388. self.assertIn(
  389. '<h3 class="m-0 font-weight-bold">All Projects '
  390. '<span class="badge badge-secondary">0</span></h3>',
  391. output.get_data(as_text=True),
  392. )
  393. # Add a private project
  394. item = pagure.lib.model.Project(
  395. user_id=2, # foo
  396. name="test3",
  397. description="test project description",
  398. hook_token="aaabbbeee",
  399. private=True,
  400. )
  401. self.session.add(item)
  402. # Add a public project
  403. item = pagure.lib.model.Project(
  404. user_id=2, # foo
  405. name="test4",
  406. description="test project description",
  407. hook_token="aaabbbeeeccceee",
  408. )
  409. self.session.add(item)
  410. self.session.commit()
  411. output = self.app.get("/?page=abc")
  412. self.assertEqual(output.status_code, 200)
  413. output_text = output.get_data(as_text=True)
  414. self.assertIn(
  415. '<h3 class="m-0 font-weight-bold">All Projects '
  416. '<span class="badge badge-secondary">1</span></h3>',
  417. output_text,
  418. )
  419. user = tests.FakeUser(username="foo")
  420. with tests.user_set(self.app.application, user):
  421. output = self.app.get("/", follow_redirects=True)
  422. output_text = output.get_data(as_text=True)
  423. self.assertIn(
  424. '<h4 class="font-weight-bold mb-0">My Projects</h4>',
  425. output_text,
  426. )
  427. self.assertIn("2 Projects</span>", output_text)
  428. self.assertNotIn(
  429. '<span class="d-none d-md-inline">Forks', output_text
  430. )
  431. self.assertEqual(
  432. output_text.count('<span class="d-none d-md-inline">Groups'), 0
  433. )
  434. def test_view_user(self):
  435. """Test the view_user endpoint."""
  436. output = self.app.get("/user/foo?repopage=abc&forkpage=def")
  437. self.assertEqual(output.status_code, 200)
  438. output_text = output.get_data(as_text=True)
  439. self.assertIn(
  440. """<span>
  441. <i class="fa fa-fw text-muted fa-calendar-o fa-rotate-270"></i>
  442. <span class="d-none d-md-inline">Projects&nbsp;</span>
  443. </span>
  444. <div class="ml-auto">
  445. <span class="badge badge-secondary">
  446. 0
  447. </span>
  448. </div>""",
  449. output_text,
  450. )
  451. self.assertIn(
  452. """<span>
  453. <i class="fa fa-fw text-muted fa-code-fork"></i>
  454. <span class="d-none d-md-inline">Forks&nbsp;</span>
  455. </span>
  456. <div class="ml-auto">
  457. <span class="badge badge-secondary">
  458. 0
  459. </span>
  460. </div>""",
  461. output_text,
  462. )
  463. self.assertIn(
  464. """<span>
  465. <i class="fa fa-fw text-muted fa-users"></i>
  466. <span class="d-none d-md-inline">Groups&nbsp;</span>
  467. </span>
  468. <div class="ml-auto">
  469. <span class="badge badge-secondary">
  470. 0
  471. </span>
  472. </div>""",
  473. output_text,
  474. )
  475. # Add a private project
  476. item = pagure.lib.model.Project(
  477. user_id=2, # foo
  478. name="test3",
  479. description="test project description",
  480. hook_token="aaabbbeee",
  481. private=True,
  482. )
  483. self.session.add(item)
  484. # Add a public project
  485. item = pagure.lib.model.Project(
  486. user_id=2, # foo
  487. name="test4",
  488. description="test project description",
  489. hook_token="aaabbbeeeccceee",
  490. )
  491. self.session.add(item)
  492. self.session.commit()
  493. self.gitrepos = tests.create_projects_git(
  494. pagure.config.config["GIT_FOLDER"]
  495. )
  496. output = self.app.get("/user/foo")
  497. self.assertEqual(output.status_code, 200)
  498. output_text = output.get_data(as_text=True)
  499. self.assertIn(
  500. """<span>
  501. <i class="fa fa-fw text-muted fa-calendar-o fa-rotate-270"></i>
  502. <span class="d-none d-md-inline">Projects&nbsp;</span>
  503. </span>
  504. <div class="ml-auto">
  505. <span class="badge badge-secondary">
  506. 1
  507. </span>
  508. </div>""",
  509. output_text,
  510. )
  511. self.assertIn(
  512. """<span>
  513. <i class="fa fa-fw text-muted fa-code-fork"></i>
  514. <span class="d-none d-md-inline">Forks&nbsp;</span>
  515. </span>
  516. <div class="ml-auto">
  517. <span class="badge badge-secondary">
  518. 0
  519. </span>
  520. </div>""",
  521. output_text,
  522. )
  523. self.assertIn(
  524. """<span>
  525. <i class="fa fa-fw text-muted fa-users"></i>
  526. <span class="d-none d-md-inline">Groups&nbsp;</span>
  527. </span>
  528. <div class="ml-auto">
  529. <span class="badge badge-secondary">
  530. 0
  531. </span>
  532. </div>""",
  533. output_text,
  534. )
  535. user = tests.FakeUser(username="foo")
  536. with tests.user_set(self.app.application, user):
  537. output = self.app.get("/user/foo")
  538. output_text = output.get_data(as_text=True)
  539. self.assertIn(
  540. """<span>
  541. <i class="fa fa-fw text-muted fa-calendar-o fa-rotate-270"></i>
  542. <span class="d-none d-md-inline">Projects&nbsp;</span>
  543. </span>
  544. <div class="ml-auto">
  545. <span class="badge badge-secondary">
  546. 1
  547. </span>
  548. </div>""",
  549. output_text,
  550. )
  551. self.assertIn(
  552. """<span>
  553. <i class="fa fa-fw text-muted fa-code-fork"></i>
  554. <span class="d-none d-md-inline">Forks&nbsp;</span>
  555. </span>
  556. <div class="ml-auto">
  557. <span class="badge badge-secondary">
  558. 0
  559. </span>
  560. </div>""",
  561. output_text,
  562. )
  563. self.assertIn(
  564. """<span>
  565. <i class="fa fa-fw text-muted fa-users"></i>
  566. <span class="d-none d-md-inline">Groups&nbsp;</span>
  567. </span>
  568. <div class="ml-auto">
  569. <span class="badge badge-secondary">
  570. 0
  571. </span>
  572. </div>""",
  573. output_text,
  574. )
  575. user.username = "pingou"
  576. with tests.user_set(self.app.application, user):
  577. output = self.app.get("/user/foo")
  578. output_text = output.get_data(as_text=True)
  579. self.assertIn(
  580. """<span>
  581. <i class="fa fa-fw text-muted fa-calendar-o fa-rotate-270"></i>
  582. <span class="d-none d-md-inline">Projects&nbsp;</span>
  583. </span>
  584. <div class="ml-auto">
  585. <span class="badge badge-secondary">
  586. 1
  587. </span>
  588. </div>""",
  589. output_text,
  590. )
  591. self.assertIn(
  592. """<span>
  593. <i class="fa fa-fw text-muted fa-code-fork"></i>
  594. <span class="d-none d-md-inline">Forks&nbsp;</span>
  595. </span>
  596. <div class="ml-auto">
  597. <span class="badge badge-secondary">
  598. 0
  599. </span>
  600. </div>""",
  601. output_text,
  602. )
  603. self.assertIn(
  604. """<span>
  605. <i class="fa fa-fw text-muted fa-users"></i>
  606. <span class="d-none d-md-inline">Groups&nbsp;</span>
  607. </span>
  608. <div class="ml-auto">
  609. <span class="badge badge-secondary">
  610. 0
  611. </span>
  612. </div>""",
  613. output_text,
  614. )
  615. # Check pingou has 0 projects
  616. user.username = "pingou"
  617. with tests.user_set(self.app.application, user):
  618. output = self.app.get("/", follow_redirects=True)
  619. output_text = output.get_data(as_text=True)
  620. self.assertIn(
  621. '<h4 class="font-weight-bold mb-0">My Projects</h4>',
  622. output_text,
  623. )
  624. self.assertIn("0 Projects</span>", output_text)
  625. self.assertNotIn(
  626. '<span class="d-none d-md-inline">Forks', output_text
  627. )
  628. self.assertEqual(
  629. output_text.count('<span class="d-none d-md-inline">Groups'), 0
  630. )
  631. repo = pagure.lib.query._get_project(self.session, "test3")
  632. msg = pagure.lib.query.add_user_to_project(
  633. session=self.session, project=repo, new_user="pingou", user="foo"
  634. )
  635. self.session.commit()
  636. self.assertEqual(msg, "User added")
  637. # New user added to private projects
  638. user.username = "pingou"
  639. with tests.user_set(self.app.application, user):
  640. output = self.app.get("/", follow_redirects=True)
  641. output_text = output.get_data(as_text=True)
  642. self.assertIn(
  643. '<h4 class="font-weight-bold mb-0">My Projects</h4>',
  644. output_text,
  645. )
  646. self.assertIn("1 Projects</span>", output_text)
  647. self.assertNotIn(
  648. '<span class="d-none d-md-inline">Forks', output_text
  649. )
  650. self.assertEqual(
  651. output_text.count('<span class="d-none d-md-inline">Groups'), 0
  652. )
  653. @patch("pagure.decorators.admin_session_timedout")
  654. def test_private_settings_ui(self, ast):
  655. """Test UI for private repo"""
  656. ast.return_value = False
  657. # Add private repo
  658. item = pagure.lib.model.Project(
  659. user_id=1, # pingou
  660. name="test4",
  661. description="test project description",
  662. hook_token="aaabbbeeeceee",
  663. private=True,
  664. )
  665. self.session.add(item)
  666. self.session.commit()
  667. # Add a git repo
  668. repo_path = os.path.join(
  669. pagure.config.config.get("GIT_FOLDER"), "test4.git"
  670. )
  671. if not os.path.exists(repo_path):
  672. os.makedirs(repo_path)
  673. pygit2.init_repository(repo_path)
  674. user = tests.FakeUser(username="pingou")
  675. with tests.user_set(self.app.application, user):
  676. tests.create_projects(self.session)
  677. tests.create_projects_git(pagure.config.config.get("GIT_FOLDER"))
  678. output = self.app.get("/test/settings")
  679. # Check for a public repo
  680. self.assertEqual(output.status_code, 200)
  681. self.assertNotIn(
  682. '<input type="checkbox" value="private" name="private"',
  683. output.get_data(as_text=True),
  684. )
  685. output = self.app.get("/test4/settings")
  686. # Check for private repo
  687. self.assertEqual(output.status_code, 200)
  688. self.assertIn(
  689. '<input type="checkbox" value="private" name="private" checked="" />',
  690. output.get_data(as_text=True),
  691. )
  692. # Check the new project form has 'private' checkbox
  693. output = self.app.get("/new")
  694. self.assertEqual(output.status_code, 200)
  695. self.assertIn(
  696. '<input id="private" name="private" type="checkbox" value="y">',
  697. output.get_data(as_text=True),
  698. )
  699. @patch("pagure.decorators.admin_session_timedout")
  700. def test_private_settings_ui_update_privacy_false(self, ast):
  701. """Test UI for private repo"""
  702. ast.return_value = False
  703. # Add private repo
  704. item = pagure.lib.model.Project(
  705. user_id=1, # pingou
  706. name="test4",
  707. description="test project description",
  708. hook_token="aaabbbeeeceee",
  709. private=True,
  710. )
  711. self.session.add(item)
  712. self.session.commit()
  713. # Add a git repo
  714. repo_path = os.path.join(
  715. pagure.config.config.get("GIT_FOLDER"), "test4.git"
  716. )
  717. pygit2.init_repository(repo_path)
  718. user = tests.FakeUser(username="pingou")
  719. with tests.user_set(self.app.application, user):
  720. # Check for private repo
  721. output = self.app.get("/test4/settings")
  722. self.assertEqual(output.status_code, 200)
  723. self.assertIn(
  724. '<input type="checkbox" value="private" name="private" checked="" />',
  725. output.get_data(as_text=True),
  726. )
  727. self.session.commit()
  728. repo = pagure.lib.query._get_project(self.session, "test4")
  729. self.assertTrue(repo.private)
  730. # Make the project public
  731. data = {
  732. "description": "test project description",
  733. "private": False,
  734. "csrf_token": self.get_csrf(),
  735. }
  736. output = self.app.post(
  737. "/test4/update", data=data, follow_redirects=True
  738. )
  739. self.assertEqual(output.status_code, 200)
  740. self.assertIn("Project updated", output.get_data(as_text=True))
  741. self.assertNotIn(
  742. '<input type="checkbox" value="private" name="private" checked="" />',
  743. output.get_data(as_text=True),
  744. )
  745. self.session.commit()
  746. repo = pagure.lib.query._get_project(self.session, "test4")
  747. self.assertFalse(repo.private)
  748. @patch("pagure.decorators.admin_session_timedout")
  749. def test_private_settings_ui_update_privacy_true(self, ast):
  750. """Test UI for private repo"""
  751. ast.return_value = False
  752. # Add private repo
  753. item = pagure.lib.model.Project(
  754. user_id=1, # pingou
  755. name="test4",
  756. description="test project description",
  757. hook_token="aaabbbeeeceee",
  758. private=False,
  759. )
  760. self.session.add(item)
  761. self.session.commit()
  762. # Add a git repo
  763. repo_path = os.path.join(
  764. pagure.config.config.get("GIT_FOLDER"), "test4.git"
  765. )
  766. pygit2.init_repository(repo_path)
  767. user = tests.FakeUser(username="pingou")
  768. with tests.user_set(self.app.application, user):
  769. # Check for public repo
  770. output = self.app.get("/test4/settings")
  771. self.assertEqual(output.status_code, 200)
  772. self.assertNotIn(
  773. '<input type="checkbox" value="private" name="private" checked=""/>',
  774. output.get_data(as_text=True),
  775. )
  776. self.session.commit()
  777. repo = pagure.lib.query._get_project(self.session, "test4")
  778. self.assertFalse(repo.private)
  779. # Make the project private
  780. data = {
  781. "description": "test project description",
  782. "private": True,
  783. "csrf_token": self.get_csrf(),
  784. }
  785. output = self.app.post(
  786. "/test4/update", data=data, follow_redirects=True
  787. )
  788. self.assertEqual(output.status_code, 200)
  789. self.assertIn("Project updated", output.get_data(as_text=True))
  790. self.assertNotIn(
  791. '<input type="checkbox" value="private" name="private" checked=""/>',
  792. output.get_data(as_text=True),
  793. )
  794. # No change since we can't do public -> private
  795. self.session.commit()
  796. repo = pagure.lib.query._get_project(self.session, "test4")
  797. self.assertFalse(repo.private)
  798. @patch("pagure.lib.notify.send_email")
  799. def test_private_pr(self, send_email):
  800. """Test pull request made to the private repo"""
  801. send_email.return_value = True
  802. # Add a private project
  803. item = pagure.lib.model.Project(
  804. user_id=1, # pingou
  805. name="pmc",
  806. description="test project description",
  807. hook_token="aaabbbeeeceee",
  808. private=True,
  809. )
  810. self.session.add(item)
  811. self.session.commit()
  812. repo = pagure.lib.query._get_project(self.session, "pmc")
  813. msg = pagure.lib.query.add_user_to_project(
  814. session=self.session, project=repo, new_user="foo", user="pingou"
  815. )
  816. self.session.commit()
  817. self.assertEqual(msg, "User added")
  818. # Create all the git repos
  819. tests.create_projects_git(
  820. os.path.join(self.path, "requests"), bare=True
  821. )
  822. # Add a git repo
  823. repo_path = os.path.join(
  824. pagure.config.config.get("REQUESTS_FOLDER"), "pmc.git"
  825. )
  826. if not os.path.exists(repo_path):
  827. os.makedirs(repo_path)
  828. pygit2.init_repository(repo_path, bare=True)
  829. # Check repo was created - Doesn't show on the public page
  830. user = tests.FakeUser(username="pingou")
  831. with tests.user_set(self.app.application, user):
  832. output = self.app.get("/user/pingou/")
  833. self.assertEqual(output.status_code, 200)
  834. self.assertIn(
  835. """<span>
  836. <i class="fa fa-fw text-muted fa-calendar-o fa-rotate-270"></i>
  837. <span class="d-none d-md-inline">Projects&nbsp;</span>
  838. </span>
  839. <div class="ml-auto">
  840. <span class="badge badge-secondary">
  841. 0
  842. </span>
  843. </div>""",
  844. output.get_data(as_text=True),
  845. )
  846. self.assertIn(
  847. """<span>
  848. <i class="fa fa-fw text-muted fa-code-fork"></i>
  849. <span class="d-none d-md-inline">Forks&nbsp;</span>
  850. </span>
  851. <div class="ml-auto">
  852. <span class="badge badge-secondary">
  853. 0
  854. </span>
  855. </div>""",
  856. output.get_data(as_text=True),
  857. )
  858. # Shows on the front page
  859. output = self.app.get("/dashboard/projects")
  860. self.assertEqual(output.status_code, 200)
  861. self.assertIn(
  862. """<span>
  863. <i class="fa fa-calendar-o fa-rotate-270 fa-fw text-muted"></i>
  864. <span class="d-none d-md-inline">Projects&nbsp;</span>
  865. </span>
  866. <div class="ml-auto">
  867. <span class="badge badge-secondary">
  868. 1
  869. </span>
  870. </div>""",
  871. output.get_data(as_text=True),
  872. )
  873. self.set_up_git_repo(new_project=None, branch_from="feature")
  874. project = pagure.lib.query._get_project(self.session, "pmc")
  875. self.assertEqual(len(project.requests), 1)
  876. output = self.app.get("/pmc/pull-request/1")
  877. self.assertEqual(output.status_code, 200)
  878. # Check repo was created
  879. user = tests.FakeUser()
  880. with tests.user_set(self.app.application, user):
  881. output = self.app.get("/pmc/pull-requests")
  882. self.assertEqual(output.status_code, 404)
  883. user = tests.FakeUser(username="pingou")
  884. with tests.user_set(self.app.application, user):
  885. output = self.app.get("/pmc/pull-requests")
  886. self.assertEqual(output.status_code, 200)
  887. user = tests.FakeUser(username="foo")
  888. with tests.user_set(self.app.application, user):
  889. output = self.app.get("/pmc/pull-requests")
  890. self.assertEqual(output.status_code, 200)
  891. @patch("pagure.lib.git.update_git")
  892. @patch("pagure.lib.notify.send_email")
  893. def test_private_repo_issues_ui(self, p_send_email, p_ugt):
  894. """Test issues made to private repo"""
  895. p_send_email.return_value = True
  896. p_ugt.return_value = True
  897. # Add private repo
  898. item = pagure.lib.model.Project(
  899. user_id=1, # pingou
  900. name="test4",
  901. description="test project description",
  902. hook_token="aaabbbeeeceee",
  903. private=True,
  904. )
  905. self.session.add(item)
  906. self.session.commit()
  907. for repo in ["GIT_FOLDER", "TICKETS_FOLDER"]:
  908. # Add a git repo
  909. repo_path = os.path.join(
  910. pagure.config.config.get(repo), "test4.git"
  911. )
  912. if not os.path.exists(repo_path):
  913. os.makedirs(repo_path)
  914. pygit2.init_repository(repo_path)
  915. # Check if the private repo issues are publicly not accesible
  916. output = self.app.get("/test4/issues")
  917. self.assertEqual(output.status_code, 404)
  918. # Create issues to play with
  919. repo = pagure.lib.query._get_project(self.session, "test4")
  920. msg = pagure.lib.query.new_issue(
  921. session=self.session,
  922. repo=repo,
  923. title="Test issue",
  924. content="We should work on this",
  925. user="pingou",
  926. )
  927. self.session.commit()
  928. self.assertEqual(msg.title, "Test issue")
  929. user = tests.FakeUser()
  930. with tests.user_set(self.app.application, user):
  931. # Whole list
  932. output = self.app.get("/test4/issues")
  933. self.assertEqual(output.status_code, 404)
  934. # Check single issue
  935. output = self.app.get("/test4/issue/1")
  936. self.assertEqual(output.status_code, 404)
  937. user = tests.FakeUser()
  938. with tests.user_set(self.app.application, user):
  939. # Whole list
  940. output = self.app.get("/test4/issues")
  941. self.assertEqual(output.status_code, 404)
  942. user = tests.FakeUser(username="pingou")
  943. with tests.user_set(self.app.application, user):
  944. # Whole list
  945. output = self.app.get("/test4/issues")
  946. self.assertEqual(output.status_code, 200)
  947. self.assertIn(
  948. "<title>Issues - test4 - Pagure</title>",
  949. output.get_data(as_text=True),
  950. )
  951. self.assertTrue(
  952. '<span class="fa fa-fw fa-exclamation-circle"></span> 1 Open Issues\n'
  953. in output.get_data(as_text=True)
  954. )
  955. # Check single issue
  956. output = self.app.get("/test4/issue/1")
  957. self.assertEqual(output.status_code, 200)
  958. repo = pagure.lib.query._get_project(self.session, "test4")
  959. msg = pagure.lib.query.add_user_to_project(
  960. session=self.session, project=repo, new_user="foo", user="pingou"
  961. )
  962. self.session.commit()
  963. self.assertEqual(msg, "User added")
  964. user.username = "foo"
  965. with tests.user_set(self.app.application, user):
  966. # Whole list
  967. output = self.app.get("/test4/issues")
  968. self.assertEqual(output.status_code, 200)
  969. self.assertIn(
  970. "<title>Issues - test4 - Pagure</title>",
  971. output.get_data(as_text=True),
  972. )
  973. self.assertTrue(
  974. '<span class="fa fa-fw fa-exclamation-circle"></span> 1 Open Issues\n'
  975. in output.get_data(as_text=True)
  976. )
  977. # Check single issue
  978. output = self.app.get("/test4/issue/1")
  979. self.assertEqual(output.status_code, 200)
  980. @patch("pagure.decorators.admin_session_timedout")
  981. def test_private_repo_ui_for_different_repo_user(self, ast):
  982. """Test the private repo for different ACLS"""
  983. ast.return_value = False
  984. # Add private repo
  985. item = pagure.lib.model.Project(
  986. user_id=1, # pingou
  987. name="test4",
  988. description="test project description",
  989. hook_token="aaabbbeeeceee",
  990. private=True,
  991. )
  992. self.session.add(item)
  993. self.session.commit()
  994. repo = pagure.lib.query._get_project(self.session, "test4")
  995. # Add a git repo
  996. repo_path = os.path.join(
  997. pagure.config.config.get("GIT_FOLDER"), "test4.git"
  998. )
  999. pygit2.init_repository(repo_path)
  1000. user = tests.FakeUser(username="pingou")
  1001. with tests.user_set(self.app.application, user):
  1002. # Check for private repo
  1003. output = self.app.get("/test4")
  1004. self.assertEqual(output.status_code, 200)
  1005. # Check if the user who doesn't have access to private repo can access it
  1006. user = tests.FakeUser(username="foo")
  1007. with tests.user_set(self.app.application, user):
  1008. output = self.app.get("/test4")
  1009. self.assertEqual(output.status_code, 404)
  1010. # Add commit access to a user
  1011. pagure.lib.query.add_user_to_project(
  1012. self.session,
  1013. project=repo,
  1014. new_user="foo",
  1015. user="pingou",
  1016. access="commit",
  1017. )
  1018. self.session.commit()
  1019. repo = pagure.lib.query._get_project(self.session, "test4")
  1020. self.assertEqual(len(repo.users), 1)
  1021. # Check if the user can access private repo
  1022. user = tests.FakeUser(username="foo")
  1023. with tests.user_set(self.app.application, user):
  1024. output = self.app.get("/test4")
  1025. self.assertEqual(output.status_code, 200)
  1026. # Making a new user bar
  1027. item = pagure.lib.model.User(
  1028. user="bar",
  1029. fullname="bar baz",
  1030. password="foo",
  1031. default_email="bar@bar.com",
  1032. )
  1033. self.session.add(item)
  1034. item = pagure.lib.model.UserEmail(user_id=3, email="bar@bar.com")
  1035. self.session.add(item)
  1036. self.session.commit()
  1037. # Check that bar shouldn't be able to access the project
  1038. user = tests.FakeUser(username="bar")
  1039. with tests.user_set(self.app.application, user):
  1040. output = self.app.get("/test4")
  1041. self.assertEqual(output.status_code, 404)
  1042. # Adding a ticket level access to bar
  1043. pagure.lib.query.add_user_to_project(
  1044. self.session,
  1045. project=repo,
  1046. new_user="bar",
  1047. user="pingou",
  1048. access="ticket",
  1049. )
  1050. self.session.commit()
  1051. repo = pagure.lib.query._get_project(self.session, "test4")
  1052. self.assertEqual(len(repo.users), 2)
  1053. # Check if the ticket level access user can access the project
  1054. user = tests.FakeUser(username="bar")
  1055. with tests.user_set(self.app.application, user):
  1056. output = self.app.get("/test4")
  1057. self.assertEqual(output.status_code, 200)
  1058. # API checks
  1059. def test_api_private_repo_projects(self):
  1060. """Test api points for private repo for projects"""
  1061. # Add private repo
  1062. item = pagure.lib.model.Project(
  1063. user_id=1, # pingou
  1064. name="test4",
  1065. description="test project description",
  1066. hook_token="aaabbbeeeceee",
  1067. private=True,
  1068. )
  1069. self.session.add(item)
  1070. self.session.commit()
  1071. # Create a git repo to play with
  1072. gitrepo = os.path.join(self.path, "repos", "test4.git")
  1073. repo = pygit2.init_repository(gitrepo, bare=True)
  1074. newpath = tempfile.mkdtemp(prefix="pagure-fork-test")
  1075. repopath = os.path.join(newpath, "repos", "test4")
  1076. clone_repo = pygit2.clone_repository(gitrepo, repopath)
  1077. # Create a file in that git repo
  1078. with open(os.path.join(repopath, "sources"), "w") as stream:
  1079. stream.write("foo\n bar")
  1080. clone_repo.index.add("sources")
  1081. clone_repo.index.write()
  1082. # Commits the files added
  1083. tree = clone_repo.index.write_tree()
  1084. author = pygit2.Signature("Alice Author", "alice@authors.tld")
  1085. committer = pygit2.Signature("Cecil Committer", "cecil@committers.tld")
  1086. clone_repo.create_commit(
  1087. "refs/heads/master", # the name of the reference to update
  1088. author,
  1089. committer,
  1090. "Add sources file for testing",
  1091. # binary string representing the tree object ID
  1092. tree,
  1093. # list of binary strings representing parents of the new commit
  1094. [],
  1095. )
  1096. refname = "refs/heads/master:refs/heads/master"
  1097. ori_remote = clone_repo.remotes[0]
  1098. PagureRepo.push(ori_remote, refname)
  1099. # Tag our first commit
  1100. first_commit = repo.revparse_single("HEAD")
  1101. tagger = pygit2.Signature("Alice Doe", "adoe@example.com", 12347, 0)
  1102. repo.create_tag(
  1103. "0.0.1",
  1104. first_commit.oid.hex,
  1105. pygit2.GIT_OBJ_COMMIT,
  1106. tagger,
  1107. "Release 0.0.1",
  1108. )
  1109. # Create a token for foo for this project
  1110. item = pagure.lib.model.Token(
  1111. id="foobar_token",
  1112. user_id=1,
  1113. project_id=1,
  1114. expiration=datetime.datetime.utcnow()
  1115. + datetime.timedelta(days=30),
  1116. )
  1117. self.session.add(item)
  1118. self.session.commit()
  1119. item = pagure.lib.model.TokenAcl(token_id="foobar_token", acl_id=1)
  1120. self.session.add(item)
  1121. self.session.commit()
  1122. # Check if the admin requests
  1123. user = tests.FakeUser(username="pingou")
  1124. with tests.user_set(self.app.application, user):
  1125. # Check tags
  1126. output = self.app.get("/api/0/test4/git/tags")
  1127. self.assertEqual(output.status_code, 200)
  1128. data = json.loads(output.get_data(as_text=True))
  1129. self.assertDictEqual(data, {"tags": ["0.0.1"], "total_tags": 1})
  1130. output = self.app.get("/api/0/test4/git/tags")
  1131. self.assertEqual(output.status_code, 404)
  1132. # Chekc if user is not admin
  1133. user = tests.FakeUser()
  1134. with tests.user_set(self.app.application, user):
  1135. output = self.app.get("/api/0/test4/git/tags")
  1136. self.assertEqual(output.status_code, 404)
  1137. shutil.rmtree(newpath)
  1138. # Check before adding
  1139. repo = pagure.lib.query._get_project(self.session, "test4")
  1140. self.assertEqual(repo.tags, [])
  1141. # Adding a tag
  1142. output = pagure.lib.query.update_tags(
  1143. self.session, repo, "infra", "pingou"
  1144. )
  1145. self.assertEqual(output, ["Project tagged with: infra"])
  1146. # Check after adding
  1147. repo = pagure.lib.query._get_project(self.session, "test4")
  1148. self.assertEqual(len(repo.tags), 1)
  1149. self.assertEqual(repo.tags_text, ["infra"])
  1150. # Check the API
  1151. output = self.app.get("/api/0/projects?tags=inf")
  1152. self.assertEqual(output.status_code, 200)
  1153. data = json.loads(output.get_data(as_text=True))
  1154. del data["pagination"]
  1155. self.assertDictEqual(
  1156. data,
  1157. {
  1158. "args": {
  1159. "fork": None,
  1160. "namespace": None,
  1161. "owner": None,
  1162. "page": 1,
  1163. "pattern": None,
  1164. "per_page": 20,
  1165. "short": False,
  1166. "tags": ["inf"],
  1167. "username": None,
  1168. },
  1169. "projects": [],
  1170. "total_projects": 0,
  1171. },
  1172. )
  1173. # Request by not a loggged in user
  1174. output = self.app.get("/api/0/projects?tags=infra")
  1175. self.assertEqual(output.status_code, 200)
  1176. data = json.loads(output.get_data(as_text=True))
  1177. del data["pagination"]
  1178. self.assertDictEqual(
  1179. data,
  1180. {
  1181. "args": {
  1182. "fork": None,
  1183. "namespace": None,
  1184. "owner": None,
  1185. "page": 1,
  1186. "pattern": None,
  1187. "per_page": 20,
  1188. "short": False,
  1189. "tags": ["infra"],
  1190. "username": None,
  1191. },
  1192. "projects": [],
  1193. "total_projects": 0,
  1194. },
  1195. )
  1196. user = tests.FakeUser()
  1197. with tests.user_set(self.app.application, user):
  1198. # Request by a non authorized user
  1199. output = self.app.get("/api/0/projects?tags=infra")
  1200. self.assertEqual(output.status_code, 200)
  1201. data = json.loads(output.get_data(as_text=True))
  1202. del data["pagination"]
  1203. self.assertDictEqual(
  1204. data,
  1205. {
  1206. "args": {
  1207. "fork": None,
  1208. "namespace": None,
  1209. "owner": None,
  1210. "page": 1,
  1211. "pattern": None,
  1212. "per_page": 20,
  1213. "short": False,
  1214. "tags": ["infra"],
  1215. "username": None,
  1216. },
  1217. "projects": [],
  1218. "total_projects": 0,
  1219. },
  1220. )
  1221. user.username = "pingou"
  1222. with tests.user_set(self.app.application, user):
  1223. # Private repo username is compulsion to pass
  1224. output = self.app.get("/api/0/projects?tags=infra")
  1225. self.assertEqual(output.status_code, 200)
  1226. data = json.loads(output.get_data(as_text=True))
  1227. del data["pagination"]
  1228. self.assertDictEqual(
  1229. data,
  1230. {
  1231. "args": {
  1232. "fork": None,
  1233. "namespace": None,
  1234. "owner": None,
  1235. "page": 1,
  1236. "pattern": None,
  1237. "per_page": 20,
  1238. "short": False,
  1239. "tags": ["infra"],
  1240. "username": None,
  1241. },
  1242. "projects": [],
  1243. "total_projects": 0,
  1244. },
  1245. )
  1246. output = self.app.get("/api/0/projects?username=pingou")
  1247. self.assertEqual(output.status_code, 200)
  1248. data = json.loads(output.get_data(as_text=True))
  1249. data["projects"][0]["date_created"] = "1436527638"
  1250. data["projects"][0]["date_modified"] = "1436527638"
  1251. del data["pagination"]
  1252. self.assertDictEqual(
  1253. data,
  1254. {
  1255. "args": {
  1256. "fork": None,
  1257. "namespace": None,
  1258. "owner": None,
  1259. "page": 1,
  1260. "pattern": None,
  1261. "per_page": 20,
  1262. "short": False,
  1263. "tags": [],
  1264. "username": "pingou",
  1265. },
  1266. "total_projects": 1,
  1267. "projects": [
  1268. {
  1269. "access_groups": {
  1270. "admin": [],
  1271. "collaborator": [],
  1272. "commit": [],
  1273. "ticket": [],
  1274. },
  1275. "access_users": {
  1276. "admin": [],
  1277. "collaborator": [],
  1278. "commit": [],
  1279. "owner": ["pingou"],
  1280. "ticket": [],
  1281. },
  1282. "close_status": [],
  1283. "custom_keys": [],
  1284. "date_created": "1436527638",
  1285. "date_modified": "1436527638",
  1286. "description": "test project description",
  1287. "full_url": "http://localhost.localdomain/test4",
  1288. "id": 1,
  1289. "milestones": {},
  1290. "name": "test4",
  1291. "fullname": "test4",
  1292. "url_path": "test4",
  1293. "namespace": None,
  1294. "parent": None,
  1295. "priorities": {},
  1296. "tags": ["infra"],
  1297. "user": {
  1298. "fullname": "PY C",
  1299. "name": "pingou",
  1300. "full_url": "http://localhost.localdomain/user/pingou",
  1301. "url_path": "user/pingou",
  1302. },
  1303. }
  1304. ],
  1305. },
  1306. )
  1307. output = self.app.get("/api/0/projects?username=pingou&tags=infra")
  1308. self.assertEqual(output.status_code, 200)
  1309. data = json.loads(output.get_data(as_text=True))
  1310. data["projects"][0]["date_created"] = "1436527638"
  1311. data["projects"][0]["date_modified"] = "1436527638"
  1312. del data["pagination"]
  1313. self.assertDictEqual(
  1314. data,
  1315. {
  1316. "args": {
  1317. "fork": None,
  1318. "namespace": None,
  1319. "owner": None,
  1320. "page": 1,
  1321. "pattern": None,
  1322. "per_page": 20,
  1323. "short": False,
  1324. "tags": ["infra"],
  1325. "username": "pingou",
  1326. },
  1327. "total_projects": 1,
  1328. "projects": [
  1329. {
  1330. "access_groups": {
  1331. "admin": [],
  1332. "collaborator": [],
  1333. "commit": [],
  1334. "ticket": [],
  1335. },
  1336. "access_users": {
  1337. "admin": [],
  1338. "collaborator": [],
  1339. "commit": [],
  1340. "owner": ["pingou"],
  1341. "ticket": [],
  1342. },
  1343. "close_status": [],
  1344. "custom_keys": [],
  1345. "date_created": "1436527638",
  1346. "date_modified": "1436527638",
  1347. "description": "test project description",
  1348. "full_url": "http://localhost.localdomain/test4",
  1349. "id": 1,
  1350. "milestones": {},
  1351. "name": "test4",
  1352. "fullname": "test4",
  1353. "url_path": "test4",
  1354. "namespace": None,
  1355. "parent": None,
  1356. "priorities": {},
  1357. "tags": ["infra"],
  1358. "user": {
  1359. "fullname": "PY C",
  1360. "name": "pingou",
  1361. "full_url": "http://localhost.localdomain/user/pingou",
  1362. "url_path": "user/pingou",
  1363. },
  1364. }
  1365. ],
  1366. },
  1367. )
  1368. # Api pull-request views
  1369. @patch("pagure.lib.notify.send_email")
  1370. def test_api_private_repo_fork(self, send_email):
  1371. """Test api endpoints in api/fork"""
  1372. send_email.return_value = True
  1373. # Add private repo
  1374. item = pagure.lib.model.Project(
  1375. user_id=1, # pingou
  1376. name="test4",
  1377. description="test project description",
  1378. hook_token="aaabbbeeeceee",
  1379. private=True,
  1380. )
  1381. self.session.add(item)
  1382. self.session.commit()
  1383. tests.create_tokens(self.session)
  1384. tests.create_tokens_acl(self.session)
  1385. headers = {"Authorization": "token aaabbbcccddd"}
  1386. # Create a pull-request
  1387. repo = pagure.lib.query._get_project(self.session, "test4")
  1388. forked_repo = pagure.lib.query._get_project(self.session, "test4")
  1389. req = pagure.lib.query.new_pull_request(
  1390. session=self.session,
  1391. repo_from=forked_repo,
  1392. branch_from="master",
  1393. repo_to=repo,
  1394. branch_to="master",
  1395. title="test pull-request",
  1396. user="pingou",
  1397. )
  1398. self.session.commit()
  1399. self.assertEqual(req.id, 1)
  1400. self.assertEqual(req.title, "test pull-request")
  1401. # Check list of PR
  1402. output = self.app.get("/api/0/test4/pull-requests")
  1403. self.assertEqual(output.status_code, 404)
  1404. # Check single PR
  1405. output = self.app.get("/api/0/test/pull-request/1")
  1406. self.assertEqual(output.status_code, 404)
  1407. user = tests.FakeUser(username="pingou")
  1408. with tests.user_set(self.app.application, user):
  1409. # List pull-requests
  1410. output = self.app.get("/api/0/test4/pull-requests")
  1411. self.assertEqual(output.status_code, 200)
  1412. data = json.loads(output.get_data(as_text=True))
  1413. data["requests"][0]["date_created"] = "1431414800"
  1414. data["requests"][0]["updated_on"] = "1431414800"
  1415. data["requests"][0]["project"]["date_created"] = "1431414800"
  1416. data["requests"][0]["project"]["date_modified"] = "1431414800"
  1417. data["requests"][0]["repo_from"]["date_created"] = "1431414800"
  1418. data["requests"][0]["repo_from"]["date_modified"] = "1431414800"
  1419. data["requests"][0]["uid"] = "1431414800"
  1420. data["requests"][0]["last_updated"] = "1431414800"
  1421. for k in ["first", "last"]:
  1422. self.assertIsNotNone(data["pagination"][k])
  1423. data["pagination"][k] = "http://localhost..."
  1424. self.assertDictEqual(
  1425. data,
  1426. {
  1427. "args": {
  1428. "assignee": None,
  1429. "author": None,
  1430. "tags": [],
  1431. "page": 1,
  1432. "per_page": 20,
  1433. "status": True,
  1434. },
  1435. "pagination": {
  1436. "first": "http://localhost...",
  1437. "last": "http://localhost...",
  1438. "next": None,
  1439. "page": 1,
  1440. "pages": 1,
  1441. "per_page": 20,
  1442. "prev": None,
  1443. },
  1444. "requests": [
  1445. {
  1446. "assignee": None,
  1447. "branch": "master",
  1448. "branch_from": "master",
  1449. "cached_merge_status": "unknown",
  1450. "closed_at": None,
  1451. "closed_by": None,
  1452. "comments": [],
  1453. "commit_start": None,
  1454. "commit_stop": None,
  1455. "date_created": "1431414800",
  1456. "full_url": "http://localhost.localdomain/test4/pull-request/1",
  1457. "last_updated": "1431414800",
  1458. "id": 1,
  1459. "initial_comment": None,
  1460. "project": {
  1461. "access_groups": {
  1462. "admin": [],
  1463. "collaborator": [],
  1464. "commit": [],
  1465. "ticket": [],
  1466. },
  1467. "access_users": {
  1468. "admin": [],
  1469. "collaborator": [],
  1470. "commit": [],
  1471. "owner": ["pingou"],
  1472. "ticket": [],
  1473. },
  1474. "close_status": [],
  1475. "custom_keys": [],
  1476. "date_created": "1431414800",
  1477. "date_modified": "1431414800",
  1478. "description": "test project description",
  1479. "full_url": "http://localhost.localdomain/test4",
  1480. "id": 1,
  1481. "milestones": {},
  1482. "name": "test4",
  1483. "fullname": "test4",
  1484. "url_path": "test4",
  1485. "namespace": None,
  1486. "parent": None,
  1487. "priorities": {},
  1488. "tags": [],
  1489. "user": {
  1490. "fullname": "PY C",
  1491. "full_url": "http://localhost.localdomain/user/pingou",
  1492. "name": "pingou",
  1493. "url_path": "user/pingou",
  1494. },
  1495. },
  1496. "remote_git": None,
  1497. "repo_from": {
  1498. "access_groups": {
  1499. "admin": [],
  1500. "collaborator": [],
  1501. "commit": [],
  1502. "ticket": [],
  1503. },
  1504. "access_users": {
  1505. "admin": [],
  1506. "collaborator": [],
  1507. "commit": [],
  1508. "owner": ["pingou"],
  1509. "ticket": [],
  1510. },
  1511. "close_status": [],
  1512. "custom_keys": [],
  1513. "date_created": "1431414800",
  1514. "date_modified": "1431414800",
  1515. "description": "test project description",
  1516. "full_url": "http://localhost.localdomain/test4",
  1517. "id": 1,
  1518. "milestones": {},
  1519. "fullname": "test4",
  1520. "url_path": "test4",
  1521. "name": "test4",
  1522. "namespace": None,
  1523. "parent": None,
  1524. "priorities": {},
  1525. "tags": [],
  1526. "user": {
  1527. "fullname": "PY C",
  1528. "name": "pingou",
  1529. "full_url": "http://localhost.localdomain/user/pingou",
  1530. "url_path": "user/pingou",
  1531. },
  1532. },
  1533. "status": "Open",
  1534. "tags": [],
  1535. "threshold_reached": None,
  1536. "title": "test pull-request",
  1537. "uid": "1431414800",
  1538. "updated_on": "1431414800",
  1539. "user": {
  1540. "fullname": "PY C",
  1541. "full_url": "http://localhost.localdomain/user/pingou",
  1542. "name": "pingou",
  1543. "url_path": "user/pingou",
  1544. },
  1545. }
  1546. ],
  1547. "total_requests": 1,
  1548. },
  1549. )
  1550. headers = {"Authorization": "token foobar_token"}
  1551. # Access Pull-Request authenticated
  1552. output = self.app.get(
  1553. "/api/0/test4/pull-requests", headers=headers
  1554. )
  1555. self.assertEqual(output.status_code, 200)
  1556. data2 = json.loads(output.get_data(as_text=True))
  1557. data2["requests"][0]["date_created"] = "1431414800"
  1558. data2["requests"][0]["updated_on"] = "1431414800"
  1559. data2["requests"][0]["project"]["date_created"] = "1431414800"
  1560. data2["requests"][0]["project"]["date_modified"] = "1431414800"
  1561. data2["requests"][0]["repo_from"]["date_created"] = "1431414800"
  1562. data2["requests"][0]["repo_from"]["date_modified"] = "1431414800"
  1563. data2["requests"][0]["uid"] = "1431414800"
  1564. data2["requests"][0]["last_updated"] = "1431414800"
  1565. for k in ["first", "last"]:
  1566. self.assertIsNotNone(data["pagination"][k])
  1567. data2["pagination"][k] = "http://localhost..."
  1568. self.assertDictEqual(data, data2)
  1569. # For single PR
  1570. output = self.app.get("/api/0/test4/pull-request/1")
  1571. self.assertEqual(output.status_code, 200)
  1572. data = json.loads(output.get_data(as_text=True))
  1573. data["date_created"] = "1431414800"
  1574. data["updated_on"] = "1431414800"
  1575. data["project"]["date_created"] = "1431414800"
  1576. data["project"]["date_modified"] = "1431414800"
  1577. data["repo_from"]["date_created"] = "1431414800"
  1578. data["repo_from"]["date_modified"] = "1431414800"
  1579. data["uid"] = "1431414800"
  1580. data["last_updated"] = "1431414800"
  1581. self.assertDictEqual(
  1582. data,
  1583. {
  1584. "assignee": None,
  1585. "branch": "master",
  1586. "branch_from": "master",
  1587. "cached_merge_status": "unknown",
  1588. "closed_at": None,
  1589. "closed_by": None,
  1590. "comments": [],
  1591. "commit_start": None,
  1592. "commit_stop": None,
  1593. "date_created": "1431414800",
  1594. "full_url": "http://localhost.localdomain/test4/pull-request/1",
  1595. "last_updated": "1431414800",
  1596. "id": 1,
  1597. "initial_comment": None,
  1598. "project": {
  1599. "access_groups": {
  1600. "admin": [],
  1601. "collaborator": [],
  1602. "commit": [],
  1603. "ticket": [],
  1604. },
  1605. "access_users": {
  1606. "admin": [],
  1607. "collaborator": [],
  1608. "commit": [],
  1609. "owner": ["pingou"],
  1610. "ticket": [],
  1611. },
  1612. "close_status": [],
  1613. "custom_keys": [],
  1614. "date_created": "1431414800",
  1615. "date_modified": "1431414800",
  1616. "description": "test project description",
  1617. "full_url": "http://localhost.localdomain/test4",
  1618. "id": 1,
  1619. "milestones": {},
  1620. "name": "test4",
  1621. "fullname": "test4",
  1622. "url_path": "test4",
  1623. "namespace": None,
  1624. "parent": None,
  1625. "priorities": {},
  1626. "tags": [],
  1627. "user": {
  1628. "fullname": "PY C",
  1629. "full_url": "http://localhost.localdomain/user/pingou",
  1630. "name": "pingou",
  1631. "url_path": "user/pingou",
  1632. },
  1633. },
  1634. "remote_git": None,
  1635. "repo_from": {
  1636. "access_groups": {
  1637. "admin": [],
  1638. "collaborator": [],
  1639. "commit": [],
  1640. "ticket": [],
  1641. },
  1642. "access_users": {
  1643. "admin": [],
  1644. "collaborator": [],
  1645. "commit": [],
  1646. "owner": ["pingou"],
  1647. "ticket": [],
  1648. },
  1649. "close_status": [],
  1650. "custom_keys": [],
  1651. "date_created": "1431414800",
  1652. "date_modified": "1431414800",
  1653. "description": "test project description",
  1654. "full_url": "http://localhost.localdomain/test4",
  1655. "id": 1,
  1656. "milestones": {},
  1657. "name": "test4",
  1658. "fullname": "test4",
  1659. "url_path": "test4",
  1660. "namespace": None,
  1661. "parent": None,
  1662. "priorities": {},
  1663. "tags": [],
  1664. "user": {
  1665. "fullname": "PY C",
  1666. "full_url": "http://localhost.localdomain/user/pingou",
  1667. "name": "pingou",
  1668. "url_path": "user/pingou",
  1669. },
  1670. },
  1671. "status": "Open",
  1672. "tags": [],
  1673. "threshold_reached": None,
  1674. "title": "test pull-request",
  1675. "uid": "1431414800",
  1676. "updated_on": "1431414800",
  1677. "user": {
  1678. "fullname": "PY C",
  1679. "name": "pingou",
  1680. "full_url": "http://localhost.localdomain/user/pingou",
  1681. "url_path": "user/pingou",
  1682. },
  1683. },
  1684. )
  1685. # Access Pull-Request authenticated
  1686. output = self.app.get(
  1687. "/api/0/test4/pull-request/1", headers=headers
  1688. )
  1689. self.assertEqual(output.status_code, 200)
  1690. data2 = json.loads(output.get_data(as_text=True))
  1691. data2["date_created"] = "1431414800"
  1692. data2["project"]["date_created"] = "1431414800"
  1693. data2["project"]["date_modified"] = "1431414800"
  1694. data2["repo_from"]["date_created"] = "1431414800"
  1695. data2["repo_from"]["date_modified"] = "1431414800"
  1696. data2["uid"] = "1431414800"
  1697. data2["date_created"] = "1431414800"
  1698. data2["updated_on"] = "1431414800"
  1699. data2["last_updated"] = "1431414800"
  1700. self.assertDictEqual(data, data2)
  1701. @patch("pagure.lib.notify.send_email")
  1702. def test_api_pr_private_repo_add_comment(self, mockemail):
  1703. """Test the api_pull_request_add_comment method of the flask api."""
  1704. mockemail.return_value = True
  1705. pagure.config.config["REQUESTS_FOLDER"] = None
  1706. # Add private repo
  1707. item = pagure.lib.model.Project(
  1708. user_id=1, # pingou
  1709. name="test4",
  1710. description="test project description",
  1711. hook_token="aaabbbeeeceee",
  1712. private=True,
  1713. )
  1714. self.session.add(item)
  1715. self.session.commit()
  1716. tests.create_tokens(self.session)
  1717. tests.create_tokens_acl(self.session)
  1718. headers = {"Authorization": "token aaabbbcccddd"}
  1719. # Create a pull-request
  1720. repo = pagure.lib.query._get_project(self.session, "test4")
  1721. forked_repo = pagure.lib.query._get_project(self.session, "test4")
  1722. req = pagure.lib.query.new_pull_request(
  1723. session=self.session,
  1724. repo_from=forked_repo,
  1725. branch_from="master",
  1726. repo_to=repo,
  1727. branch_to="master",
  1728. title="test pull-request",
  1729. user="pingou",
  1730. )
  1731. self.session.commit()
  1732. self.assertEqual(req.id, 1)
  1733. self.assertEqual(req.title, "test pull-request")
  1734. # Check comments before
  1735. self.session.commit()
  1736. request = pagure.lib.query.search_pull_requests(
  1737. self.session, project_id=1, requestid=1
  1738. )
  1739. self.assertEqual(len(request.comments), 0)
  1740. data = {"title": "test issue"}
  1741. # Incomplete request
  1742. output = self.app.post(
  1743. "/api/0/test4/pull-request/1/comment", data=data, headers=headers
  1744. )
  1745. self.assertEqual(output.status_code, 400)
  1746. data = json.loads(output.get_data(as_text=True))
  1747. self.assertDictEqual(
  1748. data,
  1749. {
  1750. "error": "Invalid or incomplete input submitted",
  1751. "error_code": "EINVALIDREQ",
  1752. "errors": {"comment": ["This field is required."]},
  1753. },
  1754. )
  1755. # No change
  1756. self.session.commit()
  1757. request = pagure.lib.query.search_pull_requests(
  1758. self.session, project_id=1, requestid=1
  1759. )
  1760. self.assertEqual(len(request.comments), 0)
  1761. data = {"comment": "This is a very interesting question"}
  1762. # Valid request
  1763. output = self.app.post(
  1764. "/api/0/test4/pull-request/1/comment", data=data, headers=headers
  1765. )
  1766. self.assertEqual(output.status_code, 200)
  1767. data = json.loads(output.get_data(as_text=True))
  1768. self.assertDictEqual(data, {"message": "Comment added"})
  1769. # One comment added
  1770. self.session.commit()
  1771. request = pagure.lib.query.search_pull_requests(
  1772. self.session, project_id=1, requestid=1
  1773. )
  1774. self.assertEqual(len(request.comments), 1)
  1775. @patch("pagure.lib.notify.send_email")
  1776. def test_api_private_repo_pr_add_flag(self, mockemail):
  1777. """Test the api_pull_request_add_flag method of the flask api."""
  1778. mockemail.return_value = True
  1779. pagure.config.config["REQUESTS_FOLDER"] = None
  1780. # Add private repo
  1781. item = pagure.lib.model.Project(
  1782. user_id=1, # pingou
  1783. name="test4",
  1784. description="test project description",
  1785. hook_token="aaabbbeeeceee",
  1786. private=True,
  1787. )
  1788. self.session.add(item)
  1789. self.session.commit()
  1790. # Add private repo
  1791. item = pagure.lib.model.Project(
  1792. user_id=1, # pingou
  1793. name="test2",
  1794. description="test project description",
  1795. hook_token="foo_bar",
  1796. private=True,
  1797. )
  1798. self.session.add(item)
  1799. self.session.commit()
  1800. tests.create_tokens(self.session)
  1801. tests.create_tokens_acl(self.session)
  1802. headers = {"Authorization": "token aaabbbcccddd"}
  1803. # Invalid project
  1804. output = self.app.post(
  1805. "/api/0/foo/pull-request/1/flag", headers=headers
  1806. )
  1807. self.assertEqual(output.status_code, 404)
  1808. data = json.loads(output.get_data(as_text=True))
  1809. self.assertDictEqual(
  1810. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  1811. )
  1812. # Valid token, wrong project
  1813. output = self.app.post(
  1814. "/api/0/test2/pull-request/1/flag", headers=headers
  1815. )
  1816. self.assertEqual(output.status_code, 401)
  1817. data = json.loads(output.get_data(as_text=True))
  1818. self.assertEqual(sorted(data.keys()), ["error", "error_code"])
  1819. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data["error"])
  1820. self.assertEqual(
  1821. pagure.api.APIERROR.EINVALIDTOK.name, data["error_code"]
  1822. )
  1823. # No input
  1824. output = self.app.post(
  1825. "/api/0/test4/pull-request/1/flag", headers=headers
  1826. )
  1827. self.assertEqual(output.status_code, 404)
  1828. data = json.loads(output.get_data(as_text=True))
  1829. self.assertDictEqual(
  1830. data, {"error": "Pull-Request not found", "error_code": "ENOREQ"}
  1831. )
  1832. # Create a pull-request
  1833. repo = pagure.lib.query._get_project(self.session, "test4")
  1834. forked_repo = pagure.lib.query._get_project(self.session, "test4")
  1835. req = pagure.lib.query.new_pull_request(
  1836. session=self.session,
  1837. repo_from=forked_repo,
  1838. branch_from="master",
  1839. repo_to=repo,
  1840. branch_to="master",
  1841. title="test pull-request",
  1842. user="pingou",
  1843. )
  1844. req.commit_stop = "hash_commit_stop"
  1845. self.session.add(req)
  1846. self.session.commit()
  1847. self.assertEqual(req.id, 1)
  1848. self.assertEqual(req.title, "test pull-request")
  1849. # Check comments before
  1850. self.session.commit()
  1851. request = pagure.lib.query.search_pull_requests(
  1852. self.session, project_id=1, requestid=1
  1853. )
  1854. self.assertEqual(len(request.flags), 0)
  1855. data = {
  1856. "username": "Jenkins",
  1857. "percent": 100,
  1858. "url": "http://jenkins.cloud.fedoraproject.org/",
  1859. "uid": "jenkins_build_pagure_100+seed",
  1860. }
  1861. # Incomplete request
  1862. output = self.app.post(
  1863. "/api/0/test4/pull-request/1/flag", data=data, headers=headers
  1864. )
  1865. self.assertEqual(output.status_code, 400)
  1866. data = json.loads(output.get_data(as_text=True))
  1867. self.assertDictEqual(
  1868. data,
  1869. {
  1870. "error": "Invalid or incomplete input submitted",
  1871. "error_code": "EINVALIDREQ",
  1872. "errors": {"comment": ["This field is required."]},
  1873. },
  1874. )
  1875. # No change
  1876. self.session.commit()
  1877. request = pagure.lib.query.search_pull_requests(
  1878. self.session, project_id=1, requestid=1
  1879. )
  1880. self.assertEqual(len(request.flags), 0)
  1881. data = {
  1882. "username": "Jenkins",
  1883. "percent": 0,
  1884. "comment": "Tests failed",
  1885. "url": "http://jenkins.cloud.fedoraproject.org/",
  1886. "uid": "jenkins_build_pagure_100+seed",
  1887. }
  1888. # Valid request
  1889. output = self.app.post(
  1890. "/api/0/test4/pull-request/1/flag", data=data, headers=headers
  1891. )
  1892. self.assertEqual(output.status_code, 200)
  1893. data = json.loads(output.get_data(as_text=True))
  1894. data["flag"]["date_created"] = "1510742565"
  1895. data["flag"]["date_updated"] = "1510742565"
  1896. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  1897. self.assertDictEqual(
  1898. data,
  1899. {
  1900. "flag": {
  1901. "comment": "Tests failed",
  1902. "commit_hash": "hash_commit_stop",
  1903. "date_created": "1510742565",
  1904. "date_updated": "1510742565",
  1905. "percent": 0,
  1906. "status": "failure",
  1907. "url": "http://jenkins.cloud.fedoraproject.org/",
  1908. "user": {
  1909. "default_email": "bar@pingou.com",
  1910. "emails": ["bar@pingou.com", "foo@pingou.com"],
  1911. "full_url": "http://localhost.localdomain/user/pingou",
  1912. "fullname": "PY C",
  1913. "name": "pingou",
  1914. "url_path": "user/pingou",
  1915. },
  1916. "username": "Jenkins",
  1917. },
  1918. "message": "Flag added",
  1919. "uid": "jenkins_build_pagure_100+seed",
  1920. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  1921. "user": "pingou",
  1922. },
  1923. )
  1924. # One flag added
  1925. self.session.commit()
  1926. request = pagure.lib.query.search_pull_requests(
  1927. self.session, project_id=1, requestid=1
  1928. )
  1929. self.assertEqual(len(request.flags), 0)
  1930. flags = pagure.lib.query.get_commit_flag(
  1931. self.session, request.project, "hash_commit_stop"
  1932. )
  1933. self.assertEqual(len(flags), 1)
  1934. self.assertEqual(flags[0].comment, "Tests failed")
  1935. self.assertEqual(flags[0].percent, 0)
  1936. # Update flag
  1937. data = {
  1938. "username": "Jenkins",
  1939. "percent": 100,
  1940. "comment": "Tests passed",
  1941. "url": "http://jenkins.cloud.fedoraproject.org/",
  1942. "uid": "jenkins_build_pagure_100+seed",
  1943. }
  1944. output = self.app.post(
  1945. "/api/0/test4/pull-request/1/flag", data=data, headers=headers
  1946. )
  1947. self.assertEqual(output.status_code, 200)
  1948. data = json.loads(output.get_data(as_text=True))
  1949. data["flag"]["date_created"] = "1510742565"
  1950. data["flag"]["date_updated"] = "1510742565"
  1951. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  1952. self.assertDictEqual(
  1953. data,
  1954. {
  1955. "flag": {
  1956. "comment": "Tests passed",
  1957. "commit_hash": "hash_commit_stop",
  1958. "date_created": "1510742565",
  1959. "date_updated": "1510742565",
  1960. "percent": 100,
  1961. "status": "success",
  1962. "url": "http://jenkins.cloud.fedoraproject.org/",
  1963. "user": {
  1964. "default_email": "bar@pingou.com",
  1965. "emails": ["bar@pingou.com", "foo@pingou.com"],
  1966. "full_url": "http://localhost.localdomain/user/pingou",
  1967. "fullname": "PY C",
  1968. "name": "pingou",
  1969. "url_path": "user/pingou",
  1970. },
  1971. "username": "Jenkins",
  1972. },
  1973. "message": "Flag updated",
  1974. "uid": "jenkins_build_pagure_100+seed",
  1975. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  1976. "user": "pingou",
  1977. },
  1978. )
  1979. # One flag added
  1980. self.session.commit()
  1981. request = pagure.lib.query.search_pull_requests(
  1982. self.session, project_id=1, requestid=1
  1983. )
  1984. self.assertEqual(len(request.flags), 0)
  1985. flags = pagure.lib.query.get_commit_flag(
  1986. self.session, request.project, "hash_commit_stop"
  1987. )
  1988. self.assertEqual(len(flags), 1)
  1989. self.assertEqual(flags[0].comment, "Tests passed")
  1990. self.assertEqual(flags[0].percent, 100)
  1991. @patch("pagure.lib.notify.send_email")
  1992. def test_api_private_repo_pr_close(self, send_email):
  1993. """Test the api_pull_request_close method of the flask api."""
  1994. send_email.return_value = True
  1995. pagure.config.config["REQUESTS_FOLDER"] = None
  1996. # Add private repo
  1997. item = pagure.lib.model.Project(
  1998. user_id=1, # pingou
  1999. name="test4",
  2000. description="test project description",
  2001. hook_token="aaabbbeeeceee",
  2002. private=True,
  2003. )
  2004. self.session.add(item)
  2005. self.session.commit()
  2006. tests.create_tokens(self.session)
  2007. tests.create_tokens_acl(self.session)
  2008. # Add private repo
  2009. item = pagure.lib.model.Project(
  2010. user_id=1, # pingou
  2011. name="test2",
  2012. description="test project description",
  2013. hook_token="foo_bar",
  2014. private=True,
  2015. )
  2016. self.session.add(item)
  2017. self.session.commit()
  2018. # Create the pull-request to close
  2019. repo = pagure.lib.query._get_project(self.session, "test4")
  2020. forked_repo = pagure.lib.query._get_project(self.session, "test4")
  2021. req = pagure.lib.query.new_pull_request(
  2022. session=self.session,
  2023. repo_from=forked_repo,
  2024. branch_from="master",
  2025. repo_to=repo,
  2026. branch_to="master",
  2027. title="test pull-request",
  2028. user="pingou",
  2029. )
  2030. self.session.commit()
  2031. self.assertEqual(req.id, 1)
  2032. self.assertEqual(req.title, "test pull-request")
  2033. headers = {"Authorization": "token aaabbbcccddd"}
  2034. # Invalid project
  2035. output = self.app.post(
  2036. "/api/0/foo/pull-request/1/close", headers=headers
  2037. )
  2038. self.assertEqual(output.status_code, 404)
  2039. data = json.loads(output.get_data(as_text=True))
  2040. self.assertDictEqual(
  2041. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  2042. )
  2043. # Valid token, wrong project
  2044. output = self.app.post(
  2045. "/api/0/test2/pull-request/1/close", headers=headers
  2046. )
  2047. self.assertEqual(output.status_code, 401)
  2048. data = json.loads(output.get_data(as_text=True))
  2049. self.assertEqual(sorted(data.keys()), ["error", "error_code"])
  2050. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data["error"])
  2051. self.assertEqual(
  2052. pagure.api.APIERROR.EINVALIDTOK.name, data["error_code"]
  2053. )
  2054. # Invalid PR
  2055. output = self.app.post(
  2056. "/api/0/test4/pull-request/2/close", headers=headers
  2057. )
  2058. self.assertEqual(output.status_code, 404)
  2059. data = json.loads(output.get_data(as_text=True))
  2060. self.assertDictEqual(
  2061. data, {"error": "Pull-Request not found", "error_code": "ENOREQ"}
  2062. )
  2063. # Create a token for foo for this project
  2064. item = pagure.lib.model.Token(
  2065. id="foobar_token",
  2066. user_id=2,
  2067. project_id=1,
  2068. expiration=datetime.datetime.utcnow()
  2069. + datetime.timedelta(days=30),
  2070. )
  2071. self.session.add(item)
  2072. self.session.commit()
  2073. # Allow the token to close PR
  2074. acls = pagure.lib.query.get_acls(self.session)
  2075. acl = None
  2076. for acl in acls:
  2077. if acl.name == "pull_request_close":
  2078. break
  2079. item = pagure.lib.model.TokenAcl(
  2080. token_id="foobar_token", acl_id=acl.id
  2081. )
  2082. self.session.add(item)
  2083. self.session.commit()
  2084. headers = {"Authorization": "token foobar_token"}
  2085. # User not admin
  2086. output = self.app.post(
  2087. "/api/0/test4/pull-request/1/close", headers=headers
  2088. )
  2089. self.assertEqual(output.status_code, 404)
  2090. data = json.loads(output.get_data(as_text=True))
  2091. self.assertDictEqual(
  2092. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  2093. )
  2094. headers = {"Authorization": "token aaabbbcccddd"}
  2095. # Close PR
  2096. output = self.app.post(
  2097. "/api/0/test4/pull-request/1/close", headers=headers
  2098. )
  2099. self.assertEqual(output.status_code, 200)
  2100. data = json.loads(output.get_data(as_text=True))
  2101. self.assertDictEqual(data, {"message": "Pull-request closed!"})
  2102. @patch("pagure.lib.notify.send_email")
  2103. def test_api_private_repo_pr_merge(self, send_email):
  2104. """Test the api_pull_request_merge method of the flask api."""
  2105. send_email.return_value = True
  2106. pagure.config.config["REQUESTS_FOLDER"] = None
  2107. # Add private repo
  2108. item = pagure.lib.model.Project(
  2109. user_id=1, # pingou
  2110. name="test4",
  2111. description="test project description",
  2112. hook_token="aaabbbeeeceee",
  2113. private=True,
  2114. )
  2115. self.session.add(item)
  2116. self.session.commit()
  2117. tests.create_projects_git(os.path.join(self.path, "repos"), bare=True)
  2118. tests.create_projects_git(
  2119. os.path.join(self.path, "requests"), bare=True
  2120. )
  2121. tests.add_readme_git_repo(
  2122. os.path.join(self.path, "repos", "test4.git")
  2123. )
  2124. tests.add_commit_git_repo(
  2125. os.path.join(self.path, "repos", "test4.git"), branch="test"
  2126. )
  2127. tests.create_tokens(self.session)
  2128. tests.create_tokens_acl(self.session)
  2129. # Add private repo
  2130. item = pagure.lib.model.Project(
  2131. user_id=1, # pingou
  2132. name="test2",
  2133. description="test project description",
  2134. hook_token="foo_bar",
  2135. private=True,
  2136. )
  2137. self.session.add(item)
  2138. self.session.commit()
  2139. # Create the pull-request to close
  2140. repo = pagure.lib.query._get_project(self.session, "test4")
  2141. forked_repo = pagure.lib.query._get_project(self.session, "test4")
  2142. req = pagure.lib.query.new_pull_request(
  2143. session=self.session,
  2144. repo_from=forked_repo,
  2145. branch_from="test",
  2146. repo_to=repo,
  2147. branch_to="master",
  2148. title="test pull-request",
  2149. user="pingou",
  2150. )
  2151. self.session.commit()
  2152. self.assertEqual(req.id, 1)
  2153. self.assertEqual(req.title, "test pull-request")
  2154. headers = {"Authorization": "token aaabbbcccddd"}
  2155. # Invalid project
  2156. output = self.app.post(
  2157. "/api/0/foo/pull-request/1/merge", headers=headers
  2158. )
  2159. self.assertEqual(output.status_code, 404)
  2160. data = json.loads(output.get_data(as_text=True))
  2161. self.assertDictEqual(
  2162. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  2163. )
  2164. # Valid token, wrong project
  2165. output = self.app.post(
  2166. "/api/0/test2/pull-request/1/merge", headers=headers
  2167. )
  2168. self.assertEqual(output.status_code, 401)
  2169. data = json.loads(output.get_data(as_text=True))
  2170. self.assertEqual(sorted(data.keys()), ["error", "error_code"])
  2171. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data["error"])
  2172. self.assertEqual(
  2173. pagure.api.APIERROR.EINVALIDTOK.name, data["error_code"]
  2174. )
  2175. # Invalid PR
  2176. output = self.app.post(
  2177. "/api/0/test4/pull-request/2/merge", headers=headers
  2178. )
  2179. self.assertEqual(output.status_code, 404)
  2180. data = json.loads(output.get_data(as_text=True))
  2181. self.assertDictEqual(
  2182. data, {"error": "Pull-Request not found", "error_code": "ENOREQ"}
  2183. )
  2184. # Create a token for foo for this project
  2185. item = pagure.lib.model.Token(
  2186. id="foobar_token",
  2187. user_id=2,
  2188. project_id=1,
  2189. expiration=datetime.datetime.utcnow()
  2190. + datetime.timedelta(days=30),
  2191. )
  2192. self.session.add(item)
  2193. self.session.commit()
  2194. # Allow the token to merge PR
  2195. acls = pagure.lib.query.get_acls(self.session)
  2196. acl = None
  2197. for acl in acls:
  2198. if acl.name == "pull_request_merge":
  2199. break
  2200. item = pagure.lib.model.TokenAcl(
  2201. token_id="foobar_token", acl_id=acl.id
  2202. )
  2203. self.session.add(item)
  2204. self.session.commit()
  2205. headers = {"Authorization": "token foobar_token"}
  2206. # User not admin
  2207. output = self.app.post(
  2208. "/api/0/test4/pull-request/1/merge", headers=headers
  2209. )
  2210. self.assertEqual(output.status_code, 404)
  2211. data = json.loads(output.get_data(as_text=True))
  2212. self.assertDictEqual(
  2213. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  2214. )
  2215. headers = {"Authorization": "token aaabbbcccddd"}
  2216. # Merge PR
  2217. output = self.app.post(
  2218. "/api/0/test4/pull-request/1/merge", headers=headers
  2219. )
  2220. self.assertEqual(output.status_code, 200)
  2221. data = json.loads(output.get_data(as_text=True))
  2222. self.assertDictEqual(data, {"message": "Changes merged!"})
  2223. def test_api_private_repo_new_issue(self):
  2224. """Test the api_new_issue method of the flask api."""
  2225. # Add private repo
  2226. item = pagure.lib.model.Project(
  2227. user_id=1, # pingou
  2228. name="test4",
  2229. description="test project description",
  2230. hook_token="aaabbbeeeceee",
  2231. private=True,
  2232. )
  2233. self.session.add(item)
  2234. self.session.commit()
  2235. for repo in ["GIT_FOLDER", "TICKETS_FOLDER"]:
  2236. # Add a git repo
  2237. repo_path = os.path.join(
  2238. pagure.config.config.get(repo), "test4.git"
  2239. )
  2240. if not os.path.exists(repo_path):
  2241. os.makedirs(repo_path)
  2242. pygit2.init_repository(repo_path, bare=True)
  2243. tests.create_tokens(self.session)
  2244. tests.create_tokens_acl(self.session)
  2245. # Add private repo
  2246. item = pagure.lib.model.Project(
  2247. user_id=1, # pingou
  2248. name="test2",
  2249. description="test project description",
  2250. hook_token="foo_bar",
  2251. private=True,
  2252. )
  2253. self.session.add(item)
  2254. self.session.commit()
  2255. headers = {"Authorization": "token aaabbbcccddd"}
  2256. # Valid token, wrong project
  2257. output = self.app.post("/api/0/test2/new_issue", headers=headers)
  2258. self.assertEqual(output.status_code, 401)
  2259. data = json.loads(output.get_data(as_text=True))
  2260. self.assertEqual(sorted(data.keys()), ["error", "error_code"])
  2261. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data["error"])
  2262. self.assertEqual(
  2263. pagure.api.APIERROR.EINVALIDTOK.name, data["error_code"]
  2264. )
  2265. # No input
  2266. output = self.app.post("/api/0/test4/new_issue", headers=headers)
  2267. self.assertEqual(output.status_code, 400)
  2268. data = json.loads(output.get_data(as_text=True))
  2269. self.assertDictEqual(
  2270. data,
  2271. {
  2272. "error": "Invalid or incomplete input submitted",
  2273. "error_code": "EINVALIDREQ",
  2274. "errors": {
  2275. "issue_content": ["This field is required."],
  2276. "title": ["This field is required."],
  2277. },
  2278. },
  2279. )
  2280. data = {"title": "test issue"}
  2281. # Invalid repo
  2282. output = self.app.post(
  2283. "/api/0/foo/new_issue", data=data, headers=headers
  2284. )
  2285. self.assertEqual(output.status_code, 404)
  2286. data = json.loads(output.get_data(as_text=True))
  2287. self.assertDictEqual(
  2288. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  2289. )
  2290. # Incomplete request
  2291. output = self.app.post(
  2292. "/api/0/test4/new_issue", data=data, headers=headers
  2293. )
  2294. self.assertEqual(output.status_code, 400)
  2295. data = json.loads(output.get_data(as_text=True))
  2296. self.assertDictEqual(
  2297. data,
  2298. {
  2299. "error": "Invalid or incomplete input submitted",
  2300. "error_code": "EINVALIDREQ",
  2301. "errors": {
  2302. "issue_content": ["This field is required."],
  2303. "title": ["This field is required."],
  2304. },
  2305. },
  2306. )
  2307. data = {
  2308. "title": "test issue",
  2309. "issue_content": "This issue needs attention",
  2310. }
  2311. # Valid request
  2312. output = self.app.post(
  2313. "/api/0/test4/new_issue", data=data, headers=headers
  2314. )
  2315. self.assertEqual(output.status_code, 200)
  2316. data = json.loads(output.get_data(as_text=True))
  2317. data["issue"]["date_created"] = "1431414800"
  2318. data["issue"]["last_updated"] = "1431414800"
  2319. self.assertDictEqual(
  2320. data, {"issue": FULL_ISSUE_LIST[7], "message": "Issue created"}
  2321. )
  2322. def test_api_private_repo_view_issues(self):
  2323. """Test the api_view_issues method of the flask api."""
  2324. self.test_api_private_repo_new_issue()
  2325. # Invalid repo
  2326. output = self.app.get("/api/0/foo/issues")
  2327. self.assertEqual(output.status_code, 404)
  2328. data = json.loads(output.get_data(as_text=True))
  2329. self.assertDictEqual(
  2330. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  2331. )
  2332. # List all opened issues
  2333. user = tests.FakeUser(username="pingou")
  2334. with tests.user_set(self.app.application, user):
  2335. output = self.app.get("/api/0/test4/issues")
  2336. self.assertEqual(output.status_code, 200)
  2337. data = json.loads(output.get_data(as_text=True))
  2338. data["issues"][0]["date_created"] = "1431414800"
  2339. data["issues"][0]["last_updated"] = "1431414800"
  2340. for k in ["first", "last"]:
  2341. self.assertIsNotNone(data["pagination"][k])
  2342. data["pagination"][k] = "http://localhost..."
  2343. self.assertDictEqual(
  2344. data,
  2345. {
  2346. "args": {
  2347. "assignee": None,
  2348. "author": None,
  2349. "milestones": [],
  2350. "no_stones": None,
  2351. "order": None,
  2352. "priority": None,
  2353. "since": None,
  2354. "status": None,
  2355. "tags": [],
  2356. },
  2357. "total_issues": 1,
  2358. "issues": [
  2359. {
  2360. "assignee": None,
  2361. "blocks": [],
  2362. "close_status": None,
  2363. "closed_at": None,
  2364. "closed_by": None,
  2365. "comments": [],
  2366. "content": "This issue needs attention",
  2367. "custom_fields": [],
  2368. "date_created": "1431414800",
  2369. "last_updated": "1431414800",
  2370. "depends": [],
  2371. "full_url": "http://localhost.localdomain/test4/issue/1",
  2372. "id": 1,
  2373. "milestone": None,
  2374. "priority": None,
  2375. "private": False,
  2376. "related_prs": [],
  2377. "status": "Open",
  2378. "tags": [],
  2379. "title": "test issue",
  2380. "user": {
  2381. "fullname": "PY C",
  2382. "full_url": "http://localhost.localdomain/user/pingou",
  2383. "name": "pingou",
  2384. "url_path": "user/pingou",
  2385. },
  2386. }
  2387. ],
  2388. "pagination": {
  2389. "first": "http://localhost...",
  2390. "last": "http://localhost...",
  2391. "next": None,
  2392. "page": 1,
  2393. "pages": 1,
  2394. "per_page": 20,
  2395. "prev": None,
  2396. },
  2397. },
  2398. )
  2399. # Create private issue
  2400. repo = pagure.lib.query._get_project(self.session, "test4")
  2401. msg = pagure.lib.query.new_issue(
  2402. session=self.session,
  2403. repo=repo,
  2404. title="Test issue",
  2405. content="We should work on this",
  2406. user="pingou",
  2407. private=True,
  2408. )
  2409. self.session.commit()
  2410. self.assertEqual(msg.title, "Test issue")
  2411. # Private issues are retrieved
  2412. user = tests.FakeUser(username="pingou")
  2413. with tests.user_set(self.app.application, user):
  2414. output = self.app.get("/api/0/test4/issues")
  2415. self.assertEqual(output.status_code, 200)
  2416. data = json.loads(output.get_data(as_text=True))
  2417. data["issues"][0]["date_created"] = "1431414800"
  2418. data["issues"][0]["last_updated"] = "1431414800"
  2419. data["issues"][1]["date_created"] = "1431414800"
  2420. data["issues"][1]["last_updated"] = "1431414800"
  2421. for k in ["first", "last"]:
  2422. self.assertIsNotNone(data["pagination"][k])
  2423. data["pagination"][k] = "http://localhost..."
  2424. self.assertDictEqual(
  2425. data,
  2426. {
  2427. "args": {
  2428. "assignee": None,
  2429. "author": None,
  2430. "milestones": [],
  2431. "no_stones": None,
  2432. "order": None,
  2433. "priority": None,
  2434. "status": None,
  2435. "since": None,
  2436. "tags": [],
  2437. },
  2438. "issues": [
  2439. {
  2440. "assignee": None,
  2441. "blocks": [],
  2442. "close_status": None,
  2443. "closed_at": None,
  2444. "closed_by": None,
  2445. "comments": [],
  2446. "content": "We should work on this",
  2447. "custom_fields": [],
  2448. "date_created": "1431414800",
  2449. "last_updated": "1431414800",
  2450. "depends": [],
  2451. "full_url": "http://localhost.localdomain/test4/issue/2",
  2452. "id": 2,
  2453. "milestone": None,
  2454. "priority": None,
  2455. "private": True,
  2456. "related_prs": [],
  2457. "status": "Open",
  2458. "tags": [],
  2459. "title": "Test issue",
  2460. "user": {
  2461. "fullname": "PY C",
  2462. "full_url": "http://localhost.localdomain/user/pingou",
  2463. "name": "pingou",
  2464. "url_path": "user/pingou",
  2465. },
  2466. },
  2467. {
  2468. "assignee": None,
  2469. "blocks": [],
  2470. "close_status": None,
  2471. "closed_at": None,
  2472. "closed_by": None,
  2473. "comments": [],
  2474. "content": "This issue needs attention",
  2475. "custom_fields": [],
  2476. "date_created": "1431414800",
  2477. "last_updated": "1431414800",
  2478. "depends": [],
  2479. "full_url": "http://localhost.localdomain/test4/issue/1",
  2480. "id": 1,
  2481. "milestone": None,
  2482. "priority": None,
  2483. "private": False,
  2484. "related_prs": [],
  2485. "status": "Open",
  2486. "tags": [],
  2487. "title": "test issue",
  2488. "user": {
  2489. "fullname": "PY C",
  2490. "full_url": "http://localhost.localdomain/user/pingou",
  2491. "name": "pingou",
  2492. "url_path": "user/pingou",
  2493. },
  2494. },
  2495. ],
  2496. "pagination": {
  2497. "first": "http://localhost...",
  2498. "last": "http://localhost...",
  2499. "next": None,
  2500. "page": 1,
  2501. "pages": 1,
  2502. "per_page": 20,
  2503. "prev": None,
  2504. },
  2505. "total_issues": 2,
  2506. },
  2507. )
  2508. # Access issues authenticated but non-existing token
  2509. headers = {"Authorization": "token aaabbbccc"}
  2510. output = self.app.get("/api/0/test4/issues", headers=headers)
  2511. self.assertEqual(output.status_code, 401)
  2512. headers = {"Authorization": "token aaabbbcccddd"}
  2513. # Access issues authenticated correctly
  2514. output = self.app.get("/api/0/test4/issues", headers=headers)
  2515. self.assertEqual(output.status_code, 200)
  2516. data = json.loads(output.get_data(as_text=True))
  2517. data["issues"][0]["date_created"] = "1431414800"
  2518. data["issues"][0]["last_updated"] = "1431414800"
  2519. data["issues"][1]["date_created"] = "1431414800"
  2520. data["issues"][1]["last_updated"] = "1431414800"
  2521. for k in ["first", "last"]:
  2522. self.assertIsNotNone(data["pagination"][k])
  2523. data["pagination"][k] = "http://localhost..."
  2524. self.assertDictEqual(
  2525. data,
  2526. {
  2527. "args": {
  2528. "assignee": None,
  2529. "author": None,
  2530. "milestones": [],
  2531. "no_stones": None,
  2532. "order": None,
  2533. "priority": None,
  2534. "status": None,
  2535. "since": None,
  2536. "tags": [],
  2537. },
  2538. "issues": [
  2539. {
  2540. "assignee": None,
  2541. "blocks": [],
  2542. "close_status": None,
  2543. "closed_at": None,
  2544. "closed_by": None,
  2545. "comments": [],
  2546. "content": "We should work on this",
  2547. "custom_fields": [],
  2548. "date_created": "1431414800",
  2549. "last_updated": "1431414800",
  2550. "depends": [],
  2551. "full_url": "http://localhost.localdomain/test4/issue/2",
  2552. "id": 2,
  2553. "milestone": None,
  2554. "priority": None,
  2555. "private": True,
  2556. "related_prs": [],
  2557. "status": "Open",
  2558. "tags": [],
  2559. "title": "Test issue",
  2560. "user": {
  2561. "fullname": "PY C",
  2562. "full_url": "http://localhost.localdomain/user/pingou",
  2563. "name": "pingou",
  2564. "url_path": "user/pingou",
  2565. },
  2566. },
  2567. {
  2568. "assignee": None,
  2569. "blocks": [],
  2570. "close_status": None,
  2571. "closed_at": None,
  2572. "closed_by": None,
  2573. "comments": [],
  2574. "content": "This issue needs attention",
  2575. "custom_fields": [],
  2576. "date_created": "1431414800",
  2577. "last_updated": "1431414800",
  2578. "depends": [],
  2579. "full_url": "http://localhost.localdomain/test4/issue/1",
  2580. "id": 1,
  2581. "milestone": None,
  2582. "priority": None,
  2583. "private": False,
  2584. "related_prs": [],
  2585. "status": "Open",
  2586. "tags": [],
  2587. "title": "test issue",
  2588. "user": {
  2589. "fullname": "PY C",
  2590. "full_url": "http://localhost.localdomain/user/pingou",
  2591. "name": "pingou",
  2592. "url_path": "user/pingou",
  2593. },
  2594. },
  2595. ],
  2596. "pagination": {
  2597. "first": "http://localhost...",
  2598. "last": "http://localhost...",
  2599. "next": None,
  2600. "page": 1,
  2601. "pages": 1,
  2602. "per_page": 20,
  2603. "prev": None,
  2604. },
  2605. "total_issues": 2,
  2606. },
  2607. )
  2608. # List closed issue
  2609. output = self.app.get(
  2610. "/api/0/test4/issues?status=Closed", headers=headers
  2611. )
  2612. self.assertEqual(output.status_code, 200)
  2613. data = json.loads(output.get_data(as_text=True))
  2614. for k in ["first", "last"]:
  2615. self.assertIsNotNone(data["pagination"][k])
  2616. data["pagination"][k] = "http://localhost..."
  2617. self.assertDictEqual(
  2618. data,
  2619. {
  2620. "args": {
  2621. "assignee": None,
  2622. "author": None,
  2623. "milestones": [],
  2624. "no_stones": None,
  2625. "order": None,
  2626. "priority": None,
  2627. "status": "Closed",
  2628. "since": None,
  2629. "tags": [],
  2630. },
  2631. "issues": [],
  2632. "pagination": {
  2633. "first": "http://localhost...",
  2634. "last": "http://localhost...",
  2635. "next": None,
  2636. "page": 1,
  2637. "pages": 0,
  2638. "per_page": 20,
  2639. "prev": None,
  2640. },
  2641. "total_issues": 0,
  2642. },
  2643. )
  2644. # List closed issue
  2645. output = self.app.get(
  2646. "/api/0/test4/issues?status=Invalid", headers=headers
  2647. )
  2648. self.assertEqual(output.status_code, 200)
  2649. data = json.loads(output.get_data(as_text=True))
  2650. for k in ["first", "last"]:
  2651. self.assertIsNotNone(data["pagination"][k])
  2652. data["pagination"][k] = "http://localhost..."
  2653. self.assertDictEqual(
  2654. data,
  2655. {
  2656. "args": {
  2657. "assignee": None,
  2658. "author": None,
  2659. "milestones": [],
  2660. "no_stones": None,
  2661. "order": None,
  2662. "priority": None,
  2663. "status": "Invalid",
  2664. "since": None,
  2665. "tags": [],
  2666. },
  2667. "issues": [],
  2668. "pagination": {
  2669. "first": "http://localhost...",
  2670. "last": "http://localhost...",
  2671. "next": None,
  2672. "page": 1,
  2673. "pages": 0,
  2674. "per_page": 20,
  2675. "prev": None,
  2676. },
  2677. "total_issues": 0,
  2678. },
  2679. )
  2680. # List all issues
  2681. output = self.app.get(
  2682. "/api/0/test4/issues?status=All", headers=headers
  2683. )
  2684. self.assertEqual(output.status_code, 200)
  2685. data = json.loads(output.get_data(as_text=True))
  2686. data["issues"][0]["date_created"] = "1431414800"
  2687. data["issues"][0]["last_updated"] = "1431414800"
  2688. data["issues"][1]["date_created"] = "1431414800"
  2689. data["issues"][1]["last_updated"] = "1431414800"
  2690. for k in ["first", "last"]:
  2691. self.assertIsNotNone(data["pagination"][k])
  2692. data["pagination"][k] = "http://localhost..."
  2693. self.assertDictEqual(
  2694. data,
  2695. {
  2696. "args": {
  2697. "assignee": None,
  2698. "author": None,
  2699. "milestones": [],
  2700. "no_stones": None,
  2701. "order": None,
  2702. "priority": None,
  2703. "since": None,
  2704. "status": "All",
  2705. "tags": [],
  2706. },
  2707. "issues": [
  2708. {
  2709. "assignee": None,
  2710. "blocks": [],
  2711. "close_status": None,
  2712. "closed_at": None,
  2713. "closed_by": None,
  2714. "comments": [],
  2715. "content": "We should work on this",
  2716. "custom_fields": [],
  2717. "date_created": "1431414800",
  2718. "last_updated": "1431414800",
  2719. "depends": [],
  2720. "full_url": "http://localhost.localdomain/test4/issue/2",
  2721. "id": 2,
  2722. "milestone": None,
  2723. "priority": None,
  2724. "private": True,
  2725. "related_prs": [],
  2726. "status": "Open",
  2727. "tags": [],
  2728. "title": "Test issue",
  2729. "user": {
  2730. "fullname": "PY C",
  2731. "full_url": "http://localhost.localdomain/user/pingou",
  2732. "name": "pingou",
  2733. "url_path": "user/pingou",
  2734. },
  2735. },
  2736. {
  2737. "assignee": None,
  2738. "blocks": [],
  2739. "close_status": None,
  2740. "closed_at": None,
  2741. "closed_by": None,
  2742. "comments": [],
  2743. "content": "This issue needs attention",
  2744. "custom_fields": [],
  2745. "date_created": "1431414800",
  2746. "last_updated": "1431414800",
  2747. "depends": [],
  2748. "full_url": "http://localhost.localdomain/test4/issue/1",
  2749. "id": 1,
  2750. "milestone": None,
  2751. "priority": None,
  2752. "private": False,
  2753. "related_prs": [],
  2754. "status": "Open",
  2755. "tags": [],
  2756. "title": "test issue",
  2757. "user": {
  2758. "fullname": "PY C",
  2759. "full_url": "http://localhost.localdomain/user/pingou",
  2760. "name": "pingou",
  2761. "url_path": "user/pingou",
  2762. },
  2763. },
  2764. ],
  2765. "pagination": {
  2766. "first": "http://localhost...",
  2767. "last": "http://localhost...",
  2768. "next": None,
  2769. "page": 1,
  2770. "pages": 1,
  2771. "per_page": 20,
  2772. "prev": None,
  2773. },
  2774. "total_issues": 2,
  2775. },
  2776. )
  2777. def test_api_pivate_repo_view_issue(self):
  2778. """Test the api_view_issue method of the flask api."""
  2779. self.test_api_private_repo_new_issue()
  2780. # Invalid repo
  2781. output = self.app.get("/api/0/foo/issue/1")
  2782. self.assertEqual(output.status_code, 404)
  2783. data = json.loads(output.get_data(as_text=True))
  2784. self.assertDictEqual(
  2785. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  2786. )
  2787. # Invalid issue for this repo
  2788. output = self.app.get("/api/0/test4/issue/1")
  2789. self.assertEqual(output.status_code, 404)
  2790. data = json.loads(output.get_data(as_text=True))
  2791. self.assertDictEqual(
  2792. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  2793. )
  2794. # Un-authorized user
  2795. user = tests.FakeUser()
  2796. with tests.user_set(self.app.application, user):
  2797. output = self.app.get("/api/0/test4/issue/1")
  2798. self.assertEqual(output.status_code, 404)
  2799. data = json.loads(output.get_data(as_text=True))
  2800. self.assertDictEqual(
  2801. data,
  2802. {"error": "Project not found", "error_code": "ENOPROJECT"},
  2803. )
  2804. # Valid issue
  2805. user = tests.FakeUser(username="pingou")
  2806. with tests.user_set(self.app.application, user):
  2807. output = self.app.get("/api/0/test4/issue/1")
  2808. self.assertEqual(output.status_code, 200)
  2809. data = json.loads(output.get_data(as_text=True))
  2810. data["date_created"] = "1431414800"
  2811. data["last_updated"] = "1431414800"
  2812. self.assertDictEqual(
  2813. data,
  2814. {
  2815. "assignee": None,
  2816. "blocks": [],
  2817. "close_status": None,
  2818. "closed_at": None,
  2819. "closed_by": None,
  2820. "comments": [],
  2821. "content": "This issue needs attention",
  2822. "custom_fields": [],
  2823. "date_created": "1431414800",
  2824. "depends": [],
  2825. "full_url": "http://localhost.localdomain/test4/issue/1",
  2826. "id": 1,
  2827. "last_updated": "1431414800",
  2828. "milestone": None,
  2829. "priority": None,
  2830. "private": False,
  2831. "related_prs": [],
  2832. "status": "Open",
  2833. "tags": [],
  2834. "title": "test issue",
  2835. "user": {
  2836. "fullname": "PY C",
  2837. "full_url": "http://localhost.localdomain/user/pingou",
  2838. "name": "pingou",
  2839. "url_path": "user/pingou",
  2840. },
  2841. },
  2842. )
  2843. headers = {"Authorization": "token aaabbbccc"}
  2844. # Access issue authenticated but non-existing token
  2845. output = self.app.get("/api/0/test4/issue/1", headers=headers)
  2846. self.assertEqual(output.status_code, 401)
  2847. data = json.loads(output.get_data(as_text=True))
  2848. self.assertEqual(
  2849. sorted(data.keys()), ["error", "error_code", "errors"]
  2850. )
  2851. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data["error"])
  2852. self.assertEqual(
  2853. pagure.api.APIERROR.EINVALIDTOK.name, data["error_code"]
  2854. )
  2855. self.assertEqual(data["errors"], "Invalid token")
  2856. headers = {"Authorization": "token aaabbbcccddd"}
  2857. # Access issue authenticated correctly
  2858. output = self.app.get("/api/0/test4/issue/1", headers=headers)
  2859. self.assertEqual(output.status_code, 200)
  2860. data = json.loads(output.get_data(as_text=True))
  2861. data["date_created"] = "1431414800"
  2862. data["last_updated"] = "1431414800"
  2863. self.assertDictEqual(
  2864. data,
  2865. {
  2866. "assignee": None,
  2867. "blocks": [],
  2868. "close_status": None,
  2869. "closed_at": None,
  2870. "closed_by": None,
  2871. "comments": [],
  2872. "content": "This issue needs attention",
  2873. "custom_fields": [],
  2874. "date_created": "1431414800",
  2875. "depends": [],
  2876. "full_url": "http://localhost.localdomain/test4/issue/1",
  2877. "id": 1,
  2878. "last_updated": "1431414800",
  2879. "milestone": None,
  2880. "priority": None,
  2881. "private": False,
  2882. "related_prs": [],
  2883. "status": "Open",
  2884. "tags": [],
  2885. "title": "test issue",
  2886. "user": {
  2887. "fullname": "PY C",
  2888. "full_url": "http://localhost.localdomain/user/pingou",
  2889. "name": "pingou",
  2890. "url_path": "user/pingou",
  2891. },
  2892. },
  2893. )
  2894. @patch("pagure.lib.notify.send_email", MagicMock(return_value=True))
  2895. def test_api_private_repo_change_status_issue(self):
  2896. """Test the api_change_status_issue method of the flask api."""
  2897. item = pagure.lib.model.Project(
  2898. user_id=1, # pingou
  2899. name="test4",
  2900. description="test project description",
  2901. hook_token="aaabbbeeeceee",
  2902. private=True,
  2903. )
  2904. item.close_status = [
  2905. "Invalid",
  2906. "Insufficient data",
  2907. "Fixed",
  2908. "Duplicate",
  2909. ]
  2910. self.session.add(item)
  2911. self.session.commit()
  2912. for repo in ["GIT_FOLDER", "TICKETS_FOLDER"]:
  2913. # Add a git repo
  2914. repo_path = os.path.join(
  2915. pagure.config.config.get(repo), "test4.git"
  2916. )
  2917. if not os.path.exists(repo_path):
  2918. os.makedirs(repo_path)
  2919. pygit2.init_repository(repo_path, bare=True)
  2920. tests.create_tokens(self.session)
  2921. tests.create_tokens_acl(self.session)
  2922. headers = {"Authorization": "token aaabbbcccddd"}
  2923. # Invalid project
  2924. output = self.app.post("/api/0/foo/issue/1/status", headers=headers)
  2925. self.assertEqual(output.status_code, 404)
  2926. data = json.loads(output.get_data(as_text=True))
  2927. self.assertDictEqual(
  2928. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  2929. )
  2930. # Valid token, wrong project
  2931. user = tests.FakeUser(username="pingou")
  2932. with tests.user_set(self.app.application, user):
  2933. output = self.app.post(
  2934. "/api/0/test2/issue/1/status", headers=headers
  2935. )
  2936. self.assertEqual(output.status_code, 404)
  2937. data = json.loads(output.get_data(as_text=True))
  2938. self.assertDictEqual(
  2939. data,
  2940. {"error": "Project not found", "error_code": "ENOPROJECT"},
  2941. )
  2942. # No input
  2943. output = self.app.post("/api/0/test4/issue/1/status", headers=headers)
  2944. self.assertEqual(output.status_code, 404)
  2945. data = json.loads(output.get_data(as_text=True))
  2946. self.assertDictEqual(
  2947. data, {"error": "Issue not found", "error_code": "ENOISSUE"}
  2948. )
  2949. # Create normal issue
  2950. repo = pagure.lib.query._get_project(self.session, "test4")
  2951. msg = pagure.lib.query.new_issue(
  2952. session=self.session,
  2953. repo=repo,
  2954. title="Test issue #1",
  2955. content="We should work on this",
  2956. user="pingou",
  2957. private=False,
  2958. )
  2959. self.session.commit()
  2960. self.assertEqual(msg.title, "Test issue #1")
  2961. # Check status before
  2962. repo = pagure.lib.query._get_project(self.session, "test4")
  2963. issue = pagure.lib.query.search_issues(self.session, repo, issueid=1)
  2964. self.assertEqual(issue.status, "Open")
  2965. data = {"title": "test issue"}
  2966. user = tests.FakeUser(username="pingou")
  2967. with tests.user_set(self.app.application, user):
  2968. # Incomplete request
  2969. output = self.app.post(
  2970. "/api/0/test4/issue/1/status", data=data, headers=headers
  2971. )
  2972. self.assertEqual(output.status_code, 400)
  2973. data = json.loads(output.get_data(as_text=True))
  2974. expected_output = {
  2975. "error": "Invalid or incomplete input submitted",
  2976. "error_code": "EINVALIDREQ",
  2977. "errors": {"status": ["Not a valid choice"]},
  2978. }
  2979. if self.get_wtforms_version() >= (3, 0):
  2980. expected_output["errors"]["status"] = ["Not a valid choice."]
  2981. self.assertDictEqual(data, expected_output)
  2982. # No change
  2983. repo = pagure.lib.query._get_project(self.session, "test4")
  2984. issue = pagure.lib.query.search_issues(
  2985. self.session, repo, issueid=1
  2986. )
  2987. self.assertEqual(issue.status, "Open")
  2988. data = {"status": "Open"}
  2989. # Valid request but no change
  2990. output = self.app.post(
  2991. "/api/0/test4/issue/1/status", data=data, headers=headers
  2992. )
  2993. self.assertEqual(output.status_code, 200)
  2994. data = json.loads(output.get_data(as_text=True))
  2995. self.assertDictEqual(data, {"message": "No changes"})
  2996. # No change
  2997. repo = pagure.lib.query._get_project(self.session, "test4")
  2998. issue = pagure.lib.query.search_issues(
  2999. self.session, repo, issueid=1
  3000. )
  3001. self.assertEqual(issue.status, "Open")
  3002. data = {"status": "Fixed"}
  3003. # Valid request
  3004. output = self.app.post(
  3005. "/api/0/test4/issue/1/status", data=data, headers=headers
  3006. )
  3007. self.assertEqual(output.status_code, 200)
  3008. data = json.loads(output.get_data(as_text=True))
  3009. self.assertDictEqual(
  3010. data,
  3011. {
  3012. "message": [
  3013. "Issue status updated to: Closed (was: Open)",
  3014. "Issue close_status updated to: Fixed",
  3015. ]
  3016. },
  3017. )
  3018. @patch("pagure.lib.git.update_git")
  3019. @patch("pagure.lib.notify.send_email")
  3020. def test_api_private_repo_comment_issue(self, p_send_email, p_ugt):
  3021. """Test the api_comment_issue method of the flask api."""
  3022. p_send_email.return_value = True
  3023. p_ugt.return_value = True
  3024. item = pagure.lib.model.Project(
  3025. user_id=1, # pingou
  3026. name="test4",
  3027. description="test project description",
  3028. hook_token="aaabbbeeeceee",
  3029. private=True,
  3030. )
  3031. self.session.add(item)
  3032. self.session.commit()
  3033. tests.create_tokens(self.session)
  3034. tests.create_tokens_acl(self.session)
  3035. headers = {"Authorization": "token aaabbbcccddd"}
  3036. # Invalid project
  3037. output = self.app.post("/api/0/foo/issue/1/comment", headers=headers)
  3038. self.assertEqual(output.status_code, 404)
  3039. data = json.loads(output.get_data(as_text=True))
  3040. self.assertDictEqual(
  3041. data, {"error": "Project not found", "error_code": "ENOPROJECT"}
  3042. )
  3043. # Invalid token, right project
  3044. headers = {"Authorization": "token aaabbbccc"}
  3045. output = self.app.post("/api/0/test4/issue/1/comment", headers=headers)
  3046. self.assertEqual(output.status_code, 401)
  3047. data = json.loads(output.get_data(as_text=True))
  3048. self.assertEqual(
  3049. sorted(data.keys()), ["error", "error_code", "errors"]
  3050. )
  3051. self.assertEqual(pagure.api.APIERROR.EINVALIDTOK.value, data["error"])
  3052. self.assertEqual(
  3053. pagure.api.APIERROR.EINVALIDTOK.name, data["error_code"]
  3054. )
  3055. self.assertEqual(data["errors"], "Invalid token")
  3056. headers = {"Authorization": "token aaabbbcccddd"}
  3057. # No input
  3058. output = self.app.post("/api/0/test4/issue/1/comment", headers=headers)
  3059. self.assertEqual(output.status_code, 404)
  3060. data = json.loads(output.get_data(as_text=True))
  3061. self.assertDictEqual(
  3062. data, {"error": "Issue not found", "error_code": "ENOISSUE"}
  3063. )
  3064. # Create normal issue
  3065. repo = pagure.lib.query._get_project(self.session, "test4")
  3066. msg = pagure.lib.query.new_issue(
  3067. session=self.session,
  3068. repo=repo,
  3069. title="Test issue #1",
  3070. content="We should work on this",
  3071. user="pingou",
  3072. private=False,
  3073. issue_uid="aaabbbccc1",
  3074. )
  3075. self.session.commit()
  3076. self.assertEqual(msg.title, "Test issue #1")
  3077. # Check comments before
  3078. self.session.commit()
  3079. repo = pagure.lib.query._get_project(self.session, "test4")
  3080. issue = pagure.lib.query.search_issues(self.session, repo, issueid=1)
  3081. self.assertEqual(len(issue.comments), 0)
  3082. data = {"title": "test issue"}
  3083. # Incomplete request
  3084. output = self.app.post(
  3085. "/api/0/test4/issue/1/comment", data=data, headers=headers
  3086. )
  3087. self.assertEqual(output.status_code, 400)
  3088. data = json.loads(output.get_data(as_text=True))
  3089. self.assertDictEqual(
  3090. data,
  3091. {
  3092. "error": "Invalid or incomplete input submitted",
  3093. "error_code": "EINVALIDREQ",
  3094. "errors": {"comment": ["This field is required."]},
  3095. },
  3096. )
  3097. # No change
  3098. self.session.commit()
  3099. repo = pagure.lib.query._get_project(self.session, "test4")
  3100. issue = pagure.lib.query.search_issues(self.session, repo, issueid=1)
  3101. self.assertEqual(issue.status, "Open")
  3102. data = {"comment": "This is a very interesting question"}
  3103. # Valid request
  3104. output = self.app.post(
  3105. "/api/0/test4/issue/1/comment", data=data, headers=headers
  3106. )
  3107. self.assertEqual(output.status_code, 200)
  3108. data = json.loads(output.get_data(as_text=True))
  3109. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  3110. self.assertDictEqual(
  3111. data,
  3112. {
  3113. "message": "Comment added",
  3114. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  3115. "user": "pingou",
  3116. },
  3117. )
  3118. # One comment added
  3119. self.session.commit()
  3120. repo = pagure.lib.query._get_project(self.session, "test4")
  3121. issue = pagure.lib.query.search_issues(self.session, repo, issueid=1)
  3122. self.assertEqual(len(issue.comments), 1)
  3123. @patch("pagure.lib.git.update_git")
  3124. @patch("pagure.lib.notify.send_email")
  3125. def test_api_view_issue_comment(self, p_send_email, p_ugt):
  3126. """Test the api_view_issue_comment endpoint."""
  3127. p_send_email.return_value = True
  3128. p_ugt.return_value = True
  3129. self.test_api_private_repo_comment_issue()
  3130. # View a comment that does not exist
  3131. output = self.app.get("/api/0/foo/issue/100/comment/2")
  3132. self.assertEqual(output.status_code, 404)
  3133. # Issue exists but not the comment
  3134. output = self.app.get("/api/0/test/issue/1/comment/2")
  3135. self.assertEqual(output.status_code, 404)
  3136. # Issue and comment exists
  3137. output = self.app.get("/api/0/test/issue/1/comment/1")
  3138. self.assertEqual(output.status_code, 404)
  3139. user = tests.FakeUser(username="pingou")
  3140. with tests.user_set(self.app.application, user):
  3141. output = self.app.get("/api/0/test4/issue/1/comment/1")
  3142. self.assertEqual(output.status_code, 200)
  3143. data = json.loads(output.get_data(as_text=True))
  3144. data["date_created"] = "1435821770"
  3145. data["comment_date"] = "2015-07-02 09:22"
  3146. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  3147. self.assertDictEqual(
  3148. data,
  3149. {
  3150. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  3151. "comment": "This is a very interesting question",
  3152. "comment_date": "2015-07-02 09:22",
  3153. "notification": False,
  3154. "date_created": "1435821770",
  3155. "edited_on": None,
  3156. "editor": None,
  3157. "id": 1,
  3158. "parent": None,
  3159. "reactions": {},
  3160. "user": {
  3161. "fullname": "PY C",
  3162. "full_url": "http://localhost.localdomain/user/pingou",
  3163. "name": "pingou",
  3164. "url_path": "user/pingou",
  3165. },
  3166. },
  3167. )
  3168. # Issue and comment exists, using UID
  3169. output = self.app.get("/api/0/test4/issue/aaabbbccc1/comment/1")
  3170. self.assertEqual(output.status_code, 200)
  3171. data = json.loads(output.get_data(as_text=True))
  3172. data["date_created"] = "1435821770"
  3173. data["comment_date"] = "2015-07-02 09:22"
  3174. data["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  3175. self.assertDictEqual(
  3176. data,
  3177. {
  3178. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  3179. "comment": "This is a very interesting question",
  3180. "comment_date": "2015-07-02 09:22",
  3181. "notification": False,
  3182. "date_created": "1435821770",
  3183. "edited_on": None,
  3184. "editor": None,
  3185. "id": 1,
  3186. "parent": None,
  3187. "reactions": {},
  3188. "user": {
  3189. "fullname": "PY C",
  3190. "full_url": "http://localhost.localdomain/user/pingou",
  3191. "name": "pingou",
  3192. "url_path": "user/pingou",
  3193. },
  3194. },
  3195. )
  3196. if __name__ == "__main__":
  3197. unittest.main(verbosity=2)