Projet

Général

Profil

0001-api_views-finish-implementing-the-registration-API-w.patch

Benjamin Dauvergne, 02 octobre 2015 09:37

Télécharger (13,6 ko)

Voir les différences:

Subject: [PATCH] api_views: finish implementing the registration API with no
 mail validation (fixes #8480)

You have to specify at least username, email or first name and last
name.
 src/authentic2/api_views.py      | 137 +++++++++++++++++++++++++--------------
 src/authentic2/tests/test_all.py |  60 ++++++++++++++---
 2 files changed, 139 insertions(+), 58 deletions(-)
src/authentic2/api_views.py
16 16
from rest_framework import authentication, permissions, status
17 17
from rest_framework.exceptions import PermissionDenied
18 18

  
19
from .custom_user.models import User
19 20
from . import utils, decorators
20 21

  
21 22

  
......
28 29

  
29 30
class RegistrationSerializer(serializers.Serializer):
30 31
    '''Register RPC payload'''
31
    email = serializers.EmailField()
32
    email = serializers.EmailField(
33
        required=False, allow_blank=True)
32 34
    ou = serializers.SlugRelatedField(
33 35
        queryset=get_ou_model().objects.all(),
34 36
        slug_field='slug',
......
43 45
        required=False, allow_null=True)
44 46
    no_email_validation = serializers.BooleanField(
45 47
        required=False)
46
    return_url = serializers.URLField()
48
    return_url = serializers.URLField(required=False, allow_blank=True)
47 49

  
48 50
    def validate(self, data):
49 51
        request = self.context.get('request')
52
        ou = data.get('ou')
50 53
        if request:
51 54
            perm = 'custom_user.add_user'
52
            if data['ou']:
55
            if ou:
53 56
                authorized = request.user.has_ou_perm(perm, data['ou'])
54 57
            else:
55 58
                authorized = request.user.has_perm(perm)
......
58 61
                                                    'to create users in '
59 62
                                                    'this ou'))
60 63
        User = get_user_model()
61
        if data['ou'] and data['ou'].email_is_unique and \
62
                User.objects.filter(ou=data['ou'],
63
                                   email__iexact=data['email']).exists():
64
            raise serializers.ValidationError(
65
                _('You already have an account'))
66
        if data['ou'] and data['ou'].username_is_unique and not \
67
                'username' in data:
68
            raise serializers.ValidationError(
69
                _('Username is required in this ou'))
70
        if data['ou'] and data['ou'].username_is_unique and \
71
               User.objects.filter(ou=data['ou'],
72
                                   username=data['username']).exists():
73
            raise serializers.ValidationError(
64
        if ou:
65
            if ou.email_is_unique and \
66
                    User.objects.filter(ou=ou,
67
                                       email__iexact=data['email']).exists():
68
                raise serializers.ValidationError(
69
                    _('You already have an account'))
70
            if ou.username_is_unique and not \
71
                    'username' in data:
72
                raise serializers.ValidationError(
73
                    _('Username is required in this ou'))
74
            if ou.username_is_unique and \
75
                   User.objects.filter(ou=data['ou'],
76
                                       username=data['username']).exists():
77
                raise serializers.ValidationError(
74 78
                _('You already have an account'))
75 79
        return data
76 80

  
......
109 113

  
110 114
    def rpc(self, request, serializer):
111 115
        validated_data = serializer.validated_data
112
        data = serializer.data
113
        email = validated_data['email']
114
        token = utils.get_hex_uuid()[:16]
115
        final_return_url = utils.make_url(validated_data['return_url'],
116
                                          params={'token': token})
117

  
118
        registration_template = ['authentic2/activation_email']
119
        if validated_data['ou']:
120
            registration_template.insert(0, 'authentic2/activation_email_%s' %
121
                                         validated_data['ou'].slug)
116
        email = validated_data.get('email')
122 117
        registration_data = {}
123 118
        for field in ('first_name', 'last_name', 'password', 'username', 'ou'):
124 119
            if field in validated_data:
......
126 121
                    registration_data[field] = validated_data[field].pk
127 122
                else:
128 123
                    registration_data[field] = validated_data[field]
129

  
130 124
        ctx = {
131 125
            'registration_data': registration_data,
132 126
        }
133
        try:
134
            utils.send_registration_mail(self.request, email,
135
                                         registration_template,
136
                                         next_url=final_return_url,
137
                                         ctx=ctx,
138
                                         **registration_data)
139
        except smtplib.SMTPException, e:
140
            response = {
141
                'result': 0,
142
                'errors': {
143
                    '__all__': ['Mail sending failed']
144
                },
145
                'exception': unicode(e),
146
            }
147
            response_status = status.HTTP_503_SERVICE_UNAVAILABLE
127

  
128
        if email and not validated_data.get('no_email_validation'):
129
            token = utils.get_hex_uuid()[:16]
130
            if not validated_data.get('return_url'):
131
                response = {
132
                    'result': 0,
133
                    'errors': {
134
                        'return_url': ['Required']
135
                    },
136
                    'exception': unicode(e),
137
                }
138
                response_status = status.HTTP_400_BAD_REQUEST
139
                return response, response_status
140
            final_return_url = utils.make_url(validated_data['return_url'],
141
                                              params={'token': token})
142

  
143
            registration_template = ['authentic2/activation_email']
144
            if validated_data['ou']:
145
                registration_template.insert(0, 'authentic2/activation_email_%s' %
146
                                             validated_data['ou'].slug)
147

  
148
            try:
149
                utils.send_registration_mail(self.request, email,
150
                                             registration_template,
151
                                             next_url=final_return_url,
152
                                             ctx=ctx,
153
                                             **registration_data)
154
            except smtplib.SMTPException, e:
155
                response = {
156
                    'result': 0,
157
                    'errors': {
158
                        '__all__': ['Mail sending failed']
159
                    },
160
                    'exception': unicode(e),
161
                }
162
                response_status = status.HTTP_503_SERVICE_UNAVAILABLE
163
            else:
164
                response = {
165
                    'result': 1,
166
                    'token': token,
167
                }
168
                response_status = status.HTTP_202_ACCEPTED
148 169
        else:
149
            response = {
150
                'result': 1,
151
                'token': token,
152
                'request': data,
153
            }
154
            response_status = status.HTTP_202_ACCEPTED
170
            username = validated_data.get('username')
171
            first_name = validated_data.get('first_name')
172
            last_name = validated_data.get('last_name')
173
            password = validated_data.get('password')
174
            if not email and \
175
               not username and \
176
               not (first_name and last_name):
177
                response = {
178
                    'result': 0,
179
                    'errors': {
180
                        '__all__': ['You must set at least a username, an email or a first name and a last name']
181
                    },
182
                }
183
                response_status = status.HTTP_400_BAD_REQUEST
184
            else:
185
                new_user = User(email=email, username=username,
186
                                first_name=first_name, last_name=last_name)
187
                if password:
188
                    new_user.set_password(password)
189
                new_user.save()
190
                validated_data['uuid'] = new_user.uuid
191
                response = {
192
                    'result': 1,
193
                    'user': validated_data,
194
                }
195
                response_status = status.HTTP_201_CREATED
155 196
        return response, response_status
156 197

  
157 198
register = Register.as_view()
src/authentic2/tests/test_all.py
23 23
from django_rbac.utils import get_role_model, get_ou_model
24 24

  
25 25
from authentic2 import hashers, utils, models, attribute_kinds
26
from authentic2.custom_user.models import User
26 27

  
27 28
from . import Authentic2TestCase, get_response_form
28 29

  
......
786 787
        self.assertEqual(response.data['result'], 1)
787 788
        self.assertIn('token', response.data)
788 789
        token = response.data['token']
789
        self.assertIn('request', response.data)
790
        self.assertEqual(response.data['request'], payload)
791 790
        self.assertEqual(len(mail.outbox), outbox_level+1)
792 791

  
793 792
        # User side
......
902 901
        self.assertEqual(response.data['result'], 1)
903 902
        self.assertIn('token', response.data)
904 903
        token = response.data['token']
905
        self.assertIn('request', response.data)
906
        self.assertEqual(response.data['request'], payload)
907 904
        self.assertEqual(len(mail.outbox), outbox_level+1)
908 905
        outbox_level = len(mail.outbox)
909 906

  
......
916 913
        self.assertEqual(response2.data['result'], 1)
917 914
        self.assertIn('token', response2.data)
918 915
        token2 = response2.data['token']
919
        self.assertIn('request', response2.data)
920
        self.assertEqual(response2.data['request'], payload)
921 916
        self.assertEqual(len(mail.outbox), outbox_level+1)
922 917

  
923 918
        # User side - user click on first email
......
1033 1028
        self.assertEqual(response.data['result'], 1)
1034 1029
        self.assertIn('token', response.data)
1035 1030
        token = response.data['token']
1036
        self.assertIn('request', response.data)
1037
        self.assertEqual(response.data['request'], payload)
1038 1031
        self.assertEqual(len(mail.outbox), outbox_level+1)
1039 1032
        outbox_level = len(mail.outbox)
1040 1033

  
......
1048 1041
        self.assertEqual(response2.data['result'], 1)
1049 1042
        self.assertIn('token', response2.data)
1050 1043
        token2 = response2.data['token']
1051
        self.assertIn('request', response2.data)
1052
        self.assertEqual(response2.data['request'], payload)
1053 1044
        self.assertEqual(len(mail.outbox), outbox_level+1)
1054 1045

  
1055 1046
        # User side - user click on first email
......
1128 1119
        self.assertTrue(User.objects.get(username='john.doe')
1129 1120
                        .check_password('password2'))
1130 1121

  
1122
    def test_register_no_email_validation(self):
1123
        client = test.APIClient()
1124
        password = '12XYab'
1125
        username = 'john.doe'
1126
        email = 'john.doe@example.com'
1127
        first_name = 'John'
1128
        last_name = 'Doe'
1129
        return_url = 'http://sp.org/register/'
1130

  
1131
        # invalid payload
1132
        payload = {
1133
            'last_name': last_name,
1134
        }
1135
        client.credentials(HTTP_AUTHORIZATION='Basic %s' % self.reguser3_cred)
1136
        response = client.post(reverse('a2-api-register'),
1137
                               content_type='application/json',
1138
                               data=json.dumps(payload))
1139
        self.assertEquals(response.status_code, status.HTTP_400_BAD_REQUEST)
1140
        self.assertIn('errors', response.data)
1141
        self.assertEquals(response.data['result'], 0)
1142
        self.assertEquals(response.data['errors'], {
1143
            '__all__': ['You must set at least a username, an email or a first name and a last name'],
1144
        })
1145
        payload = {
1146
            'username': username,
1147
            'email': email,
1148
            'first_name': first_name,
1149
            'last_name': last_name,
1150
            'password': password,
1151
            'no_email_validation': True,
1152
        }
1153
        response = client.post(reverse('a2-api-register'),
1154
                               content_type='application/json',
1155
                               data=json.dumps(payload))
1156
        self.assertEquals(response.status_code, status.HTTP_201_CREATED)
1157
        self.assertEquals(response.data['result'], 1)
1158
        self.assertEquals(response.data['user']['username'], username)
1159
        self.assertEquals(response.data['user']['email'], email)
1160
        self.assertEquals(response.data['user']['first_name'], first_name)
1161
        self.assertEquals(response.data['user']['last_name'], last_name)
1162
        self.assertEquals(response.data['user']['password'], password)
1163
        self.assertEquals(User.objects.count(), 4)
1164
        user = User.objects.latest('id')
1165
        self.assertEquals(user.username, username)
1166
        self.assertEquals(user.email, email)
1167
        self.assertEquals(user.first_name, first_name)
1168
        self.assertEquals(user.last_name, last_name)
1169
        self.assertTrue(user.check_password(password))
1170

  
1131 1171

  
1132 1172
class PasswordResetTest(Authentic2TestCase):
1133 1173
    def setUp(self):
1134
-