#61 Rewrote to integrate CentOS and use dynamic backend
Merged 7 years ago by pingou. Opened 7 years ago by puiterwijk.
puiterwijk/pagure-dist-git reworked  into  master

file modified
+55 -5
@@ -3,12 +3,62 @@ 

  

  .. split here

  

- Since 3.0 pagure offers a way to customize the creation and compilation the of

- the gitolite configuration file.

+ This project implements a dynamic Git auth backend for Pagure for Fedora and CentOS

+ dist-git setups, which have slightly different access models than standard on Pagure.

+ 

+ Configuration

+ =============

+ 

+ This plugin reuses the Pagure configuration, and adds several keys to it.

+ 

+ ACL_DEBUG: Whether to print some output with information decisions are based on.

+ ACL_PROTECTED_NAMESPACES: List of namespaces where the extra strong protections are in place.

+ BLACKLIST_RES: List of regular expressions with refs that can never be pushed.

+ ACL_BLOCK_UNSPECIFIED: Whether to deny pushes to branches that aren't either RCM, SIG or supported branches.

+ UNSPECIFIED_BLACKLIST_RES: List of regular expressions with refs that can't be used if unspecified.

+ RCM_BRANCHES: List of regular expressions with refs that people in the RCM group can push.

+ RCM_GROUP: The group containing RCM members

+ SUPPORTED_SIGS: List of groups that grant access to sig_prefix-$signame-* refs.

+ SIG_PREFIXES: List of prefixes for SIG refs.

+ 

+ 

+ Example configurations

+ ======================

+ 

+ Fedora

+ ------

+ 

+ ````

+ ACL_DEBUG = False

+ ACL_BLOCK_UNSPECIFIED = False

+ ACL_PROTECTED_NAMESPACES = ['rpms', 'modules', 'container']

+ RCM_GROUP = 'relenggroup'

+ RCM_BRANCHES = ['refs/heads/f[0-9]+']

+ # Pushing to c* stuff is never allowed

+ BLACKLIST_RES = ['refs/heads/c[0-9]+.*']

+ # Pushing to (f|epel|el|olpc)(num+) that is not previously approved

+ # (supported branches) is not allowed.

+ UNSPECIFIED_BLACKLIST_RES = ['refs/heads/f[0-9]+',

+                              'refs/heads/epel[0-9]+',

+                              'refs/heads/el[0-9]+',

+                              'refs/heads/olpc[0-9]+']

+ ````

+ 

+ CentOS

+ ------

+ 

+ ````

+ SIG_PREFIXES = ['refs/heads/c7', 'refs/heads/c7-plus', 'refs/heads/c7-alt', ]

+ SUPPORTED_SIGS = ['sig-atomic', 'sig-cloud', 'sig-core', 'sig-storage', ]

+ 

+ # Branches to which *nobody* will be able to push (basically Fedora)

+ BLACKLIST_RES = ['refs/heads/el[0-9]+.*', 'refs/heads/olpc[0-9]+.*', ]

+ 

+ ### Specific ACO group that will have access to all protected branches with RWC rights

+ RCM_GROUP = 'centos-rcm'

+ RCM_BRANCHES = ['refs/heads/c[0-9]+.*', 'refs/tags/.*', ]

+ ````

  

- This project hosts the logic to generate gitolite's configuration file for

- dist-git which has a different access model than regular projects on pagure (for

- example, forced pushed is forbidden).

  

  Tests

  =====

file modified
+254 -155
@@ -1,177 +1,276 @@ 

  # -*- coding: utf-8 -*-

  

  """

-  (c) 2017 - Copyright Red Hat Inc

+  (c) 2017 - 2018 - Copyright Red Hat Inc

  

-  Authors:  The Dream Team

-    Pierre-Yves Chibon <pingou@pingoured.fr>

-    Ralph Bean <rbean@redhat.com>

+  Authors:

+    Patrick Uiterwijk <puiterwijk@redhat.com>

+ 

+    The Dream Team

+      Pierre-Yves Chibon <pingou@pingoured.fr>

+      Ralph Bean <rbean@redhat.com>

  

  """

  from __future__ import print_function

  

  import logging

+ import re

  import os

  

- import pdc_client

- import werkzeug

- 

- if 'PAGURE_CONFIG' not in os.environ \

-         and os.path.exists('/etc/pagure/pagure.cfg'):

-     os.environ['PAGURE_CONFIG'] = '/etc/pagure/pagure.cfg'

+ try:

+     from pdc_client import PDCClient

+ except ImportError:

+     PDCClient = None

  

- import pagure  # noqa: E402

- from pagure.config import config  # noqa: E402

- from pagure.lib import model  # noqa: E402

- from pagure.lib.git_auth import Gitolite3Auth, _read_file  # noqa: E402

  

+ if "PAGURE_CONFIG" not in os.environ and os.path.exists(

+     "/etc/pagure/pagure.cfg"

+ ):

+     os.environ["PAGURE_CONFIG"] = "/etc/pagure/pagure.cfg"

  

- _NOT_PROVENPACKAGER = ['rpms/firefox', 'rpms/thunderbird', 'rpms/xulrunner']

+ from pagure.config import config as pagure_config

+ from pagure.lib import model, get_user

+ from pagure.lib.git import is_forced_push

+ from pagure.lib.git_auth import GitAuthHelper, _read_file

+ from pagure.utils import is_repo_committer

  

  _log = logging.getLogger(__name__)

  

  

- _blacklist = '''  -    f[0-9][0-9] = @all

-   -    epel[0-9] = @all

-   -    epel[0-9][0-9] = @all

-   -    el[0-9] = @all

-   -    olpc[0-9] = @all'''

- 

- namespace2pdctype = {

-     'rpms': 'rpm',

-     'modules': 'module',

-     'container': 'container',

- }

- 

- 

- def get_supported_branches(namespace, package):

-     default_url = 'https://pdc.fedoraproject.org/rest_api/v1/'

-     url = config.get('PDC_URL', default_url)

-     pdc = pdc_client.PDCClient(url, develop=True)

-     _log.info('Querying PDC for %s/%s' % (namespace, package))

-     kwargs = dict(

-         global_component=package,

-         type=namespace2pdctype[namespace],

-         active=True,  # Not EOL.

-     )

-     branches = pdc.get_paged(pdc['component-branches'], **kwargs)

-     return [branch['name'] for branch in branches]

- 

- 

- class DistGitoliteAuth(Gitolite3Auth):

-     """ A dist-git's gitolite authentication module. """

- 

-     @staticmethod

-     def _get_gitolite_command():

-         """ Return the gitolite command to run based on the info in the

-         configuration file.

+ class DistGitAuth(GitAuthHelper):

+     """ A Fedora and CentOS dist-Git authentication module. """

+     is_dynamic = True

+ 

+     def __init__(self):

+         super(DistGitAuth, self).__init__()

+ 

+         self.is_debug = pagure_config.get("ACL_DEBUG", False)

+         self.global_pr_only = pagure_config.get("PR_ONLY", False)

+         self.block_unspecified = pagure_config.get("ACL_BLOCK_UNSPECIFIED",

+                                                    True)

+         self.blacklists = [re.compile(refre)

+                            for refre

+                            in pagure_config["BLACKLIST_RES"]]

+         self.unspecified_blacklist = [

+             re.compile(refre)

+             for refre

+             in pagure_config.get("UNSPECIFIED_BLACKLIST_RES", [])]

+         self.rcm_branches = [re.compile(refre)

+                              for refre

+                              in pagure_config["RCM_BRANCHES"]]

+         self.rcm_group = pagure_config.get("RCM_GROUP")

+         self.supported_sigs = set(pagure_config.get("SUPPORTED_SIGS", []))

+         self.sig_prefixes = pagure_config.get("SIG_PREFIXES", [])

+         self.protected_namespaces = pagure_config.get(

+             "ACL_PROTECTED_NAMESPACES", ["rpms"])

+ 

+         pdc_url = pagure_config.get('PDC_URL')

+         if pdc_url and PDCClient:

+             self.pdcclient = PDCClient(pdc_url, develop=True)

+         else:

+             self.pdcclient = None

+ 

+     def is_supported_branch(self, project, refname):

+         """ Returns whether a specific branch is currently supported for Fedora

+ 

+         This retrieves the information about EOL status from PDC, to prevent

+         EOL branches being pushed to.

          """

-         _log.info('Compiling the gitolite configuration')

-         gitolite_folder = config.get('GITOLITE_HOME', None)

-         if gitolite_folder:

-             cmd = 'HOME=%s gitolite compile' % (gitolite_folder)

-             _log.debug('Command: %s', cmd)

-             return cmd

+         if not self.pdcclient:

+             # No way to confirm this is a supported branch, not supported

+             return None

+         if not refname.startswith('refs/heads/'):

+             # Anything outside of refs/heads is out-of-scope

+             return None

+         refname = refname[len('refs/heads/'):]

+ 

+         namespace2pdctype = {

+             'rpms': 'rpm',

+             'modules': 'module',

+             'container': 'container',

+         }

+         res = list(self.pdcclient.get_paged(

+             self.pdcclient['component-branches'],

+             global_component=project.name,

+             type=namespace2pdctype[project.namespace],

+             name=refname,

+             fields=['active'],

+         ))

+         if len(res) == 0:

+             # No status

+             return None

+         if len(res) != 1:

+             # PDC couldn't make up its mind....

+             # Should never happen, but just in case...

+             raise ValueError("PDC was unable to make up its mind")

+         return res[0]['active']

+ 

+     def info(self, msg):

+         """ Function to print information.

+ 

+         Is a function to help with the test suite. """

+         print(msg)

+ 

+     def debug(self, msg):

+         """ Function to print if in debug mode.

+ 

+         Function to help in test. """

+         if self.is_debug:

+             self.info(msg)

+ 

+     def check_acl(

+         self,

+         session,

+         project,

+         username,

+         refname,

+         pull_request,

+         repodir,

+         repotype,

+         revfrom,

+         revto,

+         is_internal,

+         **info

+     ):

+         """ Perform dynamic ACL checks.

+ 

+         For arguments, see GitAuthHelper.check_acl."""

+ 

+         # First, some rules regardless of user status

+         # Only the "main" and "requests" repos are used

+         if repotype not in ("main", "requests"):

+             self.info("Repotype %s not in use" % repotype)

+             return False

+ 

+         # Do not allow branch deletions

+         if revto == '0'*40:

+             self.info("Branch deletion is not allowed")

+             return False

+ 

+         # Do not allow non-fast-forward pushes for anything but forks

+         if not project.is_fork and is_forced_push(revfrom, revto, repodir):

+             self.info("Forced pushes are not allowed")

+             return False

+ 

+         # If this is pushed through internal changes, approve.

+         # This flag is only provided if it's either an update to the "side"

+         # repos, or during creation/forking of a project.

+         if is_internal:

+             self.info("Internal push allowed")

+             return True

+ 

+         # Deploy Keys are not allowed on dist-git

+         if username.startswith("deploykey_"):

+             self.info("Deploy keys are disabled")

+             return False

+ 

+         # Now build up info about the user and project to make decisions

+         # Determine the users' groups

+         user = get_user(session, username)

+         usergroups = set(user.groups)

+ 

+         # Determine whether the user is a committer

+         is_committer = is_repo_committer(project, username, session)

+ 

+         # Determine whether the user is a SIG member

+         user_sigs = self.supported_sigs & usergroups

+ 

+         # Determine whether the user is RCM

+         is_rcm = bool(self.rcm_group and self.rcm_group in usergroups)

+ 

+         # If configured, print user info

+         self.debug("Protected namespaces: %s" % self.protected_namespaces)

+         self.debug("Blocking unspecified refs: %s" % self.block_unspecified)

+         self.debug("Blacklists: %s" % self.blacklists)

+         self.debug("User: %s" % user)

+         self.debug("User groups: %s" % usergroups)

+         self.debug('Committer: %s' % is_committer)

+         self.debug('SIG memberships: %s' % user_sigs)

+         self.debug('RCM: %s' % is_rcm)

+ 

+         # We have data, start the actual ACL checking

+         if (

+             repotype == "main"

+             and not project.is_fork

+             and project.namespace in self.protected_namespaces

+         ):

+             # In the protected namespace, we want to make sure we don't

+             # trample on blacklisted content.

+             for entry in self.blacklists:

+                 if entry.match(refname):

+                     self.info("Ref %s is blocked" % refname)

+                     return False

+ 

+             # Allow RCM push

+             if is_rcm:

+                 for refre in self.rcm_branches:

+                     if refre.match(refname):

+                         # RCM on an RCM branch -> allow

+                         self.debug("RCM push")

+                         return True

+ 

+             # Allow CentOS SIGs to push to e.g. c7-sig-core-$anything

+             for signame in user_sigs:

+                 for sigprefix in self.sig_prefixes:

+                     sigbranch = "%s-%s-" % (sigprefix, signame)

+                     if refname.startswith(sigbranch):

+                         self.debug("SIG push")

+                         return True

+ 

+             # For Fedora, allow supported branches

+             is_supported = self.is_supported_branch(project, refname)

+             if is_supported is False:

+                 self.info("Branch %s is unsupported" % refname)

+                 return False

+             elif is_supported is True:

+                 self.debug("Branch %s is supported" % refname)

+                 return is_committer

+             else:

+                 self.debug("No supported status available")

+ 

+             if self.block_unspecified:

+                 self.info("Access to namespace %s is restricted"

+                           % project.namespace)

+                 return False

+ 

+             # Block second level blacklists

+             for entry in self.unspecified_blacklist:

+                 if entry.match(refname):

+                     self.info("Unspecified ref %s is blocked" % refname)

+                     return False

+ 

+             # For unspecified refs, they can push if they're a committer

+             self.debug("Unspecified branch push")

+             return is_committer

+ 

+         # This is outside of the strongly protected namespaces

+         if repotype == "main":

+             # If this project has PRs only on, or PRs are globally enforced and

+             # this is not a fork, only allow pushing if this is a PR merge.

+             pr_only = project.settings.get("pull_request_access_only", False)

+             if (

+                 pr_only

+                 or (self.global_pr_only and not project.is_fork)

+                 and pull_request is None

+             ):

+                 self.info("A pull request is required for this branch")

+                 return False

+ 

+         # This is an unprotected namespace, let's allow committers

+         if is_committer:

+             self.debug("Committer push to unprotected")

+             return True

+ 

+         # If all else fails, deny

+         self.info("Fall-through deny")

+         return False

  

      @classmethod

-     def _process_project(cls, project, config, global_pr_only):

-         """ Generate the gitolite configuration for the specified project.

- 

-         :arg project: the project to generate the configuration for

-         :type project: pagure.lib.model.Project

-         :arg config: a list containing the different lines of the

-             configuration file

-         :type config: list

-         :arg global_pr_only: boolean on whether the pagure instance enforces

-             the PR workflow only or not

-         :type global_pr_only: bool

-         :return: the updated config

-         :return type: list

- 

-         """

- 

-         _log.debug('    Processing project: %s', project.fullname)

+     def generate_acls(cls, project, group=None):

+         """ Required function that doesn't do anything. """

+         pass

  

-         # Check if the project or the pagure instance enforce the PR

-         # only development model.

-         pr_only = project.settings.get('pull_request_access_only', False)

- 

-         for repos in ['repos', 'requests/']:

-             if repos == 'repos':

-                 config.append('repo %s' % project.fullname)

- 

-                 # Add ACL for mass rebuilds, even in PR-only

-                 config.append('  RW  = releng')

- 

-                 # Do not grant access to project enforcing the PR model

-                 if pr_only or (global_pr_only and not project.is_fork):

-                     continue

-                 repos = ''

-             else:

-                 config.append('repo %s%s' % (repos, project.fullname))

- 

-             if repos not in ['tickets/', 'requests/']:

-                 config.append('  R   = @all')

- 

-             access = 'RWC'

-             if project.is_fork:

-                 access = 'RW+C'

- 

-             users = sorted(set([project.user.user]).union(

-                 set(

-                     user.user

-                     for user in project.committers

-                     if user != project.user)))

-             groups = sorted(set(

-                 group.group_name

-                 for group in project.committer_groups

-             ))

- 

-             if repos == '' and not project.is_fork:

-                 if project.fullname not in _NOT_PROVENPACKAGER:

-                     groups.append('provenpackager')

-                 # First, whitelist the supported branches from PDC

-                 for branch in get_supported_branches(

-                         project.namespace, project.name):

-                     config.append('  %s %s = %s' % (

-                         access, branch, ' '.join(users)

-                         )

-                     )

-                     if groups:

-                         config.append('  %s %s = @%s' % (

-                             access, branch, ' @'.join(groups)

-                             )

-                         )

- 

-                 # Then, blacklist a pattern over that (after).

-                 config.append(_blacklist)

- 

-             if groups:

-                 config.append('  %s = @%s' % (access, ' @'.join(groups)))

- 

-             config.append('  %s = %s' % (access, ' '.join(users)))

- 

-             for deploykey in project.deploykeys:

-                 access = 'R'

-                 if deploykey.pushaccess:

-                     access = 'RW'

-                     if project.is_fork:

-                         access = 'RW+C'

-                 # Note: the replace of / with _ is because gitolite

-                 # users can't contain a /. At first, this might look

-                 # like deploy keys in a project called

-                 # $namespace_$project would give access to the repos of

-                 # a project $namespace/$project or vica versa, however

-                 # this is NOT the case because we add the deploykey.id

-                 # to the end of the deploykey name, which means it is

-                 # unique. The project name is solely there to make it

-                 # easier to determine what project created the deploykey

-                 # for admins.

-                 config.append('  %s = deploykey_%s_%s' %

-                               (access,

-                                werkzeug.secure_filename(project.fullname),

-                                deploykey.id))

- 

-             config.append('')

- 

-         return config

+     @classmethod

+     def remove_acls(cls, session, project):

+         """ Required function that is unused. """

+         pass

file modified
+626 -484
@@ -3,539 +3,681 @@ 

  import tempfile

  import os

  

- import mock

+ from mock import Mock, patch

  

  # These are the tests from the pagure/ git repo.

  # Run with:

  # PYTHONPATH=.:/path/to/pagure/checkout nosetests dist_git_auth_tests.py

  import pagure

+ import pagure.lib

  import tests

  

  import dist_git_auth

  

  

- expected = """

- repo test

-   RW  = releng

-   R   = @all

-   RWC master = pingou

-   RWC master = @provenpackager

-   RWC f9000 = pingou

-   RWC f9000 = @provenpackager

-   -    f[0-9][0-9] = @all

-   -    epel[0-9] = @all

-   -    epel[0-9][0-9] = @all

-   -    el[0-9] = @all

-   -    olpc[0-9] = @all

-   RWC = @provenpackager

-   RWC = pingou

- 

- repo requests/test

-   RWC = pingou

- 

- repo test2

-   RW  = releng

-   R   = @all

-   RWC master = pingou

-   RWC master = @provenpackager

-   RWC f9000 = pingou

-   RWC f9000 = @provenpackager

-   -    f[0-9][0-9] = @all

-   -    epel[0-9] = @all

-   -    epel[0-9][0-9] = @all

-   -    el[0-9] = @all

-   -    olpc[0-9] = @all

-   RWC = @provenpackager

-   RWC = pingou

- 

- repo requests/test2

-   RWC = pingou

- 

- repo somenamespace/test3

-   RW  = releng

-   R   = @all

-   RWC master = pingou

-   RWC master = @provenpackager

-   RWC f9000 = pingou

-   RWC f9000 = @provenpackager

-   -    f[0-9][0-9] = @all

-   -    epel[0-9] = @all

-   -    epel[0-9][0-9] = @all

-   -    el[0-9] = @all

-   -    olpc[0-9] = @all

-   RWC = @provenpackager

-   RWC = pingou

- 

- repo requests/somenamespace/test3

-   RWC = pingou

- 

- # end of body

- """

- 

- 

- class DistGitoliteAuthTestCase(tests.Modeltests):

-     """ Test generating the gitolite configuration file for dist-git. """

+ def setUp():

+     tests.setUp()

+ 

+ 

+ def tearDown():

+     tests.tearDown()

+ 

+ 

+ def patch_pdc(values):

+     """ Decorator to patch the PDC calls to return values for this test.

+ 

+     Args:

+         values (dict): A dictionary where the keys are project fullnames

+             (i.e. namespace/name), and the values are dicts with key branch

+             names, and values their supported status.

+             Note that as namespace, the PDC "type" is used, which lacks the "s"

+             for rpms and modules.

+             e.g.: {'rpm/test': {'f28': True, 'f27': False}}

+     """

+     def pdc_get_paged(_, global_component, type, name, fields):

+         """ Function that emulates the pdc.get_paged call

+ 

+         Args as provided by dist_git_auth's calls to it.

+ 

+         Args:

+             _ (anything): PDCClient internal

+             global_component (string): package name

+             type (string): The PDC "type": "rpm", "module", ...

+             name (string): The branch name

+             fields (list): Always ["active"]

+         """

+         fullname = '%s/%s' % (type, global_component)

+         if fullname not in values:

+             return []

+         val = values[fullname]

+         if name not in val:

+             return []

+         val = val[name]

+         if val in (True, False):

+             return [{"active": val}]

+         # This case is used to emulate "weird" results

+         return val

+ 

+     def decorator(func):

+         def test_wrapper(*args, **kwargs):

+             with patch.object(dist_git_auth.PDCClient, '__getitem__'):

+                 with patch.object(dist_git_auth.PDCClient, 'get_paged',

+                                   side_effect=pdc_get_paged):

+                     return func(*args, **kwargs)

+         return test_wrapper

+     return decorator

+ 

+ 

+ class DistGitAuthTests(tests.Modeltests):

+     """ Test DistGitAuth ACLs with Fedora config. """

  

      maxDiff = None

  

      def setUp(self):

          """ Set up the environment in which to run the tests. """

-         super(DistGitoliteAuthTestCase, self).setUp()

-         self.configfile = tempfile.mkstemp()[1]

+         super(DistGitAuthTests, self).setUp()

+ 

+         pagure.config.config['ACL_DEBUG'] = True

+         pagure.config.config.update(self.dga_config)

+ 

+         self.dga = dist_git_auth.DistGitAuth()

+         self.dga.info = Mock(side_effect=print)

+         # We default to saying it's not a forced push

+         dist_git_auth.is_forced_push = Mock(return_value=False)

+ 

+         # Create an RCM user/group

+         rcmuser = pagure.lib.model.User(

+             user='releng',

+             fullname='Release Engineering',

+             token='aaabbbcd',

+             default_email='rcm@local.local',

+         )

+         self.session.add(rcmuser)

+         self.session.flush()

+         rcmgroup = pagure.lib.model.PagureGroup(

+             group_name='relenggroup',

+             group_type='user',

+             display_name='Releng group',

+             user_id=rcmuser.id,

+         )

+         self.session.add(rcmgroup)

+         self.session.flush()

+         rcmuser.group_objs.append(rcmgroup)

+         self.session.commit()

  

      def tearDown(self):

          """ Tear down the environment in which the tests ran. """

-         try:

-             os.remove(self.configfile)

-         except:

-             print("Couldn't remove %r" % self.configfile)

-             pass

-         super(DistGitoliteAuthTestCase, self).tearDown()

- 

-     @mock.patch('dist_git_auth.get_supported_branches')

-     def test_write_gitolite_acls(self, get_supported_branches):

-         """ Test generating the entire gitolite configuration file

-         (project == -1).

+         self.dga = None

+         super(DistGitAuthTests, self).tearDown()

  

-         """

-         get_supported_branches.return_value = ['master', 'f9000']

-         print("Initializing DB.")

-         tests.create_projects(self.session)

+     def create_namespaced_project(self, namespace, name, is_fork=False):

+         item = pagure.lib.model.Project(

+             user_id=1,  # pingou

+             name=name,

+             is_fork=is_fork,

+             parent_id=3 if is_fork else None,

+             description='namespaced test project',

+             hook_token='aaabbbeee',

+             namespace=namespace,

+         )

+         item.close_status = [

+             'Invalid', 'Insufficient data', 'Fixed', 'Duplicate']

+         self.session.add(item)

+         self.session.commit()

+         return pagure.lib._get_project(

+             self.session, name=name, namespace=namespace)

+ 

+     def expect_info_msg(self, expect_msg):

+         found = False

+         for call in self.dga.info.call_args_list:

+             args = call[0]

+             msg = args[0]

+             if msg == expect_msg:

+                 found = True

+         if not found:

+             raise AssertionError(

+                 "Info message '%s' expected but not found" % expect_msg)

+ 

+ 

+ class DistGitAuthTestsGeneric(DistGitAuthTests):

+     dga_config = {}

+ 

+     def test_unused_repotype(self):

+         self.assertFalse(

+             self.dga.check_acl(

+                 self.session,

+                 project=None,

+                 username=None,

+                 refname=None,

+                 pull_request=None,

+                 repodir=None,

+                 repotype='tickets',

+                 revfrom=None,

+                 revto=None,

+                 is_internal=False,

+             )

+         )

  

-         print("Generating %r" % self.configfile)

-         dist_git_auth.DistGitoliteAuth.write_gitolite_acls(

-             self.session,

-             configfile=self.configfile,

-             project=-1)

+         self.expect_info_msg("Repotype tickets not in use")

+ 

+     def test_branch_deletion(self):

+         dist_git_auth.is_forced_push.return_value = True

+ 

+         project = self.create_namespaced_project('rpms', 'test')

+ 

+         self.assertFalse(

+             self.dga.check_acl(

+                 self.session,

+                 project=project,

+                 username=None,

+                 refname=None,

+                 pull_request=None,

+                 repodir=None,

+                 repotype='main',

+                 revfrom=None,

+                 revto='0000000000000000000000000000000000000000',

+                 is_internal=False,

+             )

+         )

  

-         print("Checking the contents of %r" % self.configfile)

-         with open(self.configfile, 'r') as f:

-             contents = f.read()

-         self.assertMultiLineEqual(contents.strip(), expected.strip())

+         self.expect_info_msg("Branch deletion is not allowed")

+ 

+     def test_forced_push(self):

+         dist_git_auth.is_forced_push.return_value = True

+ 

+         project = self.create_namespaced_project('rpms', 'test')

+ 

+         self.assertFalse(

+             self.dga.check_acl(

+                 self.session,

+                 project=project,

+                 username=None,

+                 refname=None,

+                 pull_request=None,

+                 repodir=None,

+                 repotype='main',

+                 revfrom=None,

+                 revto=None,

+                 is_internal=False,

+             )

+         )

  

-     @mock.patch('dist_git_auth.get_supported_branches')

-     def test_write_gitolite_acls_none_project(self, get_supported_branches):

-         """ Test not touching the gitolite configuration file

-         (project == None).

+         self.expect_info_msg("Forced pushes are not allowed")

+ 

+     def test_internal(self):

+         project = self.create_namespaced_project('rpms', 'test')

+ 

+         self.assertTrue(

+             self.dga.check_acl(

+                 self.session,

+                 project=project,

+                 username=None,

+                 refname=None,

+                 pull_request=None,

+                 repodir=None,

+                 repotype='main',

+                 revfrom=None,

+                 revto=None,

+                 is_internal=True,

+             )

+         )

  

-         """

-         get_supported_branches.return_value = ['master', 'f9000']

-         print("Initializing DB.")

-         tests.create_projects(self.session)

+         self.expect_info_msg("Internal push allowed")

+ 

+     def test_deploykey(self):

+         project = self.create_namespaced_project('rpms', 'test')

+ 

+         self.assertFalse(

+             self.dga.check_acl(

+                 self.session,

+                 project=project,

+                 username="deploykey_foobar",

+                 refname=None,

+                 pull_request=None,

+                 repodir=None,

+                 repotype='main',

+                 revfrom=None,

+                 revto=None,

+                 is_internal=False,

+             )

+         )

+ 

+         self.expect_info_msg("Deploy keys are disabled")

  

-         print("Generating %r" % self.configfile)

-         dist_git_auth.DistGitoliteAuth.write_gitolite_acls(

+     def test_invalid_user(self):

+         project = self.create_namespaced_project('rpms', 'test')

+ 

+         self.assertRaises(

+             pagure.exceptions.PagureException,

+             self.dga.check_acl,

              self.session,

-             configfile=self.configfile,

-             project=None)

+             project=project,

+             username="nosuchuser",

+             refname=None,

+             pull_request=None,

+             repodir=None,

+             repotype='main',

+             revfrom=None,

+             revto=None,

+             is_internal=False,

+         )

  

-         print("Checking the contents of %r" % self.configfile)

-         with open(self.configfile, 'r') as f:

-             contents = f.read()

-         self.assertMultiLineEqual(contents.strip(), '')

+     def test_unprotected_committer(self):

+         project = self.create_namespaced_project('unprotected', 'test')

+ 

+         self.assertTrue(

+             self.dga.check_acl(

+                 self.session,

+                 project=project,

+                 username="pingou",

+                 refname="refs/heads/mywip",

+                 pull_request=None,

+                 repodir=None,

+                 repotype='main',

+                 revfrom=None,

+                 revto=None,

+                 is_internal=False,

+             )

+         )

  

-     @mock.patch('dist_git_auth.get_supported_branches')

-     def test_write_gitolite_acls_test_project(self, get_supported_branches):

-         """ Test updating the gitolite configuration file for just one

-         project (project == a pagure.lib.model.Project).

+         self.expect_info_msg("Committer push to unprotected")

+ 

+     def test_unprotected_non_committer(self):

+         project = self.create_namespaced_project('unprotected', 'test')

+ 

+         self.assertFalse(

+             self.dga.check_acl(

+                 self.session,

+                 project=project,

+                 username="foo",

+                 refname="refs/heads/mywip",

+                 pull_request=None,

+                 repodir=None,

+                 repotype='main',

+                 revfrom=None,

+                 revto=None,

+                 is_internal=False,

+             )

+         )

  

-         """

+         self.expect_info_msg("Fall-through deny")

+ 

+     def test_unprotected_pr_required_pr(self):

+         project = self.create_namespaced_project('unprotected', 'test')

+         self.dga.global_pr_only = True

+ 

+         self.assertTrue(

+             self.dga.check_acl(

+                 self.session,

+                 project=project,

+                 username="pingou",

+                 refname="refs/heads/mywip",

+                 pull_request=True,

+                 repodir=None,

+                 repotype='main',

+                 revfrom=None,

+                 revto=None,

+                 is_internal=False,

+             )

+         )

  

-         get_supported_branches.return_value = ['master', 'f9000']

-         self.test_write_gitolite_acls()

+         self.expect_info_msg("Committer push to unprotected")

+ 

+     def test_unprotected_pr_required_no_pr(self):

+         project = self.create_namespaced_project('unprotected', 'test')

+         self.dga.global_pr_only = True

+ 

+         self.assertFalse(

+             self.dga.check_acl(

+                 self.session,

+                 project=project,

+                 username="pingou",

+                 refname="refs/heads/mywip",

+                 pull_request=None,

+                 repodir=None,

+                 repotype='main',

+                 revfrom=None,

+                 revto=None,

+                 is_internal=False,

+             )

+         )

  

-         print("Modifying the test project so the output differs.")

-         project = pagure.lib._get_project(self.session, 'test')

-         project.user_id = 2

-         self.session.add(project)

-         self.session.commit()

+         self.expect_info_msg("A pull request is required for this branch")

+ 

+     def test_unprotected_pr_required_requests(self):

+         project = self.create_namespaced_project('unprotected', 'test')

+         self.dga.global_pr_only = True

+ 

+         self.assertTrue(

+             self.dga.check_acl(

+                 self.session,

+                 project=project,

+                 username="pingou",

+                 refname="refs/heads/mywip",

+                 pull_request=None,

+                 repodir=None,

+                 repotype='requests',

+                 revfrom=None,

+                 revto=None,

+                 is_internal=False,

+             )

+         )

  

-         project = pagure.lib._get_project(self.session, 'test')

-         msg = pagure.lib.add_user_to_project(

-             self.session,

-             project=project,

-             new_user='pingou',

-             user='foo',

-             access='commit'

+         self.expect_info_msg("Committer push to unprotected")

+ 

+ 

+ class DistGitAuthTestsFedora(DistGitAuthTests):

+     dga_config = {

+         'PR_ONLY': False,

+         'ACL_BLOCK_UNSPECIFIED': False,

+         'BLACKLIST_RES': ['refs/heads/c[0-9]+.*'],

+         'UNSPECIFIED_BLACKLIST_RES': [

+             'refs/heads/f[0-9]+',

+         ],

+         'RCM_GROUP': 'relenggroup',

+         'RCM_BRANCHES': ['refs/heads/f[0-9]+'],

+         'ACL_PROTECTED_NAMESPACES': ['rpms', 'modules', 'container'],

+         'PDC_URL': 'invalid://',

+     }

+ 

+     def test_protected_blacklisted_ref(self):

+         project = self.create_namespaced_project('rpms', 'test')

+ 

+         self.assertFalse(

+             self.dga.check_acl(

+                 self.session,

+                 project=project,

+                 username="pingou",

+                 refname="refs/heads/c7",

+                 pull_request=None,

+                 repodir=None,

+                 repotype='main',

+                 revfrom=None,

+                 revto=None,

+                 is_internal=False,

+             )

          )

-         self.assertEqual(msg, 'User added')

-         self.session.commit()

  

-         print("Rewriting %r" % self.configfile)

-         project = pagure.lib._get_project(self.session, 'test')

-         dist_git_auth.DistGitoliteAuth.write_gitolite_acls(

-             self.session,

-             configfile=self.configfile,

-             project=project

+         self.expect_info_msg("Ref refs/heads/c7 is blocked")

+ 

+     def test_protected_rcm(self):

+         project = self.create_namespaced_project('rpms', 'test')

+ 

+         self.assertTrue(

+             self.dga.check_acl(

+                 self.session,

+                 project=project,

+                 username="releng",

+                 refname="refs/heads/f27",

+                 pull_request=None,

+                 repodir=None,

+                 repotype='main',

+                 revfrom=None,

+                 revto=None,

+                 is_internal=False,

+             )

          )

  

-         print("Checking the contents of %r" % self.configfile)

-         with open(self.configfile, 'r') as f:

-             contents = f.read()

- 

-         expected = '''repo test2

-   RW  = releng

-   R   = @all

-   RWC master = pingou

-   RWC master = @provenpackager

-   RWC f9000 = pingou

-   RWC f9000 = @provenpackager

-   -    f[0-9][0-9] = @all

-   -    epel[0-9] = @all

-   -    epel[0-9][0-9] = @all

-   -    el[0-9] = @all

-   -    olpc[0-9] = @all

-   RWC = @provenpackager

-   RWC = pingou

- 

- repo requests/test2

-   RWC = pingou

- 

- repo somenamespace/test3

-   RW  = releng

-   R   = @all

-   RWC master = pingou

-   RWC master = @provenpackager

-   RWC f9000 = pingou

-   RWC f9000 = @provenpackager

-   -    f[0-9][0-9] = @all

-   -    epel[0-9] = @all

-   -    epel[0-9][0-9] = @all

-   -    el[0-9] = @all

-   -    olpc[0-9] = @all

-   RWC = @provenpackager

-   RWC = pingou

- 

- repo requests/somenamespace/test3

-   RWC = pingou

- 

- repo test

-   RW  = releng

-   R   = @all

-   RWC master = foo pingou

-   RWC master = @provenpackager

-   RWC f9000 = foo pingou

-   RWC f9000 = @provenpackager

-   -    f[0-9][0-9] = @all

-   -    epel[0-9] = @all

-   -    epel[0-9][0-9] = @all

-   -    el[0-9] = @all

-   -    olpc[0-9] = @all

-   RWC = @provenpackager

-   RWC = foo pingou

- 

- repo requests/test

-   RWC = foo pingou

- 

- # end of body'''

-         self.assertMultiLineEqual(expected, contents.strip())

- 

-     def test_get_supported_branches(self):

-         """ Test for real what is returned by PDC. """

-         expected = ['master', 'f27', 'f26', 'f25', 'el6']

-         actual = dist_git_auth.get_supported_branches('rpms', 'nethack')

-         self.assertEquals(set(actual), set(expected))

- 

-     @mock.patch('dist_git_auth.get_supported_branches')

-     def test_write_gitolite_acls_test_project_w_group(

-             self, get_supported_branches):

-         """ Test updating the gitolite configuration file for just one

-         project (project == a pagure.lib.model.Project).

+         self.expect_info_msg("RCM push")

+ 

+     @patch_pdc({"rpm/test": {"f26": False, "f27": True}})

+     def test_protected_unsupported_branch(self):

+         project = self.create_namespaced_project('rpms', 'test')

+ 

+         self.assertFalse(

+             self.dga.check_acl(

+                 self.session,

+                 project=project,

+                 username="pingou",

+                 refname="refs/heads/f26",

+                 pull_request=None,

+                 repodir=None,

+                 repotype='main',

+                 revfrom=None,

+                 revto=None,

+                 is_internal=False,

+             )

+         )

  

-         """

+         self.expect_info_msg("Branch refs/heads/f26 is unsupported")

+ 

+     @patch_pdc({"rpm/test": {"f26": False, "f27": True}})

+     def test_protected_supported_branch_committer(self):

+         project = self.create_namespaced_project('rpms', 'test')

+ 

+         self.assertTrue(

+             self.dga.check_acl(

+                 self.session,

+                 project=project,

+                 username="pingou",

+                 refname="refs/heads/f27",

+                 pull_request=None,

+                 repodir=None,

+                 repotype='main',

+                 revfrom=None,

+                 revto=None,

+                 is_internal=False,

+             )

+         )

  

-         get_supported_branches.return_value = ['master', 'f9000']

-         self.test_write_gitolite_acls()

+         self.expect_info_msg("Branch refs/heads/f27 is supported")

+ 

+     @patch_pdc({"rpm/test": {"f26": False, "f27": True}})

+     def test_protected_supported_branch_non_committer(self):

+         project = self.create_namespaced_project('rpms', 'test')

+ 

+         self.assertFalse(

+             self.dga.check_acl(

+                 self.session,

+                 project=project,

+                 username="foo",

+                 refname="refs/heads/f27",

+                 pull_request=None,

+                 repodir=None,

+                 repotype='main',

+                 revfrom=None,

+                 revto=None,

+                 is_internal=False,

+             )

+         )

  

-         print("Modifying the test project so the output differs.")

-         project = pagure.lib._get_project(self.session, 'test')

-         project.user_id = 2

-         self.session.add(project)

-         self.session.commit()

+         self.expect_info_msg("Branch refs/heads/f27 is supported")

+ 

+     @patch_pdc({"rpm/test": {"f26": False, "f27": True}})

+     def test_protected_unspecified_branch_blacklisted(self):

+         project = self.create_namespaced_project('rpms', 'test')

+ 

+         self.assertFalse(

+             self.dga.check_acl(

+                 self.session,

+                 project=project,

+                 username="pingou",

+                 refname="refs/heads/f28",

+                 pull_request=None,

+                 repodir=None,

+                 repotype='main',

+                 revfrom=None,

+                 revto=None,

+                 is_internal=False,

+             )

+         )

  

-         # Add a group to a project and someone to this group

-         project = pagure.lib._get_project(self.session, 'test')

-         msg = pagure.lib.add_group_to_project(

-             session=self.session,

-             project=project,

-             new_group='test_grp',

-             user='pingou',

-             access='admin',

-             create=True,

-             is_admin=True)

-         self.assertEqual(msg, 'Group added')

-         grp = pagure.lib.search_groups(self.session, group_name='test_grp')

-         msg = pagure.lib.add_user_to_group(

-             session=self.session,

-             username='pingou',

-             group=grp,

-             user='pingou',

-             is_admin=False)

-         self.session.commit()

+         self.expect_info_msg("Unspecified ref refs/heads/f28 is blocked")

+ 

+     @patch_pdc({"rpm/test": {"f26": False, "f27": True}})

+     def test_protected_unspecified_branch_normal_committer(self):

+         project = self.create_namespaced_project('rpms', 'test')

+ 

+         self.assertTrue(

+             self.dga.check_acl(

+                 self.session,

+                 project=project,

+                 username="pingou",

+                 refname="refs/heads/mywip",

+                 pull_request=None,

+                 repodir=None,

+                 repotype='main',

+                 revfrom=None,

+                 revto=None,

+                 is_internal=False,

+             )

+         )

  

-         print("Rewriting %r" % self.configfile)

-         project = pagure.lib._get_project(self.session, 'test')

-         dist_git_auth.DistGitoliteAuth.write_gitolite_acls(

-             self.session,

-             configfile=self.configfile,

-             project=project

+         self.expect_info_msg("Unspecified branch push")

+ 

+     @patch_pdc({"rpm/test": {"f26": False, "f27": True}})

+     def test_protected_unspecified_branch_normal_non_committer(self):

+         project = self.create_namespaced_project('rpms', 'test')

+ 

+         self.assertFalse(

+             self.dga.check_acl(

+                 self.session,

+                 project=project,

+                 username="foo",

+                 refname="refs/heads/mywip",

+                 pull_request=None,

+                 repodir=None,

+                 repotype='main',

+                 revfrom=None,

+                 revto=None,

+                 is_internal=False,

+             )

          )

  

-         print("Checking the contents of %r" % self.configfile)

-         with open(self.configfile, 'r') as f:

-             contents = f.read()

- 

-         expected = '''@test_grp  = pingou

- # end of groups

- 

- repo test2

-   RW  = releng

-   R   = @all

-   RWC master = pingou

-   RWC master = @provenpackager

-   RWC f9000 = pingou

-   RWC f9000 = @provenpackager

-   -    f[0-9][0-9] = @all

-   -    epel[0-9] = @all

-   -    epel[0-9][0-9] = @all

-   -    el[0-9] = @all

-   -    olpc[0-9] = @all

-   RWC = @provenpackager

-   RWC = pingou

- 

- repo requests/test2

-   RWC = pingou

- 

- repo somenamespace/test3

-   RW  = releng

-   R   = @all

-   RWC master = pingou

-   RWC master = @provenpackager

-   RWC f9000 = pingou

-   RWC f9000 = @provenpackager

-   -    f[0-9][0-9] = @all

-   -    epel[0-9] = @all

-   -    epel[0-9][0-9] = @all

-   -    el[0-9] = @all

-   -    olpc[0-9] = @all

-   RWC = @provenpackager

-   RWC = pingou

- 

- repo requests/somenamespace/test3

-   RWC = pingou

- 

- repo test

-   RW  = releng

-   R   = @all

-   RWC master = foo

-   RWC master = @test_grp @provenpackager

-   RWC f9000 = foo

-   RWC f9000 = @test_grp @provenpackager

-   -    f[0-9][0-9] = @all

-   -    epel[0-9] = @all

-   -    epel[0-9][0-9] = @all

-   -    el[0-9] = @all

-   -    olpc[0-9] = @all

-   RWC = @test_grp @provenpackager

-   RWC = foo

- 

- repo requests/test

-   RWC = @test_grp

-   RWC = foo

- 

- # end of body'''

-         self.assertMultiLineEqual(expected, contents.strip())

- 

-     @mock.patch('dist_git_auth.get_supported_branches')

-     def test_write_gitolite_acls_fork(

-             self, get_supported_branches):

-         """ Test updating the gitolite configuration file when forking a

-         project.

+         self.expect_info_msg("Unspecified branch push")

  

-         """

  

-         get_supported_branches.return_value = ['master', 'f9000']

-         self.test_write_gitolite_acls()

- 

-         print("Forking the test project.")

-         project = pagure.lib._get_project(self.session, 'test')

-         pagure.lib.fork_project(

-             session=self.session,

-             user='pingou',

-             repo=project,

-             gitfolder=self.path,

-             docfolder=None,

-             ticketfolder=None,

-             requestfolder=None)

- 

-         print("Rewriting %r" % self.configfile)

-         dist_git_auth.DistGitoliteAuth.write_gitolite_acls(

-             self.session,

-             configfile=self.configfile,

-             project=-1

+ class DistGitAuthTestsCentOS(DistGitAuthTests):

+     dga_config = {

+         'PR_ONLY': False,

+         'ACL_BLOCK_UNSPECIFIED': True,

+         'BLACKLIST_RES': ['refs/heads/f[0-9]+.*'],

+         'RCM_GROUP': 'relenggroup',

+         'RCM_BRANCHES': ['refs/heads/c[0-9]+'],

+         'SUPPORTED_SIGS': ['sig-core'],

+         'SIG_PREFIXES': ['refs/heads/c7'],

+         'ACL_PROTECTED_NAMESPACES': ['rpms'],

+     }

+ 

+     def setUp(self):

+         super(DistGitAuthTestsCentOS, self).setUp()

+ 

+         # Create an RCM user/group

+         arrfab = pagure.lib.model.User(

+             user='arrfab',

+             fullname='Fabian Arriton',

+             token='aaabbbcd',

+             default_email='arrfab@local.local',

          )

+         self.session.add(arrfab)

+         self.session.flush()

+         sigcore = pagure.lib.model.PagureGroup(

+             group_name='sig-core',

+             group_type='user',

+             display_name='Core SIG group',

+             user_id=arrfab.id,

+         )

+         self.session.add(sigcore)

+         self.session.flush()

+         arrfab.group_objs.append(sigcore)

+         self.session.commit()

  

-         print("Checking the contents of %r" % self.configfile)

-         with open(self.configfile, 'r') as f:

-             contents = f.read()

- 

-         expected = '''repo test

-   RW  = releng

-   R   = @all

-   RWC master = pingou

-   RWC master = @provenpackager

-   RWC f9000 = pingou

-   RWC f9000 = @provenpackager

-   -    f[0-9][0-9] = @all

-   -    epel[0-9] = @all

-   -    epel[0-9][0-9] = @all

-   -    el[0-9] = @all

-   -    olpc[0-9] = @all

-   RWC = @provenpackager

-   RWC = pingou

- 

- repo requests/test

-   RWC = pingou

- 

- repo test2

-   RW  = releng

-   R   = @all

-   RWC master = pingou

-   RWC master = @provenpackager

-   RWC f9000 = pingou

-   RWC f9000 = @provenpackager

-   -    f[0-9][0-9] = @all

-   -    epel[0-9] = @all

-   -    epel[0-9][0-9] = @all

-   -    el[0-9] = @all

-   -    olpc[0-9] = @all

-   RWC = @provenpackager

-   RWC = pingou

- 

- repo requests/test2

-   RWC = pingou

- 

- repo somenamespace/test3

-   RW  = releng

-   R   = @all

-   RWC master = pingou

-   RWC master = @provenpackager

-   RWC f9000 = pingou

-   RWC f9000 = @provenpackager

-   -    f[0-9][0-9] = @all

-   -    epel[0-9] = @all

-   -    epel[0-9][0-9] = @all

-   -    el[0-9] = @all

-   -    olpc[0-9] = @all

-   RWC = @provenpackager

-   RWC = pingou

- 

- repo requests/somenamespace/test3

-   RWC = pingou

- 

- repo forks/pingou/test

-   RW  = releng

-   R   = @all

-   RW+C = pingou

- 

- repo requests/forks/pingou/test

-   RW+C = pingou

- 

- # end of body'''

-         self.assertMultiLineEqual(expected, contents.strip())

- 

-     @mock.patch('dist_git_auth.get_supported_branches')

-     def test_write_gitolite_acls_rpms_firefox(self, get_supported_branches):

-         """ Test generating the entire gitolite configuration file

-         with the firefox project in the rpms namespace (ie a project not

-         allowing provenpackager access).

+     def test_protected_blacklisted_ref(self):

+         project = self.create_namespaced_project('rpms', 'test')

+ 

+         self.assertFalse(

+             self.dga.check_acl(

+                 self.session,

+                 project=project,

+                 username="pingou",

+                 refname="refs/heads/f27",

+                 pull_request=None,

+                 repodir=None,

+                 repotype='main',

+                 revfrom=None,

+                 revto=None,

+                 is_internal=False,

+             )

+         )

  

-         """

-         get_supported_branches.return_value = ['master', 'f9000']

-         print("Initializing DB.")

-         item = pagure.lib.model.Project(

-             user_id=1,  # pingou

-             name='firefox',

-             description='The firefox project',

-             hook_token='aaabbbeee',

-             namespace='rpms',

+         self.expect_info_msg("Ref refs/heads/f27 is blocked")

+ 

+     def test_protected_rcm(self):

+         project = self.create_namespaced_project('rpms', 'test')

+ 

+         self.assertTrue(

+             self.dga.check_acl(

+                 self.session,

+                 project=project,

+                 username="releng",

+                 refname="refs/heads/c7",

+                 pull_request=None,

+                 repodir=None,

+                 repotype='main',

+                 revfrom=None,

+                 revto=None,

+                 is_internal=False,

+             )

          )

-         self.session.add(item)

-         self.session.commit()

  

-         print("Generating %r" % self.configfile)

-         dist_git_auth.DistGitoliteAuth.write_gitolite_acls(

-             self.session,

-             configfile=self.configfile,

-             project=-1)

- 

-         print("Checking the contents of %r" % self.configfile)

-         with open(self.configfile, 'r') as f:

-             contents = f.read()

-         expected = """repo rpms/firefox

-   RW  = releng

-   R   = @all

-   RWC master = pingou

-   RWC f9000 = pingou

-   -    f[0-9][0-9] = @all

-   -    epel[0-9] = @all

-   -    epel[0-9][0-9] = @all

-   -    el[0-9] = @all

-   -    olpc[0-9] = @all

-   RWC = pingou

- 

- repo requests/rpms/firefox

-   RWC = pingou

- 

- # end of body

- """

-         self.assertMultiLineEqual(contents.strip(), expected.strip())

- 

-     @mock.patch('dist_git_auth.get_supported_branches')

-     def test_write_gitolite_acls_firefox(self, get_supported_branches):

-         """ Test generating the entire gitolite configuration file

-         with the firefox project.

+         self.expect_info_msg("RCM push")

+ 

+     def test_protected_sig_sig_member(self):

+         project = self.create_namespaced_project('rpms', 'test')

+ 

+         self.assertTrue(

+             self.dga.check_acl(

+                 self.session,

+                 project=project,

+                 username="arrfab",

+                 refname="refs/heads/c7-sig-core-test",

+                 pull_request=None,

+                 repodir=None,

+                 repotype='main',

+                 revfrom=None,

+                 revto=None,

+                 is_internal=False,

+             )

+         )

  

-         """

-         get_supported_branches.return_value = ['master', 'f9000']

-         print("Initializing DB.")

-         item = pagure.lib.model.Project(

-             user_id=1,  # pingou

-             name='firefox',

-             description='The firefox project',

-             hook_token='aaabbbeee',

-             namespace=None,

+         self.expect_info_msg("SIG push")

+ 

+     def test_protected_sig_no_sig_member(self):

+         project = self.create_namespaced_project('rpms', 'test')

+ 

+         self.assertFalse(

+             self.dga.check_acl(

+                 self.session,

+                 project=project,

+                 username="pingou",

+                 refname="refs/heads/c7-sig-core-test",

+                 pull_request=None,

+                 repodir=None,

+                 repotype='main',

+                 revfrom=None,

+                 revto=None,

+                 is_internal=False,

+             )

          )

-         self.session.add(item)

-         self.session.commit()

  

-         print("Generating %r" % self.configfile)

-         dist_git_auth.DistGitoliteAuth.write_gitolite_acls(

-             self.session,

-             configfile=self.configfile,

-             project=-1)

- 

-         print("Checking the contents of %r" % self.configfile)

-         with open(self.configfile, 'r') as f:

-             contents = f.read()

-         expected = """repo firefox

-   RW  = releng

-   R   = @all

-   RWC master = pingou

-   RWC master = @provenpackager

-   RWC f9000 = pingou

-   RWC f9000 = @provenpackager

-   -    f[0-9][0-9] = @all

-   -    epel[0-9] = @all

-   -    epel[0-9][0-9] = @all

-   -    el[0-9] = @all

-   -    olpc[0-9] = @all

-   RWC = @provenpackager

-   RWC = pingou

- 

- repo requests/firefox

-   RWC = pingou

- 

- # end of body

- """

-         self.assertMultiLineEqual(contents.strip(), expected.strip())

+         self.expect_info_msg("Access to namespace rpms is restricted")

+ 

+     def test_protected_sig_sig_member_no_sig_branch(self):

+         project = self.create_namespaced_project('rpms', 'test')

+ 

+         self.assertFalse(

+             self.dga.check_acl(

+                 self.session,

+                 project=project,

+                 username="arrfab",

+                 refname="refs/heads/c7",

+                 pull_request=None,

+                 repodir=None,

+                 repotype='main',

+                 revfrom=None,

+                 revto=None,

+                 is_internal=False,

+             )

+         )

+ 

+         self.expect_info_msg("Access to namespace rpms is restricted")

file modified
+38 -46
@@ -1,9 +1,10 @@ 

  # Python3 packaging is turned off until pagure itself is ported to python3.

- %global with_python3 0

+ %global with_python3 1

  

  # Current EL releases & older Fedora use "python-*"

  %if 0%{?el6} || 0%{?el7} || 0%{?fedora} < 25

  %define py_prefix python

+ %global with_python3 0

  %if 0%{?el6} || 0%{?el7}

  BuildRequires: python-devel

  %else
@@ -19,10 +20,10 @@ 

  %{!?_licensedir: %global license %%doc}

  

  %global modname pagure-dist-git

- %global sum     Pagure gitolite plugin for Fedora's dist-git setup.

+ %global sum     Pagure Git auth backend for Fedora and CentOS dist-git setups

  

  Name:               pagure-dist-git

- Version:            0.12

+ Version:            1.0

  Release:            1%{?dist}

  Summary:            %{sum}

  
@@ -30,52 +31,47 @@ 

  URL:                http://pypi.python.org/pypi/pagure-dist-git

  Source0:            https://pypi.io/packages/source/p/%{modname}/%{modname}-%{version}.tar.gz

  BuildArch:          noarch

+ # https://fedoraproject.org/wiki/Packaging:Guidelines#Noarch_with_Unported_Dependencies

+ ExclusiveArch:      x86_64 noarch

  

  

  %description

- Since 3.0 pagure offers a way to customize the creation and compilation the

- of the gitolite configuration file.

- 

- This project hosts the logic to generate gitolite's configuration file for

- dist-git which has a different access model than regular projects on pagure

- (for example, forced pushed is forbidden).

+ This implements access control list checks for Fedora and CentOS dist-git.

  

- %package -n python2-%{modname}

- Summary:            Pagure gitolite plugin for Fedora's dist-git setup.

+ %package -n %{py_prefix}-%{modname}

+ Summary:            Pagure Git auth backend for Fedora and CentOS dist-git

  %{?python_provide:%python_provide python2-%{modname}}

  

  BuildRequires:      %{py_prefix}-devel

  BuildRequires:      %{py_prefix}-setuptools

+ # For tests

+ BuildRequires:      %{py_prefix}-mock

+ BuildRequires:      %{py_prefix}-pdc-client

+ BuildRequires:      %{py_prefix}-nose

+ BuildRequires:      pagure >= 5.1

  

- Requires:           %{py_prefix}-pdc-client

- Requires:           pagure >= 3.90

+ Requires:           pagure >= 5.1

  

- %description -n python2-%{modname}

- Since 3.0 pagure offers a way to customize the creation and compilation the

- of the gitolite configuration file.

- 

- This project hosts the logic to generate gitolite's configuration file for

- dist-git which has a different access model than regular projects on pagure

- (for example, forced pushed is forbidden).

+ %description -n %{py_prefix}-%{modname}

+ This implements access control list checks for Fedora and CentOS dist-git.

  

  %if 0%{?with_python3}

  %package -n python3-%{modname}

- Summary:            Pagure gitolite plugin for Fedora's dist-git setup.

+ Summary:            Pagure Git auth backend for Fedora and CentOS dist-git

  %{?python_provide:%python_provide python3-%{modname}}

  

  BuildRequires:      python3-devel

  BuildRequires:      python3-setuptools

+ # For tests

+ BuildRequires:      python3-mock

+ BuildRequires:      python3-pdc-client

+ BuildRequires:      python3-nose

+ BuildRequires:      pagure >= 5.1

  

- Requires:           python3-pdc-client

- Requires:           python3-pagure>=3.90

+ Requires:           python3-pagure >= 5.1

  

  %description -n python3-%{modname}

- Since 3.0 pagure offers a way to customize the creation and compilation the

- of the gitolite configuration file.

- 

- This project hosts the logic to generate gitolite's configuration file for

- dist-git which has a different access model than regular projects on pagure

- (for example, forced pushed is forbidden).

+ This implements access control list checks for Fedora and CentOS dist-git.

  %endif

  

  %prep
@@ -93,32 +89,24 @@ 

  %py3_install

  %endif

  

- # Install the custom template/theme

- mkdir -p $RPM_BUILD_ROOT/%{_datadir}/pagure_dist_git/template/

- install -p -m 644 template/*.html $RPM_BUILD_ROOT/%{_datadir}/pagure_dist_git/template/

- 

- # Install the customized static files or our own

- mkdir -p $RPM_BUILD_ROOT/%{_datadir}/pagure_dist_git/static/

- install -p -m 644 static/pagure-logo.png $RPM_BUILD_ROOT/%{_datadir}/pagure_dist_git/static/

- 

  # Install the different cron job scripts

  mkdir -p $RPM_BUILD_ROOT/%{_libexecdir}/pagure-dist-git/

  install -p -m 644 scripts/*.py $RPM_BUILD_ROOT/%{_libexecdir}/pagure-dist-git/

  

  

- # The tests require network access, so don't run them.

- #%%check

- #%%{__python2} setup.py test

- #%%if 0%%{?with_python3}

- #%%{__python3} setup.py test

- #%%endif

+ %check

+ # These tests don't currently pass because Pagure doesn't ship its testsuite

+ exit 0

+ nosetests -v

+ %if 0%{?with_python3}

+ nosetests-3 -v

+ %endif

  

- %files -n python2-%{modname}

+ %files -n %{py_prefix}-%{modname}

  %doc README.rst

  %license LICENSE

  %{python2_sitelib}/dist_git_auth.py*

  %{python2_sitelib}/pagure_dist_git-%{version}*

- %{_datadir}/pagure_dist_git/

  %{_libexecdir}/pagure-dist-git/

  

  %if 0%{?with_python3}
@@ -126,13 +114,17 @@ 

  %doc README.rst

  %license LICENSE

  %{python3_sitelib}/dist_git_auth.py*

+ %{python3_sitelib}/__pycache__/*

  %{python3_sitelib}/pagure_dist_git-%{version}*

- %{_datadir}/pagure_dist_git/

  %{_libexecdir}/pagure-dist-git/

  %endif

  

  

  %changelog

+ * Tue Oct 09 2018 Patrick Uiterwijk <puiterwijk@redhat.com> - 1.0-1

+ - Rewrote to Dynamic auth backend system (new in Pagure 5.0)

+ - Merged CentOS ACL checks

+ 

  * Mon Apr 23 2018 Pierre-Yves Chibon <pingou@pingoured.fr> - 0.12-1

  - Update to 0.12

  - Add namespace to all the url_for() calls

file modified
+3 -4
@@ -6,7 +6,6 @@ 

  f.close()

  

  install_requires = [

-     'pdc_client',

      'pagure',

  ]

  tests_require = [
@@ -16,8 +15,8 @@ 

  

  setup(

      name='pagure-dist-git',

-     version='0.12',

-     description="Pagure gitolite plugin for Fedora's dist-git setup.",

+     version='1.0',

+     description="Pagure Git auth backend for Fedora and CentOS dist-git",

      long_description=long_description,

      author='Pierre-Yves Chibon',

      author_email='pingou@fedoraproject.org',
@@ -32,6 +31,6 @@ 

      zip_safe=False,

      entry_points="""

      [pagure.git_auth.helpers]

-     distgit = dist_git_auth:DistGitoliteAuth

+     distgit = dist_git_auth:DistGitAuth

      """,

  )

This is basically a full rewrite of the actual dist_git_auth, so I would suggest for review to only look at the new code instead of the actual diff.

rebased onto 8a6af288ff6a61a4e0ecc942b34442bde343ea86

7 years ago

rebased onto cb0dfb28790ef749c6707a36b6d7fe09bcf11d6c

7 years ago

rebased onto e2834022e6344909e14d2c4aba57d7e2bec1b5e5

7 years ago

rebased onto b397cea7084d6565d6c7add618ad4c9821c8e981

7 years ago

rebased onto 90a96786cc9e66a8a72844a655cfe66bfd8f5852

7 years ago

rebased onto f148717cae0429eefd470509a8e959151f652e78

7 years ago

rebased onto 38d9a5609d18ffe748116781c253cae362c6b7d3

7 years ago

I'd definitely put you in the Dream Team ;-)

I think we have a few new configuration keys here. Could we document them somewhere (even just the README file of this project)?

rebased onto 1c23ab0b77a3edceb023044d4e2f71f2e2ebe3eb

7 years ago

rebased onto 1c23ab0b77a3edceb023044d4e2f71f2e2ebe3eb

7 years ago

rebased onto 3c948dc0891fbcee24b2df968e69a74ec94447ed

7 years ago

Could we add some example for these? Just to be complete

See the comments for SUPPORTED_SIGS. That example is basically for both of the SIG options.

rebased onto c7bb2479b8387b2e4c408fdaccbfea6d9408352d

7 years ago

rebased onto c7bb2479b8387b2e4c408fdaccbfea6d9408352d

7 years ago

rebased onto dba03d5

7 years ago

rebased onto dba03d5

7 years ago

Pull-Request has been merged by pingou

7 years ago