Skip to content
This repository has been archived by the owner on May 5, 2020. It is now read-only.

Commit

Permalink
fix: Rename LoginCodeRequestView to LoginView
Browse files Browse the repository at this point in the history
Makes more sense from outside of nopassword, as requesting a login code is the entry point of the login process.
This way the default value of LOGIN_URL (`/accounts/login/`) is correctly opening the login code request page.
  • Loading branch information
rubengrill authored and relekang committed Sep 14, 2018
1 parent bbbf554 commit 44363c5
Show file tree
Hide file tree
Showing 17 changed files with 67 additions and 66 deletions.
6 changes: 3 additions & 3 deletions nopassword/backends/email.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@


class EmailBackend(NoPasswordBackend):
template_name = 'registration/login_code_request_email.txt'
html_template_name = 'registration/login_code_request_email.html'
subject_template_name = 'registration/login_code_request_subject.txt'
template_name = 'registration/login_email.txt'
html_template_name = 'registration/login_email.html'
subject_template_name = 'registration/login_subject.txt'
from_email = None

def send_login_code(self, code, context, **kwargs):
Expand Down
2 changes: 1 addition & 1 deletion nopassword/backends/sms.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@


class TwilioBackend(NoPasswordBackend):
template_name = 'registration/login_code_request_sms.txt'
template_name = 'registration/login_sms.txt'
from_number = None

def __init__(self):
Expand Down
13 changes: 6 additions & 7 deletions nopassword/forms.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
from django import forms
from django.conf import settings
from django.contrib.auth import authenticate, get_backends, get_user_model
from django.contrib.sites.shortcuts import get_current_site
from django.core.exceptions import ImproperlyConfigured
Expand All @@ -10,7 +9,7 @@
from nopassword import models


class LoginCodeRequestForm(forms.Form):
class LoginForm(forms.Form):
error_messages = {
'invalid_username': _(
"Please enter a correct %(username)s. "
Expand All @@ -20,7 +19,7 @@ class LoginCodeRequestForm(forms.Form):
}

def __init__(self, *args, **kwargs):
super(LoginCodeRequestForm, self).__init__(*args, **kwargs)
super(LoginForm, self).__init__(*args, **kwargs)

self.username_field = get_user_model()._meta.get_field(get_user_model().USERNAME_FIELD)
self.fields['username'] = self.username_field.formfield()
Expand All @@ -47,7 +46,7 @@ def clean_username(self):

return username

def save(self, request, login_url=None, domain_override=None, extra_context=None):
def save(self, request, login_code_url='login_code', domain_override=None, extra_context=None):
login_code = self.cleaned_data['login_code']
login_code.next = request.GET.get('next')
login_code.save()
Expand All @@ -62,7 +61,7 @@ def save(self, request, login_url=None, domain_override=None, extra_context=None
url = '{}://{}{}?code={}&next={}'.format(
'https' if request.is_secure() else 'http',
domain,
resolve_url(login_url or settings.LOGIN_URL),
resolve_url(login_code_url),
login_code.code,
login_code.next,
)
Expand Down Expand Up @@ -91,7 +90,7 @@ def send_login_code(self, login_code, context, **kwargs):
)


class LoginForm(forms.Form):
class LoginCodeForm(forms.Form):
code = forms.ModelChoiceField(
label=_('Login code'),
queryset=models.LoginCode.objects.select_related('user'),
Expand All @@ -107,7 +106,7 @@ class LoginForm(forms.Form):
}

def __init__(self, request=None, *args, **kwargs):
super(LoginForm, self).__init__(*args, **kwargs)
super(LoginCodeForm, self).__init__(*args, **kwargs)

self.request = request

Expand Down
8 changes: 4 additions & 4 deletions nopassword/rest/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
from nopassword import forms


class LoginCodeRequestSerializer(serializers.Serializer):
class LoginSerializer(serializers.Serializer):
username = serializers.CharField()

form_class = forms.LoginCodeRequestForm
form_class = forms.LoginForm

def validate(self, data):
self.form = self.form_class(data=self.initial_data)
Expand All @@ -23,10 +23,10 @@ def save(self):
self.form.save(request=request)


class LoginSerializer(serializers.Serializer):
class LoginCodeSerializer(serializers.Serializer):
code = serializers.CharField()

form_class = forms.LoginForm
form_class = forms.LoginCodeForm

def validate(self, data):
request = self.context.get('request')
Expand Down
6 changes: 1 addition & 5 deletions nopassword/rest/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@
from nopassword.rest import views

urlpatterns = [
url(
r'^login-code/request/$',
views.LoginCodeRequestView.as_view(),
name='rest_login_code_request',
),
url(r'^login/$', views.LoginView.as_view(), name='rest_login'),
url(r'^login/code/$', views.LoginCodeView.as_view(), name='rest_login_code'),
url(r'^logout/$', views.LogoutView.as_view(), name='rest_logout'),
]
8 changes: 4 additions & 4 deletions nopassword/rest/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
from nopassword.rest import serializers


class LoginCodeRequestView(GenericAPIView):
serializer_class = serializers.LoginCodeRequestSerializer
class LoginView(GenericAPIView):
serializer_class = serializers.LoginSerializer
permission_classes = (AllowAny,)

def post(self, request, *args, **kwargs):
Expand All @@ -32,9 +32,9 @@ def post(self, request, *args, **kwargs):


@method_decorator(sensitive_post_parameters('code'), 'dispatch')
class LoginView(GenericAPIView):
class LoginCodeView(GenericAPIView):
permission_classes = (AllowAny,)
serializer_class = serializers.LoginSerializer
serializer_class = serializers.LoginCodeSerializer
token_serializer_class = serializers.TokenSerializer
token_model = Token

Expand Down
6 changes: 1 addition & 5 deletions nopassword/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@
from nopassword import views

urlpatterns = [
url(
r'^login-code/request/$',
views.LoginCodeRequestView.as_view(),
name='login_code_request',
),
url(r'^login/$', views.LoginView.as_view(), name='login'),
url(r'^login/code/$', views.LoginCodeView.as_view(), name='login_code'),
url(r'^logout/$', views.LogoutView.as_view(), name='logout'),
]
34 changes: 22 additions & 12 deletions nopassword/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,44 @@
from nopassword import forms


class LoginCodeRequestView(FormView):
form_class = forms.LoginCodeRequestForm
success_url = reverse_lazy('login')
template_name = 'registration/login_code_request_form.html'
class LoginView(FormView):
"""
Sends a login code to the user.
It doesn't authenticate a user but it is the entry point for the login process (login url).
"""

form_class = forms.LoginForm
success_url = reverse_lazy('login_code')
template_name = 'registration/login_form.html'

@method_decorator(csrf_protect)
def dispatch(self, request, *args, **kwargs):
return super(LoginCodeRequestView, self).dispatch(request, *args, **kwargs)
return super(LoginView, self).dispatch(request, *args, **kwargs)

def form_valid(self, form):
form.save(request=self.request)
return super(LoginCodeRequestView, self).form_valid(form)
return super(LoginView, self).form_valid(form)


class LoginView(DjangoLoginView):
form_class = forms.LoginForm
class LoginCodeView(DjangoLoginView):
"""
Authenticates a user with a login code.
"""

form_class = forms.LoginCodeForm
template_name = 'registration/login_code.html'

def get(self, request, *args, **kwargs):
if 'code' in self.request.GET and getattr(settings, 'NOPASSWORD_LOGIN_ON_GET', False):
return super(LoginView, self).post(request, *args, **kwargs)
return super(LoginView, self).get(request, *args, **kwargs)
return super(LoginCodeView, self).post(request, *args, **kwargs)
return super(LoginCodeView, self).get(request, *args, **kwargs)

def form_valid(self, form):
form.save()
return super(LoginView, self).form_valid(form)
return super(LoginCodeView, self).form_valid(form)

def get_form_kwargs(self):
kwargs = super(LoginView, self).get_form_kwargs()
kwargs = super(LoginCodeView, self).get_form_kwargs()

if self.request.method == 'GET' and 'code' in self.request.GET:
kwargs['data'] = self.request.GET
Expand Down
2 changes: 1 addition & 1 deletion tests/test_backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def test_email_backend(self):

def test_html_template_name(self):
# We don't have an existing html template, so we just use the txt template
self.backend.html_template_name = 'registration/login_code_request_email.txt'
self.backend.html_template_name = 'registration/login_email.txt'
self.backend.send_login_code(self.code, {'url': 'https://example.com'})
self.assertEqual(1, len(mail.outbox))
message = mail.outbox[0]
Expand Down
8 changes: 4 additions & 4 deletions tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from nopassword import forms


class TestLoginCodeRequestForm(TestCase):
class TestLoginForm(TestCase):

def setUp(self):
self.factory = RequestFactory()
Expand All @@ -17,7 +17,7 @@ def test_domain_override(self):
request = self.factory.post('/accounts/login/', {
'username': 'user',
})
form = forms.LoginCodeRequestForm(data=request.POST)
form = forms.LoginForm(data=request.POST)
form.send_login_code = MagicMock()

self.assertTrue(form.is_valid())
Expand All @@ -32,7 +32,7 @@ def test_extra_context(self):
request = self.factory.post('/accounts/login/', {
'username': 'user',
})
form = forms.LoginCodeRequestForm(data=request.POST)
form = forms.LoginForm(data=request.POST)
form.send_login_code = MagicMock()

self.assertTrue(form.is_valid())
Expand All @@ -48,5 +48,5 @@ def test_extra_context(self):
AUTHENTICATION_BACKENDS=['django.contrib.auth.backends.ModelBackend'],
)
def test_missing_backend(self):
form = forms.LoginCodeRequestForm()
form = forms.LoginForm()
self.assertRaises(ImproperlyConfigured, form.send_login_code, None, None)
16 changes: 8 additions & 8 deletions tests/test_rest_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def setUp(self):
self.user = get_user_model().objects.create(username='user')

def test_request_login_code(self):
response = self.client.post('/accounts-rest/login-code/request/', {
response = self.client.post('/accounts-rest/login/', {
'username': self.user.username,
})

Expand All @@ -23,15 +23,15 @@ def test_request_login_code(self):
self.assertIsNotNone(login_code)

def test_request_login_code_missing_username(self):
response = self.client.post('/accounts-rest/login-code/request/')
response = self.client.post('/accounts-rest/login/')

self.assertEqual(response.status_code, 400)
self.assertEqual(response.json(), {
'username': ['This field is required.'],
})

def test_request_login_code_unknown_user(self):
response = self.client.post('/accounts-rest/login-code/request/', {
response = self.client.post('/accounts-rest/login/', {
'username': 'unknown',
})

Expand All @@ -44,7 +44,7 @@ def test_request_login_code_inactive_user(self):
self.user.is_active = False
self.user.save()

response = self.client.post('/accounts-rest/login-code/request/', {
response = self.client.post('/accounts-rest/login/', {
'username': self.user.username,
})

Expand All @@ -56,7 +56,7 @@ def test_request_login_code_inactive_user(self):
def test_login(self):
login_code = LoginCode.objects.create(user=self.user, code='foobar')

response = self.client.post('/accounts-rest/login/', {
response = self.client.post('/accounts-rest/login/code/', {
'code': login_code.code,
})

Expand All @@ -69,15 +69,15 @@ def test_login(self):
self.assertEqual(response.data['key'], token.key)

def test_login_missing_code(self):
response = self.client.post('/accounts-rest/login/')
response = self.client.post('/accounts-rest/login/code/')

self.assertEqual(response.status_code, 400)
self.assertEqual(response.json(), {
'code': ['This field is required.'],
})

def test_login_unknown_code(self):
response = self.client.post('/accounts-rest/login/', {
response = self.client.post('/accounts-rest/login/code/', {
'code': 'unknown',
})

Expand All @@ -92,7 +92,7 @@ def test_login_inactive_user(self):

login_code = LoginCode.objects.create(user=self.user, code='foobar')

response = self.client.post('/accounts-rest/login/', {
response = self.client.post('/accounts-rest/login/code/', {
'code': login_code.code,
})

Expand Down

0 comments on commit 44363c5

Please sign in to comment.