def test_user_creation_race_condition(self): """ If a user double clicks a 'login' button or something, causing 2 threads to be authenticating the same user at the same time, ensure it doesn't die. """ email = "*****@*****.**" user_id = "111111111100000000001" original_user_get = get_user_model().objects.get def crazy_user_get_patch(*args, **kwargs): """ Patch for User.objects.get which simulates another thread creating the same user immedidately after this is called (by doing it as part of this function). """ User = get_user_model() try: return original_user_get(*args, **kwargs) # We patched .get() except User.DoesNotExist: # This is horrible, but... the backend first tries get() by username and then tries # get() by email, and we only want to create our user after that second call if kwargs.keys() != ['username']: User.objects.create_user(username=user_id, email=email) raise backend = AppEngineUserAPIBackend() google_user = users.User(email, _user_id=user_id) user_class_path = "djangae.contrib.gauth.datastore.models.GaeDatastoreUser.objects.get" with sleuth.switch(user_class_path, crazy_user_get_patch): backend.authenticate(google_user)
def test_authenticate_creates_user_object(self): """ If `authenticate` is called with valid credentials then a User object should be created """ User = get_user_model() self.assertEqual(User.objects.count(), 0) email = '*****@*****.**' google_user = users.User(email, _user_id='111111111100000000001') backend = AppEngineUserAPIBackend() user = backend.authenticate(google_user=google_user,) self.assertEqual(user.email, email.lower()) self.assertEqual(User.objects.count(), 1) # Calling authenticate again with the same credentials should not create another user user2 = backend.authenticate(google_user=google_user) self.assertEqual(user.pk, user2.pk)
def test_authenticate_creates_user_object(self): """ If `authenticate` is called with valid credentials then a User object should be created """ User = get_user_model() self.assertEqual(User.objects.count(), 0) email = '*****@*****.**' google_user = users.User(email, _user_id='111111111100000000001') backend = AppEngineUserAPIBackend() user = backend.authenticate(google_user=google_user, ) self.assertEqual(user.email, email.lower()) self.assertEqual(User.objects.count(), 1) # Calling authenticate again with the same credentials should not create another user user2 = backend.authenticate(google_user=google_user) self.assertEqual(user.pk, user2.pk)
def test_force_user_pre_creation(self): User = get_user_model() self.assertEqual(User.objects.count(), 0) google_user = users.User('*****@*****.**', _user_id='111111111100000000001') backend = AppEngineUserAPIBackend() self.assertIsNone(backend.authenticate(google_user=google_user,)) self.assertEqual(User.objects.count(), 0) # superusers don't need pre-creation of User object. self.assertEqual(User.objects.count(), 0) with sleuth.switch('google.appengine.api.users.is_current_user_admin', lambda: True): user = backend.authenticate(google_user=google_user,) self.assertEqual(User.objects.count(), 1) self.assertEquals(User.objects.get(), user)
def test_user_pre_creation(self): """ User objects for Google-Accounts-based users should be able to be pre-created in DB and then matched by email address when they log in. """ User = get_user_model() backend = AppEngineUserAPIBackend() email = '*****@*****.**' # Pre-create our user User.objects.pre_create_google_user(email) # Now authenticate this user via the Google Accounts API google_user = users.User(email=email, _user_id='111111111100000000001') user = backend.authenticate(google_user=google_user) # Check things self.assertEqual(user.email, email) self.assertIsNotNone(user.last_login) self.assertFalse(user.has_usable_password())
def test_user_pre_creation_no_create_unknown(self): """ User objects for Google-Accounts-based users should be able to be pre-created in DB and then matched by email address when they log in - even if unknown users are not allowed. """ User = get_user_model() backend = AppEngineUserAPIBackend() email = '*****@*****.**' # Pre-create our user User.objects.pre_create_google_user(email) # Now authenticate this user via the Google Accounts API google_user = users.User(email=email, _user_id='111111111100000000001') user = backend.authenticate(google_user=google_user) # Check things self.assertEqual(user.email, email) self.assertIsNotNone(user.last_login) self.assertFalse(user.has_usable_password())
def test_invalid_credentials_cause_typeerror(self): """ If the `authenticate` method is passed credentials which it doesn't understand then Django expects it to raise a TypeError. """ backend = AppEngineUserAPIBackend() credentials = {'username': '******', 'password': '******'} self.assertRaises(TypeError, backend.authenticate, **credentials)
def test_middleware_resaves_email(self): # Create user with uppercased email email = '*****@*****.**' google_user = users.User(email, _user_id='111111111100000000001') backend = AppEngineUserAPIBackend() user = backend.authenticate(google_user=google_user,) # Normalize_email should save a user with lowercase email self.assertEqual(user.email, email.lower()) # Run AuthenticationMiddleware, if email are mismatched with sleuth.switch('djangae.contrib.gauth.middleware.users.get_current_user', lambda: google_user): request = HttpRequest() SessionMiddleware().process_request(request) # Make the damn sessions work middleware = AuthenticationMiddleware() middleware.process_request(request) # Middleware should resave to uppercased email, keeping user the same self.assertEqual(request.user.email, email) self.assertEqual(request.user.pk, user.pk)
def test_user_pre_created_users_are_authenticated_case_insensitively(self): """ When a user is pre-created their email address may not have been saved with the same upper/lower case-ness as that which they end up logging in with. So the matching needs to be done case insensitively. """ User = get_user_model() backend = AppEngineUserAPIBackend() email = '*****@*****.**' # Pre-create our user User.objects.pre_create_google_user(email) # Now authenticate this user via the Google Accounts API google_user = users.User(email='*****@*****.**', _user_id='111111111100000000001') user = backend.authenticate(google_user=google_user) # Check things self.assertEqual(user.username, '111111111100000000001') # We expect the email address to have been updated to the one which they logged in with self.assertEqual(user.email, google_user.email()) self.assertIsNotNone(user.last_login) self.assertFalse(user.has_usable_password())
def test_user_id_switch(self): """ Users sometimes login with the same email, but a different google user id. We handle those cases by blanking out the email on the old user object and creating a new one with the new user id. """ email = '*****@*****.**' old_user = users.User(email=email, _user_id='111111111100000000001') new_user = users.User(email=email, _user_id='111111111100000000002') User = get_user_model() backend = AppEngineUserAPIBackend() # Authenticate 1st time, creating the user user1 = backend.authenticate(google_user=old_user) self.assertEqual(user1.email, email) self.assertTrue(user1.username.endswith('1')) self.assertEqual(1, User.objects.count()) # Now another user logs in using the same email user2 = backend.authenticate(google_user=new_user) self.assertEqual(user2.email, email) self.assertTrue(user2.username.endswith('2')) self.assertEqual(2, User.objects.count()) # The old account is kept around, but the email is blanked user1 = User.objects.get(pk=user1.pk) self.assertEqual(user1.email, None)
def test_user_id_switch(self): """ Users sometimes login with the same email, but a different google user id. We handle those cases by blanking out the email on the old user object and creating a new one with the new user id. """ email = '*****@*****.**' old_user = users.User(email=email, _user_id='111111111100000000001') new_user = users.User(email=email, _user_id='111111111100000000002') User = get_user_model() backend = AppEngineUserAPIBackend() # Authenticate 1st time, creating the user user1 = backend.authenticate(google_user=old_user) self.assertEqual(user1.email, email) self.assertTrue(user1.username.endswith('1')) self.assertEqual(1, User.objects.count()) # Now another user logs in using the same email user2 = backend.authenticate(google_user=new_user) self.assertEqual(user2.email, email) self.assertTrue(user2.username.endswith('2')) self.assertEqual(2, User.objects.count()) # The old account is kept around, but the email is blanked user1 = User.objects.get(pk=user1.pk) self.assertEqual(user1.email, "")