1
+ from functools import update_wrapper
1
2
2
3
from django .conf import settings
3
4
from django .contrib .admin import AdminSite
6
7
from django .http import HttpResponseRedirect
7
8
from django .shortcuts import resolve_url
8
9
from django .urls import reverse
10
+ from django .views .decorators .cache import never_cache
11
+ from django .views .decorators .csrf import csrf_protect
12
+
9
13
10
14
from .utils import monkeypatch_method
11
15
@@ -25,33 +29,89 @@ class AdminSiteOTPRequiredMixin:
25
29
use :meth:`has_permission` in order to secure those views.
26
30
"""
27
31
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
+
28
37
def has_permission (self , request ):
29
38
"""
30
39
Returns True if the given HttpRequest has permission to view
31
40
*at least one* page in the admin site.
32
41
"""
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()``:
36
52
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
37
91
def login (self , request , extra_context = None ):
38
92
"""
39
93
Redirects to the site login page for the given HttpRequest.
40
94
If user has admin permissions but 2FA not setup, then redirect to
41
95
2FA setup page.
42
96
"""
97
+ print ("AdminSiteOTPRequiredMixin.login" )
98
+
43
99
# redirect to admin page after login
44
100
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 )
45
103
46
104
# 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 :
48
106
49
107
# if user has 2FA setup, go to admin homepage
50
108
if request .user .is_verified ():
109
+ print ("User is verified, going to normal index." )
51
110
index_path = reverse ("admin:index" , current_app = self .name )
52
111
53
112
# 2FA not setup. redirect to 2FA setup page
54
113
else :
114
+ print ("User is not verified. redirecting to two_factor setup." )
55
115
index_path = reverse ("two_factor:setup" , current_app = self .name )
56
116
57
117
return HttpResponseRedirect (index_path )
0 commit comments