github.com/jiasir/deis@v1.12.2/controller/api/tests/test_auth.py (about) 1 """ 2 Unit tests for the Deis api app. 3 4 Run the tests with "./manage.py test api" 5 """ 6 7 from __future__ import unicode_literals 8 9 import json 10 import urllib 11 12 from django.contrib.auth.models import User 13 from django.test import TestCase 14 from django.test.utils import override_settings 15 from rest_framework.authtoken.models import Token 16 17 18 class AuthTest(TestCase): 19 20 fixtures = ['test_auth.json'] 21 22 """Tests user registration, authentication and authorization""" 23 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 32 def test_auth(self): 33 """ 34 Test that a user can register using the API, login and logout 35 """ 36 # test registration workflow 37 username, password = 'newuser', 'password' 38 first_name, last_name = 'Otto', 'Test' 39 email = 'autotest@deis.io' 40 submit = { 41 'username': username, 42 'password': password, 43 'first_name': first_name, 44 'last_name': last_name, 45 'email': email, 46 # try to abuse superuser/staff level perms (not the first signup!) 47 'is_superuser': True, 48 'is_staff': True, 49 } 50 url = '/v1/auth/register' 51 response = self.client.post(url, json.dumps(submit), content_type='application/json') 52 self.assertEqual(response.status_code, 201) 53 for key in response.data: 54 self.assertIn(key, ['id', 'last_login', 'is_superuser', 'username', 'first_name', 55 'last_name', 'email', 'is_active', 'is_superuser', 'is_staff', 56 'date_joined', 'groups', 'user_permissions']) 57 expected = { 58 'username': username, 59 'email': email, 60 'first_name': first_name, 61 'last_name': last_name, 62 'is_active': True, 63 'is_superuser': False, 64 'is_staff': False 65 } 66 self.assertDictContainsSubset(expected, response.data) 67 # test login 68 url = '/v1/auth/login/' 69 payload = urllib.urlencode({'username': username, 'password': password}) 70 response = self.client.post(url, data=payload, 71 content_type='application/x-www-form-urlencoded') 72 self.assertEqual(response.status_code, 200) 73 74 @override_settings(REGISTRATION_MODE="disabled") 75 def test_auth_registration_disabled(self): 76 """test that a new user cannot register when registration is disabled.""" 77 url = '/v1/auth/register' 78 submit = { 79 'username': 'testuser', 80 'password': 'password', 81 'first_name': 'test', 82 'last_name': 'user', 83 'email': 'test@user.com', 84 'is_superuser': False, 85 'is_staff': False, 86 } 87 response = self.client.post(url, json.dumps(submit), content_type='application/json') 88 self.assertEqual(response.status_code, 403) 89 90 @override_settings(REGISTRATION_MODE="admin_only") 91 def test_auth_registration_admin_only_fails_if_not_admin(self): 92 """test that a non superuser cannot register when registration is admin only.""" 93 url = '/v1/auth/register' 94 submit = { 95 'username': 'testuser', 96 'password': 'password', 97 'first_name': 'test', 98 'last_name': 'user', 99 'email': 'test@user.com', 100 'is_superuser': False, 101 'is_staff': False, 102 } 103 response = self.client.post(url, json.dumps(submit), content_type='application/json') 104 self.assertEqual(response.status_code, 403) 105 106 @override_settings(REGISTRATION_MODE="admin_only") 107 def test_auth_registration_admin_only_works(self): 108 """test that a superuser can register when registration is admin only.""" 109 url = '/v1/auth/register' 110 111 username, password = 'newuser_by_admin', 'password' 112 first_name, last_name = 'Otto', 'Test' 113 email = 'autotest@deis.io' 114 115 submit = { 116 'username': username, 117 'password': password, 118 'first_name': first_name, 119 'last_name': last_name, 120 'email': email, 121 # try to abuse superuser/staff level perms (not the first signup!) 122 'is_superuser': True, 123 'is_staff': True, 124 } 125 response = self.client.post(url, json.dumps(submit), content_type='application/json', 126 HTTP_AUTHORIZATION='token {}'.format(self.admin_token)) 127 128 self.assertEqual(response.status_code, 201) 129 for key in response.data: 130 self.assertIn(key, ['id', 'last_login', 'is_superuser', 'username', 'first_name', 131 'last_name', 'email', 'is_active', 'is_superuser', 'is_staff', 132 'date_joined', 'groups', 'user_permissions']) 133 expected = { 134 'username': username, 135 'email': email, 136 'first_name': first_name, 137 'last_name': last_name, 138 'is_active': True, 139 'is_superuser': False, 140 'is_staff': False 141 } 142 self.assertDictContainsSubset(expected, response.data) 143 # test login 144 url = '/v1/auth/login/' 145 payload = urllib.urlencode({'username': username, 'password': password}) 146 response = self.client.post(url, data=payload, 147 content_type='application/x-www-form-urlencoded') 148 self.assertEqual(response.status_code, 200) 149 150 @override_settings(REGISTRATION_MODE="not_a_mode") 151 def test_auth_registration_fails_with_nonexistant_mode(self): 152 """test that a registration should fail with a nonexistant mode""" 153 url = '/v1/auth/register' 154 submit = { 155 'username': 'testuser', 156 'password': 'password', 157 'first_name': 'test', 158 'last_name': 'user', 159 'email': 'test@user.com', 160 'is_superuser': False, 161 'is_staff': False, 162 } 163 164 try: 165 self.client.post(url, json.dumps(submit), content_type='application/json') 166 except Exception, e: 167 self.assertEqual(str(e), 'not_a_mode is not a valid registation mode') 168 169 def test_cancel(self): 170 """Test that a registered user can cancel her account.""" 171 # test registration workflow 172 username, password = 'newuser', 'password' 173 submit = { 174 'username': username, 175 'password': password, 176 'first_name': 'Otto', 177 'last_name': 'Test', 178 'email': 'autotest@deis.io', 179 # try to abuse superuser/staff level perms 180 'is_superuser': True, 181 'is_staff': True, 182 } 183 184 other_username, other_password = 'newuser2', 'password' 185 other_submit = { 186 'username': other_username, 187 'password': other_password, 188 'first_name': 'Test', 189 'last_name': 'Tester', 190 'email': 'autotest-2@deis.io', 191 'is_superuser': False, 192 'is_staff': False, 193 } 194 url = '/v1/auth/register' 195 response = self.client.post(url, json.dumps(submit), content_type='application/json') 196 self.assertEqual(response.status_code, 201) 197 198 # cancel the account 199 url = '/v1/auth/cancel' 200 user = User.objects.get(username=username) 201 token = Token.objects.get(user=user).key 202 response = self.client.delete(url, 203 HTTP_AUTHORIZATION='token {}'.format(token)) 204 self.assertEqual(response.status_code, 204) 205 206 url = '/v1/auth/register' 207 response = self.client.post(url, json.dumps(other_submit), content_type='application/json') 208 self.assertEqual(response.status_code, 201) 209 210 # normal user can't delete another user 211 url = '/v1/auth/cancel' 212 other_user = User.objects.get(username=other_username) 213 other_token = Token.objects.get(user=other_user).key 214 response = self.client.delete(url, json.dumps({'username': self.admin.username}), 215 content_type='application/json', 216 HTTP_AUTHORIZATION='token {}'.format(other_token)) 217 self.assertEqual(response.status_code, 403) 218 219 # admin can delete another user 220 response = self.client.delete(url, json.dumps({'username': other_username}), 221 content_type='application/json', 222 HTTP_AUTHORIZATION='token {}'.format(self.admin_token)) 223 self.assertEqual(response.status_code, 204) 224 225 def test_passwd(self): 226 """Test that a registered user can change the password.""" 227 # test registration workflow 228 username, password = 'newuser', 'password' 229 first_name, last_name = 'Otto', 'Test' 230 email = 'autotest@deis.io' 231 submit = { 232 'username': username, 233 'password': password, 234 'first_name': first_name, 235 'last_name': last_name, 236 'email': email, 237 } 238 url = '/v1/auth/register' 239 response = self.client.post(url, json.dumps(submit), content_type='application/json') 240 self.assertEqual(response.status_code, 201) 241 # change password 242 url = '/v1/auth/passwd' 243 user = User.objects.get(username=username) 244 token = Token.objects.get(user=user).key 245 submit = { 246 'password': 'password2', 247 'new_password': password, 248 } 249 response = self.client.post(url, json.dumps(submit), content_type='application/json', 250 HTTP_AUTHORIZATION='token {}'.format(token)) 251 self.assertEqual(response.status_code, 400) 252 self.assertEqual(response.data, {'detail': 'Current password does not match'}) 253 self.assertEqual(response.get('content-type'), 'application/json') 254 submit = { 255 'password': password, 256 'new_password': 'password2', 257 } 258 response = self.client.post(url, json.dumps(submit), content_type='application/json', 259 HTTP_AUTHORIZATION='token {}'.format(token)) 260 self.assertEqual(response.status_code, 200) 261 # test login with old password 262 url = '/v1/auth/login/' 263 payload = urllib.urlencode({'username': username, 'password': password}) 264 response = self.client.post(url, data=payload, 265 content_type='application/x-www-form-urlencoded') 266 self.assertEqual(response.status_code, 400) 267 # test login with new password 268 payload = urllib.urlencode({'username': username, 'password': 'password2'}) 269 response = self.client.post(url, data=payload, 270 content_type='application/x-www-form-urlencoded') 271 self.assertEqual(response.status_code, 200) 272 273 def test_change_user_passwd(self): 274 """ 275 Test that an administrator can change a user's password, while a regular user cannot. 276 """ 277 # change password 278 url = '/v1/auth/passwd' 279 old_password = self.user1.password 280 new_password = 'password' 281 submit = { 282 'username': self.user1.username, 283 'new_password': new_password, 284 } 285 response = self.client.post(url, json.dumps(submit), content_type='application/json', 286 HTTP_AUTHORIZATION='token {}'.format(self.admin_token)) 287 self.assertEqual(response.status_code, 200) 288 # test login with old password 289 url = '/v1/auth/login/' 290 payload = urllib.urlencode({'username': self.user1.username, 'password': old_password}) 291 response = self.client.post(url, data=payload, 292 content_type='application/x-www-form-urlencoded') 293 self.assertEqual(response.status_code, 400) 294 # test login with new password 295 payload = urllib.urlencode({'username': self.user1.username, 'password': new_password}) 296 response = self.client.post(url, data=payload, 297 content_type='application/x-www-form-urlencoded') 298 self.assertEqual(response.status_code, 200) 299 # Non-admins can't change another user's password 300 submit['password'], submit['new_password'] = submit['new_password'], old_password 301 url = '/v1/auth/passwd' 302 response = self.client.post(url, json.dumps(submit), content_type='application/json', 303 HTTP_AUTHORIZATION='token {}'.format(self.user2_token)) 304 self.assertEqual(response.status_code, 403) 305 # change back password with a regular user 306 response = self.client.post(url, json.dumps(submit), content_type='application/json', 307 HTTP_AUTHORIZATION='token {}'.format(self.user1_token)) 308 self.assertEqual(response.status_code, 200) 309 # test login with new password 310 url = '/v1/auth/login/' 311 payload = urllib.urlencode({'username': self.user1.username, 'password': old_password}) 312 response = self.client.post(url, data=payload, 313 content_type='application/x-www-form-urlencoded') 314 self.assertEqual(response.status_code, 200) 315 316 def test_regenerate(self): 317 """ Test that token regeneration works""" 318 319 url = '/v1/auth/tokens/' 320 321 response = self.client.post(url, '{}', content_type='application/json', 322 HTTP_AUTHORIZATION='token {}'.format(self.admin_token)) 323 324 self.assertEqual(response.status_code, 200) 325 self.assertNotEqual(response.data['token'], self.admin_token) 326 327 self.admin_token = Token.objects.get(user=self.admin) 328 329 response = self.client.post(url, '{"username" : "autotest2"}', 330 content_type='application/json', 331 HTTP_AUTHORIZATION='token {}'.format(self.admin_token)) 332 333 self.assertEqual(response.status_code, 200) 334 self.assertNotEqual(response.data['token'], self.user1_token) 335 336 response = self.client.post(url, '{"all" : "true"}', 337 content_type='application/json', 338 HTTP_AUTHORIZATION='token {}'.format(self.admin_token)) 339 self.assertEqual(response.status_code, 200) 340 341 response = self.client.post(url, '{}', content_type='application/json', 342 HTTP_AUTHORIZATION='token {}'.format(self.admin_token)) 343 344 self.assertEqual(response.status_code, 401)