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() - ) -] -'''