8000 Add _legacy_get_session_auth_hash to fix Django 3.1 support · codingjoe/django-mail-auth@84eeb6d · GitHub
[go: up one dir, main page]

Skip to content

Commit 84eeb6d

Browse files
committed
Add _legacy_get_session_auth_hash to fix Django 3.1 support
1 parent becd3b7 commit 84eeb6d

File tree

13 files changed

+142
-22
lines changed

13 files changed

+142
-22
lines changed

.github/workflows/ci.yml

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ jobs:
44
docs:
55
runs-on: ubuntu-latest
66
steps:
7-
- uses: actions/setup-python@v1.1.1
8-
- uses: actions/checkout@v2.0.0
7+
- uses: actions/setup-python@v2
8+
- uses: actions/checkout@v2
99
- run: python -m pip install -r requirements.txt
1010
- run: python setup.py develop
1111
- run: python setup.py build_sphinx -W
@@ -18,16 +18,37 @@ jobs:
1818
python-version: [3.6, 3.7, 3.8]
1919
steps:
2020
- name: Set up Python ${{ matrix.python-version }}
21-
uses: actions/setup-python@v1.1.1
21+
uses: actions/setup-python@v2
2222
with:
2323
python-version: ${{ matrix.python-version }}
24-
- uses: actions/checkout@v2.0.0
24+
- uses: actions/checkout@v2
2525
- run: python setup.py test
2626
- name: Codecov
2727
run: |
2828
python -m pip install codecov
2929
codecov -t ${{secrets.CODECOV_TOKEN}}
3030
31+
extras:
32+
needs: [docs]
33+
runs-on: ubuntu-latest
34+
strategy:
35+
matrix:
36+
extras:
37+
- wagtail
38+
python-version: [3.8]
39+
steps:
40+
- name: Set up Python ${{ matrix.python-version }}
41+
uses: actions/setup-python@v2
42+
with:
43+
python-version: ${{ matrix.python-version }}
44+
- uses: actions/checkout@v2
45+
- run: python -m pip install -e ".[${{ matrix.extras }}]"
46+
- run: python setup.py test
47+
- name: Codecov
48+
run: |
49+
python -m pip install codecov
50+
codecov -t ${{ secrets.CODECOV_TOKEN }}
51+
3152
3253
PostgreSQL:
3354
needs: [docs]
@@ -50,10 +71,10 @@ jobs:
5071
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
5172
steps:
5273
- name: Set up Python ${{ matrix.python-version }}
53-
uses: actions/setup-python@v1.1.1
74+
uses: actions/setup-python@v2
5475
with:
5576
python-version: ${{ matrix.python-version }}
56-
- uses: actions/checkout@v2.0.0
77+
- uses: actions/checkout@v2
5778
- run: python -m pip install psycopg2-binary Django==${{ matrix.django-version }}
5879
- run: python setup.py test
5980
env:

mailauth/contrib/admin/views.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from django.contrib.auth import REDIRECT_FIELD_NAME
22
from django.urls import reverse
3-
from django.utils.translation import ugettext_lazy as _
3+
from django.utils.translation import gettext_lazy as _
44

55
from mailauth.views import LoginView
66

mailauth/contrib/user/migrations/0002_emailuser_session_salt.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# Generated by Django 2.2.1 on 2019-05-27 10:39
22

3-
import django.utils.crypto
43
from django.db import migrations, models
54

5+
import mailauth
6+
67

78
class Migration(migrations.Migration):
89

@@ -14,6 +15,6 @@ class Migration(migrations.Migration):
1415
migrations.AddField(
1516
model_name='emailuser',
1617
name='session_salt',
17-
field=models.CharField(default=django.utils.crypto.get_random_string, editable=False, max_length=12),
18+
field=models.CharField(default=mailauth.contrib.user.models._get_session_salt, editable=False, max_length=12),
1819
),
1920
]
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Generated by Django 3.1 on 2020-08-12 07:22
2+
3+
import django
4+
from django.db import migrations, models
5+
6+
import mailauth.contrib.user.models
7+
8+
9+
class Migration(migrations.Migration):
10+
11+
dependencies = [
12+
('mailauth_user', '0003_ci_unique_index'),
13+
]
14+
15+
operations = [
16+
migrations.AlterField(
17+
model_name='emailuser',
18+
name='first_name',
19+
field=models.CharField(blank=True, max_length=150, verbose_name='first name'),
20+
),
21+
]

mailauth/contrib/user/models.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from django.conf import settings
12
from django.contrib.auth.base_user import BaseUserManager
23
from django.contrib.auth.models import AbstractUser
34
from django.db import models
@@ -37,6 +38,10 @@ def create_superuser(self, email, **extra_fields):
3738
return self._create_user(email, **extra_fields)
3839

3940

41+
def _get_session_salt():
42+
return get_random_string(12)
43+
44+
4045
class AbstractEmailUser(AbstractUser):
4146
EMAIL_FIELD = 'email'
4247
USERNAME_FIELD = 'email'
@@ -51,7 +56,7 @@ class AbstractEmailUser(AbstractUser):
5156
# Salt for the session hash replacing the password in this function.
5257
session_salt = models.CharField(
5358
max_length=12, editable=False,
54-
default=get_random_string,
59+
default=_get_session_salt,
5560
)
5661

5762
def has_usable_password(self):
@@ -62,12 +67,29 @@ def has_usable_password(self):
6267
class Meta(AbstractUser.Meta):
6368
abstract = True
6469

70+
def _legacy_get_session_auth_hash(self):
71+
# RemovedInDjango40Warning: pre-Django 3.1 hashes will be invalid.
72+
key_salt = "mailauth.contrib.user.models.EmailUserManager.get_session_auth_hash"
73+
if not self.session_salt:
74+
raise ValueError("'session_salt' must be set")
75+
return salted_hmac(key_salt, self.session_salt, algorithm='sha1').hexdigest()
76+
6577
def get_session_auth_hash(self):
6678
"""Return an HMAC of the :attr:`.session_salt` field."""
6779
key_salt = "mailauth.contrib.user.models.EmailUserManager.get_session_auth_hash"
6880
if not self.session_salt:
6981
raise ValueError("'session_salt' must be set")
70-
return salted_hmac(key_salt, self.session_salt).hexdigest()
82+
algorithm = getattr(settings, 'DEFAULT_HASHING_ALGORITHM')
83+
if algorithm is None:
84+
return salted_hmac(key_salt, self.session_salt).hexdigest()
85+
return salted_hmac(
86+
key_salt,
87 55E +
self.session_salt,
88+
# RemovedInDjango40Warning: when the deprecation ends, replace
89+
# with:
90+
# algorithm='sha256',
91+
algorithm=algorithm,
92+
).hexdigest()
7193

7294

7395
delattr(AbstractEmailUser, 'password')

setup.cfg

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ tests_require =
3838
pytest
3939
pytest-django
4040
pytest-cov
41-
wagtail
4241

4342
[options.package_data]
4443
* = *.txt, *.rst, *.html, *.po

tests/conftest.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import django
12
import pytest
23
from django.contrib.auth import get_user_model
34
from django.utils import timezone
@@ -36,7 +37,9 @@ def admin_user(db):
3637
@pytest.fixture()
3738
def signature():
3839
"""Return a signature matching the user fixture."""
39-
return 'LZ.173QUS.1Hjptg.lf2hFgOXQtjQsFypS2ItRG2hkpA'
40+
if django.VERSION < (3, 1):
41+
return 'LZ.173QUS.1Hjptg.lf2hFgOXQtjQsFypS2ItRG2hkpA'
42+
return 'LZ.173QUS.1Hjptg.UtFdkTPoyrSA0IB6AUEhtz_hMyFZY0kcREE1HnWdFq4'
4043

4144

4245
@pytest.fixture()

tests/contrib/auth/test_models.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,29 @@ def test_get_session_auth_hash__unique(self, db):
2828

2929
assert spiderman.get_session_auth_hash() != ironman.get_session_auth_hash()
3030

31+
def test_legacy_get_session_auth_hash__default(self, db):
32+
user = EmailUser(email='spiderman@avengers.com')
33+
34+
assert user.session_salt
35+
assert user._legacy_get_session_auth_hash()
36+
37+
def test_legacy_get_session_auth_hash__value_error(self, db):
38+
user = EmailUser(email='spiderman@avengers.com', session_salt=None)
39+
40+
with pytest.raises(ValueError) as e:
41+
user._legacy_get_session_auth_hash()
42+
43+
assert "'session_salt' must be set" in str(e.value)
44+
45+
def test_legacy_get_session_auth_hash__unique(self, db):
46+
spiderman = EmailUser(email='spiderman@avengers.com')
47+
ironman = EmailUser(email='ironman@avengers.com')
48+
49+
assert (
50+
spiderman._legacy_get_session_auth_hash() !=
51+
ironman._legacy_get_session_auth_hash()
52+
)
53+
3154
def test_password_field(self):
3255
user = EmailUser(email='spiderman@avengers.com')
3356
with pytest.raises(FieldDoesNotExist):

tests/contrib/wagtail/test_views.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
from mailauth.contrib.wagtail.views import LoginView
1+
import pytest
2+
23
from mailauth.forms import EmailLoginForm
34

5+
LoginView = pytest.importorskip("mailauth.contrib.wagtail.views.LoginView")
6+
47

58
class TestLoginView:
69
def test_get_from_class(self):

tests/test_backends.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,5 +62,5 @@ def test_get_login_url(self, signer, signature):
6262
backend = MailAuthBackend()
6363
MailAuthBackend.signer = signer
6464
assert backend.get_login_url(signature) == (
65-
"/accounts/login/LZ.173QUS.1Hjptg.lf2hFgOXQtjQsFypS2ItRG2hkpA"
65+
f"/accounts/login/{signature}"
6666
)

0 commit comments

Comments
 (0)
0