www/nginx: fix orphaned sni_hostname_upstream_map_item / ip_acl_item on edit - #5654
www/nginx: fix orphaned sni_hostname_upstream_map_item / ip_acl_item on edit#5654muchachagrande wants to merge 3 commits into
Conversation
|
Hi! Agreed on the root cause. But I think the proposed changes can still leave orphan rows.
delete_uuids() is still used, and it swallows all exceptions (including a failed UUID delete). After the intermediate save, safe-delete should succeed on the happy path — but what if something still blocks the delete?
A model migration is also needed to purge orphans already left by #5650 (and a model version bump)? |
|
Hi @kulikov-a. Thanks for the detailed review. I agree that these points are valid, particularly the possibility of leaving orphan rows if the intermediate save succeeds but setBase() subsequently fails. I’ll investigate the proposed approach, including factoring the shared regeneration logic, avoiding delete_uuids(), and adding a model migration to clean up existing orphan rows. I'll push a follow-up commit once I've tested it. |
Drop delBase()/delete_uuids() in favor of ArrayField::del(), factor shared logic into regenerate_map_items() and add a model migration to purge orphans left by installations already affected by opnsense#5650.
|
Pushed a follow-up commit addressing all three points:
Tested: repeated edits on maps/ACLs with no orphans left, ran the |
|
Hi! Thanks, this looks good to me ) One optional note: in the migration it may be safer not to del() while iterating the live collection. Can collect the orphan uuids first, then delete after the loop (same style as in https://github.com/opnsense/core/blob/master/src/opnsense/mvc/app/models/OPNsense/IDS/Migrations/M1_0_6.php) |
|
I've got your point. It is safer to iterate the collection in a first step and mutate it in a second one. |
Important notices
Before you submit a pull request, we ask you kindly to acknowledge the following:
If AI was used, please disclose:
Describe the problem
regenerate_hostname_map()/regenerate_ipacl()inSettingsController.phpdeleted the previous child itemssni_hostname_upstream_map_item/ip_acl_item) on every edit, but the parent'sdatafield (a comma-separated list of child uuids) still referenced the old uuids at delete time. BecauseSettingsControlleruses$internalModelUseSafeDelete = true, the safe-delete check does a raw text search over the whole config.xml, finds this self-reference, and blocks the delete; the exception is silently caught, so the old items are left as permanent orphans. Editing the same map/ACL repeatedly accumulates orphans, and each orphan still references a real upstream server, which then can no longer be deleted ("in use").Two related issues surfaced while fixing this:
ValidationException(raw stack trace) instead of a normal validationmessage.
cleared/deleted, cancelling in the GUI left the configuration
partially modified, since the failed attempt had already been
persisted to disk.
Describe the proposed solution
New items are now built and fully validated in memory before anything is written to disk. If the submitted set is empty, or any row fails validation, the request returns a normal
{result: "failed", validations: {...}}response without touching the existing configuration. Only once the new items are known valid does the function clear the parent'sdatafield, persist that intermediate state to disk (required, sincedelBase()'sConfig::lock()reloads from disk on its first call in the request and would otherwise discard an in-memory-only change), and then delete the old child items. Same fix applied toregenerate_ipacl().Related issue
Fixes #5650