Validate fields used in custom form config
This commit is contained in:
parent
aa77a10de2
commit
5cc582b638
1 changed files with 72 additions and 0 deletions
|
|
@ -178,8 +178,80 @@ class ServiceDefinitionAdminForm(forms.ModelForm):
|
||||||
{"form_config": _("Schema error: {}").format(e.message)}
|
{"form_config": _("Schema error: {}").format(e.message)}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self._validate_field_mappings(form_config, cleaned_data)
|
||||||
|
|
||||||
return cleaned_data
|
return cleaned_data
|
||||||
|
|
||||||
|
def _validate_field_mappings(self, form_config, cleaned_data):
|
||||||
|
if not self.instance.pk:
|
||||||
|
return
|
||||||
|
crd = self.instance.offering_control_planes.all().first()
|
||||||
|
if not crd:
|
||||||
|
return
|
||||||
|
|
||||||
|
schema = None
|
||||||
|
try:
|
||||||
|
schema = crd.resource_schema
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if not schema or not (spec_schema := schema.get("properties", {}).get("spec")):
|
||||||
|
return
|
||||||
|
|
||||||
|
valid_paths = self._extract_field_paths(spec_schema, "spec") | {"name"}
|
||||||
|
included_mappings = set()
|
||||||
|
errors = []
|
||||||
|
for fieldset in form_config.get("fieldsets", []):
|
||||||
|
for field in fieldset.get("fields", []):
|
||||||
|
mapping = field.get("controlplane_field_mapping")
|
||||||
|
included_mappings.add(mapping)
|
||||||
|
if mapping and mapping not in valid_paths:
|
||||||
|
field_name = field.get("name", mapping)
|
||||||
|
errors.append(
|
||||||
|
_(
|
||||||
|
"Field '{}' has invalid mapping '{}'. Valid paths are: {}"
|
||||||
|
).format(
|
||||||
|
field_name,
|
||||||
|
mapping,
|
||||||
|
", ".join(sorted(valid_paths)[:10])
|
||||||
|
+ ("..." if len(valid_paths) > 10 else ""),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if "name" not in included_mappings:
|
||||||
|
raise forms.ValidationError(
|
||||||
|
{
|
||||||
|
"form_config": _(
|
||||||
|
"You must include a `name` field in the custom form config."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if errors:
|
||||||
|
raise forms.ValidationError({"form_config": errors})
|
||||||
|
|
||||||
|
def _extract_field_paths(self, schema, prefix=""):
|
||||||
|
paths = set()
|
||||||
|
|
||||||
|
if not isinstance(schema, dict):
|
||||||
|
return paths
|
||||||
|
|
||||||
|
if "type" in schema and schema["type"] != "object":
|
||||||
|
if prefix:
|
||||||
|
paths.add(prefix)
|
||||||
|
|
||||||
|
if schema.get("properties"):
|
||||||
|
for prop_name, prop_schema in schema["properties"].items():
|
||||||
|
new_prefix = f"{prefix}.{prop_name}" if prefix else prop_name
|
||||||
|
paths.add(new_prefix)
|
||||||
|
paths.update(self._extract_field_paths(prop_schema, new_prefix))
|
||||||
|
|
||||||
|
if schema.get("type") == "array" and "items" in schema:
|
||||||
|
if prefix:
|
||||||
|
paths.add(prefix)
|
||||||
|
|
||||||
|
return paths
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
self.instance.api_definition = self.cleaned_data["api_definition"]
|
self.instance.api_definition = self.cleaned_data["api_definition"]
|
||||||
return super().save(*args, **kwargs)
|
return super().save(*args, **kwargs)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue