🐛 — Allow to use SHA1-signed anonymous edit URL

The default django.core.signing Signer uses SHA256 algorithm since Django 3.
Umap used Django 2 in the paste, so people had SHA1 signed anonymous edit URLs,
which became unusable when umap switch to Django 3.
This commit makes them usable again (the new SHA256-signed anonymous edit URLs
still works, obviously).
This commit is contained in:
Luc Didry 2023-03-27 16:26:32 +02:00
parent 3f155101af
commit 123af0a7c9
No known key found for this signature in database
GPG key ID: EA868E12D0257E3C
2 changed files with 30 additions and 11 deletions

View file

@ -4,6 +4,7 @@ import pytest
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.urls import reverse from django.urls import reverse
from django.core.signing import Signer
from umap.models import DataLayer, Map from umap.models import DataLayer, Map
from .base import login_required from .base import login_required
@ -401,6 +402,20 @@ def test_anonymous_edit_url(cookieclient, anonymap):
assert key in cookieclient.cookies assert key in cookieclient.cookies
@pytest.mark.usefixtures('allow_anonymous')
def test_sha1_anonymous_edit_url(cookieclient, anonymap):
signer = Signer(algorithm='sha1')
signature = signer.sign(anonymap.pk)
url = reverse('map_anonymous_edit_url', kwargs={'signature': signature})
canonical = reverse('map', kwargs={'pk': anonymap.pk,
'slug': anonymap.slug})
response = cookieclient.get(url)
assert response.status_code == 302
assert response['Location'] == canonical
key, value = anonymap.signed_cookie_elements
assert key in cookieclient.cookies
@pytest.mark.usefixtures('allow_anonymous') @pytest.mark.usefixtures('allow_anonymous')
def test_bad_anonymous_edit_url_should_return_403(cookieclient, anonymap): def test_bad_anonymous_edit_url_should_return_403(cookieclient, anonymap):
url = anonymap.get_anonymous_edit_url() url = anonymap.get_anonymous_edit_url()

View file

@ -654,11 +654,15 @@ class MapAnonymousEditUrl(RedirectView):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
signer = Signer() signer = Signer()
try:
pk = signer.unsign(self.kwargs["signature"])
except BadSignature:
signer = Signer(algorithm='sha1')
try: try:
pk = signer.unsign(self.kwargs["signature"]) pk = signer.unsign(self.kwargs["signature"])
except BadSignature: except BadSignature:
return HttpResponseForbidden() return HttpResponseForbidden()
else:
map_inst = get_object_or_404(Map, pk=pk) map_inst = get_object_or_404(Map, pk=pk)
url = map_inst.get_absolute_url() url = map_inst.get_absolute_url()
response = HttpResponseRedirect(url) response = HttpResponseRedirect(url)