github.com/chasestarr/deis@v1.13.5-0.20170519182049-1d9e59fbdbfc/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 # user can not be deleted if it has an app attached to it 225 response = self.client.post( 226 '/v1/apps', 227 HTTP_AUTHORIZATION='token {}'.format(self.admin_token) 228 ) 229 self.assertEqual(response.status_code, 201) 230 app_id = response.data['id'] # noqa 231 self.assertIn('id', response.data) 232 233 response = self.client.delete(url, json.dumps({'username': str(self.admin)}), 234 content_type='application/json', 235 HTTP_AUTHORIZATION='token {}'.format(self.admin_token)) 236 self.assertEqual(response.status_code, 409) 237 238 def test_passwd(self): 239 """Test that a registered user can change the password.""" 240 # test registration workflow 241 username, password = 'newuser', 'password' 242 first_name, last_name = 'Otto', 'Test' 243 email = 'autotest@deis.io' 244 submit = { 245 'username': username, 246 'password': password, 247 'first_name': first_name, 248 'last_name': last_name, 249 'email': email, 250 } 251 url = '/v1/auth/register' 252 response = self.client.post(url, json.dumps(submit), content_type='application/json') 253 self.assertEqual(response.status_code, 201) 254 # change password 255 url = '/v1/auth/passwd' 256 user = User.objects.get(username=username) 257 token = Token.objects.get(user=user).key 258 submit = { 259 'password': 'password2', 260 'new_password': password, 261 } 262 response = self.client.post(url, json.dumps(submit), content_type='application/json', 263 HTTP_AUTHORIZATION='token {}'.format(token)) 264 self.assertEqual(response.status_code, 400) 265 self.assertEqual(response.data, {'detail': 'Current password does not match'}) 266 self.assertEqual(response.get('content-type'), 'application/json') 267 submit = { 268 'password': password, 269 'new_password': 'password2', 270 } 271 response = self.client.post(url, json.dumps(submit), content_type='application/json', 272 HTTP_AUTHORIZATION='token {}'.format(token)) 273 self.assertEqual(response.status_code, 200) 274 # test login with old password 275 url = '/v1/auth/login/' 276 payload = urllib.urlencode({'username': username, 'password': password}) 277 response = self.client.post(url, data=payload, 278 content_type='application/x-www-form-urlencoded') 279 self.assertEqual(response.status_code, 400) 280 # test login with new password 281 payload = urllib.urlencode({'username': username, 'password': 'password2'}) 282 response = self.client.post(url, data=payload, 283 content_type='application/x-www-form-urlencoded') 284 self.assertEqual(response.status_code, 200) 285 286 def test_change_user_passwd(self): 287 """ 288 Test that an administrator can change a user's password, while a regular user cannot. 289 """ 290 # change password 291 url = '/v1/auth/passwd' 292 old_password = self.user1.password 293 new_password = 'password' 294 submit = { 295 'username': self.user1.username, 296 'new_password': new_password, 297 } 298 response = self.client.post(url, json.dumps(submit), content_type='application/json', 299 HTTP_AUTHORIZATION='token {}'.format(self.admin_token)) 300 self.assertEqual(response.status_code, 200) 301 # test login with old password 302 url = '/v1/auth/login/' 303 payload = urllib.urlencode({'username': self.user1.username, 'password': old_password}) 304 response = self.client.post(url, data=payload, 305 content_type='application/x-www-form-urlencoded') 306 self.assertEqual(response.status_code, 400) 307 # test login with new password 308 payload = urllib.urlencode({'username': self.user1.username, 'password': new_password}) 309 response = self.client.post(url, data=payload, 310 content_type='application/x-www-form-urlencoded') 311 self.assertEqual(response.status_code, 200) 312 # Non-admins can't change another user's password 313 submit['password'], submit['new_password'] = submit['new_password'], old_password 314 url = '/v1/auth/passwd' 315 response = self.client.post(url, json.dumps(submit), content_type='application/json', 316 HTTP_AUTHORIZATION='token {}'.format(self.user2_token)) 317 self.assertEqual(response.status_code, 403) 318 # change back password with a regular user 319 response = self.client.post(url, json.dumps(submit), content_type='application/json', 320 HTTP_AUTHORIZATION='token {}'.format(self.user1_token)) 321 self.assertEqual(response.status_code, 200) 322 # test login with new password 323 url = '/v1/auth/login/' 324 payload = urllib.urlencode({'username': self.user1.username, 'password': old_password}) 325 response = self.client.post(url, data=payload, 326 content_type='application/x-www-form-urlencoded') 327 self.assertEqual(response.status_code, 200) 328 329 def test_regenerate(self): 330 """ Test that token regeneration works""" 331 332 url = '/v1/auth/tokens/' 333 334 response = self.client.post(url, '{}', content_type='application/json', 335 HTTP_AUTHORIZATION='token {}'.format(self.admin_token)) 336 337 self.assertEqual(response.status_code, 200) 338 self.assertNotEqual(response.data['token'], self.admin_token) 339 340 self.admin_token = Token.objects.get(user=self.admin) 341 342 response = self.client.post(url, '{"username" : "autotest2"}', 343 content_type='application/json', 344 HTTP_AUTHORIZATION='token {}'.format(self.admin_token)) 345 346 self.assertEqual(response.status_code, 200) 347 self.assertNotEqual(response.data['token'], self.user1_token) 348 349 response = self.client.post(url, '{"all" : "true"}', 350 content_type='application/json', 351 HTTP_AUTHORIZATION='token {}'.format(self.admin_token)) 352 self.assertEqual(response.status_code, 200) 353 354 response = self.client.post(url, '{}', content_type='application/json', 355 HTTP_AUTHORIZATION='token {}'.format(self.admin_token)) 356 357 self.assertEqual(response.status_code, 401)