github.com/spg/deis@v1.7.3/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 first_name, last_name = 'Otto', 'Test' 174 email = 'autotest@deis.io' 175 submit = { 176 'username': username, 177 'password': password, 178 'first_name': first_name, 179 'last_name': last_name, 180 'email': email, 181 # try to abuse superuser/staff level perms 182 'is_superuser': True, 183 'is_staff': True, 184 } 185 url = '/v1/auth/register' 186 response = self.client.post(url, json.dumps(submit), content_type='application/json') 187 self.assertEqual(response.status_code, 201) 188 # cancel the account 189 url = '/v1/auth/cancel' 190 user = User.objects.get(username=username) 191 token = Token.objects.get(user=user).key 192 response = self.client.delete(url, 193 HTTP_AUTHORIZATION='token {}'.format(token)) 194 self.assertEqual(response.status_code, 204) 195 196 def test_passwd(self): 197 """Test that a registered user can change the password.""" 198 # test registration workflow 199 username, password = 'newuser', 'password' 200 first_name, last_name = 'Otto', 'Test' 201 email = 'autotest@deis.io' 202 submit = { 203 'username': username, 204 'password': password, 205 'first_name': first_name, 206 'last_name': last_name, 207 'email': email, 208 } 209 url = '/v1/auth/register' 210 response = self.client.post(url, json.dumps(submit), content_type='application/json') 211 self.assertEqual(response.status_code, 201) 212 # change password 213 url = '/v1/auth/passwd' 214 user = User.objects.get(username=username) 215 token = Token.objects.get(user=user).key 216 submit = { 217 'password': 'password2', 218 'new_password': password, 219 } 220 response = self.client.post(url, json.dumps(submit), content_type='application/json', 221 HTTP_AUTHORIZATION='token {}'.format(token)) 222 self.assertEqual(response.status_code, 400) 223 self.assertEqual(response.data, {'detail': 'Current password does not match'}) 224 self.assertEqual(response.get('content-type'), 'application/json') 225 submit = { 226 'password': password, 227 'new_password': 'password2', 228 } 229 response = self.client.post(url, json.dumps(submit), content_type='application/json', 230 HTTP_AUTHORIZATION='token {}'.format(token)) 231 self.assertEqual(response.status_code, 200) 232 # test login with old password 233 url = '/v1/auth/login/' 234 payload = urllib.urlencode({'username': username, 'password': password}) 235 response = self.client.post(url, data=payload, 236 content_type='application/x-www-form-urlencoded') 237 self.assertEqual(response.status_code, 400) 238 # test login with new password 239 payload = urllib.urlencode({'username': username, 'password': 'password2'}) 240 response = self.client.post(url, data=payload, 241 content_type='application/x-www-form-urlencoded') 242 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)