Example #1
0
    def dispatch(self, request, *args, **kwargs):
        """Handle a HTTP request and dispatch to a handler.

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

            *args (tuple):
                Positional arguments passed to the handler.

            **kwargs (dict):
                Keyword arguments passed to the handler.

        Returns:
            django.http.HttpResponse:
            The resulting HTTP response from the handler.
        """
        handle_etag = request.method.upper() in ('GET', 'HEAD')

        if handle_etag:
            etag = self.get_etag_data(request, *args, **kwargs)

            if etag:
                etag = encode_etag(etag)

                if etag_if_none_match(request, etag):
                    return HttpResponseNotModified()

        response = super(ETagViewMixin, self).dispatch(request, *args,
                                                       **kwargs)

        if handle_etag and etag and 200 <= response.status_code < 300:
            set_etag(response, etag)

        return response
Example #2
0
    def test_generate_etag_with_encode_etag_true(self):
        """Testing WebAPIResource.generate_etag with encode_etag=True"""
        class TestObject(object):
            my_field = 'abc'

        request = RequestFactory().request()
        request.user = User()

        resource = WebAPIResource()
        obj = TestObject()

        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter('always')
            etag = resource.generate_etag(obj, ['my_field'],
                                          request,
                                          encode_etag=True)

        self.assertEqual(len(w), 1)
        self.assertIn('generate_etag is deprecated',
                      six.text_type(w[0].message))

        self.assertEqual(
            etag,
            encode_etag(':%s' %
                        repr(resource.serialize_object(obj, request=request))))
Example #3
0
    def encode_etag(self, request, etag, *args, **kwargs):
        """Encodes an ETag for usage in a header.

        This will take a precomputed ETag, augment it with additional
        information, encode it as a SHA1, and return it.
        """
        return encode_etag('%s:%s' % (request.user.username, etag))
Example #4
0
    def encode_etag(self, request, etag, *args, **kwargs):
        """Encodes an ETag for usage in a header.

        This will take a precomputed ETag, augment it with additional
        information, encode it as a SHA1, and return it.
        """
        return encode_etag('%s:%s' % (request.user.username, etag))
Example #5
0
    def dispatch(self, request, *args, **kwargs):
        """Handle a HTTP request and dispatch to a handler.

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

            *args (tuple):
                Positional arguments passed to the handler.

            **kwargs (dict):
                Keyword arguments passed to the handler.

        Returns:
            django.http.HttpResponse:
            The resulting HTTP response from the handler.
        """
        handle_etag = request.method.upper() in ('GET', 'HEAD')

        if handle_etag:
            etag = self.get_etag_data(request, *args, **kwargs)

            if etag:
                etag = encode_etag(etag)

                if etag_if_none_match(request, etag):
                    return HttpResponseNotModified()

        response = super(ETagViewMixin, self).dispatch(request, *args,
                                                       **kwargs)

        if handle_etag and etag and 200 <= response.status_code < 300:
            set_etag(response, etag)

        return response
Example #6
0
    def _test_without_matching_etag(self, method):
        class MyView(ETagViewMixin, View):
            def get_etag_data(self, *args, **kwargs):
                return 'test123'

            def head(self, *args, **kwargs):
                return HttpResponse()

        setattr(MyView, method.lower(), lambda *args, **kwargs: HttpResponse())

        view = MyView.as_view()
        request = RequestFactory().request(REQUEST_METHOD=method)
        request.META['HTTP_IF_NONE_MATCH'] = encode_etag('nope')

        response = view(request)
        self.assertNotIsInstance(response, HttpResponseNotModified)
        self.assertTrue(response.has_header('ETag'))
        self.assertEqual(response['ETag'], encode_etag('test123'))
Example #7
0
    def _test_without_matching_etag(self, method):
        class MyView(ETagViewMixin, View):
            def get_etag_data(self, *args, **kwargs):
                return 'test123'

            def head(self, *args, **kwargs):
                return HttpResponse()

        setattr(MyView, method.lower(), lambda *args, **kwargs: HttpResponse())

        view = MyView.as_view()
        request = RequestFactory().request(REQUEST_METHOD=method)
        request.META['HTTP_IF_NONE_MATCH'] = encode_etag('nope')

        response = view(request)
        self.assertNotIsInstance(response, HttpResponseNotModified)
        self.assertTrue(response.has_header('ETag'))
        self.assertEqual(response['ETag'], encode_etag('test123'))
Example #8
0
    def make_etag(self, renderer_settings):
        """Return an ETag identifying this render."""
        etag = '%s:%s:%s:%s' % (
            get_diff_renderer_class(),
            renderer_settings['collapse_all'],
            renderer_settings['highlighting'],
            settings.TEMPLATE_SERIAL)

        return encode_etag(etag)
Example #9
0
    def make_etag(self, renderer_settings, filediff_id, interdiffset_or_id=None, **kwargs):
        """Return an ETag identifying this render."""
        if interdiffset_or_id and isinstance(interdiffset_or_id, DiffSet):
            interdiffset_or_id = interdiffset_or_id.pk

        etag = "%s:%s:%s:%s:%s:%s" % (
            get_diff_renderer_class(),
            renderer_settings["collapse_all"],
            renderer_settings["highlighting"],
            filediff_id,
            interdiffset_or_id,
            settings.TEMPLATE_SERIAL,
        )

        return encode_etag(etag)
Example #10
0
    def _test_ignore_etag(self, method):
        class MyView(ETagViewMixin, View):
            def get_etag_data(self, *args, **kwargs):
                return 'test123'

        setattr(MyView, method.lower(),
                lambda *args, **kwargs: HttpResponse('hi there'))

        view = MyView.as_view()
        request = RequestFactory().request(REQUEST_METHOD=method)
        request.META['HTTP_IF_NONE_MATCH'] = encode_etag('test123')

        response = view(request)
        self.assertNotIsInstance(response, HttpResponseNotModified)
        self.assertEqual(response.content, b'hi there')
        self.assertFalse(response.has_header('ETag'))
Example #11
0
    def _test_ignore_etag(self, method):
        class MyView(ETagViewMixin, View):
            def get_etag_data(self, *args, **kwargs):
                return 'test123'

        setattr(MyView, method.lower(),
                lambda *args, **kwargs: HttpResponse('hi there'))

        view = MyView.as_view()
        request = RequestFactory().request(REQUEST_METHOD=method)
        request.META['HTTP_IF_NONE_MATCH'] = encode_etag('test123')

        response = view(request)
        self.assertNotIsInstance(response, HttpResponseNotModified)
        self.assertEqual(response.content, b'hi there')
        self.assertFalse(response.has_header('ETag'))
Example #12
0
    def make_etag(self,
                  renderer_settings,
                  filediff_id,
                  interfilediff_id=None,
                  **kwargs):
        """Return an ETag identifying this render.

        Args:
            renderer_settings (dict):
                The settings determining how to render this diff.

                The following keys are required: ``collapse_all`` and
                ``highlighting``.

                The following key is optional: ``show_deleted``.

            filediff_id (int):
                The ID of the
                :py:class:`~reviewboard.diffviewer.models.filediff.FileDiff`
                being rendered.

            interfilediff_id (int):
                The ID of the
                :py:class:`~reviewboard.diffviewer.models.filediff.FileDiff` on
                the other side of the diff revision, if viewing an interdiff.

            **kwargs (dict):
                Additional keyword arguments passed to the function.

        Return:
            unicode:
            The encoded ETag identifying this render.
        """
        etag = '%s:%s:%s:%s:%s:%s' % (
            get_diff_renderer_class(), renderer_settings['collapse_all'],
            renderer_settings['highlighting'], filediff_id, interfilediff_id,
            settings.TEMPLATE_SERIAL)

        show_deleted = renderer_settings.get('show_deleted')

        if show_deleted:
            etag += ':%s' % show_deleted

        return encode_etag(etag)
Example #13
0
    def make_etag(self, renderer_settings, filediff_id,
                  interfilediff_id=None, **kwargs):
        """Return an ETag identifying this render.

        Args:
            renderer_settings (dict):
                The settings determining how to render this diff.

                The following keys are required: ``collapse_all`` and
                ``highlighting``.

                The following key is optional: ``show_deleted``.

            filediff_id (int):
                The ID of the
                :py:class:`~reviewboard.diffviewer.models.FileDiff` being
                rendered.

            interfilediff_id (int):
                The ID of the
                :py:class:`~reviewboard.diffviewer.models.FileDiff` on the
                other side of the diff revision, if viewing an interdiff.

            **kwargs (dict):
                Additional keyword arguments passed to the function.

        Return:
            unicode:
            The encoded ETag identifying this render.
        """
        etag = '%s:%s:%s:%s:%s:%s' % (
            get_diff_renderer_class(),
            renderer_settings['collapse_all'],
            renderer_settings['highlighting'],
            filediff_id,
            interfilediff_id,
            settings.TEMPLATE_SERIAL)

        show_deleted = renderer_settings.get('show_deleted')

        if show_deleted:
            etag += ':%s' % show_deleted

        return encode_etag(etag)
Example #14
0
    def test_generate_etag_with_encode_etag_true(self):
        """Testing WebAPIResource.generate_etag with encode_etag=True"""
        class TestObject(object):
            my_field = 'abc'

        request = RequestFactory().request()
        request.user = User()

        resource = WebAPIResource()
        obj = TestObject()

        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter('always')
            etag = resource.generate_etag(obj, ['my_field'], request,
                                          encode_etag=True)

        self.assertEqual(len(w), 1)
        self.assertIn('generate_etag is deprecated',
                      six.text_type(w[0].message))

        self.assertEqual(
            etag,
            encode_etag(
                ':%s' % repr(resource.serialize_object(obj, request=request))))
    def get(self, request, *args, **kwargs):
        """Returns the last update made to the review request.

        This shows the type of update that was made, the user who made the
        update, and when the update was made. Clients can use this to inform
        the user that the review request was updated, or automatically update
        it in the background.

        This does not take into account changes to a draft review request, as
        that's generally not update information that the owner of the draft is
        interested in. Only public updates are represented.
        """
        try:
            review_request = \
                resources.review_request.get_object(request, *args, **kwargs)
        except ObjectDoesNotExist:
            return DOES_NOT_EXIST

        if not resources.review_request.has_access_permissions(
                request, review_request):
            return self.get_no_access_error(request)

        info = review_request.get_last_activity_info()
        timestamp = info['timestamp']
        updated_object = info['updated_object']
        changedesc = info['changedesc']

        etag = encode_etag('%s:%s' % (timestamp, updated_object.pk))

        if etag_if_none_match(request, etag):
            return HttpResponseNotModified()

        summary = None
        update_type = None

        if isinstance(updated_object, ReviewRequest):
            if updated_object.status == ReviewRequest.SUBMITTED:
                summary = _('Review request submitted')
            elif updated_object.status == ReviewRequest.DISCARDED:
                summary = _('Review request discarded')
            else:
                summary = _('Review request updated')

            update_type = 'review-request'
        elif isinstance(updated_object, DiffSet):
            summary = _('Diff updated')
            update_type = 'diff'
        elif isinstance(updated_object, Review):
            if updated_object.is_reply():
                summary = _('New reply')
                update_type = 'reply'
            else:
                summary = _('New review')
                update_type = 'review'
        else:
            # Should never be able to happen. The object will always at least
            # be a ReviewRequest.
            assert False

        if changedesc:
            user = changedesc.get_user(review_request)
        else:
            # There is no changedesc which means this review request hasn't
            # been changed since it was first published, so this change must
            # be due to the original submitter.
            user = review_request.submitter

        return 200, {
            self.item_result_key: {
                'timestamp': timestamp,
                'user': user,
                'summary': summary,
                'type': update_type,
            }
        }, {
            'ETag': etag,
        }
Example #16
0
    def get(self, request, *args, **kwargs):
        """Returns the last update made to the review request.

        This shows the type of update that was made, the user who made the
        update, and when the update was made. Clients can use this to inform
        the user that the review request was updated, or automatically update
        it in the background.

        This does not take into account changes to a draft review request, as
        that's generally not update information that the owner of the draft is
        interested in. Only public updates are represented.
        """
        try:
            review_request = \
                resources.review_request.get_object(request, *args, **kwargs)
        except ObjectDoesNotExist:
            return DOES_NOT_EXIST

        if not resources.review_request.has_access_permissions(
                request, review_request):
            return self.get_no_access_error(request)

        timestamp, updated_object = review_request.get_last_activity()

        etag = encode_etag('%s:%s' % (timestamp, updated_object.pk))

        if etag_if_none_match(request, etag):
            return HttpResponseNotModified()

        user = None
        summary = None
        update_type = None

        if isinstance(updated_object, ReviewRequest):
            user = updated_object.submitter

            if updated_object.status == ReviewRequest.SUBMITTED:
                summary = _("Review request submitted")
            elif updated_object.status == ReviewRequest.DISCARDED:
                summary = _("Review request discarded")
            else:
                summary = _("Review request updated")

            update_type = "review-request"
        elif isinstance(updated_object, DiffSet):
            summary = _("Diff updated")
            update_type = "diff"
        elif isinstance(updated_object, Review):
            user = updated_object.user

            if updated_object.is_reply():
                summary = _("New reply")
                update_type = "reply"
            else:
                summary = _("New review")
                update_type = "review"
        else:
            # Should never be able to happen. The object will always at least
            # be a ReviewRequest.
            assert False

        return 200, {
            self.item_result_key: {
                'timestamp': timestamp,
                'user': user,
                'summary': summary,
                'type': update_type,
            }
        }, {
            'ETag': etag,
        }
    def get(self, request, *args, **kwargs):
        """Returns the last update made to the review request.

        This shows the type of update that was made, the user who made the
        update, and when the update was made. Clients can use this to inform
        the user that the review request was updated, or automatically update
        it in the background.

        This does not take into account changes to a draft review request, as
        that's generally not update information that the owner of the draft is
        interested in. Only public updates are represented.
        """
        try:
            review_request = \
                resources.review_request.get_object(request, *args, **kwargs)
        except ObjectDoesNotExist:
            return DOES_NOT_EXIST

        if not resources.review_request.has_access_permissions(request,
                                                               review_request):
            return self.get_no_access_error(request)

        timestamp, updated_object = review_request.get_last_activity()

        etag = encode_etag('%s:%s' % (timestamp, updated_object.pk))

        if etag_if_none_match(request, etag):
            return HttpResponseNotModified()

        user = None
        summary = None
        update_type = None

        if isinstance(updated_object, ReviewRequest):
            user = updated_object.submitter

            if updated_object.status == ReviewRequest.SUBMITTED:
                summary = _("Review request submitted")
            elif updated_object.status == ReviewRequest.DISCARDED:
                summary = _("Review request discarded")
            else:
                summary = _("Review request updated")

            update_type = "review-request"
        elif isinstance(updated_object, DiffSet):
            summary = _("Diff updated")
            update_type = "diff"
        elif isinstance(updated_object, Review):
            user = updated_object.user

            if updated_object.is_reply():
                summary = _("New reply")
                update_type = "reply"
            else:
                summary = _("New review")
                update_type = "review"
        else:
            # Should never be able to happen. The object will always at least
            # be a ReviewRequest.
            assert False

        return 200, {
            self.item_result_key: {
                'timestamp': timestamp,
                'user': user,
                'summary': summary,
                'type': update_type,
            }
        }, {
            'ETag': etag,
        }
    def get(self, request, *args, **kwargs):
        """Returns the last update made to the review request.

        This shows the type of update that was made, the user who made the
        update, and when the update was made. Clients can use this to inform
        the user that the review request was updated, or automatically update
        it in the background.

        This does not take into account changes to a draft review request, as
        that's generally not update information that the owner of the draft is
        interested in. Only public updates are represented.
        """
        try:
            review_request = \
                resources.review_request.get_object(request, *args, **kwargs)
        except ObjectDoesNotExist:
            return DOES_NOT_EXIST

        if not resources.review_request.has_access_permissions(request,
                                                               review_request):
            return self.get_no_access_error(request)

        info = review_request.get_last_activity_info()
        timestamp = info['timestamp']
        updated_object = info['updated_object']
        changedesc = info['changedesc']

        etag = encode_etag('%s:%s' % (timestamp, updated_object.pk))

        if etag_if_none_match(request, etag):
            return HttpResponseNotModified()

        summary = None
        update_type = None
        user = None

        if isinstance(updated_object, ReviewRequest):
            if updated_object.status == ReviewRequest.SUBMITTED:
                summary = _('Review request submitted')
            elif updated_object.status == ReviewRequest.DISCARDED:
                summary = _('Review request discarded')
            else:
                summary = _('Review request updated')

            update_type = 'review-request'
        elif isinstance(updated_object, DiffSet):
            summary = _('Diff updated')
            update_type = 'diff'
        elif isinstance(updated_object, Review):
            if updated_object.is_reply():
                summary = _('New reply')
                update_type = 'reply'
            else:
                summary = _('New review')
                update_type = 'review'

            user = updated_object.user
        else:
            # Should never be able to happen. The object will always at least
            # be a ReviewRequest.
            assert False

        if changedesc:
            user = changedesc.get_user(review_request)
        elif user is None:
            # There is no changedesc which means this review request hasn't
            # been changed since it was first published, so this change must
            # be due to the original submitter.
            user = review_request.submitter

        return 200, {
            self.item_result_key: {
                'timestamp': timestamp,
                'user': user,
                'summary': summary,
                'type': update_type,
            }
        }, {
            'ETag': etag,
        }