diff --git a/README.md b/README.md index fc57fe3..216e330 100644 --- a/README.md +++ b/README.md @@ -130,7 +130,7 @@ The `RequestIDMiddleware` also has the ability to log all requests received by t Logging other user attributes -------------------- -If you would like to log another user attribute instead of user ID, this can be specified with the `LOG_USER_ATTRIBUTE` setting. Eg. to log the username, use: `LOG_USER_ATTRIBUTE = "username"` +If you would like to log another user attribute instead of user ID, this can be specified with the `LOG_USER_ATTRIBUTE` setting. Eg. to log the username, use: `LOG_USER_ATTRIBUTE = "username"`. If this setting is set to `None`, no user attribute will be logged. License ------- diff --git a/log_request_id/middleware.py b/log_request_id/middleware.py index 6629276..ca1a117 100644 --- a/log_request_id/middleware.py +++ b/log_request_id/middleware.py @@ -21,17 +21,25 @@ def process_request(self, request): request.id = request_id def get_log_message(self, request, response): + message = 'method=%s path=%s status=%s' % (request.method, request.path, response.status_code) + + # `LOG_USER_ATTRIBUTE_SETTING` accepts False/None to skip setting attribute + # but falls back to 'pk' if value is not set + user_attribute = getattr(settings, LOG_USER_ATTRIBUTE_SETTING, 'pk') + if not user_attribute: + return message + + # avoid accessing session if it is empty + if getattr(request, 'session', None) and request.session.is_empty(): + return message + user = getattr(request, 'user', None) - user_attribute = getattr(settings, LOG_USER_ATTRIBUTE_SETTING, False) - if user_attribute: - user_id = getattr(user, user_attribute, None) - else: - user_id = getattr(user, 'pk', None) or getattr(user, 'id', None) - message = 'method=%s path=%s status=%s' % (request.method, request.path, response.status_code) - if user_id: - message += ' user=' + str(user_id) - return message + if not user: + return message + user_id = getattr(user, user_attribute, None) or getattr(user, 'id', None) + message += ' user=' + str(user_id) + return message def process_response(self, request, response): if getattr(settings, REQUEST_ID_RESPONSE_HEADER_SETTING, False) and getattr(request, 'id', None): diff --git a/log_request_id/tests.py b/log_request_id/tests.py index ffea7d4..c4f9b7a 100644 --- a/log_request_id/tests.py +++ b/log_request_id/tests.py @@ -5,6 +5,7 @@ except ImportError: async_to_sync = None +from django.contrib.sessions.backends.file import SessionStore from django.core.exceptions import ImproperlyConfigured from django.test import RequestFactory, TestCase, override_settings @@ -14,6 +15,11 @@ from unittest import mock +class DummyUser(object): + pk = 'fake_pk' + username = 'fake_username' + + class RequestIDLoggingTestCase(TestCase): url = "/" @@ -91,14 +97,10 @@ class DummyUser(object): self.assertTrue('fake_pk' in self.handler.messages[1]) def test_log_user_attribute(self): - - class DummyUser(object): - pk = 'fake_pk' - username = 'fake_username' - with self.settings(LOG_REQUESTS=True, LOG_USER_ATTRIBUTE='username'): request = self.factory.get(self.url) request.user = DummyUser() + request.session = SessionStore("session_key") middleware = RequestIDMiddleware(get_response=lambda request: None) middleware.process_request(request) response = self.call_view(request) @@ -106,6 +108,31 @@ class DummyUser(object): self.assertEqual(len(self.handler.messages), 2) self.assertTrue('fake_username' in self.handler.messages[1]) + def test_log_user_attribute_anonymous_user(self): + with self.settings(LOG_REQUESTS=True, LOG_USER_ATTRIBUTE='username'): + request = self.factory.get(self.url) + request.session = SessionStore() + middleware = RequestIDMiddleware(get_response=lambda request: None) + middleware.process_request(request) + response = self.call_view(request) + middleware.process_response(request, response) + self.assertEqual(len(self.handler.messages), 2) + self.assertFalse('fake_username' in self.handler.messages[1]) + self.assertFalse(request.session.accessed) + + def test_log_user_attribute_unset(self): + with self.settings(LOG_REQUESTS=True, LOG_USER_ATTRIBUTE=None): + request = self.factory.get(self.url) + request.user = DummyUser() + request.session = SessionStore("session_key") + middleware = RequestIDMiddleware(get_response=lambda request: None) + middleware.process_request(request) + response = self.call_view(request) + middleware.process_response(request, response) + self.assertEqual(len(self.handler.messages), 2) + self.assertFalse('fake_username' in self.handler.messages[1]) + self.assertFalse(request.session.accessed) + def test_response_header_unset(self): with self.settings(LOG_REQUEST_ID_HEADER='REQUEST_ID_HEADER'): request = self.factory.get(self.url)