from django.db import models from django.contrib.auth.models import AbstractBaseUser, BaseUserManager from django.utils import timezone import uuid class CustomUserManager(BaseUserManager): def create_user(self, email, name, password=None, **extra_fields): if not email: raise ValueError('Email обязателен') email = self.normalize_email(email) # SECURITY FIX: Явно устанавливаем флаги безопасности в False по умолчанию # Обычные пользователи НЕ должны иметь доступ к админке extra_fields.setdefault('is_staff', False) extra_fields.setdefault('is_superuser', False) user = self.model(email=email, name=name, **extra_fields) user.set_password(password) user.save(using=self._db) return user def create_superuser(self, email, name, password=None, **extra_fields): extra_fields.setdefault('is_staff', True) extra_fields.setdefault('is_superuser', True) extra_fields.setdefault('is_active', True) # Суперпользователь автоматически имеет подтвержденный email extra_fields.setdefault('is_email_confirmed', True) if extra_fields.get('is_staff') is not True: raise ValueError('Суперпользователь должен иметь is_staff=True.') if extra_fields.get('is_superuser') is not True: raise ValueError('Суперпользователь должен иметь is_superuser=True.') user = self.create_user(email, name, password, **extra_fields) # Устанавливаем дату подтверждения email if user.is_email_confirmed and not user.email_confirmed_at: user.email_confirmed_at = timezone.now() user.save() return user class CustomUser(AbstractBaseUser): """ Пользователь тенанта (магазина). ВАЖНО: Эта модель в TENANT_APPS - каждый тенант имеет свою таблицу! Один email в разных тенантах = разные записи в разных схемах БД. Полная изоляция обеспечивается на уровне PostgreSQL schemas. НЕ является AUTH_USER_MODEL (это PlatformAdmin). НЕ использует Django Groups/Permissions - используется своя система ролей (UserRole). """ email = models.EmailField(unique=True) name = models.CharField(max_length=100) # Стандартные поля для совместимости с Django auth is_active = models.BooleanField(default=True) is_staff = models.BooleanField(default=False) # Для доступа к админке (если нужно) is_superuser = models.BooleanField(default=False) # Для полных прав в тенанте date_joined = models.DateTimeField(default=timezone.now) is_email_confirmed = models.BooleanField(default=False) email_confirmation_token = models.UUIDField(default=uuid.uuid4, editable=False, unique=True) email_confirmed_at = models.DateTimeField(null=True, blank=True) password_reset_token = models.UUIDField(null=True, blank=True, editable=False, unique=True) USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['name'] objects = CustomUserManager() class Meta: verbose_name = "Пользователь магазина" verbose_name_plural = "Пользователи магазина" def __str__(self): return self.email def has_perm(self, perm, obj=None): """ Проверка разрешения через authentication backends. Django вызывает все зарегистрированные backends по очереди. """ if not self.is_active: return False # Импортируем здесь, чтобы избежать циклических импортов from django.contrib.auth import get_backends for backend in get_backends(): if hasattr(backend, 'has_perm'): result = backend.has_perm(self, perm, obj) if result is not None: # Backend обработал запрос return result return False def has_module_perms(self, app_label): """ Проверка разрешений для модуля через authentication backends. """ if not self.is_active: return False from django.contrib.auth import get_backends for backend in get_backends(): if hasattr(backend, 'has_module_perms'): result = backend.has_module_perms(self, app_label) if result is not None: # Backend обработал запрос return result return False def generate_confirmation_token(self): """Генерирует новый токен для подтверждения email""" self.email_confirmation_token = uuid.uuid4() self.save() return self.email_confirmation_token def confirm_email(self): """Подтверждает email пользователя""" self.is_email_confirmed = True self.email_confirmed_at = timezone.now() self.save() def get_tenant_role(self): """Получить роль пользователя в текущем тенанте""" from user_roles.services import RoleService return RoleService.get_user_role(self) def has_role(self, *role_codes): """Проверить, имеет ли пользователь одну из указанных ролей""" from user_roles.services import RoleService return RoleService.user_has_role(self, *role_codes) @property def is_owner(self): """Является ли пользователь владельцем""" return self.has_role('owner') @property def is_manager(self): """Является ли пользователь менеджером""" return self.has_role('manager') @property def is_florist(self): """Является ли пользователь флористом""" return self.has_role('florist') @property def is_courier(self): """Является ли пользователь курьером""" return self.has_role('courier')