from django.contrib.auth import get_user_model from django.core import mail from django.urls import reverse from django.utils import six from django.utils.six.moves import range from misago.acl.models import Role from misago.admin.testutils import AdminTestCase from misago.categories.models import Category from misago.threads.testutils import post_thread, reply_thread from misago.users.models import Ban, Rank UserModel = get_user_model() class UserAdminViewsTests(AdminTestCase): AJAX_HEADER = {'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'} def test_link_registered(self): """admin index view contains users link""" response = self.client.get(reverse('misago:admin:index')) self.assertContains(response, reverse('misago:admin:users:accounts:index')) def test_list_view(self): """users list view returns 200""" response = self.client.get( reverse('misago:admin:users:accounts:index')) self.assertEqual(response.status_code, 302) response = self.client.get(response['location']) self.assertEqual(response.status_code, 200) self.assertContains(response, self.user.username) def test_list_search(self): """users list is searchable""" response = self.client.get( reverse('misago:admin:users:accounts:index')) self.assertEqual(response.status_code, 302) link_base = response['location'] response = self.client.get(link_base) self.assertEqual(response.status_code, 200) user_a = UserModel.objects.create_user('Tyrael', 't123@test.com', 'pass123') user_b = UserModel.objects.create_user('Tyrion', 't321@test.com', 'pass123') user_c = UserModel.objects.create_user('Karen', 't432@test.com', 'pass123') # Search both response = self.client.get('%s&username=tyr' % link_base) self.assertEqual(response.status_code, 200) self.assertContains(response, user_a.username) self.assertContains(response, user_b.username) # Search tyrion response = self.client.get('%s&username=tyrion' % link_base) self.assertEqual(response.status_code, 200) self.assertNotContains(response, user_a.username) self.assertContains(response, user_b.username) # Search tyrael response = self.client.get('%s&email=t123@test.com' % link_base) self.assertEqual(response.status_code, 200) self.assertContains(response, user_a.username) self.assertNotContains(response, user_b.username) # Search disabled user_c.is_active = False user_c.save() response = self.client.get('%s&disabled=1' % link_base) self.assertEqual(response.status_code, 200) self.assertNotContains(response, user_a.username) self.assertNotContains(response, user_b.username) self.assertContains(response, '%s' % user_c.username) def test_mass_activation(self): """users list activates multiple users""" user_pks = [] for i in range(10): test_user = UserModel.objects.create_user( 'Bob%s' % i, 'bob%s@test.com' % i, 'pass123', requires_activation=1 ) user_pks.append(test_user.pk) response = self.client.post( reverse('misago:admin:users:accounts:index'), data={'action': 'activate', 'selected_items': user_pks}) self.assertEqual(response.status_code, 302) inactive_qs = UserModel.objects.filter(id__in=user_pks, requires_activation=1) self.assertEqual(inactive_qs.count(), 0) self.assertIn("has been activated", mail.outbox[0].subject) def test_mass_ban(self): """users list bans multiple users""" user_pks = [] for i in range(10): test_user = UserModel.objects.create_user( 'Bob%s' % i, 'bob%s@test.com' % i, 'pass123', requires_activation=1 ) user_pks.append(test_user.pk) response = self.client.post( reverse('misago:admin:users:accounts:index'), data={'action': 'ban', 'selected_items': user_pks}) self.assertEqual(response.status_code, 200) response = self.client.post( reverse('misago:admin:users:accounts:index'), data={ 'action': 'ban', 'selected_items': user_pks, 'ban_type': [ 'usernames', 'emails', 'domains', 'ip', 'ip_first', 'ip_two' ], 'finalize': '' }) self.assertEqual(response.status_code, 302) self.assertEqual(Ban.objects.count(), 24) def test_mass_delete_accounts(self): """users list deletes users""" user_pks = [] for i in range(10): test_user = UserModel.objects.create_user( 'Bob%s' % i, 'bob%s@test.com' % i, 'pass123', requires_activation=1 ) user_pks.append(test_user.pk) response = self.client.post( reverse('misago:admin:users:accounts:index'), data={'action': 'delete_accounts', 'selected_items': user_pks}) self.assertEqual(response.status_code, 302) self.assertEqual(UserModel.objects.count(), 1) def test_mass_delete_all(self): """users list deletes users and their content""" user_pks = [] for i in range(10): test_user = UserModel.objects.create_user( 'Bob%s' % i, 'bob%s@test.com' % i, 'pass123', requires_activation=1 ) user_pks.append(test_user.pk) response = self.client.post( reverse('misago:admin:users:accounts:index'), data={'action': 'delete_accounts', 'selected_items': user_pks}) self.assertEqual(response.status_code, 302) self.assertEqual(UserModel.objects.count(), 1) def test_new_view(self): """new user view creates account""" response = self.client.get( reverse('misago:admin:users:accounts:new')) self.assertEqual(response.status_code, 200) default_rank = Rank.objects.get_default() authenticated_role = Role.objects.get(special_role='authenticated') response = self.client.post(reverse('misago:admin:users:accounts:new'), data={ 'username': 'Bawww', 'rank': six.text_type(default_rank.pk), 'roles': six.text_type(authenticated_role.pk), 'email': 'reg@stered.com', 'new_password': 'pass123', 'staff_level': '0' }) self.assertEqual(response.status_code, 302) UserModel.objects.get_by_username('Bawww') UserModel.objects.get_by_email('reg@stered.com') def test_edit_view(self): """edit user view changes account""" test_user = UserModel.objects.create_user('Bob', 'bob@test.com', 'pass123') test_link = reverse('misago:admin:users:accounts:edit', kwargs={'pk': test_user.pk}) response = self.client.get(test_link) self.assertEqual(response.status_code, 200) response = self.client.post(test_link, data={ 'username': 'Bawww', 'rank': six.text_type(test_user.rank_id), 'roles': six.text_type(test_user.roles.all()[0].pk), 'email': 'reg@stered.com', 'new_password': 'newpass123', 'staff_level': '0', 'signature': 'Hello world!', 'is_signature_locked': '1', 'is_hiding_presence': '0', 'limits_private_thread_invites_to': '0', 'signature_lock_staff_message': 'Staff message', 'signature_lock_user_message': 'User message', 'subscribe_to_started_threads': '2', 'subscribe_to_replied_threads': '2', }) self.assertEqual(response.status_code, 302) updated_user = UserModel.objects.get(pk=test_user.pk) self.assertTrue(updated_user.check_password('newpass123')) self.assertEqual(updated_user.username, 'Bawww') self.assertEqual(updated_user.slug, 'bawww') UserModel.objects.get_by_username('Bawww') UserModel.objects.get_by_email('reg@stered.com') def test_edit_dont_change_username(self): """ If username wasn't changed, don't touch user's username, slug or history This is regression test for issue #640 """ test_user = UserModel.objects.create_user('Bob', 'bob@test.com', 'pass123') test_link = reverse('misago:admin:users:accounts:edit', kwargs={'pk': test_user.pk}) response = self.client.get(test_link) self.assertEqual(response.status_code, 200) response = self.client.post(test_link, data={ 'username': 'Bob', 'rank': six.text_type(test_user.rank_id), 'roles': six.text_type(test_user.roles.all()[0].pk), 'email': 'reg@stered.com', 'new_password': 'pass123', 'signature': 'Hello world!', 'is_signature_locked': '1', 'is_hiding_presence': '0', 'limits_private_thread_invites_to': '0', 'signature_lock_staff_message': 'Staff message', 'signature_lock_user_message': 'User message', 'subscribe_to_started_threads': '2', 'subscribe_to_replied_threads': '2', }) self.assertEqual(response.status_code, 302) updated_user = UserModel.objects.get(pk=test_user.pk) self.assertEqual(updated_user.username, 'Bob') self.assertEqual(updated_user.slug, 'bob') self.assertEqual(updated_user.namechanges.count(), 0) def test_edit_make_admin(self): """edit user view allows super admin to make other user admin""" test_user = UserModel.objects.create_user('Bob', 'bob@test.com', 'pass123') test_link = reverse('misago:admin:users:accounts:edit', kwargs={'pk': test_user.pk}) response = self.client.get(test_link) self.assertContains(response, 'id="id_is_staff_1"') self.assertContains(response, 'id="id_is_superuser_1"') response = self.client.post(test_link, data={ 'username': 'Bawww', 'rank': six.text_type(test_user.rank_id), 'roles': six.text_type(test_user.roles.all()[0].pk), 'email': 'reg@stered.com', 'new_password': 'pass123', 'is_staff': '1', 'is_superuser': '0', 'signature': 'Hello world!', 'is_signature_locked': '1', 'is_hiding_presence': '0', 'limits_private_thread_invites_to': '0', 'signature_lock_staff_message': 'Staff message', 'signature_lock_user_message': 'User message', 'subscribe_to_started_threads': '2', 'subscribe_to_replied_threads': '2', }) self.assertEqual(response.status_code, 302) updated_user = UserModel.objects.get(pk=test_user.pk) self.assertTrue(updated_user.is_staff) self.assertFalse(updated_user.is_superuser) def test_edit_make_superadmin_admin(self): """edit user view allows super admin to make other user super admin""" test_user = UserModel.objects.create_user('Bob', 'bob@test.com', 'pass123') test_link = reverse('misago:admin:users:accounts:edit', kwargs={'pk': test_user.pk}) response = self.client.get(test_link) self.assertContains(response, 'id="id_is_staff_1"') self.assertContains(response, 'id="id_is_superuser_1"') response = self.client.post(test_link, data={ 'username': 'Bawww', 'rank': six.text_type(test_user.rank_id), 'roles': six.text_type(test_user.roles.all()[0].pk), 'email': 'reg@stered.com', 'new_password': 'pass123', 'is_staff': '0', 'is_superuser': '1', 'signature': 'Hello world!', 'is_signature_locked': '1', 'is_hiding_presence': '0', 'limits_private_thread_invites_to': '0', 'signature_lock_staff_message': 'Staff message', 'signature_lock_user_message': 'User message', 'subscribe_to_started_threads': '2', 'subscribe_to_replied_threads': '2', }) self.assertEqual(response.status_code, 302) updated_user = UserModel.objects.get(pk=test_user.pk) self.assertFalse(updated_user.is_staff) self.assertTrue(updated_user.is_superuser) def test_edit_cant_make_admin(self): """edit user view forbids admins from making other admins""" self.user.is_superuser = False self.user.save() test_user = UserModel.objects.create_user('Bob', 'bob@test.com', 'pass123') test_link = reverse('misago:admin:users:accounts:edit', kwargs={'pk': test_user.pk}) response = self.client.get(test_link) self.assertNotContains(response, 'id="id_is_staff_1"') self.assertNotContains(response, 'id="id_is_superuser_1"') response = self.client.post(test_link, data={ 'username': 'Bawww', 'rank': six.text_type(test_user.rank_id), 'roles': six.text_type(test_user.roles.all()[0].pk), 'email': 'reg@stered.com', 'new_password': 'pass123', 'is_staff': '1', 'is_superuser': '1', 'signature': 'Hello world!', 'is_signature_locked': '1', 'is_hiding_presence': '0', 'limits_private_thread_invites_to': '0', 'signature_lock_staff_message': 'Staff message', 'signature_lock_user_message': 'User message', 'subscribe_to_started_threads': '2', 'subscribe_to_replied_threads': '2', }) self.assertEqual(response.status_code, 302) updated_user = UserModel.objects.get(pk=test_user.pk) self.assertFalse(updated_user.is_staff) self.assertFalse(updated_user.is_superuser) def test_edit_disable_user(self): """edit user view allows admin to disable non admin""" self.user.is_superuser = False self.user.save() test_user = UserModel.objects.create_user('Bob', 'bob@test.com', 'pass123') test_link = reverse('misago:admin:users:accounts:edit', kwargs={'pk': test_user.pk}) response = self.client.get(test_link) self.assertContains(response, 'id="id_is_active_1"') self.assertContains(response, 'id="id_is_active_staff_message"') response = self.client.post(test_link, data={ 'username': 'Bawww', 'rank': six.text_type(test_user.rank_id), 'roles': six.text_type(test_user.roles.all()[0].pk), 'email': 'reg@stered.com', 'new_password': 'pass123', 'is_staff': '0', 'is_superuser': '0', 'signature': 'Hello world!', 'is_signature_locked': '1', 'is_hiding_presence': '0', 'limits_private_thread_invites_to': '0', 'signature_lock_staff_message': 'Staff message', 'signature_lock_user_message': 'User message', 'subscribe_to_started_threads': '2', 'subscribe_to_replied_threads': '2', 'is_active': '0', 'is_active_staff_message': "Disabled in test!" }) self.assertEqual(response.status_code, 302) updated_user = UserModel.objects.get(pk=test_user.pk) self.assertFalse(updated_user.is_active) self.assertEqual(updated_user.is_active_staff_message, "Disabled in test!") def test_edit_superuser_disable_admin(self): """edit user view allows admin to disable non admin""" self.user.is_superuser = True self.user.save() test_user = UserModel.objects.create_user('Bob', 'bob@test.com', 'pass123') test_user.is_staff = True test_user.save() test_link = reverse('misago:admin:users:accounts:edit', kwargs={'pk': test_user.pk}) response = self.client.get(test_link) self.assertContains(response, 'id="id_is_active_1"') self.assertContains(response, 'id="id_is_active_staff_message"') response = self.client.post(test_link, data={ 'username': 'Bawww', 'rank': six.text_type(test_user.rank_id), 'roles': six.text_type(test_user.roles.all()[0].pk), 'email': 'reg@stered.com', 'new_password': 'pass123', 'is_staff': '1', 'is_superuser': '0', 'signature': 'Hello world!', 'is_signature_locked': '1', 'is_hiding_presence': '0', 'limits_private_thread_invites_to': '0', 'signature_lock_staff_message': 'Staff message', 'signature_lock_user_message': 'User message', 'subscribe_to_started_threads': '2', 'subscribe_to_replied_threads': '2', 'is_active': '0', 'is_active_staff_message': "Disabled in test!" }) self.assertEqual(response.status_code, 302) updated_user = UserModel.objects.get(pk=test_user.pk) self.assertFalse(updated_user.is_active) self.assertEqual(updated_user.is_active_staff_message, "Disabled in test!") def test_edit_admin_cant_disable_admin(self): """edit user view disallows admin to disable admin""" self.user.is_superuser = False self.user.save() test_user = UserModel.objects.create_user('Bob', 'bob@test.com', 'pass123') test_user.is_staff = True test_user.save() test_link = reverse('misago:admin:users:accounts:edit', kwargs={'pk': test_user.pk}) response = self.client.get(test_link) self.assertNotContains(response, 'id="id_is_active_1"') self.assertNotContains(response, 'id="id_is_active_staff_message"') response = self.client.post(test_link, data={ 'username': 'Bawww', 'rank': six.text_type(test_user.rank_id), 'roles': six.text_type(test_user.roles.all()[0].pk), 'email': 'reg@stered.com', 'new_password': 'pass123', 'is_staff': '1', 'is_superuser': '0', 'signature': 'Hello world!', 'is_signature_locked': '1', 'is_hiding_presence': '0', 'limits_private_thread_invites_to': '0', 'signature_lock_staff_message': 'Staff message', 'signature_lock_user_message': 'User message', 'subscribe_to_started_threads': '2', 'subscribe_to_replied_threads': '2', 'is_active': '0', 'is_active_staff_message': "Disabled in test!" }) self.assertEqual(response.status_code, 302) updated_user = UserModel.objects.get(pk=test_user.pk) self.assertTrue(updated_user.is_active) self.assertFalse(updated_user.is_active_staff_message) def test_delete_threads_view(self): """delete user threads view deletes threads""" test_user = UserModel.objects.create_user('Bob', 'bob@test.com', 'pass123') test_link = reverse('misago:admin:users:accounts:delete-threads', kwargs={'pk': test_user.pk}) category = Category.objects.all_categories()[:1][0] [post_thread(category, poster=test_user) for _ in range(10)] response = self.client.post(test_link, **self.AJAX_HEADER) self.assertEqual(response.status_code, 200) response_dict = response.json() self.assertEqual(response_dict['deleted_count'], 10) self.assertFalse(response_dict['is_completed']) response = self.client.post(test_link, **self.AJAX_HEADER) self.assertEqual(response.status_code, 200) response_dict = response.json() self.assertEqual(response_dict['deleted_count'], 0) self.assertTrue(response_dict['is_completed']) def test_delete_posts_view(self): """delete user posts view deletes posts""" test_user = UserModel.objects.create_user('Bob', 'bob@test.com', 'pass123') test_link = reverse('misago:admin:users:accounts:delete-posts', kwargs={'pk': test_user.pk}) category = Category.objects.all_categories()[:1][0] thread = post_thread(category) [reply_thread(thread, poster=test_user) for _ in range(10)] response = self.client.post(test_link, **self.AJAX_HEADER) self.assertEqual(response.status_code, 200) response_dict = response.json() self.assertEqual(response_dict['deleted_count'], 10) self.assertFalse(response_dict['is_completed']) response = self.client.post(test_link, **self.AJAX_HEADER) self.assertEqual(response.status_code, 200) response_dict = response.json() self.assertEqual(response_dict['deleted_count'], 0) self.assertTrue(response_dict['is_completed']) def test_delete_account_view(self): """delete user account view deletes user account""" test_user = UserModel.objects.create_user('Bob', 'bob@test.com', 'pass123') test_link = reverse('misago:admin:users:accounts:delete-account', kwargs={'pk': test_user.pk}) response = self.client.post(test_link, **self.AJAX_HEADER) self.assertEqual(response.status_code, 200) response_dict = response.json() self.assertTrue(response_dict['is_completed'])