from urllib.parse import parse_qs import requests from allauth.socialaccount.models import SocialApp from django.urls import reverse from requests_oauthlib import OAuth1 from rest_framework.viewsets import ModelViewSet from rest_framework.decorators import detail_route, parser_classes, action from rest_framework.response import Response from rest_framework.parsers import FormParser, MultiPartParser from rest_framework.authtoken.models import Token from rest_framework import status, generics, reverse from rest_framework import permissions from django.http import Http404, JsonResponse from django.utils.translation import ugettext_lazy as _ 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 from rest_auth.registration.views import SocialLoginView, SocialConnectView from rest_auth.social_serializers import TwitterLoginSerializer, \ TwitterConnectSerializer 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) def retrieve(self, request, *args, **kwargs): 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 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) 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)