Merge pull request #1768 from AlanCoding/all_the_search_fields

Enforce consistently setting view search_fields
This commit is contained in:
Alan Rominger 2018-05-15 08:32:44 -04:00 committed by GitHub
commit 64fed4d360
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 101 additions and 0 deletions

View File

@ -612,6 +612,7 @@ class InstanceList(ListAPIView):
view_name = _("Instances")
model = Instance
serializer_class = InstanceSerializer
search_fields = ('hostname',)
class InstanceDetail(RetrieveUpdateAPIView):
@ -698,6 +699,7 @@ class InstanceGroupInstanceList(InstanceGroupMembershipMixin, SubListAttachDetac
serializer_class = InstanceSerializer
parent_model = InstanceGroup
relationship = "instances"
search_fields = ('hostname',)
class ScheduleList(ListAPIView):
@ -1074,6 +1076,7 @@ class OrganizationActivityStreamList(ActivityStreamEnforcementMixin, SubListAPIV
serializer_class = ActivityStreamSerializer
parent_model = Organization
relationship = 'activitystream_set'
search_fields = ('changes',)
class OrganizationNotificationTemplatesList(SubListCreateAttachDetachAPIView):
@ -1128,6 +1131,7 @@ class OrganizationObjectRolesList(SubListAPIView):
model = Role
serializer_class = RoleSerializer
parent_model = Organization
search_fields = ('role_field', 'content_type__model',)
def get_queryset(self):
po = self.get_parent_object()
@ -1167,6 +1171,7 @@ class TeamRolesList(SubListAttachDetachAPIView):
metadata_class = RoleMetadata
parent_model = Team
relationship='member_role.children'
search_fields = ('role_field', 'content_type__model',)
def get_queryset(self):
team = get_object_or_404(Team, pk=self.kwargs['pk'])
@ -1204,6 +1209,7 @@ class TeamObjectRolesList(SubListAPIView):
model = Role
serializer_class = RoleSerializer
parent_model = Team
search_fields = ('role_field', 'content_type__model',)
def get_queryset(self):
po = self.get_parent_object()
@ -1235,6 +1241,7 @@ class TeamActivityStreamList(ActivityStreamEnforcementMixin, SubListAPIView):
serializer_class = ActivityStreamSerializer
parent_model = Team
relationship = 'activitystream_set'
search_fields = ('changes',)
def get_queryset(self):
parent = self.get_parent_object()
@ -1330,6 +1337,7 @@ class ProjectActivityStreamList(ActivityStreamEnforcementMixin, SubListAPIView):
serializer_class = ActivityStreamSerializer
parent_model = Project
relationship = 'activitystream_set'
search_fields = ('changes',)
def get_queryset(self):
parent = self.get_parent_object()
@ -1417,6 +1425,7 @@ class ProjectUpdateEventsList(SubListAPIView):
parent_model = ProjectUpdate
relationship = 'project_update_events'
view_name = _('Project Update Events List')
search_fields = ('stdout',)
def finalize_response(self, request, response, *args, **kwargs):
response['X-UI-Max-Events'] = settings.MAX_UI_JOB_EVENTS
@ -1430,6 +1439,7 @@ class SystemJobEventsList(SubListAPIView):
parent_model = SystemJob
relationship = 'system_job_events'
view_name = _('System Job Events List')
search_fields = ('stdout',)
def finalize_response(self, request, response, *args, **kwargs):
response['X-UI-Max-Events'] = settings.MAX_UI_JOB_EVENTS
@ -1443,6 +1453,7 @@ class InventoryUpdateEventsList(SubListAPIView):
parent_model = InventoryUpdate
relationship = 'inventory_update_events'
view_name = _('Inventory Update Events List')
search_fields = ('stdout',)
def finalize_response(self, request, response, *args, **kwargs):
response['X-UI-Max-Events'] = settings.MAX_UI_JOB_EVENTS
@ -1470,6 +1481,7 @@ class ProjectUpdateNotificationsList(SubListAPIView):
serializer_class = NotificationSerializer
parent_model = ProjectUpdate
relationship = 'notifications'
search_fields = ('subject', 'notification_type', 'body',)
class ProjectUpdateScmInventoryUpdates(SubListCreateAPIView):
@ -1493,6 +1505,7 @@ class ProjectObjectRolesList(SubListAPIView):
model = Role
serializer_class = RoleSerializer
parent_model = Project
search_fields = ('role_field', 'content_type__model',)
def get_queryset(self):
po = self.get_parent_object()
@ -1575,6 +1588,7 @@ class OAuth2ApplicationActivityStreamList(ActivityStreamEnforcementMixin, SubLis
parent_model = OAuth2Application
relationship = 'activitystream_set'
swagger_topic = 'Authentication'
search_fields = ('changes',)
class OAuth2TokenList(ListCreateAPIView):
@ -1659,6 +1673,7 @@ class OAuth2TokenActivityStreamList(ActivityStreamEnforcementMixin, SubListAPIVi
parent_model = OAuth2AccessToken
relationship = 'activitystream_set'
swagger_topic = 'Authentication'
search_fields = ('changes',)
class UserTeamsList(ListAPIView):
@ -1682,6 +1697,7 @@ class UserRolesList(SubListAttachDetachAPIView):
parent_model = User
relationship='roles'
permission_classes = (IsAuthenticated,)
search_fields = ('role_field', 'content_type__model',)
def get_queryset(self):
u = get_object_or_404(User, pk=self.kwargs['pk'])
@ -1768,6 +1784,7 @@ class UserActivityStreamList(ActivityStreamEnforcementMixin, SubListAPIView):
serializer_class = ActivityStreamSerializer
parent_model = User
relationship = 'activitystream_set'
search_fields = ('changes',)
def get_queryset(self):
parent = self.get_parent_object()
@ -1854,6 +1871,7 @@ class CredentialTypeActivityStreamList(ActivityStreamEnforcementMixin, SubListAP
serializer_class = ActivityStreamSerializer
parent_model = CredentialType
relationship = 'activitystream_set'
search_fields = ('changes',)
# remove in 3.3
@ -1967,6 +1985,7 @@ class CredentialActivityStreamList(ActivityStreamEnforcementMixin, SubListAPIVie
serializer_class = ActivityStreamSerializer
parent_model = Credential
relationship = 'activitystream_set'
search_fields = ('changes',)
class CredentialAccessList(ResourceAccessList):
@ -1980,6 +1999,7 @@ class CredentialObjectRolesList(SubListAPIView):
model = Role
serializer_class = RoleSerializer
parent_model = Credential
search_fields = ('role_field', 'content_type__model',)
def get_queryset(self):
po = self.get_parent_object()
@ -2020,6 +2040,7 @@ class InventoryScriptObjectRolesList(SubListAPIView):
model = Role
serializer_class = RoleSerializer
parent_model = CustomInventoryScript
search_fields = ('role_field', 'content_type__model',)
def get_queryset(self):
po = self.get_parent_object()
@ -2107,6 +2128,7 @@ class InventoryActivityStreamList(ActivityStreamEnforcementMixin, SubListAPIView
serializer_class = ActivityStreamSerializer
parent_model = Inventory
relationship = 'activitystream_set'
search_fields = ('changes',)
def get_queryset(self):
parent = self.get_parent_object()
@ -2134,6 +2156,7 @@ class InventoryObjectRolesList(SubListAPIView):
model = Role
serializer_class = RoleSerializer
parent_model = Inventory
search_fields = ('role_field', 'content_type__model',)
def get_queryset(self):
po = self.get_parent_object()
@ -2277,6 +2300,7 @@ class HostActivityStreamList(ActivityStreamEnforcementMixin, SubListAPIView):
serializer_class = ActivityStreamSerializer
parent_model = Host
relationship = 'activitystream_set'
search_fields = ('changes',)
def get_queryset(self):
parent = self.get_parent_object()
@ -2290,6 +2314,7 @@ class HostFactVersionsList(SystemTrackingEnforcementMixin, ParentMixin, ListAPIV
model = Fact
serializer_class = FactVersionSerializer
parent_model = Host
search_fields = ('facts',)
def get_queryset(self):
from_spec = self.request.query_params.get('from', None)
@ -2523,6 +2548,7 @@ class GroupActivityStreamList(ActivityStreamEnforcementMixin, SubListAPIView):
serializer_class = ActivityStreamSerializer
parent_model = Group
relationship = 'activitystream_set'
search_fields = ('changes',)
def get_queryset(self):
parent = self.get_parent_object()
@ -2754,6 +2780,7 @@ class InventorySourceActivityStreamList(ActivityStreamEnforcementMixin, SubListA
serializer_class = ActivityStreamSerializer
parent_model = InventorySource
relationship = 'activitystream_set'
search_fields = ('changes',)
class InventorySourceNotificationTemplatesAnyList(SubListCreateAttachDetachAPIView):
@ -2893,6 +2920,7 @@ class InventoryUpdateNotificationsList(SubListAPIView):
serializer_class = NotificationSerializer
parent_model = InventoryUpdate
relationship = 'notifications'
search_fields = ('subject', 'notification_type', 'body',)
class JobTemplateList(ListCreateAPIView):
@ -3231,6 +3259,7 @@ class JobTemplateActivityStreamList(ActivityStreamEnforcementMixin, SubListAPIVi
serializer_class = ActivityStreamSerializer
parent_model = JobTemplate
relationship = 'activitystream_set'
search_fields = ('changes',)
class JobTemplateNotificationTemplatesAnyList(SubListCreateAttachDetachAPIView):
@ -3514,6 +3543,7 @@ class JobTemplateObjectRolesList(SubListAPIView):
model = Role
serializer_class = RoleSerializer
parent_model = JobTemplate
search_fields = ('role_field', 'content_type__model',)
def get_queryset(self):
po = self.get_parent_object()
@ -3531,6 +3561,7 @@ class WorkflowJobNodeList(WorkflowsEnforcementMixin, ListAPIView):
model = WorkflowJobNode
serializer_class = WorkflowJobNodeListSerializer
search_fields = ('unified_job_template__name', 'unified_job_template__description',)
class WorkflowJobNodeDetail(WorkflowsEnforcementMixin, RetrieveAPIView):
@ -3551,6 +3582,7 @@ class WorkflowJobTemplateNodeList(WorkflowsEnforcementMixin, ListCreateAPIView):
model = WorkflowJobTemplateNode
serializer_class = WorkflowJobTemplateNodeSerializer
search_fields = ('unified_job_template__name', 'unified_job_template__description',)
class WorkflowJobTemplateNodeDetail(WorkflowsEnforcementMixin, RetrieveUpdateDestroyAPIView):
@ -3572,6 +3604,7 @@ class WorkflowJobTemplateNodeChildrenBaseList(WorkflowsEnforcementMixin, Enforce
parent_model = WorkflowJobTemplateNode
relationship = ''
enforce_parent_relationship = 'workflow_job_template'
search_fields = ('unified_job_template__name', 'unified_job_template__description',)
'''
Limit the set of WorkflowJobTemplateNodes to the related nodes of specified by
@ -3641,6 +3674,7 @@ class WorkflowJobNodeChildrenBaseList(WorkflowsEnforcementMixin, SubListAPIView)
serializer_class = WorkflowJobNodeListSerializer
parent_model = WorkflowJobNode
relationship = ''
search_fields = ('unified_job_template__name', 'unified_job_template__description',)
#
#Limit the set of WorkflowJobeNodes to the related nodes of specified by
@ -3796,6 +3830,7 @@ class WorkflowJobTemplateWorkflowNodesList(WorkflowsEnforcementMixin, SubListCre
parent_model = WorkflowJobTemplate
relationship = 'workflow_job_template_nodes'
parent_key = 'workflow_job_template'
search_fields = ('unified_job_template__name', 'unified_job_template__description',)
def get_queryset(self):
return super(WorkflowJobTemplateWorkflowNodesList, self).get_queryset().order_by('id')
@ -3856,6 +3891,7 @@ class WorkflowJobTemplateObjectRolesList(WorkflowsEnforcementMixin, SubListAPIVi
model = Role
serializer_class = RoleSerializer
parent_model = WorkflowJobTemplate
search_fields = ('role_field', 'content_type__model',)
def get_queryset(self):
po = self.get_parent_object()
@ -3869,6 +3905,7 @@ class WorkflowJobTemplateActivityStreamList(WorkflowsEnforcementMixin, ActivityS
serializer_class = ActivityStreamSerializer
parent_model = WorkflowJobTemplate
relationship = 'activitystream_set'
search_fields = ('changes',)
def get_queryset(self):
parent = self.get_parent_object()
@ -3898,6 +3935,7 @@ class WorkflowJobWorkflowNodesList(WorkflowsEnforcementMixin, SubListAPIView):
parent_model = WorkflowJob
relationship = 'workflow_job_nodes'
parent_key = 'workflow_job'
search_fields = ('unified_job_template__name', 'unified_job_template__description',)
def get_queryset(self):
return super(WorkflowJobWorkflowNodesList, self).get_queryset().order_by('id')
@ -3926,6 +3964,7 @@ class WorkflowJobNotificationsList(WorkflowsEnforcementMixin, SubListAPIView):
serializer_class = NotificationSerializer
parent_model = WorkflowJob
relationship = 'notifications'
search_fields = ('subject', 'notification_type', 'body',)
class WorkflowJobActivityStreamList(WorkflowsEnforcementMixin, ActivityStreamEnforcementMixin, SubListAPIView):
@ -3934,6 +3973,7 @@ class WorkflowJobActivityStreamList(WorkflowsEnforcementMixin, ActivityStreamEnf
serializer_class = ActivityStreamSerializer
parent_model = WorkflowJob
relationship = 'activitystream_set'
search_fields = ('changes',)
class SystemJobTemplateList(ListAPIView):
@ -4089,6 +4129,7 @@ class JobActivityStreamList(ActivityStreamEnforcementMixin, SubListAPIView):
serializer_class = ActivityStreamSerializer
parent_model = Job
relationship = 'activitystream_set'
search_fields = ('changes',)
# TODO: remove endpoint in 3.3
@ -4292,6 +4333,7 @@ class JobNotificationsList(SubListAPIView):
serializer_class = NotificationSerializer
parent_model = Job
relationship = 'notifications'
search_fields = ('subject', 'notification_type', 'body',)
class BaseJobHostSummariesList(SubListAPIView):
@ -4301,6 +4343,7 @@ class BaseJobHostSummariesList(SubListAPIView):
parent_model = None # Subclasses must define this attribute.
relationship = 'job_host_summaries'
view_name = _('Job Host Summaries List')
search_fields = ('host_name',)
def get_queryset(self):
parent = self.get_parent_object()
@ -4333,6 +4376,7 @@ class JobEventList(ListAPIView):
model = JobEvent
serializer_class = JobEventSerializer
search_fields = ('stdout',)
class JobEventDetail(RetrieveAPIView):
@ -4348,6 +4392,7 @@ class JobEventChildrenList(SubListAPIView):
parent_model = JobEvent
relationship = 'children'
view_name = _('Job Event Children List')
search_fields = ('stdout',)
class JobEventHostsList(HostRelatedSearchMixin, SubListAPIView):
@ -4561,6 +4606,7 @@ class AdHocCommandEventList(ListAPIView):
model = AdHocCommandEvent
serializer_class = AdHocCommandEventSerializer
search_fields = ('stdout',)
class AdHocCommandEventDetail(RetrieveAPIView):
@ -4576,6 +4622,7 @@ class BaseAdHocCommandEventsList(SubListAPIView):
parent_model = None # Subclasses must define this attribute.
relationship = 'ad_hoc_command_events'
view_name = _('Ad Hoc Command Events List')
search_fields = ('stdout',)
class HostAdHocCommandEventsList(BaseAdHocCommandEventsList):
@ -4598,6 +4645,7 @@ class AdHocCommandActivityStreamList(ActivityStreamEnforcementMixin, SubListAPIV
serializer_class = ActivityStreamSerializer
parent_model = AdHocCommand
relationship = 'activitystream_set'
search_fields = ('changes',)
class AdHocCommandNotificationsList(SubListAPIView):
@ -4606,6 +4654,7 @@ class AdHocCommandNotificationsList(SubListAPIView):
serializer_class = NotificationSerializer
parent_model = AdHocCommand
relationship = 'notifications'
search_fields = ('subject', 'notification_type', 'body',)
class SystemJobList(ListCreateAPIView):
@ -4646,6 +4695,7 @@ class SystemJobNotificationsList(SubListAPIView):
serializer_class = NotificationSerializer
parent_model = SystemJob
relationship = 'notifications'
search_fields = ('subject', 'notification_type', 'body',)
class UnifiedJobTemplateList(ListAPIView):
@ -4851,6 +4901,7 @@ class NotificationTemplateNotificationList(SubListAPIView):
parent_model = NotificationTemplate
relationship = 'notifications'
parent_key = 'notification_template'
search_fields = ('subject', 'notification_type', 'body',)
class NotificationTemplateCopy(CopyAPIView):
@ -4863,6 +4914,7 @@ class NotificationList(ListAPIView):
model = Notification
serializer_class = NotificationSerializer
search_fields = ('subject', 'notification_type', 'body',)
class NotificationDetail(RetrieveAPIView):
@ -4887,6 +4939,7 @@ class ActivityStreamList(ActivityStreamEnforcementMixin, SimpleListAPIView):
model = ActivityStream
serializer_class = ActivityStreamSerializer
search_fields = ('changes',)
class ActivityStreamDetail(ActivityStreamEnforcementMixin, RetrieveAPIView):
@ -4900,6 +4953,7 @@ class RoleList(ListAPIView):
model = Role
serializer_class = RoleSerializer
permission_classes = (IsAuthenticated,)
search_fields = ('role_field', 'content_type__model',)
def get_queryset(self):
result = Role.visible_roles(self.request.user)
@ -5012,6 +5066,7 @@ class RoleParentsList(SubListAPIView):
parent_model = Role
relationship = 'parents'
permission_classes = (IsAuthenticated,)
search_fields = ('role_field', 'content_type__model',)
def get_queryset(self):
role = Role.objects.get(pk=self.kwargs['pk'])
@ -5025,6 +5080,7 @@ class RoleChildrenList(SubListAPIView):
parent_model = Role
relationship = 'children'
permission_classes = (IsAuthenticated,)
search_fields = ('role_field', 'content_type__model',)
def get_queryset(self):
role = Role.objects.get(pk=self.kwargs['pk'])

View File

@ -3,6 +3,10 @@ import mock
# Django REST Framework
from rest_framework import exceptions
from rest_framework.generics import ListAPIView
# Django
from django.core.urlresolvers import RegexURLResolver, RegexURLPattern
# AWX
from awx.main.views import ApiErrorView
@ -52,3 +56,44 @@ def test_disable_post_on_v1_inventory_source_list(version, supports_post):
inv_source_list.request = mock.MagicMock()
with mock.patch('awx.api.views.get_request_version', return_value=version):
assert ('POST' in inv_source_list.allowed_methods) == supports_post
def test_views_have_search_fields():
from awx.api.urls import urlpatterns as api_patterns
patterns = set([])
url_views = set([])
# Add recursive URL patterns
unprocessed = set(api_patterns)
while unprocessed:
to_process = unprocessed.copy()
unprocessed = set([])
for pattern in to_process:
if hasattr(pattern, 'lookup_str') and not pattern.lookup_str.startswith('awx.api'):
continue
patterns.add(pattern)
if isinstance(pattern, RegexURLResolver):
for sub_pattern in pattern.url_patterns:
if sub_pattern not in patterns:
unprocessed.add(sub_pattern)
# Get view classes
for pattern in patterns:
if isinstance(pattern, RegexURLPattern) and hasattr(pattern.callback, 'view_class'):
cls = pattern.callback.view_class
if issubclass(cls, ListAPIView):
url_views.add(pattern.callback.view_class)
# Gather any views that don't have search fields defined
views_missing_search = []
for View in url_views:
view = View()
if not hasattr(view, 'search_fields') or len(view.search_fields) == 0:
views_missing_search.append(view)
if views_missing_search:
raise Exception('{} views do not have search fields defined:\n{}'.format(
len(views_missing_search),
'\n'.join([
v.__class__.__name__ + ' (model: {})'.format(getattr(v, 'model', type(None)).__name__)
for v in views_missing_search
]))
)