0001-api_views-finish-implementing-the-registration-API-w.patch
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 |
- |