django-activity-audit 1.3.0.dev19__tar.gz → 1.3.0.dev20__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/PKG-INFO +87 -32
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/README.md +84 -28
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/config.py +16 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/middleware.py +12 -16
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/shared_processors.py +20 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/utils.py +1 -1
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/pyproject.toml +3 -3
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/.claude/settings.local.json +0 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/.gitignore +0 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/.pre-commit-config.yaml +0 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/LICENSE +0 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/MANIFEST.in +0 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/README.rst +0 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/__init__.py +0 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/apps.py +0 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/constants.py +0 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/formatters.py +0 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/handlers.py +0 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/logger_levels.py +0 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/protocols.py +0 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/settings.py +0 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/signals.py +0 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/unregistered.py +0 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/docs/django-activity-audit.md +0 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/docs/hipaa-audit-gaps.md +0 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/docs/improvements.md +0 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/docs/structlog-integration.md +0 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/docs/user-activity-feed-plan.md +0 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/hatch +0 -0
- {django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/pytest.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: django-activity-audit
|
|
3
|
-
Version: 1.3.0.
|
|
3
|
+
Version: 1.3.0.dev20
|
|
4
4
|
Summary: A Django package for easy CRUD operation logging and container logs
|
|
5
5
|
Project-URL: Homepage, https://github.com/shree256/django-activity-audit
|
|
6
6
|
Project-URL: Repository, https://github.com/shree256/django-activity-audit
|
|
@@ -26,19 +26,18 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
26
26
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
27
27
|
Requires-Python: >=3.8
|
|
28
28
|
Requires-Dist: django<6.0,>=4.2
|
|
29
|
+
Requires-Dist: orjson>=3.0
|
|
30
|
+
Requires-Dist: structlog>=24.0
|
|
29
31
|
Provides-Extra: dev
|
|
30
32
|
Requires-Dist: pre-commit>=3.5; (python_version >= '3.9') and extra == 'dev'
|
|
31
33
|
Requires-Dist: pre-commit~=3.5; (python_version < '3.9') and extra == 'dev'
|
|
32
34
|
Requires-Dist: ruff>=0.1.11; extra == 'dev'
|
|
33
|
-
Provides-Extra: structlog
|
|
34
|
-
Requires-Dist: structlog>=24.0; extra == 'structlog'
|
|
35
35
|
Provides-Extra: test
|
|
36
36
|
Requires-Dist: djangorestframework>=3.14.0; extra == 'test'
|
|
37
37
|
Requires-Dist: factory-boy>=3.2.0; extra == 'test'
|
|
38
38
|
Requires-Dist: pytest-cov>=4.0.0; extra == 'test'
|
|
39
39
|
Requires-Dist: pytest-django>=4.0.0; extra == 'test'
|
|
40
40
|
Requires-Dist: pytest>=6.0.0; extra == 'test'
|
|
41
|
-
Requires-Dist: structlog>=24.0; extra == 'test'
|
|
42
41
|
Description-Content-Type: text/markdown
|
|
43
42
|
|
|
44
43
|
# Django Activity Audit
|
|
@@ -62,6 +61,8 @@ A Django package that extends the default logging mechanism to track CRUD operat
|
|
|
62
61
|
pip install django-activity-audit
|
|
63
62
|
```
|
|
64
63
|
|
|
64
|
+
This also installs [`structlog`](https://www.structlog.org/) and [`orjson`](https://github.com/ijl/orjson) as required dependencies.
|
|
65
|
+
|
|
65
66
|
2. Add 'activity_audit' to your INSTALLED_APPS in settings.py:
|
|
66
67
|
```python
|
|
67
68
|
INSTALLED_APPS = [
|
|
@@ -79,47 +80,101 @@ MIDDLEWARE = [
|
|
|
79
80
|
```
|
|
80
81
|
|
|
81
82
|
4. Configure logging in settings.py:
|
|
83
|
+
|
|
84
|
+
Import the formatter helpers from `activity_audit.config`:
|
|
85
|
+
|
|
82
86
|
```python
|
|
83
|
-
from activity_audit import
|
|
87
|
+
from activity_audit.config import get_plain_formatter, get_stdlib_formatter
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
- `get_stdlib_formatter()` — structlog JSON renderer. Use in staging/production where logs are ingested by a pipeline (Vector, CloudWatch, etc.).
|
|
91
|
+
- `get_plain_formatter()` — structlog plain-text renderer. Use locally for human-readable console output.
|
|
92
|
+
|
|
93
|
+
**Local development** (plain text output):
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
from activity_audit.config import get_plain_formatter, get_stdlib_formatter
|
|
84
97
|
|
|
85
98
|
LOGGING = {
|
|
86
99
|
"version": 1,
|
|
87
100
|
"disable_existing_loggers": False,
|
|
88
101
|
"formatters": {
|
|
89
|
-
"
|
|
90
|
-
"
|
|
102
|
+
"structlog": get_stdlib_formatter(),
|
|
103
|
+
"default": get_plain_formatter(),
|
|
91
104
|
},
|
|
92
105
|
"handlers": {
|
|
93
|
-
"console":
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
"
|
|
99
|
-
"api_file": get_api_file_handler(),
|
|
100
|
-
"audit_file": get_audit_handler(),
|
|
106
|
+
"console": {"class": "logging.StreamHandler", "formatter": "default"},
|
|
107
|
+
"console_struct": {"class": "logging.StreamHandler", "formatter": "structlog"},
|
|
108
|
+
},
|
|
109
|
+
"root": {
|
|
110
|
+
"level": "INFO",
|
|
111
|
+
"handlers": ["console"], # plain text fallback for all loggers
|
|
101
112
|
},
|
|
102
|
-
"root": {"level": "DEBUG", "handlers": ["console", "file"]},
|
|
103
113
|
"loggers": {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
114
|
+
# Structlog owns these — explicit handler, no propagation to avoid double output
|
|
115
|
+
"audit.model": {"handlers": ["console_struct"], "propagate": False},
|
|
116
|
+
"audit.request": {"handlers": ["console_struct"], "propagate": False},
|
|
117
|
+
"audit.login": {"handlers": ["console_struct"], "propagate": False},
|
|
118
|
+
|
|
119
|
+
# Celery — structlog formats log_type correctly
|
|
120
|
+
"celery": {"level": "INFO", "handlers": ["console_struct"], "propagate": False},
|
|
121
|
+
"celery.task": {"level": "INFO", "handlers": ["console_struct"], "propagate": False},
|
|
122
|
+
"celery.beat": {"level": "INFO", "handlers": ["console_struct"], "propagate": False},
|
|
123
|
+
|
|
124
|
+
# Third-party noise control — WARNING only, routed to root
|
|
125
|
+
"django.db.backends": {"level": "WARNING", "handlers": [], "propagate": True},
|
|
126
|
+
"boto3": {"level": "WARNING", "handlers": [], "propagate": True},
|
|
127
|
+
"botocore": {"level": "WARNING", "handlers": [], "propagate": True},
|
|
128
|
+
|
|
129
|
+
# Framework loggers
|
|
130
|
+
"django": {"level": "INFO", "handlers": [], "propagate": True},
|
|
131
|
+
"uvicorn": {"level": "INFO", "handlers": [], "propagate": True},
|
|
132
|
+
"uvicorn.error": {"level": "INFO", "handlers": [], "propagate": True},
|
|
133
|
+
"uvicorn.access":{"level": "INFO", "handlers": [], "propagate": True},
|
|
134
|
+
},
|
|
120
135
|
}
|
|
121
136
|
```
|
|
122
137
|
|
|
138
|
+
**Staging / production** (structured JSON output): identical structure, but the `root` handler also uses `console_struct` (or keep `console` for mixed output — both handlers use the same `StreamHandler` class):
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
"root": {
|
|
142
|
+
"level": "INFO",
|
|
143
|
+
"handlers": ["console"],
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
### When to add a logger entry
|
|
150
|
+
|
|
151
|
+
Add an explicit logger entry when you need **any** of the following:
|
|
152
|
+
|
|
153
|
+
| Situation | What to set |
|
|
154
|
+
|-----------|-------------|
|
|
155
|
+
| Route to structured JSON (`console_struct`) | `handlers: ["console_struct"], propagate: False` |
|
|
156
|
+
| Suppress a noisy third-party library | `level: "WARNING", handlers: [], propagate: True` |
|
|
157
|
+
| Prevent double output for a structlog-owned logger | `handlers: ["console_struct"], propagate: False` |
|
|
158
|
+
| Change the log level for a specific namespace | Set `level` explicitly |
|
|
159
|
+
|
|
160
|
+
**Do not** add a logger entry if the default behaviour is acceptable — a logger with no entry propagates to `root` and is emitted in plain text at INFO level. That is the correct behaviour for most application loggers.
|
|
161
|
+
|
|
162
|
+
### Silencing audit loggers (route to root instead of structlog)
|
|
163
|
+
|
|
164
|
+
By default `audit.model`, `audit.request`, and `audit.login` are pointed at `console_struct` with `propagate: False` so only the structlog-formatted JSON line is emitted.
|
|
165
|
+
|
|
166
|
+
To stop structlog from handling them and fall back to the plain-text root logger instead, set `handlers: []` and `propagate: True`:
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
"loggers": {
|
|
170
|
+
"audit.model": {"handlers": [], "propagate": True},
|
|
171
|
+
"audit.request": {"handlers": [], "propagate": True},
|
|
172
|
+
"audit.login": {"handlers": [], "propagate": True},
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
This routes all three through the `root` logger (`console` handler, `default` / plain-text formatter). Use this when you want to completely disable structured audit output — for example, in a minimal local environment or during debugging.
|
|
177
|
+
|
|
123
178
|
5. Configure the service name in `settings.py` (optional, defaults to `"default"`):
|
|
124
179
|
```python
|
|
125
180
|
AUDIT_SERVICE_NAME = "my_service"
|
|
@@ -19,6 +19,8 @@ A Django package that extends the default logging mechanism to track CRUD operat
|
|
|
19
19
|
pip install django-activity-audit
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
+
This also installs [`structlog`](https://www.structlog.org/) and [`orjson`](https://github.com/ijl/orjson) as required dependencies.
|
|
23
|
+
|
|
22
24
|
2. Add 'activity_audit' to your INSTALLED_APPS in settings.py:
|
|
23
25
|
```python
|
|
24
26
|
INSTALLED_APPS = [
|
|
@@ -36,47 +38,101 @@ MIDDLEWARE = [
|
|
|
36
38
|
```
|
|
37
39
|
|
|
38
40
|
4. Configure logging in settings.py:
|
|
41
|
+
|
|
42
|
+
Import the formatter helpers from `activity_audit.config`:
|
|
43
|
+
|
|
39
44
|
```python
|
|
40
|
-
from activity_audit import
|
|
45
|
+
from activity_audit.config import get_plain_formatter, get_stdlib_formatter
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- `get_stdlib_formatter()` — structlog JSON renderer. Use in staging/production where logs are ingested by a pipeline (Vector, CloudWatch, etc.).
|
|
49
|
+
- `get_plain_formatter()` — structlog plain-text renderer. Use locally for human-readable console output.
|
|
50
|
+
|
|
51
|
+
**Local development** (plain text output):
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
from activity_audit.config import get_plain_formatter, get_stdlib_formatter
|
|
41
55
|
|
|
42
56
|
LOGGING = {
|
|
43
57
|
"version": 1,
|
|
44
58
|
"disable_existing_loggers": False,
|
|
45
59
|
"formatters": {
|
|
46
|
-
"
|
|
47
|
-
"
|
|
60
|
+
"structlog": get_stdlib_formatter(),
|
|
61
|
+
"default": get_plain_formatter(),
|
|
48
62
|
},
|
|
49
63
|
"handlers": {
|
|
50
|
-
"console":
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
"
|
|
56
|
-
"api_file": get_api_file_handler(),
|
|
57
|
-
"audit_file": get_audit_handler(),
|
|
64
|
+
"console": {"class": "logging.StreamHandler", "formatter": "default"},
|
|
65
|
+
"console_struct": {"class": "logging.StreamHandler", "formatter": "structlog"},
|
|
66
|
+
},
|
|
67
|
+
"root": {
|
|
68
|
+
"level": "INFO",
|
|
69
|
+
"handlers": ["console"], # plain text fallback for all loggers
|
|
58
70
|
},
|
|
59
|
-
"root": {"level": "DEBUG", "handlers": ["console", "file"]},
|
|
60
71
|
"loggers": {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
# Structlog owns these — explicit handler, no propagation to avoid double output
|
|
73
|
+
"audit.model": {"handlers": ["console_struct"], "propagate": False},
|
|
74
|
+
"audit.request": {"handlers": ["console_struct"], "propagate": False},
|
|
75
|
+
"audit.login": {"handlers": ["console_struct"], "propagate": False},
|
|
76
|
+
|
|
77
|
+
# Celery — structlog formats log_type correctly
|
|
78
|
+
"celery": {"level": "INFO", "handlers": ["console_struct"], "propagate": False},
|
|
79
|
+
"celery.task": {"level": "INFO", "handlers": ["console_struct"], "propagate": False},
|
|
80
|
+
"celery.beat": {"level": "INFO", "handlers": ["console_struct"], "propagate": False},
|
|
81
|
+
|
|
82
|
+
# Third-party noise control — WARNING only, routed to root
|
|
83
|
+
"django.db.backends": {"level": "WARNING", "handlers": [], "propagate": True},
|
|
84
|
+
"boto3": {"level": "WARNING", "handlers": [], "propagate": True},
|
|
85
|
+
"botocore": {"level": "WARNING", "handlers": [], "propagate": True},
|
|
86
|
+
|
|
87
|
+
# Framework loggers
|
|
88
|
+
"django": {"level": "INFO", "handlers": [], "propagate": True},
|
|
89
|
+
"uvicorn": {"level": "INFO", "handlers": [], "propagate": True},
|
|
90
|
+
"uvicorn.error": {"level": "INFO", "handlers": [], "propagate": True},
|
|
91
|
+
"uvicorn.access":{"level": "INFO", "handlers": [], "propagate": True},
|
|
92
|
+
},
|
|
77
93
|
}
|
|
78
94
|
```
|
|
79
95
|
|
|
96
|
+
**Staging / production** (structured JSON output): identical structure, but the `root` handler also uses `console_struct` (or keep `console` for mixed output — both handlers use the same `StreamHandler` class):
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
"root": {
|
|
100
|
+
"level": "INFO",
|
|
101
|
+
"handlers": ["console"],
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
### When to add a logger entry
|
|
108
|
+
|
|
109
|
+
Add an explicit logger entry when you need **any** of the following:
|
|
110
|
+
|
|
111
|
+
| Situation | What to set |
|
|
112
|
+
|-----------|-------------|
|
|
113
|
+
| Route to structured JSON (`console_struct`) | `handlers: ["console_struct"], propagate: False` |
|
|
114
|
+
| Suppress a noisy third-party library | `level: "WARNING", handlers: [], propagate: True` |
|
|
115
|
+
| Prevent double output for a structlog-owned logger | `handlers: ["console_struct"], propagate: False` |
|
|
116
|
+
| Change the log level for a specific namespace | Set `level` explicitly |
|
|
117
|
+
|
|
118
|
+
**Do not** add a logger entry if the default behaviour is acceptable — a logger with no entry propagates to `root` and is emitted in plain text at INFO level. That is the correct behaviour for most application loggers.
|
|
119
|
+
|
|
120
|
+
### Silencing audit loggers (route to root instead of structlog)
|
|
121
|
+
|
|
122
|
+
By default `audit.model`, `audit.request`, and `audit.login` are pointed at `console_struct` with `propagate: False` so only the structlog-formatted JSON line is emitted.
|
|
123
|
+
|
|
124
|
+
To stop structlog from handling them and fall back to the plain-text root logger instead, set `handlers: []` and `propagate: True`:
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
"loggers": {
|
|
128
|
+
"audit.model": {"handlers": [], "propagate": True},
|
|
129
|
+
"audit.request": {"handlers": [], "propagate": True},
|
|
130
|
+
"audit.login": {"handlers": [], "propagate": True},
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
This routes all three through the `root` logger (`console` handler, `default` / plain-text formatter). Use this when you want to completely disable structured audit output — for example, in a minimal local environment or during debugging.
|
|
135
|
+
|
|
80
136
|
5. Configure the service name in `settings.py` (optional, defaults to `"default"`):
|
|
81
137
|
```python
|
|
82
138
|
AUDIT_SERVICE_NAME = "my_service"
|
{django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/config.py
RENAMED
|
@@ -20,6 +20,22 @@ class AuditBoundLogger(structlog.stdlib.BoundLogger):
|
|
|
20
20
|
return self._proxy_to_logger("login", event, *args, **kw)
|
|
21
21
|
|
|
22
22
|
|
|
23
|
+
def get_plain_formatter() -> dict:
|
|
24
|
+
"""
|
|
25
|
+
LOGGING formatter dict that routes stdlib loggers through the structlog
|
|
26
|
+
processor chain but renders as plain text instead of JSON. Use for local
|
|
27
|
+
development when human-readable output is preferred over structured JSON.
|
|
28
|
+
"""
|
|
29
|
+
return {
|
|
30
|
+
"()": structlog.stdlib.ProcessorFormatter,
|
|
31
|
+
"processors": [
|
|
32
|
+
structlog.stdlib.ProcessorFormatter.remove_processors_meta,
|
|
33
|
+
structlog.dev.ConsoleRenderer(colors=False),
|
|
34
|
+
],
|
|
35
|
+
"foreign_pre_chain": shared_processors,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
23
39
|
def get_stdlib_formatter() -> dict:
|
|
24
40
|
"""
|
|
25
41
|
LOGGING formatter dict that routes stdlib loggers through the structlog
|
{django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/middleware.py
RENAMED
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import contextlib
|
|
2
1
|
import json
|
|
3
2
|
import re
|
|
4
3
|
import time
|
|
5
4
|
import uuid
|
|
6
5
|
|
|
6
|
+
from contextvars import ContextVar
|
|
7
|
+
|
|
7
8
|
import structlog.contextvars as ctx
|
|
8
9
|
|
|
9
|
-
from asgiref.local import Local
|
|
10
10
|
from asgiref.sync import (
|
|
11
11
|
iscoroutinefunction,
|
|
12
12
|
markcoroutinefunction,
|
|
13
|
-
sync_to_async,
|
|
14
13
|
)
|
|
15
14
|
from django.http import HttpResponse
|
|
16
15
|
from django.utils.deprecation import MiddlewareMixin
|
|
@@ -21,7 +20,7 @@ from .settings import REGISTERED_URLS, SERVICE_NAME, UNREGISTERED_URLS
|
|
|
21
20
|
|
|
22
21
|
_log = get_logger("audit.request")
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
_request_var: ContextVar = ContextVar("current_request", default=None)
|
|
25
24
|
|
|
26
25
|
|
|
27
26
|
class MockRequest:
|
|
@@ -32,11 +31,11 @@ class MockRequest:
|
|
|
32
31
|
|
|
33
32
|
|
|
34
33
|
def get_current_request():
|
|
35
|
-
return
|
|
34
|
+
return _request_var.get()
|
|
36
35
|
|
|
37
36
|
|
|
38
37
|
def set_current_request(request):
|
|
39
|
-
|
|
38
|
+
_request_var.set(request)
|
|
40
39
|
|
|
41
40
|
|
|
42
41
|
def get_current_user():
|
|
@@ -47,11 +46,11 @@ def get_current_user():
|
|
|
47
46
|
|
|
48
47
|
|
|
49
48
|
def set_current_user(user):
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
request = _request_var.get()
|
|
50
|
+
if request is not None:
|
|
51
|
+
request.user = user
|
|
52
|
+
else:
|
|
53
|
+
_request_var.set(MockRequest(user=user))
|
|
55
54
|
|
|
56
55
|
|
|
57
56
|
def get_user_details():
|
|
@@ -73,8 +72,7 @@ def get_user_details():
|
|
|
73
72
|
|
|
74
73
|
|
|
75
74
|
def clear_request():
|
|
76
|
-
|
|
77
|
-
del _thread_locals.request
|
|
75
|
+
_request_var.set(None)
|
|
78
76
|
|
|
79
77
|
|
|
80
78
|
def should_log_url(url):
|
|
@@ -242,9 +240,7 @@ class AuditLoggingMiddleware(MiddlewareMixin):
|
|
|
242
240
|
end_time = time.time()
|
|
243
241
|
|
|
244
242
|
# Capture user details AFTER authentication has happened
|
|
245
|
-
user_id, user_info =
|
|
246
|
-
get_user_details, thread_sensitive=True
|
|
247
|
-
)()
|
|
243
|
+
user_id, user_info = get_user_details()
|
|
248
244
|
ctx.bind_contextvars(user_id=user_id, user_info=user_info)
|
|
249
245
|
|
|
250
246
|
# TODO: Find way to add status code to response_data
|
|
@@ -96,6 +96,26 @@ _STANDARD_KEYS = frozenset(
|
|
|
96
96
|
"request_id",
|
|
97
97
|
"_record",
|
|
98
98
|
"_from_structlog",
|
|
99
|
+
# audit.model fields
|
|
100
|
+
"model",
|
|
101
|
+
"event_type",
|
|
102
|
+
"instance_id",
|
|
103
|
+
"instance_repr",
|
|
104
|
+
"user_id",
|
|
105
|
+
"user_info",
|
|
106
|
+
"extra",
|
|
107
|
+
# audit.request fields
|
|
108
|
+
"service_name",
|
|
109
|
+
"request_type",
|
|
110
|
+
"protocol",
|
|
111
|
+
"request_repr",
|
|
112
|
+
"response_repr",
|
|
113
|
+
"error_message",
|
|
114
|
+
"execution_time",
|
|
115
|
+
# audit.login fields
|
|
116
|
+
"event",
|
|
117
|
+
"success",
|
|
118
|
+
"error",
|
|
99
119
|
}
|
|
100
120
|
)
|
|
101
121
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "django-activity-audit"
|
|
3
|
-
version = "1.3.0.
|
|
3
|
+
version = "1.3.0.dev20"
|
|
4
4
|
description = "A Django package for easy CRUD operation logging and container logs"
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "Shreeshan", email = "shreeshan256@gmail.com" }
|
|
@@ -31,6 +31,8 @@ classifiers = [
|
|
|
31
31
|
requires-python = ">=3.8"
|
|
32
32
|
dependencies = [
|
|
33
33
|
"django>=4.2,<6.0",
|
|
34
|
+
"structlog>=24.0",
|
|
35
|
+
"orjson>=3.0",
|
|
34
36
|
]
|
|
35
37
|
|
|
36
38
|
[project.urls]
|
|
@@ -50,9 +52,7 @@ test = [
|
|
|
50
52
|
"pytest-django>=4.0.0",
|
|
51
53
|
"pytest-cov>=4.0.0",
|
|
52
54
|
"djangorestframework>=3.14.0",
|
|
53
|
-
"structlog>=24.0",
|
|
54
55
|
]
|
|
55
|
-
structlog = ["structlog>=24.0"]
|
|
56
56
|
|
|
57
57
|
[build-system]
|
|
58
58
|
requires = ["hatchling"]
|
{django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/.claude/settings.local.json
RENAMED
|
File without changes
|
|
File without changes
|
{django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/.pre-commit-config.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/__init__.py
RENAMED
|
File without changes
|
{django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/apps.py
RENAMED
|
File without changes
|
{django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/constants.py
RENAMED
|
File without changes
|
{django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/formatters.py
RENAMED
|
File without changes
|
{django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/handlers.py
RENAMED
|
File without changes
|
|
File without changes
|
{django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/protocols.py
RENAMED
|
File without changes
|
{django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/settings.py
RENAMED
|
File without changes
|
{django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/activity_audit/signals.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/docs/hipaa-audit-gaps.md
RENAMED
|
File without changes
|
{django_activity_audit-1.3.0.dev19 → django_activity_audit-1.3.0.dev20}/docs/improvements.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|