diff --git a/awx/api/serializers.py b/awx/api/serializers.py index 9c9d0634d7..52f19eff11 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -4616,8 +4616,10 @@ class ActivityStreamSerializer(BaseSerializer): ('workflow_job_template_node', ('id', 'unified_job_template_id')), ('label', ('id', 'name', 'organization_id')), ('notification', ('id', 'status', 'notification_type', 'notification_template_id')), - ('access_token', ('id', 'token')), - ('credential_type', ('id', 'name', 'description', 'kind', 'managed_by_tower')) + ('o_auth2_access_token', ('id', 'user_id', 'description', 'application', 'scope')), + ('o_auth2_application', ('id', 'name', 'description')), + ('credential_type', ('id', 'name', 'description', 'kind', 'managed_by_tower')), + ('ad_hoc_command', ('id', 'name', 'status', 'limit')) ] return field_list @@ -4659,6 +4661,10 @@ class ActivityStreamSerializer(BaseSerializer): def get_related(self, obj): rel = {} + VIEW_NAME_EXCEPTIONS = { + 'custom_inventory_script': 'inventory_script_detail', + 'o_auth2_access_token': 'o_auth2_token_detail' + } if obj.actor is not None: rel['actor'] = self.reverse('api:user_detail', kwargs={'pk': obj.actor.pk}) for fk, __ in self._local_summarizable_fk_fields: @@ -4672,18 +4678,11 @@ class ActivityStreamSerializer(BaseSerializer): if getattr(thisItem, 'id', None) in id_list: continue id_list.append(getattr(thisItem, 'id', None)) - if fk == 'custom_inventory_script': - rel[fk].append(self.reverse('api:inventory_script_detail', kwargs={'pk': thisItem.id})) - elif fk == 'application': - rel[fk].append(self.reverse( - 'api:o_auth2_application_detail', kwargs={'pk': thisItem.pk} - )) - elif fk == 'access_token': - rel[fk].append(self.reverse( - 'api:o_auth2_token_detail', kwargs={'pk': thisItem.pk} - )) + if fk in VIEW_NAME_EXCEPTIONS: + view_name = VIEW_NAME_EXCEPTIONS[fk] else: - rel[fk].append(self.reverse('api:' + fk + '_detail', kwargs={'pk': thisItem.id})) + view_name = fk + '_detail' + rel[fk].append(self.reverse('api:' + view_name, kwargs={'pk': thisItem.id})) if fk == 'schedule': rel['unified_job_template'] = thisItem.unified_job_template.get_absolute_url(self.context.get('request')) diff --git a/awx/main/tests/unit/api/serializers/test_activity_stream_serializer.py b/awx/main/tests/unit/api/serializers/test_activity_stream_serializer.py new file mode 100644 index 0000000000..50849b31c5 --- /dev/null +++ b/awx/main/tests/unit/api/serializers/test_activity_stream_serializer.py @@ -0,0 +1,31 @@ +from awx.api.serializers import ActivityStreamSerializer +from awx.main.registrar import activity_stream_registrar +from awx.main.models import ActivityStream + +from awx.conf.models import Setting + + +def test_activity_stream_related(): + ''' + If this test failed with content in `missing_models`, that means that a + model has been connected to the activity stream, but the model has not + been added to the activity stream serializer. + + How to fix this: + Ideally, all models should be in awx.api.serializers.SUMMARIZABLE_FK_FIELDS + + If, for whatever reason, the missing model should not generally be + summarized from related resources, then a special case can be carved out in + ActivityStreamSerializer._local_summarizable_fk_fields + ''' + serializer_related = set( + ActivityStream._meta.get_field(field_name).related_model for field_name, stuff in + ActivityStreamSerializer()._local_summarizable_fk_fields + if hasattr(ActivityStream, field_name) + ) + + models = set(activity_stream_registrar.models) + models.remove(Setting) + + missing_models = models - serializer_related + assert not missing_models