diff --git a/rhodecode/apps/ssh_support/lib/backends/__init__.py b/rhodecode/apps/ssh_support/lib/backends/__init__.py --- a/rhodecode/apps/ssh_support/lib/backends/__init__.py +++ b/rhodecode/apps/ssh_support/lib/backends/__init__.py @@ -120,11 +120,25 @@ class SshWrapper(object): return vcs_type, repo_name, mode - def serve(self, vcs, repo, mode, user, permissions): + def serve(self, vcs, repo, mode, user, permissions, branch_permissions): store = ScmModel().repos_path + check_branch_perms = False + detect_force_push = False + + if branch_permissions: + check_branch_perms = True + detect_force_push = True + log.debug( - 'VCS detected:`%s` mode: `%s` repo_name: %s', vcs, mode, repo) + 'VCS detected:`%s` mode: `%s` repo_name: %s, branch_permission_checks:%s', + vcs, mode, repo, check_branch_perms) + + # detect if we have to check branch permissions + extras = { + 'detect_force_push': detect_force_push, + 'check_branch_perms': check_branch_perms, + } if vcs == 'hg': server = MercurialServer( @@ -132,7 +146,7 @@ class SshWrapper(object): repo_name=repo, user=user, user_permissions=permissions, config=self.config, env=self.env) self.server_impl = server - return server.run() + return server.run(tunnel_extras=extras) elif vcs == 'git': server = GitServer( @@ -140,7 +154,7 @@ class SshWrapper(object): repo_name=repo, repo_mode=mode, user=user, user_permissions=permissions, config=self.config, env=self.env) self.server_impl = server - return server.run() + return server.run(tunnel_extras=extras) elif vcs == 'svn': server = SubversionServer( @@ -148,7 +162,7 @@ class SshWrapper(object): repo_name=None, user=user, user_permissions=permissions, config=self.config, env=self.env) self.server_impl = server - return server.run() + return server.run(tunnel_extras=extras) else: raise Exception('Unrecognised VCS: {}'.format(vcs)) @@ -188,10 +202,11 @@ class SshWrapper(object): auth_user = user.AuthUser() permissions = auth_user.permissions['repositories'] - + repo_branch_permissions = auth_user.get_branch_permissions(scm_repo) try: exit_code, is_updated = self.serve( - scm_detected, scm_repo, scm_mode, user, permissions) + scm_detected, scm_repo, scm_mode, user, permissions, + repo_branch_permissions) except Exception: log.exception('Error occurred during execution of SshWrapper') exit_code = -1 diff --git a/rhodecode/apps/ssh_support/lib/backends/base.py b/rhodecode/apps/ssh_support/lib/backends/base.py --- a/rhodecode/apps/ssh_support/lib/backends/base.py +++ b/rhodecode/apps/ssh_support/lib/backends/base.py @@ -106,11 +106,15 @@ class VcsServer(object): 'make_lock': None, 'locked_by': [None, None], 'server_url': None, - 'is_shadow_repo': False, - 'hooks_module': 'rhodecode.lib.hooks_daemon', + 'user_agent': 'ssh-user-agent', 'hooks': ['push', 'pull'], + 'hooks_module': 'rhodecode.lib.hooks_daemon', + 'is_shadow_repo': False, + 'detect_force_push': False, + 'check_branch_perms': False, + 'SSH': True, - 'SSH_PERMISSIONS': self.user_permissions.get(self.repo_name) + 'SSH_PERMISSIONS': self.user_permissions.get(self.repo_name), } if extras: scm_data.update(extras) @@ -139,8 +143,10 @@ class VcsServer(object): return exit_code, action == "push" - def run(self): + def run(self, tunnel_extras=None): + tunnel_extras = tunnel_extras or {} extras = {} + extras.update(tunnel_extras) callback_daemon, extras = prepare_callback_daemon( extras, protocol=vcs_settings.HOOKS_PROTOCOL, diff --git a/rhodecode/apps/ssh_support/tests/test_server_git.py b/rhodecode/apps/ssh_support/tests/test_server_git.py --- a/rhodecode/apps/ssh_support/tests/test_server_git.py +++ b/rhodecode/apps/ssh_support/tests/test_server_git.py @@ -139,6 +139,9 @@ class TestGitServer(object): 'hooks': ['push', 'pull'], 'is_shadow_repo': False, 'hooks_module': 'rhodecode.lib.hooks_daemon', + 'check_branch_perms': False, + 'detect_force_push': False, + 'user_agent': u'ssh-user-agent', 'SSH': True, 'SSH_PERMISSIONS': 'repository.admin', } diff --git a/rhodecode/apps/ssh_support/tests/test_ssh_wrapper.py b/rhodecode/apps/ssh_support/tests/test_ssh_wrapper.py --- a/rhodecode/apps/ssh_support/tests/test_ssh_wrapper.py +++ b/rhodecode/apps/ssh_support/tests/test_ssh_wrapper.py @@ -27,7 +27,7 @@ class TestSSHWrapper(object): with pytest.raises(Exception) as exc_info: ssh_wrapper.serve( vcs='microsoft-tfs', repo='test-repo', mode=None, user='test', - permissions={}) + permissions={}, branch_permissions={}) assert exc_info.value.message == 'Unrecognised VCS: microsoft-tfs' def test_parse_config(self, ssh_wrapper): diff --git a/rhodecode/lib/auth.py b/rhodecode/lib/auth.py --- a/rhodecode/lib/auth.py +++ b/rhodecode/lib/auth.py @@ -1362,8 +1362,11 @@ class AuthUser(object): def get_branch_permissions(self, repo_name, perms=None): perms = perms or self.permissions_with_scope({'repo_name': repo_name}) - branch_perms = perms.get('repository_branches') - return branch_perms + branch_perms = perms.get('repository_branches', {}) + if not branch_perms: + return {} + repo_branch_perms = branch_perms.get(repo_name) + return repo_branch_perms or {} def get_rule_and_branch_permission(self, repo_name, branch_name): """ @@ -1373,11 +1376,7 @@ class AuthUser(object): rule = default_perm = '' - branch_perms = self.get_branch_permissions(repo_name=repo_name) - if not branch_perms: - return rule, default_perm - - repo_branch_perms = branch_perms.get(repo_name) + repo_branch_perms = self.get_branch_permissions(repo_name=repo_name) if not repo_branch_perms: return rule, default_perm diff --git a/rhodecode/lib/base.py b/rhodecode/lib/base.py --- a/rhodecode/lib/base.py +++ b/rhodecode/lib/base.py @@ -179,7 +179,9 @@ def vcs_operation_context( settings_model = VcsSettingsModel(repo=repo_name) ui_settings = settings_model.get_ui_settings() - extras = { + # NOTE(marcink): This should be also in sync with + # rhodecode/apps/ssh_support/lib/backends/base.py:update_enviroment scm_data + scm_data = { 'ip': get_ip_addr(environ), 'username': username, 'user_id': user_id, @@ -196,7 +198,7 @@ def vcs_operation_context( 'detect_force_push': detect_force_push, 'check_branch_perms': check_branch_perms, } - return extras + return scm_data class BasicAuth(AuthBasicAuthenticator):