2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-08-07 20:32:12 +00:00

Improve back-end validation

This commit is contained in:
Oliver Walters
2024-11-06 00:20:40 +00:00
parent cf2dae00af
commit 15f6930d6b
3 changed files with 50 additions and 15 deletions

View File

@@ -3403,7 +3403,30 @@ class Attachment(InvenTree.models.MetadataMixin, InvenTree.models.InvenTreeModel
class InvenTreeCustomUserStateModel(models.Model): class InvenTreeCustomUserStateModel(models.Model):
"""Custom model to extends any registered state with extra custom, user defined states.""" """Custom model to extends any registered state with extra custom, user defined states.
Fields:
reference_status: Status set that is extended with this custom state
logical_key: State logical key that is equal to this custom state in business logic
key: Numerical value that will be saved in the models database
name: Name of the state (must be uppercase and a valid variable identifier)
label: Label that will be displayed in the frontend (human readable)
color: Color that will be displayed in the frontend
"""
reference_status = models.CharField(
max_length=250,
verbose_name=_('Reference Status Set'),
help_text=_('Status set that is extended with this custom state'),
)
logical_key = models.IntegerField(
verbose_name=_('Logical Key'),
help_text=_(
'State logical key that is equal to this custom state in business logic'
),
)
key = models.IntegerField( key = models.IntegerField(
verbose_name=_('Value'), verbose_name=_('Value'),
@@ -3411,7 +3434,13 @@ class InvenTreeCustomUserStateModel(models.Model):
) )
name = models.CharField( name = models.CharField(
max_length=250, verbose_name=_('Name'), help_text=_('Name of the state') max_length=250,
verbose_name=_('Name'),
help_text=_('Name of the state'),
validators=[
common.validators.validate_uppercase,
common.validators.validate_variable_string,
],
) )
label = models.CharField( label = models.CharField(
@@ -3428,13 +3457,6 @@ class InvenTreeCustomUserStateModel(models.Model):
help_text=_('Color that will be displayed in the frontend'), help_text=_('Color that will be displayed in the frontend'),
) )
logical_key = models.IntegerField(
verbose_name=_('Logical Key'),
help_text=_(
'State logical key that is equal to this custom state in business logic'
),
)
model = models.ForeignKey( model = models.ForeignKey(
ContentType, ContentType,
on_delete=models.SET_NULL, on_delete=models.SET_NULL,
@@ -3444,12 +3466,6 @@ class InvenTreeCustomUserStateModel(models.Model):
help_text=_('Model this state is associated with'), help_text=_('Model this state is associated with'),
) )
reference_status = models.CharField(
max_length=250,
verbose_name=_('Reference Status Set'),
help_text=_('Status set that is extended with this custom state'),
)
class Meta: class Meta:
"""Metaclass options for this mixin.""" """Metaclass options for this mixin."""
@@ -3493,17 +3509,21 @@ class InvenTreeCustomUserStateModel(models.Model):
get_custom_classes(include_custom=False), get_custom_classes(include_custom=False),
) )
) )
if len(ref_set) == 0: if len(ref_set) == 0:
raise ValidationError({ raise ValidationError({
'reference_status': _('Reference status set not found') 'reference_status': _('Reference status set not found')
}) })
ref_set = ref_set[0] ref_set = ref_set[0]
if self.key in ref_set.keys(): # noqa: SIM118 if self.key in ref_set.keys(): # noqa: SIM118
raise ValidationError({ raise ValidationError({
'key': _( 'key': _(
'Key must be different from the logical keys of the reference status' 'Key must be different from the logical keys of the reference status'
) )
}) })
if self.logical_key not in ref_set.keys(): # noqa: SIM118 if self.logical_key not in ref_set.keys(): # noqa: SIM118
raise ValidationError({ raise ValidationError({
'logical_key': _( 'logical_key': _(

View File

@@ -335,6 +335,7 @@ class CustomStateSerializer(DataImportExportSerializerMixin, InvenTreeModelSeria
] ]
model_name = serializers.CharField(read_only=True, source='model.name') model_name = serializers.CharField(read_only=True, source='model.name')
reference_status = serializers.ChoiceField( reference_status = serializers.ChoiceField(
choices=generic.states.custom.state_reference_mappings() choices=generic.states.custom.state_reference_mappings()
) )

View File

@@ -113,3 +113,17 @@ def validate_icon(name: Union[str, None]):
return return
common.icons.validate_icon(name) common.icons.validate_icon(name)
def validate_uppercase(value: str):
"""Ensure that the provided value is uppercase."""
value = str(value)
if value != value.upper():
raise ValidationError(_('Value must be uppercase'))
def validate_variable_string(value: str):
"""The passed value must be a valid variable identifier string."""
if not re.match(r'^[a-zA-Z_][a-zA-Z0-9_]*$', value):
raise ValidationError(_('Value must be a valid variable identifier'))