diff --git a/mayan/apps/events/apps.py b/mayan/apps/events/apps.py index b063e6b35e..a320a2b454 100644 --- a/mayan/apps/events/apps.py +++ b/mayan/apps/events/apps.py @@ -16,9 +16,7 @@ from .links import ( link_events_list, link_notification_mark_read, link_notification_mark_read_all, link_user_notifications_list ) -from .widgets import ( - widget_event_actor_link, widget_event_type_link -) +from .widgets import widget_event_actor_link, widget_event_type_link class EventsApp(MayanAppConfig): @@ -56,10 +54,10 @@ class EventsApp(MayanAppConfig): ) SourceColumn( - source=StoredEventType, label=_('Namespace'), attribute='namespace' + attribute='namespace', label=_('Namespace'), source=StoredEventType ) SourceColumn( - source=StoredEventType, label=_('Label'), attribute='label' + attribute='label', label=_('Label'), source=StoredEventType ) SourceColumn( @@ -67,12 +65,12 @@ class EventsApp(MayanAppConfig): is_sortable=True, label=_('Date and time'), source=Notification ) SourceColumn( - func=widget_event_actor_link, kwargs={'attribute': 'action'}, - label=_('Actor'), source=Notification + func=widget_event_actor_link, label=_('Actor'), + kwargs={'attribute': 'action'}, source=Notification ) SourceColumn( - func=widget_event_type_link, kwargs={'attribute': 'action'}, - label=_('Event'), source=Notification + func=widget_event_type_link, label=_('Event'), + kwargs={'attribute': 'action'}, source=Notification ) SourceColumn( attribute='action.target', label=_('Target'), source=Notification, diff --git a/mayan/apps/events/icons.py b/mayan/apps/events/icons.py index bbbc1bde38..5473c4508e 100644 --- a/mayan/apps/events/icons.py +++ b/mayan/apps/events/icons.py @@ -5,8 +5,8 @@ from mayan.apps.appearance.classes import Icon icon_event_types_subscriptions_list = Icon( driver_name='fontawesome', symbol='rss' ) -icon_events_list = Icon(driver_name='fontawesome', symbol='list-ol') icon_events_for_object = Icon(driver_name='fontawesome', symbol='list-ol') +icon_events_list = Icon(driver_name='fontawesome', symbol='list-ol') icon_object_event_types_user_subcriptions_list = Icon( driver_name='fontawesome', symbol='rss' ) diff --git a/mayan/apps/events/links.py b/mayan/apps/events/links.py index 6854bd3277..0a2b8c6fd5 100644 --- a/mayan/apps/events/links.py +++ b/mayan/apps/events/links.py @@ -20,7 +20,7 @@ def get_kwargs_factory(variable_name): ) content_type = ContentType.objects.get_for_model( - context[variable_name] + model=context[variable_name] ) return { 'app_label': '"{}"'.format(content_type.app_label), @@ -54,7 +54,7 @@ link_event_types_subscriptions_list = Link( view='events:event_types_user_subcriptions_list' ) link_notification_mark_read = Link( - args='object.pk', text=_('Mark as seen'), + kwargs={'notification_id': 'object.pk'}, text=_('Mark as seen'), view='events:notification_mark_read' ) link_notification_mark_read_all = Link( diff --git a/mayan/apps/events/migrations/0005_auto_20170731_0452.py b/mayan/apps/events/migrations/0005_auto_20170731_0452.py index 7626b31cda..9305e8d69e 100644 --- a/mayan/apps/events/migrations/0005_auto_20170731_0452.py +++ b/mayan/apps/events/migrations/0005_auto_20170731_0452.py @@ -38,12 +38,12 @@ def operation_revert_event_types_names(apps, schema_editor): StoredEventType = apps.get_model('events', 'StoredEventType') known_namespaces = { - 'documents\.': 'documents_', - 'checkouts\.': 'checkouts_', - 'document_comments\.': 'document_comment_', - 'document_parsing\.': 'parsing_document_', - 'ocr\.': 'ocr_', - 'tags\.': 'tag_', + r'documents\.': 'documents_', + r'checkouts\.': 'checkouts_', + r'document_comments\.': 'document_comment_', + r'document_parsing\.': 'parsing_document_', + r'ocr\.': 'ocr_', + r'tags\.': 'tag_', } pattern = re.compile('|'.join(known_namespaces.keys())) diff --git a/mayan/apps/events/permissions.py b/mayan/apps/events/permissions.py index dc04070ce0..50e001f65e 100644 --- a/mayan/apps/events/permissions.py +++ b/mayan/apps/events/permissions.py @@ -6,5 +6,5 @@ from mayan.apps.permissions import PermissionNamespace namespace = PermissionNamespace(label=_('Events'), name='events') permission_events_view = namespace.add_permission( - name='events_view', label=_('Access the events of an object') + label=_('Access the events of an object'), name='events_view' ) diff --git a/mayan/apps/events/tests/test_api.py b/mayan/apps/events/tests/test_api.py index b11e6e85e0..d0ffffd967 100644 --- a/mayan/apps/events/tests/test_api.py +++ b/mayan/apps/events/tests/test_api.py @@ -7,5 +7,5 @@ from mayan.apps.rest_api.tests import BaseAPITestCase class EventAPITestCase(BaseAPITestCase): def test_evet_type_list_view(self): - response = self.client.get(reverse('rest_api:event-type-list')) + response = self.client.get(reverse(viewname='rest_api:event-type-list')) self.assertEqual(response.status_code, 200) diff --git a/mayan/apps/events/tests/test_views.py b/mayan/apps/events/tests/test_views.py index c7bad2f229..c830ff202e 100644 --- a/mayan/apps/events/tests/test_views.py +++ b/mayan/apps/events/tests/test_views.py @@ -10,59 +10,33 @@ from ..permissions import permission_events_view class EventsViewTestCase(GenericDocumentViewTestCase): def setUp(self): super(EventsViewTestCase, self).setUp() + self.test_object = self.document - content_type = ContentType.objects.get_for_model(self.document) + content_type = ContentType.objects.get_for_model(model=self.test_object) self.view_arguments = { 'app_label': content_type.app_label, 'model': content_type.model, - 'object_id': self.document.pk + 'object_id': self.test_object.pk } + def _request_events_for_object_view(self): + return self.get( + viewname='events:events_for_object', kwargs=self.view_arguments + ) + def test_events_for_object_view_no_permission(self): - self.login_user() - - document = self.document.add_as_recent_document_for_user( - self.user - ).document - - content_type = ContentType.objects.get_for_model(document) - - view_arguments = { - 'app_label': content_type.app_label, - 'model': content_type.model, - 'object_id': document.pk - } - - response = self.get( - viewname='events:events_for_object', kwargs=view_arguments + response = self._request_events_for_object_view() + self.assertNotContains( + response=response, text=self.test_object.label, status_code=404 ) - self.assertNotContains(response, text=document.label, status_code=403) - self.assertNotContains(response, text='otal:', status_code=403) - - def test_events_for_object_view_with_permission(self): - self.login_user() - - self.role.permissions.add( - permission_events_view.stored_permission + def test_events_for_object_view_with_access(self): + self.grant_access( + obj=self.test_object, permission=permission_events_view ) - document = self.document.add_as_recent_document_for_user( - self.user - ).document - - content_type = ContentType.objects.get_for_model(document) - - view_arguments = { - 'app_label': content_type.app_label, - 'model': content_type.model, - 'object_id': document.pk - } - - response = self.get( - viewname='events:events_for_object', kwargs=view_arguments + response = self._request_events_for_object_view() + self.assertContains( + response=response, text=self.test_object.label, status_code=200 ) - - self.assertContains(response, text=document.label, status_code=200) - self.assertNotContains(response, text='otal: 0', status_code=200) diff --git a/mayan/apps/events/urls.py b/mayan/apps/events/urls.py index e60cb1cc71..f93a84eaac 100644 --- a/mayan/apps/events/urls.py +++ b/mayan/apps/events/urls.py @@ -15,69 +15,70 @@ from .views import ( ) urlpatterns = [ - url(r'^all/$', EventListView.as_view(), name='events_list'), + url(regex=r'^events/$', name='events_list', view=EventListView.as_view()), url( - r'^for/(?P[-\w]+)/(?P[-\w]+)/(?P\d+)/$', - ObjectEventListView.as_view(), name='events_for_object' + regex=r'^events/by_verb/(?P[\w\-\.]+)/$', name='events_by_verb', + view=VerbEventListView.as_view() ), url( - r'^by_verb/(?P[\w\-\.]+)/$', VerbEventListView.as_view(), - name='events_by_verb' + regex=r'^objects/(?P[-\w]+)/(?P[-\w]+)/(?P\d+)/events/$', + name='events_for_object', view=ObjectEventListView.as_view() ), url( - r'^notifications/(?P\d+)/mark_read/$', - NotificationMarkRead.as_view(), name='notification_mark_read' + regex=r'^user/events/$', name='current_user_events', + view=CurrentUserEventListView.as_view() ), url( - r'^notifications/all/mark_read/$', - NotificationMarkReadAll.as_view(), name='notification_mark_read_all' + regex=r'^user/event_types/subscriptions/$', + name='event_types_user_subcriptions_list', + view=EventTypeSubscriptionListView.as_view() ), url( - r'^user/(?P[-\w]+)/(?P[-\w]+)/(?P\d+)/subscriptions/$', - ObjectEventTypeSubscriptionListView.as_view(), - name='object_event_types_user_subcriptions_list' + regex=r'^user/notifications/$', name='user_notifications_list', + view=NotificationListView.as_view() ), url( - r'^user/$', CurrentUserEventListView.as_view(), - name='current_user_events' + regex=r'^user/notifications/(?P\d+)/mark_read/$', + name='notification_mark_read', view=NotificationMarkRead.as_view() ), url( - r'^user/event_types/subscriptions/$', - EventTypeSubscriptionListView.as_view(), - name='event_types_user_subcriptions_list' + regex=r'^user/notifications/all/mark_read/$', + name='notification_mark_read_all', + view=NotificationMarkReadAll.as_view() ), url( - r'^user/notifications/$', NotificationListView.as_view(), - name='user_notifications_list' - ), + regex=r'^user/subscriptions/for/(?P[-\w]+)/(?P[-\w]+)/(?P\d+)/$', + name='object_event_types_user_subcriptions_list', + view=ObjectEventTypeSubscriptionListView.as_view() + ) ] api_urls = [ url( - r'^event_type_namespaces/(?P[-\w]+)/$', - APIEventTypeNamespaceDetailView.as_view(), - name='event-type-namespace-detail' + regex=r'^event_type_namespaces/(?P[-\w]+)/$', + name='event-type-namespace-detail', + view=APIEventTypeNamespaceDetailView.as_view() ), url( - r'^event_type_namespaces/(?P[-\w]+)/event_types/$', - APIEventTypeNamespaceEventTypeListView.as_view(), - name='event-type-namespace-event-type-list' + regex=r'^event_type_namespaces/(?P[-\w]+)/event_types/$', + name='event-type-namespace-event-type-list', + view=APIEventTypeNamespaceEventTypeListView.as_view() ), url( - r'^event_type_namespaces/$', APIEventTypeNamespaceListView.as_view(), - name='event-type-namespace-list' + regex=r'^event_type_namespaces/$', name='event-type-namespace-list', + view=APIEventTypeNamespaceListView.as_view() ), url( - r'^event_types/$', APIEventTypeListView.as_view(), - name='event-type-list' + regex=r'^event_types/$', name='event-type-list', + view=APIEventTypeListView.as_view() ), - url(r'^events/$', APIEventListView.as_view(), name='event-list'), + url(regex=r'^events/$', name='event-list', view=APIEventListView.as_view()), url( - r'^notifications/$', APINotificationListView.as_view(), - name='notification-list' + regex=r'^notifications/$', name='notification-list', + view=APINotificationListView.as_view() ), url( - r'^objects/(?P[-\w]+)/(?P[-\w]+)/(?P\d+)/events/$', - APIObjectEventListView.as_view(), name='object-event-list' - ), + regex=r'^objects/(?P[-\w]+)/(?P[-\w]+)/(?P\d+)/events/$', + name='object-event-list', view=APIObjectEventListView.as_view() + ) ] diff --git a/mayan/apps/events/views.py b/mayan/apps/events/views.py index 8b42157733..49603b33bb 100644 --- a/mayan/apps/events/views.py +++ b/mayan/apps/events/views.py @@ -2,7 +2,7 @@ from __future__ import absolute_import, unicode_literals from django.contrib import messages from django.contrib.contenttypes.models import ContentType -from django.http import Http404, HttpResponseRedirect +from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404 from django.template import RequestContext from django.urls import reverse @@ -18,9 +18,7 @@ from .classes import EventType, ModelEventType from .forms import ( EventTypeUserRelationshipFormSet, ObjectEventTypeUserRelationshipFormSet ) -from .icons import ( - icon_events_list, icon_user_notifications_list -) +from .icons import icon_events_list, icon_user_notifications_list from .links import link_event_types_subscriptions_list from .models import StoredEventType from .permissions import permission_events_view @@ -46,7 +44,9 @@ class EventTypeSubscriptionListView(FormView): def dispatch(self, *args, **kwargs): EventType.refresh() - return super(EventTypeSubscriptionListView, self).dispatch(*args, **kwargs) + return super( + EventTypeSubscriptionListView, self + ).dispatch(*args, **kwargs) def form_valid(self, form): try: @@ -54,21 +54,19 @@ class EventTypeSubscriptionListView(FormView): instance.save() except Exception as exception: messages.error( - self.request, - _('Error updating event subscription; %s') % exception + message=_('Error updating event subscription; %s') % exception, + request=self.request ) else: messages.success( - self.request, _('Event subscriptions updated successfully') + message=_('Event subscriptions updated successfully'), + request=self.request ) return super( EventTypeSubscriptionListView, self ).form_valid(form=form) - def get_object(self): - return self.request.user - def get_extra_context(self): return { 'form_display_mode_table': True, @@ -83,20 +81,25 @@ class EventTypeSubscriptionListView(FormView): initial = [] for element in self.get_queryset(): - initial.append({ - 'user': obj, - 'main_model': self.main_model, - 'stored_event_type': element, - }) + initial.append( + { + 'user': obj, + 'main_model': self.main_model, + 'stored_event_type': element, + } + ) return initial + def get_object(self): + return self.request.user + def get_queryset(self): # Return the queryset by name from the sorted list of the class event_type_ids = [event_type.id for event_type in EventType.all()] return self.submodel.objects.filter(name__in=event_type_ids) def get_post_action_redirect(self): - return reverse('common:current_user_details') + return reverse(viewname='common:current_user_details') class NotificationListView(SingleObjectListView): @@ -124,8 +127,12 @@ class NotificationListView(SingleObjectListView): class NotificationMarkRead(SimpleView): def dispatch(self, *args, **kwargs): - self.get_queryset().filter(pk=self.kwargs['pk']).update(read=True) - return HttpResponseRedirect(reverse('events:user_notifications_list')) + self.get_queryset().filter( + pk=self.kwargs['notification_id'] + ).update(read=True) + return HttpResponseRedirect( + redirect_to=reverse(viewname='events:user_notifications_list') + ) def get_queryset(self): return self.request.user.notifications.all() @@ -134,24 +141,16 @@ class NotificationMarkRead(SimpleView): class NotificationMarkReadAll(SimpleView): def dispatch(self, *args, **kwargs): self.get_queryset().update(read=True) - return HttpResponseRedirect(reverse('events:user_notifications_list')) + return HttpResponseRedirect( + redirect_to=reverse(viewname='events:user_notifications_list') + ) def get_queryset(self): return self.request.user.notifications.all() class ObjectEventListView(EventListView): - view_permissions = None - - def _get_object(self): - content_type = get_object_or_404( - klass=ContentType, app_label=self.kwargs['app_label'], - model=self.kwargs['model'] - ) - - return get_object_or_404( - klass=content_type.model_class(), pk=self.kwargs['object_id'] - ) + view_permission = None def get_extra_context(self): context = super(ObjectEventListView, self).get_extra_context() @@ -171,12 +170,19 @@ class ObjectEventListView(EventListView): return context def get_object(self): - obj = self._get_object() - AccessControlList.objects.check_access( - permissions=permission_events_view, user=self.request.user, - obj=obj + content_type = get_object_or_404( + klass=ContentType, app_label=self.kwargs['app_label'], + model=self.kwargs['model'] + ) + + queryset = AccessControlList.objects.restrict_queryset( + permission=permission_events_view, + queryset=content_type.model_class().objects.all(), + user=self.request.user + ) + return get_object_or_404( + klass=queryset, pk=self.kwargs['object_id'] ) - return obj def get_object_list(self): return any_stream(self.get_object()) @@ -197,40 +203,21 @@ class ObjectEventTypeSubscriptionListView(FormView): instance.save() except Exception as exception: messages.error( - self.request, - _('Error updating object event subscription; %s') % exception + message=_( + 'Error updating object event subscription; %s' + ) % exception, request=self.request ) else: messages.success( - self.request, _( + message=_( 'Object event subscriptions updated successfully.' - ) + ), request=self.request ) return super( ObjectEventTypeSubscriptionListView, self ).form_valid(form=form) - def get_object(self): - object_content_type = get_object_or_404( - klass=ContentType, app_label=self.kwargs['app_label'], - model=self.kwargs['model'] - ) - - try: - content_object = object_content_type.get_object_for_this_type( - pk=self.kwargs['object_id'] - ) - except object_content_type.model_class().DoesNotExist: - raise Http404 - - AccessControlList.objects.check_access( - permissions=permission_events_view, user=self.request.user, - obj=content_object - ) - - return content_object - def get_extra_context(self): return { 'form_display_mode_table': True, @@ -245,13 +232,30 @@ class ObjectEventTypeSubscriptionListView(FormView): initial = [] for element in self.get_queryset(): - initial.append({ - 'user': self.request.user, - 'object': obj, - 'stored_event_type': element, - }) + initial.append( + { + 'user': self.request.user, + 'object': obj, + 'stored_event_type': element, + } + ) return initial + def get_object(self): + content_type = get_object_or_404( + klass=ContentType, app_label=self.kwargs['app_label'], + model=self.kwargs['model'] + ) + + queryset = AccessControlList.objects.restrict_queryset( + permission=permission_events_view, + queryset=content_type.model_class().objects.all(), + user=self.request.user + ) + return get_object_or_404( + klass=queryset, pk=self.kwargs['object_id'] + ) + def get_queryset(self): return ModelEventType.get_for_instance(instance=self.get_object()) diff --git a/mayan/apps/events/widgets.py b/mayan/apps/events/widgets.py index 2acacdfd37..5b3d75a9fa 100644 --- a/mayan/apps/events/widgets.py +++ b/mayan/apps/events/widgets.py @@ -49,7 +49,7 @@ def widget_event_type_link(context, attribute=None): return mark_safe( '%(label)s' % { - 'url': reverse('events:events_by_verb', kwargs={'verb': entry.verb}), + 'url': reverse(viewname='events:events_by_verb', kwargs={'verb': entry.verb}), 'label': EventType.get(name=entry.verb) } )