test_pagure_lib_git_auth.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. # -*- coding: utf-8 -*-
  2. """
  3. (c) 2015-2018 - Copyright Red Hat Inc
  4. Authors:
  5. Pierre-Yves Chibon <pingou@pingoured.fr>
  6. Patrick Uiterwijk <patrick@puiterwijk.org>
  7. """
  8. from __future__ import unicode_literals, absolute_import
  9. import datetime
  10. import os
  11. import shutil
  12. import sys
  13. import tempfile
  14. import time
  15. import unittest
  16. import pygit2
  17. import six
  18. from mock import patch, MagicMock
  19. sys.path.insert(
  20. 0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")
  21. )
  22. import pagure.lib.git
  23. import pagure.lib.query
  24. import tests
  25. from pagure.lib.repo import PagureRepo
  26. class PagureLibGitAuthtests(tests.Modeltests):
  27. """ Tests for pagure.lib.git_auth """
  28. config_values = {"authbackend": "test_auth"}
  29. def setUp(self):
  30. super(PagureLibGitAuthtests, self).setUp()
  31. tests.create_projects(self.session)
  32. tests.create_tokens(self.session)
  33. tests.create_tokens_acl(self.session)
  34. self.create_project_full("hooktest")
  35. def test_edit_with_all_allowed(self):
  36. """Tests that editing a file is possible if ACLs say allowed."""
  37. user = tests.FakeUser()
  38. user.username = "pingou"
  39. with tests.user_set(self.app.application, user):
  40. # Add some content to the git repo
  41. tests.add_content_git_repo(
  42. os.path.join(self.path, "repos", "hooktest.git")
  43. )
  44. data = {
  45. "content": "foo\n bar\n baz",
  46. "commit_title": "test commit",
  47. "commit_message": "Online commits from the gure.lib.get",
  48. "email": "bar@pingou.com",
  49. "branch": "master",
  50. "csrf_token": self.get_csrf(),
  51. }
  52. output = self.app.post(
  53. "/hooktest/edit/master/f/sources",
  54. data=data,
  55. follow_redirects=True,
  56. )
  57. self.assertEqual(output.status_code, 200)
  58. output_text = output.get_data(as_text=True)
  59. self.assertIn(
  60. "<title>Commits - hooktest - Pagure</title>", output_text
  61. )
  62. self.assertIn("test commit", output_text)
  63. # Check file after the commit
  64. output = self.app.get("/hooktest/raw/master/f/sources")
  65. self.assertEqual(output.status_code, 200)
  66. output_text = output.get_data(as_text=True)
  67. self.assertEqual(output_text, "foo\n bar\n baz")
  68. def test_edit_with_all_denied(self):
  69. """Tests that editing a file is not possible if ACLs say denied."""
  70. self.set_auth_status(False)
  71. user = tests.FakeUser()
  72. user.username = "pingou"
  73. with tests.user_set(self.app.application, user):
  74. # Add some content to the git repo
  75. tests.add_content_git_repo(
  76. os.path.join(self.path, "repos", "hooktest.git")
  77. )
  78. data = {
  79. "content": "foo\n bar\n baz",
  80. "commit_title": "test commit",
  81. "commit_message": "Online commits from the gure.lib.get",
  82. "email": "bar@pingou.com",
  83. "branch": "master",
  84. "csrf_token": self.get_csrf(),
  85. }
  86. output = self.app.post(
  87. "/hooktest/edit/master/f/sources",
  88. data=data,
  89. follow_redirects=True,
  90. )
  91. self.assertEqual(output.status_code, 200)
  92. output_text = output.get_data(as_text=True)
  93. self.assertIn(
  94. "Remote hook declined the push: "
  95. "Denied push for ref &#39;refs/heads/master&#39; for user &#39;pingou&#39;",
  96. output_text,
  97. )
  98. self.assertIn("All changes have been rejected", output_text)
  99. # Check file after the commit:
  100. output = self.app.get("/hooktest/raw/master/f/sources")
  101. self.assertEqual(output.status_code, 200)
  102. output_text = output.get_data(as_text=True)
  103. self.assertEqual(output_text, "foo\n bar")
  104. def test_edit_pr(self):
  105. """Tests the ACLs if they only accept PRs."""
  106. self.set_auth_status(
  107. {"refs/heads/master": "pronly", "refs/heads/source": True}
  108. )
  109. user = tests.FakeUser()
  110. user.username = "pingou"
  111. with tests.user_set(self.app.application, user):
  112. # Add some content to the git repo
  113. tests.add_content_git_repo(
  114. os.path.join(self.path, "repos", "hooktest.git")
  115. )
  116. # Try editing master branch, should fail (only PRs allowed)
  117. data = {
  118. "content": "foo\n bar\n baz",
  119. "commit_title": "test commit",
  120. "commit_message": "Online commits from the gure.lib.get",
  121. "email": "bar@pingou.com",
  122. "branch": "master",
  123. "csrf_token": self.get_csrf(),
  124. }
  125. output = self.app.post(
  126. "/hooktest/edit/master/f/sources",
  127. data=data,
  128. follow_redirects=True,
  129. )
  130. self.assertEqual(output.status_code, 200)
  131. output_text = output.get_data(as_text=True)
  132. self.assertIn(
  133. "Remote hook declined the push: "
  134. "Denied push for ref &#39;refs/heads/master&#39; for user &#39;pingou&#39;",
  135. output_text,
  136. )
  137. self.assertIn("All changes have been rejected", output_text)
  138. # Change something in the "source" branch
  139. data = {
  140. "content": "foo\n bar\n baz",
  141. "commit_title": "test commit",
  142. "commit_message": "Online commits from the gure.lib.get",
  143. "email": "bar@pingou.com",
  144. "branch": "source",
  145. "csrf_token": self.get_csrf(),
  146. }
  147. output = self.app.post(
  148. "/hooktest/edit/master/f/sources",
  149. data=data,
  150. follow_redirects=True,
  151. )
  152. self.assertEqual(output.status_code, 200)
  153. output_text = output.get_data(as_text=True)
  154. self.assertIn(
  155. "<title>Commits - hooktest - Pagure</title>", output_text
  156. )
  157. self.assertIn("test commit", output_text)
  158. # Check file after the commit:
  159. output = self.app.get("/hooktest/raw/source/f/sources")
  160. self.assertEqual(output.status_code, 200)
  161. output_text = output.get_data(as_text=True)
  162. self.assertEqual(output_text, "foo\n bar\n baz")
  163. # Create the PRs
  164. project = pagure.lib.query.get_authorized_project(
  165. self.session, "hooktest"
  166. )
  167. req = pagure.lib.query.new_pull_request(
  168. session=self.session,
  169. repo_from=project,
  170. branch_from="source",
  171. repo_to=project,
  172. branch_to="master",
  173. title="PR to master",
  174. user="pingou",
  175. )
  176. self.session.add(req)
  177. self.session.commit()
  178. # Check file before the merge
  179. output = self.app.get("/hooktest/raw/master/f/sources")
  180. self.assertEqual(output.status_code, 200)
  181. output_text = output.get_data(as_text=True)
  182. self.assertEqual(output_text, "foo\n bar")
  183. # Try to merge (should work)
  184. output = self.app.post(
  185. "/hooktest/pull-request/1/merge",
  186. data=data,
  187. follow_redirects=True,
  188. )
  189. self.assertEqual(output.status_code, 200)
  190. output_text = output.get_data(as_text=True)
  191. self.assertIn(
  192. "<title>PR#1: PR to master - hooktest\n - Pagure</title>",
  193. output_text,
  194. )
  195. # Check file after the merge
  196. output = self.app.get("/hooktest/raw/master/f/sources")
  197. self.assertEqual(output.status_code, 200)
  198. output_text = output.get_data(as_text=True)
  199. self.assertEqual(output_text, "foo\n bar\n baz")
  200. class PagureLibGitAuthPagureBackendtests(tests.Modeltests):
  201. """ Tests for pagure.lib.git_auth """
  202. config_values = {"authbackend": "pagure"}
  203. def setUp(self):
  204. super(PagureLibGitAuthPagureBackendtests, self).setUp()
  205. tests.create_projects(self.session)
  206. tests.create_tokens(self.session)
  207. tests.create_tokens_acl(self.session)
  208. self.create_project_full("hooktest")
  209. def test_edit_no_commit(self):
  210. user = tests.FakeUser()
  211. user.username = "foo"
  212. with tests.user_set(self.app.application, user):
  213. # Add some content to the git repo
  214. tests.add_content_git_repo(
  215. os.path.join(self.path, "repos", "hooktest.git")
  216. )
  217. data = {
  218. "content": "foo\n bar\n baz",
  219. "commit_title": "test commit",
  220. "commit_message": "Online commits from the gure.lib.get",
  221. "email": "bar@pingou.com",
  222. "branch": "master",
  223. "csrf_token": self.get_csrf(),
  224. }
  225. output = self.app.post(
  226. "/hooktest/edit/master/f/sources",
  227. data=data,
  228. follow_redirects=True,
  229. )
  230. self.assertEqual(output.status_code, 403)
  231. output_text = output.get_data(as_text=True)
  232. self.assertIn(
  233. "You are not allowed to edit files in this project",
  234. output_text,
  235. )
  236. # Check file after the commit:
  237. output = self.app.get("/hooktest/raw/master/f/sources")
  238. self.assertEqual(output.status_code, 200)
  239. output_text = output.get_data(as_text=True)
  240. self.assertEqual(output_text, "foo\n bar")
  241. def test_edit_ticket_rejected(self):
  242. project = pagure.lib.query._get_project(self.session, "hooktest")
  243. # Add user foo to project test
  244. msg = pagure.lib.query.add_user_to_project(
  245. self.session,
  246. project=project,
  247. new_user="foo",
  248. user="pingou",
  249. access="ticket",
  250. branches="epel*",
  251. )
  252. self.session.commit()
  253. user = tests.FakeUser()
  254. user.username = "foo"
  255. with tests.user_set(self.app.application, user):
  256. # Add some content to the git repo
  257. tests.add_content_git_repo(
  258. os.path.join(self.path, "repos", "hooktest.git")
  259. )
  260. data = {
  261. "content": "foo\n bar\n baz",
  262. "commit_title": "test commit",
  263. "commit_message": "Online commits from the gure.lib.get",
  264. "email": "foo@bar.com",
  265. "branch": "master",
  266. "csrf_token": self.get_csrf(),
  267. }
  268. output = self.app.post(
  269. "/hooktest/edit/master/f/sources",
  270. data=data,
  271. follow_redirects=True,
  272. )
  273. self.assertEqual(output.status_code, 403)
  274. output_text = output.get_data(as_text=True)
  275. self.assertIn(
  276. "You are not allowed to edit files in this project",
  277. output_text,
  278. )
  279. # Check file after the commit:
  280. output = self.app.get("/hooktest/raw/master/f/sources")
  281. self.assertEqual(output.status_code, 200)
  282. output_text = output.get_data(as_text=True)
  283. self.assertEqual(output_text, "foo\n bar")
  284. def test_edit_contributor_rejected(self):
  285. project = pagure.lib.query._get_project(self.session, "hooktest")
  286. # Add user foo to project test
  287. msg = pagure.lib.query.add_user_to_project(
  288. self.session,
  289. project=project,
  290. new_user="foo",
  291. user="pingou",
  292. access="collaborator",
  293. branches="epel*",
  294. )
  295. self.session.commit()
  296. user = tests.FakeUser()
  297. user.username = "foo"
  298. with tests.user_set(self.app.application, user):
  299. # Add some content to the git repo
  300. tests.add_content_git_repo(
  301. os.path.join(self.path, "repos", "hooktest.git")
  302. )
  303. data = {
  304. "content": "foo\n bar\n baz",
  305. "commit_title": "test commit",
  306. "commit_message": "Online commits from the gure.lib.get",
  307. "email": "foo@bar.com",
  308. "branch": "master",
  309. "csrf_token": self.get_csrf(),
  310. }
  311. output = self.app.post(
  312. "/hooktest/edit/master/f/sources",
  313. data=data,
  314. follow_redirects=True,
  315. )
  316. self.assertEqual(output.status_code, 403)
  317. output_text = output.get_data(as_text=True)
  318. self.assertIn(
  319. "You are not allowed to edit files in this project",
  320. output_text,
  321. )
  322. # Check file after the commit:
  323. output = self.app.get("/hooktest/raw/master/f/sources")
  324. self.assertEqual(output.status_code, 200)
  325. output_text = output.get_data(as_text=True)
  326. self.assertEqual(output_text, "foo\n bar")
  327. def test_edit_contributor_passed_epel8(self):
  328. project = pagure.lib.query._get_project(self.session, "hooktest")
  329. # Add user foo to project test
  330. msg = pagure.lib.query.add_user_to_project(
  331. self.session,
  332. project=project,
  333. new_user="foo",
  334. user="pingou",
  335. access="collaborator",
  336. branches="epel*",
  337. )
  338. self.session.commit()
  339. user = tests.FakeUser()
  340. user.username = "foo"
  341. with tests.user_set(self.app.application, user):
  342. # Add some content to the git repo
  343. tests.add_content_git_repo(
  344. os.path.join(self.path, "repos", "hooktest.git")
  345. )
  346. data = {
  347. "content": "foo\n bar\n baz",
  348. "commit_title": "test commit",
  349. "commit_message": "Online commits from the gure.lib.get",
  350. "email": "foo@bar.com",
  351. "branch": "epel8",
  352. "csrf_token": self.get_csrf(),
  353. }
  354. output = self.app.post(
  355. "/hooktest/edit/master/f/sources",
  356. data=data,
  357. follow_redirects=True,
  358. )
  359. self.assertEqual(output.status_code, 200)
  360. output_text = output.get_data(as_text=True)
  361. self.assertIn(
  362. "<title>Commits - hooktest - Pagure</title>", output_text
  363. )
  364. # Check file after the commit:
  365. # master did not change
  366. output = self.app.get("/hooktest/raw/master/f/sources")
  367. self.assertEqual(output.status_code, 200)
  368. output_text = output.get_data(as_text=True)
  369. self.assertEqual(output_text, "foo\n bar")
  370. # epel8 did change
  371. output = self.app.get("/hooktest/raw/epel8/f/sources")
  372. self.assertEqual(output.status_code, 200)
  373. output_text = output.get_data(as_text=True)
  374. self.assertEqual(output_text, "foo\n bar\n baz")
  375. def test_edit_commit_passed_epel8(self):
  376. project = pagure.lib.query._get_project(self.session, "hooktest")
  377. # Add user foo to project test
  378. msg = pagure.lib.query.add_user_to_project(
  379. self.session,
  380. project=project,
  381. new_user="foo",
  382. user="pingou",
  383. access="commit",
  384. branches="epel*",
  385. )
  386. self.session.commit()
  387. user = tests.FakeUser()
  388. user.username = "foo"
  389. with tests.user_set(self.app.application, user):
  390. # Add some content to the git repo
  391. tests.add_content_git_repo(
  392. os.path.join(self.path, "repos", "hooktest.git")
  393. )
  394. data = {
  395. "content": "foo\n bar\n baz",
  396. "commit_title": "test commit",
  397. "commit_message": "Online commits from the gure.lib.get",
  398. "email": "foo@bar.com",
  399. "branch": "epel8",
  400. "csrf_token": self.get_csrf(),
  401. }
  402. output = self.app.post(
  403. "/hooktest/edit/master/f/sources",
  404. data=data,
  405. follow_redirects=True,
  406. )
  407. self.assertEqual(output.status_code, 200)
  408. output_text = output.get_data(as_text=True)
  409. self.assertIn(
  410. "<title>Commits - hooktest - Pagure</title>", output_text
  411. )
  412. # Check file after the commit:
  413. # master did not change
  414. output = self.app.get("/hooktest/raw/master/f/sources")
  415. self.assertEqual(output.status_code, 200)
  416. output_text = output.get_data(as_text=True)
  417. self.assertEqual(output_text, "foo\n bar")
  418. # epel8 did change
  419. output = self.app.get("/hooktest/raw/epel8/f/sources")
  420. self.assertEqual(output.status_code, 200)
  421. output_text = output.get_data(as_text=True)
  422. self.assertEqual(output_text, "foo\n bar\n baz")
  423. def test_edit_contributor_passed_epel(self):
  424. # Same test as above but the target branch change
  425. project = pagure.lib.query._get_project(self.session, "hooktest")
  426. # Add user foo to project test
  427. msg = pagure.lib.query.add_user_to_project(
  428. self.session,
  429. project=project,
  430. new_user="foo",
  431. user="pingou",
  432. access="collaborator",
  433. branches="epel*",
  434. )
  435. self.session.commit()
  436. user = tests.FakeUser()
  437. user.username = "foo"
  438. with tests.user_set(self.app.application, user):
  439. # Add some content to the git repo
  440. tests.add_content_git_repo(
  441. os.path.join(self.path, "repos", "hooktest.git")
  442. )
  443. data = {
  444. "content": "foo\n bar\n baz",
  445. "commit_title": "test commit",
  446. "commit_message": "Online commits from the gure.lib.get",
  447. "email": "foo@bar.com",
  448. "branch": "epel",
  449. "csrf_token": self.get_csrf(),
  450. }
  451. output = self.app.post(
  452. "/hooktest/edit/master/f/sources",
  453. data=data,
  454. follow_redirects=True,
  455. )
  456. self.assertEqual(output.status_code, 200)
  457. output_text = output.get_data(as_text=True)
  458. self.assertIn(
  459. "<title>Commits - hooktest - Pagure</title>", output_text
  460. )
  461. # Check file after the commit:
  462. # master did not change
  463. output = self.app.get("/hooktest/raw/master/f/sources")
  464. self.assertEqual(output.status_code, 200)
  465. output_text = output.get_data(as_text=True)
  466. self.assertEqual(output_text, "foo\n bar")
  467. # epel did change
  468. output = self.app.get("/hooktest/raw/epel/f/sources")
  469. self.assertEqual(output.status_code, 200)
  470. output_text = output.get_data(as_text=True)
  471. self.assertEqual(output_text, "foo\n bar\n baz")
  472. def test_edit_contributor_passed_epel_no_regex(self):
  473. # Same test as above but the allowed branch has no regex
  474. project = pagure.lib.query._get_project(self.session, "hooktest")
  475. # Add user foo to project test
  476. msg = pagure.lib.query.add_user_to_project(
  477. self.session,
  478. project=project,
  479. new_user="foo",
  480. user="pingou",
  481. access="collaborator",
  482. branches="epel",
  483. )
  484. self.session.commit()
  485. user = tests.FakeUser()
  486. user.username = "foo"
  487. with tests.user_set(self.app.application, user):
  488. # Add some content to the git repo
  489. tests.add_content_git_repo(
  490. os.path.join(self.path, "repos", "hooktest.git")
  491. )
  492. data = {
  493. "content": "foo\n bar\n baz",
  494. "commit_title": "test commit",
  495. "commit_message": "Online commits from the gure.lib.get",
  496. "email": "foo@bar.com",
  497. "branch": "epel",
  498. "csrf_token": self.get_csrf(),
  499. }
  500. output = self.app.post(
  501. "/hooktest/edit/master/f/sources",
  502. data=data,
  503. follow_redirects=True,
  504. )
  505. self.assertEqual(output.status_code, 200)
  506. output_text = output.get_data(as_text=True)
  507. self.assertIn(
  508. "<title>Commits - hooktest - Pagure</title>", output_text
  509. )
  510. # Check file after the commit:
  511. # master did not change
  512. output = self.app.get("/hooktest/raw/master/f/sources")
  513. self.assertEqual(output.status_code, 200)
  514. output_text = output.get_data(as_text=True)
  515. self.assertEqual(output_text, "foo\n bar")
  516. # epel did change
  517. output = self.app.get("/hooktest/raw/epel/f/sources")
  518. self.assertEqual(output.status_code, 200)
  519. output_text = output.get_data(as_text=True)
  520. self.assertEqual(output_text, "foo\n bar\n baz")
  521. def test_edit_contributor_denied_epel8_no_regex(self):
  522. # Same test as above but the allowed branch has no regex
  523. project = pagure.lib.query._get_project(self.session, "hooktest")
  524. # Add user foo to project test
  525. msg = pagure.lib.query.add_user_to_project(
  526. self.session,
  527. project=project,
  528. new_user="foo",
  529. user="pingou",
  530. access="collaborator",
  531. branches="epel",
  532. )
  533. self.session.commit()
  534. user = tests.FakeUser()
  535. user.username = "foo"
  536. with tests.user_set(self.app.application, user):
  537. # Add some content to the git repo
  538. tests.add_content_git_repo(
  539. os.path.join(self.path, "repos", "hooktest.git")
  540. )
  541. data = {
  542. "content": "foo\n bar\n baz",
  543. "commit_title": "test commit",
  544. "commit_message": "Online commits from the gure.lib.get",
  545. "email": "foo@bar.com",
  546. "branch": "epel8",
  547. "csrf_token": self.get_csrf(),
  548. }
  549. output = self.app.post(
  550. "/hooktest/edit/master/f/sources",
  551. data=data,
  552. follow_redirects=True,
  553. )
  554. self.assertEqual(output.status_code, 403)
  555. output_text = output.get_data(as_text=True)
  556. self.assertIn(
  557. "You are not allowed to edit files in this project",
  558. output_text,
  559. )
  560. # Check file after the commit:
  561. # epel not found
  562. output = self.app.get("/hooktest/raw/epel8/f/sources")
  563. self.assertEqual(output.status_code, 404)