Custom Processors

Base Processors

All processors inherit from BaseProcessor.

class permissions_auditor.processors.base.BaseProcessor
can_process(view)

Can this processor process the provided view?

Parameters:view (function or class) – the view being processed.
Returns:whether this processor can process the view. Default: False
Return type:boolean
get_docstring(view)

Return any additional information that should be displayed when showing permisison information.

Parameters:view (function or class) – the view being processed.
Returns:the string to display in the additional info column. Default: None
Return type:str or None
get_login_required(view)

Get whether or not the view needs the user to be logged in to access.

Parameters:view (function or class) – the view being processed.
Returns:whether a user must be logged in to access this view. Default: False
Return type:boolean or None (if unknown)
get_permission_required(view)

Get the permissions required on the provided view. Must return an iterable.

Parameters:view (function or class) – the view being processed.
Returns:the permissions required to access the view. Default: []
Return type:list(str)

Other useful base classes:

class permissions_auditor.processors.base.BaseFuncViewProcessor

Base class for processing function based views.

class permissions_auditor.processors.base.BaseCBVProcessor

Base class for processing class based views.

class permissions_auditor.processors.base.BaseFileredMixinProcessor

Base class for parsing mixins on class based views. Set class_filter to filter the class names the processor applies to. ONLY checks top level base classes.

Variables:class_filter – initial value: None
get_class_filter()

Override this method to override the class_names attribute. Must return an iterable.

Returns:a list of strings containing the full paths of mixins to detect.
Raises:ImproperlyConfigured – if the class_filter atribute is None.

Parsing Mixins

Creating a custom processor for mixins on class based views is fairly straight forward.

In this example, we have a mixin BobRequiredMixin and a view that uses it, BobsPage. The mixin should only allow users with the first name Bob to access the page.

example_project/views.py
from django.core.exceptions import PermissionDenied
from django.views.generic import TemplateView

class BobRequiredMixin:
    def dispatch(self, request, *args, **kwargs):
        if self.request.user.first_name != 'Bob':
            raise PermissionDenied("You are not Bob")
        return super().dispatch(request, *args, **kwargs)

class BobsPage(BobRequiredMixin, TemplateView):
    ...

Let’s define our processor in processors.py.

example_project/processors.py
from permissions_auditor.processors.base import BaseFileredMixinProcessor

class BobRequiredMixinProcessor(BaseFileredMixinProcessor):
    class_filter = 'example_project.views.BobRequiredMixin'

    def get_login_required(self, view):
        return True

    def get_docstring(self, view):
        return "The user's first name must be Bob to view."

To register our processor, we need to add it to PERMISSIONS_AUDITOR_PROCESSORS in our project settings.

settings.py
PERMISSIONS_AUDITOR_PROCESSORS = [
    ...

    'example_project.processors.BobRequiredProcessor',
]

When BobsPage is registered to a URL, we should see this in the admin panel:

Name URL Permission Required Login Required Additional Info
BobsPage /   True The user’s first name must be Bob to view.

Perhaps we want to make our mixin configurable so we can detect different names depending on the view. We also have multiple people with the same first name, so we also want to check for a permission: example.view_pages.

class FirstNameRequiredMixin:
    required_first_name = ''

    def dispatch(self, request, *args, **kwargs):
        if not (self.request.user.has_perm('example_app.view_userpages')
                and self.request.user.first_name == self.required_first_name):
            raise PermissionDenied()
        return super().dispatch(request, *args, **kwargs)

class GeorgesPage(FirstNameRequiredMixin, TemplateView):
    required_first_name = 'George'

    ...

We’ll modify class_filter and get_docstring() from our old processor, and override get_permission_required().

from permissions_auditor.processors.base import BaseFileredMixinProcessor

class FirstNameRequiredMixinProcessor(BaseFileredMixinProcessor):
    class_filter = 'example_project.views.FirstNameRequiredMixin'

    def get_permission_required(self, view):
        return ['example.view_pages']

    def get_login_required(self, view):
        return True

    def get_docstring(self, view):
        return "The user's first name must be {} to view.".format(view.first_name_required)

Once we register our view to a URL and register the processor, our admin table should look like this:

Name URL Permission Required Login Required Additional Info
GeorgesPage / example.view_pages True The user’s first name must be George to view.

Additional Examples

See the permissions_auditor/processors/ folder in the source code for more examples.