[0.12.x] Fix missing filters for get settings validator (#5480) (#5522)

* 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

(cherry picked from commit 9a6c2d2953)

# Conflicts:
#	InvenTree/plugin/samples/integration/test_sample.py

* Add missing import

* Added second missing import
This commit is contained in:
Lukas 2023-09-11 02:57:42 +02:00 committed by GitHub
parent 099b837a4e
commit 09872eec8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 3 deletions

View File

@ -166,7 +166,7 @@ class BaseInvenTreeSetting(models.Model):
do_cache = kwargs.pop('cache', True)
self.clean(**kwargs)
self.clean()
self.validate_unique()
# Execute before_save action
@ -560,7 +560,7 @@ class BaseInvenTreeSetting(models.Model):
"""Return units for setting."""
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."""
super().clean()
@ -571,7 +571,7 @@ class BaseInvenTreeSetting(models.Model):
elif self.is_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:
self.run_validator(validator)

View File

@ -5,9 +5,11 @@ import json
import time
from datetime import timedelta
from http import HTTPStatus
from unittest import mock
from django.contrib.auth import get_user_model
from django.core.cache import cache
from django.core.exceptions import ValidationError
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import Client, TestCase
from django.urls import reverse
@ -106,6 +108,36 @@ class SettingsTest(InvenTreeTestCase):
self.assertIn('STOCK_OWNERSHIP_CONTROL', result)
self.assertIn('SIGNUP_GROUP', result)
@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):
"""Test that all settings are valid.

View File

@ -1,5 +1,8 @@
"""Sample implementations for IntegrationPlugin."""
import json
from django.core.exceptions import ValidationError
from django.http import HttpResponse
from django.urls import include, re_path
from django.utils.translation import gettext_lazy as _
@ -8,6 +11,14 @@ from plugin import InvenTreePlugin
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):
"""A full plugin example."""
@ -77,6 +88,11 @@ class SampleIntegrationPlugin(AppMixin, SettingsMixin, UrlsMixin, NavigationMixi
'description': 'A protected setting, hidden from the UI',
'default': 'ABC-123',
'protected': True,
},
'VALIDATOR_SETTING': {
'name': 'JSON validator Setting',
'description': 'A setting using a JSON validator',
'validator': validate_json,
}
}

View File

@ -1,6 +1,9 @@
"""Unit tests for action plugins."""
from django.core.exceptions import ValidationError
from InvenTree.unit_test import InvenTreeTestCase
from plugin import registry
class SampleIntegrationPluginTests(InvenTreeTestCase):
@ -11,3 +14,17 @@ class SampleIntegrationPluginTests(InvenTreeTestCase):
response = self.client.get('/plugin/sample/ho/he/')
self.assertEqual(response.status_code, 200)
self.assertEqual(response.content, b'Hi there testuser this works')
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)