# Copyright (c) 2015 Ansible, Inc. # All Rights Reserved. # Python import inspect import logging import time import urllib.parse # Django from django.conf import settings from django.db import connection from django.db.models.fields import FieldDoesNotExist from django.db.models.fields.related import OneToOneRel from django.http import QueryDict from django.shortcuts import get_object_or_404 from django.template.loader import render_to_string from django.utils.encoding import smart_text from django.utils.safestring import mark_safe from django.contrib.contenttypes.models import ContentType from django.utils.translation import ugettext_lazy as _ from django.contrib.auth import views as auth_views # Django REST Framework from rest_framework.exceptions import PermissionDenied, AuthenticationFailed, ParseError, NotAcceptable, UnsupportedMediaType from rest_framework import generics from rest_framework.response import Response from rest_framework import status from rest_framework import views from rest_framework.permissions import AllowAny from rest_framework.renderers import StaticHTMLRenderer, JSONRenderer from rest_framework.negotiation import DefaultContentNegotiation # AWX from awx.api.filters import FieldLookupBackend from awx.main.models import ( UnifiedJob, UnifiedJobTemplate, User, Role, Credential, WorkflowJobTemplateNode, WorkflowApprovalTemplate ) from awx.main.access import access_registry from awx.main.utils import ( camelcase_to_underscore, get_search_fields, getattrd, get_object_or_400, decrypt_field ) from awx.main.utils.db import get_all_field_names from awx.api.serializers import ResourceAccessListElementSerializer, CopySerializer, UserSerializer from awx.api.versioning import URLPathVersioning from awx.api.metadata import SublistAttachDetatchMetadata, Metadata __all__ = ['APIView', 'GenericAPIView', 'ListAPIView', 'SimpleListAPIView', 'ListCreateAPIView', 'SubListAPIView', 'SubListCreateAPIView', 'SubListDestroyAPIView', 'SubListCreateAttachDetachAPIView', 'RetrieveAPIView', 'RetrieveUpdateAPIView', 'RetrieveDestroyAPIView', 'RetrieveUpdateDestroyAPIView', 'SubDetailAPIView', 'ResourceAccessList', 'ParentMixin', 'DeleteLastUnattachLabelMixin', 'SubListAttachDetachAPIView', 'CopyAPIView', 'BaseUsersList',] logger = logging.getLogger('awx.api.generics') analytics_logger = logging.getLogger('awx.analytics.performance') class LoggedLoginView(auth_views.LoginView): def get(self, request, *args, **kwargs): # The django.auth.contrib login form doesn't perform the content # negotiation we've come to expect from DRF; add in code to catch # situations where Accept != text/html (or */*) and reply with # an HTTP 406 try: DefaultContentNegotiation().select_renderer( request, [StaticHTMLRenderer], 'html' ) except NotAcceptable: resp = Response(status=status.HTTP_406_NOT_ACCEPTABLE) resp.accepted_renderer = StaticHTMLRenderer() resp.accepted_media_type = 'text/plain' resp.renderer_context = {} return resp return super(LoggedLoginView, self).get(request, *args, **kwargs) def post(self, request, *args, **kwargs): ret = super(LoggedLoginView, self).post(request, *args, **kwargs) current_user = getattr(request, 'user', None) if request.user.is_authenticated: logger.info(smart_text(u"User {} logged in from {}".format(self.request.user.username,request.META.get('REMOTE_ADDR', None)))) ret.set_cookie('userLoggedIn', 'true') current_user = UserSerializer(self.request.user) current_user = smart_text(JSONRenderer().render(current_user.data)) current_user = urllib.parse.quote('%s' % current_user, '') ret.set_cookie('current_user', current_user, secure=settings.SESSION_COOKIE_SECURE or None) return ret else: if 'username' in self.request.POST: logger.warn(smart_text(u"Login failed for user {} from {}".format(self.request.POST.get('username'),request.META.get('REMOTE_ADDR', None)))) ret.status_code = 401 return ret class LoggedLogoutView(auth_views.LogoutView): def dispatch(self, request, *args, **kwargs): original_user = getattr(request, 'user', None) ret = super(LoggedLogoutView, self).dispatch(request, *args, **kwargs) current_user = getattr(request, 'user', None) ret.set_cookie('userLoggedIn', 'false') if (not current_user or not getattr(current_user, 'pk', True)) \ and current_user != original_user: logger.info("User {} logged out.".format(original_user.username)) return ret def get_view_description(view, html=False): '''Wrapper around REST framework get_view_description() to continue to support our historical div. ''' desc = views.get_view_description(view, html=html) if html: desc = '