"""Predefined check functions controlling menu item visibility.
All check functions receive a Django request object and optional keyword
arguments. They return a boolean value indicating whether the menu item
should be visible.
"""
[docs]
def user_is_staff(request, **kwargs):
"""Check if the user associated with the given request is a staff member.
Args:
request: The HTTP request object.
**kwargs: Additional arguments (ignored).
Returns:
True if the user is a staff member, False otherwise.
"""
return hasattr(request, "user") and request.user and request.user.is_staff
[docs]
def user_is_authenticated(request, **kwargs):
"""Check if the user associated with the given request is authenticated.
Args:
request: The HTTP request object.
**kwargs: Additional arguments (ignored).
Returns:
True if the user is authenticated, False otherwise.
"""
return hasattr(request, "user") and request.user and request.user.is_authenticated
[docs]
def user_is_anonymous(request, **kwargs):
"""Check if the user associated with the given request is anonymous.
Args:
request: The HTTP request object.
**kwargs: Additional arguments (ignored).
Returns:
True if the user is anonymous, False otherwise.
"""
return not hasattr(request, "user") or not request.user or request.user.is_anonymous
[docs]
def user_is_superuser(request, **kwargs):
"""Check if the user associated with the given request is a superuser.
Args:
request: The HTTP request object.
**kwargs: Additional arguments (ignored).
Returns:
True if the user is a superuser, False otherwise.
"""
return hasattr(request, "user") and request.user and request.user.is_superuser
[docs]
def user_in_any_group(*groups):
"""Build a check for membership in any of the given groups.
Args:
*groups: Variable length argument list of group names to check against.
Returns:
A function that takes a Django request object and optional keyword
arguments, and returns True if the user is authenticated and is a
member of any of the specified groups, otherwise False.
Example:
::
MenuLink(
name="Authors only",
view_name="author-management-page",
check=user_in_any_group("authors"),
)
"""
def _function(request, **kwargs):
return (
hasattr(request, "user")
and request.user
and request.user.is_authenticated
and request.user.groups.filter(name__in=groups).exists()
)
return _function
[docs]
def user_has_any_permission(*perms: str):
"""Build a check for at least one of the given permissions.
Args:
*perms: One or more permission strings to check against the user.
Returns:
True if the user has at least one of the specified permissions, False
otherwise.
Example:
::
MenuLink(
name="Authors",
view_name="book-create",
check=user_has_any_permission("book.add_book"),
)
"""
def _check(request, **kwargs):
return (
hasattr(request, "user")
and request.user
and request.user.is_authenticated
and any(request.user.has_perm(perm) for perm in perms)
)
return _check
[docs]
def user_has_object_permission(perm: str):
"""Build a check for a specific object-level permission.
Note: This function is removed as it depended on the instance parameter.
For object-level permissions, create custom check functions that get
the object from the request context or other means.
Args:
perm: The permission codename to check (e.g., 'blog.change_post').
Returns:
A function that always returns False with a warning.
"""
def _check(request, **kwargs):
import warnings
warnings.warn(
"user_has_object_permission is deprecated. Create custom check functions "
"that retrieve objects from request context instead of relying on instance parameter.",
DeprecationWarning,
stacklevel=2,
)
return False
return _check
[docs]
def user_in_all_groups(*groups):
"""Build a check for membership in all of the given groups.
Args:
*groups: Variable length argument list of group names to check against.
Returns:
A function that takes a Django request object and optional keyword
arguments, and returns True if the user is authenticated and is a
member of ALL specified groups, otherwise False.
Example:
::
MenuLink(
name="Authors and Editors only",
view_name="special-page",
check=user_in_all_groups("authors", "editors"),
)
"""
def _function(request, **kwargs):
if not (
hasattr(request, "user") and request.user and request.user.is_authenticated
):
return False
user_groups = request.user.groups.values_list("name", flat=True)
return all(group in user_groups for group in groups)
return _function
[docs]
def user_has_all_permissions(*perms: str):
"""Build a check for all of the given permissions.
Args:
*perms: One or more permission strings to check against the user.
Returns:
A function that returns True if the user has ALL specified
permissions, False otherwise.
Example:
::
MenuLink(
name="Full Admin",
view_name="admin-panel",
check=user_has_all_permissions(
"auth.add_user", "auth.change_user", "auth.delete_user"
),
)
"""
def _check(request, **kwargs):
if not (
hasattr(request, "user") and request.user and request.user.is_authenticated
):
return False
return all(request.user.has_perm(perm) for perm in perms)
return _check
[docs]
def user_is_active(request, **kwargs):
"""Check if the user associated with the given request is active.
Args:
request: The HTTP request object.
**kwargs: Additional arguments (ignored).
Returns:
True if the user is active, False otherwise.
"""
if not (hasattr(request, "user") and request.user):
return False
return bool(getattr(request.user, "is_active", False))
[docs]
def user_email_verified(request, **kwargs):
"""Check if the user's email is verified.
Assumes verified for authenticated users if the user model has no
``email_verified`` field.
Args:
request: The HTTP request object.
**kwargs: Additional arguments (ignored).
Returns:
True if the user's email is verified, False otherwise.
"""
if not (
hasattr(request, "user") and request.user and request.user.is_authenticated
):
return False
if hasattr(request.user, "email_verified"):
return request.user.email_verified
return True
[docs]
def user_has_profile(request, **kwargs):
"""Check if the user has an associated profile.
Args:
request: The HTTP request object.
**kwargs: Additional arguments (ignored).
Returns:
True if the user has a profile, False otherwise.
"""
if not (
hasattr(request, "user") and request.user and request.user.is_authenticated
):
return False
profile_attrs = ["profile", "userprofile", "user_profile"]
for attr in profile_attrs:
if hasattr(request.user, attr):
try:
profile = getattr(request.user, attr)
except AttributeError:
continue
else:
return profile is not None
return True # Assume profile exists if no profile model detected
[docs]
def request_is_ajax(request, **kwargs):
"""Check if the request is an AJAX request.
Args:
request: The HTTP request object.
**kwargs: Additional arguments (ignored).
Returns:
True if the request is AJAX, False otherwise.
"""
return request.headers.get("X-Requested-With") == "XMLHttpRequest"
[docs]
def request_is_secure(request, **kwargs):
"""Check if the request is secure (HTTPS).
Args:
request: The HTTP request object.
**kwargs: Additional arguments (ignored).
Returns:
True if the request is secure, False otherwise.
"""
return request.is_secure()
[docs]
def request_method_is(*methods):
"""Build a check for the request method matching any of the given methods.
Args:
*methods: Variable length argument list of HTTP methods to check against.
Returns:
A function that takes a Django request object and returns True if
the request method matches any of the specified methods.
Example:
::
MenuLink(
name="POST only action",
view_name="post-handler",
check=request_method_is("POST"),
)
"""
def _check(request, **kwargs):
return request.method.upper() in [method.upper() for method in methods]
return _check
[docs]
def user_attribute_equals(attribute_name: str, expected_value):
"""Build a check for a user attribute equalling a specific value.
Args:
attribute_name: The name of the user attribute to check.
expected_value: The expected value to compare against.
Returns:
A function that returns True if the user attribute equals the
expected value.
Example:
::
MenuLink(
name="Premium users only",
view_name="premium-content",
check=user_attribute_equals("subscription_type", "premium"),
)
"""
def _check(request, **kwargs):
if not (
hasattr(request, "user") and request.user and request.user.is_authenticated
):
return False
if hasattr(request.user, attribute_name):
return getattr(request.user, attribute_name) == expected_value
return False
return _check
[docs]
def user_in_group_with_permission(group_name: str, permission: str):
"""Build a check for group membership combined with a permission.
Args:
group_name: The name of the group to check.
permission: The permission to check.
Returns:
A function that returns True if the user is in the group and has
the permission.
Example:
::
MenuLink(
name="Editor with publish rights",
view_name="publish-content",
check=user_in_group_with_permission("editors", "blog.publish_post"),
)
"""
def _check(request, **kwargs):
if not (
hasattr(request, "user") and request.user and request.user.is_authenticated
):
return False
has_group = request.user.groups.filter(name=group_name).exists()
has_permission = request.user.has_perm(permission)
return has_group and has_permission
return _check
[docs]
def debug_mode_only(request, **kwargs):
"""Check if Django is running in debug mode.
Args:
request: The HTTP request object.
**kwargs: Additional arguments (ignored).
Returns:
True if DEBUG=True, False otherwise.
"""
from django.conf import settings
return settings.DEBUG
[docs]
def combine_checks(*check_functions, operator="and"):
"""Combine multiple check functions with AND or OR logic.
Args:
*check_functions: Variable length argument list of check functions.
operator: Either 'and' or 'or' to specify the combination logic.
Returns:
A combined check function.
Example:
::
MenuLink(
name="Staff or superuser",
view_name="admin-area",
check=combine_checks(user_is_staff, user_is_superuser, operator="or"),
)
"""
def _check(request, **kwargs):
if operator.lower() == "or":
return any(check_func(request, **kwargs) for check_func in check_functions)
else: # default to 'and'
return all(check_func(request, **kwargs) for check_func in check_functions)
return _check
[docs]
def negate_check(check_function):
"""Negate a check function (NOT logic).
Args:
check_function: The check function to negate.
Returns:
A negated check function.
Example:
::
MenuLink(
name="Non-staff only",
view_name="public-area",
check=negate_check(user_is_staff),
)
"""
def _check(request, **kwargs):
return not check_function(request, **kwargs)
return _check