diff --git a/openedx_filters/learning/filters.py b/openedx_filters/learning/filters.py index 6db44fd3..d939e97e 100644 --- a/openedx_filters/learning/filters.py +++ b/openedx_filters/learning/filters.py @@ -1445,3 +1445,41 @@ def run_filter(cls, schedules: QuerySet) -> QuerySet | None: """ data = super().run_pipeline(schedules=schedules) return data.get("schedules") + + +class AccountSettingsReadOnlyFieldsRequested(OpenEdxPublicFilter): + """ + Filter used to expand the set of read-only fields on the account settings API. + + Purpose: + This filter is triggered when the account settings API validates which fields + may be updated for a given user. Pipeline steps may add field names to + ``readonly_fields`` to mark those fields as read-only for the requesting user. + + Filter Type: + org.openedx.learning.account.settings.read_only_fields.requested.v1 + + Trigger: + - Repository: openedx/openedx-platform + - Path: openedx/core/djangoapps/user_api/accounts/api.py + - Function or Method: _validate_read_only_fields + """ + + filter_type = "org.openedx.learning.account.settings.read_only_fields.requested.v1" + + @classmethod + def run_filter(cls, readonly_fields: set, user: Any) -> set: + """ + Process the readonly_fields set using the configured pipeline steps. + + Arguments: + readonly_fields (set): the set of field names the caller considers read-only. + Pipeline steps add field names to this set to mark additional fields as + read-only. + user (User): the Django User whose account settings are being updated. + + Returns: + set: the (possibly expanded) set of read-only field names. + """ + data = super().run_pipeline(readonly_fields=readonly_fields, user=user) + return data.get("readonly_fields", set()) diff --git a/openedx_filters/learning/tests/test_filters.py b/openedx_filters/learning/tests/test_filters.py index b4ccf69a..134d7c5e 100644 --- a/openedx_filters/learning/tests/test_filters.py +++ b/openedx_filters/learning/tests/test_filters.py @@ -8,6 +8,7 @@ from django.test import TestCase from openedx_filters.learning.filters import ( + AccountSettingsReadOnlyFieldsRequested, AccountSettingsRenderStarted, CertificateCreationRequested, CertificateRenderStarted, @@ -801,3 +802,33 @@ def test_schedule_requested(self): result = ScheduleQuerySetRequested.run_filter(schedules) self.assertEqual(schedules, result) + + +class TestAccountSettingsReadOnlyFieldsRequestedFilter(TestCase): + """ + Tests for the AccountSettingsReadOnlyFieldsRequested filter. + """ + + def test_run_filter_returns_empty_set_unchanged_when_no_pipeline(self): + """ + When no pipeline steps are configured, run_filter returns the original readonly_fields. + """ + readonly_fields = set() + user = Mock() + + with patch.object( + AccountSettingsReadOnlyFieldsRequested, + "run_pipeline", + return_value={"readonly_fields": readonly_fields}, + ): + result = AccountSettingsReadOnlyFieldsRequested.run_filter( + readonly_fields=readonly_fields, user=user + ) + + self.assertEqual(result, readonly_fields) + + def test_filter_type(self): + self.assertEqual( + AccountSettingsReadOnlyFieldsRequested.filter_type, + "org.openedx.learning.account.settings.read_only_fields.requested.v1", + )