(reusing code previously written for the community lists) instead of the a custom MD5 scheme, add tests of all views, rewrite custom form handling code to use plain forms and ensure that the data is properly validated and errors visible in the UI. Move help texts on the Person form up to the model. - Legacy-Id: 11136
262 lines
10 KiB
Python
262 lines
10 KiB
Python
# -*- coding: utf-8 -*-
|
|
import os, shutil
|
|
from urlparse import urlsplit
|
|
|
|
from pyquery import PyQuery
|
|
|
|
from django.core.urlresolvers import reverse as urlreverse
|
|
from django.contrib.auth.models import User
|
|
from django.conf import settings
|
|
|
|
from ietf.utils.test_utils import TestCase, login_testing_unauthorized
|
|
from ietf.utils.test_data import make_test_data
|
|
from ietf.utils.mail import outbox, empty_outbox
|
|
from ietf.person.models import Person, Email
|
|
from ietf.group.models import Group, Role, RoleName
|
|
|
|
class IetfAuthTests(TestCase):
|
|
def setUp(self):
|
|
self.saved_htpasswd_file = settings.HTPASSWD_FILE
|
|
self.htpasswd_dir = os.path.abspath("tmp-htpasswd-dir")
|
|
os.mkdir(self.htpasswd_dir)
|
|
settings.HTPASSWD_FILE = os.path.join(self.htpasswd_dir, "htpasswd")
|
|
open(settings.HTPASSWD_FILE, 'a').close() # create empty file
|
|
self.saved_htdigest_realm = getattr(settings, "HTDIGEST_REALM", None)
|
|
settings.HTDIGEST_REALM = "test-realm"
|
|
|
|
def tearDown(self):
|
|
shutil.rmtree(self.htpasswd_dir)
|
|
settings.HTPASSWD_FILE = self.saved_htpasswd_file
|
|
settings.HTDIGEST_REALM = self.saved_htdigest_realm
|
|
|
|
def test_index(self):
|
|
self.assertEqual(self.client.get(urlreverse("ietf.ietfauth.views.index")).status_code, 200)
|
|
|
|
def test_login_and_logout(self):
|
|
make_test_data()
|
|
|
|
# try logging in without a next
|
|
r = self.client.get(urlreverse("account_login"))
|
|
self.assertEqual(r.status_code, 200)
|
|
|
|
r = self.client.post(urlreverse("account_login"), {"username":"plain", "password":"plain+password"})
|
|
self.assertEqual(r.status_code, 302)
|
|
self.assertEqual(urlsplit(r["Location"])[2], "/accounts/profile/")
|
|
|
|
# try logging out
|
|
r = self.client.get(urlreverse("account_logout"))
|
|
self.assertEqual(r.status_code, 200)
|
|
|
|
r = self.client.get(urlreverse("account_profile"))
|
|
self.assertEqual(r.status_code, 302)
|
|
self.assertEqual(urlsplit(r["Location"])[2], "/accounts/login/")
|
|
|
|
# try logging in with a next
|
|
r = self.client.post(urlreverse("account_login") + "?next=/foobar", {"username":"plain", "password":"plain+password"})
|
|
self.assertEqual(r.status_code, 302)
|
|
self.assertEqual(urlsplit(r["Location"])[2], "/foobar")
|
|
|
|
def extract_confirm_url(self, confirm_email):
|
|
# dig out confirm_email link
|
|
msg = confirm_email.get_payload(decode=True)
|
|
line_start = "http"
|
|
confirm_url = None
|
|
for line in msg.split("\n"):
|
|
if line.strip().startswith(line_start):
|
|
confirm_url = line.strip()
|
|
self.assertTrue(confirm_url)
|
|
|
|
return confirm_url
|
|
|
|
def username_in_htpasswd_file(self, username):
|
|
with open(settings.HTPASSWD_FILE) as f:
|
|
for l in f:
|
|
if l.startswith(username + ":" + settings.HTDIGEST_REALM):
|
|
return True
|
|
return False
|
|
|
|
def test_create_account(self):
|
|
make_test_data()
|
|
|
|
url = urlreverse('create_account')
|
|
|
|
# get
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
|
|
# register email
|
|
email = 'new-account@example.com'
|
|
empty_outbox()
|
|
r = self.client.post(url, { 'email': email })
|
|
self.assertEqual(r.status_code, 200)
|
|
self.assertEqual(len(outbox), 1)
|
|
|
|
# go to confirm page
|
|
confirm_url = self.extract_confirm_url(outbox[-1])
|
|
r = self.client.get(confirm_url)
|
|
self.assertEqual(r.status_code, 200)
|
|
|
|
# password mismatch
|
|
r = self.client.post(confirm_url, { 'password': 'secret', 'password_confirmation': 'nosecret' })
|
|
self.assertEqual(r.status_code, 200)
|
|
self.assertEqual(User.objects.filter(username=email).count(), 0)
|
|
|
|
# confirm
|
|
r = self.client.post(confirm_url, { 'password': 'secret', 'password_confirmation': 'secret' })
|
|
self.assertEqual(r.status_code, 200)
|
|
self.assertEqual(User.objects.filter(username=email).count(), 1)
|
|
self.assertEqual(Person.objects.filter(user__username=email).count(), 1)
|
|
self.assertEqual(Email.objects.filter(person__user__username=email).count(), 1)
|
|
|
|
self.assertTrue(self.username_in_htpasswd_file(email))
|
|
|
|
def test_profile(self):
|
|
make_test_data()
|
|
|
|
username = "plain"
|
|
email_address = Email.objects.filter(person__user__username=username).first().address
|
|
|
|
url = urlreverse('account_profile')
|
|
login_testing_unauthorized(self, username, url)
|
|
|
|
|
|
# get
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertEqual(len(q('.form-control-static:contains("%s")' % username)), 1)
|
|
self.assertEqual(len(q('[name="active_emails"][value="%s"][checked]' % email_address)), 1)
|
|
|
|
base_data = {
|
|
"name": u"Test Nãme",
|
|
"ascii": u"Test Name",
|
|
"ascii_short": u"T. Name",
|
|
"address": "Test address",
|
|
"affiliation": "Test Org",
|
|
"active_emails": email_address,
|
|
}
|
|
|
|
# edit details - faulty ASCII
|
|
faulty_ascii = base_data.copy()
|
|
faulty_ascii["ascii"] = u"Test Nãme"
|
|
r = self.client.post(url, faulty_ascii)
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertTrue(len(q("form .has-error")) > 0)
|
|
|
|
# edit details
|
|
r = self.client.post(url, base_data)
|
|
self.assertEqual(r.status_code, 200)
|
|
person = Person.objects.get(user__username=username)
|
|
self.assertEqual(person.name, u"Test Nãme")
|
|
self.assertEqual(person.ascii, u"Test Name")
|
|
self.assertEqual(Person.objects.filter(alias__name=u"Test Name", user__username=username).count(), 1)
|
|
self.assertEqual(Person.objects.filter(alias__name=u"Test Nãme", user__username=username).count(), 1)
|
|
self.assertEqual(Email.objects.filter(address=email_address, person__user__username=username, active=True).count(), 1)
|
|
|
|
# deactivate address
|
|
without_email_address = { k: v for k, v in base_data.iteritems() if k != "active_emails" }
|
|
|
|
r = self.client.post(url, without_email_address)
|
|
self.assertEqual(r.status_code, 200)
|
|
self.assertEqual(Email.objects.filter(address=email_address, person__user__username="plain", active=True).count(), 0)
|
|
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertEqual(len(q('[name="%s"][checked]' % email_address)), 0)
|
|
|
|
# add email address
|
|
empty_outbox()
|
|
new_email_address = "plain2@example.com"
|
|
with_new_email_address = base_data.copy()
|
|
with_new_email_address["new_email"] = new_email_address
|
|
r = self.client.post(url, with_new_email_address)
|
|
self.assertEqual(r.status_code, 200)
|
|
self.assertEqual(len(outbox), 1)
|
|
|
|
# confirm new email address
|
|
confirm_url = self.extract_confirm_url(outbox[-1])
|
|
r = self.client.get(confirm_url)
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertEqual(len(q('[name="action"][value=confirm]')), 1)
|
|
|
|
r = self.client.post(confirm_url, { "action": "confirm" })
|
|
self.assertEqual(r.status_code, 200)
|
|
self.assertEqual(Email.objects.filter(address=new_email_address, person__user__username=username, active=1).count(), 1)
|
|
|
|
# check that we can't re-add it - that would give a duplicate
|
|
r = self.client.get(confirm_url)
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertEqual(len(q('[name="action"][value="confirm"]')), 0)
|
|
|
|
# change role email
|
|
role = Role.objects.create(
|
|
person=Person.objects.get(user__username=username),
|
|
email=Email.objects.get(address=email_address),
|
|
name=RoleName.objects.get(slug="chair"),
|
|
group=Group.objects.get(acronym="mars"),
|
|
)
|
|
|
|
role_email_input_name = "role_%s-email" % role.pk
|
|
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertEqual(len(q('[name="%s"]' % role_email_input_name)), 1)
|
|
|
|
with_changed_role_email = base_data.copy()
|
|
with_changed_role_email["active_emails"] = new_email_address
|
|
with_changed_role_email[role_email_input_name] = new_email_address
|
|
r = self.client.post(url, with_changed_role_email)
|
|
self.assertEqual(r.status_code, 200)
|
|
updated_roles = Role.objects.filter(person=role.person, name=role.name, group=role.group)
|
|
self.assertEqual(len(updated_roles), 1)
|
|
self.assertEqual(updated_roles[0].email_id, new_email_address)
|
|
|
|
|
|
def test_reset_password(self):
|
|
url = urlreverse('password_reset')
|
|
|
|
user = User.objects.create(username="someone@example.com", email="someone@example.com")
|
|
user.set_password("forgotten")
|
|
user.save()
|
|
p = Person.objects.create(name="Some One", ascii="Some One", user=user)
|
|
Email.objects.create(address=user.username, person=p)
|
|
|
|
# get
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
|
|
# ask for reset, wrong username
|
|
r = self.client.post(url, { 'email': "nobody@example.com" })
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertTrue(len(q("form .has-error")) > 0)
|
|
|
|
# ask for reset
|
|
empty_outbox()
|
|
r = self.client.post(url, { 'email': user.username })
|
|
self.assertEqual(r.status_code, 200)
|
|
self.assertEqual(len(outbox), 1)
|
|
|
|
# go to change password page
|
|
confirm_url = self.extract_confirm_url(outbox[-1])
|
|
r = self.client.get(confirm_url)
|
|
self.assertEqual(r.status_code, 200)
|
|
|
|
# password mismatch
|
|
r = self.client.post(confirm_url, { 'password': 'secret', 'password_confirmation': 'nosecret' })
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertTrue(len(q("form .has-error")) > 0)
|
|
|
|
# confirm
|
|
r = self.client.post(confirm_url, { 'password': 'secret', 'password_confirmation': 'secret' })
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertEqual(len(q("form .has-error")), 0)
|
|
self.assertTrue(self.username_in_htpasswd_file(user.username))
|