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 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): user_id = serializers.IntegerField(required=False) email = serializers.CharField(label=_("Email"), required=False) password = serializers.CharField( label=_("Password"), style={'input_type': 'password'}, trim_whitespace=False, required=False, ) def validate(self, attrs): user_id = attrs.get('user_id') email = attrs.get('email') password = attrs.get('password') request = self.context.get('request') if email and password: user = authenticate(request=request, email=email, password=password) # The authenticate call simply returns None for is_active=False # users. (Assuming the default ModelBackend authentication # backend.) if not user: msg = _('Unable to log in with provided credentials.') raise serializers.ValidationError(msg, code='authorization') elif user.role != User.ADMIN_ROLE: msg = _('Only admin have permission to login admin page.') raise serializers.ValidationError(msg, code='authorization') elif user_id and request.user.is_authenticated and request.user.role == User.ADMIN_ROLE: user = get_object_or_404(User, pk=user_id) else: msg = _('Must include "email" and "password".') raise serializers.ValidationError(msg, code='authorization') attrs['user'] = user 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 class ObtainTempToken(APIView): def get(self, request): user_id = request.GET.get('user') if user_id and request.user.is_authenticated and request.user.role == User.ADMIN_ROLE: user = get_object_or_404(User, pk=user_id) token, created = TempToken.objects.get_or_create(user=user) if not created and now() - token.created > timedelta(hours=1): token.delete() token = TempToken.objects.create(user=user) 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, })