diff --git a/mayan/apps/document_comments/api_views.py b/mayan/apps/document_comments/api_views.py index 04ea5b0897..b7aaa195a2 100644 --- a/mayan/apps/document_comments/api_views.py +++ b/mayan/apps/document_comments/api_views.py @@ -1,10 +1,8 @@ from __future__ import absolute_import, unicode_literals -from django.shortcuts import get_object_or_404 - from rest_framework import generics -from mayan.apps.acls.models import AccessControlList +from mayan.apps.common.mixins import ExternalObjectViewMixin from mayan.apps.documents.models import Document from .permissions import ( @@ -14,27 +12,22 @@ from .permissions import ( from .serializers import CommentSerializer, WritableCommentSerializer -class APICommentListView(generics.ListCreateAPIView): +class APICommentListView(ExternalObjectViewMixin, generics.ListCreateAPIView): """ get: Returns a list of all the document comments. post: Create a new document comment. """ + external_object_pk_url_kwarg = 'document_pk' + external_object_class = Document + def get_document(self): + return self.get_external_object() + + def get_external_object_permission(self): if self.request.method == 'GET': - permission_required = permission_comment_view + return permission_comment_view else: - permission_required = permission_comment_create - - document = get_object_or_404( - klass=Document, pk=self.kwargs['document_pk'] - ) - - AccessControlList.objects.check_access( - permissions=permission_required, user=self.request.user, - obj=document - ) - - return document + return permission_comment_create def get_queryset(self): return self.get_document().comments.all() @@ -66,30 +59,24 @@ class APICommentListView(generics.ListCreateAPIView): return context -class APICommentView(generics.RetrieveDestroyAPIView): +class APICommentView(ExternalObjectViewMixin, generics.RetrieveDestroyAPIView): """ delete: Delete the selected document comment. get: Returns the details of the selected document comment. """ + external_object_pk_url_kwarg = 'document_pk' + external_object_class = Document lookup_url_kwarg = 'comment_pk' serializer_class = CommentSerializer def get_document(self): + return self.get_external_object() + + def get_external_object_permission(self): if self.request.method == 'GET': - permission_required = permission_comment_view + return permission_comment_view else: - permission_required = permission_comment_delete - - document = get_object_or_404( - klass=Document, pk=self.kwargs['document_pk'] - ) - - AccessControlList.objects.check_access( - permissions=permission_required, user=self.request.user, - obj=document - ) - - return document + return permission_comment_delete def get_queryset(self): return self.get_document().comments.all() diff --git a/mayan/apps/document_comments/apps.py b/mayan/apps/document_comments/apps.py index 866f78678a..df27c74dd1 100644 --- a/mayan/apps/document_comments/apps.py +++ b/mayan/apps/document_comments/apps.py @@ -12,7 +12,7 @@ from mayan.apps.events import ModelEventType from mayan.apps.navigation import SourceColumn from .events import ( - event_document_comment_create, event_document_comment_delete + event_document_comment_created, event_document_comment_deleted ) from .links import ( link_comment_add, link_comment_delete, link_comments_for_document @@ -32,6 +32,7 @@ class DocumentCommentsApp(MayanAppConfig): verbose_name = _('Document comments') def ready(self): + from actstream import registry super(DocumentCommentsApp, self).ready() Document = apps.get_model( @@ -42,7 +43,7 @@ class DocumentCommentsApp(MayanAppConfig): ModelEventType.register( model=Document, event_types=( - event_document_comment_create, event_document_comment_delete + event_document_comment_created, event_document_comment_deleted ) ) @@ -86,3 +87,5 @@ class DocumentCommentsApp(MayanAppConfig): menu_facet.bind_links( links=(link_comments_for_document,), sources=(Document,) ) + + registry.register(Comment) diff --git a/mayan/apps/document_comments/events.py b/mayan/apps/document_comments/events.py index 66cd211e5b..ba34f362e9 100644 --- a/mayan/apps/document_comments/events.py +++ b/mayan/apps/document_comments/events.py @@ -8,9 +8,9 @@ namespace = EventTypeNamespace( name='document_comments', label=_('Document comments') ) -event_document_comment_create = namespace.add_event_type( +event_document_comment_created = namespace.add_event_type( name='create', label=_('Document comment created') ) -event_document_comment_delete = namespace.add_event_type( +event_document_comment_deleted = namespace.add_event_type( name='delete', label=_('Document comment deleted') ) diff --git a/mayan/apps/document_comments/models.py b/mayan/apps/document_comments/models.py index 94bde4e8d5..b9706ecfb3 100644 --- a/mayan/apps/document_comments/models.py +++ b/mayan/apps/document_comments/models.py @@ -10,7 +10,7 @@ from django.utils.translation import ugettext_lazy as _ from mayan.apps.documents.models import Document from .events import ( - event_document_comment_create, event_document_comment_delete + event_document_comment_created, event_document_comment_deleted ) logger = logging.getLogger(__name__) @@ -49,11 +49,11 @@ class Comment(models.Model): user = kwargs.pop('_user', None) super(Comment, self).delete(*args, **kwargs) if user: - event_document_comment_delete.commit( + event_document_comment_deleted.commit( actor=user, target=self.document ) else: - event_document_comment_delete.commit(target=self.document) + event_document_comment_deleted.commit(target=self.document) def save(self, *args, **kwargs): user = kwargs.pop('_user', None) or self.user @@ -61,15 +61,15 @@ class Comment(models.Model): super(Comment, self).save(*args, **kwargs) if is_new: if user: - event_document_comment_create.commit( - actor=user, target=self.document + event_document_comment_created.commit( + actor=user, action_object=self.document, target=self ) logger.info( 'Comment "%s" added to document "%s" by user "%s"', self.comment, self.document, user ) else: - event_document_comment_create.commit(target=self.document) + event_document_comment_created.commit(target=self.document) logger.info( 'Comment "%s" added to document "%s"', self.comment, self.document diff --git a/mayan/apps/document_comments/tests/mixins.py b/mayan/apps/document_comments/tests/mixins.py new file mode 100644 index 0000000000..906c32bee1 --- /dev/null +++ b/mayan/apps/document_comments/tests/mixins.py @@ -0,0 +1,31 @@ +from __future__ import unicode_literals + +from ..models import Comment + +from .literals import TEST_COMMENT_TEXT + + +class CommentsTestMixin(object): + def _create_comment(self, user=None): + self.test_comment = self.document.comments.create( + comment=TEST_COMMENT_TEXT, + user=user or self.user or self.admin_user + ) + + def _request_document_comment_add_view(self): + response = self.post( + viewname='comments:comment_add', + kwargs={'document_pk': self.document.pk}, + data={'comment': TEST_COMMENT_TEXT} + ) + self.test_comment = Comment.objects.filter( + document=self.document.pk + ).first() + + return response + + def _request_document_comment_delete_view(self): + return self.post( + viewname='comments:comment_delete', + kwargs={'comment_pk': self.test_comment.pk}, + ) diff --git a/mayan/apps/document_comments/tests/test_api.py b/mayan/apps/document_comments/tests/test_api.py index 7a50638160..dc898249a7 100644 --- a/mayan/apps/document_comments/tests/test_api.py +++ b/mayan/apps/document_comments/tests/test_api.py @@ -12,102 +12,98 @@ from ..permissions import ( ) from .literals import TEST_COMMENT_TEXT +from .mixins import CommentsTestMixin -class CommentAPITestCase(DocumentTestMixin, BaseAPITestCase): +class CommentAPITestCase(CommentsTestMixin, DocumentTestMixin, BaseAPITestCase): def setUp(self): super(CommentAPITestCase, self).setUp() self.login_user() - def _create_comment(self): - return self.document.comments.create( - comment=TEST_COMMENT_TEXT, user=self.admin_user - ) - - def _request_comment_create_view(self): + def _request_api_comment_create_view(self): return self.post( - viewname='rest_api:comment-list', kwargs={'document_pk': self.document.pk}, - data={ + viewname='rest_api:comment-list', + kwargs={'document_pk': self.document.pk}, data={ 'comment': TEST_COMMENT_TEXT } ) def test_comment_create_view_no_access(self): - response = self._request_comment_create_view() - self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + response = self._request_api_comment_create_view() + self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) self.assertEqual(Comment.objects.count(), 0) def test_comment_create_view_with_access(self): self.grant_access(permission=permission_comment_create, obj=self.document) - response = self._request_comment_create_view() + response = self._request_api_comment_create_view() self.assertEqual(response.status_code, status.HTTP_201_CREATED) comment = Comment.objects.first() self.assertEqual(Comment.objects.count(), 1) self.assertEqual(response.data['id'], comment.pk) - def _request_comment_delete_view(self): + def _request_api_comment_delete_view(self): return self.delete( viewname='rest_api:comment-detail', kwargs={ 'document_pk': self.document.pk, - 'comment_pk': self.comment.pk + 'comment_pk': self.test_comment.pk } ) def test_comment_delete_view_no_access(self): - self.comment = self._create_comment() - response = self._request_comment_delete_view() - self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) - self.assertTrue(self.comment in Comment.objects.all()) + self._create_comment() + response = self._request_api_comment_delete_view() + self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + self.assertTrue(self.test_comment in Comment.objects.all()) def test_comment_delete_view_with_access(self): - self.comment = self._create_comment() + self._create_comment() self.grant_access( permission=permission_comment_delete, obj=self.document ) - response = self._request_comment_delete_view() + response = self._request_api_comment_delete_view() self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) - self.assertFalse(self.comment in Comment.objects.all()) + self.assertFalse(self.test_comment in Comment.objects.all()) - def _request_comment_view(self): + def _request_api_comment_detail_view(self): return self.get( viewname='rest_api:comment-detail', kwargs={ 'document_pk': self.document.pk, - 'comment_pk': self.comment.pk + 'comment_pk': self.test_comment.pk } ) def test_comment_detail_view_no_access(self): - self.comment = self._create_comment() - response = self._request_comment_view() - self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + self._create_comment() + response = self._request_api_comment_detail_view() + self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_comment_detail_view_with_access(self): - self.comment = self._create_comment() + self._create_comment() self.grant_access( permission=permission_comment_view, obj=self.document ) - response = self._request_comment_view() + response = self._request_api_comment_detail_view() self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response.data['comment'], self.comment.comment) + self.assertEqual(response.data['comment'], self.test_comment.comment) - def _request_comment_list_view(self): + def _request_api_comment_list_view(self): return self.get( viewname='rest_api:comment-list', kwargs={'document_pk': self.document.pk} ) def test_comment_list_view_no_access(self): - self.comment = self._create_comment() - response = self._request_comment_list_view() - self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + self._create_comment() + response = self._request_api_comment_list_view() + self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) def test_comment_list_view_with_access(self): - self.comment = self._create_comment() + self._create_comment() self.grant_access( permission=permission_comment_view, obj=self.document ) - response = self._request_comment_list_view() + response = self._request_api_comment_list_view() self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual( - response.data['results'][0]['comment'], self.comment.comment + response.data['results'][0]['comment'], self.test_comment.comment ) diff --git a/mayan/apps/document_comments/tests/test_events.py b/mayan/apps/document_comments/tests/test_events.py new file mode 100644 index 0000000000..8618baf8aa --- /dev/null +++ b/mayan/apps/document_comments/tests/test_events.py @@ -0,0 +1,65 @@ +from __future__ import unicode_literals + +from actstream.models import Action + +from mayan.apps.documents.tests import GenericDocumentViewTestCase + +from ..events import ( + event_document_comment_created, event_document_comment_deleted +) +from ..permissions import permission_comment_create, permission_comment_delete + +from .mixins import CommentsTestMixin + + +class CommentEventsTestCase(CommentsTestMixin, GenericDocumentViewTestCase): + def setUp(self): + super(CommentEventsTestCase, self).setUp() + self.login_user() + + def test_comment_created_event_no_permissions(self): + Action.objects.all().delete() + + response = self._request_document_comment_add_view() + self.assertEqual(response.status_code, 404) + self.assertEqual(Action.objects.count(), 0) + + def test_comment_created_event_with_permissions(self): + Action.objects.all().delete() + + self.grant_access( + obj=self.document, permission=permission_comment_create + ) + response = self._request_document_comment_add_view() + self.assertEqual(response.status_code, 302) + + event = Action.objects.first() + + self.assertEqual(event.verb, event_document_comment_created.id) + self.assertEqual(event.action_object, self.document) + self.assertEqual(event.target, self.test_comment) + self.assertEqual(event.actor, self.user) + + def test_comment_deleted_event_no_permissions(self): + self._create_comment() + Action.objects.all().delete() + + response = self._request_document_comment_delete_view() + self.assertEqual(response.status_code, 404) + self.assertEqual(Action.objects.count(), 0) + + def test_comment_deleted_event_with_access(self): + self._create_comment() + Action.objects.all().delete() + + self.grant_access( + obj=self.document, permission=permission_comment_delete + ) + + response = self._request_document_comment_delete_view() + self.assertEqual(response.status_code, 302) + event = Action.objects.first() + + self.assertEqual(event.verb, event_document_comment_deleted.id) + self.assertEqual(event.target, self.document) + self.assertEqual(event.actor, self.user) diff --git a/mayan/apps/document_comments/tests/test_views.py b/mayan/apps/document_comments/tests/test_views.py index f729d0b226..59b0882ca1 100644 --- a/mayan/apps/document_comments/tests/test_views.py +++ b/mayan/apps/document_comments/tests/test_views.py @@ -8,20 +8,14 @@ from ..permissions import ( ) from .literals import TEST_COMMENT_TEXT +from .mixins import CommentsTestMixin -class CommentsViewsTestCase(GenericDocumentViewTestCase): +class CommentsViewsTestCase(CommentsTestMixin, GenericDocumentViewTestCase): def setUp(self): super(CommentsViewsTestCase, self).setUp() self.login_user() - def _request_document_comment_add_view(self): - return self.post( - viewname='comments:comment_add', - kwargs={'document_pk': self.document.pk}, - data={'comment': TEST_COMMENT_TEXT} - ) - def test_document_comment_add_view_no_permission(self): response = self._request_document_comment_add_view() self.assertEqual(response.status_code, 404) @@ -40,12 +34,6 @@ class CommentsViewsTestCase(GenericDocumentViewTestCase): user=self.user, comment=TEST_COMMENT_TEXT ) - def _request_document_comment_delete_view(self): - return self.post( - viewname='comments:comment_delete', - kwargs={'comment_pk': self.test_comment.pk}, - ) - def test_document_comment_delete_view_no_permission(self): self._create_test_comment()