AlekSIS
AlekSIS

Source code for aleksis.core.util.predicates

from typing import Optional

from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User
from django.db.models import Model
from django.http import HttpRequest

from django_otp import user_has_device
from guardian.backends import ObjectPermissionBackend
from guardian.shortcuts import get_objects_for_user
from rules import predicate

from ..mixins import ExtensibleModel
from ..models import Group
from .core_helpers import get_content_type_by_perm, get_site_preferences
from .core_helpers import has_person as has_person_helper
from .core_helpers import queryset_rules_filter


[docs]def permission_validator(request: HttpRequest, perm: str) -> bool: """Check whether the request user has a permission.""" if request.user: return request.user.has_perm(perm) return False
[docs]def check_global_permission(user: User, perm: str) -> bool: """Check whether a user has a global permission.""" return ModelBackend().has_perm(user, perm)
[docs]def check_object_permission( user: User, perm: str, obj: Model, checker_obj: Optional[ExtensibleModel] = None ) -> bool: """Check whether a user has a permission on an object. You can provide a custom ``ObjectPermissionChecker`` for prefetching object permissions by annotating an extensible model with ``set_object_permission_checker``. This can be the provided object (``obj``) or a special object which is only used to get the checker class (``checker_obj``). """ if not checker_obj: checker_obj = obj if hasattr(checker_obj, "_permission_checker"): return checker_obj._permission_checker.has_perm(perm, obj) return ObjectPermissionBackend().has_perm(user, perm, obj)
[docs]def has_global_perm(perm: str): """Build predicate which checks whether a user has a global permission.""" name = f"has_global_perm:{perm}" @predicate(name) def fn(user: User) -> bool: return check_global_permission(user, perm) return fn
[docs]def has_object_perm(perm: str): """Build predicate which checks whether a user has a permission on a object.""" name = f"has_global_perm:{perm}" @predicate(name) def fn(user: User, obj: Model) -> bool: if not obj: return False return check_object_permission(user, perm, obj) return fn
[docs]def has_any_object(perm: str, klass): """Check if has any object. Build predicate which checks whether a user has access to objects with the provided permission or rule. Differentiates between object-related permissions and rules. """ name = f"has_any_object:{perm}" @predicate(name) def fn(user: User) -> bool: ct_perm = get_content_type_by_perm(perm) # In case an object-related permission with the same ContentType class as the given class # is passed, the optimized django-guardian get_objects_for_user function is used. if ct_perm and ct_perm.model_class() == klass: return get_objects_for_user(user, perm, klass).exists() # In other cases, it is checked for each object of the given model whether the current user # fulfills the given rule. else: return queryset_rules_filter(user, klass.objects.all(), perm).exists() return fn
[docs]def is_site_preference_set(section: str, pref: str): """Check the boolean value of a given site preference.""" name = f"check_site_preference:{section}__{pref}" @predicate(name) def fn() -> bool: return bool(get_site_preferences()[f"{section}__{pref}"]) return fn
@predicate def has_person(user: User) -> bool: """Predicate which checks whether a user has a linked person.""" return has_person_helper(user) @predicate def is_current_person(user: User, obj: Model) -> bool: """Predicate which checks if the provided object is the person linked to the user object.""" return user.person == obj @predicate def is_group_owner(user: User, group: Group) -> bool: """Predicate which checks if the user is a owner of the provided group.""" return user.person in group.owners.all() @predicate def is_group_member(user: User, group: Group) -> bool: """Predicate which checks if the user is a member of the provided group.""" return user.person in group.members.all() @predicate def is_notification_recipient(user: User, obj: Model) -> bool: """Check if is a notification recipient. Predicate which checks whether the recipient of the notification a user wants to mark read is this user. """ return user == obj.recipient.user
[docs]def contains_site_preference_value(section: str, pref: str, value: str): """Check if given site preference contains a value.""" name = f"check_site_preference_value:{section}__{pref}" @predicate(name) def fn() -> bool: return bool(value in get_site_preferences()[f"{section}__{pref}"]) return fn
@predicate def has_activated_2fa(user: User) -> bool: """Check if the user has activated two-factor authentication.""" return user_has_device(user)