From 8c837043beb5eb06d2ef14da1e9679505787c118 Mon Sep 17 00:00:00 2001 From: Viktor van Wijk Date: Thu, 30 Jan 2025 15:40:45 +0100 Subject: [PATCH] :sparkles: [#5012] Add metadata to JSON dump configuration options Also add support for an extra static variables registry in generate_json_schema --- src/openforms/forms/json_schema.py | 19 +++++-- .../registrations/contrib/json_dump/config.py | 25 +++++++++ .../registrations/contrib/json_dump/plugin.py | 53 +++++++++++++++---- 3 files changed, 85 insertions(+), 12 deletions(-) diff --git a/src/openforms/forms/json_schema.py b/src/openforms/forms/json_schema.py index 96c732db14..5f691c7182 100644 --- a/src/openforms/forms/json_schema.py +++ b/src/openforms/forms/json_schema.py @@ -4,20 +4,32 @@ from openforms.variables.service import get_static_variables from .models import Form, FormVariable +from ..plugins.registry import BaseRegistry +from ..variables.base import BaseStaticVariable -def _iter_form_variables(form: Form) -> Iterator[FormVariable]: +def _iter_form_variables( + form: Form, variables_registry: BaseRegistry[BaseStaticVariable] | None = None +) -> Iterator[FormVariable]: """Iterate over static variables and all form variables. :param form: Form + :param variables_registry: Optional registry of static variables. """ # Static variables are always available yield from get_static_variables() + # If the optional variables registry is passed + if variables_registry is not None: + yield from get_static_variables(variables_registry=variables_registry) # Handle from variables holding dynamic data (component and user defined) yield from form.formvariable_set.all() -def generate_json_schema(form: Form, limit_to_variables: Sequence[str]) -> JSONObject: +def generate_json_schema( + form: Form, + limit_to_variables: Sequence[str], + variables_registry: BaseRegistry[BaseStaticVariable] | None = None, +) -> JSONObject: """Generate a JSON schema from a form, for the specified variables. Note: this schema is an informative description of the variables and should not be @@ -25,12 +37,13 @@ def generate_json_schema(form: Form, limit_to_variables: Sequence[str]) -> JSONO :param form: The form to generate JSON schema for. :param limit_to_variables: Variables that will be included in the schema. + :param variables_registry: Optional registry of static variables. :returns: A JSON schema representing the form variables. """ requested_variables_schema = { key: variable.as_json_schema() - for variable in _iter_form_variables(form) + for variable in _iter_form_variables(form, variables_registry) if (key := variable.key) in limit_to_variables } diff --git a/src/openforms/registrations/contrib/json_dump/config.py b/src/openforms/registrations/contrib/json_dump/config.py index 724ec4e19b..1ead0651e6 100644 --- a/src/openforms/registrations/contrib/json_dump/config.py +++ b/src/openforms/registrations/contrib/json_dump/config.py @@ -47,6 +47,29 @@ class JSONDumpOptionsSerializer(JsonSchemaSerializerMixin, serializers.Serialize required=True, min_length=1, ) + required_metadata_variables = serializers.ListField( + child=FormioVariableKeyField(), + default=[ + "public_reference", + "form_name", + "form_version", + "registration_timestamp", + "auth_type", + ], + label=_("Required metadata variable key list"), + help_text=_( + "A list of required variables to use in the metadata. These include " + "the registration variables of the JSON dump plugin" + ), + required=False, + ) + additional_metadata_variables = serializers.ListField( + child=FormioVariableKeyField(), + label=_("Additional metadata variable key list"), + help_text=_("A list of additional variables to use in the metadata"), + required=False, + default=[], + ) class JSONDumpOptions(TypedDict): @@ -60,3 +83,5 @@ class JSONDumpOptions(TypedDict): service: Service path: str variables: list[str] + required_metadata_variables: list[str] + additional_metadata_variables: list[str] diff --git a/src/openforms/registrations/contrib/json_dump/plugin.py b/src/openforms/registrations/contrib/json_dump/plugin.py index b377d0f6a4..12f89e66bb 100644 --- a/src/openforms/registrations/contrib/json_dump/plugin.py +++ b/src/openforms/registrations/contrib/json_dump/plugin.py @@ -16,15 +16,18 @@ SelectComponent, ) from openforms.forms.json_schema import generate_json_schema +from openforms.forms.models import FormVariable from openforms.submissions.models import Submission, SubmissionFileAttachment from openforms.submissions.service import DataContainer from openforms.typing import JSONObject from openforms.utils.json_schema import to_multiple from openforms.variables.constants import FormVariableSources +from openforms.variables.service import get_static_variables from ...base import BasePlugin # openforms.registrations.base from ...registry import register # openforms.registrations.registry from .config import JSONDumpOptions, JSONDumpOptionsSerializer +from .registration_variables import register as variables_registry @register("json_dump") @@ -38,27 +41,56 @@ def register_submission( ) -> dict: state = submission.load_submission_value_variables_state() - # Generate values # TODO: keys with a period (e.g. `foo.bar`) will currently not be added to the # submission data. This will be fixed with issue 5041 + # Get static values + static_values = state.get_static_data() + # Update static values with registration variables + static_values.update(state.get_static_data(other_registry=variables_registry)) + all_values: JSONObject = { - **state.get_static_data(), + **static_values, **state.get_data(), # dynamic values from user input } + + # Values values = { key: value for key, value in all_values.items() if key in options["variables"] } - - # Generate schema - schema = generate_json_schema(submission.form, options["variables"]) - - # Post-processing - post_process(values, schema, submission) + values_schema = generate_json_schema(submission.form, options["variables"]) + post_process(values, values_schema, submission) + + # Metadata + # Note: as the metadata contains static variables (TODO-5012: do we need a validator for this?) + # no post-processing is required. + metadata_variables = [ + *options["required_metadata_variables"], + *options["additional_metadata_variables"], + ] + metadata = { + key: value for key, value in all_values.items() if key in metadata_variables + } + # TODO-5012: maybe it is better to just generate the schemas here by iterating + # over get_static_variables(), as we don't need the dynamic values anyway. + # Though, all the schema generation will stay together now, which is also nice + metadata_schema = generate_json_schema( + submission.form, + metadata_variables, + variables_registry=variables_registry, + ) # Send to the service - data = json.dumps({"values": values, "schema": schema}, cls=DjangoJSONEncoder) + data = json.dumps( + { + "values": values, + "values_schema": values_schema, + "metadata": metadata, + "metadata_schema": metadata_schema, + }, + cls=DjangoJSONEncoder, + ) service = options["service"] with build_client(service) as client: if ".." in (path := options["path"]): @@ -73,6 +105,9 @@ def check_config(self) -> None: # Config checks are not really relevant for this plugin right now pass + def get_variables(self) -> list[FormVariable]: + return get_static_variables(variables_registry=variables_registry) + def post_process( values: JSONObject, schema: JSONObject, submission: Submission