diff --git a/apps/tags/__init__.py b/apps/tags/__init__.py index c730620b3b..8cf8fc2307 100644 --- a/apps/tags/__init__.py +++ b/apps/tags/__init__.py @@ -7,6 +7,7 @@ from navigation.api import (register_links, register_top_menu, from common.utils import encapsulate from documents.models import Document from acls.models import class_permissions +from acls.permissions import ACLS_VIEW_ACL from taggit.models import Tag from taggit.managers import TaggableManager @@ -17,8 +18,8 @@ from .permissions import (PERMISSION_TAG_CREATE, PERMISSION_TAG_ATTACH, PERMISSION_TAG_VIEW) tag_list = {'text': _(u'tag list'), 'view': 'tag_list', 'famfam': 'tag_blue'} -tag_create = {'text': _(u'create new tag'), 'view': 'tag_create', 'famfam': 'tag_blue_add'} -tag_add_attach = {'text': _(u'attach tag'), 'view': 'tag_add_attach', 'args': 'object.pk', 'famfam': 'tag_blue_add', 'permission': [PERMISSION_TAG_CREATE, PERMISSION_TAG_ATTACH]} +tag_create = {'text': _(u'create new tag'), 'view': 'tag_create', 'famfam': 'tag_blue_add', 'permission': [PERMISSION_TAG_CREATE]} +tag_attach = {'text': _(u'attach tag'), 'view': 'tag_attach', 'args': 'object.pk', 'famfam': 'tag_blue_add', 'permission': [PERMISSION_TAG_ATTACH]} tag_document_remove = {'text': _(u'remove'), 'view': 'tag_remove', 'args': ['object.id', 'document.id'], 'famfam': 'tag_blue_delete', 'permissions': [PERMISSION_TAG_REMOVE]} tag_document_remove_multiple = {'text': _(u'remove'), 'view': 'tag_multiple_remove', 'args': 'document.id', 'famfam': 'tag_blue_delete', 'permissions': [PERMISSION_TAG_REMOVE]} tag_document_list = {'text': _(u'tags'), 'view': 'document_tags', 'args': 'object.pk', 'famfam': 'tag_blue', 'permissions': [PERMISSION_TAG_REMOVE], 'children_view_regex': ['tag']} @@ -26,6 +27,8 @@ tag_delete = {'text': _(u'delete'), 'view': 'tag_delete', 'args': 'object.id', ' tag_edit = {'text': _(u'edit'), 'view': 'tag_edit', 'args': 'object.id', 'famfam': 'tag_blue_edit', 'permissions': [PERMISSION_TAG_EDIT]} tag_tagged_item_list = {'text': _(u'tagged documents'), 'view': 'tag_tagged_item_list', 'args': 'object.id', 'famfam': 'page'} tag_multiple_delete = {'text': _(u'delete'), 'view': 'tag_multiple_delete', 'famfam': 'tag_blue_delete', 'permissions': [PERMISSION_TAG_DELETE]} +tag_acl_list = {'text': _(u'ACLs'), 'view': 'tag_acl_list', 'args': 'object.pk', 'famfam': 'lock', 'permissions': [ACLS_VIEW_ACL]} +tag_new_holder = {'text': _(u'New holder'), 'view': 'tag_new_holder', 'args': 'object.pk', 'famfam': 'user', 'permissions': [ACLS_VIEW_ACL]} register_model_list_columns(Tag, [ { @@ -35,22 +38,21 @@ register_model_list_columns(Tag, [ { 'name': _(u'color name'), 'attribute': encapsulate(lambda x: x.tagproperties_set.get().get_color_display()), + }, + { + 'name': _(u'tagged items'), + 'attribute': encapsulate(lambda x: x.taggit_taggeditem_items.count()) } ]) -register_links(Tag, [tag_tagged_item_list, tag_edit, tag_delete]) - +register_links(Tag, [tag_tagged_item_list, tag_edit, tag_delete, tag_acl_list]) register_multi_item_links(['tag_list'], [tag_multiple_delete]) - -register_links(['tag_list', 'tag_delete', 'tag_edit', 'tag_tagged_item_list', 'tag_multiple_delete', 'tag_create'], [tag_list, tag_create], menu_name='secondary_menu') - -#register_sidebar_template(['document_tags'], 'tags_sidebar_template.html') - -register_top_menu('tags', link={'text': _(u'tags'), 'view': 'tag_list', 'famfam': 'tag_blue'}, children_path_regex=[r'^tags/[^d]']) +register_links([Tag, 'tag_list', 'tag_create'], [tag_list, tag_create], menu_name='secondary_menu') +register_top_menu('tags', link={'text': _(u'tags'), 'view': 'tag_list', 'famfam': 'tag_blue'}, children_path_regex=[r'^tags/[^d]'])#TODO: change to children view regex or list +register_links(['tag_acl_list', 'tag_new_holder'], [tag_new_holder], menu_name='sidebar') register_links(Document, [tag_document_list], menu_name='form_header') -register_links(['document_tags', 'tag_add_attach', 'tag_remove', 'tag_multiple_remove'], [tag_add_attach], menu_name='sidebar') - +register_links(['document_tags', 'tag_add_attach', 'tag_remove', 'tag_multiple_remove'], [tag_attach], menu_name='sidebar') register_multi_item_links(['document_tags'], [tag_document_remove_multiple]) class_permissions(Document, [ diff --git a/apps/tags/admin.py b/apps/tags/admin.py index 0ba921af19..009033002f 100644 --- a/apps/tags/admin.py +++ b/apps/tags/admin.py @@ -4,5 +4,4 @@ from django.contrib import admin from .models import TagProperties - admin.site.register(TagProperties) diff --git a/apps/tags/forms.py b/apps/tags/forms.py index 01a210494a..15ccc66411 100644 --- a/apps/tags/forms.py +++ b/apps/tags/forms.py @@ -1,26 +1,41 @@ from __future__ import absolute_import +import logging + from django import forms from django.utils.translation import ugettext_lazy as _ from taggit.models import Tag +from acls.models import AccessEntry +from permissions.models import Permission + from .models import COLOR_CHOICES +from .permissions import PERMISSION_TAG_VIEW - -class AddTagForm(forms.Form): - """ - Form to be displayed in the sidebar of a document and allow adding - new or existing tags - """ - new_tag = forms.CharField(required=False, label=_(u'New tag')) - color = forms.ChoiceField(choices=COLOR_CHOICES, required=False, label=_(u'Color')) - existing_tags = forms.ModelChoiceField(required=False, queryset=Tag.objects.all(), label=_(u'Existing tags')) +logger = logging.getLogger(__name__) class TagForm(forms.Form): - """ + ''' Form to edit an existing tag's properties - """ + ''' name = forms.CharField(label=_(u'Name')) color = forms.ChoiceField(choices=COLOR_CHOICES, label=_(u'Color')) + + +class TagListForm(forms.Form): + def __init__(self, *args, **kwargs): + user = kwargs.pop('user', None) + logger.debug('user: %s' % user) + super(TagListForm, self).__init__(*args, **kwargs) + + queryset = Tag.objects.all() + try: + Permission.objects.check_permissions(user, [PERMISSION_TAG_VIEW]) + except PermissionDenied: + queryset = AccessEntry.objects.filter_objects_by_access(PERMISSION_TAG_VIEW, user, queryset) + + self.fields['tag'] = forms.ModelChoiceField( + queryset=queryset, + label=_(u'Tags')) diff --git a/apps/tags/models.py b/apps/tags/models.py index 8c36a2cb7c..98bd405f3b 100644 --- a/apps/tags/models.py +++ b/apps/tags/models.py @@ -1,44 +1,11 @@ +from __future__ import absolute_import + from django.db import models from django.utils.translation import ugettext_lazy as _ from taggit.models import Tag -COLOR_RED = u'red' -COLOR_BLUE = u'blu' -COLOR_MAGENTA = u'mag' -COLOR_CYAN = u'cya' -COLOR_YELLOW = u'yel' -COLOR_GREENYELLOW = u'gry' -COLOR_CORAL = u'crl' -COLOR_KHAKI = u'kki' -COLOR_LIGHTGREY = u'lig' -COLOR_ORANGE = u'org' - -COLOR_CHOICES = ( - (COLOR_BLUE, _(u'Blue')), - (COLOR_CYAN, _(u'Cyan')), - (COLOR_CORAL, _(u'Coral')), - (COLOR_GREENYELLOW, _(u'Green-Yellow')), - (COLOR_KHAKI, _(u'Khaki')), - (COLOR_LIGHTGREY, _(u'LightGrey')), - (COLOR_MAGENTA, _(u'Magenta')), - (COLOR_RED, _(u'Red')), - (COLOR_ORANGE, _(u'Orange')), - (COLOR_YELLOW, _(u'Yellow')) -) - -COLOR_CODES = ( - (COLOR_RED, u'red'), - (COLOR_BLUE, u'blue'), - (COLOR_MAGENTA, u'magenta'), - (COLOR_CYAN, u'cyan'), - (COLOR_YELLOW, u'yellow'), - (COLOR_GREENYELLOW, u'greenyellow '), - (COLOR_CORAL, u'coral'), - (COLOR_KHAKI, u'khaki'), - (COLOR_ORANGE, u'orange'), - (COLOR_LIGHTGREY, u'lightgrey'), -) +from .literals import COLOR_CHOICES, COLOR_CODES class TagProperties(models.Model): diff --git a/apps/tags/tests.py b/apps/tags/tests.py index 612cd1803e..094293d35c 100644 --- a/apps/tags/tests.py +++ b/apps/tags/tests.py @@ -1,6 +1,7 @@ from django.utils import unittest -from .models import Tag, TagProperties, COLOR_RED +from .models import Tag, TagProperties +from .literals import COLOR_RED class TagTestCase(unittest.TestCase): diff --git a/apps/tags/urls.py b/apps/tags/urls.py index d649819642..403d4c258d 100644 --- a/apps/tags/urls.py +++ b/apps/tags/urls.py @@ -10,7 +10,9 @@ urlpatterns = patterns('tags.views', url(r'^(?P\d+)/remove_from_document/(?P\d+)/$', 'tag_remove', (), 'tag_remove'), url(r'^multiple/remove_from_document/(?P\d+)/$', 'tag_multiple_remove', (), 'tag_multiple_remove'), - url(r'^document/(?P\d+)/add/$', 'tag_add_attach', (), 'tag_add_attach'), - url(r'^document/(?P\d+)/add/from_sidebar/$', 'tag_add_sidebar', (), 'tag_add_sidebar'), + url(r'^document/(?P\d+)/add/$', 'tag_attach', (), 'tag_attach'), url(r'^document/(?P\d+)/list/$', 'document_tags', (), 'document_tags'), + + url(r'^(?P\d+)/acl/list/$', 'tag_acl_list', (), 'tag_acl_list'), + url(r'^(?P\d+)/acl/holder/new/$', 'tag_new_holder', (), 'tag_new_holder'), ) diff --git a/apps/tags/views.py b/apps/tags/views.py index 12dba9dea9..8083f8d696 100644 --- a/apps/tags/views.py +++ b/apps/tags/views.py @@ -1,5 +1,7 @@ from __future__ import absolute_import +import logging + from django.http import HttpResponseRedirect from django.shortcuts import render_to_response, get_object_or_404 from django.template import RequestContext @@ -7,22 +9,26 @@ from django.contrib import messages from django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ -from permissions.models import Permission +from permissions import Permission from taggit.models import Tag from documents.models import Document from documents.views import document_list +from documents.permissions import PERMISSION_DOCUMENT_VIEW from common.utils import encapsulate +from acls.models import AccessEntry, PermissionDenied +from acls.views import acl_list_for, acl_new_holder_for -from .forms import AddTagForm, TagForm +from .forms import TagListForm, TagForm from .models import TagProperties from .permissions import (PERMISSION_TAG_CREATE, PERMISSION_TAG_ATTACH, PERMISSION_TAG_REMOVE, PERMISSION_TAG_DELETE, PERMISSION_TAG_EDIT, PERMISSION_TAG_VIEW) -from . import tag_tagged_item_list as tag_tagged_item_list_link + +logger = logging.getLogger(__name__) def tag_create(request): - #Permission.objects.check_permissions(request.user, [PERMISSION_TAG_EDIT]) + Permission.objects.check_permissions(request.user, [PERMISSION_TAG_CREATE]) redirect_url = reverse('tag_list') previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', redirect_url))) @@ -51,85 +57,30 @@ def tag_create(request): context_instance=RequestContext(request)) -def tag_add_sidebar(request, document_id): +def tag_attach(request, document_id): document = get_object_or_404(Document, pk=document_id) - previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', reverse('tag_list')))) - - if request.method == 'POST': - previous = request.META.get('HTTP_REFERER', '/') - form = AddTagForm(request.POST) - if form.is_valid(): - if form.cleaned_data['new_tag']: - Permission.objects.check_permissions(request.user, [PERMISSION_TAG_CREATE]) - tag_name = form.cleaned_data['new_tag'] - if Tag.objects.filter(name=tag_name): - is_new = False - else: - is_new = True - elif form.cleaned_data['existing_tags']: - Permission.objects.check_permissions(request.user, [PERMISSION_TAG_ATTACH]) - tag_name = form.cleaned_data['existing_tags'] - is_new = False - else: - messages.error(request, _(u'Must choose either a new tag or an existing one.')) - return HttpResponseRedirect(previous) - - if tag_name in document.tags.values_list('name', flat=True): - messages.warning(request, _(u'Document is already tagged as "%s"') % tag_name) - return HttpResponseRedirect(previous) - - document.tags.add(tag_name) - - if is_new: - tag = Tag.objects.get(name=tag_name) - TagProperties(tag=tag, color=form.cleaned_data['color']).save() - - messages.success(request, _(u'Tag "%s" added successfully.') % tag_name) - - return HttpResponseRedirect(previous) - - -def tag_add_attach(request, document_id): - # TODO: merge with tag_add_sidebar - document = get_object_or_404(Document, pk=document_id) + try: + Permission.objects.check_permissions(request.user, [PERMISSION_TAG_ATTACH]) + except PermissionDenied: + AccessEntry.objects.check_access(PERMISSION_TAG_ATTACH, request.user, document) next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', reverse('document_tags', args=[document.pk])))) if request.method == 'POST': - form = AddTagForm(request.POST) + form = TagListForm(request.POST, user=request.user) if form.is_valid(): - if form.cleaned_data['new_tag']: - Permission.objects.check_permissions(request.user, [PERMISSION_TAG_CREATE]) - tag_name = form.cleaned_data['new_tag'] - if Tag.objects.filter(name=tag_name): - is_new = False - else: - is_new = True - elif form.cleaned_data['existing_tags']: - Permission.objects.check_permissions(request.user, [PERMISSION_TAG_ATTACH]) - tag_name = form.cleaned_data['existing_tags'] - is_new = False - else: - messages.error(request, _(u'Must choose either a new tag or an existing one.')) + tag = form.cleaned_data['tag'] + if tag in document.tags.all(): + messages.warning(request, _(u'Document is already tagged as "%s"') % tag) return HttpResponseRedirect(next) - if tag_name in document.tags.values_list('name', flat=True): - messages.warning(request, _(u'Document is already tagged as "%s"') % tag_name) - return HttpResponseRedirect(next) - - document.tags.add(tag_name) - - if is_new: - tag = Tag.objects.get(name=tag_name) - TagProperties(tag=tag, color=form.cleaned_data['color']).save() - messages.success(request, _(u'Tag "%s" added and attached successfully.') % tag_name) - else: - messages.success(request, _(u'Tag "%s" attached successfully.') % tag_name) + document.tags.add(tag) + messages.success(request, _(u'Tag "%s" attached successfully.') % tag) return HttpResponseRedirect(next) else: - form = AddTagForm() + form = TagListForm(user=request.user) return render_to_response('generic_form.html', { 'title': _(u'attach tag to: %s') % document, @@ -140,23 +91,31 @@ def tag_add_attach(request, document_id): context_instance=RequestContext(request)) -def tag_list(request): - return render_to_response('generic_list.html', { - 'object_list': Tag.objects.all(), +def tag_list(request, queryset=None, extra_context=None): + context = { 'title': _(u'tags'), 'hide_link': True, 'multi_select_as_buttons': True, - 'extra_columns': [ - { - 'name': _(u'tagged items'), - 'attribute': encapsulate(lambda x: x.taggit_taggeditem_items.count()) - } - ] - }, context_instance=RequestContext(request)) + } + if extra_context: + context.update(extra_context) + + queryset = queryset if not (queryset is None) else Tag.objects.all() + + try: + Permission.objects.check_permissions(request.user, [PERMISSION_TAG_VIEW]) + except PermissionDenied: + queryset = AccessEntry.objects.filter_objects_by_access(PERMISSION_TAG_VIEW, request.user, queryset) + + context['object_list'] = queryset + + return render_to_response('generic_list.html', + context, + context_instance=RequestContext(request) + ) def tag_delete(request, tag_id=None, tag_id_list=None): - Permission.objects.check_permissions(request.user, [PERMISSION_TAG_DELETE]) post_action_redirect = None if tag_id: @@ -167,6 +126,11 @@ def tag_delete(request, tag_id=None, tag_id_list=None): else: messages.error(request, _(u'Must provide at least one tag.')) return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/')) + + try: + Permission.objects.check_permissions(request.user, [PERMISSION_TAG_DELETE]) + except PermissionDenied: + tags = AccessEntry.objects.filter_objects_by_access(PERMISSION_TAG_DELETE, request.user, tags) previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/'))) next = request.POST.get('next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', '/'))) @@ -209,9 +173,13 @@ def tag_multiple_delete(request): def tag_edit(request, tag_id): - Permission.objects.check_permissions(request.user, [PERMISSION_TAG_EDIT]) tag = get_object_or_404(Tag, pk=tag_id) + try: + Permission.objects.check_permissions(request.user, [PERMISSION_TAG_EDIT]) + except PermissionDenied: + AccessEntry.objects.check_access(PERMISSION_TAG_EDIT, request.user, tag) + if request.method == 'POST': form = TagForm(request.POST) if form.is_valid(): @@ -253,24 +221,29 @@ def tag_tagged_item_list(request, tag_id): def document_tags(request, document_id): - Permission.objects.check_permissions(request.user, [PERMISSION_TAG_VIEW]) document = get_object_or_404(Document, pk=document_id) - return render_to_response('generic_list.html', { - 'title': _(u'tags for: %s') % document, - 'object_list': document.tags.all(), - 'hide_link': True, - 'navigation_object_links': [tag_tagged_item_list_link], + try: + Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW]) + except PermissionDenied: + AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document) + + context = { 'object': document, 'document': document, - 'disable_auto_focus': True, - 'multi_select_as_buttons': True, - }, - context_instance=RequestContext(request)) + 'title': _(u'tags for: %s') % document, + } + + return tag_list(request, queryset=document.tags.all(), extra_context=context) def tag_remove(request, document_id, tag_id=None, tag_id_list=None): - Permission.objects.check_permissions(request.user, [PERMISSION_TAG_REMOVE]) + document = get_object_or_404(Document, pk=document_id) + + try: + Permission.objects.check_permissions(request.user, [PERMISSION_TAG_REMOVE]) + except PermissionDenied: + AccessEntry.objects.check_access(PERMISSION_TAG_REMOVE, request.user, document) post_action_redirect = None @@ -282,8 +255,6 @@ def tag_remove(request, document_id, tag_id=None, tag_id_list=None): messages.error(request, _(u'Must provide at least one tag.')) return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/')) - document = get_object_or_404(Document, pk=document_id) - previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/'))) next = request.POST.get('next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', '/'))) @@ -317,3 +288,28 @@ def tag_remove(request, document_id, tag_id=None, tag_id_list=None): def tag_multiple_remove(request, document_id): return tag_remove(request, document_id=document_id, tag_id_list=request.GET.get('id_list', [])) + + +def tag_acl_list(request, tag_pk): + tag = get_object_or_404(Tag, pk=tag_pk) + logger.debug('tag: %s' % tag) + + return acl_list_for( + request, + tag, + extra_context={ + 'object': tag, + } + ) + + +def tag_new_holder(request, tag_pk): + tag = get_object_or_404(Tag, pk=tag_pk) + return acl_new_holder_for( + request, + tag, + extra_context={ + #'tag': tag, + 'object': tag, + } + ) diff --git a/apps/tags/widgets.py b/apps/tags/widgets.py index ab1b6762b1..b9dcb0266b 100644 --- a/apps/tags/widgets.py +++ b/apps/tags/widgets.py @@ -3,9 +3,9 @@ from django.utils.safestring import mark_safe def get_tags_inline_widget(document): - """ + ''' A tag widget that includes the total tag count for a given document - """ + ''' tags_template = [] tag_count = document.tags.count() if tag_count: @@ -20,10 +20,10 @@ def get_tags_inline_widget(document): def get_tags_inline_widget_simple(document): - """ + ''' A tag widget that only displayes the rectangular colored boxes for a given document - """ + ''' tags_template = [] tag_count = document.tags.count()