Skip to content

Implementing form import options - #6482

Closed
robinmolen wants to merge 28 commits into
feature/6429-form-import/export-export-optionsfrom
feature/6430-form-import-options
Closed

Implementing form import options#6482
robinmolen wants to merge 28 commits into
feature/6429-form-import/export-export-optionsfrom
feature/6430-form-import-options

Conversation

@robinmolen

Copy link
Copy Markdown
Contributor

Closes #6430, #6431
Depends on, and build ontop of #6429

Changes

This PR further extends the import/export module by processing the new export options (#6429), adding additional import options, and updating the form version handling

  1. Refactor of the import code
  2. Added UI for new import options
  3. Preventing duplicate creation of form definitions and additional configuration (product, theme, etc.)
  4. Saving additional configuration as part of the form version
    (this allows us to fully restore a form to its previous version, with the product, theme, category, tile layers and yivi attributes that were used at the time the form version was created)

Checklist

Check off the items that are completed or not relevant.

  • Impact on features

    • Checked copying a form
    • Checked import/export of a form
    • Config checks in the configuration overview admin page
    • Checked new model fields are usable in the admin
    • Problem detection in the admin email digest is handled
  • Dockerfile/scripts

    • Updated the Dockerfile with the necessary scripts from the ./bin folder
  • Commit hygiene

    • Commit messages refer to the relevant Github issue
    • Commit messages explain the "why" of change, not the how
  • Documentation

    • Added documentation which describes the changes

Added the UI components for the form export options.
Allow exporting with export options from the form detail page
…nt logic

The removal of sensitive content is done in the export serializer after validation, as part of `to_representation`.
Each serializer is responsible for removing their own sensitive information.

Because the e-mail registration plugin can be populated from a variable, all places that can set the variable value must be sanitized. This includes the variable initial value, logic rules and component default value.
Implementing the option to exclude form data containing environment-specific data (like registration backends)
Implemented the option to include additional form configuration (like product, map tile layers, category, etc.) in the export data. This makes it possible to share a form with as much information as possible to different municipalities.

Additionally, all additional form configurations that are deliberately excluded will now also be removed from the main form configuration. This ensures that no stale references will be kept in place, which could/would cause importing issues.
Added translations for frontend form export options labels and help texts.
Passing the form import options from the admin view back to the import_form_data method.
When imported, you can decide whether to add, remove or ignore the unknown domains in the email templates.

For the 'remove' option, all email templates will be sanitized before field validation is applied. Ensuring that only links to unknown and explicitly allowed domains remain in the templates.

For the 'accept' option, all unknown domains are gathered and added to the allowlist, before field validation is applied.

The 'ignore' option is a "do nothing" option. If the email templates contain links to unknown domains, validation errors will be triggered and the importing will be canceled.
The serializer-specific import logic has been moved to the respective import serializers. Those now deal with things like applying backwards compatibility code, creating additional data after persisting data, updating uuid's, etc.

The `IMPORT_SERIALIZER_CONFIGS` specifies the serializers and kwargs that are used for the `import_form_data` process.
When importing additional form configuration (product, theme, category, WMS- and WMTS-tile layers and Yivi attribute groups) we perform shallow and deep comparisons.

The shallow comparisons are done for the quick "importing a form into the environment where the importdata was made" situations. This shallow comparison looks of the existing object using the UUID from the importdata.

The deep comparison is for cross-environment situations, using the object data when searching for an already existing variant. This is used when importing a form that was made in another Open Forms environment.

When an existing instance is found, the UUID's in the form data are updated to match with the UUID of the existing instance. The existing instance will remain as it is, the import data won't update the existing configuration.

In case neither comparison returns an existing instance, we create the imported additional object using the configuration from the import data.
When restoring a previous form version, we should import the form blob with as much acceptance as possible. This means re-using form definitions if the configuration has not changed. The links in email templates should not be blindly accepted, as we do not know why they aren't accepted anymore. It could be that a source has been moved to a different domain, that the old domain changed owners, information is no-longer trusted, etc. So, as the quickest solution we should remove unknown domains, to prevent possible errors and security issues.

The form version blob should also be extended to contain the full form configuration. By saving the additional data, like product, alongside the form data, we can ensure full restoration when restoring a previous version.
When restoring a previous version, we know for certain that all direct configuration has not been changed. The product, theme, category, tile layers and Yivi attributes are all as they were when the form version was created.
…nality

The form version restore now save the resources used at the time of creating the form version. This ensures that when restoring a form version, the result is the exact form with the exact resources as before.

Added tests to validate complete saving and restoring, and how form resources will be re-used
converter(configuration)


def remove_key_from_dict(dictionary, key):

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dead code, remove

Comment on lines +21 to +23
The default get_or_init_instance uses the import_id_fields. If there is no match,
we do a deep comparison with the name, description, and attributes, and return
the first match. If there is again no match, we create a new instance.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The default get_or_init_instance uses the import_id_fields. If there is no match,
we do a deep comparison with the name, description, and attributes, and return
the first match. If there is again no match, we create a new instance.
The default get_or_init_instance uses `import_id_fields` to search
resources using their identifiers. If there is no match, we do a deep
comparison with `deep_comparison_fields` and return the first match.
If there is again no match, we create a new instance.

@robinmolen
robinmolen force-pushed the feature/6429-form-import/export-export-options branch 8 times, most recently from 060f3ec to 4da8b11 Compare July 27, 2026 21:03
@robinmolen

Copy link
Copy Markdown
Contributor Author

Replaced by #6509

@robinmolen robinmolen closed this Aug 1, 2026
@robinmolen
robinmolen deleted the feature/6430-form-import-options branch August 1, 2026 14:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant