fix: Исправлена вторая ошибка - отключен ModelBackend для CustomUser

Проблема:
После первого исправления ошибка продолжалась, но теперь в другом месте.
Django's ModelBackend пытался проверить permissions для CustomUser через
Permission.objects.filter(group__user=user_obj), что вызывало ошибку
"Cannot query 'chupa@chus.by': Must be 'PlatformAdmin' instance"

Причина:
RoleBasedPermissionBackend наследует ModelBackend, и для CustomUser
все равно вызывался super().has_perm(), который обращался к Django
Permission таблице в public schema, ожидая PlatformAdmin.

Решение:
Полностью отключен вызов super().has_perm() и super().has_module_perms()
для CustomUser. Теперь для CustomUser используется только role-based
permission checking, а для PlatformAdmin - стандартный ModelBackend.

Изменения в user_roles/auth_backend.py:
- has_perm(): добавлена ветка if is_tenant, которая полностью обрабатывает
  CustomUser без вызова super()
- has_module_perms(): аналогичная логика
- Для PlatformAdmin сохранена проверка через super() (ModelBackend)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-09 23:50:19 +03:00
parent 71ca681073
commit d90b0162c5

View File

@@ -99,45 +99,46 @@ class RoleBasedPermissionBackend(ModelBackend):
if not user_obj.is_authenticated:
return False
# Для CustomUser (пользователи тенантов) пропускаем стандартную проверку Django permissions
# т.к. AUTH_USER_MODEL = PlatformAdmin, и super().has_perm() будет пытаться
# искать permissions для PlatformAdmin, а не для CustomUser
# Определяем тип пользователя
is_tenant = _is_tenant_user(user_obj)
if not is_tenant:
# Для PlatformAdmin проверяем стандартные permissions через ModelBackend
if super().has_perm(user_obj, perm, obj):
# Для CustomUser (пользователи тенантов) НЕ вызываем super().has_perm()
# т.к. AUTH_USER_MODEL = PlatformAdmin, и ModelBackend будет пытаться
# искать permissions в Django Permission таблице для PlatformAdmin
if is_tenant:
# Суперпользователь имеет все права
if user_obj.is_superuser:
return True
# Суперпользователь имеет все права
if user_obj.is_superuser:
return True
# ВАЖНО: В public схеме нет таблиц UserRole/Role!
if _is_public_schema():
return False
# ВАЖНО: В public схеме нет таблиц UserRole/Role!
# Используем только стандартные Django permissions.
if _is_public_schema():
return False
# Для CustomUser получаем роль пользователя в текущем тенанте
user_role = RoleService.get_user_role(user_obj)
if not user_role:
return False
# Для CustomUser получаем роль пользователя в текущем тенанте
# ВАЖНО: RoleService работает с текущей tenant schema!
user_role = RoleService.get_user_role(user_obj)
if not user_role:
return False
# Парсим разрешение: 'app_label.action_modelname'
try:
app_label, codename = perm.split('.')
action = codename.split('_')[0]
except (ValueError, IndexError):
return False
# Парсим разрешение: 'app_label.action_modelname'
# Например: 'products.add_product' -> app_label='products', action='add'
try:
app_label, codename = perm.split('.')
# Извлекаем действие из codename (add_product -> add, change_order -> change)
action = codename.split('_')[0]
except (ValueError, IndexError):
return False
# Проверяем, есть ли у роли это разрешение
role_perms = self.ROLE_PERMISSIONS.get(user_role.code, {})
app_perms = role_perms.get(app_label, [])
# Проверяем, есть ли у роли это разрешение
role_perms = self.ROLE_PERMISSIONS.get(user_role.code, {})
app_perms = role_perms.get(app_label, [])
return action in app_perms
else:
# Для PlatformAdmin проверяем стандартные permissions через ModelBackend
# Суперпользователь имеет все права
if user_obj.is_superuser:
return True
return action in app_perms
# Проверяем через родительский ModelBackend
return super().has_perm(user_obj, perm, obj)
def has_module_perms(self, user_obj, app_label):
"""
@@ -156,28 +157,32 @@ class RoleBasedPermissionBackend(ModelBackend):
if not user_obj.is_authenticated:
return False
# Для CustomUser (пользователи тенантов) пропускаем стандартную проверку Django permissions
# Определяем тип пользователя
is_tenant = _is_tenant_user(user_obj)
if not is_tenant:
# Для PlatformAdmin проверяем стандартные permissions через ModelBackend
if super().has_module_perms(user_obj, app_label):
# Для CustomUser (пользователи тенантов) НЕ вызываем super().has_module_perms()
if is_tenant:
# Суперпользователь имеет все права
if user_obj.is_superuser:
return True
# Суперпользователь имеет все права
if user_obj.is_superuser:
return True
# ВАЖНО: В public схеме нет таблиц UserRole/Role!
if _is_public_schema():
return False
# ВАЖНО: В public схеме нет таблиц UserRole/Role!
# Используем только стандартные Django permissions.
if _is_public_schema():
return False
# Для CustomUser получаем роль пользователя в текущем тенанте
user_role = RoleService.get_user_role(user_obj)
if not user_role:
return False
# Для CustomUser получаем роль пользователя в текущем тенанте
user_role = RoleService.get_user_role(user_obj)
if not user_role:
return False
# Проверяем, есть ли у роли какие-либо разрешения для этого приложения
role_perms = self.ROLE_PERMISSIONS.get(user_role.code, {})
return app_label in role_perms and len(role_perms[app_label]) > 0
else:
# Для PlatformAdmin проверяем стандартные permissions через ModelBackend
# Суперпользователь имеет все права
if user_obj.is_superuser:
return True
# Проверяем, есть ли у роли какие-либо разрешения для этого приложения
role_perms = self.ROLE_PERMISSIONS.get(user_role.code, {})
return app_label in role_perms and len(role_perms[app_label]) > 0
# Проверяем через родительский ModelBackend
return super().has_module_perms(user_obj, app_label)