Skip to content

Commit f7ed14e

Browse files
delsimGibbsConsulting
authored andcommitted
Added documentation for per-view access control (#90)
* Added documentation and sketch of example control for access control through view decoration * Tidy up code based on linter comments
1 parent e10ed4d commit f7ed14e

File tree

5 files changed

+100
-3
lines changed

5 files changed

+100
-3
lines changed

django_plotly_dash/access.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727

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

30+
#pylint: disable=bare-except, unused-argument
31+
3032
def login_required(view_function, **kwargs):
3133
'Wrap all DPD calls with login_required'
3234
return login_required_decorator(view_function)
@@ -37,7 +39,7 @@ def login_required(view_function, **kwargs):
3739
dash_view_decorator = locals()[dash_view_decorator_name]
3840
except:
3941
mod_name, func_name = dash_view_decorator_name.rsplit('.', 1)
40-
if len(mod_name):
42+
if mod_name:
4143
mod = importlib.import_module(mod_name)
4244
dash_view_decorator = getattr(mod, func_name)
4345
else:

docs/access_control.rst

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
.. _access_control:
2+
3+
View decoration
4+
===============
5+
6+
The ``django-plotly-dash`` views, as served by Django, can be wrapped with
7+
an arbitrary decoration function. This allows the use
8+
of the Django `login_required <https://docs.djangoproject.com/en/2.1/topics/auth/default/#the-login-required-decorator>`_ view decorator
9+
as well as enabling more specialised and fine-grained control.
10+
11+
The ``login_required`` decorator
12+
----------------------------
13+
14+
The ``login_required`` decorator from the Django authentication system can be used as a view decorator. A wrapper function is provided
15+
in ``django_plotly_dash.access``.
16+
17+
.. code-block:: python
18+
19+
PLOTLY_DASH = {
20+
21+
...
22+
# Name of view wrapping function
23+
"view_decorator": "django_plotly_dash.access.login_required",
24+
...
25+
}
26+
27+
Note that the view wrapping is on all of the ``django-plotly-dash`` views.
28+
29+
Fine-grained control
30+
--------------------
31+
32+
The view decoration function is called for each variant exposed in
33+
the ``django_plotly_dash.urls`` file. As well as the
34+
underlying view function, each call to the decorator is given the name of the
35+
route, as used by ``django.urls.reverse``, the specific url fragment for the view, and a name
36+
describing the type of view.
37+
38+
From this information, it is possible to implement view-specific wrapping of the view functions, and
39+
in turn the wrapper functions can then use the request content, along with other information, to control
40+
access to the underlying view function.
41+
42+
.. code-block:: python
43+
44+
from django.views.decorators.csrf import csrf_exempt
45+
46+
def check_access_permitted(request, **kwargs):
47+
# See if access is allowed; if so return True
48+
# This function is called on each request
49+
50+
...
51+
52+
return True
53+
54+
def user_app_control(view_function, name=None, **kwargs):
55+
# This function is called on the registration of each django-plotly-dash view
56+
# name is one of main component-suites routes layout dependencies update-component
57+
58+
def wrapped_view(request, *args, **kwargs):
59+
is_permitted = check_access_permitted(request, **kwargs)
60+
if not is_permitted:
61+
# Access not permitted, so raise error or generate an appropriate response
62+
63+
...
64+
65+
else:
66+
return view_function(request, *args, **kwargs)
67+
68+
if getattr(view_function,"csrf_exempt",False):
69+
return csrf_exempt(wrapped_view)
70+
71+
return wrapped_view
72+
73+
The above sketch highlights how access can be controlled based on each request. Note that the
74+
``csrf_exempt`` property of any wrapped view is preserved by the decoration function and this
75+
approach needs to be extended to other properties if needed. Also, this sketch only passes
76+
``kwargs`` to the permission function.
77+
78+

docs/configuration.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,19 @@ View decoration
5757

5858
Each view delegated through to ``plotly_dash`` can be wrapped using a view decoration function. This enables access to be restricted to
5959
logged-in users, or using a desired conditions based on the user and session state.
60+
61+
To restrict all access to logged-in users, use the ``login_required`` wrapper:
62+
63+
.. code-block:: python
64+
65+
PLOTLY_DASH = {
66+
67+
...
68+
# Name of view wrapping function
69+
"view_decorator": "django_plotly_dash.access.login_required",
70+
...
71+
}
72+
73+
More information can be found in the :ref:`view decoration <access_control>` section.
74+
75+

docs/faq.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,5 @@ in this github `issue <https://github.com/GibbsConsulting/django-plotly-dash/iss
3030

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

33-
Yes. See the :ref:`view_decoration` configuration setting.
33+
Yes. See the :ref:`view_decoration` configuration setting and :ref:`access_control` section.
3434

docs/index.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Contents
2323
template_tags
2424
dash_components
2525
configuration
26-
development
26+
access_control
2727
faq
28+
development
2829
license

0 commit comments

Comments
 (0)