From ef415ef8265f8bc835533d8683f0dfb456508534 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Fri, 22 Feb 2019 03:57:07 -0400 Subject: [PATCH] Refactor the events app API Use viewsets for the events app API. Use new link badge support for the unread notification count display. Remove AJAX workers support now that it is now needed anymore. Signed-off-by: Roberto Rosario --- mayan/apps/events/api_views.py | 76 +++++++++++------------------ mayan/apps/events/links.py | 14 ++++-- mayan/apps/events/tests/literals.py | 1 - mayan/apps/events/tests/test_api.py | 44 +++++++++++++++-- mayan/apps/events/urls.py | 48 +++++------------- 5 files changed, 91 insertions(+), 92 deletions(-) diff --git a/mayan/apps/events/api_views.py b/mayan/apps/events/api_views.py index dc7f05d6ea..f2d0b5df40 100644 --- a/mayan/apps/events/api_views.py +++ b/mayan/apps/events/api_views.py @@ -1,17 +1,14 @@ from __future__ import absolute_import, unicode_literals -from django.contrib.contenttypes.models import ContentType -from django.http import Http404 -from django.shortcuts import get_object_or_404 - -from actstream.models import Action, any_stream -from rest_framework import generics, viewsets +from actstream.models import any_stream +from rest_framework import viewsets from rest_framework.response import Response from rest_framework.decorators import action -from mayan.apps.acls.models import AccessControlList +from mayan.apps.common.mixins import ContentTypeViewMixin, ExternalObjectMixin +from mayan.apps.rest_api.viewsets import MayanAPIReadOnlyModelViewSet -from .classes import EventType, EventTypeNamespace +from .classes import EventTypeNamespace from .models import Notification from .permissions import permission_events_view from .serializers import ( @@ -20,7 +17,6 @@ from .serializers import ( ) - class EventTypeNamespaceAPIViewSet(viewsets.ReadOnlyModelViewSet): lookup_field = 'name' lookup_url_kwarg = 'event_type_namespace_name' @@ -64,46 +60,12 @@ class EventTypeAPIViewSet(viewsets.ReadOnlyModelViewSet): return event_types.get(self.kwargs['event_type_id']) - -''' -class APIObjectEventListView(generics.ListAPIView): - """ - get: Return a list of events for the specified object. - """ - serializer_class = EventSerializer - - def get_object(self): - content_type = get_object_or_404( - klass=ContentType, app_label=self.kwargs['app_label'], - model=self.kwargs['model'] - ) - - try: - return content_type.get_object_for_this_type( - pk=self.kwargs['object_id'] - ) - except content_type.model_class().DoesNotExist: - raise Http404 - - def get_queryset(self): - obj = self.get_object() - - AccessControlList.objects.check_access( - permissions=permission_events_view, user=self.request.user, - obj=obj - ) - - return any_stream(obj) - - -class APINotificationListView(generics.ListAPIView): - """ - get: Return a list of notifications for the current user. - """ +class NotificationAPIViewSet(MayanAPIReadOnlyModelViewSet): serializer_class = NotificationSerializer def get_queryset(self): - parameter_read = self.request.GET.get('read') + query_parameter = 'read' + parameter_read = self.request.GET.get(query_parameter) if self.request.user.is_authenticated: queryset = Notification.objects.filter(user=self.request.user) @@ -116,4 +78,24 @@ class APINotificationListView(generics.ListAPIView): queryset = queryset.filter(read=False) return queryset -''' + + +class ObjectEventAPIViewSet(ContentTypeViewMixin, ExternalObjectMixin, MayanAPIReadOnlyModelViewSet): + content_type_url_kw_args = { + 'app_label': 'app_label', + 'model': 'model_name' + } + + external_object_permission = permission_events_view + external_object_pk_url_kwarg = 'object_id' + serializer_class = EventSerializer + + def get_external_object_queryset(self): + # Here we get a queryset the object model for which the event + # will be accessed. + return self.get_content_type().get_all_objects_for_this_type() + + def get_queryset(self): + obj = self.get_external_object() + + return any_stream(obj) diff --git a/mayan/apps/events/links.py b/mayan/apps/events/links.py index e020df2af8..ae938ed894 100644 --- a/mayan/apps/events/links.py +++ b/mayan/apps/events/links.py @@ -31,6 +31,13 @@ def get_kwargs_factory(variable_name): return get_kwargs +def get_unread_notification_count(context): + Notification = apps.get_model( + app_label='events', model_name='Notification' + ) + return Notification.objects.filter(user=context.request.user).filter(read=False).count() + + link_current_user_events = Link( icon_class=icon_events_list, text=_('My events'), view='events:current_user_events' @@ -67,10 +74,7 @@ link_object_event_types_user_subcriptions_list = Link( view='events:object_event_types_user_subcriptions_list', ) link_user_notifications_list = Link( - html_data={ - 'apw-attribute': 'count', 'apw-interval': '5000', - 'apw-url': '/api/notifications/?read=False', - 'apw-callback': 'MayanAppClass.mayanNotificationBadge' - }, icon_class=icon_user_notifications_list, text='', + badge_text=get_unread_notification_count, + icon_class=icon_user_notifications_list, view='events:user_notifications_list' ) diff --git a/mayan/apps/events/tests/literals.py b/mayan/apps/events/tests/literals.py index 7919302efa..ac8a767583 100644 --- a/mayan/apps/events/tests/literals.py +++ b/mayan/apps/events/tests/literals.py @@ -4,4 +4,3 @@ TEST_EVENT_TYPE_NAMESPACE_LABEL = 'test event type namespace label' TEST_EVENT_TYPE_NAMESPACE_NAME = 'test_event_type_namespace_name' TEST_EVENT_TYPE_LABEL = 'test event type label' TEST_EVENT_TYPE_NAME = 'test_event_type_name' - diff --git a/mayan/apps/events/tests/test_api.py b/mayan/apps/events/tests/test_api.py index b285392936..9e8383731b 100644 --- a/mayan/apps/events/tests/test_api.py +++ b/mayan/apps/events/tests/test_api.py @@ -1,7 +1,14 @@ from __future__ import unicode_literals +from django.contrib.contenttypes.models import ContentType + +from rest_framework import status + +from mayan.apps.documents.tests.mixins import DocumentTestMixin from mayan.apps.rest_api.tests import BaseAPITestCase +from ..permissions import permission_events_view + from .mixins import EventTypeTestMixin @@ -12,7 +19,7 @@ class EventTypeNamespaceAPITestCase(EventTypeTestMixin, BaseAPITestCase): def test_event_type_namespace_list_view(self): response = self.get(viewname='rest_api:event_type_namespace-list') - self.assertEqual(response.status_code, 200) + self.assertEqual(response.status_code, status.HTTP_200_OK) def test_event_type_namespace_event_type_list_view(self): response = self.get( @@ -22,7 +29,7 @@ class EventTypeNamespaceAPITestCase(EventTypeTestMixin, BaseAPITestCase): } ) - self.assertEqual(response.status_code, 200) + self.assertEqual(response.status_code, status.HTTP_200_OK) def test_event_type_list_view(self): response = self.get( @@ -32,4 +39,35 @@ class EventTypeNamespaceAPITestCase(EventTypeTestMixin, BaseAPITestCase): 'event_type_id': self.test_event_type.id } ) - self.assertEqual(response.status_code, 200) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + +class DocumentEventAPITestCase(DocumentTestMixin, BaseAPITestCase): + def setUp(self): + super(DocumentEventAPITestCase, self).setUp() + self.test_object = self.test_document + + def _request_object_event_list_api_view(self): + content_type = ContentType.objects.get_for_model( + model=self.test_object + ) + + return self.get( + viewname='rest_api:object-event-list', + kwargs={ + 'app_label': content_type.app_label, + 'model_name': content_type.model, + 'object_id': self.test_object.pk + } + ) + + def test_object_event_list_view_no_permission(self): + response = self._request_object_event_list_api_view() + self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + + def test_object_event_list_view_with_access(self): + self.grant_access( + obj=self.test_object, permission=permission_events_view + ) + response = self._request_object_event_list_api_view() + self.assertEqual(response.status_code, status.HTTP_200_OK) diff --git a/mayan/apps/events/urls.py b/mayan/apps/events/urls.py index 34ddb15824..748f90b00e 100644 --- a/mayan/apps/events/urls.py +++ b/mayan/apps/events/urls.py @@ -2,7 +2,10 @@ from __future__ import unicode_literals from django.conf.urls import url -from .api_views import EventTypeAPIViewSet, EventTypeNamespaceAPIViewSet +from .api_views import ( + EventTypeAPIViewSet, EventTypeNamespaceAPIViewSet, NotificationAPIViewSet, + ObjectEventAPIViewSet +) from .views import ( CurrentUserEventListView, EventListView, EventTypeSubscriptionListView, NotificationListView, NotificationMarkRead, NotificationMarkReadAll, @@ -49,7 +52,6 @@ urlpatterns = [ ) ] - api_router_entries = ( { 'prefix': r'event_type_namespaces', 'viewset': EventTypeNamespaceAPIViewSet, @@ -59,38 +61,12 @@ api_router_entries = ( 'prefix': r'event_type_namespaces/(?P[^/.]+)/event_types', 'viewset': EventTypeAPIViewSet, 'basename': 'event_type' }, - #{'prefix': r'roles', 'viewset': RoleAPIViewSet, 'basename': 'role'}, + { + 'prefix': r'apps/(?P[^/.]+)/models/(?P[^/.]+)/objects/(?P\d+)/events', + 'viewset': ObjectEventAPIViewSet, 'basename': 'object-event' + }, + { + 'prefix': r'notifications', 'viewset': NotificationAPIViewSet, + 'basename': 'notification' + } ) - - -''' -api_urls = [ - url( - regex=r'^event_type_namespaces/(?P[-\w]+)/$', - name='event-type-namespace-detail', - view=APIEventTypeNamespaceDetailView.as_view() - ), - url( - regex=r'^event_type_namespaces/(?P[-\w]+)/event_types/$', - name='event-type-namespace-event-type-list', - view=APIEventTypeNamespaceEventTypeListView.as_view() - ), - url( - regex=r'^event_type_namespaces/$', name='event-type-namespace-list', - view=APIEventTypeNamespaceListView.as_view() - ), - url( - regex=r'^event_types/$', name='event-type-list', - view=APIEventTypeListView.as_view() - ), - url(regex=r'^events/$', name='event-list', view=APIEventListView.as_view()), - url( - regex=r'^notifications/$', name='notification-list', - view=APINotificationListView.as_view() - ), - url( - regex=r'^objects/(?P[-\w]+)/(?P[-\w]+)/(?P\d+)/events/$', - name='object-event-list', view=APIObjectEventListView.as_view() - ) -] -'''