В моем проекте у меня есть как групповые, так и настраиваемые разрешения на основе пользователей.
У меня есть настраиваемый бэкэнд аутентификации, который по сути проверяет, есть ли у пользователя разрешения группы, а затем проверяет, есть ли у них отозванные разрешения, которые необходимы быть удаленным из проверенных разрешений.
Я столкнулся с проблемой оптимизации сейчас, когда я тестирую реализацию указанного отозванного разрешения, потому что моя модель CustomUser имеет поле M2M, которое содержит эти отозванные разрешения, что является отношением на auth_permissions
, и моя BackendAuthentication проверяет это, я получаю сумасшедшее количество обращений к БД при загрузке страницы.
Как я могу передать предварительно выбранный объект в свой AuthBackend?
Вот мой AuthBackend:
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import Permission
class UsersAuthenticationBackend(ModelBackend):
def _get_revoked_perms(self, user_obj):
if user_obj.is_superuser or user_obj.is_admin:
revoked_perms = Permission.objects.none()
elif hasattr(user_obj, 'revoked_permissions'):
# this causes the issue, I need to pass in the prefetch related to my model backend...HOW?
# this should be something like CustomUser.objects.prefetch_related('revoked_permissions')
revoked_perms = getattr(user_obj, 'revoked_permissions').values_list('content_type__app_label', 'codename')
else:
revoked_perms = Permission.objects.none()
revoked_perms = ["{}.{}".format(perm[0], perm[1]) for perm in revoked_perms]
print(revoked_perms)
return revoked_perms
def has_perm(self, user_obj, perm, obj=None):
if not user_obj.is_active:
return False
revoked_perms = self._get_revoked_perms(user_obj)
all_perms = self.get_all_permissions(user_obj)
allowed_perms = [p for p in all_perms if not p in revoked_perms]
if isinstance(perm, str):
return perm in allowed_perms
elif isinstance(perm, Permission):
return '{}.{}'.format(perm.content_type.app_label, perm.codename) in allowed_perms
else:
return False
Вот соответствующая часть CustomUser, если вам нужно ее увидеть
class CustomUser(AbstractUser, SafeDeleteModel):
...
revoked_permissions = models.ManyToManyField(Permission, blank=True)