mirror of
https://github.com/ansible/awx.git
synced 2026-01-09 23:12:08 -03:30
Get created_by and modified_by updating automatically.
This commit is contained in:
parent
d632aa0af9
commit
118ddf97f6
@ -253,11 +253,7 @@ class ListAPIView(generics.ListAPIView, GenericAPIView):
|
||||
|
||||
class ListCreateAPIView(ListAPIView, generics.ListCreateAPIView):
|
||||
# Base class for a list view that allows creating new objects.
|
||||
|
||||
def pre_save(self, obj):
|
||||
super(ListCreateAPIView, self).pre_save(obj)
|
||||
if isinstance(obj, PrimordialModel):
|
||||
obj.created_by = self.request.user
|
||||
pass
|
||||
|
||||
class SubListAPIView(ListAPIView):
|
||||
# Base class for a read-only sublist view.
|
||||
|
||||
@ -17,6 +17,7 @@ d2to1==0.2.11 (d2to1/*)
|
||||
distribute==0.7.3 (no files)
|
||||
django-auth-ldap==1.1.8 (django_auth_ldap/*)
|
||||
django-celery==3.1.10 (djcelery/*)
|
||||
django-crum==0.6.1 (crum/*)
|
||||
django-extensions==1.3.3 (django_extensions/*)
|
||||
django-jsonfield==0.9.12 (jsonfield/*, minor fix in jsonfield/fields.py)
|
||||
django-polymorphic==0.5.3 (polymorphic/*)
|
||||
|
||||
87
awx/lib/site-packages/crum/__init__.py
Normal file
87
awx/lib/site-packages/crum/__init__.py
Normal file
@ -0,0 +1,87 @@
|
||||
# Python
|
||||
import contextlib
|
||||
import logging
|
||||
import threading
|
||||
|
||||
_thread_locals = threading.local()
|
||||
|
||||
_logger = logging.getLogger('crum')
|
||||
|
||||
__version__ = '0.6.1'
|
||||
|
||||
__all__ = ['get_current_request', 'get_current_user', 'impersonate']
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def impersonate(user=None):
|
||||
"""Temporarily impersonate the given user for audit trails."""
|
||||
try:
|
||||
current_user = get_current_user(_return_false=True)
|
||||
set_current_user(user)
|
||||
yield user
|
||||
finally:
|
||||
set_current_user(current_user)
|
||||
|
||||
|
||||
def get_current_request():
|
||||
"""Return the request associated with the current thread."""
|
||||
return getattr(_thread_locals, 'request', None)
|
||||
|
||||
|
||||
def set_current_request(request=None):
|
||||
"""Update the request associated with the current thread."""
|
||||
_thread_locals.request = request
|
||||
# Clear the current user if also clearing the request.
|
||||
if not request:
|
||||
set_current_user(False)
|
||||
|
||||
|
||||
def get_current_user(_return_false=False):
|
||||
"""Return the user associated with the current request thread."""
|
||||
from crum.signals import current_user_getter
|
||||
top_priority = -9999
|
||||
top_user = False if _return_false else None
|
||||
results = current_user_getter.send_robust(get_current_user)
|
||||
for receiver, response in results:
|
||||
priority = 0
|
||||
if isinstance(response, Exception):
|
||||
_logger.exception('%r raised exception: %s', receiver, response)
|
||||
continue
|
||||
elif isinstance(response, (tuple, list)) and response:
|
||||
user = response[0]
|
||||
if len(response) > 1:
|
||||
priority = response[1]
|
||||
elif response or response in (None, False):
|
||||
user = response
|
||||
else:
|
||||
_logger.error('%r returned invalid response: %r', receiver,
|
||||
response)
|
||||
continue
|
||||
if user is not False:
|
||||
if priority > top_priority:
|
||||
top_priority = priority
|
||||
top_user = user
|
||||
return top_user
|
||||
|
||||
|
||||
def set_current_user(user=None):
|
||||
"""Update the user associated with the current request thread."""
|
||||
from crum.signals import current_user_setter
|
||||
results = current_user_setter.send_robust(set_current_user, user=user)
|
||||
for receiver, response in results:
|
||||
if isinstance(response, Exception):
|
||||
_logger.exception('%r raised exception: %s', receiver, response)
|
||||
|
||||
|
||||
class CurrentRequestUserMiddleware(object):
|
||||
"""Middleware to capture the request and user from the current thread."""
|
||||
|
||||
def process_request(self, request):
|
||||
set_current_request(request)
|
||||
|
||||
def process_response(self, request, response):
|
||||
set_current_request(None)
|
||||
return response
|
||||
|
||||
def process_exception(self, request, exception):
|
||||
set_current_request(None)
|
||||
44
awx/lib/site-packages/crum/signals.py
Normal file
44
awx/lib/site-packages/crum/signals.py
Normal file
@ -0,0 +1,44 @@
|
||||
# Django
|
||||
from django.dispatch import Signal, receiver
|
||||
|
||||
__all__ = ['current_user_getter']
|
||||
|
||||
|
||||
# Signal used when getting current user. Receivers should return a tuple of
|
||||
# (user, priority).
|
||||
current_user_getter = Signal(providing_args=[])
|
||||
|
||||
|
||||
# Signal used when setting current user. Receivers should store the current
|
||||
# user as needed. Return values are ignored.
|
||||
current_user_setter = Signal(providing_args=['user'])
|
||||
|
||||
|
||||
@receiver(current_user_getter)
|
||||
def _get_current_user_from_request(sender, **kwargs):
|
||||
"""Signal handler to retrieve current user from request."""
|
||||
from crum import get_current_request
|
||||
return (getattr(get_current_request(), 'user', False), -10)
|
||||
|
||||
|
||||
@receiver(current_user_getter)
|
||||
def _get_current_user_from_thread_locals(sender, **kwargs):
|
||||
"""Signal handler to retrieve current user from thread locals."""
|
||||
from crum import _thread_locals
|
||||
return (getattr(_thread_locals, 'user', False), 10)
|
||||
|
||||
|
||||
@receiver(current_user_setter)
|
||||
def _set_current_user_on_request(sender, **kwargs):
|
||||
"""Signal handler to store current user to request."""
|
||||
from crum import get_current_request
|
||||
request = get_current_request()
|
||||
if request:
|
||||
request.user = kwargs['user']
|
||||
|
||||
|
||||
@receiver(current_user_setter)
|
||||
def _set_current_user_on_thread_locals(sender, **kwargs):
|
||||
"""Signal handler to store current user on thread locals."""
|
||||
from crum import _thread_locals
|
||||
_thread_locals.user = kwargs['user']
|
||||
@ -27,6 +27,9 @@ from taggit.managers import TaggableManager
|
||||
# Django-Celery
|
||||
from djcelery.models import TaskMeta
|
||||
|
||||
# Django-CRUM
|
||||
from crum import get_current_user
|
||||
|
||||
# Ansible Tower
|
||||
from awx.main.utils import encrypt_field
|
||||
|
||||
@ -284,6 +287,20 @@ class PrimordialModel(CreatedModifiedModel):
|
||||
self.save(update_fields=update_fields)
|
||||
return update_fields
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
update_fields = kwargs.get('update_fields', [])
|
||||
user = get_current_user()
|
||||
if user and not user.pk:
|
||||
user = None
|
||||
if not self.pk:
|
||||
self.created_by = user
|
||||
if 'created_by' not in update_fields:
|
||||
update_fields.append('created_by')
|
||||
self.modified_by = user
|
||||
if 'modified_by' not in update_fields:
|
||||
update_fields.append('modified_by')
|
||||
super(PrimordialModel, self).save(*args, **kwargs)
|
||||
|
||||
def clean_description(self):
|
||||
# Description should always be empty string, never null.
|
||||
return self.description or ''
|
||||
|
||||
@ -12,6 +12,10 @@ from django.conf import settings
|
||||
from django.db.models.signals import pre_save, post_save, pre_delete, post_delete, m2m_changed
|
||||
from django.dispatch import receiver
|
||||
|
||||
# Django-CRUM
|
||||
from crum import get_current_request
|
||||
from crum.signals import current_user_getter
|
||||
|
||||
# AWX
|
||||
from awx.main.models import *
|
||||
from awx.api.serializers import *
|
||||
@ -361,3 +365,15 @@ def activity_stream_associate(sender, instance, **kwargs):
|
||||
activity_entry.save()
|
||||
getattr(activity_entry, object1).add(obj1)
|
||||
getattr(activity_entry, object2).add(obj2_actual)
|
||||
|
||||
|
||||
@receiver(current_user_getter)
|
||||
def get_current_user_from_drf_request(sender, **kwargs):
|
||||
'''
|
||||
Provider a signal handler to return the current user from the current
|
||||
request when using Django REST Framework. Requires that the APIView set
|
||||
drf_request on the underlying Django Request object.
|
||||
'''
|
||||
request = get_current_request()
|
||||
drf_request = getattr(request, 'drf_request', None)
|
||||
return (getattr(drf_request, 'user', False), 0)
|
||||
|
||||
@ -112,7 +112,8 @@ TEMPLATE_CONTEXT_PROCESSORS += (
|
||||
MIDDLEWARE_CLASSES += (
|
||||
'django.middleware.transaction.TransactionMiddleware',
|
||||
# Middleware loaded after this point will be subject to transactions.
|
||||
'awx.main.middleware.ActivityStreamMiddleware'
|
||||
'awx.main.middleware.ActivityStreamMiddleware',
|
||||
'crum.CurrentRequestUserMiddleware',
|
||||
)
|
||||
|
||||
TEMPLATE_DIRS = (
|
||||
|
||||
@ -12,6 +12,7 @@ Django>=1.4
|
||||
#boto
|
||||
#django-auth-ldap
|
||||
#django-celery
|
||||
#django-crum
|
||||
#django-extensions
|
||||
#django-jsonfield
|
||||
#django-split-settings
|
||||
|
||||
@ -62,6 +62,7 @@ Django-1.5.5.tar.gz
|
||||
#boto-2.27.0.tar.gz
|
||||
#django-auth-ldap-1.1.8.tar.gz
|
||||
#django-celery-3.1.10.tar.gz
|
||||
#django-crum-0.6.1.tar.gz
|
||||
#django-extensions-1.3.3.tar.gz
|
||||
#django-jsonfield-0.9.12.tar.gz
|
||||
#django_polymorphic-0.5.3.tar.gz
|
||||
|
||||
BIN
requirements/django-crum-0.6.1.tar.gz
Normal file
BIN
requirements/django-crum-0.6.1.tar.gz
Normal file
Binary file not shown.
@ -9,6 +9,7 @@ Django>=1.4
|
||||
#boto
|
||||
#django-auth-ldap
|
||||
#django-celery
|
||||
#django-crum
|
||||
#django-extensions
|
||||
#django-jsonfield
|
||||
#django-polymorphic
|
||||
|
||||
@ -60,6 +60,7 @@ Django-1.5.5.tar.gz
|
||||
#boto-2.27.0.tar.gz
|
||||
#django-auth-ldap-1.1.8.tar.gz
|
||||
#django-celery-3.1.10.tar.gz
|
||||
#django-crum-0.6.1.tar.gz
|
||||
#django-extensions-1.3.3.tar.gz
|
||||
#django-jsonfield-0.9.12.tar.gz
|
||||
#django_polymorphic-0.5.3.tar.gz
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user