diff --git a/api/v1/auth.py b/api/v1/auth.py index e09d27c5..3ff1e9bc 100644 --- a/api/v1/auth.py +++ b/api/v1/auth.py @@ -1,21 +1,31 @@ from datetime import timedelta +import string +import logging +from urllib.parse import urlencode +from django.conf import settings from django.contrib.auth import get_user_model +from django.db.models import Q from django.utils.translation import ugettext_lazy as _ from django.shortcuts import get_object_or_404 from django.utils.timezone import now +from django.urls import reverse_lazy +from phonenumber_field.serializerfields import PhoneNumberField from rest_framework import serializers from rest_framework.authtoken.views import ObtainAuthToken from rest_framework.compat import authenticate from rest_framework.response import Response from rest_framework.views import APIView -from rest_framework.authtoken.models import Token from rest_framework import status +from rest_framework.authentication import BasicAuthentication from apps.auth.models import TempToken +from apps.auth.tokens import verification_email_token +from apps.notification.utils import send_email User = get_user_model() +logger = logging.getLogger(__name__) class AuthTokenSerializer(serializers.Serializer): @@ -56,6 +66,12 @@ class AuthTokenSerializer(serializers.Serializer): return attrs +class LandingRegistrationSerializer(serializers.Serializer): + phone = PhoneNumberField(required=True) + email = serializers.EmailField(required=True) + first_name = serializers.CharField(required=True) + + class ObtainToken(ObtainAuthToken): serializer_class = AuthTokenSerializer @@ -73,3 +89,52 @@ class ObtainTempToken(APIView): return Response({'temp_token': token.key}) return Response(status=status.HTTP_400_BAD_REQUEST) + +class LandingRegistrationView(APIView): + serializer_class = LandingRegistrationSerializer + authentication_classes = (BasicAuthentication,) + + def post(self, request, *args, **kwargs): + serializer = self.serializer_class(data=request.data, context={'request': request}) + if not serializer.is_valid(): + return Response({ + 'status': 'error', + 'errors': serializer.errors, + }, status=400) + email = serializer.validated_data['email'] + phone = serializer.validated_data['phone'] + + if User.objects.filter(Q(email=email) | Q(phone=phone)).count(): + return Response({ + 'status': 'error', + 'errors': ['Возможно вы уже зарегистрированы?'], + 'user_exists': True, + }, status=400) + + user = User( + username=email, + email=email, + phone=phone, + ) + name = serializer.validated_data['first_name'].split(' ') + user.first_name = name[0] + if len(name) > 1: + user.last_name = name[1] + password = User.objects.make_random_password(8, string.ascii_lowercase + string.digits) + user.set_password(password) + user.save() + + verification_token = verification_email_token.make_token(user) + url = 'https://%s%s?%s' % (settings.MAIN_HOST, + reverse_lazy('lilcity:verification-email', args=[verification_token, user.id]), + urlencode({'next': 'https://lil.school/p/free-lesson'})) + try: + send_email('Регистрация в Lil School', email, "notification/email/landing_registration.html", url=url, + user=user, password=password) + except Exception as e: + logger.error(str(e)) + + return Response({ + 'status': 'ok', + 'url': url, + }) diff --git a/api/v1/urls.py b/api/v1/urls.py index ab6e3525..ee6683f8 100644 --- a/api/v1/urls.py +++ b/api/v1/urls.py @@ -6,7 +6,7 @@ from rest_framework.routers import DefaultRouter from drf_yasg.views import get_schema_view from drf_yasg import openapi -from .auth import ObtainToken, ObtainTempToken +from .auth import ObtainToken, ObtainTempToken, LandingRegistrationView from .views import ( AuthorBalanceViewSet, AuthorRequestViewSet, BannerViewSet, ConfigViewSet, CategoryViewSet, @@ -71,6 +71,7 @@ urlpatterns = [ path('author-balance-users/', AuthorBalanceUsersViewSet.as_view(), name='author-balance-users'), path('api-token-auth/', ObtainToken.as_view(), name='api-token-auth'), path('temp-auth-token/', ObtainTempToken.as_view(), name='temp-auth-token'), + path('landing-registration/', LandingRegistrationView.as_view(), name='landing-registration'), path('configs/', ConfigViewSet.as_view(), name='configs'), path('swagger(.json|.yaml)', schema_view.without_ui(cache_timeout=None), name='schema-json'), path('swagger/', schema_view.with_ui('swagger', cache_timeout=None), name='schema-swagger-ui'), diff --git a/api/v1/views.py b/api/v1/views.py index 6972826e..4b4ad44c 100644 --- a/api/v1/views.py +++ b/api/v1/views.py @@ -774,11 +774,13 @@ class NotifiedAboutBonuses(views.APIView): b.save() return Response({'status': 'ok'}) + class PackageViewSet(ExtendedModelViewSet): queryset = Package.objects.all() serializer_class = PackageSerializer permission_classes = (IsAdmin,) + class TagViewSet(ExtendedModelViewSet): queryset = Tag.objects.all() serializer_class = TagSerializer diff --git a/apps/auth/views.py b/apps/auth/views.py index 48719b3f..f9f3de1c 100644 --- a/apps/auth/views.py +++ b/apps/auth/views.py @@ -122,13 +122,14 @@ class VerificationEmailView(View): user = User.objects.get(pk=kwargs.get('uid')) is_valid_token = verification_email_token.check_token( user, kwargs.get('token')) + next = request.GET.get('next') if is_valid_token: user.is_email_proved = True user.save() login(request, user) self.request.session['referrer'] = None - return redirect(reverse_lazy('lilcity:success-verification-email')) + return redirect(next or reverse_lazy('lilcity:success-verification-email')) else: return JsonResponse({"success": False}, status=400) diff --git a/apps/notification/templates/notification/email/landing_registration.html b/apps/notification/templates/notification/email/landing_registration.html new file mode 100644 index 00000000..f5227ab4 --- /dev/null +++ b/apps/notification/templates/notification/email/landing_registration.html @@ -0,0 +1,19 @@ +

Здравствуйте, {{ user.get_full_name }}! Вы только что записались на вводный урок в онлайн-школе Lil School!

+ +

Перейдите по ссылке, чтобы пройти вводный урок

+

Пройти вводный урок +

+ +

Доступ в личный кабинет:
+логин
+{{ user.email }}
+временный пароль
+{{ password }} +

+ +

Теперь у вас есть личный кабинет. Там хранятся учебные материалы, видео прошлых уроков, актуальное расписание и море вдохновения.

+ +

Желаем интересных уроков и свободы в творчестве!