Files
mayan-edms/mayan/apps/acls/views.py
2015-01-19 04:06:40 -04:00

639 lines
25 KiB
Python

from __future__ import absolute_import, unicode_literals
import logging
from json import loads
from django.contrib import messages
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
from django.core.urlresolvers import reverse
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render_to_response
from django.template import RequestContext
from django.utils.http import urlencode
from django.utils.translation import ugettext_lazy as _
from common.utils import encapsulate
from common.widgets import two_state_template
from permissions.models import Permission
from .api import get_class_permissions_for
from .classes import (AccessHolder, AccessObject, AccessObjectClass,
ClassAccessHolder)
from .forms import ClassHolderSelectionForm, HolderSelectionForm
from .models import AccessEntry, DefaultAccessEntry
from .permissions import (ACLS_EDIT_ACL, ACLS_CLASS_EDIT_ACL,
ACLS_CLASS_VIEW_ACL, ACLS_VIEW_ACL)
from .widgets import object_w_content_type_icon
logger = logging.getLogger(__name__)
def _permission_titles(permission_list):
return ', '.join([unicode(permission) for permission in permission_list])
def acl_list_for(request, obj, extra_context=None):
try:
Permission.objects.check_permissions(request.user, [ACLS_VIEW_ACL])
except PermissionDenied:
AccessEntry.objects.check_access(ACLS_VIEW_ACL, request.user, obj)
logger.debug('obj: %s', obj)
context = {
'object_list': AccessEntry.objects.get_holders_for(obj),
'title': _('Access control lists for: %s' % obj),
'extra_columns': [
{'name': _('Holder'), 'attribute': encapsulate(lambda x: object_w_content_type_icon(x.source_object))},
{'name': _('Permissions'), 'attribute': encapsulate(lambda x: _permission_titles(AccessEntry.objects.get_holder_permissions_for(obj, x.source_object, db_only=True)))},
],
'hide_object': True,
'access_object': AccessObject.encapsulate(obj),
'object': obj,
'navigation_object_list': [
{'object': 'object'},
{'object': 'access_object'}
],
}
if extra_context:
context.update(extra_context)
return render_to_response('main/generic_list.html', context,
context_instance=RequestContext(request))
def acl_list(request, app_label, model_name, object_id):
ct = get_object_or_404(ContentType, app_label=app_label, model=model_name)
obj = get_object_or_404(ct.get_object_for_this_type, pk=object_id)
return acl_list_for(request, obj)
def acl_detail(request, access_object_gid, holder_object_gid):
try:
holder = AccessHolder.get(gid=holder_object_gid)
access_object = AccessObject.get(gid=access_object_gid)
except ObjectDoesNotExist:
raise Http404
# return acl_detail_for(request, holder.source_object, access_object.source_object)
return acl_detail_for(request, holder, access_object)
def acl_detail_for(request, actor, obj):
try:
Permission.objects.check_permissions(request.user, [ACLS_VIEW_ACL])
except PermissionDenied:
AccessEntry.objects.check_accesses([ACLS_VIEW_ACL], actor, obj)
permission_list = get_class_permissions_for(obj.source_object)
# TODO : get all globally assigned permission, new function get_permissions_for_holder (roles aware)
subtemplates_list = [
{
'name': 'main/generic_list_subtemplate.html',
'context': {
'title': _('Permissions available to: %(actor)s for %(obj)s' % {
'actor': actor,
'obj': obj
}
),
'object_list': permission_list,
'extra_columns': [
{'name': _('Namespace'), 'attribute': 'namespace'},
{'name': _('Label'), 'attribute': 'label'},
{
'name': _('Has permission'),
'attribute': encapsulate(lambda permission: two_state_template(AccessEntry.objects.has_access(permission, actor, obj, db_only=True)))
},
],
'hide_object': True,
}
},
]
context = {
'object': obj.source_object,
'subtemplates_list': subtemplates_list,
'multi_select_item_properties': {
'permission_pk': lambda x: x.pk,
'holder_gid': lambda x: actor.gid,
'object_gid': lambda x: obj.gid,
},
'access_object': obj,
'navigation_object_list': [
{'object': 'object'},
{'object': 'access_object'}
],
}
return render_to_response('main/generic_detail.html', context,
context_instance=RequestContext(request))
def acl_grant(request):
items_property_list = loads(request.GET.get('items_property_list', []))
next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', reverse('main:home'))))
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', reverse('main:home'))))
items = {}
title_suffix = []
navigation_object = None
navigation_object_count = 0
for item_properties in items_property_list:
try:
permission = Permission.objects.get({'pk': item_properties['permission_pk']})
except Permission.DoesNotExist:
raise Http404
try:
requester = AccessHolder.get(gid=item_properties['holder_gid'])
access_object = AccessObject.get(gid=item_properties['object_gid'])
except ObjectDoesNotExist:
raise Http404
try:
Permission.objects.check_permissions(request.user, [ACLS_EDIT_ACL])
except PermissionDenied:
try:
AccessEntry.objects.check_access(ACLS_EDIT_ACL, request.user, access_object)
except PermissionDenied:
raise
else:
items.setdefault(requester, {})
items[requester].setdefault(access_object, [])
items[requester][access_object].append(permission)
navigation_object = access_object
navigation_object_count += 1
else:
items.setdefault(requester, {})
items[requester].setdefault(access_object, [])
items[requester][access_object].append(permission)
navigation_object = access_object
navigation_object_count += 1
for requester, obj_ps in items.items():
for obj, ps in obj_ps.items():
title_suffix.append(_(', ').join(['"%s"' % unicode(p) for p in ps]))
title_suffix.append(_(' for %s') % obj)
title_suffix.append(_(' to %s') % requester)
if len(items_property_list) == 1:
title_prefix = _('Are you sure you wish to grant the permission %(title_suffix)s?')
else:
title_prefix = _('Are you sure you wish to grant the permissions %(title_suffix)s?')
if request.method == 'POST':
for requester, object_permissions in items.items():
for obj, permissions in object_permissions.items():
for permission in permissions:
if AccessEntry.objects.grant(permission, requester.source_object, obj.source_object):
messages.success(request, _('Permission "%(permission)s" granted to %(actor)s for %(object)s.') % {
'permission': permission,
'actor': requester,
'object': obj
})
else:
messages.warning(request, _('%(actor)s, already had the permission "%(permission)s" granted for %(object)s.') % {
'actor': requester,
'permission': permission,
'object': obj,
})
return HttpResponseRedirect(next)
context = {
'delete_view': True,
'previous': previous,
'next': next,
}
context['title'] = title_prefix % {
'title_suffix': ''.join(title_suffix),
}
logger.debug('navigation_object_count: %d', navigation_object_count)
logger.debug('navigation_object: %s', navigation_object)
if navigation_object_count == 1:
context['object'] = navigation_object.source_object
return render_to_response('main/generic_confirm.html', context,
context_instance=RequestContext(request))
def acl_revoke(request):
items_property_list = loads(request.GET.get('items_property_list', []))
next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', reverse('main:home'))))
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', reverse('main:home'))))
items = {}
title_suffix = []
navigation_object = None
navigation_object_count = 0
for item_properties in items_property_list:
try:
permission = Permission.objects.get({'pk': item_properties['permission_pk']})
except Permission.DoesNotExist:
raise Http404
try:
requester = AccessHolder.get(gid=item_properties['holder_gid'])
access_object = AccessObject.get(gid=item_properties['object_gid'])
except ObjectDoesNotExist:
raise Http404
try:
Permission.objects.check_permissions(request.user, [ACLS_EDIT_ACL])
except PermissionDenied:
try:
AccessEntry.objects.check_access(ACLS_EDIT_ACL, request.user, access_object)
except PermissionDenied:
raise
else:
items.setdefault(requester, {})
items[requester].setdefault(access_object, [])
items[requester][access_object].append(permission)
navigation_object = access_object
navigation_object_count += 1
else:
items.setdefault(requester, {})
items[requester].setdefault(access_object, [])
items[requester][access_object].append(permission)
navigation_object = access_object
navigation_object_count += 1
for requester, obj_ps in items.items():
for obj, ps in obj_ps.items():
title_suffix.append(_(', ').join(['"%s"' % unicode(p) for p in ps]))
title_suffix.append(_(' for %s') % obj)
title_suffix.append(_(' from %s') % requester)
if len(items_property_list) == 1:
title_prefix = _('Are you sure you wish to revoke the permission %(title_suffix)s?')
else:
title_prefix = _('Are you sure you wish to revoke the permissions %(title_suffix)s?')
if request.method == 'POST':
for requester, object_permissions in items.items():
for obj, permissions in object_permissions.items():
for permission in permissions:
if AccessEntry.objects.revoke(permission, requester.source_object, obj.source_object):
messages.success(request, _('Permission "%(permission)s" revoked of %(actor)s for %(object)s.') % {
'permission': permission,
'actor': requester,
'object': obj
})
else:
messages.warning(request, _('%(actor)s, didn\'t had the permission "%(permission)s" for %(object)s.') % {
'actor': requester,
'permission': permission,
'object': obj,
})
return HttpResponseRedirect(next)
context = {
'delete_view': True,
'previous': previous,
'next': next,
}
context['title'] = title_prefix % {
'title_suffix': ''.join(title_suffix),
}
logger.debug('navigation_object_count: %d', navigation_object_count)
logger.debug('navigation_object: %s', navigation_object)
if navigation_object_count == 1:
context['object'] = navigation_object.source_object
return render_to_response('main/generic_confirm.html', context,
context_instance=RequestContext(request))
def acl_new_holder_for(request, obj, extra_context=None, navigation_object=None):
try:
Permission.objects.check_permissions(request.user, [ACLS_EDIT_ACL])
except PermissionDenied:
AccessEntry.objects.check_access(ACLS_EDIT_ACL, request.user, obj)
if request.method == 'POST':
form = HolderSelectionForm(request.POST)
if form.is_valid():
try:
access_object = AccessObject.encapsulate(obj)
access_holder = AccessHolder.get(form.cleaned_data['holder_gid'])
query_string = {'navigation_object': navigation_object}
return HttpResponseRedirect(
'%s?%s' % (
reverse('acls:acl_detail', args=[access_object.gid, access_holder.gid]),
urlencode(query_string)
)
)
except ObjectDoesNotExist:
raise Http404
else:
form = HolderSelectionForm()
context = {
'form': form,
'title': _('Add new holder for: %s') % obj,
'submit_label': _('Select'),
'submit_icon_famfam': 'tick',
'object': obj,
'access_object': AccessObject.encapsulate(obj),
'navigation_object_list': [
{'object': 'object'},
{'object': 'access_object'},
],
}
if extra_context:
context.update(extra_context)
return render_to_response('main/generic_form.html', context,
context_instance=RequestContext(request))
def acl_holder_new(request, access_object_gid):
try:
access_object = AccessObject.get(gid=access_object_gid)
except ObjectDoesNotExist:
raise Http404
return acl_new_holder_for(request, access_object.source_object) # , extra_context={'access_object': access_object})
# Setup views
def acl_setup_valid_classes(request):
Permission.objects.check_permissions(request.user, [ACLS_CLASS_VIEW_ACL])
context = {
'object_list': DefaultAccessEntry.get_classes(),
'title': _('Classes'),
'extra_columns': [
{'name': _('Class'), 'attribute': encapsulate(lambda x: object_w_content_type_icon(x.source_object))},
],
'hide_object': True,
}
return render_to_response('main/generic_list.html', context,
context_instance=RequestContext(request))
def acl_class_acl_list(request, access_object_class_gid):
logger.debug('access_object_class_gid: %s', access_object_class_gid)
Permission.objects.check_permissions(request.user, [ACLS_CLASS_VIEW_ACL])
access_object_class = AccessObjectClass.get(gid=access_object_class_gid)
logger.debug('access_object_class: %s', access_object_class)
context = {
'object_list': DefaultAccessEntry.objects.get_holders_for(access_object_class.source_object),
'title': _('Default access control lists for class: %s') % access_object_class,
'extra_columns': [
{'name': _('Holder'), 'attribute': encapsulate(lambda x: object_w_content_type_icon(x.source_object))},
{'name': _('Permissions'), 'attribute': encapsulate(lambda x: _permission_titles(DefaultAccessEntry.objects.get_holder_permissions_for(access_object_class.source_object, x.source_object)))},
],
'hide_object': True,
'access_object_class': access_object_class,
'object': access_object_class,
}
return render_to_response('main/generic_list.html', context,
context_instance=RequestContext(request))
def acl_class_acl_detail(request, access_object_class_gid, holder_object_gid):
Permission.objects.check_permissions(request.user, [ACLS_CLASS_VIEW_ACL])
try:
actor = AccessHolder.get(gid=holder_object_gid)
access_object_class = AccessObjectClass.get(gid=access_object_class_gid)
except ObjectDoesNotExist:
raise Http404
permission_list = get_class_permissions_for(access_object_class.content_type.model_class())
# TODO : get all globally assigned permission, new function get_permissions_for_holder (roles aware)
subtemplates_list = [
{
'name': 'main/generic_list_subtemplate.html',
'context': {
'title': _('Permissions available to: %(actor)s for class %(class)s' % {
'actor': actor,
'class': access_object_class
}),
'object_list': permission_list,
'extra_columns': [
{'name': _('Namespace'), 'attribute': 'namespace'},
{'name': _('Label'), 'attribute': 'label'},
{
'name': _('Has permission'),
'attribute': encapsulate(lambda x: two_state_template(DefaultAccessEntry.objects.has_access(x, actor.source_object, access_object_class.source_object)))
},
],
'hide_object': True,
}
},
]
return render_to_response('main/generic_detail.html', {
'object': access_object_class,
'subtemplates_list': subtemplates_list,
'multi_select_item_properties': {
'permission_pk': lambda x: x.pk,
'holder_gid': lambda x: actor.gid,
'access_object_class_gid': lambda x: access_object_class.gid,
},
}, context_instance=RequestContext(request))
def acl_class_new_holder_for(request, access_object_class_gid):
Permission.objects.check_permissions(request.user, [ACLS_CLASS_EDIT_ACL])
access_object_class = AccessObjectClass.get(gid=access_object_class_gid)
if request.method == 'POST':
form = ClassHolderSelectionForm(request.POST)
if form.is_valid():
try:
access_holder = ClassAccessHolder.get(form.cleaned_data['holder_gid'])
return HttpResponseRedirect(reverse('acls:acl_class_acl_detail', args=[access_object_class.gid, access_holder.gid]))
except ObjectDoesNotExist:
raise Http404
else:
form = ClassHolderSelectionForm(current_holders=DefaultAccessEntry.objects.get_holders_for(access_object_class))
context = {
'form': form,
'title': _('Add new holder for class: %s') % unicode(access_object_class),
'object': access_object_class,
'submit_label': _('Select'),
'submit_icon_famfam': 'tick'
}
return render_to_response('main/generic_form.html', context,
context_instance=RequestContext(request))
def acl_class_multiple_grant(request):
Permission.objects.check_permissions(request.user, [ACLS_CLASS_EDIT_ACL])
items_property_list = loads(request.GET.get('items_property_list', []))
next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', reverse('main:home'))))
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', reverse('main:home'))))
items = {}
title_suffix = []
navigation_object = None
navigation_object_count = 0
for item_properties in items_property_list:
try:
permission = Permission.objects.get({'pk': item_properties['permission_pk']})
except Permission.DoesNotExist:
raise Http404
try:
requester = AccessHolder.get(gid=item_properties['holder_gid'])
access_object_class = AccessObjectClass.get(gid=item_properties['access_object_class_gid'])
except ObjectDoesNotExist:
raise Http404
items.setdefault(requester, {})
items[requester].setdefault(access_object_class, [])
items[requester][access_object_class].append(permission)
navigation_object = access_object_class
navigation_object_count += 1
for requester, obj_ps in items.items():
for obj, ps in obj_ps.items():
title_suffix.append(_(', ').join(['"%s"' % unicode(p) for p in ps]))
title_suffix.append(_(' for %s') % obj)
title_suffix.append(_(' to %s') % requester)
if len(items_property_list) == 1:
title_prefix = _('Are you sure you wish to grant the permission %(title_suffix)s?')
else:
title_prefix = _('Are you sure you wish to grant the permissions %(title_suffix)s?')
if request.method == 'POST':
for requester, object_permissions in items.items():
for obj, permissions in object_permissions.items():
for permission in permissions:
if DefaultAccessEntry.objects.grant(permission, requester.source_object, obj.source_object):
messages.success(request, _('Permission "%(permission)s" granted to %(actor)s for %(object)s.') % {
'permission': permission,
'actor': requester,
'object': obj
})
else:
messages.warning(request, _('%(actor)s, already had the permission "%(permission)s" granted for %(object)s.') % {
'actor': requester,
'permission': permission,
'object': obj,
})
return HttpResponseRedirect(next)
context = {
'delete_view': True,
'previous': previous,
'next': next,
}
context['title'] = title_prefix % {
'title_suffix': ''.join(title_suffix),
}
logger.debug('navigation_object_count: %d', navigation_object_count)
logger.debug('navigation_object: %s', navigation_object)
if navigation_object_count == 1:
context['object'] = navigation_object
return render_to_response('main/generic_confirm.html', context,
context_instance=RequestContext(request))
def acl_class_multiple_revoke(request):
Permission.objects.check_permissions(request.user, [ACLS_CLASS_EDIT_ACL])
items_property_list = loads(request.GET.get('items_property_list', []))
next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', reverse('main:home'))))
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', reverse('main:home'))))
items = {}
title_suffix = []
navigation_object = None
navigation_object_count = 0
for item_properties in items_property_list:
try:
permission = Permission.objects.get({'pk': item_properties['permission_pk']})
except Permission.DoesNotExist:
raise Http404
try:
requester = AccessHolder.get(gid=item_properties['holder_gid'])
access_object_class = AccessObjectClass.get(gid=item_properties['access_object_class_gid'])
except ObjectDoesNotExist:
raise Http404
items.setdefault(requester, {})
items[requester].setdefault(access_object_class, [])
items[requester][access_object_class].append(permission)
navigation_object = access_object_class
navigation_object_count += 1
for requester, obj_ps in items.items():
for obj, ps in obj_ps.items():
title_suffix.append(_(', ').join(['"%s"' % unicode(p) for p in ps]))
title_suffix.append(_(' for %s') % obj)
title_suffix.append(_(' from %s') % requester)
if len(items_property_list) == 1:
title_prefix = _('Are you sure you wish to revoke the permission %(title_suffix)s?')
else:
title_prefix = _('Are you sure you wish to revoke the permissions %(title_suffix)s?')
if request.method == 'POST':
for requester, object_permissions in items.items():
for obj, permissions in object_permissions.items():
for permission in permissions:
if DefaultAccessEntry.objects.revoke(permission, requester.source_object, obj.source_object):
messages.success(request, _('Permission "%(permission)s" revoked of %(actor)s for %(object)s.') % {
'permission': permission,
'actor': requester,
'object': obj
})
else:
messages.warning(request, _('%(actor)s, didn\'t had the permission "%(permission)s" for %(object)s.') % {
'actor': requester,
'permission': permission,
'object': obj,
})
return HttpResponseRedirect(next)
context = {
'delete_view': True,
'previous': previous,
'next': next,
}
context['title'] = title_prefix % {
'title_suffix': ''.join(title_suffix),
}
logger.debug('navigation_object_count: %d', navigation_object_count)
logger.debug('navigation_object: %s', navigation_object)
if navigation_object_count == 1:
context['object'] = navigation_object
return render_to_response('main/generic_confirm.html', context,
context_instance=RequestContext(request))