diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 6c293f86..17a3fd46 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -16,6 +16,15 @@ Unreleased * +0.20.0 - 2025-11-27 +******************** + +Added +===== + +* Add configurable logging level for Casbin enforcer via ``CASBIN_LOG_LEVEL`` setting (defaults to WARNING). + + 0.19.2 - 2025-11-25 ******************** diff --git a/openedx_authz/__init__.py b/openedx_authz/__init__.py index 839432d0..c158cdcc 100644 --- a/openedx_authz/__init__.py +++ b/openedx_authz/__init__.py @@ -4,6 +4,6 @@ import os -__version__ = "0.19.2" +__version__ = "0.20.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 950a1962..123b1d75 100644 --- a/openedx_authz/engine/enforcer.py +++ b/openedx_authz/engine/enforcer.py @@ -16,9 +16,11 @@ """ import logging +from copy import deepcopy from uuid import uuid4 from casbin import SyncedEnforcer +from casbin.util.log import DEFAULT_LOGGING, configure_logging from casbin_adapter.enforcer import initialize_enforcer from django.conf import settings @@ -154,6 +156,19 @@ def configure_enforcer_auto_save_and_load(cls): cls.configure_enforcer_auto_save(auto_save_policy) + @classmethod + def _configure_logging(cls) -> None: + """Configure logging levels for Casbin's internal loggers. + + This controls the verbosity of Casbin's policy evaluation and role management + logging. The log level defaults to WARNING if CASBIN_LOG_LEVEL is not set. + """ + log_level = getattr(settings, "CASBIN_LOG_LEVEL", "WARNING") + casbin_logging = deepcopy(DEFAULT_LOGGING) + for logger_name in casbin_logging["loggers"]: + casbin_logging["loggers"][logger_name]["level"] = log_level + configure_logging(casbin_logging) + @classmethod def load_policy_if_needed(cls): """Load policy if the last load version indicates it's needed. @@ -246,6 +261,10 @@ def _initialize_enforcer(cls) -> SyncedEnforcer: # Avoid circular import from openedx_authz.engine.matcher import is_admin_or_superuser_check # pylint: disable=import-outside-toplevel + # Configure logging BEFORE initialize_enforcer() because it creates a ProxyEnforcer + # that doesn't pass logging config and would use Casbin's defaults + cls._configure_logging() + db_alias = getattr(settings, "CASBIN_DB_ALIAS", "default") try: diff --git a/openedx_authz/settings/common.py b/openedx_authz/settings/common.py index 32dc2384..03662a6c 100644 --- a/openedx_authz/settings/common.py +++ b/openedx_authz/settings/common.py @@ -45,3 +45,8 @@ def plugin_settings(settings): # Set default ContentLibrary model for swappable dependency if not hasattr(settings, "OPENEDX_AUTHZ_CONTENT_LIBRARY_MODEL"): settings.OPENEDX_AUTHZ_CONTENT_LIBRARY_MODEL = "content_libraries.ContentLibrary" + + # Set default CASBIN_LOG_LEVEL if not already set. + # This setting defines the logging level for the Casbin enforcer. + if not hasattr(settings, "CASBIN_LOG_LEVEL"): + settings.CASBIN_LOG_LEVEL = "WARNING"