Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion django_plotly_dash/access.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

from django.contrib.auth.decorators import login_required as login_required_decorator

#pylint: disable=bare-except, unused-argument

def login_required(view_function, **kwargs):
'Wrap all DPD calls with login_required'
return login_required_decorator(view_function)
Expand All @@ -37,7 +39,7 @@ def login_required(view_function, **kwargs):
dash_view_decorator = locals()[dash_view_decorator_name]
except:
mod_name, func_name = dash_view_decorator_name.rsplit('.', 1)
if len(mod_name):
if mod_name:
mod = importlib.import_module(mod_name)
dash_view_decorator = getattr(mod, func_name)
else:
Expand Down
78 changes: 78 additions & 0 deletions docs/access_control.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
.. _access_control:

View decoration
===============

The ``django-plotly-dash`` views, as served by Django, can be wrapped with
an arbitrary decoration function. This allows the use
of the Django `login_required <https://docs.djangoproject.com/en/2.1/topics/auth/default/#the-login-required-decorator>`_ view decorator
as well as enabling more specialised and fine-grained control.

The ``login_required`` decorator
----------------------------

The ``login_required`` decorator from the Django authentication system can be used as a view decorator. A wrapper function is provided
in ``django_plotly_dash.access``.

.. code-block:: python

PLOTLY_DASH = {

...
# Name of view wrapping function
"view_decorator": "django_plotly_dash.access.login_required",
...
}

Note that the view wrapping is on all of the ``django-plotly-dash`` views.

Fine-grained control
--------------------

The view decoration function is called for each variant exposed in
the ``django_plotly_dash.urls`` file. As well as the
underlying view function, each call to the decorator is given the name of the
route, as used by ``django.urls.reverse``, the specific url fragment for the view, and a name
describing the type of view.

From this information, it is possible to implement view-specific wrapping of the view functions, and
in turn the wrapper functions can then use the request content, along with other information, to control
access to the underlying view function.

.. code-block:: python

from django.views.decorators.csrf import csrf_exempt

def check_access_permitted(request, **kwargs):
# See if access is allowed; if so return True
# This function is called on each request

...

return True

def user_app_control(view_function, name=None, **kwargs):
# This function is called on the registration of each django-plotly-dash view
# name is one of main component-suites routes layout dependencies update-component

def wrapped_view(request, *args, **kwargs):
is_permitted = check_access_permitted(request, **kwargs)
if not is_permitted:
# Access not permitted, so raise error or generate an appropriate response

...

else:
return view_function(request, *args, **kwargs)

if getattr(view_function,"csrf_exempt",False):
return csrf_exempt(wrapped_view)

return wrapped_view

The above sketch highlights how access can be controlled based on each request. Note that the
``csrf_exempt`` property of any wrapped view is preserved by the decoration function and this
approach needs to be extended to other properties if needed. Also, this sketch only passes
``kwargs`` to the permission function.


16 changes: 16 additions & 0 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,19 @@ View decoration

Each view delegated through to ``plotly_dash`` can be wrapped using a view decoration function. This enables access to be restricted to
logged-in users, or using a desired conditions based on the user and session state.

To restrict all access to logged-in users, use the ``login_required`` wrapper:

.. code-block:: python

PLOTLY_DASH = {

...
# Name of view wrapping function
"view_decorator": "django_plotly_dash.access.login_required",
...
}

More information can be found in the :ref:`view decoration <access_control>` section.


2 changes: 1 addition & 1 deletion docs/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,5 @@ in this github `issue <https://github.com/GibbsConsulting/django-plotly-dash/iss

* Can per-user or other fine-grained access control be used?

Yes. See the :ref:`view_decoration` configuration setting.
Yes. See the :ref:`view_decoration` configuration setting and :ref:`access_control` section.

3 changes: 2 additions & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Contents
template_tags
dash_components
configuration
development
access_control
faq
development
license