views.py 5 KB
Newer Older
1 2 3 4 5 6
from urllib.parse import parse_qs

import requests
from allauth.socialaccount.models import SocialApp
from django.urls import reverse
from requests_oauthlib import OAuth1
7
from rest_framework.viewsets import ModelViewSet
8
from rest_framework.decorators import detail_route, parser_classes, action
9 10 11
from rest_framework.response import Response
from rest_framework.parsers import FormParser, MultiPartParser
from rest_framework.authtoken.models import Token
12
from rest_framework import status, generics, reverse
13 14 15
from rest_framework import permissions

from django.http import Http404, JsonResponse
16
from django.utils.translation import ugettext_lazy as _
17 18 19 20 21 22
from .models import User
from .permissions import IsCurrentUserOrAdmin

from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter
from allauth.socialaccount.providers.twitter.views import TwitterOAuthAdapter
from rest_auth.views import LoginView
23 24 25
from rest_auth.registration.views import SocialLoginView, SocialConnectView
from rest_auth.social_serializers import TwitterLoginSerializer, \
    TwitterConnectSerializer
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49

from .serializers import UserSerializer, FixSocialLoginSerializer


class UserViewSet(ModelViewSet):
    serializer_class = UserSerializer
    queryset = User.objects.all()

    @detail_route(methods=['POST'])
    @parser_classes((FormParser, MultiPartParser))
    def image(self, request, *args, **kwargs):
        if 'image' in request.data:
            user_profile = self.get_object()
            user_profile.image.delete()

            upload = request.data['image']

            user_profile.image.save(upload.name, upload)

            return Response(status=status.HTTP_201_CREATED,
                            headers={'Location': user_profile.image.url})
        else:
            return Response(status=status.HTTP_400_BAD_REQUEST)

50
    def retrieve(self, request, *args, **kwargs):
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
        if self.request.user.id is None:
            raise Http404

        serializer = UserSerializer(self.request.user)
        return Response(serializer.data)

    def get_permissions(self):
        if self.action == 'list':
            self.permission_classes = [permissions.IsAdminUser, ]
        elif self.action == 'retrieve':
            self.permission_classes = [IsCurrentUserOrAdmin]
        return super(self.__class__, self).get_permissions()


# FIXME: the social classes may need rework when updating to v0.9.3
#        FixSocialLoginSerializer class may not be needed anymore
class FacebookLogin(SocialLoginView):
    adapter_class = FacebookOAuth2Adapter
    serializer_class = FixSocialLoginSerializer


class TwitterLogin(LoginView):
    serializer_class = TwitterLoginSerializer
    adapter_class = TwitterOAuthAdapter


77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
class FacebookConnect(SocialConnectView):
    adapter_class = FacebookOAuth2Adapter


class TwitterConnect(SocialConnectView):
    serializer_class = TwitterConnectSerializer
    adapter_class = TwitterOAuthAdapter


class TwitterRequestToken(generics.GenericAPIView):
    def post(self, request):
        if not SocialApp.objects.filter(provider='twitter').exists():
            return Response({'message': _('No Twitter provider found')},
                            status=status.HTTP_404_NOT_FOUND)
        twitter_app = SocialApp.objects.get(provider='twitter')
        CONSUMER_KEY = twitter_app.client_id
        CONSUMER_SECRET = twitter_app.secret

        callback = request\
            .build_absolute_uri(reverse('twitter_connect_callback'))
        auth = OAuth1(CONSUMER_KEY, CONSUMER_SECRET, callback_uri=callback)
        r = requests.post('https://api.twitter.com/oauth/request_token',
                          auth=auth)
        if r.status_code == 200:
            data = parse_qs(r.content.decode('utf-8'))
        else:
            return Response({'message': r.content},
                            status.HTTP_400_BAD_REQUEST)

        return Response(data, status=status.HTTP_200_OK)


class TwitterAccessToken(generics.GenericAPIView):
    def post(self, request):
        if not SocialApp.objects.filter(provider='twitter').exists():
            return Response({'error': ('No Twitter provider found')},
                            status=status.HTTP_404_NOT_FOUND)
        twitter_app = SocialApp.objects.get(provider='twitter')
        CONSUMER_KEY = twitter_app.client_id
        CONSUMER_SECRET = twitter_app.secret

        auth = OAuth1(CONSUMER_KEY, CONSUMER_SECRET,
                      request.data['oauth_token'],
                      verifier=request.data['oauth_verifier'])
        r = requests\
            .post('https://api.twitter.com/oauth/access_token', auth=auth)
        if r.status_code == 200:
            data = parse_qs(r.content.decode('ascii'))
        else:
            return Response({'message': r.content},
                            status.HTTP_400_BAD_REQUEST)

        return Response(data, status=status.HTTP_200_OK)


132 133 134 135 136 137
def get_api_key(request):
    if request.user.id is None:
            raise Http404

    token = Token.objects.get_or_create(user=request.user)
    return JsonResponse({'key': token[0].key}, status=200)