utils: add form field for template and condition's templates (#74797)

This commit is contained in:
Benjamin Dauvergne 2023-03-01 12:37:39 +01:00 committed by Gitea
parent 687e05b28e
commit 0aa78ffedb
4 changed files with 100 additions and 2 deletions

View File

@ -15,8 +15,34 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from django import forms from django import forms
from django.core import validators from django.core import exceptions, validators
from django.template import Template, TemplateSyntaxError
from django.utils.translation import gettext_lazy as _
class LDAPURLField(forms.URLField): class LDAPURLField(forms.URLField):
default_validators = [validators.URLValidator(schemes=['ldap', 'ldaps'])] default_validators = [validators.URLValidator(schemes=['ldap', 'ldaps'])]
def validate_condition_template(condition_template):
real_template = f'{{% if {condition_template} %}}OK{{% endif %}}'
try:
Template(real_template)
except (TemplateSyntaxError, OverflowError) as e:
raise exceptions.ValidationError(_('syntax error: %s') % e, code='syntax-error')
class ConditionField(forms.CharField):
default_validators = [validate_condition_template]
def validate_template(template):
try:
Template(template)
except (TemplateSyntaxError, OverflowError) as e:
raise exceptions.ValidationError(_('syntax error: %s') % e, code='syntax-error')
class TemplateField(forms.CharField):
default_validators = [validate_template]
widget = forms.Textarea

View File

@ -20,7 +20,7 @@ Disable autoescaping.
''' '''
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.template import TemplateSyntaxError from django.template import Context, Template, TemplateSyntaxError
from django.template.backends.django import DjangoTemplates from django.template.backends.django import DjangoTemplates
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
@ -46,3 +46,15 @@ def validate_template(template_string):
make_template(template_string) make_template(template_string)
except TemplateSyntaxError as e: except TemplateSyntaxError as e:
raise ValidationError(_('Invalid template: %s') % e) raise ValidationError(_('Invalid template: %s') % e)
def evaluate_condition(condition_template, context_dict):
template = Template(f'{{% if {condition_template} %}}OK{{% endif %}}')
context = Context(context_dict)
return template.render(context) == 'OK'
def evaluate_template(template, context_dict):
template = Template(template)
context = Context(context_dict)
return template.render(context)

34
tests/test_utils_forms.py Normal file
View File

@ -0,0 +1,34 @@
# passerelle - uniform access to multiple data sources and services
# Copyright (C) 2023 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import pytest
from django.core.exceptions import ValidationError
from passerelle.utils.forms import ConditionField, TemplateField
def test_condition_field():
field = ConditionField()
with pytest.raises(ValidationError):
field.clean('x ==')
assert field.clean('x == 1') == 'x == 1'
def test_template_field():
field = TemplateField()
with pytest.raises(ValidationError):
field.clean('{% if foo %}bar')
assert field.clean('{% if foo %}bar{% endif %}') == '{% if foo %}bar{% endif %}'

View File

@ -0,0 +1,26 @@
# passerelle - uniform access to multiple data sources and services
# Copyright (C) 2023 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from passerelle.utils.templates import evaluate_condition, evaluate_template
def test_evaluate_condition():
assert evaluate_condition('x == 1', {'x': 1}) is True
assert evaluate_condition('x == 0', {'x': 1}) is False
def test_evaluate_template():
assert evaluate_template('{% if foo %}bar{% endif %}', {'foo': True}) == 'bar'