Fix missing filters for get settings validator (#5480)

* Fix missing filters for get settings validator

* merge default model instance filters and kwargs

* Added tests for validators

* Give it a try without the kwargs passed to clean in save function

* Added string for identification for debug statement

* Added more debug comments

* Added more debug prints

* Fix test debug

* Modiefied workflow

* trigger ci

* Fix test and remove unused kwargs

* Added debug prints

* Only run one test in ci

* Added more debug code

* Remove all debug prints and reset workflow

* Reset overlooked file
This commit is contained in:
Lukas 2023-09-10 13:37:21 +02:00 committed by GitHub
parent 14a6330114
commit 9a6c2d2953
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 67 additions and 3 deletions

View File

@ -170,7 +170,7 @@ class BaseInvenTreeSetting(models.Model):
do_cache = kwargs.pop('cache', True) do_cache = kwargs.pop('cache', True)
self.clean(**kwargs) self.clean()
self.validate_unique() self.validate_unique()
# Execute before_save action # Execute before_save action
@ -604,7 +604,7 @@ class BaseInvenTreeSetting(models.Model):
"""Return units for setting.""" """Return units for setting."""
return self.__class__.get_setting_units(self.key, **self.get_filters_for_instance()) return self.__class__.get_setting_units(self.key, **self.get_filters_for_instance())
def clean(self, **kwargs): def clean(self):
"""If a validator (or multiple validators) are defined for a particular setting key, run them against the 'value' field.""" """If a validator (or multiple validators) are defined for a particular setting key, run them against the 'value' field."""
super().clean() super().clean()
@ -615,7 +615,7 @@ class BaseInvenTreeSetting(models.Model):
elif self.is_bool(): elif self.is_bool():
self.value = self.as_bool() self.value = self.as_bool()
validator = self.__class__.get_setting_validator(self.key, **kwargs) validator = self.__class__.get_setting_validator(self.key, **self.get_filters_for_instance())
if validator is not None: if validator is not None:
self.run_validator(validator) self.run_validator(validator)

View File

@ -9,6 +9,7 @@ from unittest import mock
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.core.cache import cache from django.core.cache import cache
from django.core.exceptions import ValidationError
from django.core.files.uploadedfile import SimpleUploadedFile from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import Client, TestCase from django.test import Client, TestCase
from django.urls import reverse from django.urls import reverse
@ -142,6 +143,36 @@ class SettingsTest(InvenTreeTestCase):
InvenTreeSetting.set_setting('CD', "world", self.user) InvenTreeSetting.set_setting('CD', "world", self.user)
self.assertEqual(InvenTreeSetting.check_all_settings(), (True, [])) self.assertEqual(InvenTreeSetting.check_all_settings(), (True, []))
@mock.patch("common.models.InvenTreeSetting.get_setting_definition")
def test_settings_validator(self, get_setting_definition):
"""Make sure that the validator function gets called on set setting."""
def validator(x):
if x == "hello":
return x
raise ValidationError(f"{x} is not valid")
mock_validator = mock.Mock(side_effect=validator)
# define partial schema
settings_definition = {
"AB": { # key that's has not already been accessed
"validator": mock_validator,
},
}
def mocked(key, **kwargs):
return settings_definition.get(key, {})
get_setting_definition.side_effect = mocked
InvenTreeSetting.set_setting("AB", "hello", self.user)
mock_validator.assert_called_with("hello")
with self.assertRaises(ValidationError):
InvenTreeSetting.set_setting("AB", "world", self.user)
mock_validator.assert_called_with("world")
def run_settings_check(self, key, setting): def run_settings_check(self, key, setting):
"""Test that all settings are valid. """Test that all settings are valid.

View File

@ -1,5 +1,8 @@
"""Sample implementations for IntegrationPlugin.""" """Sample implementations for IntegrationPlugin."""
import json
from django.core.exceptions import ValidationError
from django.http import HttpResponse from django.http import HttpResponse
from django.urls import include, re_path from django.urls import include, re_path
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@ -8,6 +11,14 @@ from plugin import InvenTreePlugin
from plugin.mixins import AppMixin, NavigationMixin, SettingsMixin, UrlsMixin from plugin.mixins import AppMixin, NavigationMixin, SettingsMixin, UrlsMixin
def validate_json(value):
"""Example validator for json input."""
try:
json.loads(value)
except Exception as e:
raise ValidationError(str(e))
class SampleIntegrationPlugin(AppMixin, SettingsMixin, UrlsMixin, NavigationMixin, InvenTreePlugin): class SampleIntegrationPlugin(AppMixin, SettingsMixin, UrlsMixin, NavigationMixin, InvenTreePlugin):
"""A full plugin example.""" """A full plugin example."""
@ -78,6 +89,11 @@ class SampleIntegrationPlugin(AppMixin, SettingsMixin, UrlsMixin, NavigationMixi
'description': 'A protected setting, hidden from the UI', 'description': 'A protected setting, hidden from the UI',
'default': 'ABC-123', 'default': 'ABC-123',
'protected': True, 'protected': True,
},
'VALIDATOR_SETTING': {
'name': 'JSON validator Setting',
'description': 'A setting using a JSON validator',
'validator': validate_json,
} }
} }

View File

@ -1,5 +1,7 @@
"""Unit tests for action plugins.""" """Unit tests for action plugins."""
from django.core.exceptions import ValidationError
from InvenTree.unit_test import InvenTreeTestCase from InvenTree.unit_test import InvenTreeTestCase
from plugin import registry from plugin import registry
@ -22,3 +24,18 @@ class SampleIntegrationPluginTests(InvenTreeTestCase):
self.assertEqual(plugin.check_settings(), (False, ['API_KEY'])) self.assertEqual(plugin.check_settings(), (False, ['API_KEY']))
plugin.set_setting('API_KEY', "dsfiodsfjsfdjsf") plugin.set_setting('API_KEY', "dsfiodsfjsfdjsf")
self.assertEqual(plugin.check_settings(), (True, [])) self.assertEqual(plugin.check_settings(), (True, []))
# validator
def test_settings_validator(self):
"""Test settings validator for plugins."""
plugin = registry.get_plugin('sample')
valid_json = '{"ts": 13}'
not_valid_json = '{"ts""13"}'
# no error, should pass validator
plugin.set_setting('VALIDATOR_SETTING', valid_json)
# should throw an error
with self.assertRaises(ValidationError):
plugin.set_setting('VALIDATOR_SETTING', not_valid_json)