Add cascade permission checks for links. Avoid allowing users to reach a empty views because they don't access to any of the view's objects. Apply link permission cascade checks to the message of the day, indexing and parsing, setup link.

Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
This commit is contained in:
Roberto Rosario
2018-08-22 00:14:21 -04:00
parent 8e39016f12
commit bf3723ae24
6 changed files with 71 additions and 7 deletions

View File

@@ -58,6 +58,11 @@
- Renamed setting LOCK_MANAGER_DEFAULT_BACKEND to LOCK_MANAGER_BACKEND. - Renamed setting LOCK_MANAGER_DEFAULT_BACKEND to LOCK_MANAGER_BACKEND.
- Add help texts to more setting options. - Add help texts to more setting options.
- Add ACL support for metadata types. - Add ACL support for metadata types.
- Add cascade permission checks for links. Avoid allowing users
to reach a empty views because they don't access to any of
the view's objects.
- Apply link permission cascade checks to the message of the day,
indexing and parsing, setup link.
3.0.1 (2018-07-08) 3.0.1 (2018-07-08)
================= =================

View File

@@ -2,7 +2,7 @@ from __future__ import unicode_literals
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from navigation import Link from navigation import Link, get_cascade_condition
from .icons import ( from .icons import (
icon_document_index_list, icon_index, icon_rebuild_index_instances icon_document_index_list, icon_index, icon_rebuild_index_instances
@@ -10,6 +10,7 @@ from .icons import (
from .permissions import ( from .permissions import (
permission_document_indexing_create, permission_document_indexing_edit, permission_document_indexing_create, permission_document_indexing_edit,
permission_document_indexing_delete, permission_document_indexing_rebuild, permission_document_indexing_delete, permission_document_indexing_rebuild,
permission_document_indexing_view
) )
@@ -26,7 +27,11 @@ link_index_main_menu = Link(
view='indexing:index_list' view='indexing:index_list'
) )
link_index_setup = Link( link_index_setup = Link(
icon_class=icon_index, text=_('Indexes'), condition=get_cascade_condition(
app_label='document_indexing', model_name='Index',
object_permission=permission_document_indexing_view,
view_permission=permission_document_indexing_create,
), icon_class=icon_index, text=_('Indexes'),
view='indexing:index_setup_list' view='indexing:index_setup_list'
) )
link_index_setup_list = Link( link_index_setup_list = Link(

View File

@@ -2,7 +2,7 @@ from __future__ import unicode_literals
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from navigation import Link from navigation import Link, get_cascade_condition
from .icons import ( from .icons import (
icon_document_content, icon_document_parsing_errors_list, icon_document_content, icon_document_parsing_errors_list,
@@ -44,7 +44,11 @@ link_document_type_parsing_settings = Link(
view='document_parsing:document_type_parsing_settings', view='document_parsing:document_type_parsing_settings',
) )
link_document_type_submit = Link( link_document_type_submit = Link(
icon_class=icon_document_type_submit, text=_('Parse documents per type'), condition=get_cascade_condition(
app_label='documents', model_name='DocumentType',
object_permission=permission_document_type_parsing_setup
), icon_class=icon_document_type_submit,
text=_('Parse documents per type'),
view='document_parsing:document_type_submit' view='document_parsing:document_type_submit'
) )
link_error_list = Link( link_error_list = Link(

View File

@@ -1,15 +1,19 @@
from __future__ import absolute_import, unicode_literals from __future__ import absolute_import, unicode_literals
from django.apps import apps
from django.core.exceptions import PermissionDenied
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from navigation import Link from navigation import Link, get_cascade_condition
from permissions import Permission
from .icons import icon_message_list from .icons import icon_message_list
from .permissions import ( from .permissions import (
permission_message_create, permission_message_delete, permission_message_create, permission_message_delete,
permission_message_edit, permission_message_edit, permission_message_view
) )
link_message_create = Link( link_message_create = Link(
permissions=(permission_message_create,), text=_('Create message'), permissions=(permission_message_create,), text=_('Create message'),
view='motd:message_create' view='motd:message_create'
@@ -23,6 +27,10 @@ link_message_edit = Link(
view='motd:message_edit' view='motd:message_edit'
) )
link_message_list = Link( link_message_list = Link(
icon_class=icon_message_list, text=_('Message of the day'), condition=get_cascade_condition(
app_label='motd', model_name='Message',
object_permission=permission_message_view,
view_permission=permission_message_create,
), icon_class=icon_message_list, text=_('Message of the day'),
view='motd:message_list' view='motd:message_list'
) )

View File

@@ -1,5 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from .classes import Link, Menu, SourceColumn # NOQA from .classes import Link, Menu, SourceColumn # NOQA
from .utils import get_cascade_condition # NOQA
default_app_config = 'navigation.apps.NavigationApp' default_app_config = 'navigation.apps.NavigationApp'

View File

@@ -0,0 +1,41 @@
from __future__ import absolute_import, unicode_literals
from django.apps import apps
from django.core.exceptions import PermissionDenied
from django.utils.translation import ugettext_lazy as _
from permissions import Permission
def get_cascade_condition(app_label, model_name, object_permission, view_permission=None):
"""
Return a function that first checks to see if the user has the view
permission. If not, then filters the objects with the object permission
and return True if there is at least one item in the filtered queryset.
This is used to avoid showing a link that ends up in a view with an
empty results set.
"""
def condition(context):
AccessControlList = apps.get_model(
app_label='acls', model_name='AccessControlList'
)
Model = apps.get_model(app_label=app_label, model_name=model_name)
if view_permission:
try:
Permission.check_permissions(
requester=context.request.user,
permissions=(view_permission,)
)
except PermissionDenied:
pass
else:
return True
queryset = AccessControlList.objects.filter_by_access(
permission=object_permission, user=context.request.user,
queryset=Model.objects.all()
)
return queryset.count() > 0
return condition