Skip to content

Commit 10ae7ac

Browse files
committed
Rewrite registration logic
1 parent f3151ad commit 10ae7ac

File tree

5 files changed

+98
-74
lines changed

5 files changed

+98
-74
lines changed

docs/api_endpoints.rst

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,20 +51,9 @@ Registration
5151
- /rest-auth/registration/ (POST)
5252

5353
- username
54-
- password1
55-
- password2
54+
- password
5655
- email
5756

58-
.. note:: This endpoint is based on ``allauth.account.views.SignupView`` and uses the same form as in this view. To override fields you have to create custom Signup Form and define it in django settings:
59-
60-
.. code-block:: python
61-
62-
ACCOUNT_FORMS = {
63-
'signup': 'path.to.custom.SignupForm'
64-
}
65-
66-
See allauth documentation for more details.
67-
6857
- /rest-auth/registration/verify-email/ (POST)
6958

7059
- key

docs/configuration.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ Configuration
2929
...
3030
}
3131
32+
- **REST_AUTH_REGISTRATION_SERIALIZERS**
33+
34+
You can define your custom serializers for registration endpoint.
35+
Possible key values:
36+
37+
- REGISTER_SERIALIZER - serializer class in ``rest_auth.register.views.RegisterView``, default value ``rest_auth.register.serializers.RegisterSerializer``
38+
39+
3240

3341
- **REST_SESSION_LOGIN** - Enable session login in Login API view (default: True)
3442

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from django.conf import settings
2+
3+
from rest_auth.registration.serializers import (
4+
RegisterSerializer as DefaultRegisterSerializer)
5+
from ..utils import import_callable
6+
7+
8+
serializers = getattr(settings, 'REST_AUTH_REGISTER_SERIALIZERS', {})
9+
10+
RegisterSerializer = import_callable(
11+
serializers.get('REGISTER_SERIALIZER', DefaultRegisterSerializer))

rest_auth/registration/serializers.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
from django.http import HttpRequest
22
from django.conf import settings
33

4+
try:
5+
from allauth.account import app_settings as allauth_settings
6+
from allauth.utils import (email_address_exists,
7+
get_username_max_length)
8+
from allauth.account.adapter import get_adapter
9+
from allauth.account.utils import setup_user_email
10+
except ImportError:
11+
raise ImportError('allauth needs to be added to INSTALLED_APPS.')
12+
413
from rest_framework import serializers
514
from requests.exceptions import HTTPError
615
# Import is needed only if we are using social login, in which
@@ -109,3 +118,44 @@ def validate(self, attrs):
109118
attrs['user'] = login.account.user
110119

111120
return attrs
121+
122+
123+
class RegisterSerializer(serializers.Serializer):
124+
username = serializers.CharField(
125+
max_length=get_username_max_length(),
126+
min_length=allauth_settings.USERNAME_MIN_LENGTH,
127+
required=allauth_settings.USERNAME_REQUIRED)
128+
email = serializers.EmailField(required=allauth_settings.EMAIL_REQUIRED)
129+
password = serializers.CharField(required=True, write_only=True)
130+
131+
def validate_username(self, username):
132+
username = get_adapter().clean_username(username)
133+
return username
134+
135+
def validate_email(self, email):
136+
email = get_adapter().clean_email(email)
137+
if allauth_settings.UNIQUE_EMAIL:
138+
if email and email_address_exists(email):
139+
raise serializers.ValidationError(
140+
"A user is already registered with this e-mail address.")
141+
return email
142+
143+
def validate_password(self, password):
144+
return get_adapter().clean_password(password)
145+
146+
def custom_signup(self, request, user):
147+
pass
148+
149+
def save(self, request):
150+
adapter = get_adapter()
151+
user = adapter.new_user(request)
152+
self.cleaned_data = self.validated_data
153+
self.cleaned_data['password1'] = self.cleaned_data['password']
154+
adapter.save_user(request, user, self)
155+
self.custom_signup(request, user)
156+
setup_user_email(request, user, [])
157+
return user
158+
159+
160+
class VerifyEmailSerializer(serializers.Serializer):
161+
key = serializers.CharField()

rest_auth/registration/views.py

Lines changed: 28 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,41 @@
1-
from django.http import HttpRequest
21
from rest_framework.views import APIView
32
from rest_framework.response import Response
43
from rest_framework.permissions import AllowAny
4+
from rest_framework.generics import CreateAPIView
55
from rest_framework import status
66
from rest_framework.authtoken.models import Token
7+
from rest_framework.exceptions import MethodNotAllowed
78

8-
from allauth.account.views import SignupView, ConfirmEmailView
9+
from allauth.account.views import ConfirmEmailView
910
from allauth.account.utils import complete_signup
10-
from allauth.account import app_settings
11+
from allauth.account import app_settings as allauth_settings
1112

1213
from rest_auth.app_settings import TokenSerializer
13-
from rest_auth.registration.serializers import SocialLoginSerializer
14+
from rest_auth.registration.serializers import (SocialLoginSerializer,
15+
VerifyEmailSerializer)
16+
from .app_settings import RegisterSerializer
1417
from rest_auth.views import LoginView
1518

1619

17-
class RegisterView(APIView, SignupView):
18-
"""
19-
Accepts the credentials and creates a new user
20-
if user does not exist already
21-
Return the REST Token if the credentials are valid and authenticated.
22-
Calls allauth complete_signup method
23-
24-
Accept the following POST parameters: username, email, password
25-
Return the REST Framework Token Object's key.
26-
"""
27-
28-
permission_classes = (AllowAny,)
29-
allowed_methods = ('POST', 'OPTIONS', 'HEAD')
30-
token_model = Token
31-
serializer_class = TokenSerializer
32-
33-
def get(self, *args, **kwargs):
34-
return Response({}, status=status.HTTP_405_METHOD_NOT_ALLOWED)
35-
36-
def put(self, *args, **kwargs):
37-
return Response({}, status=status.HTTP_405_METHOD_NOT_ALLOWED)
38-
39-
def form_valid(self, form):
40-
self.user = form.save(self.request)
41-
self.token, created = self.token_model.objects.get_or_create(
42-
user=self.user
43-
)
44-
if isinstance(self.request, HttpRequest):
45-
request = self.request
46-
else:
47-
request = self.request._request
48-
return complete_signup(request, self.user,
49-
app_settings.EMAIL_VERIFICATION,
50-
self.get_success_url())
51-
52-
def get_form_kwargs(self, *args, **kwargs):
53-
kwargs = super(RegisterView, self).get_form_kwargs(*args, **kwargs)
54-
kwargs['data'] = self.request.data
55-
return kwargs
56-
57-
def post(self, request, *args, **kwargs):
58-
self.initial = {}
59-
form_class = self.get_form_class()
60-
self.form = self.get_form(form_class)
61-
if self.form.is_valid():
62-
self.form_valid(self.form)
63-
return self.get_response()
64-
else:
65-
return self.get_response_with_errors()
20+
class RegisterView(CreateAPIView):
21+
serializer_class = RegisterSerializer
6622

67-
def get_response(self):
68-
# serializer = self.user_serializer_class(instance=self.user)
69-
serializer = self.serializer_class(instance=self.token,
70-
context={'request': self.request})
71-
return Response(serializer.data, status=status.HTTP_201_CREATED)
23+
def create(self, request, *args, **kwargs):
24+
serializer = self.get_serializer(data=request.data)
25+
serializer.is_valid(raise_exception=True)
26+
user = self.perform_create(serializer)
27+
headers = self.get_success_headers(serializer.data)
28+
return Response(TokenSerializer(user.auth_token).data,
29+
status=status.HTTP_201_CREATED,
30+
headers=headers)
7231

73-
def get_response_with_errors(self):
74-
return Response(self.form.errors, status=status.HTTP_400_BAD_REQUEST)
32+
def perform_create(self, serializer):
33+
user = serializer.save(self.request)
34+
Token.objects.get_or_create(user=user)
35+
complete_signup(self.request._request, user,
36+
allauth_settings.EMAIL_VERIFICATION,
37+
'/')
38+
return user
7539

7640

7741
class VerifyEmailView(APIView, ConfirmEmailView):
@@ -80,10 +44,12 @@ class VerifyEmailView(APIView, ConfirmEmailView):
8044
allowed_methods = ('POST', 'OPTIONS', 'HEAD')
8145

8246
def get(self, *args, **kwargs):
83-
return Response({}, status=status.HTTP_405_METHOD_NOT_ALLOWED)
47+
raise MethodNotAllowed('GET')
8448

8549
def post(self, request, *args, **kwargs):
86-
self.kwargs['key'] = self.request.data.get('key', '')
50+
serializer = VerifyEmailSerializer(data=request.data)
51+
serializer.is_valid(raise_exception=True)
52+
self.kwargs['key'] = serializer.validated_data['key']
8753
confirmation = self.get_object()
8854
confirmation.confirm(self.request)
8955
return Response({'message': 'ok'}, status=status.HTTP_200_OK)

0 commit comments

Comments
 (0)