Require view permissions for tag and document
Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
This commit is contained in:
@@ -247,6 +247,8 @@
|
|||||||
* Move the user set password views to the authentication app.
|
* Move the user set password views to the authentication app.
|
||||||
* All views redirect to common's home view instead of the
|
* All views redirect to common's home view instead of the
|
||||||
REDIRECT_URL setting.
|
REDIRECT_URL setting.
|
||||||
|
* Update tag document list and the document tag list
|
||||||
|
views to require the view permissions for both objects.
|
||||||
|
|
||||||
3.1.11 (2019-04-XX)
|
3.1.11 (2019-04-XX)
|
||||||
===================
|
===================
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -68,9 +68,7 @@ class TagsApp(MayanAppConfig):
|
|||||||
DocumentTag = self.get_model(model_name='DocumentTag')
|
DocumentTag = self.get_model(model_name='DocumentTag')
|
||||||
Tag = self.get_model(model_name='Tag')
|
Tag = self.get_model(model_name='Tag')
|
||||||
|
|
||||||
Document.add_to_class(
|
Document.add_to_class(name='get_tags', value=method_document_get_tags)
|
||||||
name='attached_tags', value=method_document_get_tags
|
|
||||||
)
|
|
||||||
|
|
||||||
ModelEventType.register(
|
ModelEventType.register(
|
||||||
model=Tag, event_types=(
|
model=Tag, event_types=(
|
||||||
|
|||||||
@@ -4,12 +4,19 @@ from django.apps import apps
|
|||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
def method_document_get_tags(self):
|
def method_document_get_tags(self, permission, user):
|
||||||
|
AccessControlList = apps.get_model(
|
||||||
|
app_label='acls', model_name='AccessControlList'
|
||||||
|
)
|
||||||
DocumentTag = apps.get_model(app_label='tags', model_name='DocumentTag')
|
DocumentTag = apps.get_model(app_label='tags', model_name='DocumentTag')
|
||||||
|
|
||||||
return DocumentTag.objects.filter(documents=self)
|
return AccessControlList.objects.restrict_queryset(
|
||||||
|
permission=permission,
|
||||||
|
queryset=DocumentTag.objects.filter(documents=self), user=user
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
method_document_get_tags.help_text = _(
|
method_document_get_tags.help_text = _(
|
||||||
'Return a the tags attached to the document.'
|
'Return a the tags attached to the document.'
|
||||||
)
|
)
|
||||||
|
method_document_get_tags.short_description = _('get_tags()')
|
||||||
|
|||||||
@@ -64,11 +64,21 @@ class Tag(models.Model):
|
|||||||
The count if filtered by access.
|
The count if filtered by access.
|
||||||
"""
|
"""
|
||||||
queryset = AccessControlList.objects.restrict_queryset(
|
queryset = AccessControlList.objects.restrict_queryset(
|
||||||
permission_document_view, user, queryset=self.documents
|
permission=permission_document_view, queryset=self.documents,
|
||||||
|
user=user
|
||||||
)
|
)
|
||||||
|
|
||||||
return queryset.count()
|
return queryset.count()
|
||||||
|
|
||||||
|
def get_documents(self, user):
|
||||||
|
"""
|
||||||
|
Return a filtered queryset documents that have this tag attached.
|
||||||
|
"""
|
||||||
|
return AccessControlList.objects.restrict_queryset(
|
||||||
|
permission=permission_document_view, queryset=self.documents.all(),
|
||||||
|
user=user
|
||||||
|
)
|
||||||
|
|
||||||
def get_preview_widget(self):
|
def get_preview_widget(self):
|
||||||
return widget_single_tag(tag=self)
|
return widget_single_tag(tag=self)
|
||||||
get_preview_widget.short_description = _('Preview')
|
get_preview_widget.short_description = _('Preview')
|
||||||
|
|||||||
@@ -110,8 +110,13 @@ class TagViewTestMixin(object):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _request_test_tag_list_view(self):
|
||||||
|
return self.get(viewname='tags:tag_list')
|
||||||
|
|
||||||
def _request_test_tag_document_list_view(self):
|
def _request_test_tag_document_list_view(self):
|
||||||
return self.get(viewname='documents:document_list')
|
return self.get(
|
||||||
|
viewname='tags:tag_document_list', kwargs={'pk': self.test_tag.pk}
|
||||||
|
)
|
||||||
|
|
||||||
def _request_test_document_tag_attach_view(self):
|
def _request_test_document_tag_attach_view(self):
|
||||||
return self.post(
|
return self.post(
|
||||||
@@ -146,3 +151,10 @@ class TagViewTestMixin(object):
|
|||||||
'tags': self.test_tag.pk,
|
'tags': self.test_tag.pk,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _request_test_document_tag_list_view(self):
|
||||||
|
return self.get(
|
||||||
|
viewname='tags:document_tag_list', kwargs={
|
||||||
|
'pk': self.test_document.pk
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.utils.encoding import force_text
|
||||||
|
|
||||||
from mayan.apps.common.tests import GenericViewTestCase
|
from mayan.apps.common.tests import GenericViewTestCase
|
||||||
from mayan.apps.documents.permissions import permission_document_view
|
from mayan.apps.documents.permissions import permission_document_view
|
||||||
from mayan.apps.documents.tests import GenericDocumentViewTestCase
|
from mayan.apps.documents.tests import GenericDocumentViewTestCase
|
||||||
@@ -100,8 +102,27 @@ class TagViewTestCase(TagTestMixin, TagViewTestMixin, GenericViewTestCase):
|
|||||||
self.test_tag.refresh_from_db()
|
self.test_tag.refresh_from_db()
|
||||||
self.assertNotEqual(self.test_tag.label, tag_label)
|
self.assertNotEqual(self.test_tag.label, tag_label)
|
||||||
|
|
||||||
|
def test_tag_list_view_with_no_permission(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
|
||||||
|
response = self._request_test_tag_list_view()
|
||||||
|
self.assertNotContains(
|
||||||
|
response=response, text=self.test_tag.label, status_code=200
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_tag_list_view_with_access(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
|
||||||
|
self.grant_access(obj=self.test_tag, permission=permission_tag_view)
|
||||||
|
|
||||||
|
response = self._request_test_tag_list_view()
|
||||||
|
self.assertContains(
|
||||||
|
response=response, text=self.test_tag.label, status_code=200
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TagDocumentViewTestCase(TagTestMixin, TagViewTestMixin, GenericDocumentViewTestCase):
|
class TagDocumentViewTestCase(TagTestMixin, TagViewTestMixin, GenericDocumentViewTestCase):
|
||||||
|
"""
|
||||||
def test_document_tags_widget_no_permissions(self):
|
def test_document_tags_widget_no_permissions(self):
|
||||||
self._create_test_tag()
|
self._create_test_tag()
|
||||||
|
|
||||||
@@ -126,6 +147,58 @@ class TagDocumentViewTestCase(TagTestMixin, TagViewTestMixin, GenericDocumentVie
|
|||||||
self.assertContains(
|
self.assertContains(
|
||||||
response=response, text=self.test_tag.label, status_code=200
|
response=response, text=self.test_tag.label, status_code=200
|
||||||
)
|
)
|
||||||
|
"""
|
||||||
|
def test_document_tags_list_no_permissions(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
|
||||||
|
self.test_tag.documents.add(self.test_document)
|
||||||
|
|
||||||
|
response = self._request_test_document_tag_list_view()
|
||||||
|
self.assertNotContains(
|
||||||
|
response=response, text=force_text(self.test_tag), status_code=404
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_document_tags_list_with_document_access(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
|
||||||
|
self.test_tag.documents.add(self.test_document)
|
||||||
|
|
||||||
|
self.grant_access(
|
||||||
|
obj=self.test_document, permission=permission_tag_view
|
||||||
|
)
|
||||||
|
|
||||||
|
response = self._request_test_document_tag_list_view()
|
||||||
|
self.assertNotContains(
|
||||||
|
response=response, text=force_text(self.test_tag), status_code=200
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_document_tags_list_with_tag_access(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
|
||||||
|
self.test_tag.documents.add(self.test_document)
|
||||||
|
|
||||||
|
self.grant_access(obj=self.test_tag, permission=permission_tag_view)
|
||||||
|
|
||||||
|
response = self._request_test_document_tag_list_view()
|
||||||
|
self.assertNotContains(
|
||||||
|
response=response, text=force_text(self.test_tag), status_code=404
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_document_tags_list_with_full_access(self):
|
||||||
|
self._create_test_tag()
|
||||||
|
|
||||||
|
self.test_tag.documents.add(self.test_document)
|
||||||
|
|
||||||
|
self.grant_access(obj=self.test_tag, permission=permission_tag_view)
|
||||||
|
self.grant_access(
|
||||||
|
obj=self.test_document, permission=permission_tag_view
|
||||||
|
)
|
||||||
|
|
||||||
|
response = self._request_test_document_tag_list_view()
|
||||||
|
self.assertContains(
|
||||||
|
response=response, text=force_text(self.test_tag), status_code=200
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_document_attach_tag_view_no_permission(self):
|
def test_document_attach_tag_view_no_permission(self):
|
||||||
self._create_test_tag()
|
self._create_test_tag()
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ from mayan.apps.common.generics import (
|
|||||||
MultipleObjectFormActionView, MultipleObjectConfirmActionView,
|
MultipleObjectFormActionView, MultipleObjectConfirmActionView,
|
||||||
SingleObjectCreateView, SingleObjectEditView, SingleObjectListView
|
SingleObjectCreateView, SingleObjectEditView, SingleObjectListView
|
||||||
)
|
)
|
||||||
|
from mayan.apps.common.mixins import ExternalObjectMixin
|
||||||
from mayan.apps.documents.models import Document
|
from mayan.apps.documents.models import Document
|
||||||
from mayan.apps.documents.views import DocumentListView
|
from mayan.apps.documents.views import DocumentListView
|
||||||
from mayan.apps.documents.permissions import permission_document_view
|
from mayan.apps.documents.permissions import permission_document_view
|
||||||
@@ -96,7 +97,9 @@ class TagAttachActionView(MultipleObjectFormActionView):
|
|||||||
return super(TagAttachActionView, self).get_post_action_redirect()
|
return super(TagAttachActionView, self).get_post_action_redirect()
|
||||||
|
|
||||||
def object_action(self, form, instance):
|
def object_action(self, form, instance):
|
||||||
attached_tags = instance.attached_tags()
|
attached_tags = instance.get_tags(
|
||||||
|
permission=permission_tag_attach, user=self.request.user
|
||||||
|
)
|
||||||
|
|
||||||
for tag in form.cleaned_data['tags']:
|
for tag in form.cleaned_data['tags']:
|
||||||
AccessControlList.objects.check_access(
|
AccessControlList.objects.check_access(
|
||||||
@@ -227,12 +230,13 @@ class TagListView(SingleObjectListView):
|
|||||||
return Tag.objects.all()
|
return Tag.objects.all()
|
||||||
|
|
||||||
|
|
||||||
class TagDocumentListView(DocumentListView):
|
class TagDocumentListView(ExternalObjectMixin, DocumentListView):
|
||||||
def get_tag(self):
|
external_object_class = Tag
|
||||||
return get_object_or_404(klass=Tag, pk=self.kwargs['pk'])
|
external_object_permission = permission_tag_view
|
||||||
|
external_object_pk_url_kwarg = 'pk'
|
||||||
|
|
||||||
def get_document_queryset(self):
|
def get_document_queryset(self):
|
||||||
return self.get_tag().documents.all()
|
return self.get_tag().get_documents(user=self.request.user).all()
|
||||||
|
|
||||||
def get_extra_context(self):
|
def get_extra_context(self):
|
||||||
context = super(TagDocumentListView, self).get_extra_context()
|
context = super(TagDocumentListView, self).get_extra_context()
|
||||||
@@ -244,39 +248,38 @@ class TagDocumentListView(DocumentListView):
|
|||||||
)
|
)
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
def get_tag(self):
|
||||||
|
return self.get_external_object()
|
||||||
|
|
||||||
class DocumentTagListView(TagListView):
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
|
||||||
self.document = get_object_or_404(klass=Document, pk=self.kwargs['pk'])
|
|
||||||
|
|
||||||
AccessControlList.objects.check_access(
|
class DocumentTagListView(ExternalObjectMixin, TagListView):
|
||||||
obj=self.document, permissions=(permission_document_view,),
|
external_object_class = Document
|
||||||
user=request.user,
|
external_object_permission = permission_tag_view
|
||||||
)
|
external_object_pk_url_kwarg = 'pk'
|
||||||
|
|
||||||
return super(DocumentTagListView, self).dispatch(
|
|
||||||
request, *args, **kwargs
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_extra_context(self):
|
def get_extra_context(self):
|
||||||
context = super(DocumentTagListView, self).get_extra_context()
|
context = super(DocumentTagListView, self).get_extra_context()
|
||||||
context.update(
|
context.update(
|
||||||
{
|
{
|
||||||
'hide_link': True,
|
'hide_link': True,
|
||||||
'no_results_title': _('Document has no tags attached'),
|
|
||||||
'no_results_main_link': link_document_tag_multiple_attach.resolve(
|
'no_results_main_link': link_document_tag_multiple_attach.resolve(
|
||||||
context=RequestContext(
|
context=RequestContext(
|
||||||
request=self.request, dict_={'object': self.document}
|
self.request, {'object': self.get_external_object()}
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
'object': self.document,
|
'no_results_title': _('Document has no tags attached'),
|
||||||
'title': _('Tags for document: %s') % self.document,
|
'object': self.get_external_object(),
|
||||||
|
'title': _(
|
||||||
|
'Tags for document: %s'
|
||||||
|
) % self.get_external_object(),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def get_tag_queryset(self):
|
def get_source_queryset(self):
|
||||||
return self.document.attached_tags().all()
|
return self.get_external_object().get_tags(
|
||||||
|
permission=permission_tag_view, user=self.request.user
|
||||||
|
).all()
|
||||||
|
|
||||||
|
|
||||||
class TagRemoveActionView(MultipleObjectFormActionView):
|
class TagRemoveActionView(MultipleObjectFormActionView):
|
||||||
@@ -343,7 +346,9 @@ class TagRemoveActionView(MultipleObjectFormActionView):
|
|||||||
return super(TagRemoveActionView, self).get_post_action_redirect()
|
return super(TagRemoveActionView, self).get_post_action_redirect()
|
||||||
|
|
||||||
def object_action(self, form, instance):
|
def object_action(self, form, instance):
|
||||||
attached_tags = instance.attached_tags()
|
attached_tags = instance.get_tags(
|
||||||
|
permission=permission_tag_remove, user=self.request.user
|
||||||
|
)
|
||||||
|
|
||||||
for tag in form.cleaned_data['tags']:
|
for tag in form.cleaned_data['tags']:
|
||||||
AccessControlList.objects.check_access(
|
AccessControlList.objects.check_access(
|
||||||
|
|||||||
Reference in New Issue
Block a user