Added activity stream events for User

Completes development for #1087
This commit is contained in:
Akita Noek
2016-04-06 16:07:04 -04:00
parent 86d98e0999
commit 6182dad0d4
3 changed files with 31 additions and 11 deletions

View File

@@ -11,6 +11,7 @@ import time
import socket import socket
import sys import sys
import errno import errno
import logging
from base64 import b64encode from base64 import b64encode
from collections import OrderedDict from collections import OrderedDict
@@ -22,7 +23,7 @@ from django.core.exceptions import FieldError
from django.db.models import Q, Count from django.db.models import Q, Count
from django.db import IntegrityError, transaction from django.db import IntegrityError, transaction
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.utils.encoding import force_text from django.utils.encoding import smart_text, force_text
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils.timezone import now from django.utils.timezone import now
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
@@ -71,6 +72,8 @@ from awx.api.metadata import RoleMetadata
from awx.main.utils import emit_websocket_notification from awx.main.utils import emit_websocket_notification
from awx.main.conf import tower_settings from awx.main.conf import tower_settings
logger = logging.getLogger('awx.api.generics')
def api_exception_handler(exc, context): def api_exception_handler(exc, context):
''' '''
Override default API exception handler to catch IntegrityError exceptions. Override default API exception handler to catch IntegrityError exceptions.
@@ -528,9 +531,13 @@ class AuthTokenView(APIView):
expires__gt=now(), expires__gt=now(),
reason='')[0] reason='')[0]
token.refresh() token.refresh()
if 'username' in request.data:
logger.info(smart_text(u"User {} logged in".format(request.data['username'])))
except IndexError: except IndexError:
token = AuthToken.objects.create(user=serializer.validated_data['user'], token = AuthToken.objects.create(user=serializer.validated_data['user'],
request_hash=request_hash) request_hash=request_hash)
if 'username' in request.data:
logger.info(smart_text(u"User {} logged in".format(request.data['username'])))
# Get user un-expired tokens that are not invalidated that are # Get user un-expired tokens that are not invalidated that are
# over the configured limit. # over the configured limit.
# Mark them as invalid and inform the user # Mark them as invalid and inform the user
@@ -549,6 +556,8 @@ class AuthTokenView(APIView):
'Auth-Token-Timeout': int(tower_settings.AUTH_TOKEN_EXPIRATION) 'Auth-Token-Timeout': int(tower_settings.AUTH_TOKEN_EXPIRATION)
} }
return Response({'token': token.key, 'expires': token.expires}, headers=headers) return Response({'token': token.key, 'expires': token.expires}, headers=headers)
if 'username' in request.data:
logger.warning(smart_text(u"Login failed for user {}".format(request.data['username'])))
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class OrganizationList(ListCreateAPIView): class OrganizationList(ListCreateAPIView):

View File

@@ -85,3 +85,4 @@ activity_stream_registrar.connect(TowerSettings)
activity_stream_registrar.connect(Notifier) activity_stream_registrar.connect(Notifier)
activity_stream_registrar.connect(Notification) activity_stream_registrar.connect(Notification)
activity_stream_registrar.connect(Label) activity_stream_registrar.connect(Label)
activity_stream_registrar.connect(User)

View File

@@ -284,6 +284,22 @@ def update_scm_url(scm_type, url, username=True, password=True,
return new_url return new_url
def get_allowed_fields(obj, serializer_mapping):
from django.contrib.auth.models import User
if serializer_mapping is not None and obj.__class__ in serializer_mapping:
serializer_actual = serializer_mapping[obj.__class__]()
allowed_fields = [x for x in serializer_actual.fields if not serializer_actual.fields[x].read_only] + ['id']
else:
allowed_fields = [x.name for x in obj._meta.fields]
if isinstance(obj, User):
field_blacklist = ['last_login']
allowed_fields = [f for f in allowed_fields if f not in field_blacklist]
return allowed_fields
def model_instance_diff(old, new, serializer_mapping=None): def model_instance_diff(old, new, serializer_mapping=None):
""" """
Calculate the differences between two model instances. One of the instances may be None (i.e., a newly Calculate the differences between two model instances. One of the instances may be None (i.e., a newly
@@ -301,11 +317,7 @@ def model_instance_diff(old, new, serializer_mapping=None):
diff = {} diff = {}
if serializer_mapping is not None and new.__class__ in serializer_mapping: allowed_fields = get_allowed_fields(new, serializer_mapping)
serializer_actual = serializer_mapping[new.__class__]()
allowed_fields = [x for x in serializer_actual.fields if not serializer_actual.fields[x].read_only] + ['id']
else:
allowed_fields = [x.name for x in new._meta.fields]
for field in allowed_fields: for field in allowed_fields:
old_value = getattr(old, field, None) old_value = getattr(old, field, None)
@@ -334,11 +346,9 @@ def model_to_dict(obj, serializer_mapping=None):
""" """
from awx.main.models.credential import Credential from awx.main.models.credential import Credential
attr_d = {} attr_d = {}
if serializer_mapping is not None and obj.__class__ in serializer_mapping:
serializer_actual = serializer_mapping[obj.__class__]() allowed_fields = get_allowed_fields(obj, serializer_mapping)
allowed_fields = [x for x in serializer_actual.fields if not serializer_actual.fields[x].read_only] + ['id']
else:
allowed_fields = [x.name for x in obj._meta.fields]
for field in obj._meta.fields: for field in obj._meta.fields:
if field.name not in allowed_fields: if field.name not in allowed_fields:
continue continue