1+ from functools import update_wrapper
12
23from django .conf import settings
34from django .contrib .admin import AdminSite
67from django .http import HttpResponseRedirect
78from django .shortcuts import resolve_url
89from django .urls import reverse
10+ from django .views .decorators .cache import never_cache
11+ from django .views .decorators .csrf import csrf_protect
12+
913
1014from .utils import monkeypatch_method
1115
@@ -25,33 +29,89 @@ class AdminSiteOTPRequiredMixin:
2529 use :meth:`has_permission` in order to secure those views.
2630 """
2731
32+ def has_admin_permission (self , request ):
33+ print ('has_admin_permission, super' , super ().has_permission (request ))
34+ print ('has_admin_permission, AdminSite' , AdminSite ().has_permission (request ) )
35+ return AdminSite ().has_permission (request )
36+
2837 def has_permission (self , request ):
2938 """
3039 Returns True if the given HttpRequest has permission to view
3140 *at least one* page in the admin site.
3241 """
33- if not super ().has_permission (request ):
34- return False
35- return request .user .is_verified ()
42+ print ("AdminSiteOTPRequiredMixin.super" , self .has_admin_permission (), request .user .is_verified ())
43+ return self .has_admin_permission (request ) and request .user .is_verified ()
44+
45+ def admin_view (self , view , cacheable = False ):
46+ """
47+ Decorator to create an admin view attached to this ``AdminSite``. This
48+ wraps the view and provides permission checking by calling
49+ ``self.has_permission``.
50+
51+ You'll want to use this from within ``AdminSite.get_urls()``:
3652
53+ class MyAdminSite(AdminSite):
54+
55+ def get_urls(self):
56+ from django.urls import path
57+
58+ urls = super().get_urls()
59+ urls += [
60+ path('my_view/', self.admin_view(some_view))
61+ ]
62+ return urls
63+
64+ By default, admin_views are marked non-cacheable using the
65+ ``never_cache`` decorator. If the view can be safely cached, set
66+ cacheable=True.
67+ """
68+ def inner (request , * args , ** kwargs ):
69+ print ("AdminSiteOTPRequiredMixin.admin_view.inner" , )
70+ if not self .has_permission (request ):
71+ if request .path == reverse ('admin:logout' , current_app = self .name ):
72+ index_path = reverse ('admin:index' , current_app = self .name )
73+ return HttpResponseRedirect (index_path )
74+ # Inner import to prevent django.contrib.admin (app) from
75+ # importing django.contrib.auth.models.User (unrelated model).
76+ from django .contrib .auth .views import redirect_to_login
77+ return redirect_to_login (
78+ request .get_full_path (),
79+ reverse ('admin:login' , current_app = self .name )
80+ )
81+ return view (request , * args , ** kwargs )
82+ if not cacheable :
83+ inner = never_cache (inner )
84+ # We add csrf_protect here so this function can be used as a utility
85+ # function for any view, without having to repeat 'csrf_protect'.
86+ if not getattr (view , 'csrf_exempt' , False ):
87+ inner = csrf_protect (inner )
88+ return update_wrapper (inner , view )
89+
90+ @never_cache
3791 def login (self , request , extra_context = None ):
3892 """
3993 Redirects to the site login page for the given HttpRequest.
4094 If user has admin permissions but 2FA not setup, then redirect to
4195 2FA setup page.
4296 """
97+ print ("AdminSiteOTPRequiredMixin.login" )
98+
4399 # redirect to admin page after login
44100 redirect_to = request .POST .get (REDIRECT_FIELD_NAME , request .GET .get (REDIRECT_FIELD_NAME ))
101+ has_admin_access = AdminSite ().has_permission (request )
102+ print ("AdminSiteOTPRequiredMixin.login" , redirect_to , request .method , has_admin_access )
45103
46104 # if user (is_active and is_staff)
47- if request .method == "GET" and AdminSite (). has_permission ( request ) :
105+ if request .method == "GET" and has_admin_access :
48106
49107 # if user has 2FA setup, go to admin homepage
50108 if request .user .is_verified ():
109+ print ("User is verified, going to normal index." )
51110 index_path = reverse ("admin:index" , current_app = self .name )
52111
53112 # 2FA not setup. redirect to 2FA setup page
54113 else :
114+ print ("User is not verified. redirecting to two_factor setup." )
55115 index_path = reverse ("two_factor:setup" , current_app = self .name )
56116
57117 return HttpResponseRedirect (index_path )
0 commit comments