Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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).

Expand Down
2 changes: 1 addition & 1 deletion openedx_authz/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@

import os

__version__ = "0.7.0"
__version__ = "0.8.0"

ROOT_DIRECTORY = os.path.dirname(os.path.abspath(__file__))
9 changes: 7 additions & 2 deletions openedx_authz/engine/enforcer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 3 additions & 0 deletions openedx_authz/tests/api/test_roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
37 changes: 37 additions & 0 deletions openedx_authz/tests/test_enforcer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Copy link
Copy Markdown
Member

@mariajgrimaldi mariajgrimaldi Oct 24, 2025

Choose a reason for hiding this comment

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

Can we also make sure there are no SQL queries run in the background against the DB during this?

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.

Yes, that's right! Thanks. I updated the unit test to check the queries.

"""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)