Skip to content

Commit

Permalink
Merge bcd2c60 into 585d7a2
Browse files Browse the repository at this point in the history
  • Loading branch information
sekayasin committed Dec 6, 2018
2 parents 585d7a2 + bcd2c60 commit b52bb15
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 5 deletions.
3 changes: 2 additions & 1 deletion authors/apps/authentication/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 2.1 on 2018-11-27 11:56
# Generated by Django 2.1 on 2018-12-06 05:43

from django.db import migrations, models

Expand All @@ -21,6 +21,7 @@ class Migration(migrations.Migration):
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('username', models.CharField(db_index=True, max_length=255, unique=True)),
('email', models.EmailField(db_index=True, max_length=254, unique=True)),
('is_verified', models.BooleanField(default=False)),
('is_active', models.BooleanField(default=True)),
('is_staff', models.BooleanField(default=False)),
('created_at', models.DateTimeField(auto_now_add=True)),
Expand Down
1 change: 1 addition & 0 deletions authors/apps/authentication/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class User(AbstractBaseUser, PermissionsMixin):
# will simply offer users a way to deactivate their account instead of
# letting them delete it. That way they won't show up on the site anymore,
# but we can still analyze the data.
is_verified = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)

# The `is_staff` flag is expected by Django to determine who can and cannot
Expand Down
2 changes: 2 additions & 0 deletions authors/apps/authentication/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,6 @@ def update(self, instance, validated_data):

return instance

class PasswordSerializer(serializers.Serializer):
new_password = serializers.CharField(max_length=255, required=True)

1 change: 0 additions & 1 deletion authors/apps/authentication/tests/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ def test_token_received_after_successful_registration(self):
}
response = self.client.post('/api/users/' ,data, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
assert 'token' in response.data

def test_token_received_after_successful_login(self):
"""
Expand Down
5 changes: 4 additions & 1 deletion authors/apps/authentication/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
from rest_framework_swagger.views import get_swagger_view

from .views import (
LoginAPIView, RegistrationAPIView, UserRetrieveUpdateAPIView
LoginAPIView, RegistrationAPIView, UserRetrieveUpdateAPIView, PasswordResetAPIView,
PasswordUpdateAPIView
)

schema_view = get_swagger_view(title='Authors Haven')
Expand All @@ -12,5 +13,7 @@
path('users/', RegistrationAPIView.as_view()),
path('users/login/', LoginAPIView.as_view()),
path('swagger/', schema_view),
path('users/password_reset/', PasswordResetAPIView.as_view()),
path('users/password_update/<token>',PasswordUpdateAPIView.as_view()),

]
69 changes: 67 additions & 2 deletions authors/apps/authentication/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from django.core.mail import send_mail
from authors.settings import EMAIL_HOST_USER, SECRET_KEY
import jwt
from django.conf import settings
from rest_framework import generics
from authors.apps.authentication.models import User

from .renderers import UserJSONRenderer
from .serializers import (
LoginSerializer, RegistrationSerializer, UserSerializer
LoginSerializer, RegistrationSerializer, UserSerializer, PasswordSerializer
)


Expand All @@ -30,8 +36,67 @@ def post(self, request):

return Response(serializer.data, status=status.HTTP_201_CREATED)



def generate_password_reset_token(data):
token = jwt.encode({
'email': data
}, settings.SECRET_KEY, algorithm='HS256')

return token.decode('utf-8')


class PasswordResetAPIView(generics.CreateAPIView):
permission_classes = (AllowAny,)
renderer_classes = (UserJSONRenderer,)
serializer_class = UserSerializer

def post(self, request):
user_data = request.data['user']['email']

if not user_data:
return Response({"message": "Please enter your email"}, status=status.HTTP_400_BAD_REQUEST)

try:
user = User.objects.get(email=user_data)

token = generate_password_reset_token(user_data)

serializer_data = self.serializer_class(user)
email_sender = EMAIL_HOST_USER
receipient = [serializer_data['email'].value]
subject = "Password Reset "
message = "Click this link to reset your password:" + "http://127.0.0.1:8000/api/users/password_update/{}".format(
token)
send_mail(subject, message, email_sender,
receipient, fail_silently=False)
return Response(
{'message': 'Check your email for the password reset link', "token": token}, status=status.HTTP_201_CREATED)
except:
return Response({'message': 'User not found'}, status=status.HTTP_400_BAD_REQUEST)



class PasswordUpdateAPIView(generics.UpdateAPIView):
permission_classes = (AllowAny,)
serializer_class = PasswordSerializer
#The URL conf should include a keyword argument corresponding to this value
look_url_kwarg = 'token'

def update(self, request, *args, **kwargs):
token = self.kwargs.get(self.look_url_kwarg)
new_password = request.data.get('new_password')

if not new_password:
return Response({"message": "Please enter your password"}, status=status.HTTP_400_BAD_REQUEST)
try:
decode_token = jwt.decode(
token, settings.SECRET_KEY, algorithms=['HS256'])
user = User.objects.get(email=decode_token['email'])
user.set_password(new_password)
user.save()
return Response({'message': 'Your password has been reset'}, status=status.HTTP_201_CREATED)
except:
return Response({'message': 'Cannot reset password'}, status=status.HTTP_400_BAD_REQUEST)

class LoginAPIView(APIView):
permission_classes = (AllowAny,)
Expand Down
7 changes: 7 additions & 0 deletions authors/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,5 +152,12 @@
),
}

EMAIL_HOST = os.environ.get("EMAIL_HOST")
EMAIL_HOST_USER = os.environ.get("EMAIL_HOST_USER")
EMAIL_HOST_PASSWORD = os.environ.get("EMAIL_HOST_PASSWORD")
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_USE_SSL = False

# Configure Django App for Heroku.
django_heroku.settings(locals())

0 comments on commit b52bb15

Please sign in to comment.