from importlib import import_module
import django
import pytest
from django.conf import settings
from django.dispatch import receiver
from django.test import RequestFactory
from django_cas_ng.backends import CASBackend
from django_cas_ng.models import SessionTicket
from django_cas_ng.signals import cas_user_authenticated, cas_user_logout
from django_cas_ng.views import LoginView, LogoutView
SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
[docs]@pytest.mark.django_db
def test_signal_when_user_logout_manual(monkeypatch, django_user_model):
session = SessionStore()
session['fake_session_key'] = 'fake-session_value'
session.save()
assert SessionStore(session_key=session.session_key) is not None
factory = RequestFactory()
request = factory.get('/logout')
request.session = session
# Create a fake session ticket and make sure it exists in the db
SessionTicket.objects.create(
session_key=session.session_key,
ticket='fake-ticket'
)
user = django_user_model.objects.create_user('test@example.com', '')
assert user is not None
request.user = user
callback_values = {}
@receiver(cas_user_logout)
def callback(sender, session, **kwargs):
callback_values.update(kwargs)
callback_values['session'] = dict(session)
LogoutView().get(request)
if django.VERSION[0] < 2:
assert request.user.is_anonymous() is True
else:
assert request.user.is_anonymous is True
assert 'user' in callback_values
assert callback_values['user'] == user
assert 'session' in callback_values
assert callback_values['session'].get('fake_session_key') == 'fake-session_value'
assert 'ticket' in callback_values
assert callback_values['ticket'] == 'fake-ticket'
[docs]@pytest.mark.django_db
def test_signal_when_user_logout_slo(monkeypatch, django_user_model, settings):
data = {
'logoutRequest': '<samlp:LogoutRequest '
'xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">'
'<samlp:SessionIndex>fake-ticket'
'</samlp:SessionIndex></samlp:LogoutRequest>'
}
settings.CAS_VERSION = 'CAS_2_SAML_1_0'
factory = RequestFactory()
request = factory.post('/login', data)
# user session and current requests.session are different
request.session = {}
user = django_user_model.objects.create_user('test@example.com', '')
assert user is not None
session = SessionStore()
session['fake_session_key'] = 'fake-session_value'
session.save()
assert SessionStore(session_key=session.session_key) is not None
# Create a fake session ticket and make sure it exists in the db
SessionTicket.objects.create(
session_key=session.session_key,
ticket='fake-ticket'
)
callback_values = {}
@receiver(cas_user_logout)
def callback(sender, session, **kwargs):
callback_values.update(kwargs)
callback_values['session'] = dict(session)
LoginView().post(request)
assert 'user' in callback_values
assert 'session' in callback_values
assert callback_values['session'].get('fake_session_key') == 'fake-session_value'
assert 'ticket' in callback_values
assert callback_values['ticket'] == 'fake-ticket'
[docs]@pytest.mark.django_db
def test_signal_when_user_is_created(monkeypatch, django_user_model):
"""
Test that when CAS authentication creates a user, the signal is called with
`created = True`
"""
factory = RequestFactory()
request = factory.get('/login/')
request.session = {}
def mock_verify(ticket, service):
return 'test@example.com', {'ticket': ticket, 'service': service}, None
callback_values = {}
@receiver(cas_user_authenticated)
def callback(sender, **kwargs):
callback_values.update(kwargs)
# we mock out the verify method so that we can bypass the external http
# calls needed for real authentication since we are testing the logic
# around authentication.
monkeypatch.setattr('cas.CASClientV2.verify_ticket', mock_verify)
# sanity check
assert not django_user_model.objects.filter(
username='test@example.com',
).exists()
backend = CASBackend()
user = backend.authenticate(
ticket='fake-ticket', service='fake-service', request=request,
)
assert 'user' in callback_values
assert callback_values.get('user') == user
assert callback_values.get('created') is True
assert 'attributes' in callback_values
assert 'ticket' in callback_values
assert 'service' in callback_values
[docs]@pytest.mark.django_db
def test_signal_when_user_already_exists(monkeypatch, django_user_model):
"""
Test that when CAS authentication creates a user, the signal is called with
`created = False`
"""
factory = RequestFactory()
request = factory.get('/login/')
request.session = {}
def mock_verify(ticket, service):
return 'test@example.com', {'ticket': ticket, 'service': service}, None
callback_values = {}
@receiver(cas_user_authenticated)
def callback(sender, **kwargs):
callback_values.update(kwargs)
# we mock out the verify method so that we can bypass the external http
# calls needed for real authentication since we are testing the logic
# around authentication.
monkeypatch.setattr('cas.CASClientV2.verify_ticket', mock_verify)
# sanity check
existing_user = django_user_model.objects.create_user(
'test@example.com', '',
)
backend = CASBackend()
user = backend.authenticate(
ticket='fake-ticket', service='fake-service', request=request,
)
assert 'user' in callback_values
assert callback_values.get('user') == user == existing_user
assert callback_values.get('created') is False
assert 'attributes' in callback_values
assert 'ticket' in callback_values
assert 'service' in callback_values
[docs]@pytest.mark.django_db
def test_signal_not_fired_if_auth_fails(monkeypatch, django_user_model):
"""
Test that the cas_user_authenticated signal is not fired when CAS
authentication fails.
"""
factory = RequestFactory()
request = factory.get('/login/')
request.session = {}
def mock_verify(ticket, service):
return None, {}, None
callback_values = {}
@receiver(cas_user_authenticated)
def callback(sender, **kwargs):
callback_values.update(kwargs)
# we mock out the verify method so that we can bypass the external http
# calls needed for real authentication since we are testing the logic
# around authentication.
monkeypatch.setattr('cas.CASClientV2.verify_ticket', mock_verify)
# sanity check
backend = CASBackend()
user = backend.authenticate(
ticket='fake-ticket', service='fake-service', request=request,
)
assert user is None
assert callback_values == {}