mirror of
https://github.com/jazzband/django-auditlog.git
synced 2026-03-16 22:20:26 +00:00
Added remote port (#671)
This commit is contained in:
parent
22dcbc4d06
commit
4c3ee0b36d
7 changed files with 56 additions and 3 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -80,3 +80,4 @@ venv.bak/
|
||||||
|
|
||||||
### JetBrains
|
### JetBrains
|
||||||
.idea/
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
## Next Release
|
## Next Release
|
||||||
|
|
||||||
|
#### Improvements
|
||||||
|
- feat: Added `LogEntry.remote_port` field. ([#671](https://github.com/jazzband/django-auditlog/pull/671))
|
||||||
|
|
||||||
#### Fixes
|
#### Fixes
|
||||||
|
|
||||||
- Fixed a problem when setting `Value(None)` in `JSONField` ([#646](https://github.com/jazzband/django-auditlog/pull/646))
|
- Fixed a problem when setting `Value(None)` in `JSONField` ([#646](https://github.com/jazzband/django-auditlog/pull/646))
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,13 @@ auditlog_disabled = ContextVar("auditlog_disabled", default=False)
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def set_actor(actor, remote_addr=None):
|
def set_actor(actor, remote_addr=None, remote_port=None):
|
||||||
"""Connect a signal receiver with current user attached."""
|
"""Connect a signal receiver with current user attached."""
|
||||||
# Initialize thread local storage
|
# Initialize thread local storage
|
||||||
context_data = {
|
context_data = {
|
||||||
"signal_duid": ("set_actor", time.time()),
|
"signal_duid": ("set_actor", time.time()),
|
||||||
"remote_addr": remote_addr,
|
"remote_addr": remote_addr,
|
||||||
|
"remote_port": remote_port,
|
||||||
}
|
}
|
||||||
auditlog_value.set(context_data)
|
auditlog_value.set(context_data)
|
||||||
|
|
||||||
|
|
@ -63,6 +64,7 @@ def _set_actor(user, sender, instance, signal_duid, **kwargs):
|
||||||
instance.actor = user
|
instance.actor = user
|
||||||
|
|
||||||
instance.remote_addr = auditlog["remote_addr"]
|
instance.remote_addr = auditlog["remote_addr"]
|
||||||
|
instance.remote_port = auditlog["remote_port"]
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
|
|
||||||
|
|
@ -36,6 +38,17 @@ class AuditlogMiddleware:
|
||||||
|
|
||||||
return remote_addr
|
return remote_addr
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _get_remote_port(request) -> Optional[int]:
|
||||||
|
remote_port = request.headers.get("X-Forwarded-Port", "")
|
||||||
|
|
||||||
|
try:
|
||||||
|
remote_port = int(remote_port)
|
||||||
|
except ValueError:
|
||||||
|
remote_port = None
|
||||||
|
|
||||||
|
return remote_port
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_actor(request):
|
def _get_actor(request):
|
||||||
user = getattr(request, "user", None)
|
user = getattr(request, "user", None)
|
||||||
|
|
@ -45,9 +58,10 @@ class AuditlogMiddleware:
|
||||||
|
|
||||||
def __call__(self, request):
|
def __call__(self, request):
|
||||||
remote_addr = self._get_remote_addr(request)
|
remote_addr = self._get_remote_addr(request)
|
||||||
|
remote_port = self._get_remote_port(request)
|
||||||
user = self._get_actor(request)
|
user = self._get_actor(request)
|
||||||
|
|
||||||
set_cid(request)
|
set_cid(request)
|
||||||
|
|
||||||
with set_actor(actor=user, remote_addr=remote_addr):
|
with set_actor(actor=user, remote_addr=remote_addr, remote_port=remote_port):
|
||||||
return self.get_response(request)
|
return self.get_response(request)
|
||||||
|
|
|
||||||
17
auditlog/migrations/0016_logentry_remote_port.py
Normal file
17
auditlog/migrations/0016_logentry_remote_port.py
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("auditlog", "0015_alter_logentry_changes"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="logentry",
|
||||||
|
name="remote_port",
|
||||||
|
field=models.PositiveIntegerField(
|
||||||
|
blank=True, null=True, verbose_name="remote port"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -373,6 +373,9 @@ class LogEntry(models.Model):
|
||||||
remote_addr = models.GenericIPAddressField(
|
remote_addr = models.GenericIPAddressField(
|
||||||
blank=True, null=True, verbose_name=_("remote address")
|
blank=True, null=True, verbose_name=_("remote address")
|
||||||
)
|
)
|
||||||
|
remote_port = models.PositiveIntegerField(
|
||||||
|
blank=True, null=True, verbose_name=_("remote port")
|
||||||
|
)
|
||||||
timestamp = models.DateTimeField(
|
timestamp = models.DateTimeField(
|
||||||
default=django_timezone.now,
|
default=django_timezone.now,
|
||||||
db_index=True,
|
db_index=True,
|
||||||
|
|
|
||||||
|
|
@ -585,6 +585,13 @@ class MiddlewareTest(TestCase):
|
||||||
self.middleware._get_remote_addr(request), expected_remote_addr
|
self.middleware._get_remote_addr(request), expected_remote_addr
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_get_remote_port(self):
|
||||||
|
headers = {
|
||||||
|
"HTTP_X_FORWARDED_PORT": "12345",
|
||||||
|
}
|
||||||
|
request = self.factory.get("/", **headers)
|
||||||
|
self.assertEqual(self.middleware._get_remote_port(request), 12345)
|
||||||
|
|
||||||
def test_cid(self):
|
def test_cid(self):
|
||||||
header = str(settings.AUDITLOG_CID_HEADER).lstrip("HTTP_").replace("_", "-")
|
header = str(settings.AUDITLOG_CID_HEADER).lstrip("HTTP_").replace("_", "-")
|
||||||
header_meta = "HTTP_" + header.upper().replace("-", "_")
|
header_meta = "HTTP_" + header.upper().replace("-", "_")
|
||||||
|
|
@ -622,9 +629,10 @@ class MiddlewareTest(TestCase):
|
||||||
The remote address will be set even when there is no actor
|
The remote address will be set even when there is no actor
|
||||||
"""
|
"""
|
||||||
remote_addr = "123.213.145.99"
|
remote_addr = "123.213.145.99"
|
||||||
|
remote_port = 12345
|
||||||
actor = None
|
actor = None
|
||||||
|
|
||||||
with set_actor(actor=actor, remote_addr=remote_addr):
|
with set_actor(actor=actor, remote_addr=remote_addr, remote_port=remote_port):
|
||||||
obj = SimpleModel.objects.create(text="I am not difficult.")
|
obj = SimpleModel.objects.create(text="I am not difficult.")
|
||||||
|
|
||||||
history = obj.history.get()
|
history = obj.history.get()
|
||||||
|
|
@ -633,6 +641,11 @@ class MiddlewareTest(TestCase):
|
||||||
remote_addr,
|
remote_addr,
|
||||||
msg=f"Remote address is {remote_addr}",
|
msg=f"Remote address is {remote_addr}",
|
||||||
)
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
history.remote_port,
|
||||||
|
remote_port,
|
||||||
|
msg=f"Remote port is {remote_port}",
|
||||||
|
)
|
||||||
self.assertIsNone(history.actor, msg="Actor is `None` for anonymous user")
|
self.assertIsNone(history.actor, msg="Actor is `None` for anonymous user")
|
||||||
|
|
||||||
def test_get_actor(self):
|
def test_get_actor(self):
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue