django-utils

personal collection of django utilities
git clone https://git.ce9e.org/django-utils.git

commit
43aac7d1de4c3fa27673a6fb1fc50306385296a0
parent
60f2d2e2447fee9b4196cf15ece781416c590858
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2023-04-06 13:24
Merge branch 'feature-auth-check-views'

Diffstat

A utils/auth_check_views.py 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

1 files changed, 79 insertions, 0 deletions


diff --git a/utils/auth_check_views.py b/utils/auth_check_views.py

@@ -0,0 +1,79 @@
   -1     1 """
   -1     2 This is a draft implementation.
   -1     3 
   -1     4 -   It only checks class based views.
   -1     5 -   There can be many ways to check for login. This only checks that a
   -1     6     view inherits from LoginRequiredMixin or PermissionRequiredMixin.
   -1     7 
   -1     8 """
   -1     9 
   -1    10 import re
   -1    11 
   -1    12 from django.core.checks import Error, register
   -1    13 
   -1    14 from django.contrib.auth.mixins import PermissionRequiredMixin
   -1    15 from django.contrib.auth.mixins import LoginRequiredMixin
   -1    16 
   -1    17 IGNORE = [
   -1    18     re.compile('^/login/$'),
   -1    19     re.compile('^/logout/$'),
   -1    20     re.compile('^/media/'),
   -1    21     re.compile('^/admin/'),
   -1    22     re.compile('^/__debug__/'),
   -1    23     re.compile('^/jsi18n/'),
   -1    24 ]
   -1    25 
   -1    26 
   -1    27 def iter_views(resolver=None, path=''):
   -1    28     if resolver is None:
   -1    29         from django.urls import get_resolver
   -1    30         resolver = get_resolver()
   -1    31     path += str(resolver.pattern).lstrip('^')
   -1    32     if getattr(resolver, 'callback', None):
   -1    33         yield resolver.callback, path
   -1    34     for child in getattr(resolver, 'url_patterns', []):
   -1    35         for c, p in iter_views(child, path):
   -1    36             yield c, p
   -1    37 
   -1    38 
   -1    39 @register()
   -1    40 def check_permission_required(app_configs, **kwargs):
   -1    41     errors = []
   -1    42     for view, path in iter_views():
   -1    43         if not hasattr(view, 'view_class'):
   -1    44             continue
   -1    45         if (
   -1    46             hasattr(view.view_class, 'permission_required')
   -1    47             and not issubclass(view.view_class, PermissionRequiredMixin)
   -1    48         ):
   -1    49             errors.append(Error(
   -1    50                 'The class-based-view {!r} at {} has an attribute called '
   -1    51                 '``permission_required``, but does not inherit from '
   -1    52                 'PermissionRequiredMixin'.format(view.view_class, path),
   -1    53                 obj=view.view_class,
   -1    54                 id='auth.E001',
   -1    55             ))
   -1    56     return errors
   -1    57 
   -1    58 
   -1    59 @register()
   -1    60 def check_login(app_configs, **kwargs):
   -1    61     errors = []
   -1    62     for view, path in iter_views():
   -1    63         if not hasattr(view, 'view_class'):
   -1    64             continue
   -1    65         if any(p.search(path) for p in IGNORE):
   -1    66             continue
   -1    67         if (
   -1    68             not issubclass(view.view_class, PermissionRequiredMixin)
   -1    69             and not issubclass(view.view_class, LoginRequiredMixin)
   -1    70         ):
   -1    71             errors.append(Error(
   -1    72                 'The class-based-view {!r} at {} does not inherit from '
   -1    73                 'LoginRequiredMixin or '
   -1    74                 'PermissionRequiredMixin'.format(view.view_class, path),
   -1    75                 hint='You can add a pattern to IGNORE',
   -1    76                 obj=view.view_class,
   -1    77                 id='auth.E002',
   -1    78             ))
   -1    79     return errors