diff --git a/src/authentic2/apps/authenticators/models.py b/src/authentic2/apps/authenticators/models.py index cd6ffed24..b6cd8dd89 100644 --- a/src/authentic2/apps/authenticators/models.py +++ b/src/authentic2/apps/authenticators/models.py @@ -19,6 +19,7 @@ import logging import uuid from django.apps import apps +from django.conf import settings from django.core.exceptions import ValidationError from django.db import models from django.db.models import Max @@ -135,10 +136,28 @@ class BaseAuthenticator(models.Model): value=value, ) + def is_for_office(self, office_keyword, ctx): + try: + return evaluate_condition( + settings.AUTHENTICATOR_SHOW_CONDITIONS[office_keyword], ctx, on_raise=False + ) + except Exception as e: + logger.error(e) + return False + def shown(self, ctx=()): if not self.show_condition: return True - ctx = dict(ctx, id=self.slug) + + def is_for_backoffice(): + return self.is_for_office('is_for_backoffice', ctx) + + def is_for_frontoffice(): + return self.is_for_office('is_for_frontoffice', ctx) + + ctx = dict( + ctx, id=self.slug, is_for_backoffice=is_for_backoffice, is_for_frontoffice=is_for_frontoffice + ) try: return evaluate_condition(self.show_condition, ctx, on_raise=True) except Exception as e: diff --git a/src/authentic2/settings.py b/src/authentic2/settings.py index ababf8bc2..7713bfc3c 100644 --- a/src/authentic2/settings.py +++ b/src/authentic2/settings.py @@ -405,6 +405,11 @@ PHONE_COUNTRY_CODES = { DEFAULT_COUNTRY_CODE = '33' +AUTHENTICATOR_SHOW_CONDITIONS = { + 'is_for_backoffice': "'backoffice' in login_hint", + 'is_for_frontoffice': "'backoffice' not in login_hint", +} + # # Load configuration file # diff --git a/tests/test_login.py b/tests/test_login.py index 8620f8675..3f8a5006a 100644 --- a/tests/test_login.py +++ b/tests/test_login.py @@ -334,6 +334,81 @@ def test_show_condition_with_headers(db, app, settings): assert 'name="login-password-submit"' in response +def test_show_condition_is_for_backoffice(db, app, settings, caplog): + response = app.get('/login/') + assert 'name="login-password-submit"' in response + + LoginPasswordAuthenticator.objects.update(show_condition='is_for_backoffice()') + response = app.get('/login/') + assert 'name="login-password-submit"' not in response + assert len(caplog.records) == 0 + + response = app.get('/manage/') + response = response.follow() + assert 'name="login-password-submit"' in response + assert len(caplog.records) == 0 + app.reset() + + # combine + LoginPasswordAuthenticator.objects.update( + show_condition="is_for_backoffice() and 'X-Entrouvert' in headers" + ) + response = app.get('/manage/') + response = response.follow() + assert 'name="login-password-submit"' not in response + assert len(caplog.records) == 0 + app.reset() + + response = app.get('/manage/') + response = response.follow(headers={'x-entrouvert': '1'}) + assert 'name="login-password-submit"' in response + assert len(caplog.records) == 0 + app.reset() + + # set a condition with error + settings.AUTHENTICATOR_SHOW_CONDITIONS['is_for_backoffice'] = "'backoffice' in unknown" + LoginPasswordAuthenticator.objects.update(show_condition='is_for_backoffice()') + response = app.get('/manage/') + response = response.follow() + assert 'name="login-password-submit"' not in response + assert len(caplog.records) == 1 + + +def test_show_condition_is_for_frontoffice(db, app, settings, caplog): + response = app.get('/login/') + assert 'name="login-password-submit"' in response + + LoginPasswordAuthenticator.objects.update(show_condition='is_for_frontoffice()') + response = app.get('/login/') + assert 'name="login-password-submit"' in response + assert len(caplog.records) == 0 + + response = app.get('/manage/') + response = response.follow() + assert 'name="login-password-submit"' not in response + assert len(caplog.records) == 0 + app.reset() + + # combine + LoginPasswordAuthenticator.objects.update( + show_condition="is_for_frontoffice() and 'X-Entrouvert' in headers" + ) + response = app.get('/login/') + assert 'name="login-password-submit"' not in response + assert len(caplog.records) == 0 + + response = app.get('/login/', headers={'X-entrouvert': '1'}) + assert 'name="login-password-submit"' in response + assert len(caplog.records) == 0 + + # set a condition with error + settings.AUTHENTICATOR_SHOW_CONDITIONS['is_for_frontoffice'] = "'backoffice' not in unknown" + LoginPasswordAuthenticator.objects.update(show_condition='is_for_frontoffice()') + response = app.get('/login/') + assert 'name="login-password-submit"' not in response + assert len(caplog.records) == 1 + + def test_registration_url_on_login_page(db, app): response = app.get('/login/?next=/whatever') assert 'register/?next=/whatever"' in response