serializers.py 7.4 KB
Newer Older
1 2
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth import get_user_model
Bruno Martin's avatar
Bruno Martin committed
3
from django.conf import settings
4 5 6 7 8 9 10
from rest_framework import serializers
from rest_auth.registration.serializers import SocialLoginSerializer, RegisterSerializer
from allauth.account.adapter import get_adapter
from allauth.account.utils import setup_user_email
from allauth.account import app_settings as allauth_settings
from allauth.socialaccount.helpers import complete_social_login
from requests.exceptions import HTTPError
11
from cities_light.models import City, Region
12

Bruno Martin's avatar
Bruno Martin committed
13 14
import requests

15
from .models import PoliticalFront, ActivismSchoolWorkplace, CtbRole
16 17 18 19 20 21 22 23
User = get_user_model()


class UserSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = User
        fields = ('id', 'image', 'name', 'email', 'biography', 'city',
Laury Bueno's avatar
Laury Bueno committed
24
                  'state', 'country', 'username', 'race', 'gender',
25
                  'occupation', 'is_superuser', 'is_staff',)
26 27


28 29 30 31 32 33 34
class SimpleUserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ('id', 'image', 'name', 'biography')


35
class RegistrationSerializer(RegisterSerializer):
36 37 38 39

    name = serializers.CharField(max_length=255, required=False)

    captcha = serializers.CharField(max_length=2048)
Bruno Martin's avatar
Bruno Martin committed
40 41 42 43 44
    # city = serializers.PrimaryKeyRelatedField(queryset=City.objects.all(),
    #                                           allow_null=True)
    # state = serializers.PrimaryKeyRelatedField(queryset=Region.objects.all(),
    #                                            allow_null=True)
    # phone_number = serializers.CharField(max_length=255, allow_null=True)
45
    origin = serializers.CharField(max_length=30, required=False, allow_blank=True)
46
    accepted_terms = serializers.BooleanField()
47 48 49 50 51 52

    def get_cleaned_data(self):
        return {
            'name': self.validated_data.get('name', ''),
            'username': self.validated_data.get('username', ''),
            'password1': self.validated_data.get('password1', ''),
53
            'email': self.validated_data.get('email', ''),
Bruno Martin's avatar
Bruno Martin committed
54 55 56
            # 'city': self.validated_data.get('city', None),
            # 'state': self.validated_data.get('state', None),
            # 'phone_number': self.validated_data.get('phone_number', ''),
57 58
            'origin': self.validated_data.get('origin', 'signup'),
            'accepted_terms': self.validated_data.get('accepted_terms', ''),
59 60
        }

61 62 63 64 65 66 67
    def validate_captcha(self, attr):
        captcha_req = requests.post('https://www.google.com/recaptcha/api/siteverify',
            data = {
                'secret': settings.RECAPTCHA_SECRET_KEY,
                'response': attr
            })
        captcha_resp = captcha_req.json()
Bruno Martin's avatar
Bruno Martin committed
68 69
        print(settings.RECAPTCHA_SECRET_KEY)
        print(captcha_resp)
70 71 72 73 74
        if not captcha_resp['success']:
            raise serializers.ValidationError(_('Invalid CAPTCHA.'))

    def custom_signup(self, request, user):
        user.name = self.cleaned_data['name']
Bruno Martin's avatar
Bruno Martin committed
75 76 77
        # user.phone_number = self.cleaned_data['phone_number']
        # user.city = self.cleaned_data['city']
        # user.state = self.cleaned_data['state']
78
        user.accepted_terms = self.cleaned_data['accepted_terms']
79 80 81
        user.origin = self.cleaned_data['origin']
        user.save()

82 83 84 85 86 87 88 89 90 91
    def save(self, request):
        adapter = get_adapter()
        user = adapter.new_user(request)
        self.cleaned_data = self.get_cleaned_data()
        adapter.save_user(request, user, self)
        self.custom_signup(request, user)
        setup_user_email(request, user, [])
        return user


92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
class PoliticalFrontSerializer(serializers.ModelSerializer):

    class Meta:
        model = PoliticalFront
        fields = ('id', 'name')


class ActivismSchoolWorkplaceSerializer(serializers.ModelSerializer):

    class Meta:
        model = ActivismSchoolWorkplace
        fields = ('id', 'name')


class CtbRoleSerializer(serializers.ModelSerializer):

    class Meta:
        model = CtbRole
        fields = ('id', 'name')


113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
class FixSocialLoginSerializer(SocialLoginSerializer):
        def validate(self, attrs):
            view = self.context.get('view')
            request = self._get_request()

            if not view:
                raise serializers.ValidationError(
                    _("View is not defined, pass it as a context variable")
                )

            adapter_class = getattr(view, 'adapter_class', None)
            if not adapter_class:
                raise serializers.ValidationError(_("Define adapter_class in view"))

            adapter = adapter_class(request)
            app = adapter.get_provider().get_app(request)

            # More info on code vs access_token
            # http://stackoverflow.com/questions/8666316/facebook-oauth-2-0-code-and-token

            # Case 1: We received the access_token
            if attrs.get('access_token'):
                access_token = attrs.get('access_token')

            # Case 2: We received the authorization code
            elif attrs.get('code'):
                self.callback_url = getattr(view, 'callback_url', None)
                self.client_class = getattr(view, 'client_class', None)

                if not self.callback_url:
                    raise serializers.ValidationError(
                        _("Define callback_url in view")
                    )
                if not self.client_class:
                    raise serializers.ValidationError(
                        _("Define client_class in view")
                    )

                code = attrs.get('code')

                provider = adapter.get_provider()
                scope = provider.get_scope(request)
                client = self.client_class(
                    request,
                    app.client_id,
                    app.secret,
                    adapter.access_token_method,
                    adapter.access_token_url,
                    self.callback_url,
                    scope
                )
                token = client.get_access_token(code)
                access_token = token['access_token']

            else:
                raise serializers.ValidationError(
                    _("Incorrect input. access_token or code is required."))

            social_token = adapter.parse_token({'access_token': access_token})
            social_token.app = app

            try:
                login = self.get_social_login(adapter, app, social_token, access_token)
                complete_social_login(request, login)
            except HTTPError:
                raise serializers.ValidationError(_('Incorrect value'))

            if not login.is_existing:
                # We have an account already signed up in a different flow
                # with the same email address: raise an exception.
                # This needs to be handled in the frontend. We can not just
                # link up the accounts due to security constraints
                if(allauth_settings.UNIQUE_EMAIL):
                    if login.user.email and get_user_model().objects.filter(
                        email=login.user.email,
                    ).exists():
                        # There is an account already
                        raise serializers.ValidationError(
                                          ("A user is already registered with this e-mail address."))

                login.lookup()
                login.save(request, connect=True)
            attrs['user'] = login.account.user

            return attrs