diff --git a/README.md b/README.md index a67da88..7fd1603 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ drf-tracking provides a Django model and DRF view mixin that work together to lo Model field name | Description | Model field type ------------------|-------------|----------------- `user` | User if authenticated, None if not | Foreign Key +`username_persistent` | Static field that persists the username even if the User model object is deleted | CharField `requested_at` | Date-time that the request was made | DateTimeField `response_ms` | Number of milliseconds spent in view code | PositiveIntegerField `path` | Target URI of the request, e.g., `"/api/"` | CharField @@ -153,6 +154,8 @@ class LoggingView(LoggingMixin, generics.CreateModelMixin, generics.GenericAPIVi sensitive_fields = {'my_secret_key', 'my_secret_recipe'} ``` +By default drf-tracking allows API request log entries to be modified from Django admin. This can present a data integrity issue in production environments. In order to change this behavior, you can set `DRF_TRACKING_ADMIN_LOG_READONLY` to `True` in your `settings.py` file. + ## Testing Install testing requirements. diff --git a/rest_framework_tracking/admin.py b/rest_framework_tracking/admin.py index cd38f81..052dd0a 100644 --- a/rest_framework_tracking/admin.py +++ b/rest_framework_tracking/admin.py @@ -1,3 +1,4 @@ +from django.conf import settings from django.contrib import admin from .models import APIRequestLog @@ -12,5 +13,11 @@ class APIRequestLogAdmin(admin.ModelAdmin): search_fields = ('path', 'user__email',) raw_id_fields = ('user', ) + if getattr(settings, 'DRF_TRACKING_ADMIN_LOG_READONLY', False): + readonly_fields = ('user', 'username_persistent', 'requested_at', + 'response_ms', 'path', 'view', 'view_method', + 'remote_addr', 'host', 'method', 'query_params', + 'data', 'response', 'errors', 'status_code') + admin.site.register(APIRequestLog, APIRequestLogAdmin) diff --git a/rest_framework_tracking/base_mixins.py b/rest_framework_tracking/base_mixins.py index f00ef37..8b167be 100644 --- a/rest_framework_tracking/base_mixins.py +++ b/rest_framework_tracking/base_mixins.py @@ -68,6 +68,8 @@ def finalize_response(self, request, response, *args, **kwargs): 'method': request.method, 'query_params': self._clean_data(request.query_params.dict()), 'user': self._get_user(request), + 'username_persistent': + self._get_user(request).username if self._get_user(request) else 'Anonymous', 'response_ms': self._get_response_ms(), 'response': self._clean_data(rendered_content), 'status_code': response.status_code, diff --git a/rest_framework_tracking/base_models.py b/rest_framework_tracking/base_models.py index 56eed69..9bbefbd 100644 --- a/rest_framework_tracking/base_models.py +++ b/rest_framework_tracking/base_models.py @@ -14,6 +14,11 @@ class BaseAPIRequestLog(models.Model): null=True, blank=True, ) + username_persistent = models.CharField( + max_length=getattr(settings, 'DRF_TRACKING_USERNAME_LENGTH', 200), + null=True, + blank=True, + ) requested_at = models.DateTimeField(db_index=True) response_ms = models.PositiveIntegerField(default=0) path = models.CharField( diff --git a/rest_framework_tracking/migrations/0008_auto_20200201_2048.py b/rest_framework_tracking/migrations/0008_auto_20200201_2048.py new file mode 100644 index 0000000..a0a644d --- /dev/null +++ b/rest_framework_tracking/migrations/0008_auto_20200201_2048.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 3.0.2 on 2020-02-01 20:48 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('rest_framework_tracking', '0007_merge_20180419_1646'), + ] + + operations = [ + migrations.AddField( + model_name='apirequestlog', + name='username_persistent', + field=models.CharField( + blank=True, + default='', + max_length=200, + null=True + ) + ), + ]