Skip to content

Use permissions (project and group) for RemoteRepository.admin on GitLab #7479

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Sep 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 25 additions & 6 deletions readthedocs/oauth/services/gitlab.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ class GitLabService(Service):
re.escape(urlparse(adapter.provider_base_url).netloc),
)

PERMISSION_NO_ACCESS = 0
PERMISSION_MAINTAINER = 40
PERMISSION_OWNER = 50

def _get_repo_id(self, project):
# The ID or URL-encoded path of the project
# https://docs.gitlab.com/ce/api/README.html#namespaced-path-encoding
Expand Down Expand Up @@ -132,13 +136,20 @@ def sync_organizations(self):

return remote_organizations, remote_repositories

def is_owned_by(self, owner_id):
return self.account.extra_data['id'] == owner_id

def create_repository(self, fields, privacy=None, organization=None):
"""
Update or create a repository from GitLab API response.

``admin`` field is computed using the ``permissions`` fields from the
repository response. The permission from GitLab is given by an integer:
* 0: No access
* (... others ...)
* 40: Maintainer
* 50: Owner

https://docs.gitlab.com/ee/api/access_requests.html
https://gitlab.com/help/user/permissions

:param fields: dictionary of response data from API
:param privacy: privacy level to support
:param organization: remote organization to associate with
Expand Down Expand Up @@ -179,9 +190,17 @@ def create_repository(self, fields, privacy=None, organization=None):
else:
repo.clone_url = fields['http_url_to_repo']

repo.admin = not repo_is_public
if not repo.admin and 'owner' in fields:
repo.admin = self.is_owned_by(fields['owner']['id'])
project_access_level = group_access_level = self.PERMISSION_NO_ACCESS
project_access = fields.get('permissions', {}).get('project_access', {})
if project_access:
project_access_level = project_access.get('access_level', self.PERMISSION_NO_ACCESS)
group_access = fields.get('permissions', {}).get('group_access', {})
if group_access:
group_access_level = group_access.get('access_level', self.PERMISSION_NO_ACCESS)
repo.admin = any([
project_access_level in (self.PERMISSION_MAINTAINER, self.PERMISSION_OWNER),
group_access_level in (self.PERMISSION_MAINTAINER, self.PERMISSION_OWNER),
])

repo.vcs = 'git'
repo.account = self.account
Expand Down
14 changes: 5 additions & 9 deletions readthedocs/rtd_tests/tests/test_oauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -951,12 +951,10 @@ def get_private_repo_data(self):
return data

def test_make_project_pass(self):
with mock.patch('readthedocs.oauth.services.gitlab.GitLabService.is_owned_by') as m: # yapf: disable
m.return_value = True
repo = self.service.create_repository(
self.repo_response_data, organization=self.org,
privacy=self.privacy,
)
repo = self.service.create_repository(
self.repo_response_data, organization=self.org,
privacy=self.privacy,
)
self.assertIsInstance(repo, RemoteRepository)
self.assertEqual(repo.name, 'testrepo')
self.assertEqual(repo.full_name, 'testorga / testrepo')
Expand Down Expand Up @@ -1009,9 +1007,7 @@ def test_make_private_project(self):
"""
data = self.repo_response_data.copy()
data['visibility'] = 'public'
with mock.patch('readthedocs.oauth.services.gitlab.GitLabService.is_owned_by') as m: # yapf: disable
m.return_value = True
repo = self.service.create_repository(data, organization=self.org)
repo = self.service.create_repository(data, organization=self.org)
self.assertIsNotNone(repo)

@mock.patch('readthedocs.oauth.services.gitlab.log')
Expand Down