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 guardian.backends import ObjectPermissionBackend from guardian.shortcuts import get_objects_for_user from rules import predicate from aleksis.core.util.core_helpers import has_person # 1. Global permissions (view all, add, change all, delete all) # 2. Object permissions (view, change, delete) # 3. Rules def permission_validator(request: HttpRequest, perm: str) -> bool: """ Checks whether the request user has a permission """ if request.user: return request.user.has_perm(perm) return False def check_global_permission(user: User, perm: str) -> bool: """ Checks whether a user has a global permission """ return ModelBackend().has_perm(user, perm) def check_object_permission(user: User, perm: str, obj: Model) -> bool: """ Checks whether a user has a permission on a object """ return ObjectPermissionBackend().has_perm(user, perm, obj) def has_global_perm(perm: str): """ Builds predicate which checks whether a user has a global permission """ name = "has_global_perm:{}".format(perm) @predicate(name) def fn(user: User) -> bool: return check_global_permission(user, perm) return fn def has_object_perm(perm: str): """ Builds predicate which checks whether a user has a permission on a object """ name = "has_global_perm:{}".format(perm) @predicate(name) def fn(user: User, obj: Model) -> bool: if not obj: return False return check_object_permission(user, perm, obj) return fn def has_any_object(perm: str, klass): """ Build predicate which checks whether a user has access to objects with the provided permission """ name = "has_any_object:{}".format(perm) @predicate(name) def fn(user: User) -> bool: objs = get_objects_for_user(user, perm, klass) return len(objs) > 0 return fn @predicate def has_person_predicate(user: User) -> bool: """ Predicate which checks whether a user has a linked person """ return has_person(user) @predicate() def is_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