예제 #1
0
    def get_draft(self, user=None):
        """Returns the draft of the review request.

        If a user is specified, than the draft will be returned only if owned
        by the user. Otherwise, None will be returned.
        """
        if not user:
            return get_object_or_none(self.draft)
        elif user.is_authenticated():
            return get_object_or_none(self.draft, review_request__submitter=user)

        return None
예제 #2
0
    def get_draft(self, user=None):
        """Returns the draft of the review request.

        If a user is specified, than the draft will be returned only if owned
        by the user. Otherwise, None will be returned.
        """
        if not user:
            return get_object_or_none(self.draft)
        elif user.is_authenticated():
            return get_object_or_none(self.draft,
                                      review_request__submitter=user)

        return None
예제 #3
0
파일: forms.py 프로젝트: halvorlu/djblets
    def save(self):
        """Save the form, creating a user if validation passes.

        The :py:class:`User` will be created with the provided username,
        e-mail address, password, and full name. If there are failures
        in creating this user, or there's an existing user with the given
        name, an error will be raisd.

        Subclasses that want to override this can call the parent's
        py:meth:`save` and modify the resulting user, if ``None`` is not
        returned.

        Returns:
            User: The newly-created user.
        """
        if not self.errors:
            try:
                user = auth.models.User.objects.create_user(
                    self.cleaned_data['username'],
                    self.cleaned_data['email'],
                    self.cleaned_data['password1'])
                user.first_name = self.cleaned_data['first_name']
                user.last_name = self.cleaned_data['last_name']
                user.save()
                return user
            except:
                # We check for duplicate users here instead of clean, since
                # it's possible that two users could race for a name.
                if get_object_or_none(User,
                                      username=self.cleaned_data['username']):
                    self.errors['username'] = forms.util.ErrorList(
                        [_('Sorry, this username is taken.')])
                else:
                    raise
예제 #4
0
    def _check(*args, **kwargs):
        request = _find_httprequest(args)
        local_site_name = kwargs.get('local_site_name', None)
        webapi_token = getattr(request, '_webapi_token', None)

        if webapi_token:
            restrict_to_local_site = request._webapi_token.local_site_id
        else:
            restrict_to_local_site = None

        if local_site_name:
            local_site = get_object_or_none(LocalSite, name=local_site_name)

            if not local_site:
                return DOES_NOT_EXIST
            elif not local_site.is_accessible_by(request.user):
                if request.user.is_authenticated():
                    return PERMISSION_DENIED
                else:
                    return NOT_LOGGED_IN
            elif (restrict_to_local_site
                  and restrict_to_local_site != local_site.pk):
                return PERMISSION_DENIED
        elif restrict_to_local_site is not None:
            return PERMISSION_DENIED

        return view_func(*args, **kwargs)
예제 #5
0
    def _check(*args, **kwargs):
        request = _find_httprequest(args)
        local_site_name = kwargs.get('local_site_name', None)
        webapi_token = getattr(request, '_webapi_token', None)

        if webapi_token:
            restrict_to_local_site = request._webapi_token.local_site_id
        else:
            restrict_to_local_site = None

        if local_site_name:
            local_site = get_object_or_none(LocalSite, name=local_site_name)

            if not local_site:
                return DOES_NOT_EXIST
            elif not local_site.is_accessible_by(request.user):
                if request.user.is_authenticated():
                    return PERMISSION_DENIED
                else:
                    return NOT_LOGGED_IN
            elif (restrict_to_local_site and
                  restrict_to_local_site != local_site.pk):
                return PERMISSION_DENIED

            kwargs['local_site'] = local_site
        elif restrict_to_local_site is not None:
            return PERMISSION_DENIED
        else:
            kwargs['local_site'] = None

        return view_func(*args, **kwargs)
예제 #6
0
    def process_view(self, request, view_func, view_args, view_kwargs):
        """Process the request before calling the view.

        This sets up a ``local_site`` attribute on the request to fetch the
        :py:class:`~reviewboard.site.models.LocalSite` used for this view,
        if any. This is based on the ``local_site_name`` key in
        ``view_kwargs``.

        Args:
            request (django.http.HttpRequest):
                The HTTP request from the client.

            view_func (callable):
                The view being called. This is unused.

            view_args (tuple):
                The positional arguments passed to the view. This is unused.

            view_kwargs (dict):
                The keyword arguments passed to the view.
        """
        local_site_name = view_kwargs.get('local_site_name')
        request._local_site_name = local_site_name

        if request._local_site_name:
            request.local_site = SimpleLazyObject(
                lambda: get_object_or_none(LocalSite, name=local_site_name))
        else:
            request.local_site = None
예제 #7
0
    def process_view(self, request, view_func, view_args, view_kwargs):
        """Process the request before calling the view.

        This sets up a ``local_site`` attribute on the request to fetch the
        :py:class:`~reviewboard.site.models.LocalSite` used for this view,
        if any. This is based on the ``local_site_name`` key in
        ``view_kwargs``.

        Args:
            request (django.http.HttpRequest):
                The HTTP request from the client.

            view_func (callable):
                The view being called. This is unused.

            view_args (tuple):
                The positional arguments passed to the view. This is unused.

            view_kwargs (dict):
                The keyword arguments passed to the view.
        """
        local_site_name = view_kwargs.get('local_site_name')
        request._local_site_name = local_site_name

        if request._local_site_name:
            request.local_site = SimpleLazyObject(
                lambda: get_object_or_none(LocalSite, name=local_site_name))
        else:
            request.local_site = None
예제 #8
0
    def save(self):
        """Save the form, creating a user if validation passes.

        The :py:class:`User` will be created with the provided username,
        e-mail address, password, and full name. If there are failures
        in creating this user, or there's an existing user with the given
        name, an error will be raisd.

        Subclasses that want to override this can call the parent's
        py:meth:`save` and modify the resulting user, if ``None`` is not
        returned.

        Returns:
            User: The newly-created user.
        """
        if not self.errors:
            try:
                user = auth.models.User.objects.create_user(
                    self.cleaned_data['username'], self.cleaned_data['email'],
                    self.cleaned_data['password1'])
                user.first_name = self.cleaned_data['first_name']
                user.last_name = self.cleaned_data['last_name']
                user.save()
                return user
            except:
                # We check for duplicate users here instead of clean, since
                # it's possible that two users could race for a name.
                if get_object_or_none(User,
                                      username=self.cleaned_data['username']):
                    self.errors['username'] = form_utils.ErrorList(
                        [_('Sorry, this username is taken.')])
                else:
                    raise
예제 #9
0
    def publish(self, user):
        """Publishes the current draft attached to this review request.

        The review request will be mark as public, and signals will be
        emitted for any listeners.
        """
        from reviewboard.accounts.models import LocalSiteProfile

        if not self.is_mutable_by(user):
            raise PermissionError

        draft = get_object_or_none(self.draft)

        review_request_publishing.send(sender=self.__class__,
                                       user=user,
                                       review_request_draft=draft)

        # Decrement the counts on everything. we lose them.
        # We'll increment the resulting set during ReviewRequest.save.
        # This should be done before the draft is published.
        # Once the draft is published, the target people
        # and groups will be updated with new values.
        # Decrement should not happen while publishing
        # a new request or a discarded request
        if self.public:
            Group.incoming_request_count.decrement(self.target_groups.all())
            LocalSiteProfile.direct_incoming_request_count.decrement(
                LocalSiteProfile.objects.filter(
                    user__in=self.target_people.all(),
                    local_site=self.local_site))
            LocalSiteProfile.total_incoming_request_count.decrement(
                LocalSiteProfile.objects.filter(
                    Q(local_site=self.local_site) & Q(
                        Q(user__review_groups__in=self.target_groups.all())
                        | Q(user__in=self.target_people.all()))))
            LocalSiteProfile.starred_public_request_count.decrement(
                LocalSiteProfile.objects.filter(
                    profile__starred_review_requests=self,
                    local_site=self.local_site))

        if draft is not None:
            # This will in turn save the review request, so we'll be done.
            changes = draft.publish(self, send_notification=False)
            draft.delete()
        else:
            changes = None

        if not self.public and self.changedescs.count() == 0:
            # This is a brand new review request that we're publishing
            # for the first time. Set the creation timestamp to now.
            self.time_added = timezone.now()

        self.public = True
        self.save(update_counts=True)

        review_request_published.send(sender=self.__class__,
                                      user=user,
                                      review_request=self,
                                      changedesc=changes)
예제 #10
0
    def publish(self, user, trivial=False, validate_fields=True):
        """Publishes the current draft attached to this review request.

        The review request will be mark as public, and signals will be
        emitted for any listeners.
        """
        if not self.is_mutable_by(user):
            raise PermissionError

        draft = get_object_or_none(self.draft)
        old_submitter = self.submitter

        review_request_publishing.send(sender=self.__class__,
                                       user=user,
                                       review_request_draft=draft)

        # Decrement the counts on everything. we lose them.
        # We'll increment the resulting set during ReviewRequest.save.
        # This should be done before the draft is published.
        # Once the draft is published, the target people
        # and groups will be updated with new values.
        # Decrement should not happen while publishing
        # a new request or a discarded request
        if self.public:
            self._decrement_reviewer_counts()

        if draft is not None:
            # This will in turn save the review request, so we'll be done.
            try:
                changes = draft.publish(self,
                                        send_notification=False,
                                        user=user,
                                        validate_fields=validate_fields)
            except Exception:
                # The draft failed to publish, for one reason or another.
                # Check if we need to re-increment those counters we
                # previously decremented.
                if self.public:
                    self._increment_reviewer_counts()

                raise

            draft.delete()
        else:
            changes = None

        if not self.public and self.changedescs.count() == 0:
            # This is a brand new review request that we're publishing
            # for the first time. Set the creation timestamp to now.
            self.time_added = timezone.now()

        self.public = True
        self.save(update_counts=True, old_submitter=old_submitter)

        review_request_published.send(sender=self.__class__,
                                      user=user,
                                      review_request=self,
                                      trivial=trivial,
                                      changedesc=changes)
예제 #11
0
    def get_pending_reply(self, user):
        """Returns the pending reply owned by the specified user."""
        if user.is_authenticated():
            return get_object_or_none(Review,
                                      user=user,
                                      public=False,
                                      base_reply_to=self)

        return None
예제 #12
0
    def get_pending_reply(self, user):
        """Returns the pending reply owned by the specified user."""
        if user.is_authenticated():
            return get_object_or_none(Review,
                                      user=user,
                                      public=False,
                                      base_reply_to=self)

        return None
예제 #13
0
    def close(self, type, user=None, description=None, rich_text=False):
        """Closes the review request.

        The type must be one of SUBMITTED or DISCARDED.
        """
        if (user and not self.is_mutable_by(user) and
            not user.has_perm("reviews.can_change_status", self.local_site)):
            raise PermissionError

        if type not in [self.SUBMITTED, self.DISCARDED]:
            raise AttributeError("%s is not a valid close type" % type)

        draft = get_object_or_none(self.draft)

        if self.status != type:
            if (draft is not None and
                not self.public and type == self.DISCARDED):
                # Copy over the draft information if this is a private discard.
                draft.copy_fields_to_request(self)

            # TODO: Use the user's default for rich_text.
            changedesc = ChangeDescription(public=True,
                                           text=description or "",
                                           rich_text=rich_text or False)

            status_field = get_review_request_field('status')(self)
            status_field.record_change_entry(changedesc, self.status, type)
            changedesc.save()

            self.changedescs.add(changedesc)

            if type == self.SUBMITTED:
                if not self.public:
                    raise PublishError("The draft must be public first.")
            else:
                self.commit_id = None

            self.status = type
            self.save(update_counts=True)

            review_request_closed.send(sender=self.__class__, user=user,
                                       review_request=self,
                                       type=type)
        else:
            # Update submission description.
            changedesc = self.changedescs.filter(public=True).latest()
            changedesc.timestamp = timezone.now()
            changedesc.text = description or ""
            changedesc.rich_text = rich_text
            changedesc.save()

            # Needed to renew last-update.
            self.save()

        # Delete the associated draft review request.
        if draft is not None:
            draft.delete()
예제 #14
0
    def close(self, type, user=None, description=None, rich_text=False):
        """Closes the review request.

        The type must be one of SUBMITTED or DISCARDED.
        """
        if (user and not self.is_mutable_by(user) and
            not user.has_perm("reviews.can_change_status", self.local_site)):
            raise PermissionError

        if type not in [self.SUBMITTED, self.DISCARDED]:
            raise AttributeError("%s is not a valid close type" % type)

        draft = get_object_or_none(self.draft)

        if self.status != type:
            if (draft is not None and
                not self.public and type == self.DISCARDED):
                # Copy over the draft information if this is a private discard.
                draft.copy_fields_to_request(self)

            # TODO: Use the user's default for rich_text.
            changedesc = ChangeDescription(public=True,
                                           text=description or "",
                                           rich_text=rich_text or False)

            status_field = get_review_request_field('status')(self)
            status_field.record_change_entry(changedesc, self.status, type)
            changedesc.save()

            self.changedescs.add(changedesc)

            if type == self.SUBMITTED:
                if not self.public:
                    raise PublishError("The draft must be public first.")
            else:
                self.commit_id = None

            self.status = type
            self.save(update_counts=True)

            review_request_closed.send(sender=self.__class__, user=user,
                                       review_request=self,
                                       type=type)
        else:
            # Update submission description.
            changedesc = self.changedescs.filter(public=True).latest()
            changedesc.timestamp = timezone.now()
            changedesc.text = description or ""
            changedesc.rich_text = rich_text
            changedesc.save()

            # Needed to renew last-update.
            self.save()

        # Delete the associated draft review request.
        if draft is not None:
            draft.delete()
예제 #15
0
    def publish(self, user):
        """Publishes the current draft attached to this review request.

        The review request will be mark as public, and signals will be
        emitted for any listeners.
        """
        from reviewboard.accounts.models import LocalSiteProfile

        if not self.is_mutable_by(user):
            raise PermissionError

        draft = get_object_or_none(self.draft)

        review_request_publishing.send(sender=self.__class__, user=user,
                                       review_request_draft=draft)

        # Decrement the counts on everything. we lose them.
        # We'll increment the resulting set during ReviewRequest.save.
        # This should be done before the draft is published.
        # Once the draft is published, the target people
        # and groups will be updated with new values.
        # Decrement should not happen while publishing
        # a new request or a discarded request
        if self.public:
            Group.incoming_request_count.decrement(self.target_groups.all())
            LocalSiteProfile.direct_incoming_request_count.decrement(
                LocalSiteProfile.objects.filter(
                    user__in=self.target_people.all(),
                    local_site=self.local_site))
            LocalSiteProfile.total_incoming_request_count.decrement(
                LocalSiteProfile.objects.filter(
                    Q(local_site=self.local_site) &
                    Q(Q(user__review_groups__in=self.target_groups.all()) |
                      Q(user__in=self.target_people.all()))))
            LocalSiteProfile.starred_public_request_count.decrement(
                LocalSiteProfile.objects.filter(
                    profile__starred_review_requests=self,
                    local_site=self.local_site))

        if draft is not None:
            # This will in turn save the review request, so we'll be done.
            changes = draft.publish(self, send_notification=False)
            draft.delete()
        else:
            changes = None

        if not self.public and self.changedescs.count() == 0:
            # This is a brand new review request that we're publishing
            # for the first time. Set the creation timestamp to now.
            self.time_added = timezone.now()

        self.public = True
        self.save(update_counts=True)

        review_request_published.send(sender=self.__class__, user=user,
                                      review_request=self,
                                      changedesc=changes)
예제 #16
0
    def post(self, request):
        """Save the extension configuration.

        Args:
            request (django.http.HttpRequest):
                The HTTP request, including POSTed data.

        Returns:
            django.http.HttpResponse:
            The response. The body of the response is a JSON-encoded blob which
            indicates success or failure, and in the success case, includes the
            the current configuration.
        """
        if not request.user.is_superuser:
            return HttpResponseForbidden()

        extension = ReviewBotExtension.instance
        should_save = False
        new_user = request.POST.get('reviewbot_user')

        if new_user:
            try:
                user = User.objects.get(pk=new_user)
            except User.DoesNotExist:
                # TODO: return which field was invalid
                return HttpResponseBadRequest(json.dumps({
                    'result':
                    'error',
                    'field':
                    'user',
                    'error':
                    'The specified user does not exist.',
                }),
                                              content_type='application/json')

            extension.settings['user'] = user.pk
            should_save = True
        else:
            user = get_object_or_none(User, pk=extension.settings.get('user'))

        if 'reviewbot_broker_url' in request.POST:
            broker_url = request.POST['reviewbot_broker_url']
            extension.settings['broker_url'] = broker_url
            should_save = True
        else:
            broker_url = extension.settings.get('broker_url', '')

        if should_save:
            extension.settings.save()

        return HttpResponse(json.dumps({
            'result': 'success',
            'broker_url': broker_url,
            'user': _serialize_user(request, user),
        }),
                            content_type='application/json')
예제 #17
0
    def post(self, request):
        """Save the extension configuration.

        Args:
            request (django.http.HttpRequest):
                The HTTP request, including POSTed data.

        Returns:
            django.http.HttpResponse:
            The response. The body of the response is a JSON-encoded blob which
            indicates success or failure, and in the success case, includes the
            the current configuration.
        """
        if not request.user.is_superuser:
            return HttpResponseForbidden()

        extension = ReviewBotExtension.instance
        should_save = False
        new_user = request.POST.get('reviewbot_user')

        if new_user:
            try:
                user = User.objects.get(pk=new_user)
            except User.DoesNotExist:
                # TODO: return which field was invalid
                return HttpResponseBadRequest(
                    json.dumps({
                        'result': 'error',
                        'field': 'user',
                        'error': 'The specified user does not exist.',
                    }),
                    content_type='application/json')

            extension.settings['user'] = user.pk
            should_save = True
        else:
            user = get_object_or_none(User, pk=extension.settings.get('user'))

        if 'reviewbot_broker_url' in request.POST:
            broker_url = request.POST['reviewbot_broker_url']
            extension.settings['broker_url'] = broker_url
            should_save = True
        else:
            broker_url = extension.settings.get('broker_url', '')

        if should_save:
            extension.settings.save()

        return HttpResponse(
            json.dumps({
                'result': 'success',
                'broker_url': broker_url,
                'user': _serialize_user(request, user),
            }),
            content_type='application/json')
예제 #18
0
    def publish(self, user, trivial=False):
        """Publishes the current draft attached to this review request.

        The review request will be mark as public, and signals will be
        emitted for any listeners.
        """
        if not self.is_mutable_by(user):
            raise PermissionError

        draft = get_object_or_none(self.draft)
        old_submitter = self.submitter

        review_request_publishing.send(sender=self.__class__, user=user,
                                       review_request_draft=draft)

        # Decrement the counts on everything. we lose them.
        # We'll increment the resulting set during ReviewRequest.save.
        # This should be done before the draft is published.
        # Once the draft is published, the target people
        # and groups will be updated with new values.
        # Decrement should not happen while publishing
        # a new request or a discarded request
        if self.public:
            self._decrement_reviewer_counts()

        if draft is not None:
            # This will in turn save the review request, so we'll be done.
            try:
                changes = draft.publish(self, send_notification=False,
                                        user=user)
            except Exception:
                # The draft failed to publish, for one reason or another.
                # Check if we need to re-increment those counters we
                # previously decremented.
                if self.public:
                    self._increment_reviewer_counts()

                raise

            draft.delete()
        else:
            changes = None

        if not self.public and self.changedescs.count() == 0:
            # This is a brand new review request that we're publishing
            # for the first time. Set the creation timestamp to now.
            self.time_added = timezone.now()

        self.public = True
        self.save(update_counts=True, old_submitter=old_submitter)

        review_request_published.send(sender=self.__class__, user=user,
                                      review_request=self, trivial=trivial,
                                      changedesc=changes)
예제 #19
0
    def get_user(self, user_id):
        """Return an existing user given a numeric user ID.

        Args:
            user_id (int):
                The ID of the user to retrieve.

        Returns:
            django.contrib.auth.models.User:
            The resulting user, or ``None`` if one could not be found.
        """
        return get_object_or_none(User, pk=user_id)
예제 #20
0
    def publish(self, user):
        """Publishes the current draft attached to this review request.

        The review request will be mark as public, and signals will be
        emitted for any listeners.
        """
        if not self.is_mutable_by(user):
            raise PermissionError

        draft = get_object_or_none(self.draft)

        review_request_publishing.send(sender=self.__class__, user=user,
                                       review_request_draft=draft)

        # Decrement the counts on everything. we lose them.
        # We'll increment the resulting set during ReviewRequest.save.
        # This should be done before the draft is published.
        # Once the draft is published, the target people
        # and groups will be updated with new values.
        # Decrement should not happen while publishing
        # a new request or a discarded request
        if self.public:
            self._decrement_reviewer_counts()

        if draft is not None:
            # This will in turn save the review request, so we'll be done.
            changes = draft.publish(self, send_notification=False)
            draft.delete()
        else:
            changes = None

        if not self.public and self.changedescs.count() == 0:
            # This is a brand new review request that we're publishing
            # for the first time. Set the creation timestamp to now.
            self.time_added = timezone.now()

            # make a call to jira api to update status for the new request
            self.send_jira_transition('start')

        self.public = True
        self.save(update_counts=True)



        review_request_published.send(sender=self.__class__, user=user,
                                      review_request=self,
                                      changedesc=changes)
예제 #21
0
 def save(self):
     if not self.errors:
         try:
             user = auth.models.User.objects.create_user(
                 self.cleaned_data['username'], self.cleaned_data['email'],
                 self.cleaned_data['password1'])
             user.first_name = self.cleaned_data['first_name']
             user.last_name = self.cleaned_data['last_name']
             user.save()
             return user
         except:
             # We check for duplicate users here instead of clean, since it's
             # possible that two users could race for a name.
             if get_object_or_none(User,
                                   username=self.cleaned_data['username']):
                 self.errors['username'] = forms.util.ErrorList(
                     [_('Sorry, this username is taken.')])
             else:
                 raise
예제 #22
0
    def _check(*args, **kwargs):
        request = _find_httprequest(args)
        local_site_name = kwargs.get('local_site_name', None)
        webapi_token = getattr(request, '_webapi_token', None)

        if webapi_token:
            restrict_to_local_site = request._webapi_token.local_site_id
        else:
            restrict_to_local_site = None

        if local_site_name:
            local_site = get_object_or_none(LocalSite, name=local_site_name)

            if not local_site:
                return DOES_NOT_EXIST
            elif not local_site.is_accessible_by(request.user):
                if request.user.is_authenticated():
                    logging.warning('%s %s: user %s does not have access to '
                                    'local site "%s".',
                                    request.method, request.path_info,
                                    request.user.username, local_site_name)
                    return PERMISSION_DENIED
                else:
                    return NOT_LOGGED_IN
            elif (restrict_to_local_site and
                  restrict_to_local_site != local_site.pk):
                logging.warning('%s %s: API token for user %s does not have '
                                'access to local site "%s".',
                                request.method, request.path_info,
                                request.user.username, local_site_name)
                return PERMISSION_DENIED

            kwargs['local_site'] = local_site
        elif restrict_to_local_site is not None:
            logging.warning('%s %s: API token for user %s is limited to a '
                            'local site but the request was for the root.',
                            request.method, request.path_info,
                            request.user.username)
            return PERMISSION_DENIED
        else:
            kwargs['local_site'] = None

        return view_func(*args, **kwargs)
예제 #23
0
    def __get_oauth2_token_for_request(self, request):
        """Return the OAuth2 token for the request.

        Args:
            request (django.http.HttpRequest):
                The current HTTP request.

        Returns:
            tuple:
            A 2-tuple of the following:

            * the access token, if it exists
              (:py:class:`~oauth2_provider.models.AccessToken`); and
            * whether or not the token was retrieved from the session
              (:py:class:`bool`).
        """
        try:
            from oauth2_provider.models import AccessToken
        except ImportError:
            raise ImproperlyConfigured(
                'WebAPIOAuth2TokenAuthBackend requires django-oauth-toolkit'
                '>=0.9,<0.9.999.'
            )

        token = getattr(request, '_oauth2_token', None)
        from_session = False

        if not token:
            token_pk = request.session.get('oauth2_token_id')

            if token_pk:
                from_session = True
                token = get_object_or_none(AccessToken, pk=token_pk)

                if not token or token.is_expired():
                    # Either the token no longer exists or has expired, so we
                    # must log the user out.
                    auth.logout(request)

                request._oauth2_token = token

        return token, from_session
예제 #24
0
파일: forms.py 프로젝트: Harikanrh/djblets
 def save(self):
     if not self.errors:
         try:
             user = auth.models.User.objects.create_user(
                 self.cleaned_data['username'],
                 self.cleaned_data['email'],
                 self.cleaned_data['password1'])
             user.first_name = self.cleaned_data['first_name']
             user.last_name = self.cleaned_data['last_name']
             user.save()
             return user
         except:
             # We check for duplicate users here instead of clean, since it's
             # possible that two users could race for a name.
             if get_object_or_none(User,
                                   username=self.cleaned_data['username']):
                 self.errors['username'] = forms.util.ErrorList(
                     [_('Sorry, this username is taken.')])
             else:
                 raise
예제 #25
0
    def _get_stored_consent_for_user(self, user):
        """Return stored consent data for a user.

        This will look up the consent data and cache it on the user, speeding
        up subsequent calls.

        Args:
            user (django.contrib.auth.models.User):
                The user to retrieve and cache stored consent data for.

        Returns:
            djblets.privacy.models.StoredConsentData:
            The stored consent data for the user, or ``None`` if there's no
            existing data on record.
        """
        if not hasattr(user, '_djblets_stored_consent'):
            user._djblets_stored_consent = \
                get_object_or_none(self.model, user=user)

        return user._djblets_stored_consent
예제 #26
0
    def __get_oauth2_token_for_request(self, request):
        """Return the OAuth2 token for the request.

        Args:
            request (django.http.HttpRequest):
                The current HTTP request.

        Returns:
            tuple:
            A 2-tuple of the following:

            * the access token, if it exists
              (:py:class:`~oauth2_provider.models.AccessToken`); and
            * whether or not the token was retrieved from the session
              (:py:class:`bool`).
        """
        try:
            from oauth2_provider.models import AccessToken
        except ImportError:
            raise ImproperlyConfigured(
                'WebAPIOAuth2TokenAuthBackend requires django-oauth-toolkit'
                '>=0.9,<0.9.999.')

        token = getattr(request, '_oauth2_token', None)
        from_session = False

        if not token:
            token_pk = request.session.get('oauth2_token_id')

            if token_pk:
                from_session = True
                token = get_object_or_none(AccessToken, pk=token_pk)

                if not token or token.is_expired():
                    # Either the token no longer exists or has expired, so we
                    # must log the user out.
                    auth.logout(request)

                request._oauth2_token = token

        return token, from_session
예제 #27
0
    def get(self, request):
        """Render and return the admin page.

        Args:
            request (django.http.HttpRequest):
                The HTTP request.

        Returns:
            django.http.HttpResponse:
            The response.
        """
        if not request.user.is_superuser:
            # TODO: Once we move to Django 1.9+, we can switch to the new
            # access mixin methods instead of testing this ourselves. Here and
            # below in the other views in this file.
            return HttpResponseForbidden()

        extension = ReviewBotExtension.instance
        user = get_object_or_none(User, pk=extension.settings.get('user'))

        return render(request, self.template_name, {
            'extension': extension,
            'reviewbot_user': user,
        })
예제 #28
0
    def get(self, request):
        """Render and return the admin page.

        Args:
            request (django.http.HttpRequest):
                The HTTP request.

        Returns:
            django.http.HttpResponse:
            The response.
        """
        if not request.user.is_superuser:
            # TODO: Once we move to Django 1.9+, we can switch to the new
            # access mixin methods instead of testing this ourselves. Here and
            # below in the other views in this file.
            return HttpResponseForbidden()

        extension = ReviewBotExtension.instance
        user = get_object_or_none(User, pk=extension.settings.get('user'))

        return render(request, self.template_name, {
            'extension': extension,
            'reviewbot_user': user,
        })
예제 #29
0
    def __init__(self, data=None, initial={}, request=None, *args, **kwargs):
        """Initialize the form.

        Args:
            data (dict, optional):
                Posted data for the form.

            initial (dict, optional):
                Initial data for the form.

            request (django.http.HttpRequest, optional):
                The HTTP request from the client. This is used for logging
                of access errors, and will be passed to the underlying form
                if :py:attr:`form_needs_request` is ``True``.

            *args (tuple):
                Positional arguments to pass to the parent form.

            **kwargs (dict):
                Keyword arguments to pass to the parent form.

        Keyword Args:
            limit_to_local_site (reviewboard.site.models.LocalSite, optional):
                A specific Local Site to bind the form to.

            request (django.http.HttpRequest, optional):
                The HTTP request from the client.

        Raises:
            ValueError:
                An object instance was provided to the form that isn't
                compatible with the
                :py:class:`~reviewboard.site.models.LocalSite` provided in
                ``limit_to_local_site``.
        """
        local_site = kwargs.pop('limit_to_local_site', None)

        if self.form_needs_request:
            kwargs['request'] = request

        self.limited_to_local_site = local_site

        local_site_field_name = self.local_site_field_name

        if local_site is None:
            if data and data.get(local_site_field_name):
                local_site = get_object_or_none(LocalSite,
                                                pk=data[local_site_field_name])
            elif initial and initial.get(local_site_field_name):
                local_site = initial[local_site_field_name]

        if data is not None and local_site:
            # Always use the assigned Local Site in the model data. We
            # don't want to allow this to ever be overridden. We'll delete
            # here and then assign after the constructor does its thing.
            data = data.copy()
            data[local_site_field_name] = local_site.pk

        self.cur_local_site = local_site

        super(LocalSiteAwareModelFormMixin, self).__init__(data=data,
                                                           initial=initial,
                                                           *args,
                                                           **kwargs)

        # Prepare to patch up some fields. We have a few special types we'll
        # be dealing with.
        self._conditions_fields = []
        self._related_obj_fields = []
        self._queryset_fields = []

        for field_name, field in six.iteritems(self.fields):
            if isinstance(field.widget, RelatedObjectWidget):
                self._related_obj_fields.append(field)
            elif isinstance(field, ConditionsField):
                self._conditions_fields.append(field)
                field.choice_kwargs['request'] = request

            if getattr(field, 'queryset', None) is not None:
                self._queryset_fields.append(field)

        if self.limited_to_local_site is not None:
            if self.instance is not None:
                if self.instance.pk is None:
                    # This is a new instance, so force its Local Site now.
                    self.instance.local_site = local_site
                elif self.instance.local_site != local_site:
                    # Something went very wrong, and an instance is now in our
                    # form that isn't part of this Local Site. Log this and
                    # bail out now.
                    logger.error(
                        'Attempted to pass instance %r with '
                        'LocalSite "%s" to form %r. Only LocalSite '
                        '"%s" is permitted.',
                        self.instance,
                        self.instance.local_site,
                        self.__class__,
                        local_site,
                        request=request)

                    raise ValueError(
                        _('The provided instance is not associated with a '
                          'LocalSite compatible with this form. Please '
                          'contact support.'))

            # We never want to show a "Local Site" field, so let's get rid of
            # it.
            del self.fields[local_site_field_name]

            # Go through the fields and widgets and start limiting querysets
            # and other choices.
            local_site_name = local_site.name

            for field in self._related_obj_fields:
                field.widget.local_site_name = local_site_name

            for field in self._conditions_fields:
                field.choice_kwargs['local_site'] = local_site

            for field in self._queryset_fields:
                self._patch_field_local_site_queryset(field, local_site)
예제 #30
0
 def can_publish(self):
     return not self.public or get_object_or_none(self.draft) is not None
예제 #31
0
 def get_user(self, user_id):
     return get_object_or_none(User, pk=user_id)
예제 #32
0
    def _on_review_request_published(self, user, review_request, changedesc,
                                     **kwargs):
        """Handler for when review requests are published.

        This will send a notification to any configured channels when
        a review request is published.

        Args:
            user (django.contrib.auth.models.User):
                The user who published the review request.

            review_request (reviewboard.reviews.models.ReviewRequest):
                The review request that was published.

            changedesc (reviewboard.changedescs.models.ChangeDescription):
                The change description for the update, if any.

            **kwargs (dict):
                Additional keyword arguments passed to the handler.
        """
        user_link = self.get_user_text_link(user, review_request.local_site)
        fields = []

        if changedesc:
            fallback_text = 'New update from %s' % user_displayname(user)
            pre_text = 'New update from %s' % user_link

            # This might be empty, which is fine. We won't show an update
            # at that point.
            body = changedesc.text
        else:
            fallback_text = 'New review request from %s' % \
                user_displayname(user)
            pre_text = 'New review request from %s' % user_link
            body = None

            fields.append({
                'short': False,
                'title': 'Description',
                'value': review_request.description,
            })

        # Link to the diff in the update, if any.
        diffset = review_request.get_latest_diffset()

        if diffset:
            diff_url = local_site_reverse(
                'view-diff-revision',
                local_site=review_request.local_site,
                kwargs={
                    'review_request_id': review_request.display_id,
                    'revision': diffset.revision,
                })

            fields.append({
                'short': True,
                'title': 'Diff',
                'value': self.format_link(diff_url,
                                          'Revision %s' % diffset.revision),
            })

        if review_request.repository:
            fields.append({
                'short': True,
                'title': 'Repository',
                'value': review_request.repository.name,
            })

        if review_request.branch:
            fields.append({
                'short': True,
                'title': 'Branch',
                'value': review_request.branch,
            })

        # See if there are any new interesting file attachments to show.
        # These will only show up if the file is accessible.
        attachment = None

        if changedesc:
            # Only show new files added in this change.
            try:
                new_files = changedesc.fields_changed['files']['added']
            except KeyError:
                new_files = []

            for file_info in new_files:
                if (len(file_info) >= 3 and
                    file_info[1].endswith(self.VALID_IMAGE_URL_EXTS)):
                    # This one wins. Show it.
                    attachment = get_object_or_none(
                        review_request.file_attachments,
                        pk=file_info[2])
                    break
        else:
            # This is a new review request, so show the first valid image
            # we can find.
            for attachment in review_request.file_attachments.all():
                if attachment.filename.endswith(self.VALID_IMAGE_URL_EXTS):
                    # This one wins. Show it.
                    break
            else:
                attachment = None

        if attachment:
            image_url = attachment.get_absolute_url()
        else:
            image_url = None

        # Find any trophies we may want to show in the update.
        trophies = Trophy.objects.get_trophies(review_request)
        trophy_url = None

        if trophies:
            # For now, due to the need to look up resources from a stable
            # location, we're only supporting certain trophies. First one
            # wins.
            for trophy in trophies:
                try:
                    trophy_url = self.TROPHY_URLS[trophy.category]
                    break
                except KeyError:
                    pass

        self.notify_review_request(review_request,
                                   fallback_text=fallback_text,
                                   body=body,
                                   pre_text=pre_text,
                                   fields=fields,
                                   thumb_url=trophy_url,
                                   image_url=image_url,
                                   local_site=review_request.local_site,
                                   event_name='review_request_published')
예제 #33
0
 def get_user(self, user_id):
     return get_object_or_none(User, pk=user_id)
예제 #34
0
 def get_user(self, user_id):
     """Get an existing user, or None if it does not exist."""
     return get_object_or_none(User, pk=user_id)
예제 #35
0
    def _on_review_request_published(self, user, review_request, changedesc,
                                     **kwargs):
        """Handler for when review requests are published.

        This will send a notification to any configured Slack channels when
        a review request is published.

        Args:
            user (django.contrib.auth.models.User):
                The user who published the review request.

            review_request (reviewboard.reviews.models.ReviewRequest):
                The review request that was published.

            changedesc (reviewboard.changedescs.models.ChangeDescription):
                The change description for the update, if any.

            **kwargs (dict):
                Additional keyword arguments passed to the handler.
        """
        user_link = self.get_user_text_link(user, review_request.local_site)
        fields = []

        if changedesc:
            fallback_text = 'New update from %s' % user_displayname(user)
            pre_text = 'New update from %s' % user_link

            # This might be empty, which is fine. We won't show an update
            # at that point.
            body = changedesc.text
        else:
            fallback_text = 'New review request from %s' % \
                user_displayname(user)
            pre_text = 'New review request from %s' % user_link
            body = None

            fields.append({
                'short': False,
                'title': 'Description',
                'value': review_request.description,
            })

        # Link to the diff in the update, if any.
        diffset = review_request.get_latest_diffset()

        if diffset:
            diff_url = local_site_reverse(
                'view-diff-revision',
                local_site=review_request.local_site,
                kwargs={
                    'review_request_id': review_request.display_id,
                    'revision': diffset.revision,
                })

            fields.append({
                'short': True,
                'title': 'Diff',
                'value': self.format_link(diff_url,
                                          'Revision %s' % diffset.revision),
            })

        if review_request.repository:
            fields.append({
                'short': True,
                'title': 'Repository',
                'value': review_request.repository.name,
            })

        if review_request.branch:
            fields.append({
                'short': True,
                'title': 'Branch',
                'value': review_request.branch,
            })

        # See if there are any new interesting file attachments to show.
        # These will only show up if the file is accessible to Slack.
        attachment = None

        if changedesc:
            # Only show new files added in this change.
            try:
                new_files = changedesc.fields_changed['files']['added']
            except KeyError:
                new_files = []

            for file_info in new_files:
                if (len(file_info) >= 3 and
                    file_info[1].endswith(self.VALID_IMAGE_URL_EXTS)):
                    # This one wins. Show it.
                    attachment = get_object_or_none(
                        review_request.file_attachments,
                        pk=file_info[2])
                    break
        else:
            # This is a new review request, so show the first valid image
            # we can find.
            for attachment in review_request.file_attachments.all():
                if attachment.filename.endswith(self.VALID_IMAGE_URL_EXTS):
                    # This one wins. Show it.
                    break
            else:
                attachment = None

        if attachment:
            image_url = attachment.get_absolute_url()
        else:
            image_url = None

        # Find any trophies we may want to show in the update.
        trophies = Trophy.objects.get_trophies(review_request)
        trophy_url = None

        if trophies:
            # For now, due to the need to look up resources from a stable
            # location, we're only supporting certain trophies. First one
            # wins.
            for trophy in trophies:
                try:
                    trophy_url = self.TROPHY_URLS[trophy.category]
                    break
                except KeyError:
                    pass

        self.notify_review_request(review_request,
                                   fallback_text=fallback_text,
                                   body=body,
                                   pre_text=pre_text,
                                   fields=fields,
                                   thumb_url=trophy_url,
                                   image_url=image_url,
                                   local_site=review_request.local_site,
                                   event_name='review_request_published')
예제 #36
0
 def check_delete_result(self, user, app_pk):
     self.assertIsNone(get_object_or_none(Application, pk=app_pk))
예제 #37
0
    def close(self,
              close_type=None,
              user=None,
              description=None,
              rich_text=False,
              **kwargs):
        """Closes the review request.

        Args:
            close_type (unicode):
                How the close occurs. This should be one of
                :py:attr:`SUBMITTED` or :py:attr:`DISCARDED`.

            user (django.contrib.auth.models.User):
                The user who is closing the review request.

            description (unicode):
                An optional description that indicates why the review request
                was closed.

            rich_text (bool):
                Indicates whether or not that the description is rich text.

        Raises:
            ValueError:
                The provided close type is not a valid value.

            PermissionError:
                The user does not have permission to close the review request.

            TypeError:
                Keyword arguments were supplied to the function.

        .. versionchanged:: 3.0
           The ``type`` argument is deprecated: ``close_type`` should be used
           instead.

           This method raises :py:exc:`ValueError` instead of
           :py:exc:`AttributeError` when the ``close_type`` has an incorrect
           value.
        """
        if close_type is None:
            try:
                close_type = kwargs.pop('type')
            except KeyError:
                raise AttributeError('close_type must be provided')

            warnings.warn(
                'The "type" argument was deprecated in Review Board 3.0 and '
                'will be removed in a future version. Use "close_type" '
                'instead.')

        if kwargs:
            raise TypeError('close() does not accept keyword arguments.')

        if (user and not self.is_mutable_by(user) and not user.has_perm(
                "reviews.can_change_status", self.local_site)):
            raise PermissionError

        if close_type not in [self.SUBMITTED, self.DISCARDED]:
            raise ValueError("%s is not a valid close type" % type)

        review_request_closing.send(sender=type(self),
                                    user=user,
                                    review_request=self,
                                    close_type=close_type,
                                    type=deprecated_signal_argument(
                                        signal_name='review_request_closing',
                                        old_name='type',
                                        new_name='close_type',
                                        value=close_type),
                                    description=description,
                                    rich_text=rich_text)

        draft = get_object_or_none(self.draft)

        if self.status != close_type:
            if (draft is not None and not self.public
                    and close_type == self.DISCARDED):
                # Copy over the draft information if this is a private discard.
                draft.copy_fields_to_request(self)

            # TODO: Use the user's default for rich_text.
            changedesc = ChangeDescription(public=True,
                                           text=description or "",
                                           rich_text=rich_text or False,
                                           user=user or self.submitter)

            status_field = get_review_request_field('status')(self)
            status_field.record_change_entry(changedesc, self.status,
                                             close_type)
            changedesc.save()

            self.changedescs.add(changedesc)

            if close_type == self.SUBMITTED:
                if not self.public:
                    raise PublishError("The draft must be public first.")
            else:
                self.commit_id = None

            self.status = close_type
            self.save(update_counts=True)

            review_request_closed.send(sender=type(self),
                                       user=user,
                                       review_request=self,
                                       close_type=close_type,
                                       type=deprecated_signal_argument(
                                           signal_name='review_request_closed',
                                           old_name='type',
                                           new_name='close_type',
                                           value=close_type),
                                       description=description,
                                       rich_text=rich_text)
        else:
            # Update submission description.
            changedesc = self.changedescs.filter(public=True).latest()
            changedesc.timestamp = timezone.now()
            changedesc.text = description or ""
            changedesc.rich_text = rich_text
            changedesc.save()

            # Needed to renew last-update.
            self.save()

        # Delete the associated draft review request.
        if draft is not None:
            draft.delete()
예제 #38
0
 def check_delete_result(self, user, access_token_pk):
     self.assertIsNone(get_object_or_none(AccessToken, pk=access_token_pk))
예제 #39
0
 def check_delete_result(self, user, review_request_id):
     self.assertIsNone(get_object_or_none(ReviewRequest,
                                          pk=review_request_id))
예제 #40
0
 def check_delete_result(self, user, review_request_id):
     self.assertIsNone(
         get_object_or_none(ReviewRequest, pk=review_request_id))
예제 #41
0
 def check_delete_result(self, user, access_token_pk):
     self.assertIsNone(get_object_or_none(AccessToken, pk=access_token_pk))
예제 #42
0
    def _check(*args, **kwargs):
        request = _find_httprequest(args)
        local_site_name = kwargs.get('local_site_name', None)
        webapi_token = getattr(request, '_webapi_token', None)
        oauth_token = getattr(request, '_oauth2_token', None)

        if webapi_token:
            restrict_to_local_site = request._webapi_token.local_site_id
            token_type = 'API'
        elif oauth_token:
            restrict_to_local_site = oauth_token.application.local_site_id
            token_type = 'OAuth'
        else:
            restrict_to_local_site = None
            token_type = None

        if local_site_name:
            local_site = get_object_or_none(LocalSite, name=local_site_name)

            if not local_site:
                return DOES_NOT_EXIST
            elif not local_site.is_accessible_by(request.user):
                if request.user.is_authenticated():
                    logging.warning(
                        'User does not have access to local site.',
                        request=request,
                    )
                    return PERMISSION_DENIED
                else:
                    return NOT_LOGGED_IN
            elif oauth_token and not oauth_token.application.enabled:
                logging.warning(
                    'OAuth token using disabled application "%s" (%d).',
                    oauth_token.application.name,
                    oauth_token.application.pk,
                    request=request,
                )
                return PERMISSION_DENIED
            elif oauth_token and not restrict_to_local_site:
                # OAuth tokens for applications on the global site cannot be
                # used on a local site.
                logging.warning(
                    'OAuth token is for root, not local site.',
                    request=request,
                )
                return PERMISSION_DENIED
            elif (restrict_to_local_site and
                  restrict_to_local_site != local_site.pk):
                logging.warning(
                    '%s token does not have access to local site.',
                    token_type,
                    request=request,
                )
                return PERMISSION_DENIED

            kwargs['local_site'] = local_site
        elif restrict_to_local_site is not None:
            logging.warning(
                '%s token is limited to a local site but the request was for '
                'the root.',
                token_type,
                request=request,
            )
            return PERMISSION_DENIED
        else:
            kwargs['local_site'] = None

        return view_func(*args, **kwargs)
예제 #43
0
 def check_delete_result(self, user, token_id):
     self.assertIsNone(get_object_or_none(WebAPIToken, pk=token_id))
예제 #44
0
 def check_delete_result(self, user, group_name):
     self.assertIsNone(get_object_or_none(Group, name=group_name))
예제 #45
0
 def get_or_create_user(self, username, request):
     """Get an existing user, or create one if it does not exist."""
     return get_object_or_none(User, username=username)
예제 #46
0
    def close(self, close_type=None, user=None, description=None,
              rich_text=False, **kwargs):
        """Closes the review request.

        Args:
            close_type (unicode):
                How the close occurs. This should be one of
                :py:attr:`SUBMITTED` or :py:attr:`DISCARDED`.

            user (django.contrib.auth.models.User):
                The user who is closing the review request.

            description (unicode):
                An optional description that indicates why the review request
                was closed.

            rich_text (bool):
                Indicates whether or not that the description is rich text.

        Raises:
            ValueError:
                The provided close type is not a valid value.

            PermissionError:
                The user does not have permission to close the review request.

            TypeError:
                Keyword arguments were supplied to the function.

        .. versionchanged:: 3.0
           The ``type`` argument is deprecated: ``close_type`` should be used
           instead.

           This method raises :py:exc:`ValueError` instead of
           :py:exc:`AttributeError` when the ``close_type`` has an incorrect
           value.
        """
        if close_type is None:
            try:
                close_type = kwargs.pop('type')
            except KeyError:
                raise AttributeError('close_type must be provided')

            warnings.warn(
                'The "type" argument was deprecated in Review Board 3.0 and '
                'will be removed in a future version. Use "close_type" '
                'instead.'
            )

        if kwargs:
            raise TypeError('close() does not accept keyword arguments.')

        if (user and not self.is_mutable_by(user) and
            not user.has_perm("reviews.can_change_status", self.local_site)):
            raise PermissionError

        if close_type not in [self.SUBMITTED, self.DISCARDED]:
            raise ValueError("%s is not a valid close type" % type)

        review_request_closing.send(
            sender=type(self),
            user=user,
            review_request=self,
            close_type=close_type,
            type=deprecated_signal_argument(
                signal_name='review_request_closing',
                old_name='type',
                new_name='close_type',
                value=close_type),
            description=description,
            rich_text=rich_text)

        draft = get_object_or_none(self.draft)

        if self.status != close_type:
            if (draft is not None and
                not self.public and close_type == self.DISCARDED):
                # Copy over the draft information if this is a private discard.
                draft.copy_fields_to_request(self)

            # TODO: Use the user's default for rich_text.
            changedesc = ChangeDescription(public=True,
                                           text=description or "",
                                           rich_text=rich_text or False,
                                           user=user or self.submitter)

            status_field = get_review_request_field('status')(self)
            status_field.record_change_entry(changedesc, self.status,
                                             close_type)
            changedesc.save()

            self.changedescs.add(changedesc)

            if close_type == self.SUBMITTED:
                if not self.public:
                    raise PublishError("The draft must be public first.")
            else:
                self.commit_id = None

            self.status = close_type
            self.save(update_counts=True)

            review_request_closed.send(
                sender=type(self),
                user=user,
                review_request=self,
                close_type=close_type,
                type=deprecated_signal_argument(
                    signal_name='review_request_closed',
                    old_name='type',
                    new_name='close_type',
                    value=close_type),
                description=description,
                rich_text=rich_text)
        else:
            # Update submission description.
            changedesc = self.changedescs.filter(public=True).latest()
            changedesc.timestamp = timezone.now()
            changedesc.text = description or ""
            changedesc.rich_text = rich_text
            changedesc.save()

            # Needed to renew last-update.
            self.save()

        # Delete the associated draft review request.
        if draft is not None:
            draft.delete()
예제 #47
0
 def check_delete_result(self, user, group_name):
     self.assertIsNone(get_object_or_none(Group, name=group_name))
예제 #48
0
 def get_user(self, user_id):
     """Get an existing user, or None if it does not exist."""
     return get_object_or_none(User, pk=user_id)
예제 #49
0
 def check_delete_result(self, user, app_pk):
     self.assertIsNone(get_object_or_none(Application, pk=app_pk))
예제 #50
0
    def _check(*args, **kwargs):
        request = _find_httprequest(args)
        local_site_name = kwargs.get('local_site_name', None)
        webapi_token = getattr(request, '_webapi_token', None)
        oauth_token = getattr(request, '_oauth2_token', None)

        if webapi_token:
            restrict_to_local_site = request._webapi_token.local_site_id
            token_type = 'API'
        elif oauth_token:
            restrict_to_local_site = oauth_token.application.local_site_id
            token_type = 'OAuth'
        else:
            restrict_to_local_site = None
            token_type = None

        if local_site_name:
            local_site = get_object_or_none(LocalSite, name=local_site_name)

            if not local_site:
                return DOES_NOT_EXIST
            elif not local_site.is_accessible_by(request.user):
                if request.user.is_authenticated:
                    logger.warning(
                        'User does not have access to local site.',
                        request=request,
                    )
                    return PERMISSION_DENIED
                else:
                    return NOT_LOGGED_IN
            elif oauth_token and not oauth_token.application.enabled:
                logger.warning(
                    'OAuth token using disabled application "%s" (%d).',
                    oauth_token.application.name,
                    oauth_token.application.pk,
                    request=request,
                )
                return PERMISSION_DENIED
            elif oauth_token and not restrict_to_local_site:
                # OAuth tokens for applications on the global site cannot be
                # used on a local site.
                logger.warning(
                    'OAuth token is for root, not local site.',
                    request=request,
                )
                return PERMISSION_DENIED
            elif (restrict_to_local_site
                  and restrict_to_local_site != local_site.pk):
                logger.warning(
                    '%s token does not have access to local site.',
                    token_type,
                    request=request,
                )
                return PERMISSION_DENIED

            kwargs['local_site'] = local_site
        elif restrict_to_local_site is not None:
            logger.warning(
                '%s token is limited to a local site but the request was for '
                'the root.',
                token_type,
                request=request,
            )
            return PERMISSION_DENIED
        else:
            kwargs['local_site'] = None

        return view_func(*args, **kwargs)
예제 #51
0
 def user(self):
     """The configured user."""
     return get_object_or_none(User, pk=self.settings.get('user'))
예제 #52
0
 def get_or_create_user(self, username, request):
     """Get an existing user, or create one if it does not exist."""
     return get_object_or_none(User, username=username)
예제 #53
0
 def can_publish(self):
     return not self.public or get_object_or_none(self.draft) is not None
예제 #54
0
 def user(self):
     """The configured user."""
     return get_object_or_none(User, pk=self.settings.get('user'))
예제 #55
0
 def check_delete_result(self, user, token_id):
     self.assertIsNone(get_object_or_none(WebAPIToken, pk=token_id))
예제 #56
0
    def __init__(self, data=None, initial={}, *args, **kwargs):
        """Initialize the form.

        Args:
            data (dict, optional):
                Posted data for the form.

            initial (dict, optional):
                Initial data for the form.

            *args (tuple):
                Positional arguments to pass to the parent form.

            **kwargs (dict):
                Keyword arguments to pass to the parent form.

        Keyword Args:
            limit_to_local_site (reviewboard.site.models.LocalSite, optional):
                A specific Local Site to bind the form to.

            request (django.http.HttpRequest, optional):
                The HTTP request from the client.

        Raises:
            ValueError:
                An object instance was provided to the form that isn't
                compatible with the
                :py:class:`~reviewboard.site.models.LocalSite` provided in
                ``limit_to_local_site``.
        """
        local_site = kwargs.pop('limit_to_local_site', None)

        self.request = kwargs.pop('request', None)
        self.limited_to_local_site = local_site

        local_site_field_name = self.local_site_field_name

        if local_site is None:
            if data and data.get(local_site_field_name):
                local_site = get_object_or_none(LocalSite,
                                                pk=data[local_site_field_name])
            elif initial and initial.get(local_site_field_name):
                local_site = initial[local_site_field_name]

        if data is not None and local_site:
            # Always use the assigned Local Site in the model data. We
            # don't want to allow this to ever be overridden. We'll delete
            # here and then assign after the constructor does its thing.
            data = data.copy()
            data[local_site_field_name] = local_site.pk

        self.cur_local_site = local_site

        super(LocalSiteAwareModelFormMixin, self).__init__(data=data,
                                                           initial=initial,
                                                           *args,
                                                           **kwargs)

        # This is always set by BaseModelForm.
        assert self.instance is not None

        if self.limited_to_local_site is not None:
            if self.instance.pk is None:
                # This is a new instance, so force its Local Site now.
                self.instance.local_site = local_site
            elif self.instance.local_site != local_site:
                # Something went very wrong, and an instance is now in our
                # form that isn't part of this Local Site. Log this and bail
                # out now.
                logger.error(
                    'Attempted to pass instance %r with LocalSite '
                    '"%s" to form %r. Only LocalSite "%s" is '
                    'permitted.',
                    self.instance,
                    self.instance.local_site,
                    self.__class__,
                    local_site,
                    request=self.request)

                raise ValueError(
                    _('The provided instance is not associated with a '
                      'LocalSite compatible with this form. Please contact '
                      'support.'))

            # We never want to show a "Local Site" field, so let's get rid of
            # it.
            del self.fields[local_site_field_name]

            # Go through the fields and widgets and start limiting querysets
            # and other choices.
            local_site_name = local_site.name

            for field_name, field in six.iteritems(self.fields):
                if isinstance(field.widget, RelatedUserWidget):
                    field.widget.local_site_name = local_site_name

                self._patch_field_local_site_queryset(field, local_site)