Esempio n. 1
0
def sync_remote_repositories_organizations(organization_slugs=None):
    """
    Re-sync users member of organizations.

    It will trigger one `sync_remote_repositories` task per user.

    :param organization_slugs: list containg organization's slugs to sync. If
    not passed, all organizations with ALLAUTH SSO enabled will be synced

    :type organization_slugs: list
    """
    if organization_slugs:
        query = Organization.objects.filter(slug__in=organization_slugs)
        log.info(
            'Triggering SSO re-sync for organizations.',
            organization_slugs=organization_slugs,
            count=query.count(),
        )
    else:
        organization_ids = (SSOIntegration.objects.filter(
            provider=SSOIntegration.PROVIDER_ALLAUTH).values_list(
                'organization', flat=True))
        query = Organization.objects.filter(id__in=organization_ids)
        log.info(
            'Triggering SSO re-sync for all organizations.',
            count=query.count(),
        )

    n_task = -1
    for organization in query:
        members = AdminPermission.members(organization)
        log.info(
            'Triggering SSO re-sync for organization.',
            organization_slug=organization.slug,
            count=members.count(),
        )
        for user in members:
            n_task += 1
            sync_remote_repositories.apply_async(
                args=[user.pk],
                # delay the task by 0, 5, 10, 15, ... seconds
                countdown=n_task * 5,
            )
Esempio n. 2
0
    def resync_sso_user_accounts(self, request, queryset):  # pylint: disable=no-self-use
        users_count = 0
        organizations_count = queryset.count()

        for ssointegration in queryset.select_related('organization'):
            members = AdminPermission.members(ssointegration.organization)
            log.info(
                'Triggering SSO re-sync for organization.',
                organization_slug=ssointegration.organization.slug,
                count=members.count(),
            )
            users_count += members.count()
            for user in members:
                sync_remote_repositories.delay(user.pk)

        messages.add_message(
            request, messages.INFO,
            f'Triggered resync for {organizations_count} organizations and {users_count} users.'
        )
Esempio n. 3
0
 def members(self):
     return AdminPermission.members(self)
Esempio n. 4
0
def send_build_status(build_pk, commit, status, link_to_build=False):
    """
    Send Build Status to Git Status API for project external versions.

    It tries using these services' account in order:

    1. user's account that imported the project
    2. each user's account from the project's maintainers

    :param build_pk: Build primary key
    :param commit: commit sha of the pull/merge request
    :param status: build status failed, pending, or success to be sent.
    """
    # TODO: Send build status for BitBucket.
    build = Build.objects.filter(pk=build_pk).first()
    if not build:
        return

    provider_name = build.project.git_provider_name

    log.info('Sending build status. build=%s, project=%s', build.pk,
             build.project.slug)

    if provider_name in [GITHUB_BRAND, GITLAB_BRAND]:
        # get the service class for the project e.g: GitHubService.
        service_class = build.project.git_service_class()
        users = build.project.users.all()

        try:
            remote_repository = build.project.remote_repository
            remote_repository_relations = (
                remote_repository.remote_repository_relations.filter(
                    account__isnull=False,
                    # Use ``user_in=`` instead of ``user__projects=`` here
                    # because User's are not related to Project's directly in
                    # Read the Docs for Business
                    user__in=AdminPermission.members(build.project),
                ).select_related('account', 'user').only('user', 'account'))

            # Try using any of the users' maintainer accounts
            # Try to loop through all remote repository relations for the projects users
            for relation in remote_repository_relations:
                service = service_class(relation.user, relation.account)
                # Send status report using the API.
                success = service.send_build_status(
                    build=build,
                    commit=commit,
                    state=status,
                    link_to_build=link_to_build,
                )

                if success:
                    log.info(
                        'Build status report sent correctly. '
                        'project=%s build=%s status=%s commit=%s user=%s',
                        build.project.slug,
                        build.pk,
                        status,
                        commit,
                        relation.user.username,
                    )
                    return True

        except RemoteRepository.DoesNotExist:
            log.warning(
                'Project does not have a RemoteRepository. project=%s',
                build.project.slug,
            )
            # Try to send build status for projects with no RemoteRepository
            for user in users:
                services = service_class.for_user(user)
                # Try to loop through services for users all social accounts
                # to send successful build status
                for service in services:
                    success = service.send_build_status(build, commit, status)
                    if success:
                        log.info(
                            'Build status report sent correctly using an user account. '
                            'project=%s build=%s status=%s commit=%s user=%s',
                            build.project.slug,
                            build.pk,
                            status,
                            commit,
                            user.username,
                        )
                        return True

        for user in users:
            # Send Site notification about Build status reporting failure
            # to all the users of the project.
            notification = GitBuildStatusFailureNotification(
                context_object=build.project,
                extra_context={'provider_name': provider_name},
                user=user,
                success=False,
            )
            notification.send()

        log.info('No social account or repository permission available for %s',
                 build.project.slug)
        return False
Esempio n. 5
0
def is_project_user(user, project):
    """Checks if the user has access to the project."""
    return user in AdminPermission.members(project)