Server settings: \"Not set here\" in a three-state policy select is saved as \"No\ #493
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#493
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found on 2026-09-29 in a read-only review of postulo at
95348908d, readingPolicyFieldand cleaning an empty value with it.Checked again on 2026-10-01 against
mainat0a5cad587: still present.PolicyFieldoffers three states, "Not set here — the environment or the default applies", "Yes" and "No", and the model stores the first asNULL. The first state can never be saved: choosing it storesFalse, and the page shows "No" after saving.core/server_forms.py:19-36,PolicyField. The converter is a static method named_coerce, which shadowsTypedChoiceField._coerce, the methodTypedChoiceField.clean()calls to turn an empty value intoempty_valuebefore converting anything else.clean("")runs the field's own converter on the empty string and returns"" == "true", which isFalse;empty_value=Noneis never used. Checked:PolicyField().clean("")andPolicyField().clean(None)both returnFalse, and posting the Sign-in page withregistration_openempty over a storedTrueleavesFalsein the row. It affects everyPolicyField:registration_open,sso_is_second_factorandemail_sign_inon Sign-in, andcapture_ignore_robots,capture_keep_sourceandcapture_keep_renderingon Capture.Falsetoday, so what the instance does is the same, but the stored state is wrong, and any policy whose fallback isTruewould be switched off by choosing "Not set here"._to_bool) and passcoerce=self._to_bool, leavingTypedChoiceField._coercein place, so an empty choice becomesNone.Done when
tests/test_server_settings.pyhas a test that storesregistration_open = True, posts the Sign-in page withregistration_openempty and findsNonestored, and the page drawing "Not set here" as the selected option. It fails today.