Skip to content

Commit af79b77

Browse files
authored
Git service: add method to sync user access to remote repositories (#12016)
Extracted from #11942. Instead of getting a service for the user and manually syncing the repositories, this abstracts syncing the access to the repositories in another method. This is since with GH apps, syncing the access to the repositories is done in a different way.
1 parent 005e69b commit af79b77

File tree

3 files changed

+34
-14
lines changed

3 files changed

+34
-14
lines changed

readthedocs/oauth/management/commands/reconnect_remoterepositories.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import json
22

3-
from django.db.models import Q, Subquery
43
from django.core.management.base import BaseCommand
4+
from django.db.models import Q, Subquery
55

66
from readthedocs.oauth.models import RemoteRepository
77
from readthedocs.oauth.services import registry
88
from readthedocs.oauth.services.base import SyncServiceError
9-
from readthedocs.projects.models import Project
109
from readthedocs.organizations.models import Organization
10+
from readthedocs.projects.models import Project
1111

1212

1313
class Command(BaseCommand):
@@ -41,11 +41,12 @@ def add_arguments(self, parser):
4141
def _force_owners_social_resync(self, organization):
4242
for owner in organization.owners.all():
4343
for service_cls in registry:
44-
for service in service_cls.for_user(owner):
45-
try:
46-
service.sync()
47-
except SyncServiceError:
48-
print(f"Service {service} failed while syncing. Skipping...")
44+
try:
45+
service_cls.sync_user_access(owner)
46+
except SyncServiceError:
47+
print(
48+
f"Service {service_cls.allauth_provider.name} failed while syncing. Skipping..."
49+
)
4950

5051
def _connect_repositories(self, organization, no_dry_run, only_owners):
5152
connected_projects = []

readthedocs/oauth/services/base.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,20 @@ class Service:
4040
supports_build_status = False
4141

4242
@classmethod
43-
def for_project(self, project):
43+
def for_project(cls, project):
4444
"""Return an iterator of services that can be used for the project."""
4545
raise NotImplementedError
4646

4747
@classmethod
48-
def for_user(self, user):
48+
def for_user(cls, user):
4949
"""Return an iterator of services that belong to the user."""
5050
raise NotImplementedError
5151

52+
@classmethod
53+
def sync_user_access(cls, user):
54+
"""Sync the user's access to the provider's repositories and organizations."""
55+
raise NotImplementedError
56+
5257
def sync(self):
5358
"""
5459
Sync remote repositories and organizations.
@@ -151,6 +156,20 @@ def for_user(cls, user):
151156
for account in accounts:
152157
yield cls(user=user, account=account)
153158

159+
@classmethod
160+
def sync_user_access(cls, user):
161+
"""
162+
Sync the user's access to the provider repositories and organizations.
163+
164+
Since UserService makes use of the user's OAuth token,
165+
we can just sync the user's repositories in order to
166+
update the user access to repositories and organizations.
167+
168+
:raises SyncServiceError: if the access token is invalid or revoked
169+
"""
170+
for service in cls.for_user(user):
171+
service.sync()
172+
154173
@cached_property
155174
def session(self):
156175
return get_oauth2_client(self.account)

readthedocs/oauth/tasks.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,11 @@ def sync_remote_repositories(user_id):
4545

4646
failed_services = set()
4747
for service_cls in registry:
48-
for service in service_cls.for_user(user):
49-
try:
50-
service.sync()
51-
except SyncServiceError:
52-
failed_services.add(service_cls.allauth_provider.name)
48+
try:
49+
service_cls.sync_user_access(user)
50+
except SyncServiceError:
51+
failed_services.add(service_cls.allauth_provider.name)
52+
5353
if failed_services:
5454
raise SyncServiceError(
5555
SyncServiceError.INVALID_OR_REVOKED_ACCESS_TOKEN.format(

0 commit comments

Comments
 (0)