diff --git a/back_latienda/settings/base.py b/back_latienda/settings/base.py index 3eaa173..8355374 100644 --- a/back_latienda/settings/base.py +++ b/back_latienda/settings/base.py @@ -76,7 +76,7 @@ ROOT_URLCONF = 'back_latienda.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], + 'DIRS': [os.path.join(BASE_DIR, '../templates'),], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ diff --git a/back_latienda/settings/development.py b/back_latienda/settings/development.py index 151c75d..32d91b6 100644 --- a/back_latienda/settings/development.py +++ b/back_latienda/settings/development.py @@ -52,3 +52,5 @@ SIMPLE_JWT = { 'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5), 'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1), } + +EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' diff --git a/back_latienda/urls.py b/back_latienda/urls.py index 55a0691..4e76212 100644 --- a/back_latienda/urls.py +++ b/back_latienda/urls.py @@ -28,6 +28,7 @@ from .routers import router urlpatterns = [ path('admin/', admin.site.urls), + path('activate///',core_views.activate_user, name='activate_user'), path('api/v1/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'), path('api/v1/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'), path('api/v1/token/verify/', TokenVerifyView.as_view(), name='token_verify'), diff --git a/core/tests.py b/core/tests.py index 0257ba3..a4273c3 100644 --- a/core/tests.py +++ b/core/tests.py @@ -6,6 +6,7 @@ import base64 import csv from django.test import TestCase +from django.core import mail from rest_framework.test import APITestCase from rest_framework import status @@ -457,6 +458,7 @@ class LoadCoopManagerTestCase(APITestCase): # check for object creation self.assertEquals(company_count + 5, self.company_model.objects.count()) self.assertEquals(user_count + 5, self.user_model.objects.count()) + self.assertEquals(5, len(mail.outbox)) def test_auth_user_cannot_load_csv(self): company_count = self.company_model.objects.count() diff --git a/core/utils.py b/core/utils.py index 7fcb253..29cdab4 100644 --- a/core/utils.py +++ b/core/utils.py @@ -1,11 +1,24 @@ import logging from django.contrib.auth import get_user_model +from django.contrib.sites.shortcuts import get_current_site +from django.utils.encoding import force_bytes +from django.utils.http import urlsafe_base64_encode +from django.template.loader import render_to_string +from django.core.mail import EmailMessage +from django.contrib.auth.tokens import PasswordResetTokenGenerator from rest_framework_simplejwt.tokens import RefreshToken User = get_user_model() + +class AccountActivationTokenGenerator(PasswordResetTokenGenerator): + def _make_hash_value(self, user, timestamp): + return f"{user.pk}{timestamp}{user.full_name}" + +account_activation_token = AccountActivationTokenGenerator() + def get_tokens_for_user(user): refresh = RefreshToken.for_user(user) @@ -38,3 +51,21 @@ def create_admin_user(email, password): user.is_active = True user.save() return user + +def send_verification_email(request, user): + try: + current_site = get_current_site(request) + subject = 'Activa Tu Cuenta' + message = render_to_string('email_verification.html', { + 'user': user, + 'domain': current_site.domain, + 'uid': urlsafe_base64_encode(force_bytes(user.pk)), + 'token': account_activation_token.make_token(user), + }) + email = EmailMessage( + subject, message, to=[user.email] + ) + email.send() + logging.info(f"Verification email sent to {user.email}") + except Exception as e: + logging.error(f"Could not sent verification email to: {user.email}") diff --git a/core/views.py b/core/views.py index 4dc131c..c496f57 100644 --- a/core/views.py +++ b/core/views.py @@ -8,11 +8,13 @@ from django.shortcuts import render from django.http import HttpResponse from django.contrib.auth import get_user_model from django.core import serializers +from django.utils.http import urlsafe_base64_decode +from django.utils.encoding import force_text from rest_framework import status from rest_framework import viewsets from rest_framework.response import Response -from rest_framework.permissions import IsAdminUser, IsAuthenticated +from rest_framework.permissions import IsAdminUser, IsAuthenticated, AllowAny from rest_framework.generics import UpdateAPIView from rest_framework.decorators import api_view, permission_classes @@ -20,6 +22,7 @@ from companies.models import Company from . import models from . import serializers as core_serializers +from . import utils from back_latienda.permissions import CustomUserPermissions, YourOwnUserPermissions @@ -142,7 +145,8 @@ def load_coop_managers(request): coop_counter += 1 coop_user = User.objects.create_user(email=row['email'], company=coop, role='COOP_MANAGER', is_active=False) - # TODO: send confirmation email + # send confirmation email + utils.send_verification_email(request, coop_user) logging.info(f"Created User: {coop_user}") user_counter += 1 except Exception as e: @@ -152,3 +156,20 @@ def load_coop_managers(request): except Exception as e: return Response({"errors": {"details": str(type(e))}}) + +@api_view(['GET',]) +@permission_classes([AllowAny,]) +def activate_user(request, uidb64, token): + try: + uid = force_text(urlsafe_base64_decode(uidb64)) + user = User.objects.get(pk=uid) + except (TypeError, ValueError, OverflowError, User.DoesNotExist): + user = None + + if user is not None and account_activation_token.check_token(user, token): + # activate user + user.is_active = True + user.save() + return HttpResponse(f"Tu cuenta de usuario {request.user.email} ha sido activada") + else: + return HttpResponse(f"Tu token de verificacion no coincide con ningĂșn usuario registrado") diff --git a/templates/email_verification.html b/templates/email_verification.html new file mode 100644 index 0000000..37a09c8 --- /dev/null +++ b/templates/email_verification.html @@ -0,0 +1,7 @@ +{% autoescape off %} +Hola {{ user.full_name }}, +Por favor, verifica tu registro en LaTiendaCOOP haciendo click en el siguiente enlace: + +http://{{ domain }}{% url 'activate_user' uidb64=uid token=token %} + +{% endautoescape %} \ No newline at end of file