Skip to content

Commit eda31d0

Browse files
committed
Add Wagtail support
1 parent f8f0ba8 commit eda31d0

File tree

12 files changed

+183
-9
lines changed

12 files changed

+183
-9
lines changed

README.rst

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Django Mail Auth features:
1616
- custom user model support
1717
- drop in Django admin support
1818
- drop in Django User replacement
19+
- drop in Wagtail login replacement
1920
- extendable SMS support
2021

2122
This project was inspired by:
@@ -43,22 +44,25 @@ Run this command to install ``django-mail-auth``::
4344
Setup
4445
-----
4546

46-
First add `mailauth` to you installed apps::
47+
First add ``mailauth`` to you installed apps::
4748

4849
INSTALLED_APPS = [
4950
# Django's builtin apps…
5051

5152
'mailauth',
5253
'mailauth.contrib.admin', # optional
5354
'mailauth.contrib.user', # optional
55+
# optional, must be included before "wagtail.admin"
56+
'mailauth.contrib.wagtail',
57+
5458

5559
# other apps…
5660
]
5761

58-
`mailauth.contrib.admin` is optional and will replace the admin's login
62+
``mailauth.contrib.admin`` is optional and will replace the admin's login
5963
with token based authentication too.
6064

61-
`mailauth.contrib.user` is optional and provides a new Django User model.
65+
``mailauth.contrib.user`` is optional and provides a new Django User model.
6266
The new User model needs to be enabled via the ``AUTH_USER_MODEL`` setting::
6367

6468
AUTH_USER_MODEL = 'mailauth_user.EmailUser'
@@ -75,16 +79,18 @@ Next you will need to add the new authentication backend::
7579
'mailauth.backends.MailAuthBackend',
7680
)
7781

78-
Django's `ModelBackend` is only needed, if you still want to support
82+
Django's ``ModelBackend`` is only needed, if you still want to support
7983
password based authentication. If you don't, simply remove it from the list.
8084

81-
Last but not least, go to your URL root config `urls.py` and add the following::
85+
Last but not least, go to your URL root config ``urls.py`` and add the following::
8286

8387
from django.urls import path
8488

8589

8690
urlpatterns = [
8791
path('accounts/', include('mailauth.urls')),
92+
# optional, must be before "wagtail.admin.urls"
93+
path('', include('mailauth.contrib.wagtail.urls')),
8894
]
8995

9096
That's it!
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
default_app_config = 'mailauth.contrib.wagtail.apps.MailAuthWagtail'

mailauth/contrib/wagtail/apps.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.apps import AppConfig
2+
3+
4+
class MailAuthWagtail(AppConfig):
5+
name = 'mailauth.contrib.wagtail'
6+
label = 'mailauth_wagtail'
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
{% extends "wagtailadmin/admin_base.html" %}
2+
{% load wagtailadmin_tags i18n %}
3+
{% block titletag %}{% trans "Sign in" %}{% endblock %}
4+
{% block bodyclass %}login{% endblock %}
5+
6+
{% block extra_css %}
7+
{{ block.super }}
8+
9+
<link rel="stylesheet" href="{% versioned_static 'wagtailadmin/css/layouts/login.css' %}" type="text/css" />
10+
{% endblock %}
11+
12+
{% block furniture %}
13+
<main class="content-wrapper" role="main">
14+
{% if messages or form.errors %}
15+
<div class="messages">
16+
<ul>
17+
{% if form.errors %}
18+
<li class="error">{{ form.errors.email.0 }}</li>
19+
{% endif %}
20+
{% for message in messages %}
21+
<li class="{{ message.tags }}">{{ message }}</li>
22+
{% endfor %}
23+
</ul>
24+
</div>
25+
{% endif %}
26+
27+
{% block above_login %}{% endblock %}
28+
29+
<form action="{% url 'wagtailadmin_login' %}" method="post" autocomplete="off" novalidate>
30+
{% block login_form %}
31+
{% csrf_token %}
32+
33+
{% url 'wagtailadmin_home' as home_url %}
34+
<input type="hidden" name="next" value="{{ next|default:home_url }}" />
35+
36+
<h1>{% block branding_login %}{% trans "Sign in to Wagtail" %}{% endblock %}</h1>
37+
38+
<ul class="fields">
39+
{% block fields %}
40+
<li class="full">
41+
<div class="field iconfield">
42+
{{ form.email.label_tag }}
43+
<div class="input icon-mail">
44+
{{ form.email }}
45+
</div>
46+
</div>
47+
</li>
48+
49+
{% block extra_fields %}
50+
{% for field_name, field in form.extra_fields %}gs
51+
<li class="full">
52+
{{ field.label_tag }}
53+
<div class="field iconfield">
54+
{{ field }}
55+
</div>
56+
</li>
57+
{% endfor %}
58+
{% endblock extra_fields %}
59+
60+
{% comment %}
61+
Removed until functionality exists
62+
<li class="checkbox">
63+
<div class="field">
64+
<label><input type="checkbox" />{% trans "Remember me" %}</label>
65+
</div>
66+
</li>
67+
{% endcomment %}
68+
{% endblock %}
69+
<li class="submit">
70+
{% block submit_buttons %}
71+
<button type="submit" class="button button-longrunning" data-clicked-text="{% trans 'Signing in…' %}"><span class="icon icon-spinner"></span><em>{% trans 'Sign in' %}</em></button>
72+
{% endblock %}
73+
</li>
74+
</ul>
75+
{% endblock %}
76+
</form>
77+
78+
{% block below_login %}{% endblock %}
79+
80+
</main>
81+
{% endblock %}
82+
83+
{% block extra_js %}
84+
{{ block.super }}
85+
<script>
86+
$(function(){
87+
$('form input[name=email]').trigger('focus');
88+
})
89+
</script>
90+
{% endblock %}

mailauth/contrib/wagtail/urls.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from django.urls import path
2+
3+
from . import views
4+
5+
app_name = 'mailauth_wagtail'
6+
7+
urlpatterns = [
8+
path('admin/login/', views.LoginView.as_view(), name='wagtailadmin_login'),
9+
]

mailauth/contrib/wagtail/views.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from django.contrib import messages
2+
from django.http import response
3+
from django.utils.translation import gettext_lazy as _
4+
from wagtail.admin.views.account import LoginView as WagtailLoginView
5+
6+
from mailauth.forms import EmailLoginForm
7+
8+
__all__ = ('LoginView',)
9+
10+
11+
12+
class LoginView(WagtailLoginView):
13+
"""Authentication view for Wagtail admin."""
14+
15+
def get_form_class(self):
16+
return EmailLoginForm
17+
18+
def form_valid(self, form):
19+
form.save()
20+
messages.add_message(
21+
self.request,
22+
messages.SUCCESS,
23+
_('We sent you an email with instructions to log into your account.'),
24+
)
25+
return response.HttpResponseRedirect(self.get_success_url())

setup.cfg

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

4243
[options.package_data]
4344
* = *.txt, *.rst, *.html, *.po

tests/contrib/admin/test_views.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,22 @@
44
class TestAdminLoginView:
55

66
def test_get(self, client):
7-
response = client.get('/admin/login/')
7+
response = client.get('/django-admin/login/')
88
assert response.status_code == 200
99
assert b'type="email"' in response.content
1010
assert b'id="id_email"' in response.content
1111

1212
def test_post(self, client, user, signature):
1313
response = client.post(
14-
'/admin/login/',
14+
'/django-admin/login/',
1515
data={'email': 'spiderman@avengers.com'}
1616
)
1717
assert response.status_code == 302, response.content.decode()
1818
assert signature in mail.outbox[-1].body
1919

2020
def test_post__user_does_not_exist(self, db, client):
2121
response = client.post(
22-
'/admin/login/',
22+
'/django-admin/login/',
2323
data={'email': 'superman@avengers.com'}
2424
)
2525
assert response.status_code == 302, response.content.decode()

tests/contrib/wagtail/__init__.py

Whitespace-only changes.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from mailauth.contrib.wagtail.views import LoginView
2+
from mailauth.forms import EmailLoginForm
3+
4+
5+
class TestLoginView:
6+
def test_get_from_class(self):
7+
assert issubclass(LoginView().get_form_class(), EmailLoginForm)
8+
9+
def test_form_valid(self, rf, db):
10+
view = LoginView()
11+
request = rf.get('/')
12+
13+
class DummyMessageStorage:
14+
def __init__(self):
15+
self.messages = []
16+
17+
def add(self, *args):
18+
self.messages.append(args)
19+
20+
msgs = DummyMessageStorage()
21+
22+
request._messages = msgs
23+
view.request = request
24+
form = EmailLoginForm(view.request, data=dict(email='spiderman@avengers.com'))
25+
assert form.is_valid()
26+
response = view.form_valid(form)
27+
assert response.status_code == 302
28+
assert msgs.messages

0 commit comments

Comments
 (0)