|
| 1 | +from django.http import HttpRequest |
| 2 | +from rest_framework import serializers |
| 3 | +from requests.exceptions import HTTPError |
| 4 | +# Import is needed only if we are using social login, in which |
| 5 | +# case the allauth.socialaccount will be declared |
| 6 | +try: |
| 7 | + from allauth.socialaccount.helpers import complete_social_login |
| 8 | +except ImportError: |
| 9 | + pass |
| 10 | + |
| 11 | +from allauth.socialaccount.models import SocialToken |
| 12 | + |
| 13 | + |
| 14 | +class TwitterLoginSerializer(serializers.Serializer): |
| 15 | + access_token = serializers.CharField(required=True) |
| 16 | + token_secret = serializers.CharField(required=True) |
| 17 | + |
| 18 | + def _get_request(self): |
| 19 | + request = self.context.get('request') |
| 20 | + if not isinstance(request, HttpRequest): |
| 21 | + request = request._request |
| 22 | + return request |
| 23 | + |
| 24 | + def get_social_login(self, adapter, app, token, response): |
| 25 | + """ |
| 26 | +
|
| 27 | + :param adapter: allauth.socialaccount Adapter subclass. Usually OAuthAdapter or Auth2Adapter |
| 28 | + :param app: `allauth.socialaccount.SocialApp` instance |
| 29 | + :param token: `allauth.socialaccount.SocialToken` instance |
| 30 | + :param response: Provider's response for OAuth1. Not used in the |
| 31 | + :return: :return: A populated instance of the `allauth.socialaccount.SocialLoginView` instance |
| 32 | + """ |
| 33 | + request = self._get_request() |
| 34 | + social_login = adapter.complete_login(request, app, token, response=response) |
| 35 | + social_login.token = token |
| 36 | + return social_login |
| 37 | + |
| 38 | + def validate(self, attrs): |
| 39 | + view = self.context.get('view') |
| 40 | + request = self._get_request() |
| 41 | + |
| 42 | + if not view: |
| 43 | + raise serializers.ValidationError( |
| 44 | + 'View is not defined, pass it as a context variable' |
| 45 | + ) |
| 46 | + |
| 47 | + adapter_class = getattr(view, 'adapter_class', None) |
| 48 | + if not adapter_class: |
| 49 | + raise serializers.ValidationError('Define adapter_class in view') |
| 50 | + |
| 51 | + adapter = adapter_class() |
| 52 | + app = adapter.get_provider().get_app(request) |
| 53 | + |
| 54 | + if('access_token' in attrs) and ('token_secret' in attrs): |
| 55 | + access_token = attrs.get('access_token') |
| 56 | + token_secret = attrs.get('token_secret') |
| 57 | + else: |
| 58 | + raise serializers.ValidationError('Incorrect input. access_token and token_secret are required.') |
| 59 | + |
| 60 | + request.session['oauth_api.twitter.com_access_token'] = { |
| 61 | + 'oauth_token': access_token, |
| 62 | + 'oauth_token_secret': token_secret, |
| 63 | + } |
| 64 | + token = SocialToken(token=access_token, token_secret=token_secret) |
| 65 | + token.app = app |
| 66 | + |
| 67 | + try: |
| 68 | + login = self.get_social_login(adapter, app, token, access_token) |
| 69 | + complete_social_login(request, login) |
| 70 | + except HTTPError: |
| 71 | + raise serializers.ValidationError('Incorrect value') |
| 72 | + |
| 73 | + if not login.is_existing: |
| 74 | + login.lookup() |
| 75 | + login.save(request, connect=True) |
| 76 | + attrs['user'] = login.account.user |
| 77 | + |
| 78 | + return attrs |
0 commit comments