Exemple #1
0
    def save(self, commit=True, *args, **kwargs):
        """Saves the repository.

        This will thunk out to the hosting service form to save any extra
        repository data used for the hosting service, and saves the
        repository plan, if any.
        """
        repository = super(RepositoryForm, self).save(commit=False, *args, **kwargs)
        bug_tracker_use_hosting = self.cleaned_data["bug_tracker_use_hosting"]

        repository.extra_data = {
            "repository_plan": self.cleaned_data["repository_plan"],
            "bug_tracker_use_hosting": bug_tracker_use_hosting,
        }

        hosting_type = self.cleaned_data["hosting_type"]
        service = get_hosting_service(hosting_type)

        if service and service.self_hosted:
            repository.extra_data["hosting_url"] = self.cleaned_data["hosting_url"]

        if self.cert:
            repository.extra_data["cert"] = self.cert

        try:
            repository.extra_data["use_ticket_auth"] = self.cleaned_data["use_ticket_auth"]
        except KeyError:
            pass

        if hosting_type in self.repository_forms:
            plan = self.cleaned_data["repository_plan"] or self.DEFAULT_PLAN_ID
            self.repository_forms[hosting_type][plan].save(repository)

        if not bug_tracker_use_hosting:
            bug_tracker_type = self.cleaned_data["bug_tracker_type"]

            if bug_tracker_type in self.bug_tracker_forms:
                plan = self.cleaned_data["bug_tracker_plan"] or self.DEFAULT_PLAN_ID
                self.bug_tracker_forms[bug_tracker_type][plan].save(repository)
                repository.extra_data.update({"bug_tracker_type": bug_tracker_type, "bug_tracker_plan": plan})

                bug_tracker_service = get_hosting_service(bug_tracker_type)
                assert bug_tracker_service

                if bug_tracker_service.self_hosted:
                    repository.extra_data["bug_tracker_hosting_url"] = self.cleaned_data["bug_tracker_hosting_url"]

                if bug_tracker_service.get_bug_tracker_requires_username(plan):
                    repository.extra_data.update(
                        {
                            "bug_tracker-hosting_account_username": self.cleaned_data[
                                "bug_tracker_hosting_account_username"
                            ]
                        }
                    )

        if commit:
            repository.save()

        return repository
Exemple #2
0
    def setUpClass(cls):
        super(HostingServiceTestCase, cls).setUpClass()

        if cls.service_name:
            cls.service_class = get_hosting_service(cls.service_name)
        else:
            cls.service_class = None
Exemple #3
0
    def setUpClass(cls):
        super(HostingServiceTestCase, cls).setUpClass()

        if cls.service_name:
            cls.service_class = get_hosting_service(cls.service_name)
        else:
            cls.service_class = None
    def create(
        self, request, username, service_id, password=None, hosting_url=None, local_site_name=None, *args, **kwargs
    ):
        local_site = self._get_local_site(local_site_name)

        if not HostingServiceAccount.objects.can_create(request.user, local_site):
            return self._no_access_error(request.user)

        # Validate the service.
        service = get_hosting_service(service_id)

        if not service:
            return INVALID_FORM_DATA, {"fields": {"service": ["This is not a valid service name"]}}

        if service.self_hosted and not hosting_url:
            return INVALID_FORM_DATA, {"fields": {"hosting_url": ["This field is required"]}}

        account = HostingServiceAccount(
            service_name=service_id, username=username, hosting_url=hosting_url, local_site=local_site
        )
        service = account.service

        if service.needs_authorization:
            try:
                service.authorize(request, username, password, hosting_url, local_site_name)
            except AuthorizationError, e:
                return HOSTINGSVC_AUTH_ERROR, {"reason": str(e)}
Exemple #5
0
    def bug_tracker_service(self):
        """Returns selected bug tracker service if one exists."""
        bug_tracker_type = self.extra_data.get('bug_tracker_type')
        if bug_tracker_type:
            return get_hosting_service(bug_tracker_type)

        return None
Exemple #6
0
    def save(self, commit=True, *args, **kwargs):
        """Saves the repository.

        This will thunk out to the hosting service form to save any extra
        repository data used for the hosting service, and saves the
        repository plan, if any.
        """
        repository = super(RepositoryForm, self).save(commit=False,
                                                      *args,
                                                      **kwargs)
        bug_tracker_use_hosting = self.cleaned_data['bug_tracker_use_hosting']

        repository.extra_data = {
            'repository_plan': self.cleaned_data['repository_plan'],
            'bug_tracker_use_hosting': bug_tracker_use_hosting,
        }

        if self.cert:
            repository.extra_data['cert'] = self.cert

        try:
            repository.extra_data['use_ticket_auth'] = \
                self.cleaned_data['use_ticket_auth']
        except KeyError:
            pass

        hosting_type = self.cleaned_data['hosting_type']

        if hosting_type in self.repository_forms:
            plan = (self.cleaned_data['repository_plan']
                    or self.DEFAULT_PLAN_ID)
            self.repository_forms[hosting_type][plan].save(repository)

        if not bug_tracker_use_hosting:
            bug_tracker_type = self.cleaned_data['bug_tracker_type']

            if bug_tracker_type in self.bug_tracker_forms:
                plan = (self.cleaned_data['bug_tracker_plan']
                        or self.DEFAULT_PLAN_ID)
                self.bug_tracker_forms[bug_tracker_type][plan].save(repository)
                repository.extra_data.update({
                    'bug_tracker_type': bug_tracker_type,
                    'bug_tracker_plan': plan,
                })

                service = get_hosting_service(bug_tracker_type)
                assert service

                if service.get_bug_tracker_requires_username(plan):
                    repository.extra_data.update({
                        'bug_tracker-hosting_account_username':
                        self.
                        cleaned_data['bug_tracker_hosting_account_username'],
                    })

        if commit:
            repository.save()

        return repository
Exemple #7
0
    def test_unregister(self):
        """Testing HostingServiceHook uninitializing"""
        hook = HostingServiceHook(extension=self.extension,
                                  service_cls=TestService)

        hook.shutdown()

        self.assertEqual(None, get_hosting_service(TestService.name))
Exemple #8
0
    def test_unregister(self):
        """Testing HostingServiceHook uninitializing"""
        hook = HostingServiceHook(extension=self.extension,
                                  service_cls=TestService)

        hook.shutdown()

        self.assertEqual(None, get_hosting_service(TestService.name))
Exemple #9
0
    def save(self, commit=True, *args, **kwargs):
        """Saves the repository.

        This will thunk out to the hosting service form to save any extra
        repository data used for the hosting service, and saves the
        repository plan, if any.
        """
        repository = super(RepositoryForm, self).save(commit=False,
                                                      *args, **kwargs)
        bug_tracker_use_hosting = self.cleaned_data['bug_tracker_use_hosting']

        repository.extra_data = {
            'repository_plan': self.cleaned_data['repository_plan'],
            'bug_tracker_use_hosting': bug_tracker_use_hosting,
        }

        if self.cert:
            repository.extra_data['cert'] = self.cert

        try:
            repository.extra_data['use_ticket_auth'] = \
                self.cleaned_data['use_ticket_auth']
        except KeyError:
            pass

        hosting_type = self.cleaned_data['hosting_type']

        if hosting_type in self.repository_forms:
            plan = (self.cleaned_data['repository_plan'] or
                    self.DEFAULT_PLAN_ID)
            self.repository_forms[hosting_type][plan].save(repository)

        if not bug_tracker_use_hosting:
            bug_tracker_type = self.cleaned_data['bug_tracker_type']

            if bug_tracker_type in self.bug_tracker_forms:
                plan = (self.cleaned_data['bug_tracker_plan'] or
                        self.DEFAULT_PLAN_ID)
                self.bug_tracker_forms[bug_tracker_type][plan].save(repository)
                repository.extra_data.update({
                    'bug_tracker_type': bug_tracker_type,
                    'bug_tracker_plan': plan,
                })

                service = get_hosting_service(bug_tracker_type)
                assert service

                if service.get_bug_tracker_requires_username(plan):
                    repository.extra_data.update({
                        'bug_tracker-hosting_account_username':
                            self.cleaned_data[
                                'bug_tracker_hosting_account_username'],
                    })

        if commit:
            repository.save()

        return repository
Exemple #10
0
    def create(self,
               request,
               username,
               service_id,
               password=None,
               hosting_url=None,
               local_site_name=None,
               *args,
               **kwargs):
        """Creates a hosting service account.

        The ``service_id`` is a registered HostingService ID. This must be
        known beforehand, and can be looked up in the Review Board
        administration UI.
        """
        local_site = self._get_local_site(local_site_name)

        if not HostingServiceAccount.objects.can_create(
                request.user, local_site):
            return self._no_access_error(request.user)

        # Validate the service.
        service = get_hosting_service(service_id)

        if not service:
            return INVALID_FORM_DATA, {
                'fields': {
                    'service': ['This is not a valid service name'],
                }
            }

        if service.self_hosted and not hosting_url:
            return INVALID_FORM_DATA, {
                'fields': {
                    'hosting_url': ['This field is required'],
                }
            }

        account = HostingServiceAccount(service_name=service_id,
                                        username=username,
                                        hosting_url=hosting_url,
                                        local_site=local_site)
        service = account.service

        if service.needs_authorization:
            try:
                service.authorize(request, username, password, hosting_url,
                                  local_site_name)
            except AuthorizationError as e:
                return HOSTINGSVC_AUTH_ERROR, {
                    'reason': six.text_type(e),
                }

        account.save()

        return 201, {
            self.item_result_key: account,
        }
Exemple #11
0
    def service(self):
        if not hasattr(self, '_service'):
            cls = get_hosting_service(self.service_name)

            if cls:
                self._service = cls(self)
            else:
                self._service = None

        return self._service
Exemple #12
0
    def service(self):
        if not hasattr(self, '_service'):
            cls = get_hosting_service(self.service_name)

            if cls:
                self._service = cls(self)
            else:
                self._service = None

        return self._service
    def create(self, request, username, service_id, password=None,
               hosting_url=None, local_site_name=None, *args, **kwargs):
        """Creates a hosting service account.

        The ``service_id`` is a registered HostingService ID. This must be
        known beforehand, and can be looked up in the Review Board
        administration UI.
        """
        local_site = self._get_local_site(local_site_name)

        if not HostingServiceAccount.objects.can_create(request.user,
                                                        local_site):
            return self._no_access_error(request.user)

        # Validate the service.
        service = get_hosting_service(service_id)

        if not service:
            return INVALID_FORM_DATA, {
                'fields': {
                    'service': ['This is not a valid service name'],
                }
            }

        if service.self_hosted and not hosting_url:
            return INVALID_FORM_DATA, {
                'fields': {
                    'hosting_url': ['This field is required'],
                }
            }

        account = HostingServiceAccount(service_name=service_id,
                                        username=username,
                                        hosting_url=hosting_url,
                                        local_site=local_site)
        service = account.service

        if service.needs_authorization:
            try:
                service.authorize(request, username, password, hosting_url,
                                  local_site_name)
            except AuthorizationError as e:
                return HOSTINGSVC_AUTH_ERROR, {
                    'reason': six.text_type(e),
                }

        service.save()

        return 201, {
            self.item_result_key: account,
        }
Exemple #14
0
    def bug_tracker_service(self):
        """Returns selected bug tracker service if one exists."""
        if self.extra_data.get('bug_tracker_use_hosting'):
            return self.hosting_service
        else:
            bug_tracker_type = self.extra_data.get('bug_tracker_type')
            if bug_tracker_type:
                bug_tracker_cls = get_hosting_service(bug_tracker_type)

                # TODO: we need to figure out some way of storing a second
                # hosting service account for bug trackers.
                return bug_tracker_cls(HostingServiceAccount())

        return None
Exemple #15
0
    def bug_tracker_service(self):
        """Returns selected bug tracker service if one exists."""
        if self.extra_data.get('bug_tracker_use_hosting'):
            return self.hosting_service
        else:
            bug_tracker_type = self.extra_data.get('bug_tracker_type')
            if bug_tracker_type:
                bug_tracker_cls = get_hosting_service(bug_tracker_type)

                # TODO: we need to figure out some way of storing a second
                # hosting service account for bug trackers.
                return bug_tracker_cls(HostingServiceAccount())

        return None
Exemple #16
0
    def clean_hosting_type(self):
        """Validates that the hosting type represents a valid hosting service.

        This won't do anything if no hosting service is used.
        """
        hosting_type = self.cleaned_data['hosting_type']

        if hosting_type != self.NO_HOSTING_SERVICE_ID:
            hosting_service = get_hosting_service(hosting_type)

            if not hosting_service:
                raise forms.ValidationError(['Not a valid hosting service'])

        return hosting_type
Exemple #17
0
    def clean_hosting_type(self):
        """Validates that the hosting type represents a valid hosting service.

        This won't do anything if no hosting service is used.
        """
        hosting_type = self.cleaned_data['hosting_type']

        if hosting_type != self.NO_HOSTING_SERVICE_ID:
            hosting_service = get_hosting_service(hosting_type)

            if not hosting_service:
                raise forms.ValidationError(['Not a valid hosting service'])

        return hosting_type
Exemple #18
0
    def clean_bug_tracker_type(self):
        """Validates that the bug tracker type represents a valid hosting
        service.

        This won't do anything if no hosting service is used.
        """
        bug_tracker_type = self.cleaned_data["bug_tracker_type"] or self.NO_BUG_TRACKER_ID

        if bug_tracker_type not in self.IGNORED_SERVICE_IDS:
            hosting_service = get_hosting_service(bug_tracker_type)

            if not hosting_service or not hosting_service.supports_bug_trackers:
                raise ValidationError([_("Not a valid hosting service")])

        return bug_tracker_type
Exemple #19
0
    def _clean_ssh_key_association(self):
        hosting_type = self.cleaned_data["hosting_type"]
        hosting_account = self.cleaned_data["hosting_account"]

        # Don't proceed if there are already errors, or if not using hosting
        # (hosting type and account should be clean by this point)
        if self.errors or hosting_type == self.NO_HOSTING_SERVICE_ID or not hosting_account:
            return

        hosting_service_cls = get_hosting_service(hosting_type)
        hosting_service = hosting_service_cls(hosting_account)

        # Check the requirements for SSH key association. If the requirements
        # are not met, do not proceed.
        if (
            not hosting_service_cls.supports_ssh_key_association
            or not self.cleaned_data["associate_ssh_key"]
            or not self.public_key
        ):
            return

        if not self.instance.extra_data:
            # The instance is either a new repository or a repository that
            # was previously configured without a hosting service. In either
            # case, ensure the repository is fully initialized.
            repository = self.save(commit=False)
        else:
            repository = self.instance

        key = self.ssh_client.get_user_key()

        try:
            # Try to upload the key if it hasn't already been associated.
            if not hosting_service.is_ssh_key_associated(repository, key):
                hosting_service.associate_ssh_key(repository, key)
        except SSHKeyAssociationError as e:
            logging.warning('SSHKeyAssociationError for repository "%s" (%s)' % (repository, e.message))
            raise ValidationError(
                [
                    _(
                        "Unable to associate SSH key with your hosting service. "
                        "This is most often the result of a problem communicating "
                        "with the hosting service. Please try again later or "
                        "manually upload the SSH key to your hosting service."
                    )
                ]
            )
Exemple #20
0
    def clean_bug_tracker_type(self):
        """Validates that the bug tracker type represents a valid hosting
        service.

        This won't do anything if no hosting service is used.
        """
        bug_tracker_type = (self.cleaned_data['bug_tracker_type']
                            or self.NO_BUG_TRACKER_ID)

        if bug_tracker_type not in self.IGNORED_SERVICE_IDS:
            hosting_service = get_hosting_service(bug_tracker_type)

            if (not hosting_service
                    or not hosting_service.supports_bug_trackers):
                raise forms.ValidationError(['Not a valid hosting service'])

        return bug_tracker_type
Exemple #21
0
    def _populate_bug_tracker_fields(self):
        """Populates all the main bug tracker fields in the form.

        This populates the bug tracker type, plan, and other fields
        related to the bug tracker on the form.
        """
        data = self.instance.extra_data
        bug_tracker_type = data.get('bug_tracker_type', None)

        if (data.get('bug_tracker_use_hosting', False) and
            self.instance.hosting_account):
            # The user has chosen to use the hosting service's bug tracker.
            # We only care about the checkbox. Don't bother populating the form.
            self.fields['bug_tracker_use_hosting'].initial = True
        elif bug_tracker_type == self.NO_BUG_TRACKER_ID:
            # Do nothing.
            return
        elif (bug_tracker_type is not None and
              bug_tracker_type != self.CUSTOM_BUG_TRACKER_ID):
            # A bug tracker service or custom bug tracker was chosen.
            service = get_hosting_service(bug_tracker_type)

            if not service:
                return

            self.fields['bug_tracker_type'].initial = bug_tracker_type
            self.fields['bug_tracker_hosting_url'].initial = \
                data.get('bug_tracker_hosting_url', None)
            self.fields['bug_tracker_hosting_account_username'].initial = \
                data.get('bug_tracker-hosting_account_username', None)

            if service.plans:
                self.fields['bug_tracker_plan'].choices = [
                    (plan_id, info['name'])
                    for plan_id, info in service.plans
                ]

                self.fields['bug_tracker_plan'].initial = \
                    data.get('bug_tracker_plan', None)
        elif self.instance.bug_tracker:
            # We have a custom bug tracker. There's no point in trying to
            # reverse-match it, because we can potentially be wrong when a
            # hosting service has multiple plans with similar bug tracker
            # URLs, so just show it raw. Admins can migrate it if they want.
            self.fields['bug_tracker_type'].initial = \
                self.CUSTOM_BUG_TRACKER_ID
Exemple #22
0
    def _populate_bug_tracker_fields(self):
        """Populates all the main bug tracker fields in the form.

        This populates the bug tracker type, plan, and other fields
        related to the bug tracker on the form.
        """
        data = self.instance.extra_data
        bug_tracker_type = data.get('bug_tracker_type', None)

        if (data.get('bug_tracker_use_hosting', False) and
            self.instance.hosting_account):
            # The user has chosen to use the hosting service's bug tracker. We
            # only care about the checkbox. Don't bother populating the form.
            self.fields['bug_tracker_use_hosting'].initial = True
        elif bug_tracker_type == self.NO_BUG_TRACKER_ID:
            # Do nothing.
            return
        elif (bug_tracker_type is not None and
              bug_tracker_type != self.CUSTOM_BUG_TRACKER_ID):
            # A bug tracker service or custom bug tracker was chosen.
            service = get_hosting_service(bug_tracker_type)

            if not service:
                return

            self.fields['bug_tracker_type'].initial = bug_tracker_type
            self.fields['bug_tracker_hosting_url'].initial = \
                data.get('bug_tracker_hosting_url', None)
            self.fields['bug_tracker_hosting_account_username'].initial = \
                data.get('bug_tracker-hosting_account_username', None)

            if service.plans:
                self.fields['bug_tracker_plan'].choices = [
                    (plan_id, info['name'])
                    for plan_id, info in service.plans
                ]

                self.fields['bug_tracker_plan'].initial = \
                    data.get('bug_tracker_plan', None)
        elif self.instance.bug_tracker:
            # We have a custom bug tracker. There's no point in trying to
            # reverse-match it, because we can potentially be wrong when a
            # hosting service has multiple plans with similar bug tracker
            # URLs, so just show it raw. Admins can migrate it if they want.
            self.fields['bug_tracker_type'].initial = \
                self.CUSTOM_BUG_TRACKER_ID
    def create(self, request, username, service_id, password=None,
               hosting_url=None, local_site_name=None, *args, **kwargs):
        local_site = self._get_local_site(local_site_name)

        if not HostingServiceAccount.objects.can_create(request.user,
                                                        local_site):
            return self._no_access_error(request.user)

        # Validate the service.
        service = get_hosting_service(service_id)

        if not service:
            return INVALID_FORM_DATA, {
                'fields': {
                    'service': ['This is not a valid service name'],
                }
            }

        if service.self_hosted and not hosting_url:
            return INVALID_FORM_DATA, {
                'fields': {
                    'hosting_url': ['This field is required'],
                }
            }

        account = HostingServiceAccount(service_name=service_id,
                                        username=username,
                                        hosting_url=hosting_url,
                                        local_site=local_site)
        service = account.service

        if service.needs_authorization:
            try:
                service.authorize(request, username, password, hosting_url,
                                  local_site_name)
            except AuthorizationError as e:
                return HOSTINGSVC_AUTH_ERROR, {
                    'reason': str(e),
                }

        service.save()

        return 201, {
            self.item_result_key: account,
        }
Exemple #24
0
    def _clean_ssh_key_association(self):
        hosting_type = self.cleaned_data['hosting_type']
        hosting_account = self.cleaned_data['hosting_account']

        # Don't proceed if there are already errors, or if not using hosting
        # (hosting type and account should be clean by this point)
        if (self.errors or hosting_type == self.NO_HOSTING_SERVICE_ID
                or not hosting_account):
            return

        hosting_service_cls = get_hosting_service(hosting_type)
        hosting_service = hosting_service_cls(hosting_account)

        # Check the requirements for SSH key association. If the requirements
        # are not met, do not proceed.
        if (not hosting_service_cls.supports_ssh_key_association
                or not self.cleaned_data['associate_ssh_key']
                or not self.public_key):
            return

        if not self.instance.extra_data:
            # The instance is either a new repository or a repository that
            # was previously configured without a hosting service. In either
            # case, ensure the repository is fully initialized.
            repository = self.save(commit=False)
        else:
            repository = self.instance

        key = self.ssh_client.get_user_key()

        try:
            # Try to upload the key if it hasn't already been associated.
            if not hosting_service.is_ssh_key_associated(repository, key):
                hosting_service.associate_ssh_key(repository, key)
        except SSHKeyAssociationError, e:
            logging.warning('SSHKeyAssociationError for repository "%s" (%s)' %
                            (repository, e.message))
            raise forms.ValidationError([
                _('Unable to associate SSH key with '
                  'your hosting service. This is most often the result of a '
                  'problem communicating with the hosting service. Please try '
                  'again later or manually upload the SSH key to your hosting '
                  'service.')
            ])
    def create(self, request, username, service_id, password=None,
               hosting_url=None, local_site_name=None, *args, **kwargs):
        local_site = self._get_local_site(local_site_name)

        if not HostingServiceAccount.objects.can_create(request.user,
                                                        local_site):
            return self._no_access_error(request.user)

        # Validate the service.
        service = get_hosting_service(service_id)

        if not service:
            return INVALID_FORM_DATA, {
                'fields': {
                    'service': ['This is not a valid service name'],
                }
            }

        if service.self_hosted and not hosting_url:
            return INVALID_FORM_DATA, {
                'fields': {
                    'hosting_url': ['This field is required'],
                }
            }

        account = HostingServiceAccount(service_name=service_id,
                                        username=username,
                                        hosting_url=hosting_url,
                                        local_site=local_site)
        service = account.service

        if service.needs_authorization:
            try:
                service.authorize(request, username, password, hosting_url,
                                  local_site_name)
            except AuthorizationError, e:
                return HOSTINGSVC_AUTH_ERROR, {
                    'reason': str(e),
                }
Exemple #26
0
    def bug_tracker_service(self):
        """The selected bug tracker service for the repository.

        This will be ``None`` if this repository is not associated with a bug
        tracker.

        Type:
            reviewboard.hostingsvcs.service.HostingService
        """
        if self.extra_data.get('bug_tracker_use_hosting'):
            return self.hosting_service

        bug_tracker_type = self.extra_data.get('bug_tracker_type')

        if bug_tracker_type:
            bug_tracker_cls = get_hosting_service(bug_tracker_type)

            # TODO: we need to figure out some way of storing a second
            # hosting service account for bug trackers.
            return bug_tracker_cls(HostingServiceAccount())

        return None
Exemple #27
0
    def _clean_hosting_info(self):
        """Clean the hosting service information.

        If using a hosting service, this will validate that the data
        provided is valid on that hosting service. Then it will create an
        account and link it, if necessary, with the hosting service.
        """
        hosting_type = self.cleaned_data["hosting_type"]

        if hosting_type == self.NO_HOSTING_SERVICE_ID:
            self.data["hosting_account"] = None
            self.cleaned_data["hosting_account"] = None
            return

        # This should have been caught during validation, so we can assume
        # it's fine.
        hosting_service_cls = get_hosting_service(hosting_type)
        assert hosting_service_cls

        # Validate that the provided tool is valid for the hosting service.
        tool_name = self.cleaned_data["tool"].name

        if tool_name not in hosting_service_cls.supported_scmtools:
            self.errors["tool"] = self.error_class([_("This tool is not supported on the given hosting service")])
            return

        # Now make sure all the account info is correct.
        hosting_account = self.cleaned_data["hosting_account"]
        username = self.cleaned_data["hosting_account_username"]
        password = self.cleaned_data["hosting_account_password"]

        if hosting_service_cls.self_hosted:
            hosting_url = self.cleaned_data["hosting_url"] or None
        else:
            hosting_url = None

        if hosting_service_cls.supports_two_factor_auth:
            two_factor_auth_code = self.cleaned_data["hosting_account_two_factor_auth_code"]
        else:
            two_factor_auth_code = None

        if hosting_account and hosting_account.hosting_url != hosting_url:
            self.errors["hosting_account"] = self.error_class(
                [_("This account is not compatible with this hosting service " "configuration")]
            )
            return
        elif hosting_account and not username:
            username = hosting_account.username
        elif not hosting_account and not username:
            self.errors["hosting_account"] = self.error_class(
                [_("An account must be linked in order to use this hosting " "service")]
            )
            return

        if not hosting_account:
            # See if this account with the supplied credentials already
            # exists. If it does, we don't want to create a new entry.
            try:
                hosting_account = HostingServiceAccount.objects.get(
                    service_name=hosting_type, username=username, hosting_url=hosting_url, local_site=self.local_site
                )
            except HostingServiceAccount.DoesNotExist:
                # That's fine. We're just going to create it later.
                pass

        plan = self.cleaned_data["repository_plan"] or self.DEFAULT_PLAN_ID

        # Set the main repository fields (Path, Mirror Path, etc.) based on
        # the field definitions in the hosting service.
        #
        # This will take into account the hosting service's form data for
        # the given repository plan, the main form data, and the hosting
        # account information.
        #
        # It's expected that the required fields will have validated by now.
        repository_form = self.repository_forms[hosting_type][plan]
        field_vars = repository_form.cleaned_data.copy()
        field_vars.update(self.cleaned_data)

        # If the hosting account needs to authorize and link with an external
        # service, attempt to do so and watch for any errors.
        #
        # If it doesn't need to link with it, we'll just create an entry
        # with the username and save it.
        if not hosting_account:
            hosting_account = HostingServiceAccount(
                service_name=hosting_type, username=username, hosting_url=hosting_url, local_site=self.local_site
            )

        if hosting_service_cls.needs_authorization and not hosting_account.is_authorized:
            # Attempt to authorize the account.
            hosting_service = None
            plan = None

            if hosting_service_cls:
                hosting_service = hosting_service_cls(hosting_account)

                if hosting_service:
                    plan = self.cleaned_data["repository_plan"] or self.DEFAULT_PLAN_ID

            repository_extra_data = self._build_repository_extra_data(hosting_service, hosting_type, plan)

            try:
                hosting_account.service.authorize(
                    username,
                    password,
                    hosting_url=hosting_url,
                    two_factor_auth_code=two_factor_auth_code,
                    tool_name=tool_name,
                    local_site_name=self.local_site_name,
                    **repository_extra_data
                )
            except TwoFactorAuthCodeRequiredError as e:
                self.errors["hosting_account"] = self.error_class([six.text_type(e)])
                hosting_info = self.hosting_service_info[hosting_type]
                hosting_info["needs_two_factor_auth_code"] = True
                return
            except AuthorizationError as e:
                self.errors["hosting_account"] = self.error_class([_("Unable to link the account: %s") % e])
                return
            except Exception as e:
                self.errors["hosting_account"] = self.error_class([_("Unknown error when linking the account: %s") % e])
                return

        if hosting_account:
            # Flag that we've linked the account. If there are any
            # validation errors, and this flag is set, we tell the user
            # that we successfully linked and they don't have to do it
            # again.
            self.hosting_account_linked = True
            hosting_account.save()

        self.data["hosting_account"] = hosting_account
        self.cleaned_data["hosting_account"] = hosting_account

        try:
            self.cleaned_data.update(
                hosting_service_cls.get_repository_fields(
                    username=hosting_account.username,
                    hosting_url=hosting_account.hosting_url,
                    plan=plan,
                    tool_name=tool_name,
                    field_vars=field_vars,
                )
            )
        except KeyError as e:
            raise ValidationError([six.text_type(e)])
Exemple #28
0
    def test_register(self):
        """Testing HostingServiceHook initializing"""
        HostingServiceHook(extension=self.extension, service_cls=TestService)

        self.assertNotEqual(None, get_hosting_service(TestService.name))
    def setup_http_not_allowed_item_test(self, user):
        hosting_service = get_hosting_service('github')

        return get_hosting_service_item_url(hosting_service)
Exemple #30
0
    def __init__(self, *args, **kwargs):
        super(ServiceTests, self).__init__(*args, **kwargs)

        self.assertNotEqual(self.service_name, None)
        self.service_class = get_hosting_service(self.service_name)
Exemple #31
0
    def full_clean(self):
        extra_cleaned_data = {}
        extra_errors = {}
        required_values = {}

        for field in self.fields.itervalues():
            required_values[field] = field.required

        if self.data:
            hosting_type = self._get_field_data('hosting_type')
            hosting_service = get_hosting_service(hosting_type)
            repository_plan = (self._get_field_data('repository_plan') or
                               self.DEFAULT_PLAN_ID)

            bug_tracker_use_hosting = \
                self._get_field_data('bug_tracker_use_hosting')

            # If using the hosting service's bug tracker, we want to ignore
            # the bug tracker form (which will be hidden) and just use the
            # hosting service's form.
            if bug_tracker_use_hosting:
                bug_tracker_type = hosting_type
                bug_tracker_service = hosting_service
                bug_tracker_plan = repository_plan
            else:
                bug_tracker_type = self._get_field_data('bug_tracker_type')
                bug_tracker_service = get_hosting_service(bug_tracker_type)
                bug_tracker_plan = (self._get_field_data('bug_tracker_plan') or
                                    self.DEFAULT_PLAN_ID)

            self.fields['bug_tracker_type'].required = \
                not bug_tracker_use_hosting

            account_pk = self._get_field_data('hosting_account')

            new_hosting_account = (
                hosting_type != self.NO_HOSTING_SERVICE_ID and not account_pk)

            if account_pk:
                account = HostingServiceAccount.objects.get(
                    pk=account_pk,
                    local_site=self.local_site)
            else:
                account = None

            self.fields['path'].required = \
                (hosting_type == self.NO_HOSTING_SERVICE_ID)

            # The repository plan will only be listed if the hosting service
            # lists some plans. Otherwise, there's nothing to require.
            for service, field in ((hosting_service, 'repository_plan'),
                                   (bug_tracker_service, 'bug_tracker_plan')):
                self.fields[field].required = service and service.plans

                if service:
                    self.fields[field].choices = [
                        (id, info['name'])
                        for id, info in service.plans or []
                    ]

            self.fields['bug_tracker_plan'].required = (
                self.fields['bug_tracker_plan'].required and
                not bug_tracker_use_hosting)

            # We want to show this as required (in the label), but not
            # actually require, since we use a blank entry as
            # "Link new account."
            self.fields['hosting_account'].required = False

            # Only require a username and password if not using an existing
            # hosting account.
            self.fields['hosting_account_username'].required = \
                new_hosting_account
            self.fields['hosting_account_password'].required = (
                hosting_service and
                hosting_service.needs_authorization and
                (new_hosting_account or
                 (account and not account.is_authorized)))

            # Only require a URL if the hosting service is self-hosted.
            self.fields['hosting_url'].required = (
                hosting_service and
                hosting_service.self_hosted)

            # Only require the bug tracker username if the bug tracker field
            # requires the username.
            self.fields['bug_tracker_hosting_account_username'].required = \
                (not bug_tracker_use_hosting and
                 bug_tracker_service and
                 bug_tracker_service.get_bug_tracker_requires_username(
                    bug_tracker_plan))

            # Only require a URL if the bug tracker is self-hosted and
            # we're not using the hosting service's bug tracker.
            self.fields['bug_tracker_hosting_url'].required = (
                not bug_tracker_use_hosting and
                bug_tracker_service and
                bug_tracker_service.self_hosted)

            # Validate the custom forms and store any data or errors for later.
            custom_form_info = [
                (hosting_type, repository_plan, self.repository_forms),
            ]

            if not bug_tracker_use_hosting:
                custom_form_info.append((bug_tracker_type, bug_tracker_plan,
                                         self.bug_tracker_forms))

            for service_type, plan, form_list in custom_form_info:
                if service_type not in self.IGNORED_SERVICE_IDS:
                    form = form_list[service_type][plan]
                    form.is_bound = True

                    if form.is_valid():
                        extra_cleaned_data.update(form.cleaned_data)
                    else:
                        extra_errors.update(form.errors)
        else:
            # Validate every hosting service form and bug tracker form and
            # store any data or errors for later.
            for form_list in (self.repository_forms, self.bug_tracker_forms):
                for plans in form_list.values():
                    for form in plans.values():
                        if form.is_valid():
                            extra_cleaned_data.update(form.cleaned_data)
                        else:
                            extra_errors.update(form.errors)

        self.subforms_valid = not extra_errors

        super(RepositoryForm, self).full_clean()

        if self.is_valid():
            self.cleaned_data.update(extra_cleaned_data)
        else:
            self.errors.update(extra_errors)

        # Undo the required settings above. Now that we're done with them
        # for validation, we want to fix the display so that users don't
        # see the required states change.
        for field, required in required_values.iteritems():
            field.required = required
Exemple #32
0
    def _clean_hosting_info(self):
        """Clean the hosting service information.

        If using a hosting service, this will validate that the data
        provided is valid on that hosting service. Then it will create an
        account and link it, if necessary, with the hosting service.
        """
        hosting_type = self.cleaned_data['hosting_type']

        if hosting_type == self.NO_HOSTING_SERVICE_ID:
            return

        # This should have been caught during validation, so we can assume
        # it's fine.
        hosting_service_cls = get_hosting_service(hosting_type)
        assert hosting_service_cls

        # Validate that the provided tool is valid for the hosting service.
        tool_name = self.cleaned_data['tool'].name

        if tool_name not in hosting_service_cls.supported_scmtools:
            self.errors['tool'] = self.error_class([
                _('This tool is not supported on the given hosting service')
            ])
            return

        # Now make sure all the account info is correct.
        hosting_account = self.cleaned_data['hosting_account']
        username = self.cleaned_data['hosting_account_username']
        password = self.cleaned_data['hosting_account_password']

        if hosting_service_cls.self_hosted:
            hosting_url = self.cleaned_data['hosting_url'] or None
        else:
            hosting_url = None

        if hosting_account and hosting_account.hosting_url != hosting_url:
            self.errors['hosting_account'] = self.error_class([
                _('This account is not compatible with this hosting service '
                  'configuration'),
            ])
            return
        elif hosting_account and not username:
            username = hosting_account.username
        elif not hosting_account and not username:
            self.errors['hosting_account'] = self.error_class([
                _('An account must be linked in order to use this hosting '
                  'service'),
            ])
            return

        if not hosting_account:
            # See if this account with the supplied credentials already
            # exists. If it does, we don't want to create a new entry.
            try:
                hosting_account = HostingServiceAccount.objects.get(
                    service_name=hosting_type,
                    username=username,
                    hosting_url=hosting_url,
                    local_site=self.local_site)
            except HostingServiceAccount.DoesNotExist:
                # That's fine. We're just going to create it later.
                pass

        plan = self.cleaned_data['repository_plan'] or self.DEFAULT_PLAN_ID

        # Set the main repository fields (Path, Mirror Path, etc.) based on
        # the field definitions in the hosting service.
        #
        # This will take into account the hosting service's form data for
        # the given repository plan, the main form data, and the hosting
        # account information.
        #
        # It's expected that the required fields will have validated by now.
        repository_form = self.repository_forms[hosting_type][plan]
        field_vars = repository_form.cleaned_data.copy()
        field_vars.update(self.cleaned_data)

        # If the hosting account needs to authorize and link with an external
        # service, attempt to do so and watch for any errors.
        #
        # If it doesn't need to link with it, we'll just create an entry
        # with the username and save it.
        if not hosting_account:
            hosting_account = HostingServiceAccount(
                service_name=hosting_type,
                username=username,
                hosting_url=hosting_url,
                local_site=self.local_site)

        if (hosting_service_cls.needs_authorization and
            not hosting_account.is_authorized):
            try:
                hosting_account.service.authorize(
                    username, password,
                    hosting_url,
                    local_site_name=self.local_site_name)
            except AuthorizationError, e:
                self.errors['hosting_account'] = self.error_class([
                    _('Unable to link the account: %s') % e,
                ])
                return
            except Exception, e:
                self.errors['hosting_account'] = self.error_class([
                    _('Unknown error when linking the account: %s') % e,
                ])
                return
Exemple #33
0
    def _clean_hosting_info(self):
        """Clean the hosting service information.

        If using a hosting service, this will validate that the data
        provided is valid on that hosting service. Then it will create an
        account and link it, if necessary, with the hosting service.
        """
        hosting_type = self.cleaned_data['hosting_type']

        if hosting_type == self.NO_HOSTING_SERVICE_ID:
            return

        # This should have been caught during validation, so we can assume
        # it's fine.
        hosting_service_cls = get_hosting_service(hosting_type)
        assert hosting_service_cls

        # Validate that the provided tool is valid for the hosting service.
        tool_name = self.cleaned_data['tool'].name

        if tool_name not in hosting_service_cls.supported_scmtools:
            self.errors['tool'] = self.error_class([
                _('This tool is not supported on the given hosting service')
            ])
            return

        # Now make sure all the account info is correct.
        hosting_account = self.cleaned_data['hosting_account']
        username = self.cleaned_data['hosting_account_username']
        password = self.cleaned_data['hosting_account_password']

        if hosting_account and not username:
            username = hosting_account.username
        elif not hosting_account and not username:
            self.errors['hosting_account'] = self.error_class([
                _('An account must be linked in order to use this hosting '
                  'service'),
            ])
            return

        if not hosting_account:
            # See if this account with the supplied credentials already
            # exists. If it does, we don't want to create a new entry.
            try:
                hosting_account = HostingServiceAccount.objects.get(
                    service_name=hosting_type,
                    username=username,
                    local_site=self.local_site)
            except HostingServiceAccount.DoesNotExist:
                # That's fine. We're just going to create it later.
                pass

        # If the hosting account needs to authorize and link with an external
        # service, attempt to do so and watch for any errors.
        #
        # If it doesn't need to link with it, we'll just create an entry
        # with the username and save it.
        if not hosting_account:
            hosting_account = HostingServiceAccount(service_name=hosting_type,
                                                    username=username,
                                                    local_site=self.local_site)

        if (hosting_service_cls.needs_authorization and
            not hosting_account.is_authorized):
            try:
                hosting_account.service.authorize(
                    username, password,
                    local_site_name=self.local_site_name)
            except AuthorizationError, e:
                self.errors['hosting_account'] = self.error_class([
                    _('Unable to link the account: %s') % e,
                ])
                return
            except Exception, e:
                self.errors['hosting_account'] = self.error_class([
                    _('Unknown error when linking the account: %s') % e,
                ])
                return
    def setup_basic_get_test(self, user, with_local_site, local_site_name):
        hosting_service = get_hosting_service('github')

        return (get_hosting_service_item_url(hosting_service, local_site_name),
                hosting_service_item_mimetype, hosting_service)
Exemple #35
0
    def __init__(self, *args, **kwargs):
        super(ServiceTests, self).__init__(*args, **kwargs)

        self.assertNotEqual(self.service_name, None)
        self.service_class = get_hosting_service(self.service_name)
Exemple #36
0
    def _verify_repository_path(self):
        """
        Verifies the repository path to check if it's valid.

        This will check if the repository exists and if an SSH key or
        HTTPS certificate needs to be verified.
        """
        tool = self.cleaned_data.get('tool', None)

        if not tool:
            # This failed validation earlier, so bail.
            return

        scmtool_class = tool.get_scmtool_class()

        path = self.cleaned_data.get('path', '')
        username = self.cleaned_data['username']
        password = self.cleaned_data['password']

        if not path:
            self._errors['path'] = self.error_class(
                ['Repository path cannot be empty'])
            return

        hosting_type = self.cleaned_data['hosting_type']
        hosting_service_cls = get_hosting_service(hosting_type)
        hosting_service = None
        repository_extra_data = {}

        if hosting_service_cls:
            hosting_service = hosting_service_cls(
                self.cleaned_data['hosting_account'])
            plan = self.cleaned_data['repository_plan'] or self.DEFAULT_PLAN_ID

            if hosting_type in self.repository_forms:
                repository_extra_data = \
                    self.repository_forms[hosting_type][plan].cleaned_data

        while 1:
            # Keep doing this until we have an error we don't want
            # to ignore, or it's successful.
            try:
                if hosting_service:
                    hosting_service.check_repository(
                        path=path,
                        username=username,
                        password=password,
                        scmtool_class=scmtool_class,
                        local_site_name=self.local_site_name,
                        **repository_extra_data)
                else:
                    scmtool_class.check_repository(path, username, password,
                                                   self.local_site_name)

                # Success.
                break
            except BadHostKeyError, e:
                if self.cleaned_data['trust_host']:
                    try:
                        self.ssh_client.replace_host_key(e.hostname,
                                                         e.raw_expected_key,
                                                         e.raw_key)
                    except IOError, e:
                        raise forms.ValidationError(e)
                else:
                    self.hostkeyerror = e
                    break
    def setup_basic_get_test(self, user, with_local_site, local_site_name):
        hosting_service = get_hosting_service('github')

        return (get_hosting_service_item_url(hosting_service, local_site_name),
                hosting_service_item_mimetype,
                hosting_service)
Exemple #38
0
    def _verify_repository_path(self):
        """
        Verifies the repository path to check if it's valid.

        This will check if the repository exists and if an SSH key or
        HTTPS certificate needs to be verified.
        """
        tool = self.cleaned_data.get('tool', None)

        if not tool:
            # This failed validation earlier, so bail.
            return

        scmtool_class = tool.get_scmtool_class()

        path = self.cleaned_data.get('path', '')
        username = self.cleaned_data['username']
        password = self.cleaned_data['password']

        if not path:
            self._errors['path'] = self.error_class(
                ['Repository path cannot be empty'])
            return

        hosting_type = self.cleaned_data['hosting_type']
        hosting_service_cls = get_hosting_service(hosting_type)
        hosting_service = None
        repository_extra_data = {}

        if hosting_service_cls:
            hosting_service = hosting_service_cls(
                self.cleaned_data['hosting_account'])
            plan = self.cleaned_data['repository_plan'] or self.DEFAULT_PLAN_ID

            if hosting_type in self.repository_forms:
                repository_extra_data = \
                    self.repository_forms[hosting_type][plan].cleaned_data

        while 1:
            # Keep doing this until we have an error we don't want
            # to ignore, or it's successful.
            try:
                if hosting_service:
                    hosting_service.check_repository(
                        path=path,
                        username=username,
                        password=password,
                        scmtool_class=scmtool_class,
                        local_site_name=self.local_site_name,
                        **repository_extra_data)
                else:
                    scmtool_class.check_repository(path, username, password,
                                                   self.local_site_name)

                # Success.
                break
            except BadHostKeyError, e:
                if self.cleaned_data['trust_host']:
                    try:
                        self.ssh_client.replace_host_key(e.hostname,
                                                         e.raw_expected_key,
                                                         e.raw_key)
                    except IOError, e:
                        raise forms.ValidationError(e)
                else:
                    self.hostkeyerror = e
                    break
Exemple #39
0
    def _clean_hosting_info(self):
        """Clean the hosting service information.

        If using a hosting service, this will validate that the data
        provided is valid on that hosting service. Then it will create an
        account and link it, if necessary, with the hosting service.
        """
        hosting_type = self.cleaned_data['hosting_type']

        if hosting_type == self.NO_HOSTING_SERVICE_ID:
            return

        # This should have been caught during validation, so we can assume
        # it's fine.
        hosting_service_cls = get_hosting_service(hosting_type)
        assert hosting_service_cls

        # Validate that the provided tool is valid for the hosting service.
        tool_name = self.cleaned_data['tool'].name

        if tool_name not in hosting_service_cls.supported_scmtools:
            self.errors['tool'] = self.error_class(
                [_('This tool is not supported on the given hosting service')])
            return

        # Now make sure all the account info is correct.
        hosting_account = self.cleaned_data['hosting_account']
        username = self.cleaned_data['hosting_account_username']
        password = self.cleaned_data['hosting_account_password']

        if hosting_account and not username:
            username = hosting_account.username
        elif not hosting_account and not username:
            self.errors['hosting_account'] = self.error_class([
                _('An account must be linked in order to use this hosting '
                  'service'),
            ])
            return

        if not hosting_account:
            # See if this account with the supplied credentials already
            # exists. If it does, we don't want to create a new entry.
            try:
                hosting_account = HostingServiceAccount.objects.get(
                    service_name=hosting_type,
                    username=username,
                    local_site=self.local_site)
            except HostingServiceAccount.DoesNotExist:
                # That's fine. We're just going to create it later.
                pass

        # If the hosting account needs to authorize and link with an external
        # service, attempt to do so and watch for any errors.
        #
        # If it doesn't need to link with it, we'll just create an entry
        # with the username and save it.
        if not hosting_account:
            hosting_account = HostingServiceAccount(service_name=hosting_type,
                                                    username=username,
                                                    local_site=self.local_site)

        if (hosting_service_cls.needs_authorization
                and not hosting_account.is_authorized):
            try:
                hosting_account.service.authorize(
                    username, password, local_site_name=self.local_site_name)
            except AuthorizationError, e:
                self.errors['hosting_account'] = self.error_class([
                    _('Unable to link the account: %s') % e,
                ])
                return
            except Exception, e:
                self.errors['hosting_account'] = self.error_class([
                    _('Unknown error when linking the account: %s') % e,
                ])
                return
Exemple #40
0
    def _clean_hosting_info(self):
        """Clean the hosting service information.

        If using a hosting service, this will validate that the data
        provided is valid on that hosting service. Then it will create an
        account and link it, if necessary, with the hosting service.
        """
        hosting_type = self.cleaned_data['hosting_type']

        if hosting_type == self.NO_HOSTING_SERVICE_ID:
            self.data['hosting_account'] = None
            self.cleaned_data['hosting_account'] = None
            return

        # This should have been caught during validation, so we can assume
        # it's fine.
        hosting_service_cls = get_hosting_service(hosting_type)
        assert hosting_service_cls

        # Validate that the provided tool is valid for the hosting service.
        tool_name = self.cleaned_data['tool'].name

        if tool_name not in hosting_service_cls.supported_scmtools:
            self.errors['tool'] = self.error_class([
                _('This tool is not supported on the given hosting service')
            ])
            return

        # Now make sure all the account info is correct.
        hosting_account = self.cleaned_data['hosting_account']
        username = self.cleaned_data['hosting_account_username']
        password = self.cleaned_data['hosting_account_password']

        if hosting_service_cls.self_hosted:
            hosting_url = self.cleaned_data['hosting_url'] or None
        else:
            hosting_url = None

        if hosting_service_cls.supports_two_factor_auth:
            two_factor_auth_code = \
                self.cleaned_data['hosting_account_two_factor_auth_code']
        else:
            two_factor_auth_code = None

        if hosting_account and hosting_account.hosting_url != hosting_url:
            self.errors['hosting_account'] = self.error_class([
                _('This account is not compatible with this hosting service '
                  'configuration'),
            ])
            return
        elif hosting_account and not username:
            username = hosting_account.username
        elif not hosting_account and not username:
            self.errors['hosting_account'] = self.error_class([
                _('An account must be linked in order to use this hosting '
                  'service'),
            ])
            return

        if not hosting_account:
            # See if this account with the supplied credentials already
            # exists. If it does, we don't want to create a new entry.
            try:
                hosting_account = HostingServiceAccount.objects.get(
                    service_name=hosting_type,
                    username=username,
                    hosting_url=hosting_url,
                    local_site=self.local_site)
            except HostingServiceAccount.DoesNotExist:
                # That's fine. We're just going to create it later.
                pass

        plan = self.cleaned_data['repository_plan'] or self.DEFAULT_PLAN_ID

        # Set the main repository fields (Path, Mirror Path, etc.) based on
        # the field definitions in the hosting service.
        #
        # This will take into account the hosting service's form data for
        # the given repository plan, the main form data, and the hosting
        # account information.
        #
        # It's expected that the required fields will have validated by now.
        repository_form = self.repository_forms[hosting_type][plan]
        field_vars = repository_form.cleaned_data.copy()
        field_vars.update(self.cleaned_data)

        # If the hosting account needs to authorize and link with an external
        # service, attempt to do so and watch for any errors.
        #
        # If it doesn't need to link with it, we'll just create an entry
        # with the username and save it.
        if not hosting_account:
            hosting_account = HostingServiceAccount(
                service_name=hosting_type,
                username=username,
                hosting_url=hosting_url,
                local_site=self.local_site)

        if (hosting_service_cls.needs_authorization and
            not hosting_account.is_authorized):
            # Attempt to authorize the account.
            hosting_service = None
            plan = None

            if hosting_service_cls:
                hosting_service = hosting_service_cls(hosting_account)

                if hosting_service:
                    plan = (self.cleaned_data['repository_plan'] or
                            self.DEFAULT_PLAN_ID)

            repository_extra_data = self._build_repository_extra_data(
                hosting_service, hosting_type, plan)

            try:
                hosting_account.service.authorize(
                    username, password,
                    hosting_url=hosting_url,
                    two_factor_auth_code=two_factor_auth_code,
                    tool_name=tool_name,
                    local_site_name=self.local_site_name,
                    **repository_extra_data)
            except TwoFactorAuthCodeRequiredError as e:
                self.errors['hosting_account'] = \
                    self.error_class([six.text_type(e)])
                hosting_info = self.hosting_service_info[hosting_type]
                hosting_info['needs_two_factor_auth_code'] = True
                return
            except AuthorizationError as e:
                self.errors['hosting_account'] = self.error_class([
                    _('Unable to link the account: %s') % e,
                ])
                return
            except Exception as e:
                self.errors['hosting_account'] = self.error_class([
                    _('Unknown error when linking the account: %s') % e,
                ])
                return

            # Flag that we've linked the account. If there are any
            # validation errors, and this flag is set, we tell the user
            # that we successfully linked and they don't have to do it
            # again.
            self.hosting_account_linked = True
            hosting_account.save()

        self.data['hosting_account'] = hosting_account
        self.cleaned_data['hosting_account'] = hosting_account

        try:
            self.cleaned_data.update(hosting_service_cls.get_repository_fields(
                hosting_account.username, hosting_account.hosting_url, plan,
                tool_name, field_vars))
        except KeyError as e:
            raise ValidationError([six.text_type(e)])
Exemple #41
0
    def _clean_bug_tracker_info(self):
        """Clean the bug tracker information.

        This will figure out the defaults for all the bug tracker fields,
        based on the stored bug tracker settings.
        """
        use_hosting = self.cleaned_data['bug_tracker_use_hosting']
        plan = self.cleaned_data['bug_tracker_plan'] or self.DEFAULT_PLAN_ID
        bug_tracker_type = self.cleaned_data['bug_tracker_type']
        bug_tracker_url = ''

        if use_hosting:
            # We're using the main repository form fields instead of the
            # custom bug tracker fields.
            hosting_type = self.cleaned_data['hosting_type']

            if hosting_type == self.NO_HOSTING_SERVICE_ID:
                self.errors['bug_tracker_use_hosting'] = self.error_class([
                    _('A hosting service must be chosen in order to use this')
                ])
                return

            plan = self.cleaned_data['repository_plan'] or self.DEFAULT_PLAN_ID
            hosting_service_cls = get_hosting_service(hosting_type)

            # We already validated server-side that the hosting service
            # exists.
            assert hosting_service_cls

            if hosting_service_cls.supports_bug_trackers:
                form = self.repository_forms[hosting_type][plan]
                new_data = self.cleaned_data.copy()
                new_data.update(form.cleaned_data)
                new_data['hosting_account_username'] = \
                    self.cleaned_data['hosting_account'].username

                bug_tracker_url = hosting_service_cls.get_bug_tracker_field(
                    plan, new_data)
        elif bug_tracker_type == self.CUSTOM_BUG_TRACKER_ID:
            # bug_tracker_url should already be in cleaned_data.
            return
        elif bug_tracker_type != self.NO_BUG_TRACKER_ID:
            # We're using a bug tracker of a certain type. We need to
            # get the right data, strip the prefix on the forms, and
            # build the bug tracker URL from that.
            hosting_service_cls = get_hosting_service(bug_tracker_type)

            if not hosting_service_cls:
                self.errors['bug_tracker_type'] = self.error_class(
                    [_('This bug tracker type is not supported')])
                return

            form = self.bug_tracker_forms[bug_tracker_type][plan]

            # Strip the prefix from each bit of cleaned data in the form.
            new_data = {
                'hosting_account_username':
                self.cleaned_data['bug_tracker_hosting_account_username'],
            }

            for key, value in form.cleaned_data.iteritems():
                key = key.replace(form.prefix, '')
                new_data[key] = value

            bug_tracker_url = hosting_service_cls.get_bug_tracker_field(
                plan, new_data)

        self.cleaned_data['bug_tracker'] = bug_tracker_url
        self.data['bug_tracker'] = bug_tracker_url
Exemple #42
0
    def _clean_bug_tracker_info(self):
        """Clean the bug tracker information.

        This will figure out the defaults for all the bug tracker fields,
        based on the stored bug tracker settings.
        """
        use_hosting = self.cleaned_data['bug_tracker_use_hosting']
        plan = self.cleaned_data['bug_tracker_plan'] or self.DEFAULT_PLAN_ID
        bug_tracker_type = self.cleaned_data['bug_tracker_type']
        bug_tracker_url = ''

        if use_hosting:
            # We're using the main repository form fields instead of the
            # custom bug tracker fields.
            hosting_type = self.cleaned_data['hosting_type']

            if hosting_type == self.NO_HOSTING_SERVICE_ID:
                self.errors['bug_tracker_use_hosting'] = self.error_class([
                    _('A hosting service must be chosen in order to use this')
                ])
                return

            plan = self.cleaned_data['repository_plan'] or self.DEFAULT_PLAN_ID
            hosting_service_cls = get_hosting_service(hosting_type)

            # We already validated server-side that the hosting service
            # exists.
            assert hosting_service_cls

            if hosting_service_cls.supports_bug_trackers:
                form = self.repository_forms[hosting_type][plan]
                new_data = self.cleaned_data.copy()
                new_data.update(form.cleaned_data)
                new_data['hosting_account_username'] = \
                    self.cleaned_data['hosting_account'].username
                new_data['hosting_url'] = \
                    self.cleaned_data['hosting_account'].hosting_url

                bug_tracker_url = hosting_service_cls.get_bug_tracker_field(
                    plan, new_data)
        elif bug_tracker_type == self.CUSTOM_BUG_TRACKER_ID:
            # bug_tracker_url should already be in cleaned_data.
            return
        elif bug_tracker_type != self.NO_BUG_TRACKER_ID:
            # We're using a bug tracker of a certain type. We need to
            # get the right data, strip the prefix on the forms, and
            # build the bug tracker URL from that.
            hosting_service_cls = get_hosting_service(bug_tracker_type)

            if not hosting_service_cls:
                self.errors['bug_tracker_type'] = self.error_class([
                    _('This bug tracker type is not supported')
                ])
                return

            form = self.bug_tracker_forms[bug_tracker_type][plan]

            new_data = {
                'hosting_account_username':
                    self.cleaned_data['bug_tracker_hosting_account_username'],
                'hosting_url':
                    self.cleaned_data['bug_tracker_hosting_url'],
            }

            if form.is_valid():
                # Strip the prefix from each bit of cleaned data in the form.
                for key, value in form.cleaned_data.iteritems():
                    key = key.replace(form.prefix, '')
                    new_data[key] = value

            bug_tracker_url = hosting_service_cls.get_bug_tracker_field(
                plan, new_data)

        self.cleaned_data['bug_tracker'] = bug_tracker_url
        self.data['bug_tracker'] = bug_tracker_url
Exemple #43
0
    def full_clean(self):
        extra_cleaned_data = {}
        extra_errors = {}
        required_values = {}

        for field in self.fields.itervalues():
            required_values[field] = field.required

        if self.data:
            hosting_type = self._get_field_data('hosting_type')
            hosting_service = get_hosting_service(hosting_type)
            repository_plan = (self._get_field_data('repository_plan')
                               or self.DEFAULT_PLAN_ID)

            bug_tracker_use_hosting = \
                self._get_field_data('bug_tracker_use_hosting')

            # If using the hosting service's bug tracker, we want to ignore
            # the bug tracker form (which will be hidden) and just use the
            # hosting service's form.
            if bug_tracker_use_hosting:
                bug_tracker_type = hosting_type
                bug_tracker_service = hosting_service
                bug_tracker_plan = repository_plan
            else:
                bug_tracker_type = self._get_field_data('bug_tracker_type')
                bug_tracker_service = get_hosting_service(bug_tracker_type)
                bug_tracker_plan = (self._get_field_data('bug_tracker_plan')
                                    or self.DEFAULT_PLAN_ID)

            self.fields['bug_tracker_type'].required = \
                not bug_tracker_use_hosting

            account_pk = self._get_field_data('hosting_account')

            new_hosting_account = (hosting_type != self.NO_HOSTING_SERVICE_ID
                                   and not account_pk)

            if account_pk:
                account = HostingServiceAccount.objects.get(pk=account_pk)
            else:
                account = None

            self.fields['path'].required = \
                (hosting_type == self.NO_HOSTING_SERVICE_ID)

            # The repository plan will only be listed if the hosting service
            # lists some plans. Otherwise, there's nothing to require.
            for service, field in ((hosting_service, 'repository_plan'),
                                   (bug_tracker_service, 'bug_tracker_plan')):
                self.fields[field].required = service and service.plans

                if service:
                    self.fields[field].choices = [
                        (id, info['name']) for id, info in service.plans or []
                    ]

            self.fields['bug_tracker_plan'].required = (
                self.fields['bug_tracker_plan'].required
                and not bug_tracker_use_hosting)

            # We want to show this as required (in the label), but not
            # actually require, since we use a blank entry as
            # "Link new account."
            self.fields['hosting_account'].required = False

            # Only require a username and password if not using an existing
            # hosting account.
            self.fields['hosting_account_username'].required = \
                new_hosting_account
            self.fields['hosting_account_password'].required = (
                hosting_service and hosting_service.needs_authorization
                and (new_hosting_account or
                     (account and not account.is_authorized)))

            # Only require the bug tracker username if the bug tracker field
            # requires the username.
            self.fields['bug_tracker_hosting_account_username'].required = \
                (not bug_tracker_use_hosting and
                 bug_tracker_service and
                 bug_tracker_service.get_bug_tracker_requires_username(
                    bug_tracker_plan))

            # Validate the custom forms and store any data or errors for later.
            custom_form_info = [
                (hosting_type, repository_plan, self.repository_forms),
            ]

            if not bug_tracker_use_hosting:
                custom_form_info.append((bug_tracker_type, bug_tracker_plan,
                                         self.bug_tracker_forms))

            for service_type, plan, form_list in custom_form_info:
                if service_type not in self.IGNORED_SERVICE_IDS:
                    form = form_list[service_type][plan]
                    form.is_bound = True

                    if form.is_valid():
                        extra_cleaned_data.update(form.cleaned_data)
                    else:
                        extra_errors.update(form.errors)
        else:
            # Validate every hosting service form and bug tracker form and
            # store any data or errors for later.
            for form_list in (self.repository_forms, self.bug_tracker_forms):
                for plans in form_list.values():
                    for form in plans.values():
                        if form.is_valid():
                            extra_cleaned_data.update(form.cleaned_data)
                        else:
                            extra_errors.update(form.errors)

        self.subforms_valid = not extra_errors

        super(RepositoryForm, self).full_clean()

        if self.is_valid():
            self.cleaned_data.update(extra_cleaned_data)
        else:
            self.errors.update(extra_errors)

        # Undo the required settings above. Now that we're done with them
        # for validation, we want to fix the display so that users don't
        # see the required states change.
        for field, required in required_values.iteritems():
            field.required = required
Exemple #44
0
    def _verify_repository_path(self):
        """
        Verifies the repository path to check if it's valid.

        This will check if the repository exists and if an SSH key or
        HTTPS certificate needs to be verified.
        """
        tool = self.cleaned_data.get('tool', None)

        if not tool:
            # This failed validation earlier, so bail.
            return

        scmtool_class = tool.get_scmtool_class()

        path = self.cleaned_data.get('path', '')
        username = self.cleaned_data['username']
        password = self.cleaned_data['password']

        if not path:
            self._errors['path'] = self.error_class(
                ['Repository path cannot be empty'])
            return

        hosting_type = self.cleaned_data['hosting_type']
        hosting_service_cls = get_hosting_service(hosting_type)
        hosting_service = None
        plan = None

        if hosting_service_cls:
            hosting_service = hosting_service_cls(
                self.cleaned_data['hosting_account'])

            if hosting_service:
                plan = (self.cleaned_data['repository_plan'] or
                        self.DEFAULT_PLAN_ID)

        repository_extra_data = self._build_repository_extra_data(
            hosting_service, hosting_type, plan)

        while 1:
            # Keep doing this until we have an error we don't want
            # to ignore, or it's successful.
            try:
                if hosting_service:
                    hosting_service.check_repository(
                        path=path,
                        username=username,
                        password=password,
                        scmtool_class=scmtool_class,
                        tool_name=tool.name,
                        local_site_name=self.local_site_name,
                        plan=plan,
                        **repository_extra_data)
                else:
                    scmtool_class.check_repository(path, username, password,
                                                   self.local_site_name)

                # Success.
                break
            except BadHostKeyError as e:
                if self.cleaned_data['trust_host']:
                    try:
                        self.ssh_client.replace_host_key(e.hostname,
                                                         e.raw_expected_key,
                                                         e.raw_key)
                    except IOError as e:
                        raise ValidationError(e)
                else:
                    self.hostkeyerror = e
                    break
            except UnknownHostKeyError as e:
                if self.cleaned_data['trust_host']:
                    try:
                        self.ssh_client.add_host_key(e.hostname, e.raw_key)
                    except IOError as e:
                        raise ValidationError(e)
                else:
                    self.hostkeyerror = e
                    break
            except UnverifiedCertificateError as e:
                if self.cleaned_data['trust_host']:
                    try:
                        self.cert = scmtool_class.accept_certificate(
                            path, self.local_site_name, e.certificate)
                    except IOError as e:
                        raise ValidationError(e)
                else:
                    self.certerror = e
                    break
            except AuthenticationError as e:
                if 'publickey' in e.allowed_types and e.user_key is None:
                    self.userkeyerror = e
                    break

                raise ValidationError(e)
            except Exception as e:
                try:
                    text = six.text_type(e)
                except UnicodeDecodeError:
                    text = six.text_type(e, 'ascii', 'replace')
                raise ValidationError(text)
Exemple #45
0
    def test_register(self):
        """Testing HostingServiceHook initializing"""
        HostingServiceHook(self.extension, TestService)

        self.assertEqual(get_hosting_service('test-service'), TestService)
    def setup_http_not_allowed_item_test(self, user):
        hosting_service = get_hosting_service('github')

        return get_hosting_service_item_url(hosting_service)
Exemple #47
0
    def test_unregister(self):
        """Testing HostingServiceHook uninitializing"""
        hook = HostingServiceHook(self.extension, TestService)
        hook.disable_hook()

        self.assertIsNone(get_hosting_service('test-service'))
Exemple #48
0
    def _verify_repository_path(self):
        """
        Verifies the repository path to check if it's valid.

        This will check if the repository exists and if an SSH key or
        HTTPS certificate needs to be verified.
        """
        tool = self.cleaned_data.get('tool', None)

        if not tool:
            # This failed validation earlier, so bail.
            return

        scmtool_class = tool.get_scmtool_class()

        path = self.cleaned_data.get('path', '')
        username = self.cleaned_data['username']
        password = self.cleaned_data['password']

        if not path:
            self._errors['path'] = self.error_class(
                ['Repository path cannot be empty'])
            return

        hosting_type = self.cleaned_data['hosting_type']
        hosting_service_cls = get_hosting_service(hosting_type)
        hosting_service = None
        plan = None

        if hosting_service_cls:
            hosting_service = hosting_service_cls(
                self.cleaned_data['hosting_account'])

        repository_extra_data = self._build_repository_extra_data(
            hosting_service, hosting_type)

        while 1:
            # Keep doing this until we have an error we don't want
            # to ignore, or it's successful.
            try:
                if hosting_service:
                    hosting_service.check_repository(
                        path=path,
                        username=username,
                        password=password,
                        scmtool_class=scmtool_class,
                        tool_name=tool.name,
                        local_site_name=self.local_site_name,
                        plan=plan,
                        **repository_extra_data)
                else:
                    scmtool_class.check_repository(path, username, password,
                                                   self.local_site_name)

                # Success.
                break
            except BadHostKeyError as e:
                if self.cleaned_data['trust_host']:
                    try:
                        self.ssh_client.replace_host_key(e.hostname,
                                                         e.raw_expected_key,
                                                         e.raw_key)
                    except IOError as e:
                        raise ValidationError(e)
                else:
                    self.hostkeyerror = e
                    break
            except UnknownHostKeyError as e:
                if self.cleaned_data['trust_host']:
                    try:
                        self.ssh_client.add_host_key(e.hostname, e.raw_key)
                    except IOError as e:
                        raise ValidationError(e)
                else:
                    self.hostkeyerror = e
                    break
            except UnverifiedCertificateError as e:
                if self.cleaned_data['trust_host']:
                    try:
                        self.cert = scmtool_class.accept_certificate(
                            path, self.local_site_name, e.certificate)
                    except IOError as e:
                        raise ValidationError(e)
                else:
                    self.certerror = e
                    break
            except AuthenticationError as e:
                if 'publickey' in e.allowed_types and e.user_key is None:
                    self.userkeyerror = e
                    break

                raise ValidationError(e)
            except Exception as e:
                try:
                    text = six.text_type(e)
                except UnicodeDecodeError:
                    text = six.text_type(e, 'ascii', 'replace')
                raise ValidationError(text)
Exemple #49
0
    def test_register(self):
        """Testing HostingServiceHook initializing"""
        HostingServiceHook(extension=self.extension, service_cls=TestService)

        self.assertNotEqual(None, get_hosting_service(TestService.name))