test_pagure_flask_api_ui_private_repo.py 110 KB

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