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:
@@ -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,
|
||||
|
||||
@@ -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'
|
||||
)
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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()))
|
||||
|
||||
@@ -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'
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
]
|
||||
|
||||
@@ -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())
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user