226 lines
8.6 KiB
Python
226 lines
8.6 KiB
Python
# authentic2 - versatile identity manager
|
|
# Copyright (C) 2010-2019 Entr'ouvert
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify it
|
|
# under the terms of the GNU Affero General Public License as published
|
|
# by the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Affero General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
# authentic2
|
|
|
|
from django.contrib.auth.middleware import AuthenticationMiddleware
|
|
from django.contrib.messages.middleware import MessageMiddleware
|
|
from django.contrib.sessions.middleware import SessionMiddleware
|
|
from django.core import mail
|
|
from django.utils.functional import lazy
|
|
|
|
from authentic2.a2_rbac.models import OrganizationalUnit
|
|
from authentic2.journal import Journal
|
|
from authentic2.utils.lazy import lazy_join
|
|
from authentic2.utils.misc import (
|
|
authenticate,
|
|
get_authentication_events,
|
|
get_remember_cookie,
|
|
good_next_url,
|
|
login,
|
|
prepend_remember_cookie,
|
|
same_origin,
|
|
select_next_url,
|
|
send_templated_mail,
|
|
user_can_change_password,
|
|
)
|
|
|
|
|
|
def test_good_next_url(db, rf, settings):
|
|
request = rf.get('/', HTTP_HOST='example.net', **{'wsgi.url_scheme': 'https'})
|
|
assert good_next_url(request, '/admin/')
|
|
assert good_next_url(request, '/')
|
|
assert good_next_url(request, 'https://example.net/')
|
|
assert good_next_url(request, 'https://example.net:443/')
|
|
assert not good_next_url(request, 'https://example.net:4443/')
|
|
assert not good_next_url(request, 'http://example.net/')
|
|
assert not good_next_url(request, 'https://google.com/')
|
|
assert not good_next_url(request, '')
|
|
assert not good_next_url(request, None)
|
|
|
|
|
|
def test_good_next_url_backends(rf, external_redirect):
|
|
next_url, valid = external_redirect
|
|
request = rf.get('/', HTTP_HOST='example.net', **{'wsgi.url_scheme': 'https'})
|
|
if valid:
|
|
assert good_next_url(request, next_url)
|
|
else:
|
|
assert not good_next_url(request, next_url)
|
|
|
|
|
|
def test_same_origin():
|
|
assert same_origin('http://example.com/coin/', 'http://example.com/')
|
|
assert same_origin('http://example.com/coin/', 'http://example.com:80/')
|
|
assert same_origin('http://example.com:80/coin/', 'http://example.com/')
|
|
assert same_origin('http://example.com:80/coin/', 'http://.example.com/')
|
|
assert same_origin('http://example.com:80/coin/', '//example.com/')
|
|
assert not same_origin('https://example.com:80/coin/', 'http://example.com/')
|
|
assert not same_origin('http://example.com/coin/', 'http://bob.example.com/')
|
|
assert same_origin('https://example.com/coin/', 'https://example.com:443/')
|
|
assert not same_origin('https://example.com:34/coin/', 'https://example.com/')
|
|
assert same_origin('https://example.com:34/coin/', '//example.com')
|
|
assert not same_origin('https://example.com/coin/', '//example.com:34')
|
|
assert same_origin('https://example.com:443/coin/', 'https://example.com/')
|
|
assert same_origin('https://example.com:34/coin/', '//example.com')
|
|
|
|
|
|
def test_select_next_url(db, rf, settings):
|
|
request = rf.get('/register/', data={'next': '/admin/'})
|
|
assert select_next_url(request, '/') == '/admin/'
|
|
request = rf.get('/register/', data={'next': 'http://example.com/'})
|
|
assert select_next_url(request, '/') == '/'
|
|
settings.A2_REDIRECT_WHITELIST = ['//example.com/']
|
|
assert select_next_url(request, '/') == 'http://example.com/'
|
|
|
|
|
|
def test_user_can_change_password(simple_user, settings):
|
|
assert user_can_change_password(user=simple_user) is True
|
|
settings.A2_REGISTRATION_CAN_CHANGE_PASSWORD = False
|
|
assert user_can_change_password(user=simple_user) is False
|
|
|
|
|
|
def test_get_authentication_events_hows(rf, simple_user):
|
|
user = authenticate(username=simple_user.username, password=simple_user.username)
|
|
request = rf.get('/login/')
|
|
|
|
def get_response():
|
|
return None
|
|
|
|
middleware = SessionMiddleware(get_response)
|
|
middleware.process_request(request)
|
|
middleware = AuthenticationMiddleware(get_response)
|
|
middleware.process_request(request)
|
|
MessageMiddleware(get_response).process_request(request)
|
|
request.journal = Journal(request=request)
|
|
assert 'password' not in [ev['how'] for ev in get_authentication_events(request)]
|
|
login(request, user, 'password')
|
|
assert 'password' in [ev['how'] for ev in get_authentication_events(request)]
|
|
|
|
|
|
def test_remember_cookie(rf):
|
|
from django.http import HttpResponse
|
|
|
|
request = rf.get('/')
|
|
request.COOKIES['preferrence'] = '1 2'
|
|
assert get_remember_cookie(request, 'preferrence') == [1, 2]
|
|
request.COOKIES['preferrence'] = '1 2 3 4 5 6'
|
|
assert get_remember_cookie(request, 'preferrence') == [1, 2, 3, 4, 5]
|
|
request.COOKIES['preferrence'] = '1 2 3 4 x'
|
|
assert not get_remember_cookie(request, 'preferrence')
|
|
request.COOKIES['preferrence'] = 'aaa'
|
|
assert not get_remember_cookie(request, 'preferrence')
|
|
|
|
response = HttpResponse()
|
|
request.COOKIES['preferrence'] = '1 2'
|
|
prepend_remember_cookie(request, response, 'preferrence', 4)
|
|
assert response.cookies['preferrence'].value == '4 1 2'
|
|
|
|
response = HttpResponse()
|
|
request.COOKIES['preferrence'] = '1 2 a'
|
|
prepend_remember_cookie(request, response, 'preferrence', 4)
|
|
assert response.cookies['preferrence'].value == '4'
|
|
|
|
response = HttpResponse()
|
|
request.COOKIES['preferrence'] = '1 2 3 4 5'
|
|
prepend_remember_cookie(request, response, 'preferrence', 7)
|
|
assert response.cookies['preferrence'].value == '7 1 2 3 4'
|
|
|
|
|
|
def test_send_templated_mail_template_selection(simple_user):
|
|
ou = OrganizationalUnit.objects.create(slug='ou_name')
|
|
simple_user.ou = ou
|
|
default_template = 'default_mail_template'
|
|
specific_template = 'custom_mail_template'
|
|
default_template_ou = '_'.join((default_template, ou.slug))
|
|
specific_template_ou = '_'.join((specific_template, ou.slug))
|
|
template_names = [default_template]
|
|
|
|
send_templated_mail(simple_user, template_names)
|
|
assert len(mail.outbox) == 1
|
|
sent_mail = mail.outbox.pop()
|
|
assert sent_mail.subject == default_template
|
|
assert sent_mail.body == default_template
|
|
|
|
send_templated_mail(simple_user, template_names, per_ou_templates=True)
|
|
assert len(mail.outbox) == 1
|
|
sent_mail = mail.outbox.pop()
|
|
assert sent_mail.subject == default_template_ou
|
|
assert sent_mail.body == default_template_ou
|
|
|
|
template_names.insert(0, specific_template)
|
|
send_templated_mail(simple_user, template_names)
|
|
assert len(mail.outbox) == 1
|
|
sent_mail = mail.outbox.pop()
|
|
assert sent_mail.subject == specific_template
|
|
assert sent_mail.body == specific_template
|
|
|
|
send_templated_mail(simple_user, template_names, per_ou_templates=True)
|
|
assert len(mail.outbox) == 1
|
|
sent_mail = mail.outbox.pop()
|
|
assert sent_mail.subject == specific_template_ou
|
|
assert sent_mail.body == specific_template_ou
|
|
|
|
|
|
def test_send_templated_mail_template_vars(settings, simple_user):
|
|
settings.TEMPLATE_VARS = {
|
|
'template_vars_subject_txt': 'here is the subject',
|
|
'template_vars_body_txt': 'here is the text body',
|
|
'template_vars_body_html': 'here is the html body',
|
|
}
|
|
send_templated_mail(simple_user, ['template_vars'])
|
|
|
|
assert len(mail.outbox) == 1
|
|
sent_mail = mail.outbox.pop()
|
|
assert sent_mail.subject == 'here is the subject'
|
|
assert sent_mail.body == 'here is the text body\n'
|
|
assert sent_mail.alternatives == [('here is the html body\n', 'text/html')]
|
|
|
|
settings.A2_EMAIL_FORMAT = 'text/plain'
|
|
send_templated_mail(simple_user, ['template_vars'])
|
|
|
|
assert len(mail.outbox) == 1
|
|
sent_mail = mail.outbox.pop()
|
|
assert sent_mail.subject == 'here is the subject'
|
|
assert sent_mail.body == 'here is the text body\n'
|
|
assert sent_mail.content_subtype == 'plain'
|
|
assert not hasattr(sent_mail, 'alternatives')
|
|
|
|
settings.A2_EMAIL_FORMAT = 'text/html'
|
|
send_templated_mail(simple_user, ['template_vars'])
|
|
|
|
assert len(mail.outbox) == 1
|
|
sent_mail = mail.outbox.pop()
|
|
assert sent_mail.subject == 'here is the subject'
|
|
assert sent_mail.body == 'here is the html body\n'
|
|
assert sent_mail.content_subtype == 'html'
|
|
assert not hasattr(sent_mail, 'alternatives')
|
|
|
|
|
|
def test_lazy_join():
|
|
a = 'a'
|
|
|
|
def f():
|
|
return a
|
|
|
|
f = lazy(f, str)
|
|
|
|
joined = lazy_join(',', ['a', f()])
|
|
|
|
assert str(joined) == 'a,a'
|
|
|
|
a = 'b'
|
|
|
|
assert str(joined) == 'a,b'
|