Personnalisation de la page “Mon compte” en fonction du service connecté (#75142) #50

Merged
pmarillonnet merged 1 commits from wip/75142-accounts-default-service-customization into main 2023-06-13 11:49:11 +02:00
5 changed files with 151 additions and 12 deletions

View File

@ -64,25 +64,27 @@ def a2_processor(request):
if hasattr(request, 'session'):
variables['LAST_LOGIN'] = request.session.get(constants.LAST_LOGIN_SESSION_KEY)
variables['USER_SWITCHED'] = constants.SWITCH_USER_SESSION_KEY in request.session
service = get_service(request)
if service:
if service := get_service(request):
variables['service'] = service
variables['service_colour'] = service.colour
# name and logo should be show for OIDC service only
variables['show_service_infos'] = type(service).__name__ != 'LibertyProvider'
if service.logo:
variables['service_logo_url'] = service.logo.url
if service.ou:
variables['service_ou_colour'] = service.ou.colour
if service.ou.logo:
variables['service_ou_logo_url'] = service.ou.logo.url
if type(service).__name__ == 'LibertyProvider':
# fallback default appearance settings for SAML services
sso_settings = Setting.objects.filter_namespace('sso')
if any(sso_settings.values_list('value', flat=True)):
for setting in sso_settings:
variables[setting.key.split(':')[-1]] = setting.value
if type(service).__name__ == 'LibertyProvider':
# generic appearance settings for SAML services
sso_settings = Setting.objects.filter_namespace('sso')
if any(sso_settings.values_list('value', flat=True)):
for setting in sso_settings:
variables[setting.key.split(':')[-1]] = setting.value
variables['show_service_infos'] = True
variables['service_custom_appearance'] = True
else:
if any([service.colour, service.logo, service.ou.colour, service.ou.logo]):
# client specific appearence for third-party OIDC services
variables['service_custom_appearance'] = True
variables['show_service_infos'] = True
return variables

View File

@ -1,6 +1,21 @@
{% extends "authentic2/base-page.html" %}
{% load i18n %}
{% if service_custom_appearance %}
{% block css %}
{{ block.super }}
{% firstof generic_service_colour service_colour service_ou_colour as colour %}
{% if colour %}
<style>
div.a2-profile-block {
color: {{ colour }};
}
</style>
{% endif %}
{% endblock %}
{% endif %}
{% block title %}
{{ view.title }}
{% endblock %}
@ -12,6 +27,25 @@
{% block content %}
<div id="a2-profile-blocks">
{% if service_custom_appearance %}
{% firstof generic_service_name service.name service.ou.name as name %}
{% firstof generic_service_logo_url service_logo_url service_ou_logo_url as logo_url %}
<h3>{% trans "Remote service authentication" %}</h3>
<div id="a2-service-information" class="a2-profile-block">
{% blocktrans %}You logged in from service {{ name }}.{% endblocktrans %}
</div>
{% if logo_url %}
<picture>
{% if service.home_url or generic_service_home_url %}
<a href="{% firstof home_url generic_service_home_url %}">
{% endif %}
<img src="{{ logo_url }}" alt="{{ name }}" class="a2-service-information--logo" />
{% if service.home_url or generic_service_home_url %}

Il manque le or generic_service_home_url ici dans la condition, je vais corriger.
En l’état les tests ne cassent pas parce que django détecte l’absence de balise fermante et l’ajoute.

Il manque le `or generic_service_home_url` ici dans la condition, je vais corriger. En l’état les tests ne cassent pas parce que django détecte l’absence de balise fermante et l’ajoute.

(C’est corrigé.)

(C’est corrigé.)
</a>
{% endif %}
</picture>
{% endif %}
{% endif %}
<div id="a2-profile" class="a2-profile-block">
{% if attributes %}
<dl>

View File

@ -21,7 +21,7 @@
{% if logo_url %}
<picture>
{% if service.home_url or generic_service_home_url %}
<a href="{% firstof home_url generic_service_home_url %}">
<a href="{% firstof service.home_url generic_service_home_url %}">
{% endif %}
<img src="{{ logo_url }}" alt="{{ name }}" class="service-message--logo" />
{% if service.home_url or generic_service_home_url %}

View File

@ -2044,3 +2044,65 @@ def test_authenticate_client_exception_handling(app, oidc_client, simple_user, r
# OK
request.POST['client_secret'] = oidc_client.client_secret
assert authenticate_client(request, client=oidc_client) == oidc_client
def test_login_from_client_accounts_appearance(oidc_client, app, simple_user, settings):
redirect_uri = oidc_client.redirect_uris.split()[0]
params = {
'client_id': oidc_client.client_id,
'scope': 'openid profile email',
'redirect_uri': redirect_uri,
'state': 'xxx',
'nonce': 'yyy',
'login_hint': 'backoffice john@example.com',
'response_type': 'code',
}
authorize_url = make_url('oidc-authorize', params=params)
response = app.get(authorize_url).follow()
assert not response.pyquery.find('.service-message--link')
assert response.pyquery.find('.service-message--text')
# check default settings fallback is unused
colour = Setting.objects.get(key='sso:generic_service_colour')
colour.value = '#8c22ec'
colour.save()
home_url = Setting.objects.get(key='sso:generic_service_home_url')
home_url.value = 'https://default.example.net'
home_url.save()
logo_url = Setting.objects.get(key='sso:generic_service_logo_url')
logo_url.value = 'https://default.example.net/logo.jpg'
logo_url.save()
service_name = Setting.objects.get(key='sso:generic_service_name')
service_name.value = 'Some generic service name'
service_name.save()
oidc_client.colour = ''
oidc_client.name = ''
oidc_client.ou.name = ''
oidc_client.save()
oidc_client.ou.save()
response = app.get(authorize_url).follow()
response.form.set('username', simple_user.username)
response.form.set('password', simple_user.username)
response = response.form.submit(name='login-password-submit').follow()
response.form.submit('accept')
response = app.get('/accounts/')
assert not response.pyquery('style')
assert not response.pyquery('#a2-service-information')
oidc_client.colour = '#754da9'
oidc_client.name = 'One specific client'
oidc_client.ou.name = 'Misc OU'
with open('tests/201x201.jpg', 'rb') as fd:
oidc_client.logo = SimpleUploadedFile(name='201x201.jpg', content=fd.read())
oidc_client.save()
oidc_client.ou.save()
response = app.get('/accounts/')
assert '#754da9' in response.pyquery('style')[0].text
assert 'One specific client' in response.pyquery('#a2-service-information')[0].text
assert ('class', 'a2-service-information--logo') in response.pyquery('img')[0].items()
assert ('src', '/media/services/logos/201x201.jpg') in response.pyquery('img')[0].items()
assert ('alt', 'One specific client') in response.pyquery('img')[0].items()

View File

@ -607,6 +607,47 @@ def test_sso_redirect_post_default_appearance_deactivated_nofx(app, idp, user):
scenario.check_assertion(user=user)
def test_sso_generic_appearance_accounts_pages(app, idp, user):
# check default settings fallback are used for saml services
colour = Setting.objects.get(key='sso:generic_service_colour')
colour.value = '#8c22ec'
colour.save()
home_url = Setting.objects.get(key='sso:generic_service_home_url')
home_url.value = 'https://default.example.net'
home_url.save()
logo_url = Setting.objects.get(key='sso:generic_service_logo_url')
logo_url.value = 'https://default.example.net/logo.jpg'
logo_url.save()
service_name = Setting.objects.get(key='sso:generic_service_name')
service_name.value = 'Some default service name'
service_name.save()
scenario = Scenario(app, sp_kwargs=dict(binding='post'))
scenario.launch_authn_request()
scenario.login(user)
scenario.handle_post_response()
response = app.get('/accounts/')
assert '#8c22ec' in response.pyquery('style')[0].text
assert 'Some default service name' in response.pyquery('#a2-service-information')[0].text
assert ('class', 'a2-service-information--logo') in response.pyquery('img')[0].items()
assert ('src', 'https://default.example.net/logo.jpg') in response.pyquery('img')[0].items()
assert ('alt', 'Some default service name') in response.pyquery('img')[0].items()
colour.value = ''
colour.save()
home_url.value = ''
home_url.save()
logo_url.value = ''
logo_url.save()
service_name.value = ''
service_name.save()
# resetting generic conf disable customization support:
response = app.get('/accounts/')
assert not response.pyquery('style')
assert not response.pyquery('#a2-service-information')
def test_sso_post_post(app, idp, user):
scenario = Scenario(
app, make_authn_request_kwargs={'method': lasso.HTTP_METHOD_POST}, sp_kwargs=dict(binding='post')