Merge branch 'master' of gitlab.com:lilschool/site into feature/course-access-expire-notification

remotes/origin/feature/course-access-expire-notification
gzbender 6 years ago
commit a8123347ad
  1. 67
      api/v1/auth.py
  2. 3
      api/v1/urls.py
  3. 2
      api/v1/views.py
  4. 7
      apps/auth/forms.py
  5. 52
      apps/auth/views.py
  6. 19
      apps/notification/templates/notification/email/landing_registration.html
  7. 5
      apps/payment/views.py
  8. 4
      apps/school/templates/blocks/prolong_btn.html
  9. 8
      apps/school/templates/summer/prolong_btn.html
  10. 2
      project/urls.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)
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['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,
})

@ -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(<str:format>.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'),

@ -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

@ -1,4 +1,5 @@
from django import forms
from phonenumber_field.formfields import PhoneNumberField
class LearnerRegistrationForm(forms.Form):
@ -6,3 +7,9 @@ class LearnerRegistrationForm(forms.Form):
last_name = forms.CharField()
email = forms.EmailField()
password = forms.CharField()
class LandingRegistrationForm(forms.Form):
name = forms.CharField(required=True)
email = forms.EmailField(required=True)
phone = PhoneNumberField(required=True)

@ -1,14 +1,17 @@
import string
import os
import logging
from uuid import uuid4
from urllib.parse import urlsplit
from urllib.parse import urlsplit, urlencode
from django.db.models import Q
from facepy import GraphAPI
from facepy.exceptions import FacepyError
from django.contrib.auth import get_user_model, logout, login, views
from django.contrib.auth.forms import AuthenticationForm
from django.core.files.base import ContentFile
from django.http import JsonResponse
from django.http import JsonResponse, HttpResponse
from django.urls import reverse_lazy
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
@ -19,7 +22,7 @@ from django.conf import settings
from apps.notification.utils import send_email
from apps.config.models import Config
from apps.user.models import Referral
from .forms import LearnerRegistrationForm
from .forms import LearnerRegistrationForm, LandingRegistrationForm
from .tokens import verification_email_token
@ -122,13 +125,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)
@ -238,3 +242,43 @@ class FacebookLoginOrRegistration(View):
login(requests, user=user)
self.request.session['referrer'] = None
return JsonResponse({"success": True})
@method_decorator(csrf_exempt, name="dispatch")
class LandingRegistrationView(View):
def post(self, request, *args, **kwargs):
form = LandingRegistrationForm(request.POST)
if not form.is_valid():
return HttpResponse(form.errors.as_text())
phone = form.cleaned_data['phone']
name = form.cleaned_data['name'].split()
email = form.cleaned_data['email'].lower()
if User.objects.filter(Q(email=email) | Q(phone=phone)).count():
return redirect('/p/user-exists')
user = User(
username=email,
email=email,
phone=phone,
)
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 redirect(url)

@ -0,0 +1,19 @@
<p>Здравствуйте, {{ user.get_full_name }}! Вы только что записались на вводный урок в онлайн-школе Lil School!</p>
<p>Перейдите по ссылке, чтобы пройти вводный урок</p>
<p><a href="{{ url }}"
style="text-decoration: none; position: relative; padding: 13px 24px 12px; background-image: linear-gradient(-225deg, #D1FF7F 0%, #56FFFD 100%);
border-radius: 3px; font-size: 12px; color: #191919; text-transform: uppercase; letter-spacing: 2px; text-align: center; transition: all .2s; z-index: 2;"
>Пройти вводный урок</a>
</p>
<p>Доступ в личный кабинет:<br>
логин<br>
{{ user.email }}<br>
временный пароль<br>
{{ password }}
</p>
<p>Теперь у вас есть личный кабинет. Там хранятся учебные материалы, видео прошлых уроков, актуальное расписание и море вдохновения.</p>
<p>Желаем интересных уроков и свободы в творчестве!</p>

@ -135,6 +135,11 @@ class SchoolBuyView(TemplateView):
payment_id = request.GET.get('payment_id')
package = get_object_or_404(Package, duration=duration)
date_start = date_start and datetime.datetime.strptime(date_start, '%Y-%m-%d').date() or now().date()
prev_payment = SchoolPayment.objects.paid().filter(
user=self.request.user,
date_end__gte=now().date(),).last()
if prev_payment and prev_payment.date_end > date_start:
date_start = prev_payment.date_end + timedelta(1)
if payment_id:
school_payment = get_object_or_404(SchoolPayment, id=payment_id)
else:

@ -1,9 +1,9 @@
<a
{% if not user.is_authenticated %}
data-popup=".js-popup-auth"
href="#"
{% else %}
data-popup=".js-popup-buy"
href="{% url 'packages' %}"
{% endif %}
class="casing__btn btn{% if pink %} btn_pink{% endif %}"
href="#"
>продлить</a>

@ -1,5 +1,9 @@
<a
data-popup=".js-popup-buy" data-prolong="1" data-date-start="{{ prolong_date_start|date:'Y-m-d' }}"
class="casing__btn btn{% if pink %} btn_pink{% endif %}"
{% if not user.is_authenticated %}
data-popup=".js-popup-auth"
href="#"
{% else %}
href="{% url 'packages' %}"
{% endif %}
class="casing__btn btn{% if pink %} btn_pink{% endif %}"
>продлить</a>

@ -18,6 +18,7 @@ from django.contrib import admin
from django.views.generic import TemplateView
from django.urls import path, include
from apps.auth.views import LandingRegistrationView
from apps.content.views import ContestEditView, ContestView, ContestWorkView, contest_work_comment, FAQView
from apps.course.views import (
CoursesView, likes, coursecomment,
@ -104,6 +105,7 @@ urlpatterns = [
path('faq', FAQView.as_view(), name='faq'),
path('links', LinksView.as_view(), name='links'),
path('prices', PackagesView.as_view(), name='packages'),
path('landing-registration', LandingRegistrationView.as_view(), name='landing-registration'),
]

Loading…
Cancel
Save