authentic2-cut/tests/test_hooks.py

245 lines
8.7 KiB
Python

from authentic2.custom_user.models import Profile, ProfileType
from authentic2.manager.tables import UserTable
from authentic2.manager.user_views import UsersView
from authentic2.models import Attribute, AttributeValue
from authentic2_auth_fc.models import FcAccount, FcAuthenticator
from django.contrib.auth import get_user_model
from django.urls import reverse
from django.utils.timezone import now
from utils import login
from authentic2_cut.apps import AppConfig
def test_a2_hook_manager_modify_table(db, rf, admin, monkeypatch, app):
class DummyModule:
__path__ = [
'./dummy',
]
dummy = DummyModule()
app_config = AppConfig('authentic2_cut', dummy)
user_table = UserTable(data={})
request = rf.get('/manage/users/')
request.user = admin
users_view = UsersView.as_view()(request)
# base table contains a2 generic column
assert 'get_full_name' in list(user_table.sequence)
assert set(user_table.sequence) >= {
'get_full_name',
'username',
'email',
'first_name',
'last_name',
'ou',
}
assert 'get_full_name' in user_table.base_columns
assert set(user_table.base_columns) >= {
'get_full_name',
'username',
'email',
'first_name',
'last_name',
'ou',
}
# does not crash when explicitely run
app_config.a2_hook_manager_modify_table(users_view, user_table)
# and most of all the rendered table does not contain any such column
response = login(app, admin, '/manage/users/')
assert 'get_full_name' not in response.html
assert len(response.pyquery.find('thead').find('tr').children()) == 5
def test_a2_hook_idp_oidc_modify_user_info(db, rf, app):
class DummyModule:
__path__ = [
'./dummy',
]
dummy = DummyModule()
User = get_user_model()
user = User.objects.create(email='john.doe@example.org', first_name='John', last_name='Doe')
user.attributes.preferred_username = 'Current name'
user.attributes.preferred_givenname = 'Current givenname'
user.attributes.professional_phone = '0123456789'
user.attributes.professional_mobile_phone = '0623456789'
user.attributes.home_phone = '0133456789'
user.attributes.home_mobile_phone = '0633456789'
user.save()
app_config = AppConfig('authentic2_cut', dummy)
client = None # unused in hook
scope_set = {'email', 'profile', 'openid', 'crown'}
user_info = {
'sub': 'abc',
'email': 'abc@ad.dre.ss',
'first_name': 'Original first name',
'last_name': 'Original last name',
}
# firt attempt without profile, user_info is modified by the hook
app_config.a2_hook_idp_oidc_modify_user_info(client, user, scope_set, user_info, profile=None)
assert user_info['email'] == 'john.doe@example.org'
assert user_info['first_name'] == 'John'
assert user_info['given_name'] == 'John'
assert user_info['last_name'] == 'Doe'
assert user_info['family_name'] == 'Doe'
assert user_info['preferred_username'] == 'Current name'
assert user_info['preferred_givenname'] == 'Current givenname'
assert user_info['professional_phone'] == '0123456789'
assert user_info['professional_mobile_phone'] == '0623456789'
assert user_info['home_phone'] == '0133456789'
assert user_info['home_mobile_phone'] == '0633456789'
# phone- & address-related user information is not provided by FC by any means
assert 'phone' not in user_info
assert 'address' not in user_info
for claim, value in user_info.items():
if claim.startswith('address_'):
assert value is None
profile_type = ProfileType.objects.create(
name='Mandataire',
slug='mandataire',
)
profile = Profile.objects.create(
profile_type=profile_type,
user=user,
identifier='abc',
email='mandataire-abc',
)
user_info = {
'sub': 'abc',
'email': 'abc@ad.dre.ss',
'first_name': 'Original first name',
'last_name': 'Original last name',
}
# second attempt with profile, whose presence is detected by the hook, thus bypassed
app_config.a2_hook_idp_oidc_modify_user_info(client, user, scope_set, user_info, profile=profile)
assert user_info['email'] == 'abc@ad.dre.ss'
assert user_info['first_name'] == 'Original first name'
assert user_info['last_name'] == 'Original last name'
assert user_info['preferred_username'] == 'Current name'
assert user_info['preferred_givenname'] == 'Current givenname'
assert user_info['professional_phone'] == '0123456789'
assert user_info['professional_mobile_phone'] == '0623456789'
assert 'phone' not in user_info
assert 'address' not in user_info
for claim, value in user_info.items():
if claim.startswith('home_') and claim.endswith('_phone') or claim.startswith('address_'):
assert value is None
def test_a2_hook_manager_modify_other_actions_remove_fc(db, rf, app, admin):
class DummyModule:
__path__ = [
'./dummy',
]
dummy = DummyModule()
title = Attribute.objects.get(name='title')
app_config = AppConfig('authentic2_cut', dummy)
User = get_user_model()
user = User.objects.create(email='john.doe@example.org', first_name='John', last_name='Doe')
AttributeValue.objects.create(owner=user, attribute=title, content='Mr')
FcAccount.objects.create(user=user, sub='sub1')
user.attributes.validation_context = 'FC'
user.attributes.validation_date = now().date()
user.attributes.validation_partner = 'lambda'
user.attributes.validated = True
response = login(app, admin, f'/manage/users/{user.id}/')
assert 'Supprimer la liaison FranceConnect' in response.text
response = response.forms['object-actions'].submit('remove-franceconnect')
assert 'Supprimer la liaison FranceConnect' not in response.text
user = User.objects.get(email='john.doe@example.org')
assert FcAccount.objects.filter(user=user).count() == 0
assert AttributeValue.objects.with_owner(user).filter(verified=True).count() == 0
assert not user.attributes.validation_context
assert not user.attributes.validation_date
assert not user.attributes.validation_partner
assert not user.attributes.validated
def test_cut_event_fc_unlink(db, rf, app):
class DummyModule:
__path__ = [
'./dummy',
]
dummy = DummyModule()
title = Attribute.objects.get(name='title')
app_config = AppConfig('authentic2_cut', dummy)
FcAuthenticator.objects.create(enabled=True)
User = get_user_model()
user = User.objects.create(
email='john.doe@example.org', first_name='John', last_name='Doe', username='jdoe'
)
user.set_password('jdoe')
AttributeValue.objects.create(owner=user, attribute=title, content='Mr')
FcAccount.objects.create(user=user, sub='sub1')
user.attributes.validation_context = 'FC'
user.attributes.validation_date = now().date()
user.attributes.validation_partner = 'lambda'
user.attributes.validated = True
user.save()
login(app, user)
response = app.get(reverse('fc-unlink'))
response = response.form.submit('unlink')
user = User.objects.get(email='john.doe@example.org')
assert FcAccount.objects.filter(user=user).count() == 0
assert AttributeValue.objects.with_owner(user).filter(verified=True).count() == 0
assert not user.attributes.validation_context
assert not user.attributes.validation_date
assert not user.attributes.validation_partner
assert not user.attributes.validated
def test_a2_hook_front_modify_form(db, rf, app, admin):
class DummyModule:
__path__ = [
'./dummy',
]
dummy = DummyModule()
title = Attribute.objects.get(name='title')
app_config = AppConfig('authentic2_cut', dummy)
FcAuthenticator.objects.create(enabled=True)
User = get_user_model()
user = User.objects.create(
email='john.doe@example.org', first_name='John', last_name='Doe', username='jdoe'
)
user.set_password('jdoe')
AttributeValue.objects.create(owner=user, attribute=title, content='Mr')
FcAccount.objects.create(user=user, sub='sub1')
user.attributes.validation_context = 'FC'
user.attributes.validation_date = now().date()
user.attributes.validation_partner = 'lambda'
user.attributes.validated = True
user.save()
login(app, user)
response = app.get(reverse('cut-edit-crown'))
form = response.form
form.set('title', 'Mrs')
response = response.form.submit()
assert response.location == '/accounts/'
user.refresh_from_db()
assert user.attributes.title == 'Mrs'
response = app.get(reverse('cut-edit-core'))
assert 'title' not in response.form.fields