diff --git a/apps/auth/tests/test_registration.py b/apps/auth/tests/test_registration.py index f0824fec..231a3d69 100644 --- a/apps/auth/tests/test_registration.py +++ b/apps/auth/tests/test_registration.py @@ -1,6 +1,7 @@ from django.test import TestCase, Client from django.urls import reverse from django.contrib.auth import get_user_model +from django.core import mail User = get_user_model() @@ -43,5 +44,10 @@ class LearnerRegistrationTest(TestCase): self.assertEqual(response.status_code, 400) self.assertIn('email', response.json()) + def test_should_send_email_for_verification(self): + self.client.post(self.url, self.user_data) + + self.assertEqual(len(mail.outbox), 1) + def test_should_redirect_main_page_when_user_not_anonymous(self): # todo pass diff --git a/apps/auth/tests/test_verification_email.py b/apps/auth/tests/test_verification_email.py new file mode 100644 index 00000000..055f8500 --- /dev/null +++ b/apps/auth/tests/test_verification_email.py @@ -0,0 +1,35 @@ +from django.contrib.auth import get_user_model +from ..tokens import verification_email_token +from django.test import TestCase, Client +from django.urls import reverse + +User = get_user_model() + + +class VerificationEmailTest(TestCase): + def setUp(self): + self.client = Client() + + self.user_1 = User.objects.create_user(username='user_1@example.com', password='1234') + self.token_user_1 = verification_email_token.make_token(self.user_1) + + self.url = reverse('lilcity:verification-email', kwargs={"token": self.token_user_1}) + + def test_should_verification_email_for_login_user(self): + self.client.login(username=self.user_1.username, password='1234') + + response = self.client.get(f'{self.url}') + self.assertEqual(response.status_code, 200) + + def test_should_anonymous_user(self): + response = self.client.get(f'{self.url}') + + self.assertEqual(response.status_code, 400) + + def test_should_error_if_token_is_not_valid(self): + user_hacker = User.objects.create_user(username='hacker@example.com', password='1234') + + self.client.login(username=user_hacker.username, password='1234') + response = self.client.get(f'{self.url}') + + self.assertEqual(response.status_code, 400) diff --git a/apps/auth/tokens.py b/apps/auth/tokens.py new file mode 100644 index 00000000..c2b75412 --- /dev/null +++ b/apps/auth/tokens.py @@ -0,0 +1,13 @@ +from django.contrib.auth.tokens import PasswordResetTokenGenerator +from django.utils import six + + +class TokenGenerator(PasswordResetTokenGenerator): + def _make_hash_value(self, user, timestamp): + return ( + six.text_type(user.pk) + six.text_type(timestamp) + + six.text_type(user.is_active) + ) + + +verification_email_token = TokenGenerator() diff --git a/apps/auth/urls.py b/apps/auth/urls.py index 27e5a38f..fc8dfe57 100644 --- a/apps/auth/urls.py +++ b/apps/auth/urls.py @@ -6,4 +6,5 @@ urlpatterns = [ path('registration/learner/', views.LearnerRegistrationView.as_view(), name="registration-learner"), path('logout/', views.LogoutView.as_view(), name="logout"), path('login/', views.LoginView.as_view(), name="login"), + path('verification-email//', views.VerificationEmailView.as_view(), name="verification-email"), ] diff --git a/apps/auth/views.py b/apps/auth/views.py index 838edea0..4e74e0cc 100644 --- a/apps/auth/views.py +++ b/apps/auth/views.py @@ -1,9 +1,11 @@ from django.contrib.auth import get_user_model, logout, login from django.contrib.auth.forms import AuthenticationForm +from django.core.mail import EmailMessage from django.http import JsonResponse from django.views.generic import FormView, View from .forms import LearnerRegistrationForm +from .tokens import verification_email_token User = get_user_model() @@ -21,6 +23,12 @@ class LearnerRegistrationView(FormView): user = User.objects.create_user(username=email, email=email, first_name=first_name, last_name=last_name, password=password) login(self.request, user) + # fixme: change email text + # fixme: async send email + token = verification_email_token.make_token(user) + email = EmailMessage('VerificationEmail', f"{token}", to=[email]) + email.send() + return JsonResponse({"success": True}, status=201) def form_invalid(self, form): @@ -43,3 +51,13 @@ class LoginView(FormView): def form_invalid(self, form): return JsonResponse({"success": False, "errors": form.errors.get_json_data(escape_html=True)}, status=400) + + +class VerificationEmailView(View): + def get(self, request, *args, **kwargs): + is_valid_token = verification_email_token.check_token(request.user, kwargs.get('token')) + + if is_valid_token: + return JsonResponse({"success": True}) + else: + return JsonResponse({"success": False}, status=400)