misc: refactor ViewRestrictionMiddleware (#24056)

The generic code for checking restrictions is separated from the code
specific to each specific check; here the code to check for
PasswordReset models is extracted into
check_password_reset_view_restriction().
This commit is contained in:
Benjamin Dauvergne 2021-07-06 10:12:23 +02:00
parent 5a13211f32
commit 34cd3c1d48
1 changed files with 46 additions and 16 deletions

View File

@ -26,6 +26,7 @@ import urllib.parse
from django import http
from django.conf import settings
from django.contrib import messages
from django.db.models import Model
from django.utils.deprecation import MiddlewareMixin
from django.utils.functional import SimpleLazyObject
from django.utils.translation import ugettext as _
@ -108,32 +109,61 @@ class ViewRestrictionMiddleware(MiddlewareMixin):
def check_view_restrictions(self, request):
'''Check if a restriction on accessible views must be applied'''
from django.db.models import Model
from .models import PasswordReset
user = request.user
b = user.is_authenticated
if b and isinstance(user, Model):
now = time.time()
last_time = request.session.get('last_password_reset_check', 0)
if now - last_time > 10:
if PasswordReset.objects.filter(user=request.user).exists():
return 'password_change'
request.session['last_password_reset_check'] = now
# If the session is unlogged, do nothing
if user is None or not user.is_authenticated:
return None
# If the latest check was succesfull, do nothing.
now = time.time()
last_time = request.session.get('last_view_restriction_check', 0)
if now - last_time <= 60:
return None
view = self.check_password_reset_view_restriction(request, user)
if view:
return view
for plugin in plugins.get_plugins():
if hasattr(plugin, 'check_view_restrictions'):
view = plugin.check_view_restrictions(request)
view = plugin.check_view_restrictions(request, user)
if view:
return view
# do not check for 60 seconds
request.session['last_password_reset_check'] = now
return None
def check_password_reset_view_restriction(self, request, user):
# If user is authenticated and a password_reset_flag is set, force
# redirect to password change and show a message.
from . import models
if (
user.is_authenticated
and isinstance(user, Model)
and models.PasswordReset.objects.filter(user=request.user).exists()
):
if request.resolver_match.url_name != 'password_change':
messages.warning(request, _('You must change your password to continue'))
return 'password_change'
def process_view(self, request, view_func, view_args, view_kwargs):
'''If current view is not the one we should be, redirect'''
'''If current view is not the one where we should be, redirect'''
view = self.check_view_restrictions(request)
if not view or request.resolver_match.url_name in (view, 'auth_logout'):
if not view:
return
url_name = request.resolver_match.url_name
# do not block on the restricted view
if url_name == view:
return
# prevent blocking people when they logout
if url_name == 'auth_logout':
return
if view == 'password_change':
messages.warning(request, _('You must change your password to continue'))
return utils_misc.redirect_and_come_back(request, view)