test_pagure_lib_git_auth.py 23 KB

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