diff --git a/docs/settings.md b/docs/settings.md index f0b3a97..03de7ca 100644 --- a/docs/settings.md +++ b/docs/settings.md @@ -8,3 +8,8 @@ `USE_DJANGO_JQUERY` : By default, `smart_selects` loads jQuery from Google's CDN. However, it can use jQuery from Django's admin area. Set `USE_DJANGO_JQUERY = True` to enable this behaviour. + +`SMART_SELECTS_CHECK_MODEL_PERMISSION` +: By default, `smart_selects` does not check if the logged-in user has access to view the chained model permissions. + Setting this option to `True` will cause `smart-selects` to check if the user has the view_model + permission in the ajax endpoint. diff --git a/smart_selects/views.py b/smart_selects/views.py index d19e946..dd34cae 100644 --- a/smart_selects/views.py +++ b/smart_selects/views.py @@ -2,6 +2,7 @@ from django.core.exceptions import PermissionDenied from django.db.models import Q from django.http import JsonResponse +from django.conf import settings from six import iteritems from django.views.decorators.cache import never_cache @@ -76,6 +77,11 @@ def filterchain(request, app, model, field, foreign_key_app_name, foreign_key_mo for f in foreign_model_class._meta.get_fields()]): raise PermissionDenied("Smart select disallowed") + # SECURITY: If SMART_SELECTS_CHECK_MODEL_PERMISSIONS is enabled, do extra model permission check + if getattr(settings, 'SMART_SELECTS_CHECK_MODEL_PERMISSION', False): + if not request.user.has_perm('{0}.view_{1}'.format(foreign_key_app_name, foreign_key_model_name)): + raise PermissionDenied("Smart select disallowed") + # filter queryset using limit_choices_to limit_choices_to = get_limit_choices_to(foreign_key_app_name, foreign_key_model_name, foreign_key_field_name) queryset = get_queryset(model_class, manager, limit_choices_to) @@ -105,6 +111,11 @@ def filterchain_all(request, app, model, field, foreign_key_app_name, for f in foreign_model_class._meta.get_fields()]): raise PermissionDenied("Smart select disallowed") + # SECURITY: If SMART_SELECTS_CHECK_MODEL_PERMISSIONS is enabled, do extra model permission check + if getattr(settings, 'SMART_SELECTS_CHECK_MODEL_PERMISSION', False): + if not request.user.has_perm('{0}.view_{1}'.format(foreign_key_app_name, foreign_key_model_name)): + raise PermissionDenied("Smart select disallowed") + # filter queryset using limit_choices_to limit_choices_to = get_limit_choices_to(foreign_key_app_name, foreign_key_model_name, foreign_key_field_name) queryset = get_queryset(model_class, limit_choices_to=limit_choices_to)