authenticators: add helper functions for show condition (#67986)
gitea/authentic/pipeline/head This commit looks good Details

This commit is contained in:
Emmanuel Cazenave 2024-03-21 15:55:38 +01:00
parent 4dc8f6aab7
commit 36bc55d3ce
3 changed files with 100 additions and 1 deletions

View File

@ -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:

View File

@ -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
#

View File

@ -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