Merge branch 'feature/comment_permissions' into development

This commit is contained in:
Roberto Rosario
2012-01-03 18:49:21 -04:00
6 changed files with 58 additions and 55 deletions

View File

@@ -95,11 +95,20 @@ class AccessEntryManager(models.Manager):
raise PermissionDenied(ugettext(u'Insufficient access.'))
def get_allowed_class_objects(self, permission, actor, cls):
def get_allowed_class_objects(self, permission, actor, cls, related=None):
logger.debug('related: %s' % related)
actor_type = ContentType.objects.get_for_model(actor)
content_type = ContentType.objects.get_for_model(cls)
return (obj.content_object for obj in self.model.objects.filter(holder_type=actor_type, holder_id=actor.pk, content_type=content_type, permission=permission.get_stored_permission))
if related:
master_list = [obj.content_object for obj in self.model.objects.select_related().filter(holder_type=actor_type, holder_id=actor.pk, permission=permission.get_stored_permission)]
logger.debug('master_list: %s' % master_list)
# TODO: update to use Q objects and check performance diff
# kwargs = {'%s__in' % related: master_list}
# Q(**kwargs)
return (obj for obj in cls.objects.all() if getattr(obj, related) in master_list)
else:
return (obj.content_object for obj in self.model.objects.filter(holder_type=actor_type, holder_id=actor.pk, content_type=content_type, permission=permission.get_stored_permission))
def get_acl_url(self, obj):
content_type = ContentType.objects.get_for_model(obj)
@@ -132,7 +141,7 @@ class AccessEntryManager(models.Manager):
content_type = ContentType.objects.get_for_model(obj)
return (access.permission for access in self.model.objects.filter(content_type=content_type, object_id=obj.pk, holder_type=actor_type, holder_id=actor.pk))
def filter_objects_by_access(self, permission, actor, object_list, exception_on_empty=False):
def filter_objects_by_access(self, permission, actor, object_list, exception_on_empty=False, related=None):
logger.debug('exception_on_empty: %s' % exception_on_empty)
logger.debug('object_list: %s' % object_list)
@@ -150,7 +159,7 @@ class AccessEntryManager(models.Manager):
try:
# Try to process as a QuerySet
qs = object_list.filter(pk__in=[obj.pk for obj in self.get_allowed_class_objects(permission, actor, object_list[0])])
qs = object_list.filter(pk__in=[obj.pk for obj in self.get_allowed_class_objects(permission, actor, object_list[0].__class__, related)])
logger.debug('qs: %s' % qs)
if qs.count() == 0 and exception_on_empty == True:
@@ -158,13 +167,13 @@ class AccessEntryManager(models.Manager):
return qs
except AttributeError:
# Fallback to a list filtered list
obj_list = list(set(object_list) & set(self.get_allowed_class_objects(permission, actor, object_list[0])))
logger.debug('obj_list: %s' % obj_list)
if len(obj_list) == 0 and exception_on_empty == True:
# Fallback to a filtered list
object_list = list(set(object_list) & set(self.get_allowed_class_objects(permission, actor, object_list[0].__class__, related)))
logger.debug('object_list: %s' % object_list)
if len(object_list) == 0 and exception_on_empty == True:
raise PermissionDenied
return obj_list
return object_list
class DefaultAccessEntryManager(models.Manager):

View File

@@ -8,20 +8,19 @@ from django.contrib.contenttypes import generic
from navigation.api import register_links, register_model_list_columns
from permissions.models import PermissionNamespace, Permission
from common.utils import encapsulate
from acls.api import class_permissions
from documents.models import Document
if 'django.contrib.comments' not in settings.INSTALLED_APPS:
raise Exception('This app depends on the django.contrib.comments app.')
from .permissions import (PERMISSION_COMMENT_CREATE,
PERMISSION_COMMENT_DELETE, PERMISSION_COMMENT_EDIT,
PERMISSION_COMMENT_VIEW)
PERMISSION_COMMENT_DELETE, PERMISSION_COMMENT_VIEW)
comment_delete = {'text': _('delete'), 'view': 'comment_delete', 'args': 'object.pk', 'famfam': 'comment_delete', 'permissions': [PERMISSION_COMMENT_DELETE]}
comment_multiple_delete = {'text': _('delete'), 'view': 'comment_multiple_delete', 'args': 'object.pk', 'famfam': 'comments_delete', 'permissions': [PERMISSION_COMMENT_DELETE]}
comment_add = {'text': _('add comment'), 'view': 'comment_add', 'args': 'object.pk', 'famfam': 'comment_add', 'permissions': [PERMISSION_COMMENT_CREATE]}
comments_for_object = {'text': _('comments'), 'view': 'comments_for_object', 'args': 'object.pk', 'famfam': 'comments', 'permissions': [PERMISSION_COMMENT_VIEW], 'children_view_regex': ['comment']}
comments_for_document = {'text': _('comments'), 'view': 'comments_for_document', 'args': 'object.pk', 'famfam': 'comments', 'permissions': [PERMISSION_COMMENT_VIEW], 'children_view_regex': ['comment']}
register_model_list_columns(Comment, [
{
@@ -38,9 +37,9 @@ register_model_list_columns(Comment, [
}
])
register_links(['comments_for_object', 'comment_add', 'comment_delete', 'comment_multiple_delete'], [comment_add], menu_name='sidebar')
register_links(['comments_for_document', 'comment_add', 'comment_delete', 'comment_multiple_delete'], [comment_add], menu_name='sidebar')
register_links(Comment, [comment_delete])
register_links(Document, [comments_for_object], menu_name='form_header')
register_links(Document, [comments_for_document], menu_name='form_header')
Document.add_to_class(
'comments',
@@ -50,3 +49,9 @@ Document.add_to_class(
object_id_field='object_pk'
)
)
class_permissions(Document, [
PERMISSION_COMMENT_CREATE,
PERMISSION_COMMENT_DELETE,
PERMISSION_COMMENT_VIEW
])

View File

@@ -8,5 +8,4 @@ comments_namespace = PermissionNamespace('comments', _(u'Comments'))
PERMISSION_COMMENT_CREATE = Permission.objects.register(comments_namespace, 'comment_create', _(u'Create new comments'))
PERMISSION_COMMENT_DELETE = Permission.objects.register(comments_namespace, 'comment_delete', _(u'Delete comments'))
PERMISSION_COMMENT_EDIT = Permission.objects.register(comments_namespace, 'comment_edit', _(u'Edit comments'))
PERMISSION_COMMENT_VIEW = Permission.objects.register(comments_namespace, 'comment_view', _(u'View comments'))

View File

@@ -1,8 +1,8 @@
from django.conf.urls.defaults import patterns, url
urlpatterns = patterns('document_comments.views',
url(r'^(?P<comment_id>\d+)/delete/$', 'comment_delete', (), 'comment_delete'),
url(r'^multiple/delete/$', 'comment_multiple_delete', (), 'comment_multiple_delete'),
url(r'^add_to_document/(?P<document_id>\d+)/$', 'comment_add', (), 'comment_add'),
url(r'^for/object/(?P<document_id>\d+)/$', 'comments_for_object', (), 'comments_for_object'),
url(r'^comment/(?P<comment_id>\d+)/delete/$', 'comment_delete', (), 'comment_delete'),
url(r'^comment/multiple/delete/$', 'comment_multiple_delete', (), 'comment_multiple_delete'),
url(r'^(?P<document_id>\d+)/comment/add/$', 'comment_add', (), 'comment_add'),
url(r'^(?P<document_id>\d+)/comment/list/$', 'comments_for_document', (), 'comments_for_document'),
)

View File

@@ -1,24 +0,0 @@
from __future__ import absolute_import
from django.utils.translation import ugettext_lazy as _
from django.contrib.comments.models import Comment
from . import comment_delete
def get_comments_subtemplate(obj):
"""
Return all the settings to render a subtemplate containing an
object's comments
"""
return {
'name': 'generic_list_subtemplate.html',
'context': {
'title': _(u'comments'),
'object_list': Comment.objects.for_model(obj).order_by('-submit_date'),
'hide_link': True,
'hide_object': True,
'navigation_object_links': [comment_delete],
'scrollable_content': True,
'scrollable_content_height': '200px',
}
}

View File

@@ -8,27 +8,33 @@ from django.template import RequestContext
from django.contrib import messages
from django.contrib.contenttypes.models import ContentType
from django.contrib.sites.models import Site
from django.core.exceptions import PermissionDenied
from acls.models import AccessEntry
from permissions.models import Permission
from documents.models import Document
from .permissions import (PERMISSION_COMMENT_CREATE,
PERMISSION_COMMENT_DELETE, PERMISSION_COMMENT_EDIT,
PERMISSION_COMMENT_VIEW)
PERMISSION_COMMENT_DELETE, PERMISSION_COMMENT_VIEW)
from .forms import CommentForm
def comment_delete(request, comment_id=None, comment_id_list=None):
Permission.objects.check_permissions(request.user, [PERMISSION_COMMENT_DELETE])
post_action_redirect = None
if comment_id:
comments = [get_object_or_404(Comment, pk=comment_id)]
elif comment_id_list:
comments = [get_object_or_404(Comment, pk=comment_id) for comment_id in comment_id_list.split(',')]
else:
try:
Permission.objects.check_permissions(request.user, [PERMISSION_COMMENT_DELETE])
except PermissionDenied:
comments = AccessEntry.objects.filter_objects_by_access(PERMISSION_COMMENT_DELETE, request.user, comments, related='content_object')
if not comments:
messages.error(request, _(u'Must provide at least one comment.'))
return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
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', '/')))
@@ -69,9 +75,13 @@ def comment_multiple_delete(request):
def comment_add(request, document_id):
Permission.objects.check_permissions(request.user, [PERMISSION_COMMENT_CREATE])
document = get_object_or_404(Document, pk=document_id)
try:
Permission.objects.check_permissions(request.user, [PERMISSION_COMMENT_CREATE])
except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_COMMENT_CREATE, request.user, document)
post_action_redirect = None
next = request.POST.get('next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', '/')))
@@ -99,16 +109,20 @@ def comment_add(request, document_id):
}, context_instance=RequestContext(request))
def comments_for_object(request, document_id):
def comments_for_document(request, document_id):
'''
Show a list of all the comments related to the passed object
'''
Permission.objects.check_permissions(request.user, [PERMISSION_COMMENT_VIEW])
document = get_object_or_404(Document, pk=document_id)
try:
Permission.objects.check_permissions(request.user, [PERMISSION_COMMENT_VIEW])
except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_COMMENT_VIEW, request.user, document)
return render_to_response('generic_list.html', {
'object': document,
'access_object': document,
'title': _(u'comments: %s') % document,
'object_list': Comment.objects.for_model(document).order_by('-submit_date'),
'hide_link': True,