Skip to content

Commit bf2240d

Browse files
author
Matthew Fisher
committed
feat(controller): add username parameter to /v1/auth/passwd
1 parent 6af57b2 commit bf2240d

3 files changed

Lines changed: 89 additions & 5 deletions

File tree

api/fixtures/test_auth.json

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,41 @@
1616
"email": "autotest@deis.io",
1717
"date_joined": "2013-05-10T16:08:09.357Z"
1818
}
19+
},
20+
{
21+
"pk": 8,
22+
"model": "auth.user",
23+
"fields": {
24+
"username": "autotest2",
25+
"first_name": "Otto",
26+
"last_name": "Test",
27+
"is_active": true,
28+
"is_superuser": false,
29+
"is_staff": false,
30+
"last_login": "2013-05-10T16:08:09.357Z",
31+
"groups": [],
32+
"user_permissions": [],
33+
"password": "pbkdf2_sha256$10000$5Uoq7dl61vnN$gQhDpc2q2Rkn16VdPC+pNNEQcKpy+LGe29Zkad+2/m4=",
34+
"email": "autotest@deis.io",
35+
"date_joined": "2013-05-10T16:08:09.357Z"
36+
}
37+
},
38+
{
39+
"pk": 9,
40+
"model": "auth.user",
41+
"fields": {
42+
"username": "autotest3",
43+
"first_name": "Otto",
44+
"last_name": "Test",
45+
"is_active": true,
46+
"is_superuser": false,
47+
"is_staff": false,
48+
"last_login": "2013-05-10T16:08:09.357Z",
49+
"groups": [],
50+
"user_permissions": [],
51+
"password": "pbkdf2_sha256$10000$5Uoq7dl61vnN$gQhDpc2q2Rkn16VdPC+pNNEQcKpy+LGe29Zkad+2/m4=",
52+
"email": "autotest@deis.io",
53+
"date_joined": "2013-05-10T16:08:09.357Z"
54+
}
1955
}
2056
]

api/tests/test_auth.py

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ class AuthTest(TestCase):
2121

2222
"""Tests user registration, authentication and authorization"""
2323

24+
def setUp(self):
25+
self.admin = User.objects.get(username='autotest')
26+
self.admin_token = Token.objects.get(user=self.admin).key
27+
self.user1 = User.objects.get(username='autotest2')
28+
self.user1_token = Token.objects.get(user=self.user1).key
29+
self.user2 = User.objects.get(username='autotest3')
30+
self.user2_token = Token.objects.get(user=self.user2).key
31+
2432
def test_auth(self):
2533
"""
2634
Test that a user can register using the API, login and logout
@@ -98,10 +106,6 @@ def test_auth_registration_admin_only_fails_if_not_admin(self):
98106
@override_settings(REGISTRATION_MODE="admin_only")
99107
def test_auth_registration_admin_only_works(self):
100108
"""test that a superuser can register when registration is admin only."""
101-
102-
user = User.objects.get(username='autotest')
103-
token = Token.objects.get(user=user)
104-
105109
url = '/v1/auth/register'
106110

107111
username, password = 'newuser_by_admin', 'password'
@@ -119,7 +123,7 @@ def test_auth_registration_admin_only_works(self):
119123
'is_staff': True,
120124
}
121125
response = self.client.post(url, json.dumps(submit), content_type='application/json',
122-
HTTP_AUTHORIZATION='token {}'.format(token))
126+
HTTP_AUTHORIZATION='token {}'.format(self.admin_token))
123127

124128
self.assertEqual(response.status_code, 201)
125129
for key in response.data:
@@ -236,3 +240,41 @@ def test_passwd(self):
236240
response = self.client.post(url, data=payload,
237241
content_type='application/x-www-form-urlencoded')
238242
self.assertEqual(response.status_code, 200)
243+
244+
def test_change_user_passwd(self):
245+
"""
246+
Test that an administrator can change a user's password, while a regular user cannot.
247+
"""
248+
# change password
249+
url = '/v1/auth/passwd'
250+
old_password = self.user1.password
251+
new_password = 'password'
252+
submit = {
253+
'username': self.user1.username,
254+
'password': old_password,
255+
'new_password': new_password,
256+
}
257+
response = self.client.post(url, json.dumps(submit), content_type='application/json',
258+
HTTP_AUTHORIZATION='token {}'.format(self.admin_token))
259+
self.assertEqual(response.status_code, 400)
260+
# test login with old password
261+
url = '/v1/auth/login/'
262+
payload = urllib.urlencode({'username': self.user1.username, 'password': old_password})
263+
response = self.client.post(url, data=payload,
264+
content_type='application/x-www-form-urlencoded')
265+
self.assertEqual(response.status_code, 400)
266+
# test login with new password
267+
payload = urllib.urlencode({'username': self.user1.username, 'password': new_password})
268+
response = self.client.post(url, data=payload,
269+
content_type='application/x-www-form-urlencoded')
270+
self.assertEqual(response.status_code, 200)
271+
# try to change back password with a regular user
272+
submit['password'], submit['new_password'] = submit['new_password'], submit['password']
273+
url = '/v1/auth/passwd'
274+
response = self.client.post(url, json.dumps(submit), content_type='application/json',
275+
HTTP_AUTHORIZATION='token {}'.format(self.user2_token))
276+
self.assertEqual(response.status_code, 403)
277+
# however, targeting yourself should be fine.
278+
response = self.client.post(url, json.dumps(submit), content_type='application/json',
279+
HTTP_AUTHORIZATION='token {}'.format(self.user1_token))
280+
self.assertEqual(response.status_code, 200)

api/views.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ def get_object(self):
3737

3838
def passwd(self, request, **kwargs):
3939
obj = self.get_object()
40+
if request.data.get('username'):
41+
# if you "accidentally" target yourself, that should be fine
42+
if obj.username == request.data['username'] or obj.is_superuser:
43+
obj = get_object_or_404(User, username=request.data['username'])
44+
else:
45+
raise PermissionDenied()
4046
if not obj.check_password(request.data['password']):
4147
return Response({'detail': 'Current password does not match'},
4248
status=status.HTTP_400_BAD_REQUEST)

0 commit comments

Comments
 (0)