Update events app

Add keyword arguments. Update URLs for uniformity.
Update URL parameters to the '_id' form. Update
views to remove use of .check_access(). Fix escape
sequence warning in migration 0005.

Signed-off-by: Roberto Rosario <Roberto.Rosario@mayan-edms.com>
This commit is contained in:
Roberto Rosario
2019-01-21 02:35:00 -04:00
parent 2e5d05403a
commit 027a853885
10 changed files with 142 additions and 165 deletions

View File

@@ -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,

View File

@@ -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'
)

View File

@@ -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(

View File

@@ -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()))

View File

@@ -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'
)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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<app_label>[-\w]+)/(?P<model>[-\w]+)/(?P<object_id>\d+)/$',
ObjectEventListView.as_view(), name='events_for_object'
regex=r'^events/by_verb/(?P<verb>[\w\-\.]+)/$', name='events_by_verb',
view=VerbEventListView.as_view()
),
url(
r'^by_verb/(?P<verb>[\w\-\.]+)/$', VerbEventListView.as_view(),
name='events_by_verb'
regex=r'^objects/(?P<app_label>[-\w]+)/(?P<model>[-\w]+)/(?P<object_id>\d+)/events/$',
name='events_for_object', view=ObjectEventListView.as_view()
),
url(
r'^notifications/(?P<pk>\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<app_label>[-\w]+)/(?P<model>[-\w]+)/(?P<object_id>\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<notification_id>\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<app_label>[-\w]+)/(?P<model>[-\w]+)/(?P<object_id>\d+)/$',
name='object_event_types_user_subcriptions_list',
view=ObjectEventTypeSubscriptionListView.as_view()
)
]
api_urls = [
url(
r'^event_type_namespaces/(?P<name>[-\w]+)/$',
APIEventTypeNamespaceDetailView.as_view(),
name='event-type-namespace-detail'
regex=r'^event_type_namespaces/(?P<name>[-\w]+)/$',
name='event-type-namespace-detail',
view=APIEventTypeNamespaceDetailView.as_view()
),
url(
r'^event_type_namespaces/(?P<name>[-\w]+)/event_types/$',
APIEventTypeNamespaceEventTypeListView.as_view(),
name='event-type-namespace-event-type-list'
regex=r'^event_type_namespaces/(?P<name>[-\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<app_label>[-\w]+)/(?P<model>[-\w]+)/(?P<object_id>\d+)/events/$',
APIObjectEventListView.as_view(), name='object-event-list'
),
regex=r'^objects/(?P<app_label>[-\w]+)/(?P<model>[-\w]+)/(?P<object_id>\d+)/events/$',
name='object-event-list', view=APIObjectEventListView.as_view()
)
]

View File

@@ -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())

View File

@@ -49,7 +49,7 @@ def widget_event_type_link(context, attribute=None):
return mark_safe(
'<a href="%(url)s">%(label)s</a>' % {
'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)
}
)