Add ACL support for metadata types.
Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
This commit is contained in:
@@ -56,7 +56,8 @@
|
||||
- Add new revertsettings management command.
|
||||
- Add new permission to edit setting via the UI.
|
||||
- Renamed setting LOCK_MANAGER_DEFAULT_BACKEND to LOCK_MANAGER_BACKEND.
|
||||
- Add help text to settings.
|
||||
- Add help texts to more setting options.
|
||||
- Add ACL support for metadata types.
|
||||
|
||||
3.0.1 (2018-07-08)
|
||||
=================
|
||||
|
||||
@@ -9,6 +9,8 @@ from django.db.models.signals import post_delete, post_save
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from acls import ModelPermission
|
||||
from acls.links import link_acl_list
|
||||
from acls.permissions import permission_acl_edit, permission_acl_view
|
||||
from common import (
|
||||
MayanAppConfig, menu_facet, menu_multi_item, menu_object, menu_secondary,
|
||||
menu_setup, menu_sidebar
|
||||
@@ -147,10 +149,9 @@ class MetadataApp(MayanAppConfig):
|
||||
)
|
||||
ModelPermission.register(
|
||||
model=MetadataType, permissions=(
|
||||
permission_events_view,
|
||||
permission_metadata_type_delete,
|
||||
permission_metadata_type_edit,
|
||||
permission_metadata_type_view
|
||||
permission_acl_edit, permission_acl_view,
|
||||
permission_events_view, permission_metadata_type_delete,
|
||||
permission_metadata_type_edit, permission_metadata_type_view
|
||||
)
|
||||
)
|
||||
|
||||
@@ -223,10 +224,9 @@ class MetadataApp(MayanAppConfig):
|
||||
menu_object.bind_links(
|
||||
links=(
|
||||
link_setup_metadata_type_edit,
|
||||
link_setup_metadata_type_document_types,
|
||||
link_setup_metadata_type_document_types, link_acl_list,
|
||||
link_object_event_types_user_subcriptions_list,
|
||||
link_events_for_object,
|
||||
link_setup_metadata_type_delete,
|
||||
link_events_for_object, link_setup_metadata_type_delete,
|
||||
), sources=(MetadataType,)
|
||||
)
|
||||
menu_secondary.bind_links(
|
||||
|
||||
@@ -11,8 +11,10 @@ TEST_INVALID_DATE = '___________'
|
||||
TEST_LOOKUP_TEMPLATE = '1,2,3'
|
||||
TEST_METADATA_TYPE_LABEL = 'test metadata type'
|
||||
TEST_METADATA_TYPE_LABEL_2 = 'test metadata type label 2'
|
||||
TEST_METADATA_TYPE_LABEL_EDITED = 'test metadata type label edited'
|
||||
TEST_METADATA_TYPE_NAME = 'test'
|
||||
TEST_METADATA_TYPE_NAME_2 = 'test metadata type name 2'
|
||||
TEST_METADATA_TYPE_NAME_EDITED = 'test metadata type name edited'
|
||||
TEST_METADATA_VALUE = 'test value'
|
||||
TEST_METADATA_VALUE_EDITED = 'test value edited'
|
||||
TEST_METADATA_VALUE_UNICODE = 'español'
|
||||
|
||||
@@ -2,7 +2,10 @@ from __future__ import unicode_literals
|
||||
|
||||
from ..models import MetadataType
|
||||
|
||||
from .literals import TEST_METADATA_TYPE_NAME, TEST_METADATA_TYPE_LABEL
|
||||
from .literals import (
|
||||
TEST_METADATA_TYPE_LABEL, TEST_METADATA_TYPE_LABEL_EDITED,
|
||||
TEST_METADATA_TYPE_NAME, TEST_METADATA_TYPE_NAME_EDITED
|
||||
)
|
||||
|
||||
|
||||
class MetadataTypeMixin(object):
|
||||
@@ -11,3 +14,53 @@ class MetadataTypeMixin(object):
|
||||
self.metadata_type = MetadataType.objects.create(
|
||||
name=TEST_METADATA_TYPE_NAME, label=TEST_METADATA_TYPE_LABEL
|
||||
)
|
||||
|
||||
|
||||
class MetadataTestsMixin(object):
|
||||
def _create_metadata_type(self):
|
||||
self.metadata_type = MetadataType.objects.create(
|
||||
label=TEST_METADATA_TYPE_LABEL,
|
||||
name=TEST_METADATA_TYPE_NAME
|
||||
)
|
||||
|
||||
def _request_metadata_type_create_view(self):
|
||||
return self.post(
|
||||
viewname='metadata:setup_metadata_type_create', data={
|
||||
'label': TEST_METADATA_TYPE_LABEL,
|
||||
'name': TEST_METADATA_TYPE_NAME
|
||||
}
|
||||
)
|
||||
|
||||
def _request_metadata_type_delete_view(self):
|
||||
return self.post(
|
||||
viewname='metadata:setup_metadata_type_delete', args=(
|
||||
self.metadata_type.pk,
|
||||
),
|
||||
)
|
||||
|
||||
def _request_metadata_type_edit_view(self):
|
||||
return self.post(
|
||||
viewname='metadata:setup_metadata_type_edit', args=(
|
||||
self.metadata_type.pk,), data={
|
||||
'label': TEST_METADATA_TYPE_LABEL_EDITED,
|
||||
'name': TEST_METADATA_TYPE_NAME_EDITED
|
||||
}
|
||||
)
|
||||
|
||||
def _request_metadata_type_relationship_edit_view(self):
|
||||
# This request assumes there is only one document type and
|
||||
# blindly sets the first form of the formset.
|
||||
|
||||
return self.post(
|
||||
viewname='metadata:setup_metadata_type_document_types',
|
||||
args=(self.metadata_type.pk,), data={
|
||||
'form-TOTAL_FORMS': '1',
|
||||
'form-INITIAL_FORMS': '0',
|
||||
'form-0-relationship_type': 'required',
|
||||
}
|
||||
)
|
||||
|
||||
def _request_metadata_type_list_view(self):
|
||||
return self.get(
|
||||
viewname='metadata:setup_metadata_type_list',
|
||||
)
|
||||
|
||||
@@ -3,26 +3,33 @@ from __future__ import unicode_literals
|
||||
import logging
|
||||
|
||||
from django.core.files.base import File
|
||||
|
||||
from common.tests import GenericViewTestCase
|
||||
from documents.models import DocumentType
|
||||
from documents.permissions import (
|
||||
permission_document_properties_edit, permission_document_view
|
||||
permission_document_properties_edit, permission_document_type_edit,
|
||||
permission_document_view
|
||||
)
|
||||
from documents.tests import (
|
||||
GenericDocumentViewTestCase, TEST_DOCUMENT_TYPE_2_LABEL,
|
||||
TEST_SMALL_DOCUMENT_PATH,
|
||||
DocumentTestMixin, GenericDocumentViewTestCase,
|
||||
TEST_DOCUMENT_TYPE_2_LABEL, TEST_SMALL_DOCUMENT_PATH,
|
||||
)
|
||||
|
||||
from ..models import MetadataType
|
||||
from ..permissions import (
|
||||
permission_metadata_document_add, permission_metadata_document_remove,
|
||||
permission_metadata_document_edit
|
||||
permission_metadata_document_edit, permission_metadata_type_create,
|
||||
permission_metadata_type_delete, permission_metadata_type_edit,
|
||||
permission_metadata_type_view
|
||||
)
|
||||
|
||||
from .literals import (
|
||||
TEST_DOCUMENT_METADATA_VALUE_2, TEST_METADATA_TYPE_LABEL,
|
||||
TEST_METADATA_TYPE_LABEL_2, TEST_METADATA_TYPE_NAME,
|
||||
TEST_METADATA_TYPE_NAME_2, TEST_METADATA_VALUE_EDITED
|
||||
TEST_METADATA_TYPE_LABEL_2, TEST_METADATA_TYPE_LABEL_EDITED,
|
||||
TEST_METADATA_TYPE_NAME, TEST_METADATA_TYPE_NAME_2,
|
||||
TEST_METADATA_TYPE_NAME_EDITED, TEST_METADATA_VALUE_EDITED
|
||||
)
|
||||
from .mixins import MetadataTestsMixin
|
||||
|
||||
|
||||
class DocumentMetadataTestCase(GenericDocumentViewTestCase):
|
||||
@@ -295,3 +302,204 @@ class DocumentMetadataTestCase(GenericDocumentViewTestCase):
|
||||
)
|
||||
|
||||
self.assertContains(response, 'Edit', status_code=200)
|
||||
|
||||
|
||||
class MetadataTypeViewTestCase(DocumentTestMixin, MetadataTestsMixin, GenericViewTestCase):
|
||||
auto_create_document_type = False
|
||||
auto_upload_document = False
|
||||
|
||||
def test_metadata_type_create_view_no_permission(self):
|
||||
self.login_user()
|
||||
|
||||
response = self._request_metadata_type_create_view()
|
||||
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_metadata_type_create_view_with_access(self):
|
||||
self.login_user()
|
||||
|
||||
self.grant_permission(permission=permission_metadata_type_create)
|
||||
response = self._request_metadata_type_create_view()
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
self.assertQuerysetEqual(
|
||||
qs=MetadataType.objects.values('label', 'name'),
|
||||
values=[
|
||||
{
|
||||
'label': TEST_METADATA_TYPE_LABEL,
|
||||
'name': TEST_METADATA_TYPE_NAME
|
||||
}
|
||||
], transform=dict
|
||||
)
|
||||
|
||||
def test_metadata_type_delete_view_no_permission(self):
|
||||
self.login_user()
|
||||
self._create_metadata_type()
|
||||
|
||||
response = self._request_metadata_type_delete_view()
|
||||
|
||||
self.assertEqual(response.status_code, 403)
|
||||
self.assertQuerysetEqual(
|
||||
qs=MetadataType.objects.values('label', 'name'),
|
||||
values=[
|
||||
{
|
||||
'label': TEST_METADATA_TYPE_LABEL,
|
||||
'name': TEST_METADATA_TYPE_NAME
|
||||
}
|
||||
], transform=dict
|
||||
)
|
||||
|
||||
def test_metadata_type_delete_view_with_access(self):
|
||||
self.login_user()
|
||||
self._create_metadata_type()
|
||||
|
||||
self.grant_access(
|
||||
permission=permission_metadata_type_delete,
|
||||
obj=self.metadata_type
|
||||
)
|
||||
response = self._request_metadata_type_delete_view()
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
self.assertEqual(MetadataType.objects.count(), 0)
|
||||
|
||||
def test_metadata_type_edit_view_no_permission(self):
|
||||
self.login_user()
|
||||
self._create_metadata_type()
|
||||
|
||||
response = self._request_metadata_type_edit_view()
|
||||
|
||||
self.assertEqual(response.status_code, 403)
|
||||
self.assertQuerysetEqual(
|
||||
qs=MetadataType.objects.values('label', 'name'),
|
||||
values=[
|
||||
{
|
||||
'label': TEST_METADATA_TYPE_LABEL,
|
||||
'name': TEST_METADATA_TYPE_NAME
|
||||
}
|
||||
], transform=dict
|
||||
)
|
||||
|
||||
def test_metadata_type_edit_view_with_access(self):
|
||||
self.login_user()
|
||||
self._create_metadata_type()
|
||||
|
||||
self.grant_access(
|
||||
permission=permission_metadata_type_edit,
|
||||
obj=self.metadata_type
|
||||
)
|
||||
response = self._request_metadata_type_edit_view()
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
self.assertQuerysetEqual(
|
||||
qs=MetadataType.objects.values('label', 'name'),
|
||||
values=[
|
||||
{
|
||||
'label': TEST_METADATA_TYPE_LABEL_EDITED,
|
||||
'name': TEST_METADATA_TYPE_NAME_EDITED
|
||||
}
|
||||
], transform=dict
|
||||
)
|
||||
|
||||
def test_metadata_type_list_view_no_permission(self):
|
||||
self.login_user()
|
||||
self._create_metadata_type()
|
||||
|
||||
response = self._request_metadata_type_list_view()
|
||||
self.assertNotContains(
|
||||
response=response, text=self.metadata_type, status_code=200
|
||||
)
|
||||
|
||||
def test_metadata_type_list_view_with_access(self):
|
||||
self.login_user()
|
||||
self._create_metadata_type()
|
||||
|
||||
self.grant_access(
|
||||
permission=permission_metadata_type_view,
|
||||
obj=self.metadata_type
|
||||
)
|
||||
response = self._request_metadata_type_list_view()
|
||||
self.assertContains(
|
||||
response=response, text=self.metadata_type, status_code=200
|
||||
)
|
||||
|
||||
def test_metadata_type_relationship_view_no_permission(self):
|
||||
self.login_user()
|
||||
self._create_metadata_type()
|
||||
self.create_document_type()
|
||||
self.upload_document()
|
||||
|
||||
response = self._request_metadata_type_relationship_edit_view()
|
||||
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
self.document_type.refresh_from_db()
|
||||
|
||||
self.assertEqual(self.document_type.metadata.count(), 0)
|
||||
|
||||
def test_metadata_type_relationship_view_with_document_type_access(self):
|
||||
self.login_user()
|
||||
self._create_metadata_type()
|
||||
self.create_document_type()
|
||||
self.upload_document()
|
||||
|
||||
self.grant_access(
|
||||
permission=permission_document_type_edit, obj=self.document_type
|
||||
)
|
||||
|
||||
response = self._request_metadata_type_relationship_edit_view()
|
||||
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
self.document_type.refresh_from_db()
|
||||
|
||||
self.assertEqual(self.document_type.metadata.count(), 0)
|
||||
|
||||
def test_metadata_type_relationship_view_with_metadata_type_access(self):
|
||||
self.login_user()
|
||||
self._create_metadata_type()
|
||||
self.create_document_type()
|
||||
self.upload_document()
|
||||
|
||||
self.grant_access(
|
||||
permission=permission_metadata_type_edit, obj=self.metadata_type
|
||||
)
|
||||
|
||||
response = self._request_metadata_type_relationship_edit_view()
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
self.document_type.refresh_from_db()
|
||||
|
||||
self.assertEqual(self.document_type.metadata.count(), 0)
|
||||
|
||||
def test_metadata_type_relationship_view_with_metadata_type_and_document_type_access(self):
|
||||
self.login_user()
|
||||
self._create_metadata_type()
|
||||
self.create_document_type()
|
||||
self.upload_document()
|
||||
|
||||
self.grant_access(
|
||||
permission=permission_metadata_type_edit, obj=self.metadata_type
|
||||
)
|
||||
self.grant_access(
|
||||
permission=permission_document_type_edit, obj=self.document_type
|
||||
)
|
||||
|
||||
response = self._request_metadata_type_relationship_edit_view()
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
self.document_type.refresh_from_db()
|
||||
|
||||
self.assertQuerysetEqual(
|
||||
qs=self.document_type.metadata.values('metadata_type', 'required'),
|
||||
values=[
|
||||
{
|
||||
'metadata_type': self.metadata_type.pk,
|
||||
'required': True,
|
||||
}
|
||||
], transform=dict
|
||||
)
|
||||
|
||||
@@ -538,8 +538,8 @@ class MetadataTypeCreateView(SingleObjectCreateView):
|
||||
|
||||
class MetadataTypeDeleteView(SingleObjectDeleteView):
|
||||
model = MetadataType
|
||||
object_permission = permission_metadata_type_delete
|
||||
post_action_redirect = reverse_lazy('metadata:setup_metadata_type_list')
|
||||
view_permission = permission_metadata_type_delete
|
||||
|
||||
def get_extra_context(self):
|
||||
return {
|
||||
@@ -552,8 +552,8 @@ class MetadataTypeDeleteView(SingleObjectDeleteView):
|
||||
class MetadataTypeEditView(SingleObjectEditView):
|
||||
form_class = MetadataTypeForm
|
||||
model = MetadataType
|
||||
object_permission = permission_metadata_type_edit
|
||||
post_action_redirect = reverse_lazy('metadata:setup_metadata_type_list')
|
||||
view_permission = permission_metadata_type_edit
|
||||
|
||||
def get_extra_context(self):
|
||||
return {
|
||||
@@ -568,7 +568,7 @@ class MetadataTypeEditView(SingleObjectEditView):
|
||||
|
||||
|
||||
class MetadataTypeListView(SingleObjectListView):
|
||||
view_permission = permission_metadata_type_view
|
||||
object_permission = permission_metadata_type_view
|
||||
|
||||
def get_extra_context(self):
|
||||
return {
|
||||
@@ -591,7 +591,6 @@ class SetupDocumentTypeMetadataTypes(FormView):
|
||||
main_model = 'document_type'
|
||||
model = DocumentType
|
||||
submodel = MetadataType
|
||||
view_permission = permission_document_type_edit
|
||||
|
||||
def form_valid(self, form):
|
||||
try:
|
||||
@@ -617,7 +616,13 @@ class SetupDocumentTypeMetadataTypes(FormView):
|
||||
}
|
||||
|
||||
def get_object(self):
|
||||
return get_object_or_404(self.model, pk=self.kwargs['pk'])
|
||||
obj = get_object_or_404(self.model, pk=self.kwargs['pk'])
|
||||
|
||||
AccessControlList.objects.check_access(
|
||||
permissions=(permission_metadata_type_edit,),
|
||||
user=self.request.user, obj=obj
|
||||
)
|
||||
return obj
|
||||
|
||||
def get_extra_context(self):
|
||||
return {
|
||||
@@ -647,7 +652,11 @@ class SetupDocumentTypeMetadataTypes(FormView):
|
||||
return reverse('documents:document_type_list')
|
||||
|
||||
def get_queryset(self):
|
||||
return self.submodel.objects.all()
|
||||
queryset = self.submodel.objects.all()
|
||||
return AccessControlList.objects.filter_by_access(
|
||||
permission=permission_document_type_edit,
|
||||
user=self.request.user, queryset=queryset
|
||||
)
|
||||
|
||||
|
||||
class SetupMetadataTypesDocumentTypes(SetupDocumentTypeMetadataTypes):
|
||||
|
||||
Reference in New Issue
Block a user