Skip to content

Commit

Permalink
[#4810] Prevent parsing changes to the formVariable initial_value
Browse files Browse the repository at this point in the history
Backport-of: #4810
  • Loading branch information
robinmolen authored and vaszig committed Nov 20, 2024
1 parent 3f955b6 commit ceb3dad
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 0 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
Changelog
=========

Upgrade notes
-------------

* [:backend:`4810`] Fixed uppercase component variable values turing lowercase.
There are manual actions required.

2.8.1 (2024-10-29)
==================

Expand Down
60 changes: 60 additions & 0 deletions bin/fix_selectboxes_component_default_values.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env python
#
# Fix the initial values of form variables related to selectboxes components.
#
# Due to a bug in the JSON parser, some of the form variable initial value don't match with
# their respective component default values. This bug is mostly an issue for selectboxes components.
# The problem in the JSON parser has been fixed, so new and updated forms won't have this issue.
#
# This script automatically fixes all initial values of the selectboxes component form variables.
# Related to ticket: https://github.com/open-formulieren/open-forms/issues/4810
from __future__ import annotations

import sys
from pathlib import Path

import django

SRC_DIR = Path(__file__).parent.parent / "src"
sys.path.insert(0, str(SRC_DIR.resolve()))


def fix_selectboxes_default_values():
from django.db.models import Q

from openforms.formio.utils import get_component_default_value
from openforms.forms.models import FormDefinition, FormVariable

variables_to_update = []
fds = FormDefinition.objects.iterator()
for form_definition in fds:
for component in form_definition.iter_components():
# The fix is only needed for selectboxes components
if component["type"] != "selectboxes":
continue

# Update all form variables related to the component and form definition,
# when the form variable initial value doesn't match the component default value
form_variables = FormVariable.objects.filter(
~Q(initial_value=get_component_default_value(component)),
key=component["key"],
form_definition_id=form_definition.id,
)
for form_variable in form_variables:
form_variable.initial_value = get_component_default_value(component)
variables_to_update.append(form_variable)

FormVariable.objects.bulk_update(variables_to_update, fields=["initial_value"])


def main(**kwargs):
from openforms.setup import setup_env

setup_env()
django.setup()

return fix_selectboxes_default_values(**kwargs)


if __name__ == "__main__":
main()
6 changes: 6 additions & 0 deletions src/openforms/forms/api/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,27 @@ class IgnoreConfigurationFieldCamelCaseJSONParser(CamelCaseJSONParser):


class FormVariableJSONParser(CamelCaseJSONParser):
# The field initial_value needs to be ignored, to prevent accidental uppercase to lowercase changes.
# See github issue https://github.com/open-formulieren/open-forms/issues/4810
json_underscoreize = {
"ignore_fields": (
"body",
"headers",
"initial_value",
"mapping_expression",
"query_params",
)
}


class FormVariableJSONRenderer(CamelCaseJSONRenderer):
# The field initial_value needs to be ignored, to prevent accidental uppercase to lowercase changes.
# See github issue https://github.com/open-formulieren/open-forms/issues/4810
json_underscoreize = {
"ignore_fields": (
"body",
"headers",
"initial_value",
"mapping_expression",
"query_params",
)
Expand Down
53 changes: 53 additions & 0 deletions src/openforms/forms/tests/variables/test_viewset.py
Original file line number Diff line number Diff line change
Expand Up @@ -936,3 +936,56 @@ def test_validate_prefill_consistency(self):
error["invalidParams"][0]["name"],
"0.prefillAttribute",
)

def test_bulk_create_and_update_with_non_camel_case_initial_values(self):
user = StaffUserFactory.create(user_permissions=["change_form"])
self.client.force_authenticate(user)

form = FormFactory.create(generate_minimal_setup=True)
form_definition = form.formstep_set.get().form_definition
form_path = reverse("api:form-detail", kwargs={"uuid_or_slug": form.uuid})
form_url = f"http://testserver.com{form_path}"
form_definition_path = reverse(
"api:formdefinition-detail", kwargs={"uuid": form_definition.uuid}
)
form_definition_url = f"http://testserver.com{form_definition_path}"

data = [
{
"form": form_url,
"form_definition": form_definition_url,
"key": form_definition.configuration["components"][0]["key"],
"name": "Test",
"service_fetch_configuration": None,
"data_type": FormVariableDataTypes.object,
"source": FormVariableSources.component,
"initial_value": {
"VALUE IN UPPERCASE": True,
"VALUE-IN-UPPER-KEBAB-CASE": True,
"VALUE_IN_UPPER_SNAKE_CASE": False,
"value in lower case": False,
"value-in-lower-kebab-case": False,
"value_in_lower_snake_case": True,
},
}
]

response = self.client.put(
reverse(
"api:form-variables",
kwargs={"uuid_or_slug": form.uuid},
),
data=data,
)

expected_initial_value = {
"VALUE IN UPPERCASE": True,
"VALUE-IN-UPPER-KEBAB-CASE": True,
"VALUE_IN_UPPER_SNAKE_CASE": False,
"value in lower case": False,
"value-in-lower-kebab-case": False,
"value_in_lower_snake_case": True,
}

self.assertEqual(status.HTTP_200_OK, response.status_code)
self.assertEqual(expected_initial_value, response.json()[0]["initialValue"])

0 comments on commit ceb3dad

Please sign in to comment.