test_pagure_flask_api_ui_private_repo.py 110 KB

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