diff --git a/docs/index.rst b/docs/index.rst index ce3e847..1fea48d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -13,7 +13,11 @@ It logs all the API information for content type “application/json”. - Request Headers -- Request Method +- Request Method + +- Logged-in User + +- View - API Response @@ -394,6 +398,12 @@ DRF API Logger Model: method = models.CharField(max_length=10, db_index=True) client_ip_address = models.CharField(max_length=50) response = models.TextField() + user = models.ForeignKey( + AUTH_USER_MODEL, + null=True, + on_delete=models.SET_NULL, + ) + view = models.CharField(max_length=50) status_code = models.PositiveSmallIntegerField(help_text='Response status code', db_index=True) execution_time = models.DecimalField(decimal_places=5, max_digits=8, help_text='Server execution time (Not complete response time.)') diff --git a/drf_api_logger/admin.py b/drf_api_logger/admin.py index 7085acd..9abe49e 100644 --- a/drf_api_logger/admin.py +++ b/drf_api_logger/admin.py @@ -96,11 +96,11 @@ def added_on_time(self, obj): added_on_time.short_description = 'Added on' list_per_page = 20 - list_display = ('id', 'api', 'method', 'status_code', 'execution_time', 'added_on_time',) + list_display = ('id', 'api', 'user_id', 'method', 'status_code', 'execution_time', 'added_on_time',) list_filter = ('added_on', 'status_code', 'method',) search_fields = ('body', 'response', 'headers', 'api',) readonly_fields = ( - 'execution_time', 'client_ip_address', 'api', + 'execution_time', 'client_ip_address', 'api', 'view', 'headers', 'body', 'method', 'response', 'status_code', 'added_on_time', ) exclude = ('added_on',) diff --git a/drf_api_logger/middleware/api_logger_middleware.py b/drf_api_logger/middleware/api_logger_middleware.py index 71a2058..a73e9c0 100644 --- a/drf_api_logger/middleware/api_logger_middleware.py +++ b/drf_api_logger/middleware/api_logger_middleware.py @@ -10,7 +10,7 @@ from drf_api_logger import API_LOGGER_SIGNAL from drf_api_logger.start_logger_when_server_starts import LOGGER_THREAD -from drf_api_logger.utils import get_headers, get_client_ip, mask_sensitive_data +from drf_api_logger.utils import get_headers, get_client_ip, mask_sensitive_data, get_view_from_request, get_user """ File: api_logger_middleware.py @@ -184,7 +184,9 @@ def __call__(self, request): response=mask_sensitive_data(response_body), status_code=response.status_code, execution_time=time.time() - start_time, - added_on=timezone.now() + added_on=timezone.now(), + view=get_view_from_request(request), + user_id=get_user(request) ) if self.DRF_API_LOGGER_DATABASE: if LOGGER_THREAD: diff --git a/drf_api_logger/migrations/0003_apilogsmodel_user_apilogsmodel_view.py b/drf_api_logger/migrations/0003_apilogsmodel_user_apilogsmodel_view.py new file mode 100644 index 0000000..939d69c --- /dev/null +++ b/drf_api_logger/migrations/0003_apilogsmodel_user_apilogsmodel_view.py @@ -0,0 +1,27 @@ +# Generated by Django 5.0 on 2024-02-01 09:47 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('drf_api_logger', '0002_auto_20211221_2155'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.AddField( + model_name='apilogsmodel', + name='user', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='apilogsmodel', + name='view', + field=models.CharField(default='', max_length=50), + preserve_default=False, + ), + ] diff --git a/drf_api_logger/models.py b/drf_api_logger/models.py index 72f312a..c952a37 100644 --- a/drf_api_logger/models.py +++ b/drf_api_logger/models.py @@ -1,7 +1,8 @@ from django.db import models - +from django.conf import settings from drf_api_logger.utils import database_log_enabled +AUTH_USER_MODEL = getattr(settings, "AUTH_USER_MODEL", "auth.User") if database_log_enabled(): """ @@ -27,6 +28,12 @@ class APILogsModel(BaseModel): method = models.CharField(max_length=10, db_index=True) client_ip_address = models.CharField(max_length=50) response = models.TextField() + user = models.ForeignKey( + AUTH_USER_MODEL, + null=True, + on_delete=models.SET_NULL, + ) + view = models.CharField(max_length=50) status_code = models.PositiveSmallIntegerField(help_text='Response status code', db_index=True) execution_time = models.DecimalField(decimal_places=5, max_digits=8, help_text='Server execution time (Not complete response time.)') diff --git a/drf_api_logger/utils.py b/drf_api_logger/utils.py index 072ff8f..7a906e4 100644 --- a/drf_api_logger/utils.py +++ b/drf_api_logger/utils.py @@ -1,5 +1,6 @@ import re from django.conf import settings +from django.urls import resolve SENSITIVE_KEYS = ['password', 'token', 'access', 'refresh'] if hasattr(settings, 'DRF_API_LOGGER_EXCLUDE_KEYS'): @@ -76,3 +77,17 @@ def mask_sensitive_data(data, mask_api_parameters=False): data[key] = [mask_sensitive_data(item) for item in data[key]] return data + +def get_view_from_request(request): + try: + return f"{resolve(request.path_info)._func_path}"[:50] + except: + return "" + +def get_user(request): + if hasattr(request, "user") and hasattr(request.user, "is_authenticated"): + is_authenticated = request.user.is_authenticated + if is_authenticated: + return request.user.id + else: + return None