diff --git a/ckanext/event_audit/config.py b/ckanext/event_audit/config.py index aaeb0a3..5e504b6 100644 --- a/ckanext/event_audit/config.py +++ b/ckanext/event_audit/config.py @@ -16,8 +16,10 @@ CONF_IGNORED_ACTIONS = "ckanext.event_audit.ignore.actions" CONF_IGNORED_MODELS = "ckanext.event_audit.ignore.models" -CONF_DATABASE_TRACK_ENABLED = "ckanext.event_audit.track.model" -CONF_API_TRACK_ENABLED = "ckanext.event_audit.track.api" +CONF_TRACK_MODELS = "ckanext.event_audit.track.models" + +CONF_DATABASE_TRACK_ENABLED = "ckanext.event_audit.track_model" +CONF_API_TRACK_ENABLED = "ckanext.event_audit.track_api" CONF_STORE_PAYLOAD_AND_RESULT = "ckanext.event_audit.store_payload_and_result" @@ -62,6 +64,11 @@ def get_ignored_models() -> list[str]: return tk.config[CONF_IGNORED_MODELS] +def get_tracked_models() -> list[str]: + """A list of database models to track when logging events.""" + return tk.config[CONF_TRACK_MODELS] + + def is_database_log_enabled() -> bool: """Returns True if database logging is enabled.""" return tk.config[CONF_DATABASE_TRACK_ENABLED] diff --git a/ckanext/event_audit/config_declaration.yaml b/ckanext/event_audit/config_declaration.yaml index a166d5f..e9ef32a 100644 --- a/ckanext/event_audit/config_declaration.yaml +++ b/ckanext/event_audit/config_declaration.yaml @@ -55,18 +55,23 @@ groups: editable: true default: Option - - key: ckanext.event_audit.track.model + - key: ckanext.event_audit.track_model description: Enable logging of database events default: true editable: true type: bool - - key: ckanext.event_audit.track.api + - key: ckanext.event_audit.track_api description: Enable logging of API events default: true editable: true type: bool + - key: ckanext.event_audit.track.models + description: A list of models to track + type: list + editable: true + - key: ckanext.event_audit.store_payload_and_result description: Store the payload and result of the event default: false diff --git a/ckanext/event_audit/config_schema.yaml b/ckanext/event_audit/config_schema.yaml index 4ad4b47..a88e0cb 100644 --- a/ckanext/event_audit/config_schema.yaml +++ b/ckanext/event_audit/config_schema.yaml @@ -49,7 +49,7 @@ fields: form_snippet: tom_tags.html required: false - - field_name: ckanext.event_audit.track.model + - field_name: ckanext.event_audit.track_model label: Track Model help_text: Enable logging of database events preset: select @@ -60,7 +60,7 @@ fields: - value: false label: No - - field_name: ckanext.event_audit.track.api + - field_name: ckanext.event_audit.track_api label: Track API help_text: Enable logging of API events preset: select diff --git a/ckanext/event_audit/listeners/database.py b/ckanext/event_audit/listeners/database.py index 1956751..aa54c1c 100644 --- a/ckanext/event_audit/listeners/database.py +++ b/ckanext/event_audit/listeners/database.py @@ -61,12 +61,16 @@ def after_commit(session: SQLAlchemySession): thread_mode_enabled = config.is_threaded_mode_enabled() should_store_complex_data = config.should_store_payload_and_result() + tracked_models = config.get_tracked_models() for action, instances in session._audit_cache.items(): # type: ignore for instance in instances: if isinstance(instance, EventModel): continue + if tracked_models and instance.__class__.__name__ not in tracked_models: + continue + event = repo.build_event( types.EventData( category=const.Category.MODEL.value, diff --git a/ckanext/event_audit/plugin.py b/ckanext/event_audit/plugin.py index 41256f9..bea9bab 100644 --- a/ckanext/event_audit/plugin.py +++ b/ckanext/event_audit/plugin.py @@ -158,7 +158,14 @@ def skip_event(self, event: types.Event) -> bool: if event.category in config.get_ignored_categories(): return True - return event.action_object in config.get_ignored_models() + # track specific models have priority over ignoring specific models + if ( + not config.get_tracked_models() + and event.action_object in config.get_ignored_models() + ): + return True + + return False # IConfigDeclaration diff --git a/ckanext/event_audit/tests/listeners/test_model.py b/ckanext/event_audit/tests/listeners/test_model.py index b5fcbc5..8e0862f 100644 --- a/ckanext/event_audit/tests/listeners/test_model.py +++ b/ckanext/event_audit/tests/listeners/test_model.py @@ -170,3 +170,26 @@ def test_store_payload_and_result( user_idx = 1 assert events[user_idx].payload["name"] == user["name"] + + @pytest.mark.usefixtures("with_plugins", "clean_db") + @pytest.mark.ckan_config(config.CONF_ACTIVE_REPO, "postgres") + @pytest.mark.ckan_config(config.CONF_TRACK_MODELS, ["Dashboard"]) + def test_track_only_specific_models(self, user: dict[str, Any], repo: repositories.AbstractRepository): + events = repo.filter_events(types.Filters()) + + assert len(events) == 1 + assert events[0].action_object == "Dashboard" + + @pytest.mark.usefixtures("with_plugins", "clean_db") + @pytest.mark.ckan_config(config.CONF_ACTIVE_REPO, "postgres") + @pytest.mark.ckan_config(config.CONF_TRACK_MODELS, ["Dashboard"]) + @pytest.mark.ckan_config(config.CONF_IGNORED_MODELS, ["Dashboard"]) + def test_track_have_priority_over_ignore(self, user: dict[str, Any], repo: repositories.AbstractRepository): + assert config.get_tracked_models() == ["Dashboard"] + assert config.get_ignored_models() == ["Dashboard"] + + events = repo.filter_events(types.Filters()) + + assert len(events) == 1 + assert events[0].action_object == "Dashboard" + diff --git a/docs/configure/tracking.md b/docs/configure/tracking.md index e5cc0c2..0451a8c 100644 --- a/docs/configure/tracking.md +++ b/docs/configure/tracking.md @@ -9,7 +9,7 @@ Captures all events that are triggered by the CKAN API. Everything that is calle To disable the API tracker, specify this in the configuration file: ```ini -ckanext.event_audit.track.api = false +ckanext.event_audit.track_api = false ``` We can ignore specific actions from being tracked by setting the `ckanext.event_audit.ignore.actions` configuration option. See the [ignore](ignore.md) section for more details. @@ -21,7 +21,7 @@ We're utilising the SQLAlchemy’s event system for tracking database interactio To disable the Database tracker, specify this in the configuration file: ```ini -ckanext.event_audit.track.model = false +ckanext.event_audit.track_model = false ``` We can ignore specific models from being tracked by setting the `ckanext.event_audit.ignore.models` configuration option. See the [ignore](ignore.md) section for more details. @@ -40,3 +40,15 @@ ckanext.event_audit.store_payload_and_result = true ## Custom trackers You can create and write an event anywhere in your codebase. See the [usage](../usage.md) section for more details. + +## Track only specific models + +If you want to track only specific models, you can set the `ckanext.event_audit.track.models` configuration option. This will ignore all the models that are not specified in the list. + +```ini +ckanext.event_audit.track.models = Package Resource User +``` + +???+ Warning + 1. The model names are case-sensitive. + 2. Tracking specific models have a priority over ignoring specific models. If you specify the models to track, the ignore list will be ignored. diff --git a/pyproject.toml b/pyproject.toml index deaaf7b..7ddf176 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "ckanext-event-audit" -version = "1.0.0" +version = "1.0.1" description = "" classifiers = [ "Development Status :: 4 - Beta", diff --git a/test.ini b/test.ini index ac2794d..44d2762 100644 --- a/test.ini +++ b/test.ini @@ -17,8 +17,8 @@ ckanext.event_audit.cloudwatch.region = ap-southeast-2 # disable tracking of model and api events for tests # we're going to enable it only for specific tests -ckanext.event_audit.track.model = false -ckanext.event_audit.track.api = false +ckanext.event_audit.track_model = false +ckanext.event_audit.track_api = false # disable threaded mode for tests, as it's requires timeout for the tests to pass ckanext.event_audit.threaded_mode = false