You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

284 lines
11 KiB

import string
import os
import logging
from uuid import uuid4
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, HttpResponse
from django.urls import reverse_lazy
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import FormView, View, TemplateView
from django.shortcuts import redirect
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, LandingRegistrationForm
from .tokens import verification_email_token
User = get_user_model()
logger = logging.getLogger(__name__)
class LearnerRegistrationView(FormView):
form_class = LearnerRegistrationForm
template_name = "auth/registration-learner.html"
success_url = '/'
def form_valid(self, form):
config = Config.load()
first_name = form.cleaned_data['first_name']
last_name = form.cleaned_data['last_name']
email = form.cleaned_data['email'].lower()
password = form.cleaned_data['password']
user, created = User.objects.get_or_create(
email=email,
)
if not created:
if self.request.is_ajax():
return JsonResponse({
"success": False,
'errors': {'__all__': [{'message': 'Возможно вы уже зарегистрированы?'}]}
}, status=400)
else:
context = self.get_context_data(form=form)
context['error'] = 'Возможно вы уже зарегистрированы?'
return self.render_to_response(context)
user.username = email
user.first_name = first_name
user.last_name = last_name
user.set_password(password)
user.save()
referrer = self.request.session.get('referrer')
if referrer:
Referral.objects.create(referral=user, referrer_id=referrer, bonus=config.REFERRAL_BONUS,
referrer_bonus=config.REFERRER_BONUS)
# TODO: email admins? мб реферера уже нет, старая ссылка
self.request.session['referrer'] = None
login(self.request, user)
# fixme: change email text
# fixme: async send email
http_referer = urlsplit(self.request.META.get('HTTP_REFERER'))
http_referer = str(http_referer[0]) + '://' + str(http_referer[1])
token = verification_email_token.make_token(user)
url = http_referer + str(reverse_lazy('lilcity:verification-email', args=[token, user.id]))
try:
send_email('Вы успешно прошли регистрацию', email, "notification/email/verification_email.html", url=url, config=config)
except Exception as e:
logger.error(str(e))
if self.request.is_ajax():
return JsonResponse({"success": True}, status=201)
else:
return super().form_valid(form)
def form_invalid(self, form):
if self.request.is_ajax():
return JsonResponse(form.errors.get_json_data(escape_html=True), status=400)
else:
return super().form_invalid(form)
class LogoutView(View):
def get(self, request, *args, **kwargs):
logout(request)
return redirect('/')
class LoginView(FormView):
form_class = AuthenticationForm
template_name = "auth/login.html"
success_url = '/'
def form_valid(self, form):
login(self.request, form.get_user())
self.request.session['referrer'] = None
if self.request.is_ajax():
return JsonResponse({"success": True})
else:
return super().form_valid(form)
def form_invalid(self, form):
if self.request.is_ajax():
return JsonResponse({"success": False, "errors": form.errors.get_json_data(escape_html=True)}, status=400)
else:
return super().form_invalid(form)
class VerificationEmailView(View):
def get(self, request, *args, **kwargs):
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(next or reverse_lazy('lilcity:success-verification-email'))
else:
return JsonResponse({"success": False}, status=400)
class SuccessVerificationEmailView(TemplateView):
template_name = 'auth/success-verification.html'
class PasswordResetView(views.PasswordContextMixin, FormView):
email_template_name = 'auth/password_reset_email.txt'
subject_template_name = "auth/password_reset_subject.txt"
form_class = views.PasswordResetForm
template_name = "auth/password_reset.html"
success_url = '/'
extra_email_context = None
from_email = None
html_email_template_name = "auth/password_reset_email.html"
title = 'Password reset'
token_generator = views.default_token_generator
def form_valid(self, form):
config = Config.load()
extra_email_context = {'config': config}
if self.extra_email_context and isinstance(self.extra_email_context, dict):
extra_email_context.update(self.extra_email_context)
opts = {
'domain_override': 'https://' + settings.MAIN_HOST,
'use_https': self.request.is_secure(),
'token_generator': self.token_generator,
'from_email': self.from_email,
'email_template_name': self.email_template_name,
'subject_template_name': self.subject_template_name,
'request': self.request,
'html_email_template_name': self.html_email_template_name,
'extra_email_context': extra_email_context,
}
form.save(**opts)
if self.request.is_ajax():
return JsonResponse({"success": True})
else:
return super().form_valid(form)
class PasswordResetConfirmView(views.PasswordResetConfirmView):
template_name = "auth/password_reset_confirm.html"
success_url = reverse_lazy('lilcity:password_reset_complete')
class PasswordResetComplete(views.PasswordResetCompleteView):
template_name = 'auth/password_reset_complete.html'
@method_decorator(csrf_exempt, name="dispatch")
class FacebookLoginOrRegistration(View):
def post(self, requests, *args, **kwargs):
access_token = requests.POST.get('access_token')
graph = GraphAPI(access_token)
try:
data = graph.get('/me?fields=email, first_name, last_name')
photo_data = graph.get('/me/picture?height=120')
except FacepyError:
return JsonResponse({"success": False})
fb_id = data.get('id')
try:
user = User.objects.get(fb_id=fb_id)
except User.DoesNotExist:
email = requests.POST.get('email') or data.get('email')
if not email:
return JsonResponse({"success": False,
"errors": {"email": 'is field required'}
})
else:
email = email.lower()
try:
user = User.objects.get(email__iexact=email)
except User.DoesNotExist:
first_name = data.get('first_name', '')
last_name = data.get('last_name', '')
user = User.objects.create_user(username=email, email=email, first_name=first_name, last_name=last_name, password=uuid4().hex)
user.is_email_proved = True
user.fb_id = fb_id
if photo_data:
photo = ContentFile(photo_data)
fname = str(fb_id) + '.jpg'
user.photo.save(fname, photo, save=True)
user.save()
referrer = self.request.session.get('referrer')
if referrer:
config = Config.load()
Referral.objects.create(referral=user, referrer_id=referrer, bonus=config.REFERRAL_BONUS,
referrer_bonus=config.REFERRER_BONUS)
# TODO: email admins? мб реферера уже нет, старая ссылка
self.request.session['referrer'] = None
login(requests, user=user)
return JsonResponse({"success": True})
else:
if (not user.photo or (user.photo and not os.path.isfile(user.photo.path))) and photo_data:
photo = ContentFile(photo_data)
fname = str(fb_id) + '.jpg'
user.photo.save(fname, photo, save=True)
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(email=email).count():
return redirect('/p/user-exists')
user = User(
username=email,
email=email,
phone2=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)