wagtail/wagtail/wagtailadmin/tests/test_account_management.py
2014-07-08 10:21:53 +01:00

459 lines
18 KiB
Python

from __future__ import unicode_literals
from django.test import TestCase
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User, Group, Permission
from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.core import mail
from wagtail.tests.utils import WagtailTestUtils
from wagtail.wagtailusers.models import UserProfile
class TestAuthentication(TestCase, WagtailTestUtils):
"""
This tests that users can login and logout of the admin interface
"""
def test_login_view(self):
"""
This tests that the login view responds with a login page
"""
# Get login page
response = self.client.get(reverse('wagtailadmin_login'))
# Check that the user recieved a login page
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailadmin/login.html')
def test_login_view_post(self):
"""
This posts user credentials to the login view and checks that
the user was logged in successfully
"""
# Create user to log in with
user = User.objects.create_superuser(username='test', email='test@email.com', password='password')
# Post credentials to the login page
post_data = {
'username': 'test',
'password': 'password',
}
response = self.client.post(reverse('wagtailadmin_login'), post_data)
# Check that the user was redirected to the dashboard
self.assertRedirects(response, reverse('wagtailadmin_home'))
# Check that the user was logged in
self.assertTrue('_auth_user_id' in self.client.session)
self.assertEqual(self.client.session['_auth_user_id'], User.objects.get(username='test').id)
def test_already_logged_in_redirect(self):
"""
This tests that a user who is already logged in is automatically
redirected to the admin dashboard if they try to access the login
page
"""
# Login
self.login()
# Get login page
response = self.client.get(reverse('wagtailadmin_login'))
# Check that the user was redirected to the dashboard
self.assertRedirects(response, reverse('wagtailadmin_home'))
def test_logged_in_as_non_privileged_user_doesnt_redirect(self):
"""
This tests that if the user is logged in but hasn't got permission
to access the admin, they are not redirected to the admin
This tests issue #431
"""
# Login as unprivileged user
User.objects.create(username='unprivileged', password='123')
self.client.login(username='unprivileged', password='123')
# Get login page
response = self.client.get(reverse('wagtailadmin_login'))
# Check that the user recieved a login page and was not redirected
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailadmin/login.html')
def test_logout(self):
"""
This tests that the user can logout
"""
# Login
self.login()
# Get logout page
response = self.client.get(reverse('wagtailadmin_logout'))
# Check that the user was redirected to the login page
self.assertRedirects(response, reverse('wagtailadmin_login'))
# Check that the user was logged out
self.assertFalse('_auth_user_id' in self.client.session)
def test_not_logged_in_redirect(self):
"""
This tests that a not logged in user is redirected to the
login page
"""
# Get dashboard
response = self.client.get(reverse('wagtailadmin_home'))
# Check that the user was redirected to the login page and that next was set correctly
self.assertRedirects(response, reverse('wagtailadmin_login') + '?next=' + reverse('wagtailadmin_home'))
def test_not_logged_in_redirect_default_settings(self):
"""
This does the same as the above test but checks that it
redirects to the correct place when the user has not set
the LOGIN_URL setting correctly
"""
# Get dashboard with default LOGIN_URL setting
with self.settings(LOGIN_URL='django.contrib.auth.views.login'):
response = self.client.get(reverse('wagtailadmin_home'))
# Check that the user was redirected to the login page and that next was set correctly
# Note: The user will be redirected to 'django.contrib.auth.views.login' but
# this must be the same URL as 'wagtailadmin_login'
self.assertEqual(response.status_code, 302)
self.assertRedirects(response, reverse('wagtailadmin_login') + '?next=' + reverse('wagtailadmin_home'))
class TestAccountSection(TestCase, WagtailTestUtils):
"""
This tests that the accounts section is working
"""
def setUp(self):
self.login()
def test_account_view(self):
"""
This tests that the login view responds with a login page
"""
# Get account page
response = self.client.get(reverse('wagtailadmin_account'))
# Check that the user recieved an account page
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailadmin/account/account.html')
def test_change_password_view(self):
"""
This tests that the change password view responds with a change password page
"""
# Get change password page
response = self.client.get(reverse('wagtailadmin_account_change_password'))
# Check that the user recieved a change password page
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailadmin/account/change_password.html')
def test_change_password_view_post(self):
"""
This posts a new password to the change password view and checks
that the users password was changed
"""
# Post new password to change password page
post_data = {
'new_password1': 'newpassword',
'new_password2': 'newpassword',
}
response = self.client.post(reverse('wagtailadmin_account_change_password'), post_data)
# Check that the user was redirected to the account page
self.assertRedirects(response, reverse('wagtailadmin_account'))
# Check that the password was changed
self.assertTrue(User.objects.get(username='test').check_password('newpassword'))
def test_change_password_view_post_password_mismatch(self):
"""
This posts a two passwords that don't match to the password change
view and checks that a validation error was raised
"""
# Post new password to change password page
post_data = {
'new_password1': 'newpassword',
'new_password2': 'badpassword',
}
response = self.client.post(reverse('wagtailadmin_account_change_password'), post_data)
# Check that the user wasn't redirected
self.assertEqual(response.status_code, 200)
# Check that a validation error was raised
self.assertTrue('new_password2' in response.context['form'].errors.keys())
self.assertTrue("The two password fields didn't match." in response.context['form'].errors['new_password2'])
# Check that the password was not changed
self.assertTrue(User.objects.get(username='test').check_password('password'))
def test_notification_preferences_view(self):
"""
This tests that the notification preferences view responds with the
notification preferences page
"""
# Get notification preferences page
response = self.client.get(reverse('wagtailadmin_account_notification_preferences'))
# Check that the user recieved a notification preferences page
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailadmin/account/notification_preferences.html')
def test_notification_preferences_view_post(self):
"""
This posts to the notification preferences view and checks that the
user's profile is updated
"""
# Post new values to the notification preferences page
post_data = {
'submitted_notifications': 'false',
'approved_notifications': 'false',
'rejected_notifications': 'true',
}
response = self.client.post(reverse('wagtailadmin_account_notification_preferences'), post_data)
# Check that the user was redirected to the account page
self.assertRedirects(response, reverse('wagtailadmin_account'))
profile = UserProfile.get_for_user(User.objects.get(username='test'))
# Check that the notification preferences are as submitted
self.assertFalse(profile.submitted_notifications)
self.assertFalse(profile.approved_notifications)
self.assertTrue(profile.rejected_notifications)
class TestAccountManagementForNonModerator(TestCase, WagtailTestUtils):
"""
Tests of reduced-functionality for editors
"""
def setUp(self):
# Create a non-moderator user
self.submitter = User.objects.create_user('submitter', 'submitter@example.com', 'password')
self.submitter.groups.add(Group.objects.get(name='Editors'))
self.client.login(username=self.submitter.username, password='password')
def test_notification_preferences_form_is_reduced_for_non_moderators(self):
"""
This tests that a user without publish permissions is not shown the
notification preference for 'submitted' items
"""
response = self.client.get(reverse('wagtailadmin_account_notification_preferences'))
self.assertIn('approved_notifications', response.context['form'].fields.keys())
self.assertIn('rejected_notifications', response.context['form'].fields.keys())
self.assertNotIn('submitted_notifications', response.context['form'].fields.keys())
class TestAccountManagementForAdminOnlyUser(TestCase, WagtailTestUtils):
"""
Tests for users with no edit/publish permissions at all
"""
def setUp(self):
# Create a non-moderator user
admin_only_group = Group.objects.create(name='Admin Only')
admin_only_group.permissions.add(Permission.objects.get(codename='access_admin'))
self.admin_only_user = User.objects.create_user('admin_only_user', 'admin_only_user@example.com', 'password')
self.admin_only_user.groups.add(admin_only_group)
self.client.login(username=self.admin_only_user.username, password='password')
def test_notification_preferences_view_redirects_for_admin_only_users(self):
"""
Test that the user is not shown the notification preferences view but instead
redirected to the account page
"""
response = self.client.get(reverse('wagtailadmin_account_notification_preferences'))
self.assertRedirects(response, reverse('wagtailadmin_account'))
def test_notification_preferences_link_not_shown_for_admin_only_users(self):
"""
Test that the user is not even shown the link to the notification
preferences view
"""
response = self.client.get(reverse('wagtailadmin_account'))
self.assertEqual(response.context['show_notification_preferences'], False)
self.assertNotContains(response, reverse('wagtailadmin_account_notification_preferences'))
# safety check that checking for absence/presence of urls works
self.assertContains(response, reverse('wagtailadmin_home'))
class TestPasswordReset(TestCase, WagtailTestUtils):
"""
This tests that the password reset is working
"""
def setUp(self):
# Create a user
User.objects.create_superuser(username='test', email='test@email.com', password='password')
def test_password_reset_view(self):
"""
This tests that the password reset view returns a password reset page
"""
# Get password reset page
response = self.client.get(reverse('password_reset'))
# Check that the user recieved a password reset page
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailadmin/account/password_reset/form.html')
def test_password_reset_view_post(self):
"""
This posts an email address to the password reset view and
checks that a password reset email was sent
"""
# Post email address to password reset view
post_data = {
'email': 'test@email.com',
}
response = self.client.post(reverse('password_reset'), post_data)
# Check that the user was redirected to the done page
self.assertRedirects(response, reverse('password_reset_done'))
# Check that a password reset email was sent to the user
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].to, ['test@email.com'])
self.assertEqual(mail.outbox[0].subject, "Password reset")
def test_password_reset_view_post_unknown_email(self):
"""
This posts an unknown email address to the password reset view and
checks that the password reset form raises a validation error
"""
post_data = {
'email': 'unknown@email.com',
}
response = self.client.post(reverse('password_reset'), post_data)
# Check that the user wasn't redirected
self.assertEqual(response.status_code, 200)
# Check that a validation error was raised
self.assertTrue('__all__' in response.context['form'].errors.keys())
self.assertTrue("This email address is not recognised." in response.context['form'].errors['__all__'])
# Check that an email was not sent
self.assertEqual(len(mail.outbox), 0)
def test_password_reset_view_post_invalid_email(self):
"""
This posts an incalid email address to the password reset view and
checks that the password reset form raises a validation error
"""
post_data = {
'email': 'Hello world!',
}
response = self.client.post(reverse('password_reset'), post_data)
# Check that the user wasn't redirected
self.assertEqual(response.status_code, 200)
# Check that a validation error was raised
self.assertTrue('email' in response.context['form'].errors.keys())
self.assertTrue("Enter a valid email address." in response.context['form'].errors['email'])
# Check that an email was not sent
self.assertEqual(len(mail.outbox), 0)
def setup_password_reset_confirm_tests(self):
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode
# Get user
self.user = User.objects.get(username='test')
# Generate a password reset token
self.password_reset_token = PasswordResetTokenGenerator().make_token(self.user)
# Generate a password reset uid
self.password_reset_uid = urlsafe_base64_encode(force_bytes(self.user.pk))
# Create url_args
self.url_kwargs = dict(uidb64=self.password_reset_uid, token=self.password_reset_token)
def test_password_reset_confirm_view(self):
"""
This tests that the password reset confirm view returns a password reset confirm page
"""
self.setup_password_reset_confirm_tests()
# Get password reset confirm page
response = self.client.get(reverse('password_reset_confirm', kwargs=self.url_kwargs))
# Check that the user recieved a password confirm done page
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailadmin/account/password_reset/confirm.html')
def test_password_reset_confirm_view_post(self):
"""
This posts a new password to the password reset confirm view and checks
that the users password was changed
"""
self.setup_password_reset_confirm_tests()
# Post new password to change password page
post_data = {
'new_password1': 'newpassword',
'new_password2': 'newpassword',
}
response = self.client.post(reverse('password_reset_confirm', kwargs=self.url_kwargs), post_data)
# Check that the user was redirected to the complete page
self.assertRedirects(response, reverse('password_reset_complete'))
# Check that the password was changed
self.assertTrue(User.objects.get(username='test').check_password('newpassword'))
def test_password_reset_confirm_view_post_password_mismatch(self):
"""
This posts a two passwords that don't match to the password reset
confirm view and checks that a validation error was raised
"""
self.setup_password_reset_confirm_tests()
# Post new password to change password page
post_data = {
'new_password1': 'newpassword',
'new_password2': 'badpassword',
}
response = self.client.post(reverse('password_reset_confirm', kwargs=self.url_kwargs), post_data)
# Check that the user wasn't redirected
self.assertEqual(response.status_code, 200)
# Check that a validation error was raised
self.assertTrue('new_password2' in response.context['form'].errors.keys())
self.assertTrue("The two password fields didn't match." in response.context['form'].errors['new_password2'])
# Check that the password was not changed
self.assertTrue(User.objects.get(username='test').check_password('password'))
def test_password_reset_done_view(self):
"""
This tests that the password reset done view returns a password reset done page
"""
# Get password reset done page
response = self.client.get(reverse('password_reset_done'))
# Check that the user recieved a password reset done page
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailadmin/account/password_reset/done.html')
def test_password_reset_complete_view(self):
"""
This tests that the password reset complete view returns a password reset complete page
"""
# Get password reset complete page
response = self.client.get(reverse('password_reset_complete'))
# Check that the user recieved a password reset complete page
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailadmin/account/password_reset/complete.html')