Exemplo n.º 1
0
    def save(self,
             allow_authorize=True,
             force_authorize=False,
             extra_authorize_kwargs=None,
             trust_host=False,
             save=True):
        """Save the hosting account and authorize against the service.

        This will create or update a hosting account, based on the information
        provided in the form and to this method.

        :py:meth:`is_valid` must be called prior to saving.

        Args:
            allow_authorize (bool, optional):
                If ``True`` (the default), the account will be authorized
                against the hosting service. If ``False``, only the database
                entry for the account will be affected.

            force_authorize (bool, optional):
                Force the account to be re-authorized, if already authorized.

            extra_authorize_kwargs (dict, optional):
                Additional keyword arguments to provide for the
                :py:meth:`HostingService.authorize()
                <reviewboard.hostingsvcs.models.HostingService.authorize>`
                call.

            trust_host (bool, optional):
                Whether to trust the given host, even if the linked certificate
                is invalid or self-signed.

            save (bool, optional):
                Whether or not the created account should be saved.

                This is intended to be used by subclasses who want to add
                additional data to the resulting hosting account before saving.

                If this is ``False``, the caller must ensure the resulting
                hosting account is saved.

        Returns:
            reviewboard.hostingsvcs.models.HostingServiceAccount:
            The updated or created hosting service account.

        Raises:
            reviewboard.hostingsvcs.errors.AuthorizationError:
                Information needed to authorize was missing, or authorization
                failed.

            reviewboard.hostingsvcs.errors.TwoFactorAuthCodeRequiredError:
                A two-factor authentication code is required to authorize the
                account. A code will need to be provided to the form.
        """
        if extra_authorize_kwargs is None:
            extra_authorize_kwargs = {}

        credentials = self.get_credentials()

        # Grab the username from the credentials, sanity-checking that it's
        # been provided as part of the get_credentials() result.
        try:
            username = credentials['username']
        except KeyError:
            logging.exception(
                '%s.get_credentials() must return a "username" '
                'key.', self.__class__.__name__)

            raise AuthorizationError(
                ugettext('Hosting service implementation error: '
                         '%s.get_credentials() must return a "username" key.')
                % self.__class__.__name__)

        hosting_account = self.hosting_account
        hosting_service_id = self.hosting_service_cls.hosting_service_id
        hosting_url = self.cleaned_data.get('hosting_url')

        if not self.hosting_service_cls.self_hosted:
            assert hosting_url is None

        if hosting_account:
            # Update the username and hosting URL, if they've changed.
            hosting_account.username = username
            hosting_account.hosting_url = hosting_url
        else:
            # Fetch an existing hosting account based on the credentials and
            # parameters, if there is one. If not, we're going to create one,
            # but we won't save it until we've authorized.
            hosting_account_attrs = {
                'service_name': hosting_service_id,
                'username': username,
                'hosting_url': hosting_url,
                'local_site': self.local_site,
            }

            try:
                hosting_account = \
                    HostingServiceAccount.objects.get(**hosting_account_attrs)
            except HostingServiceAccount.DoesNotExist:
                # Create a new one, but don't save it yet.
                hosting_account = \
                    HostingServiceAccount(**hosting_account_attrs)

        if (allow_authorize and self.hosting_service_cls.needs_authorization
                and (not hosting_account.is_authorized or force_authorize)):
            # Attempt to authorize the account.
            if self.local_site:
                local_site_name = self.local_site.name
            else:
                local_site_name = None

            password = credentials.get('password')
            two_factor_auth_code = credentials.get('two_factor_auth_code')

            authorize_kwargs = dict(
                {
                    'username': username,
                    'password': password,
                    'hosting_url': hosting_url,
                    'two_factor_auth_code': two_factor_auth_code,
                    'local_site_name': local_site_name,
                    'credentials': credentials,
                }, **extra_authorize_kwargs)

            try:
                self.authorize(hosting_account, hosting_service_id,
                               **authorize_kwargs)
            except UnverifiedCertificateError as e:
                if trust_host:
                    hosting_account.accept_certificate(e.certificate)
                    self.authorize(hosting_account, hosting_service_id,
                                   **authorize_kwargs)
                else:
                    raise

        if save:
            hosting_account.save()

        return hosting_account
Exemplo n.º 2
0
    def save(self, allow_authorize=True, force_authorize=False,
             extra_authorize_kwargs=None, trust_host=False, save=True):
        """Save the hosting account and authorize against the service.

        This will create or update a hosting account, based on the information
        provided in the form and to this method.

        :py:meth:`is_valid` must be called prior to saving.

        Args:
            allow_authorize (bool, optional):
                If ``True`` (the default), the account will be authorized
                against the hosting service. If ``False``, only the database
                entry for the account will be affected.

            force_authorize (bool, optional):
                Force the account to be re-authorized, if already authorized.

            extra_authorize_kwargs (dict, optional):
                Additional keyword arguments to provide for the
                :py:meth:`HostingService.authorize()
                <reviewboard.hostingsvcs.models.HostingService.authorize>`
                call.

            trust_host (bool, optional):
                Whether to trust the given host, even if the linked certificate
                is invalid or self-signed.

            save (bool, optional):
                Whether or not the created account should be saved.

                This is intended to be used by subclasses who want to add
                additional data to the resulting hosting account before saving.

                If this is ``False``, the caller must ensure the resulting
                hosting account is saved.

        Returns:
            reviewboard.hostingsvcs.models.HostingServiceAccount:
            The updated or created hosting service account.

        Raises:
            reviewboard.hostingsvcs.errors.AuthorizationError:
                Information needed to authorize was missing, or authorization
                failed.

            reviewboard.hostingsvcs.errors.TwoFactorAuthCodeRequiredError:
                A two-factor authentication code is required to authorize the
                account. A code will need to be provided to the form.
        """
        if extra_authorize_kwargs is None:
            extra_authorize_kwargs = {}

        credentials = self.get_credentials()

        # Grab the username from the credentials, sanity-checking that it's
        # been provided as part of the get_credentials() result.
        try:
            username = credentials['username']
        except KeyError:
            logging.exception('%s.get_credentials() must return a "username" '
                              'key.',
                              self.__class__.__name__)

            raise AuthorizationError(
                ugettext('Hosting service implementation error: '
                         '%s.get_credentials() must return a "username" key.')
                % self.__class__.__name__)

        hosting_account = self.hosting_account
        hosting_service_id = self.hosting_service_cls.hosting_service_id
        hosting_url = self.cleaned_data.get('hosting_url')

        if not self.hosting_service_cls.self_hosted:
            assert hosting_url is None

        if hosting_account:
            # Update the username and hosting URL, if they've changed.
            hosting_account.username = username
            hosting_account.hosting_url = hosting_url
        else:
            # Fetch an existing hosting account based on the credentials and
            # parameters, if there is one. If not, we're going to create one,
            # but we won't save it until we've authorized.
            hosting_account_attrs = {
                'service_name': hosting_service_id,
                'username': username,
                'hosting_url': hosting_url,
                'local_site': self.local_site,
            }

            try:
                hosting_account = \
                    HostingServiceAccount.objects.get(**hosting_account_attrs)
            except HostingServiceAccount.DoesNotExist:
                # Create a new one, but don't save it yet.
                hosting_account = \
                    HostingServiceAccount(**hosting_account_attrs)

        if (allow_authorize and
            self.hosting_service_cls.needs_authorization and
            (not hosting_account.is_authorized or force_authorize)):
            # Attempt to authorize the account.
            if self.local_site:
                local_site_name = self.local_site.name
            else:
                local_site_name = None

            password = credentials.get('password')
            two_factor_auth_code = credentials.get('two_factor_auth_code')

            authorize_kwargs = dict({
                'username': username,
                'password': password,
                'hosting_url': hosting_url,
                'two_factor_auth_code': two_factor_auth_code,
                'local_site_name': local_site_name,
                'credentials': credentials,
            }, **extra_authorize_kwargs)

            try:
                self.authorize(hosting_account, hosting_service_id,
                               **authorize_kwargs)
            except UnverifiedCertificateError as e:
                if trust_host:
                    hosting_account.accept_certificate(e.certificate)
                    self.authorize(hosting_account, hosting_service_id,
                                   **authorize_kwargs)
                else:
                    raise

        if save:
            hosting_account.save()

        return hosting_account