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