diff --git a/HISTORY.rst b/HISTORY.rst index e5464122ad..8958e3a09f 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -2,12 +2,15 @@ ============= - Upgrade to use Django 1.8.8. Issue #246. - Upgrade requirements. -- Remove remaining references to Django's User model. Issue #225 +- Remove remaining references to Django's User model. GitLab issue #225 - Rename 'Content' search box to 'OCR'. - Remove included login required middleware using django-stronghold instead (http://mikegrouchy.com/django-stronghold/). - Improve generation of success and error messages for class based views. - Remove ownership concept from folders. -- Replace strip_spaces middleware with the spaceless template tag. Issue #255 +- Replace strip_spaces middleware with the spaceless template tag. GitLab issue #255 +- Deselect the update checkbox for optional metadata by default. +- Silence all Django 1.8 model import warnings. +- Implement per document type document creation permission. Closes GitLab issue #232. 2.0.2 (2016-02-09) ================== diff --git a/mayan/apps/acls/classes.py b/mayan/apps/acls/classes.py index 8750160937..08f9b520e2 100644 --- a/mayan/apps/acls/classes.py +++ b/mayan/apps/acls/classes.py @@ -24,15 +24,11 @@ class ModelPermission(object): app_label='permissions', model_name='StoredPermission' ) - try: - permissions = cls._registry[type(instance)] - except KeyError: - try: - permissions = cls._registry[cls._proxies[type(instance)]] - except KeyError: - permissions = () + permissions = [] + permissions.extend(cls._registry.get(type(instance))) + permissions.extend(cls._registry.get(cls._proxies.get(type(instance)))) - pks = [permission.stored_permission.pk for permission in permissions] + pks = [permission.stored_permission.pk for permission in set(permissions)] return StoredPermission.objects.filter(pk__in=pks) @classmethod diff --git a/mayan/apps/documents/apps.py b/mayan/apps/documents/apps.py index 9927703d8c..4b410cdb2a 100644 --- a/mayan/apps/documents/apps.py +++ b/mayan/apps/documents/apps.py @@ -61,11 +61,11 @@ from .literals import ( DELETE_STALE_STUBS_INTERVAL ) from .permissions import ( - permission_document_delete, permission_document_download, - permission_document_edit, permission_document_new_version, - permission_document_print, permission_document_properties_edit, - permission_document_trash, permission_document_version_revert, - permission_document_view + permission_document_create, permission_document_delete, + permission_document_download, permission_document_edit, + permission_document_new_version, permission_document_print, + permission_document_properties_edit, permission_document_trash, + permission_document_version_revert, permission_document_view ) from .settings import setting_thumbnail_size from .statistics import ( @@ -126,6 +126,10 @@ class DocumentsApp(MayanAppConfig): ) ) + ModelPermission.register( + model=DocumentType, permissions=(permission_document_create,) + ) + ModelPermission.register_proxy( source=Document, model=DocumentType, ) diff --git a/mayan/apps/documents/forms.py b/mayan/apps/documents/forms.py index ad7808fd86..57b2bf7720 100644 --- a/mayan/apps/documents/forms.py +++ b/mayan/apps/documents/forms.py @@ -1,16 +1,24 @@ -from __future__ import unicode_literals +from __future__ import absolute_import, unicode_literals + +import logging from django import forms +from django.core.exceptions import PermissionDenied from django.utils.translation import ugettext_lazy as _ +from acls.models import AccessControlList from common.forms import DetailForm +from permissions import Permission from .models import ( Document, DocumentType, DocumentPage, DocumentTypeFilename ) from .literals import DEFAULT_ZIP_FILENAME, PAGE_RANGE_CHOICES +from .permissions import permission_document_create from .widgets import DocumentPagesCarouselWidget, DocumentPageImageWidget +logger = logging.getLogger(__name__) + # Document page forms class DocumentPageForm(DetailForm): @@ -103,9 +111,24 @@ class DocumentTypeSelectForm(forms.Form): Form to select the document type of a document to be created, used as form #1 in the document creation wizard """ - document_type = forms.ModelChoiceField( - queryset=DocumentType.objects.all(), label=_('Document type') - ) + + def __init__(self, *args, **kwargs): + user = kwargs.pop('user', None) + logger.debug('user: %s', user) + super(DocumentTypeSelectForm, self).__init__(*args, **kwargs) + + queryset = DocumentType.objects.all() + try: + Permission.check_permissions(user, (permission_document_create,)) + except PermissionDenied: + queryset = AccessControlList.objects.filter_by_access( + permission_document_create, user, queryset + ) + + self.fields['document_type'] = forms.ModelChoiceField( + queryset=queryset, + label=_('Document type') + ) class DocumentTypeFilenameForm_create(forms.ModelForm): diff --git a/mayan/apps/documents/views.py b/mayan/apps/documents/views.py index 4ee92bbddb..d85f0ed0d7 100644 --- a/mayan/apps/documents/views.py +++ b/mayan/apps/documents/views.py @@ -650,7 +650,7 @@ def document_document_type_edit(request, document_id=None, document_id_list=None next = request.POST.get('next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL)))) if request.method == 'POST': - form = DocumentTypeSelectForm(request.POST) + form = DocumentTypeSelectForm(request.POST, user=request.user) if form.is_valid(): for instance in queryset: @@ -666,7 +666,8 @@ def document_document_type_edit(request, document_id=None, document_id_list=None return HttpResponseRedirect(next) else: form = DocumentTypeSelectForm( - initial={'document_type': queryset.first().document_type} + initial={'document_type': queryset.first().document_type}, + user=request.user ) context = { diff --git a/mayan/apps/sources/links.py b/mayan/apps/sources/links.py index 43503d61ce..e1a26d9cae 100644 --- a/mayan/apps/sources/links.py +++ b/mayan/apps/sources/links.py @@ -23,8 +23,8 @@ def document_new_version_not_blocked(context): link_document_create_multiple = Link( - icon='fa fa-upload', permissions=(permission_document_create,), - text=_('New document'), view='sources:document_create_multiple' + icon='fa fa-upload', text=_('New document'), + view='sources:document_create_multiple' ) link_document_create_siblings = Link( permissions=(permission_document_create,), text=_('Clone'), diff --git a/mayan/apps/sources/views.py b/mayan/apps/sources/views.py index ef75f158a7..367e60e9db 100644 --- a/mayan/apps/sources/views.py +++ b/mayan/apps/sources/views.py @@ -67,9 +67,18 @@ class SourceLogListView(SingleObjectListView): def document_create_siblings(request, document_id): - Permission.check_permissions(request.user, (permission_document_create,)) - document = get_object_or_404(Document, pk=document_id) + + try: + Permission.check_permissions( + request.user, (permission_document_create,) + ) + except PermissionDenied: + AccessControlList.objects.check_access( + permission_document_create, request.user, + document.document_type + ) + query_dict = {} for pk, metadata in enumerate(document.metadata.all()): query_dict['metadata%s_id' % pk] = metadata.metadata_type_id @@ -205,10 +214,6 @@ class UploadInteractiveView(UploadBaseView): def dispatch(self, request, *args, **kwargs): self.subtemplates_list = [] - Permission.check_permissions( - request.user, (permission_document_create,) - ) - self.document_type = get_object_or_404( DocumentType, pk=self.request.GET.get( @@ -216,6 +221,16 @@ class UploadInteractiveView(UploadBaseView): ) ) + try: + Permission.check_permissions( + request.user, (permission_document_create,) + ) + except PermissionDenied: + AccessControlList.objects.check_access( + permission_document_create, request.user, + self.document_type + ) + self.tab_links = UploadBaseView.get_active_tab_links() return super( diff --git a/mayan/apps/sources/wizards.py b/mayan/apps/sources/wizards.py index bd239e4381..23300b9eab 100644 --- a/mayan/apps/sources/wizards.py +++ b/mayan/apps/sources/wizards.py @@ -41,7 +41,6 @@ class DocumentCreateWizard(ViewPermissionCheckMixin, SessionWizardView): TagMultipleSelectionForm: _('Step 3 of 3: Select tags'), } template_name = 'appearance/generic_wizard.html' - view_permission = permission_document_create def dispatch(self, request, *args, **kwargs): if not InteractiveSource.objects.filter(enabled=True).exists(): @@ -89,6 +88,9 @@ class DocumentCreateWizard(ViewPermissionCheckMixin, SessionWizardView): def get_form_kwargs(self, step): # Tags form needs the user instance to determine which tags to # display + if step == STEP_DOCUMENT_TYPE: + return {'user': self.request.user} + if step == STEP_TAGS: return {'user': self.request.user}