test_pagure_lib_git_auth_paguregitauth.py 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. # -*- coding: utf-8 -*-
  2. """
  3. (c) 2019-2019 - 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 json
  10. import os
  11. import sys
  12. from mock import Mock
  13. sys.path.insert(
  14. 0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")
  15. )
  16. import pagure.lib.query
  17. import tests
  18. from pagure.config import config as pagure_config
  19. from pagure.lib.repo import PagureRepo
  20. class PagureLibGitAuthPagureGitAuthtests(tests.Modeltests):
  21. """Tests for pagure.lib.git_auth PagureGitAuth dynamic ACL"""
  22. config_values = {"authbackend": "pagure"}
  23. def setUp(self):
  24. super(PagureLibGitAuthPagureGitAuthtests, self).setUp()
  25. tests.create_projects(self.session)
  26. tests.create_tokens(self.session)
  27. tests.create_tokens_acl(self.session)
  28. self.create_project_full("acltest")
  29. project = pagure.lib.query._get_project(self.session, "acltest")
  30. # Create non-push deploy key
  31. non_push_dkey = pagure.lib.model.SSHKey(
  32. project_id=project.id,
  33. pushaccess=False,
  34. public_ssh_key="\n foo bar",
  35. ssh_short_key="\n foo bar",
  36. ssh_search_key="\n foo bar",
  37. creator_user_id=1, # pingou
  38. )
  39. self.session.add(non_push_dkey)
  40. # Create push deploy key
  41. push_dkey = pagure.lib.model.SSHKey(
  42. project_id=project.id,
  43. pushaccess=True,
  44. public_ssh_key="\n bar foo",
  45. ssh_short_key="\n bar foo",
  46. ssh_search_key="\n bar foo",
  47. creator_user_id=1, # pingou
  48. )
  49. self.session.add(push_dkey)
  50. self.session.commit()
  51. # Allow the user foo to commit to project test on epel* branches
  52. msg = pagure.lib.query.add_user_to_project(
  53. self.session,
  54. project=project,
  55. new_user="foo",
  56. user="pingou",
  57. access="collaborator",
  58. branches="epel*",
  59. )
  60. self.session.commit()
  61. def create_fork(self):
  62. # Create fork
  63. headers = {"Authorization": "token aaabbbcccddd"}
  64. data = {"repo": "acltest"}
  65. output = self.app.post("/api/0/fork/", data=data, headers=headers)
  66. self.assertEqual(output.status_code, 200)
  67. data = json.loads(output.get_data(as_text=True))
  68. self.assertDictEqual(
  69. data, {"message": 'Repo "acltest" cloned to "pingou/acltest"'}
  70. )
  71. CASES = (
  72. # Internal push
  73. {
  74. "internal": True,
  75. "username": "foo",
  76. "project_pr_only": False,
  77. "global_pr_only": False,
  78. "project": {"name": "acltest"},
  79. "ref": "refs/heads/master",
  80. "repotype": "main",
  81. "expected_messages": ["Internal push allowed"],
  82. "expected_result": True,
  83. },
  84. # Globally PR required push: PR merges are always internal
  85. {
  86. "internal": False,
  87. "username": "foo",
  88. "project_pr_only": False,
  89. "global_pr_only": True,
  90. "project": {"name": "acltest"},
  91. "ref": "refs/heads/master",
  92. "repotype": "main",
  93. "expected_messages": ["Pull request required"],
  94. "expected_result": False,
  95. },
  96. # GLobally PR required, push is to fork
  97. {
  98. "internal": False,
  99. "username": "foo",
  100. "project_pr_only": False,
  101. "global_pr_only": True,
  102. "project": {"name": "acltest", "user": "pingou"},
  103. "ref": "refs/heads/master",
  104. "repotype": "main",
  105. "expected_messages": ["Has commit access: False"],
  106. "expected_result": False,
  107. },
  108. # PR required push: PR merges are always internal
  109. {
  110. "internal": False,
  111. "username": "foo",
  112. "project_pr_only": True,
  113. "global_pr_only": False,
  114. "project": {"name": "acltest"},
  115. "ref": "refs/heads/master",
  116. "repotype": "main",
  117. "expected_messages": ["Pull request required"],
  118. "expected_result": False,
  119. },
  120. # PR required for main repo, but not for ticket
  121. {
  122. "internal": False,
  123. "username": "foo",
  124. "project_pr_only": True,
  125. "global_pr_only": False,
  126. "project": {"name": "acltest"},
  127. "ref": "refs/heads/master",
  128. "repotype": "ticket",
  129. "expected_messages": ["Has commit access: False"],
  130. "expected_result": False,
  131. },
  132. # Non-push deploy key
  133. {
  134. "internal": False,
  135. "username": "deploykey_acltest_1",
  136. "project_pr_only": False,
  137. "global_pr_only": False,
  138. "project": {"name": "acltest"},
  139. "ref": "refs/heads/master",
  140. "repotype": "main",
  141. "expected_messages": [
  142. "Deploykey used. Push access: False",
  143. "Has commit access: False",
  144. ],
  145. "expected_result": False,
  146. },
  147. # Push deploy key
  148. {
  149. "internal": False,
  150. "username": "deploykey_acltest_2",
  151. "project_pr_only": False,
  152. "global_pr_only": False,
  153. "project": {"name": "acltest"},
  154. "ref": "refs/heads/master",
  155. "repotype": "main",
  156. "expected_messages": [
  157. "Deploykey used. Push access: True",
  158. "Has commit access: True",
  159. ],
  160. "expected_result": True,
  161. },
  162. # Non-committer
  163. {
  164. "internal": False,
  165. "username": "foo",
  166. "project_pr_only": False,
  167. "global_pr_only": False,
  168. "project": {"name": "acltest"},
  169. "ref": "refs/heads/master",
  170. "repotype": "main",
  171. "expected_messages": ["Has commit access: False"],
  172. "expected_result": False,
  173. },
  174. # Committer
  175. {
  176. "internal": False,
  177. "username": "pingou",
  178. "project_pr_only": False,
  179. "global_pr_only": False,
  180. "project": {"name": "acltest"},
  181. "ref": "refs/heads/master",
  182. "repotype": "main",
  183. "expected_messages": ["Has commit access: True"],
  184. "expected_result": True,
  185. },
  186. # Contributor invalid branch
  187. {
  188. "internal": False,
  189. "username": "foo",
  190. "project_pr_only": False,
  191. "global_pr_only": False,
  192. "project": {"name": "acltest"},
  193. "ref": "refs/heads/master",
  194. "repotype": "main",
  195. "expected_messages": ["Has commit access: False"],
  196. "expected_result": False,
  197. },
  198. # Contributor valid branch epel-foo
  199. {
  200. "internal": False,
  201. "username": "foo",
  202. "project_pr_only": False,
  203. "global_pr_only": False,
  204. "project": {"name": "acltest"},
  205. "ref": "refs/heads/epel-foo",
  206. "repotype": "main",
  207. "expected_messages": ["Has commit access: True"],
  208. "expected_result": True,
  209. },
  210. # Contributor valid branch epel
  211. {
  212. "internal": False,
  213. "username": "foo",
  214. "project_pr_only": False,
  215. "global_pr_only": False,
  216. "project": {"name": "acltest"},
  217. "ref": "refs/heads/epel",
  218. "repotype": "main",
  219. "expected_messages": ["Has commit access: True"],
  220. "expected_result": True,
  221. },
  222. )
  223. def test_cases(self):
  224. self.create_fork()
  225. ga = pagure.lib.git_auth.PagureGitAuth()
  226. ga.info = Mock()
  227. casenum = 0
  228. for case in self.CASES:
  229. casenum += 1
  230. print("Case %d: %s" % (casenum, case))
  231. project = pagure.lib.query._get_project(
  232. self.session, **case["project"]
  233. )
  234. # Set global PR setting
  235. pagure_config["PR_ONLY"] = case["global_pr_only"]
  236. # Set per-project PR setting
  237. curset = project.settings
  238. curset["pull_request_access_only"] = case["project_pr_only"]
  239. project.settings = curset
  240. self.session.commit()
  241. result = ga.check_acl(
  242. session=self.session,
  243. project=project,
  244. username=case["username"],
  245. refname=case["ref"],
  246. pull_request=None,
  247. repotype=case["repotype"],
  248. is_internal=case["internal"],
  249. )
  250. print("Result: %s" % result)
  251. self.assertEqual(
  252. result,
  253. case["expected_result"],
  254. "Expected result not met in case %s" % case,
  255. )
  256. print("Correct result")
  257. self.assertListEqual(
  258. case["expected_messages"],
  259. [info_call[0][0] for info_call in ga.info.call_args_list],
  260. )
  261. print("Correct messages")
  262. ga.info.reset_mock()