Merge pull request #2771 from SchrodingersGat/plugin-settings-fix

Ensure that kwargs are correctly passed through the settings chain
This commit is contained in:
Oliver 2022-03-25 14:53:22 +11:00 committed by GitHub
commit 5921964fdb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 61 additions and 45 deletions

View File

@ -79,7 +79,7 @@ class BaseInvenTreeSetting(models.Model):
self.key = str(self.key).upper() self.key = str(self.key).upper()
self.clean(**kwargs) self.clean(**kwargs)
self.validate_unique() self.validate_unique(**kwargs)
super().save() super().save()
@ -230,10 +230,6 @@ class BaseInvenTreeSetting(models.Model):
return choices return choices
@classmethod
def get_filters(cls, key, **kwargs):
return {'key__iexact': key}
@classmethod @classmethod
def get_setting_object(cls, key, **kwargs): def get_setting_object(cls, key, **kwargs):
""" """
@ -247,29 +243,35 @@ class BaseInvenTreeSetting(models.Model):
settings = cls.objects.all() settings = cls.objects.all()
filters = {
'key__iexact': key,
}
# Filter by user # Filter by user
user = kwargs.get('user', None) user = kwargs.get('user', None)
if user is not None: if user is not None:
settings = settings.filter(user=user) filters['user'] = user
try: # Filter by plugin
setting = settings.filter(**cls.get_filters(key, **kwargs)).first() plugin = kwargs.get('plugin', None)
except (ValueError, cls.DoesNotExist):
setting = None
except (IntegrityError, OperationalError):
setting = None
plugin = kwargs.pop('plugin', None) if plugin is not None:
if plugin:
from plugin import InvenTreePluginBase from plugin import InvenTreePluginBase
if issubclass(plugin.__class__, InvenTreePluginBase): if issubclass(plugin.__class__, InvenTreePluginBase):
plugin = plugin.plugin_config() plugin = plugin.plugin_config()
filters['plugin'] = plugin
kwargs['plugin'] = plugin kwargs['plugin'] = plugin
try:
setting = settings.filter(**filters).first()
except (ValueError, cls.DoesNotExist):
setting = None
except (IntegrityError, OperationalError):
setting = None
# Setting does not exist! (Try to create it) # Setting does not exist! (Try to create it)
if not setting: if not setting:
@ -287,7 +289,7 @@ class BaseInvenTreeSetting(models.Model):
try: try:
# Wrap this statement in "atomic", so it can be rolled back if it fails # Wrap this statement in "atomic", so it can be rolled back if it fails
with transaction.atomic(): with transaction.atomic():
setting.save() setting.save(**kwargs)
except (IntegrityError, OperationalError): except (IntegrityError, OperationalError):
# It might be the case that the database isn't created yet # It might be the case that the database isn't created yet
pass pass
@ -342,8 +344,26 @@ class BaseInvenTreeSetting(models.Model):
if change_user is not None and not change_user.is_staff: if change_user is not None and not change_user.is_staff:
return return
filters = {
'key__iexact': key,
}
user = kwargs.get('user', None)
plugin = kwargs.get('plugin', None)
if user is not None:
filters['user'] = user
if plugin is not None:
from plugin import InvenTreePluginBase
if issubclass(plugin.__class__, InvenTreePluginBase):
filters['plugin'] = plugin.plugin_config()
else:
filters['plugin'] = plugin
try: try:
setting = cls.objects.get(**cls.get_filters(key, **kwargs)) setting = cls.objects.get(**filters)
except cls.DoesNotExist: except cls.DoesNotExist:
if create: if create:
@ -438,17 +458,37 @@ class BaseInvenTreeSetting(models.Model):
validator(self.value) validator(self.value)
def validate_unique(self, exclude=None, **kwargs): def validate_unique(self, exclude=None, **kwargs):
""" Ensure that the key:value pair is unique. """
Ensure that the key:value pair is unique.
In addition to the base validators, this ensures that the 'key' In addition to the base validators, this ensures that the 'key'
is unique, using a case-insensitive comparison. is unique, using a case-insensitive comparison.
Note that sub-classes (UserSetting, PluginSetting) use other filters
to determine if the setting is 'unique' or not
""" """
super().validate_unique(exclude) super().validate_unique(exclude)
filters = {
'key__iexact': self.key,
}
user = getattr(self, 'user', None)
plugin = getattr(self, 'plugin', None)
if user is not None:
filters['user'] = user
if plugin is not None:
filters['plugin'] = plugin
try: try:
setting = self.__class__.objects.exclude(id=self.id).filter(**self.get_filters(self.key, **kwargs)) # Check if a duplicate setting already exists
setting = self.__class__.objects.filter(**filters).exclude(id=self.id)
if setting.exists(): if setting.exists():
raise ValidationError({'key': _('Key string must be unique')}) raise ValidationError({'key': _('Key string must be unique')})
except self.DoesNotExist: except self.DoesNotExist:
pass pass
@ -1312,16 +1352,9 @@ class InvenTreeUserSetting(BaseInvenTreeSetting):
def get_setting_object(cls, key, user): def get_setting_object(cls, key, user):
return super().get_setting_object(key, user=user) return super().get_setting_object(key, user=user)
def validate_unique(self, exclude=None): def validate_unique(self, exclude=None, **kwargs):
return super().validate_unique(exclude=exclude, user=self.user) return super().validate_unique(exclude=exclude, user=self.user)
@classmethod
def get_filters(cls, key, **kwargs):
return {
'key__iexact': key,
'user__id': kwargs['user'].id
}
def to_native_value(self): def to_native_value(self):
""" """
Return the "pythonic" value, Return the "pythonic" value,

View File

@ -175,23 +175,6 @@ class PluginSetting(common.models.BaseInvenTreeSetting):
return super().get_setting_definition(key, **kwargs) return super().get_setting_definition(key, **kwargs)
@classmethod
def get_filters(cls, key, **kwargs):
"""
Override filters method to ensure settings are filtered by plugin id
"""
filters = super().get_filters(key, **kwargs)
plugin = kwargs.get('plugin', None)
if plugin:
if issubclass(plugin.__class__, InvenTreePluginBase):
plugin = plugin.plugin_config()
filters['plugin'] = plugin
return filters
plugin = models.ForeignKey( plugin = models.ForeignKey(
PluginConfig, PluginConfig,
related_name='settings', related_name='settings',

View File

@ -263,7 +263,7 @@ function selectLabel(labels, items, options={}) {
`; `;
plugins.forEach(function(plugin) { plugins.forEach(function(plugin) {
plugin_selection += `<option value='${plugin.key}' title='${plugin.meta.human_name}'>${plugin.meta.description} - <small>${plugin.meta.human_name}</small></option>`; plugin_selection += `<option value='${plugin.key}' title='${plugin.meta.human_name}'>${plugin.name} - <small>${plugin.meta.human_name}</small></option>`;
}); });
plugin_selection += ` plugin_selection += `