Skip to content

Commit 40f7f02

Browse files
authored
Remote repositories: filter by vcs provider when deleting (#12015)
This wasn't a problem since we are filtering by account, and the account can only have one type of vcs repositories, but just for consistency.
1 parent 3a6d6d2 commit 40f7f02

File tree

2 files changed

+44
-13
lines changed

2 files changed

+44
-13
lines changed

readthedocs/oauth/services/base.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -254,22 +254,26 @@ def sync(self):
254254
all_remote_repositories = remote_repositories + remote_repositories_organizations
255255
repository_remote_ids = [r.remote_id for r in all_remote_repositories if r is not None]
256256
(
257-
self.user.remote_repository_relations.exclude(
258-
remote_repository__remote_id__in=repository_remote_ids,
257+
self.user.remote_repository_relations.filter(
258+
account=self.account,
259259
remote_repository__vcs_provider=self.vcs_provider_slug,
260260
)
261-
.filter(account=self.account)
261+
.exclude(
262+
remote_repository__remote_id__in=repository_remote_ids,
263+
)
262264
.delete()
263265
)
264266

265267
# Delete RemoteOrganization where the user doesn't have access anymore
266268
organization_remote_ids = [o.remote_id for o in remote_organizations if o is not None]
267269
(
268-
self.user.remote_organization_relations.exclude(
269-
remote_organization__remote_id__in=organization_remote_ids,
270+
self.user.remote_organization_relations.filter(
271+
account=self.account,
270272
remote_organization__vcs_provider=self.vcs_provider_slug,
271273
)
272-
.filter(account=self.account)
274+
.exclude(
275+
remote_organization__remote_id__in=organization_remote_ids,
276+
)
273277
.delete()
274278
)
275279

readthedocs/rtd_tests/tests/test_oauth_sync.py

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import django_dynamic_fixture as fixture
22
import requests_mock
33
from allauth.socialaccount.models import SocialAccount, SocialToken
4-
from allauth.socialaccount.providers.github.views import GitHubOAuth2Adapter
4+
from allauth.socialaccount.providers.github.provider import GitHubProvider
55
from django.contrib.auth.models import User
66
from django.test import TestCase
77

@@ -12,6 +12,8 @@
1212
RemoteRepository,
1313
RemoteRepositoryRelation,
1414
)
15+
from django_dynamic_fixture import get
16+
from allauth.socialaccount.providers.gitlab.provider import GitLabProvider
1517
from readthedocs.oauth.services import GitHubService
1618
from readthedocs.projects.models import Project
1719

@@ -64,7 +66,7 @@ def setUp(self):
6466
self.socialaccount = fixture.get(
6567
SocialAccount,
6668
user=self.user,
67-
provider=GitHubOAuth2Adapter.provider_id,
69+
provider=GitHubProvider.id,
6870
)
6971
self.token = fixture.get(
7072
SocialToken,
@@ -122,6 +124,25 @@ def test_sync_delete_stale(self, mock_request):
122124
account=self.socialaccount,
123125
)
124126

127+
# Project from another provider (GitLab) that has the same ID should not be removed.
128+
gitlab_socialaccount = fixture.get(
129+
SocialAccount,
130+
user=self.user,
131+
provider=GitLabProvider.id,
132+
)
133+
gitlab_repo = fixture.get(
134+
RemoteRepository,
135+
full_name="user/repo",
136+
remote_id=repo_3.remote_id,
137+
vcs_provider=GitLabProvider.id,
138+
)
139+
fixture.get(
140+
RemoteRepositoryRelation,
141+
remote_repository=gitlab_repo,
142+
user=self.user,
143+
account=gitlab_socialaccount,
144+
)
145+
125146
org = fixture.get(
126147
RemoteOrganization,
127148
name="organization",
@@ -133,18 +154,21 @@ def test_sync_delete_stale(self, mock_request):
133154
account=self.socialaccount,
134155
)
135156

136-
self.assertEqual(RemoteRepository.objects.count(), 3)
137-
self.assertEqual(RemoteRepositoryRelation.objects.count(), 3)
157+
self.assertEqual(RemoteRepository.objects.count(), 4)
158+
self.assertEqual(RemoteRepositoryRelation.objects.count(), 4)
138159
self.assertEqual(RemoteOrganization.objects.count(), 1)
139160
self.assertEqual(RemoteOrganizationRelation.objects.count(), 1)
140161

162+
assert self.socialaccount.remote_repository_relations.count() == 3
163+
assert self.socialaccount.remote_organization_relations.count() == 1
164+
141165
self.service.sync()
142166

143167
# After calling .sync, old-repository remote relation should be deleted,
144168
# project-linked-repository remote relation should be conserved,
145169
# and only the one's returned by the API should be present (organization/repository)
146-
self.assertEqual(RemoteRepository.objects.count(), 3)
147-
self.assertEqual(RemoteRepositoryRelation.objects.count(), 1)
170+
self.assertEqual(RemoteRepository.objects.count(), 4)
171+
self.assertEqual(RemoteRepositoryRelation.objects.count(), 2)
148172
self.assertTrue(
149173
RemoteRepository.objects.filter(
150174
full_name="organization/repository"
@@ -158,6 +182,9 @@ def test_sync_delete_stale(self, mock_request):
158182
self.assertEqual(RemoteOrganization.objects.count(), 1)
159183
self.assertEqual(RemoteOrganizationRelation.objects.count(), 0)
160184

185+
assert self.socialaccount.remote_repository_relations.count() == 1
186+
assert self.socialaccount.remote_organization_relations.count() == 0
187+
161188
@requests_mock.Mocker(kw="mock_request")
162189
def test_sync_repositories(self, mock_request):
163190
mock_request.get(
@@ -284,7 +311,7 @@ def test_sync_repositories_only_creates_one_remote_repo_per_vcs_repo(
284311
user_2_socialaccount = fixture.get(
285312
SocialAccount,
286313
user=user_2,
287-
provider=GitHubOAuth2Adapter.provider_id,
314+
provider=GitHubProvider.id,
288315
)
289316
fixture.get(
290317
SocialToken,

0 commit comments

Comments
 (0)