angrybeanie_wagtail/env/lib/python3.12/site-packages/wagtail/admin/auth.py

151 lines
4.6 KiB
Python
Raw Permalink Normal View History

2025-07-25 21:32:16 +10:00
from functools import wraps
from django.conf import settings
from django.core.exceptions import PermissionDenied
from django.shortcuts import redirect
from django.urls import reverse
from django.utils.translation import gettext as _
from wagtail.admin import messages
from wagtail.admin.localization import get_localized_response
from wagtail.log_actions import LogContext
from wagtail.permissions import page_permission_policy
def permission_denied(request):
"""Return a standard 'permission denied' response"""
if request.headers.get("x-requested-with") == "XMLHttpRequest":
raise PermissionDenied
from wagtail.admin import messages
messages.error(request, _("Sorry, you do not have permission to access this area."))
return redirect("wagtailadmin_home")
def user_passes_test(test):
"""
Given a test function that takes a user object and returns a boolean,
return a view decorator that denies access to the user if the test returns false.
"""
def decorator(view_func):
# decorator takes the view function, and returns the view wrapped in
# a permission check
@wraps(view_func)
def wrapped_view_func(request, *args, **kwargs):
if test(request.user):
# permission check succeeds; run the view function as normal
return view_func(request, *args, **kwargs)
else:
# permission check failed
return permission_denied(request)
return wrapped_view_func
return decorator
def permission_required(permission_name):
"""
Replacement for django.contrib.auth.decorators.permission_required which returns a
more meaningful 'permission denied' response than just redirecting to the login page.
(The latter doesn't work anyway because Wagtail doesn't define LOGIN_URL...)
"""
def test(user):
return user.has_perm(permission_name)
# user_passes_test constructs a decorator function specific to the above test function
return user_passes_test(test)
def any_permission_required(*perms):
"""
Decorator that accepts a list of permission names, and allows the user
to pass if they have *any* of the permissions in the list
"""
def test(user):
for perm in perms:
if user.has_perm(perm):
return True
return False
return user_passes_test(test)
class PermissionPolicyChecker:
"""
Provides a view decorator that enforces the given permission policy,
returning the wagtailadmin 'permission denied' response if permission not granted
"""
def __init__(self, policy):
self.policy = policy
def require(self, action):
def test(user):
return self.policy.user_has_permission(user, action)
return user_passes_test(test)
def require_any(self, *actions):
def test(user):
return self.policy.user_has_any_permission(user, actions)
return user_passes_test(test)
def user_has_any_page_permission(user):
"""
Check if a user has any permission to add, edit, or otherwise manage any
page.
"""
return page_permission_policy.user_has_any_permission(
user, {"add", "change", "publish", "bulk_delete", "lock", "unlock"}
)
def reject_request(request):
if request.headers.get("x-requested-with") == "XMLHttpRequest":
raise PermissionDenied
# import redirect_to_login here to avoid circular imports on model files that import
# wagtail.admin.auth, specifically where custom user models are involved
from django.contrib.auth.views import redirect_to_login as auth_redirect_to_login
login_url = getattr(
settings, "WAGTAILADMIN_LOGIN_URL", reverse("wagtailadmin_login")
)
return auth_redirect_to_login(request.get_full_path(), login_url=login_url)
def require_admin_access(view_func):
def decorated_view(request, *args, **kwargs):
user = request.user
if user.is_anonymous:
return reject_request(request)
if user.has_perms(["wagtailadmin.access_admin"]):
try:
with LogContext(user=user):
return get_localized_response(view_func, request, *args, **kwargs)
except PermissionDenied:
if request.headers.get("x-requested-with") == "XMLHttpRequest":
raise
return permission_denied(request)
if not request.headers.get("x-requested-with") == "XMLHttpRequest":
messages.error(request, _("You do not have permission to access the admin"))
return reject_request(request)
return decorated_view