mirror of
https://github.com/jazzband/django-auditlog.git
synced 2026-03-16 22:20:26 +00:00
Add ability to globally mask fields by name on all models. (#702)
* Add ability to globally mask fields by name on all models. Fixes https://github.com/jazzband/django-auditlog/issues/701 * Add feature explanation in `usage.rst` file. * Add a record to CHANGELOG.md file. * Add test coverage.
This commit is contained in:
parent
fb3fac5cce
commit
c4907bcd52
5 changed files with 82 additions and 0 deletions
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#### Improvements
|
||||
|
||||
- feat: Support masking field names globally when ```AUDITLOG_INCLUDE_ALL_MODELS``` is enabled
|
||||
via `AUDITLOG_MASK_TRACKING_FIELDS` setting. ([#702](https://github.com/jazzband/django-auditlog/pull/702))
|
||||
- feat: Added 'LogEntry.actor_email` field. ([#641](https://github.com/jazzband/django-auditlog/pull/641))
|
||||
- Add Python 3.13 support. ([#671](https://github.com/jazzband/django-auditlog/pull/671))
|
||||
- feat: Added `LogEntry.remote_port` field. ([#671](https://github.com/jazzband/django-auditlog/pull/671))
|
||||
|
|
|
|||
|
|
@ -21,6 +21,11 @@ settings.AUDITLOG_EXCLUDE_TRACKING_FIELDS = getattr(
|
|||
settings, "AUDITLOG_EXCLUDE_TRACKING_FIELDS", ()
|
||||
)
|
||||
|
||||
# Mask named fields across all models
|
||||
settings.AUDITLOG_MASK_TRACKING_FIELDS = getattr(
|
||||
settings, "AUDITLOG_MASK_TRACKING_FIELDS", ()
|
||||
)
|
||||
|
||||
# Disable on raw save to avoid logging imports and similar
|
||||
settings.AUDITLOG_DISABLE_ON_RAW_SAVE = getattr(
|
||||
settings, "AUDITLOG_DISABLE_ON_RAW_SAVE", False
|
||||
|
|
|
|||
|
|
@ -107,6 +107,9 @@ class AuditlogModelRegistry:
|
|||
for fld in settings.AUDITLOG_EXCLUDE_TRACKING_FIELDS:
|
||||
exclude_fields.append(fld)
|
||||
|
||||
for fld in settings.AUDITLOG_MASK_TRACKING_FIELDS:
|
||||
mask_fields.append(fld)
|
||||
|
||||
def registrar(cls):
|
||||
"""Register models for a given class."""
|
||||
if not issubclass(cls, Model):
|
||||
|
|
@ -300,6 +303,15 @@ class AuditlogModelRegistry:
|
|||
"setting 'AUDITLOG_INCLUDE_ALL_MODELS' must be set to 'True'"
|
||||
)
|
||||
|
||||
if (
|
||||
settings.AUDITLOG_MASK_TRACKING_FIELDS
|
||||
and not settings.AUDITLOG_INCLUDE_ALL_MODELS
|
||||
):
|
||||
raise ValueError(
|
||||
"In order to use 'AUDITLOG_MASK_TRACKING_FIELDS', "
|
||||
"setting 'AUDITLOG_INCLUDE_ALL_MODELS' must be set to 'True'"
|
||||
)
|
||||
|
||||
if not isinstance(settings.AUDITLOG_INCLUDE_TRACKING_MODELS, (list, tuple)):
|
||||
raise TypeError(
|
||||
"Setting 'AUDITLOG_INCLUDE_TRACKING_MODELS' must be a list or tuple"
|
||||
|
|
@ -310,6 +322,11 @@ class AuditlogModelRegistry:
|
|||
"Setting 'AUDITLOG_EXCLUDE_TRACKING_FIELDS' must be a list or tuple"
|
||||
)
|
||||
|
||||
if not isinstance(settings.AUDITLOG_MASK_TRACKING_FIELDS, (list, tuple)):
|
||||
raise TypeError(
|
||||
"Setting 'AUDITLOG_MASK_TRACKING_FIELDS' must be a list or tuple"
|
||||
)
|
||||
|
||||
for item in settings.AUDITLOG_INCLUDE_TRACKING_MODELS:
|
||||
if not isinstance(item, (str, dict)):
|
||||
raise TypeError(
|
||||
|
|
|
|||
|
|
@ -1347,6 +1347,24 @@ class RegisterModelSettingsTest(TestCase):
|
|||
):
|
||||
self.test_auditlog.register_from_settings()
|
||||
|
||||
with override_settings(
|
||||
AUDITLOG_INCLUDE_ALL_MODELS=True,
|
||||
AUDITLOG_MASK_TRACKING_FIELDS="badvalue",
|
||||
):
|
||||
with self.assertRaisesMessage(
|
||||
TypeError,
|
||||
"Setting 'AUDITLOG_MASK_TRACKING_FIELDS' must be a list or tuple",
|
||||
):
|
||||
self.test_auditlog.register_from_settings()
|
||||
|
||||
with override_settings(AUDITLOG_MASK_TRACKING_FIELDS=("token", "otp_secret")):
|
||||
with self.assertRaisesMessage(
|
||||
ValueError,
|
||||
"In order to use 'AUDITLOG_MASK_TRACKING_FIELDS', "
|
||||
"setting 'AUDITLOG_INCLUDE_ALL_MODELS' must be set to 'True'",
|
||||
):
|
||||
self.test_auditlog.register_from_settings()
|
||||
|
||||
with override_settings(AUDITLOG_INCLUDE_TRACKING_MODELS="str"):
|
||||
with self.assertRaisesMessage(
|
||||
TypeError,
|
||||
|
|
@ -1424,6 +1442,24 @@ class RegisterModelSettingsTest(TestCase):
|
|||
["datetime"],
|
||||
)
|
||||
|
||||
@override_settings(
|
||||
AUDITLOG_INCLUDE_ALL_MODELS=True,
|
||||
AUDITLOG_MASK_TRACKING_FIELDS=("secret",),
|
||||
)
|
||||
def test_register_from_settings_register_all_models_with_mask_tracking_fields(
|
||||
self,
|
||||
):
|
||||
self.test_auditlog.register_from_settings()
|
||||
|
||||
self.assertEqual(
|
||||
self.test_auditlog.get_model_fields(SimpleModel)["mask_fields"],
|
||||
["secret"],
|
||||
)
|
||||
self.assertEqual(
|
||||
self.test_auditlog.get_model_fields(AltPrimaryKeyModel)["mask_fields"],
|
||||
["secret"],
|
||||
)
|
||||
|
||||
@override_settings(
|
||||
AUDITLOG_INCLUDE_ALL_MODELS=True,
|
||||
AUDITLOG_EXCLUDE_TRACKING_MODELS=["auditlog_tests.SimpleExcludeModel"],
|
||||
|
|
|
|||
|
|
@ -235,6 +235,28 @@ It will be considered when ``AUDITLOG_DISABLE_REMOTE_ADDR`` is `True`.
|
|||
|
||||
.. versionadded:: 3.0.0
|
||||
|
||||
**AUDITLOG_MASK_TRACKING_FIELDS**
|
||||
|
||||
You can use this setting to mask specific field values in all tracked models
|
||||
while still logging changes. This is useful when models contain sensitive fields
|
||||
like `password`, `api_key`, or `secret_token`` that should not be logged
|
||||
in plain text but need to be auditable.
|
||||
|
||||
When a masked field changes, its value will be replaced with a masked
|
||||
representation (e.g., `****`) in the audit log instead of storing the actual value.
|
||||
|
||||
This setting will be applied only when `AUDITLOG_INCLUDE_ALL_MODELS`` is `True`.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
AUDITLOG_MASK_TRACKING_FIELDS = (
|
||||
"password",
|
||||
"api_key",
|
||||
"secret_token"
|
||||
)
|
||||
|
||||
.. versionadded:: 3.1.0
|
||||
|
||||
**AUDITLOG_EXCLUDE_TRACKING_MODELS**
|
||||
|
||||
You can use this setting to exclude models in registration process.
|
||||
|
|
|
|||
Loading…
Reference in a new issue