Merge branch 'master' into appdev
[wolnelektury.git] / src / api / views.py
index 011161e..aa03f46 100644 (file)
@@ -2,14 +2,16 @@
 # Copyright © Fundacja Wolne Lektury. See NOTICE for more information.
 #
 from time import time
+from allauth.account.forms import ResetPasswordForm
+from allauth.account.utils import filter_users_by_email
 from django.conf import settings
-from django.contrib.auth import authenticate
+from django.contrib.auth import authenticate, login
 from django.contrib.auth.decorators import login_required
 from django.contrib.auth.models import User
 from django import forms
-from django.http import HttpResponse
+from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden
 from django.http import Http404
-from django.shortcuts import render
+from django.shortcuts import redirect, render
 from django.views.generic.base import View
 from oauthlib.common import urlencode, generate_token
 from oauthlib.oauth1 import RequestTokenEndpoint, AccessTokenEndpoint
@@ -19,7 +21,7 @@ from rest_framework.response import Response
 from rest_framework.views import APIView
 from rest_framework.generics import GenericAPIView, RetrieveAPIView, get_object_or_404
 from catalogue.models import Book
-from .models import BookUserData, KEY_SIZE, SECRET_SIZE, Token
+from .models import BookUserData, KEY_SIZE, SECRET_SIZE, Token, SessionTransferToken
 from social.models import UserConfirmation
 from . import serializers
 from .request_validator import PistonRequestValidator
@@ -259,14 +261,20 @@ class RegisterView(GenericAPIView):
         serializer.is_valid(raise_exception=True)
         d = serializer.validated_data
 
+        email = d['email']
+
         user = User(
-            username=d['email'],
-            email=d['email'],
-            is_active=False
+            username=email,
+            email=email,
+            is_active=True
         )
         user.set_password(d['password'])
 
+        if settings.FEATURE_CONFIRM_USER:
+            user.is_active = False
+
         try:
+            assert not filter_users_by_email(email)
             user.save()
         except:
             return Response(
@@ -276,7 +284,8 @@ class RegisterView(GenericAPIView):
                 status=400
             )
 
-        UserConfirmation.request(user)
+        if settings.FEATURE_CONFIRM_USER:
+            UserConfirmation.request(user)
         return Response({})
 
 
@@ -334,3 +343,84 @@ class RequestConfirmView(APIView):
         UserConfirmation.request(user)
         return Response({})
 
+
+class DeleteAccountView(GenericAPIView):
+    permission_classes = [IsAuthenticated]
+    serializer_class = serializers.DeleteAccountSerializer
+
+    def post(self, request):
+        u = request.user
+        serializer = self.get_serializer(
+            data=request.data,
+            context={'user': u}
+        )
+        serializer.is_valid(raise_exception=True)
+        d = serializer.validated_data
+        u.is_active = False
+        u.save()
+        return Response({})
+
+
+class PasswordView(GenericAPIView):
+    permission_classes = [IsAuthenticated]
+    serializer_class = serializers.PasswordSerializer
+
+    def post(self, request):
+        u = request.user
+        serializer = self.get_serializer(
+            data=request.data,
+            context={'user': u}
+        )
+        serializer.is_valid(raise_exception=True)
+        d = serializer.validated_data
+        u.set_password(d['new_password'])
+        u.save()
+        return Response({})
+
+
+class ResetPasswordView(GenericAPIView):
+    serializer_class = serializers.ResetPasswordSerializer
+
+    def post(self, request):
+        serializer = serializers.ResetPasswordSerializer(data=request.data)
+        serializer.is_valid(raise_exception=True)
+        form = ResetPasswordForm({"email": serializer.validated_data['email']})
+        form.is_valid()
+        form.save(request)
+        return Response({})
+
+
+class SessionTransferTokenView(APIView):
+    permission_classes = [IsAuthenticated]
+
+    def post(self, request):
+        ott = SessionTransferToken.create_for_user(request.user)
+        return Response({
+            "token": str(ott.token)
+        })
+
+
+class ConsumeSessionTransferTokenView(View):
+    def get(self, request):
+        token_str = request.GET.get("token")
+        next_url = request.GET.get("next", "/") #TODO: validate
+
+        if not token_str:
+            return HttpResponseBadRequest("Missing token")
+
+        try:
+            ott = SessionTransferToken.objects.get(token=token_str)
+        except SessionTransferToken.DoesNotExist:
+            return HttpResponseBadRequest("Invalid token")
+
+        if not ott.is_valid():
+            return HttpResponseForbidden("Token expired or already used")
+
+        # Mark token as used
+        ott.used = True
+        ott.save(update_fields=["used"])
+
+        # Log in the user via Django session
+        login(request, ott.user)
+
+        return redirect(next_url)