mirror of https://github.com/zulip/zulip.git
middleware: Use a proper error code on CSRF failure.
This allows us to reliably parse the error in code, rather than
attempt to parse the error text. Because the error text gets
translated into the user's language, this error-handling path
wasn't functioning at all for users using Zulip in any of the
seven non-English languages for which we had a translation for
this string.
Together with 709c3b50f
which fixed a similar issue in a
different error-handling path, this fixes #5598.
This commit is contained in:
parent
388acbbfcb
commit
192ec7c0f6
|
@ -192,7 +192,7 @@ function test_with_mock_ajax(test_params) {
|
||||||
test_with_mock_ajax({
|
test_with_mock_ajax({
|
||||||
xhr: {
|
xhr: {
|
||||||
status: 403,
|
status: 403,
|
||||||
responseText: '{"msg": "CSRF Error: whatever"}',
|
responseText: '{"msg": "CSRF Fehler: etwas", "code": "CSRF_FAILED"}',
|
||||||
},
|
},
|
||||||
|
|
||||||
run_code: function () {
|
run_code: function () {
|
||||||
|
|
|
@ -30,7 +30,7 @@ function call(args, idempotent) {
|
||||||
|
|
||||||
if (xhr.status === 403) {
|
if (xhr.status === 403) {
|
||||||
try {
|
try {
|
||||||
if (JSON.parse(xhr.responseText).msg.indexOf("CSRF Error:") !== -1) {
|
if (JSON.parse(xhr.responseText).code === 'CSRF_FAILED') {
|
||||||
reload.initiate({immediate: true,
|
reload.initiate({immediate: true,
|
||||||
save_pointer: true,
|
save_pointer: true,
|
||||||
save_narrow: true,
|
save_narrow: true,
|
||||||
|
|
|
@ -36,6 +36,7 @@ class ErrorCode(AbstractEnum):
|
||||||
BAD_NARROW = ()
|
BAD_NARROW = ()
|
||||||
UNAUTHORIZED_PRINCIPAL = ()
|
UNAUTHORIZED_PRINCIPAL = ()
|
||||||
BAD_EVENT_QUEUE_ID = ()
|
BAD_EVENT_QUEUE_ID = ()
|
||||||
|
CSRF_FAILED = ()
|
||||||
|
|
||||||
class JsonableError(Exception):
|
class JsonableError(Exception):
|
||||||
'''A standardized error format we can turn into a nice JSON HTTP response.
|
'''A standardized error format we can turn into a nice JSON HTTP response.
|
||||||
|
|
|
@ -9,7 +9,7 @@ from django.utils.translation import ugettext as _
|
||||||
from django.utils.deprecation import MiddlewareMixin
|
from django.utils.deprecation import MiddlewareMixin
|
||||||
|
|
||||||
from zerver.lib.response import json_error, json_response_from_error
|
from zerver.lib.response import json_error, json_response_from_error
|
||||||
from zerver.lib.request import JsonableError
|
from zerver.lib.exceptions import JsonableError, ErrorCode
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
from django.http import HttpRequest, HttpResponse, StreamingHttpResponse
|
from django.http import HttpRequest, HttpResponse, StreamingHttpResponse
|
||||||
from zerver.lib.utils import statsd, get_subdomain
|
from zerver.lib.utils import statsd, get_subdomain
|
||||||
|
@ -304,10 +304,24 @@ class TagRequests(MiddlewareMixin):
|
||||||
else:
|
else:
|
||||||
request.error_format = "HTML"
|
request.error_format = "HTML"
|
||||||
|
|
||||||
|
class CsrfFailureError(JsonableError):
|
||||||
|
http_status_code = 403
|
||||||
|
code = ErrorCode.CSRF_FAILED
|
||||||
|
data_fields = ['reason']
|
||||||
|
|
||||||
|
def __init__(self, reason):
|
||||||
|
# type: (Text) -> None
|
||||||
|
self.reason = reason # type: Text
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def msg_format():
|
||||||
|
# type: () -> None
|
||||||
|
return _("CSRF Error: {reason}")
|
||||||
|
|
||||||
def csrf_failure(request, reason=""):
|
def csrf_failure(request, reason=""):
|
||||||
# type: (HttpRequest, Optional[Text]) -> HttpResponse
|
# type: (HttpRequest, Optional[Text]) -> HttpResponse
|
||||||
if request.error_format == "JSON":
|
if request.error_format == "JSON":
|
||||||
return json_error(_("CSRF Error: %s") % (reason,), status=403)
|
return json_response_from_error(CsrfFailureError(reason))
|
||||||
else:
|
else:
|
||||||
return html_csrf_failure(request, reason)
|
return html_csrf_failure(request, reason)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue