mirror of
https://github.com/Tivix/django-rest-auth.git
synced 2024-11-22 09:06:40 +03:00
commit
86eb741b34
|
@ -16,7 +16,7 @@ Basic
|
|||
|
||||
- email
|
||||
|
||||
- /rest-auth/password/reset/confim/ (POST)
|
||||
- /rest-auth/password/reset/confirm/ (POST)
|
||||
|
||||
- uid
|
||||
- token
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
Demo project
|
||||
============
|
||||
|
||||
To run demo project (ideally in virtualenv):
|
||||
The idea of creating demo project was to show how you can potentially use
|
||||
django-rest-auth app with jQuery on frontend.
|
||||
Do these steps to make it running (ideally in virtualenv).
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
|
17
docs/faq.rst
Normal file
17
docs/faq.rst
Normal file
|
@ -0,0 +1,17 @@
|
|||
FAQ
|
||||
===
|
||||
|
||||
1. Why account_confirm_email url is defined but it is not usable?
|
||||
|
||||
In /rest_auth/registration/urls.py we can find something like this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
url(r'^account-confirm-email/(?P<key>\w+)/$', TemplateView.as_view(),
|
||||
name='account_confirm_email'),
|
||||
|
||||
This url is used by django-allauth. Empty TemplateView is defined just to allow reverse() call inside app - when email with verification link is being sent.
|
||||
|
||||
You should override this view/url to handle it in your API client somehow and then, send post to /verify-email/ endpoint with proper key.
|
||||
If you don't want to use API on that step, then just use ConfirmEmailView view from:
|
||||
djang-allauth https://github.com/pennersr/django-allauth/blob/master/allauth/account/views.py#L190
|
|
@ -22,6 +22,7 @@ Contents
|
|||
API endpoints <api_endpoints>
|
||||
Configuration <configuration>
|
||||
Demo project <demo>
|
||||
FAQ <faq>
|
||||
Changelog <changelog>
|
||||
|
||||
|
||||
|
|
|
@ -14,7 +14,21 @@ Features
|
|||
* Password reset via e-mail
|
||||
* Social Media authentication
|
||||
|
||||
|
||||
Apps structure
|
||||
--------------
|
||||
|
||||
* ``rest_auth`` has basic auth functionality like login, logout, password reset and password change
|
||||
* ``rest_auth.registration`` has logic related with registration and social media authentication
|
||||
|
||||
|
||||
Angular app
|
||||
-----------
|
||||
|
||||
- Tivix has also created angular module which uses API endpoints from this app - `angular-django-registration-auth <https://github.com/Tivix/angular-django-registration-auth>`_
|
||||
|
||||
|
||||
Demo project
|
||||
------------
|
||||
|
||||
- You can also check our :doc:`Demo Project </demo>` which is using jQuery on frontend.
|
||||
|
|
|
@ -37,5 +37,3 @@ PasswordChangeSerializer = import_callable(
|
|||
serializers.get('PASSWORD_CHANGE_SERIALIZER',
|
||||
DefaultPasswordChangeSerializer)
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ urlpatterns = patterns('',
|
|||
url(r'^$', Register.as_view(), name='rest_register'),
|
||||
url(r'^verify-email/$', VerifyEmail.as_view(), name='rest_verify_email'),
|
||||
|
||||
# These two views are used in django-allauth and empty TemplateView were
|
||||
# This url is used by django-allauth and empty TemplateView is
|
||||
# defined just to allow reverse() call inside app, for example when email
|
||||
# with verification link is being sent, then it's required to render email
|
||||
# content.
|
||||
|
@ -18,8 +18,6 @@ urlpatterns = patterns('',
|
|||
# If you don't want to use API on that step, then just use ConfirmEmailView
|
||||
# view from:
|
||||
# djang-allauth https://github.com/pennersr/django-allauth/blob/master/allauth/account/views.py#L190
|
||||
url(r'^account-email-verification-sent/$', TemplateView.as_view(),
|
||||
name='account_email_verification_sent'),
|
||||
url(r'^account-confirm-email/(?P<key>\w+)/$', TemplateView.as_view(),
|
||||
name='account_confirm_email'),
|
||||
)
|
||||
|
|
|
@ -16,6 +16,13 @@ class Register(APIView, SignupView):
|
|||
|
||||
permission_classes = (AllowAny,)
|
||||
user_serializer_class = UserDetailsSerializer
|
||||
allowed_methods = ('POST', 'OPTIONS', 'HEAD')
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
return Response({}, status=status.HTTP_405_METHOD_NOT_ALLOWED)
|
||||
|
||||
def put(self, *args, **kwargs):
|
||||
return Response({}, status=status.HTTP_405_METHOD_NOT_ALLOWED)
|
||||
|
||||
def form_valid(self, form):
|
||||
self.user = form.save(self.request)
|
||||
|
@ -45,6 +52,10 @@ class Register(APIView, SignupView):
|
|||
class VerifyEmail(APIView, ConfirmEmailView):
|
||||
|
||||
permission_classes = (AllowAny,)
|
||||
allowed_methods = ('POST', 'OPTIONS', 'HEAD')
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
return Response({}, status=status.HTTP_405_METHOD_NOT_ALLOWED)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.kwargs['key'] = self.request.DATA.get('key', '')
|
||||
|
|
|
@ -121,14 +121,31 @@ class PasswordResetConfirmSerializer(serializers.Serializer):
|
|||
|
||||
class PasswordChangeSerializer(serializers.Serializer):
|
||||
|
||||
old_password = serializers.CharField(max_length=128)
|
||||
new_password1 = serializers.CharField(max_length=128)
|
||||
new_password2 = serializers.CharField(max_length=128)
|
||||
|
||||
set_password_form_class = SetPasswordForm
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.old_password_field_enabled = getattr(settings,
|
||||
'OLD_PASSWORD_FIELD_ENABLED', False)
|
||||
super(PasswordChangeSerializer, self).__init__(*args, **kwargs)
|
||||
|
||||
if not self.old_password_field_enabled:
|
||||
self.fields.pop('old_password')
|
||||
|
||||
self.request = self.context.get('request')
|
||||
self.user = self.request.user
|
||||
|
||||
def validate_old_password(self, attrs, source):
|
||||
if self.old_password_field_enabled and \
|
||||
not self.user.check_password(attrs.get(source, '')):
|
||||
raise serializers.ValidationError('Invalid password')
|
||||
return attrs
|
||||
|
||||
def validate(self, attrs):
|
||||
request = self.context.get('request')
|
||||
self.set_password_form = self.set_password_form_class(user=request.user,
|
||||
self.set_password_form = self.set_password_form_class(user=self.user,
|
||||
data=attrs)
|
||||
|
||||
if not self.set_password_form.is_valid():
|
||||
|
|
|
@ -248,6 +248,40 @@ class APITestCase1(TestCase, BaseAPITestCase):
|
|||
# send empty payload
|
||||
self.post(self.password_change_url, data={}, status_code=400)
|
||||
|
||||
@override_settings(OLD_PASSWORD_FIELD_ENABLED=True)
|
||||
def test_password_change_with_old_password(self):
|
||||
login_payload = {
|
||||
"username": self.USERNAME,
|
||||
"password": self.PASS
|
||||
}
|
||||
User.objects.create_user(self.USERNAME, '', self.PASS)
|
||||
self.post(self.login_url, data=login_payload, status_code=200)
|
||||
self.token = self.response.json['key']
|
||||
|
||||
new_password_payload = {
|
||||
"old_password": "%s!" % self.PASS, # wrong password
|
||||
"new_password1": "new_person",
|
||||
"new_password2": "new_person"
|
||||
}
|
||||
self.post(self.password_change_url, data=new_password_payload,
|
||||
status_code=400)
|
||||
|
||||
new_password_payload = {
|
||||
"old_password": self.PASS,
|
||||
"new_password1": "new_person",
|
||||
"new_password2": "new_person"
|
||||
}
|
||||
self.post(self.password_change_url, data=new_password_payload,
|
||||
status_code=200)
|
||||
|
||||
# user should not be able to login using old password
|
||||
self.post(self.login_url, data=login_payload, status_code=400)
|
||||
|
||||
# new password should work
|
||||
login_payload['password'] = new_password_payload['new_password1']
|
||||
self.post(self.login_url, data=login_payload, status_code=200)
|
||||
|
||||
|
||||
def test_password_reset(self):
|
||||
user = User.objects.create_user(self.USERNAME, self.EMAIL, self.PASS)
|
||||
|
||||
|
|
|
@ -6,8 +6,6 @@ from rest_framework.views import APIView
|
|||
from rest_framework.response import Response
|
||||
from rest_framework.generics import GenericAPIView
|
||||
from rest_framework.permissions import IsAuthenticated, AllowAny
|
||||
from rest_framework.authentication import SessionAuthentication, \
|
||||
TokenAuthentication
|
||||
from rest_framework.authtoken.models import Token
|
||||
from rest_framework.generics import RetrieveUpdateAPIView
|
||||
|
||||
|
@ -32,10 +30,6 @@ class Login(GenericAPIView):
|
|||
token_model = Token
|
||||
response_serializer = TokenSerializer
|
||||
|
||||
def get_serializer(self):
|
||||
return self.serializer_class(data=self.request.DATA,
|
||||
context={'request': self.request, 'view': self})
|
||||
|
||||
def login(self):
|
||||
self.user = self.serializer.object['user']
|
||||
self.token, created = self.token_model.objects.get_or_create(
|
||||
|
@ -52,7 +46,7 @@ class Login(GenericAPIView):
|
|||
status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.serializer = self.get_serializer()
|
||||
self.serializer = self.get_serializer(data=self.request.DATA)
|
||||
if not self.serializer.is_valid():
|
||||
return self.get_error_response()
|
||||
self.login()
|
||||
|
@ -67,7 +61,7 @@ class Logout(APIView):
|
|||
|
||||
Accepts/Returns nothing.
|
||||
"""
|
||||
permissions_classes = (AllowAny,)
|
||||
permission_classes = (AllowAny,)
|
||||
|
||||
def post(self, request):
|
||||
try:
|
||||
|
|
Loading…
Reference in New Issue
Block a user