|
10 | 10 | from django.utils import timezone |
11 | 11 |
|
12 | 12 | from readthedocs.api.v2.views.integrations import ExternalVersionData |
13 | | -from readthedocs.core.permissions import AdminPermission |
14 | 13 | from readthedocs.core.utils.tasks import PublicTask |
15 | 14 | from readthedocs.core.utils.tasks import user_id_matches_or_superuser |
16 | 15 | from readthedocs.core.views.hooks import VersionInfo |
|
21 | 20 | from readthedocs.core.views.hooks import trigger_sync_versions |
22 | 21 | from readthedocs.notifications.models import Notification |
23 | 22 | from readthedocs.oauth.clients import get_gh_app_client |
| 23 | +from readthedocs.oauth.constants import GITHUB_APP |
24 | 24 | from readthedocs.oauth.models import GitHubAppInstallation |
| 25 | +from readthedocs.oauth.models import RemoteRepository |
25 | 26 | from readthedocs.oauth.notifications import MESSAGE_OAUTH_WEBHOOK_INVALID |
26 | 27 | from readthedocs.oauth.notifications import MESSAGE_OAUTH_WEBHOOK_NO_ACCOUNT |
27 | 28 | from readthedocs.oauth.notifications import MESSAGE_OAUTH_WEBHOOK_NO_PERMISSIONS |
28 | 29 | from readthedocs.oauth.services.base import SyncServiceError |
29 | 30 | from readthedocs.oauth.utils import SERVICE_MAP |
30 | | -from readthedocs.organizations.models import Organization |
31 | 31 | from readthedocs.projects.models import Project |
32 | 32 | from readthedocs.sso.models import SSOIntegration |
33 | 33 | from readthedocs.vcs_support.backends.git import parse_version_from_ref |
@@ -70,49 +70,40 @@ def sync_remote_repositories(user_id): |
70 | 70 |
|
71 | 71 |
|
72 | 72 | @app.task(queue="web") |
73 | | -def sync_remote_repositories_organizations(organization_slugs=None): |
| 73 | +def sync_remote_repositories_from_sso_organizations(): |
74 | 74 | """ |
75 | | - Re-sync users member of organizations. |
| 75 | + Re-sync all remote repositories from organizations with SSO enabled. |
76 | 76 |
|
77 | | - It will trigger one `sync_remote_repositories` task per user. |
| 77 | + This is useful, so all the remote repositories are up to date with the |
| 78 | + latest permissions from their providers. |
78 | 79 |
|
79 | | - :param organization_slugs: list containg organization's slugs to sync. If |
80 | | - not passed, all organizations with ALLAUTH SSO enabled will be synced |
81 | | -
|
82 | | - :type organization_slugs: list |
| 80 | + We ignore repositories from GitHub App installations, since they are kept |
| 81 | + up to date via webhooks. For all the other services, we need to sync the |
| 82 | + repository for each user that has access to it, since we need to check for |
| 83 | + their permissions individually. |
83 | 84 | """ |
84 | | - if organization_slugs: |
85 | | - query = Organization.objects.filter(slug__in=organization_slugs) |
86 | | - log.info( |
87 | | - "Triggering SSO re-sync for organizations.", |
88 | | - organization_slugs=organization_slugs, |
89 | | - count=query.count(), |
90 | | - ) |
91 | | - else: |
92 | | - organization_ids = SSOIntegration.objects.filter( |
93 | | - provider=SSOIntegration.PROVIDER_ALLAUTH |
94 | | - ).values_list("organization", flat=True) |
95 | | - query = Organization.objects.filter(id__in=organization_ids) |
96 | | - log.info( |
97 | | - "Triggering SSO re-sync for all organizations.", |
98 | | - count=query.count(), |
99 | | - ) |
100 | | - |
101 | | - n_task = -1 |
102 | | - for organization in query: |
103 | | - members = AdminPermission.members(organization) |
104 | | - log.info( |
105 | | - "Triggering SSO re-sync for organization.", |
106 | | - organization_slug=organization.slug, |
107 | | - count=members.count(), |
| 85 | + repositories = ( |
| 86 | + RemoteRepository.objects.filter( |
| 87 | + projects__organizations__ssointegration__provider=SSOIntegration.PROVIDER_ALLAUTH, |
108 | 88 | ) |
109 | | - for user in members: |
110 | | - n_task += 1 |
111 | | - sync_remote_repositories.apply_async( |
112 | | - args=[user.pk], |
113 | | - # delay the task by 0, 5, 10, 15, ... seconds |
114 | | - countdown=n_task * 5, |
115 | | - ) |
| 89 | + .exclude(vcs_provider=GITHUB_APP) |
| 90 | + .distinct() |
| 91 | + ) |
| 92 | + for repository in repositories.iterator(): |
| 93 | + service_class = repository.get_service_class() |
| 94 | + relations = repository.remote_repository_relations.select_related("user", "account") |
| 95 | + for relation in relations.iterator(): |
| 96 | + service = service_class(user=relation.user, account=relation.account) |
| 97 | + try: |
| 98 | + service.update_repository(repository) |
| 99 | + except Exception: |
| 100 | + log.info( |
| 101 | + "There was a problem updating repository for user.", |
| 102 | + user_username=relation.user.username, |
| 103 | + account_uid=relation.account.uid, |
| 104 | + repository_remote_id=repository.remote_id, |
| 105 | + repository_name=repository.full_name, |
| 106 | + ) |
116 | 107 |
|
117 | 108 |
|
118 | 109 | @app.task( |
|
0 commit comments