django-auditlog: Automatic Logging doesn't log the Actor
I have installed the plugin and on an Django Rest Framework instance. All the logging is working as expected, except the Logging of the Actor. I added the Middleware as Described in the Docs but its still not logging any Actor.
Here is my configuration:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'corsheaders',
'oauth2_provider',
'rest_framework',
'auditlog',
'stammdaten.apps.StammdatenConfig',
'main.apps.MainConfig',
'rest_framework_swagger',
]
OAUTH2_PROVIDER = {
# this is the list of available scopes
'SCOPES': {'read': 'Read scope', 'write': 'Write scope', 'groups': 'Access to your groups'},
'ACCESS_TOKEN_EXPIRE_SECONDS': 43200
}
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'oauth2_provider.ext.rest_framework.OAuth2Authentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'PAGE_SIZE': 10
}
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'oauth2_provider.middleware.OAuth2TokenMiddleware',
'auditlog.middleware.AuditlogMiddleware'
]
What am I missing here? Is it a problem with the OAuth Toolkit or did I missconfig anything?
About this issue
- Original URL
- State: open
- Created 7 years ago
- Comments: 56 (11 by maintainers)
In my case I solved this by modifying the
AuditlogMiddleware
and making the user a lazy object.And then use this custom middleware in
settings.MIDDLEWARE
.Hello everyone!
I had the same issue when trying to integrate
django-auditlog
withDjango Rest Framework
(DRF).I have been digging into the source code of both projects to understand the reason the
actor
is not being set and found a reason.django-auditlog
expects the user being logged at Django’s middleware layer as usual but DRF, for design decision, does not perform the authentication at middleware level instead it performs the authentication at View level by using tte configured mechanisms. It means just before executing the code which processes the request and generates a response. Here is the difference with Django itself! That is the reason whyis_autenticated
is alwaysFalse
at the middleware layer, as result the handler to set the actor onpre_save
signal is not being connected.I’ve created a glue code which works as integration between both projects. The approach I took is to use
mixins
as many components of DRF does . This integrations is not coupled with any AUTH mechanism which is good, it leaves that behavior to DRF, that is a big difference with the approach taken by @ivan-fedorov-probegin (Im not telling it is bad!) . I’ve been using this integration in production without issues at all 😃. I would like to know if you are open to merge some DRF integrations… In that case I’ll be happy to propose a pull request. (cc @jjkester )Integration mixin
Minimal usage example
I would like to hear feedback from the projects! Anyways, you could take this code/ideas for you projects.
Thanks in advance!
for rest_framework_simplejwt
@mcanu I tried your solution. It works flawlessly. I wonder what’s stopping people from including this solution directly in audit log middleware.
First thanks to @malderete for the solution, it worked for me with a little change. For All that came across this problem in 2022, here is @malderete solution updated for latest auditlog version:
#########
And it matters in which order inheritance is listed:
@mcanu This is working for me. Thank you for solution.
@malderete @ALgracnar @alexsavio Thank you. I added missing imports.
It works for me
For anyone stuck in this, you can create a custom middleware to populate the request.user in a middleware before running the auditlog middleware. https://crondev.wordpress.com/2018/05/13/django-middlewares-with-rest-framework/
I’m having this same issue when using this package with the Django REST Framework and Django-REST-JWT. See below for settings.py:
Screenshot of my Admin dashboard. The user for all Log Entry objects is displayed as ‘system’
The problem is the INSTALLED_APPS’s order, you just need to put auditlog app above djangorestframework app on settings.py file and @mcanu middleware, that’s it.
Hope this helps!
In my case when i am using your code my user variable is printing AnonymousUser which again lead to the same problem showing system value of actor field @magdumsuraj07
@hassaanalansary 's Idea can be modified in newer versions with the introduced -> from auditlog.context import set_actor I modified my SimpleJWT Based Auth like this ` def authenticate(self, request): …
I was a lot of time checking all these things, but nothing work for me , I was making a research about DRF and middleware, how it work and found the problem , nothing is wrong with DRF or with django-auditlog. The problem is from the middleware you can’t get the request.user when the request come from a view like is the case with DRF APIviews, and how we are registering the log in the models you will not get the user according to the token in this moment. I recommend register the log (auditlog.register(AnyModel)) in the model when we can have the log when someone manage the data from django admin panel, but to know the actor from the api or views whe need to register the log in the view , after middleware , and after view is complete loaded.
class AnyModel(models.Model): …
auditlog.register(AnyModel)
class MyApiview(APIView):
@staticmethod def post(request): card, created = AnyModel.objects.update_or_create( name=‘Jhon’ ) auditlog.register(AnyModel)
I know this is not the best solution but work for DRF and django-auditlog lib, remember this lib (django-auditlog) is not for DRF , it is for django, it will log everything if you use django admin or web, but not DRF
my middleware:
from django.utils.functional import SimpleLazyObject from django.contrib.auth import get_user from oauth2_provider.models import AccessToken
class RestOauthMiddleware(object):
THIS WORK FOR ME , AND I CAN NOW REGISTER THE ACTOR FROM MY APIs views
for oauth2_provider i fix issue wit create middleware :
and add middleware in setting file above of auditlog middleware.