diff --git a/CHANGELOG.rst b/CHANGELOG.rst index fa5e87d3..4e1283d5 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -14,6 +14,19 @@ Change Log Unreleased ********** +* + +0.8.0 - 2025-10-24 +****************** + +Added +===== + +* Allow disabling auto-load and auto-save of policies by setting CASBIN_AUTO_LOAD_POLICY_INTERVAL to -1. + +Changed +======= + * Migrate from using pycodestyle and isort to ruff for code quality checks and formatting. * Enhance enforcement command with dual operational modes (database and file mode). diff --git a/openedx_authz/__init__.py b/openedx_authz/__init__.py index 1415675a..28dd401f 100644 --- a/openedx_authz/__init__.py +++ b/openedx_authz/__init__.py @@ -4,6 +4,6 @@ import os -__version__ = "0.7.0" +__version__ = "0.8.0" ROOT_DIRECTORY = os.path.dirname(os.path.abspath(__file__)) diff --git a/openedx_authz/engine/enforcer.py b/openedx_authz/engine/enforcer.py index 0e45ac9c..cc591276 100644 --- a/openedx_authz/engine/enforcer.py +++ b/openedx_authz/engine/enforcer.py @@ -93,7 +93,12 @@ def _initialize_enforcer() -> SyncedEnforcer: adapter = ExtendedAdapter() enforcer = SyncedEnforcer(settings.CASBIN_MODEL, adapter) - enforcer.start_auto_load_policy(settings.CASBIN_AUTO_LOAD_POLICY_INTERVAL) - enforcer.enable_auto_save(True) + auto_load_policy_interval = getattr(settings, "CASBIN_AUTO_LOAD_POLICY_INTERVAL", 0) + if auto_load_policy_interval > 0: + enforcer.start_auto_load_policy(auto_load_policy_interval) + enforcer.enable_auto_save(True) + else: + # Disable auto-save to prevent unnecessary database writes + enforcer.enable_auto_save(False) return enforcer diff --git a/openedx_authz/tests/api/test_roles.py b/openedx_authz/tests/api/test_roles.py index ffac5f9c..0f4441ac 100644 --- a/openedx_authz/tests/api/test_roles.py +++ b/openedx_authz/tests/api/test_roles.py @@ -94,6 +94,9 @@ def setUpClass(cls): """ super().setUpClass() AuthzEnforcer.get_enforcer().stop_auto_load_policy() + # Enable auto-save to ensure policies are saved to the database + # This is necessary because the tests are not using auto-load policy + AuthzEnforcer.get_enforcer().enable_auto_save(True) cls._seed_database_with_policies() def setUp(self): diff --git a/openedx_authz/tests/test_enforcer.py b/openedx_authz/tests/test_enforcer.py index 6d2dccdc..878a3c3c 100644 --- a/openedx_authz/tests/test_enforcer.py +++ b/openedx_authz/tests/test_enforcer.py @@ -520,3 +520,40 @@ def test_auto_load_policy_detects_changes(self): # After auto-load, the new role assignment should be loaded policies_after_auto_load = global_enforcer.get_grouping_policy() self.assertIn(new_assignment, policies_after_auto_load) + + @override_settings(CASBIN_AUTO_LOAD_POLICY_INTERVAL=-1) + def test_auto_load_disabled(self): + """Test that auto-load can be disabled by setting interval to -1. + + This test verifies that when CASBIN_AUTO_LOAD_POLICY_INTERVAL is set to -1, + the enforcer does NOT automatically load policies from the database. + + Expected result: + - Policies remain empty after seeding database + - Manual load_policy() is required to load policies + - New policies don't appear without manual reload + """ + global_enforcer = AuthzEnforcer.get_enforcer() + + # Initial policy count should be 0 + initial_policy_count = len(global_enforcer.get_policy()) + self.assertEqual(initial_policy_count, 0) + + # Policies should still be empty since auto-load is disabled + # and no database queries should have been made + with self.assertNumQueries(0): + time.sleep(1.0) + policies_after_wait = global_enforcer.get_policy() + self.assertEqual(len(policies_after_wait), 0) + + # Seed the database with policies + self._seed_database_with_policies() + + # Manually load policies + with self.assertNumQueries(1): + time.sleep(1.0) + global_enforcer.load_policy() + # Since auto-save is also disabled, the policies should still + # be empty after manual load + policies_after_manual_load = global_enforcer.get_policy() + self.assertEqual(len(policies_after_manual_load), 0)