test_pagure_flask_api_ui_private_repo.py 123 KB

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