Files
octopus/myproject/user_roles/models.py
Andrey Smakotin f4e7ad0aac feat: implement user roles system with tenant isolation
Добавлена система ролей пользователей для управления доступом в multi-tenant приложении.

Новые роли:
- Владелец (Owner): полный доступ, управление пользователями
- Менеджер (Manager): управление заказами, клиентами, товарами, складом
- Флорист (Florist): работа с заказами и складскими операциями
- Курьер (Courier): роль создана, права будут определены позже

Архитектура:
- Роли автоматически изолируются по тенантам через django-tenants (TENANT_APPS)
- Не требуется FK на Client/Tenant - изоляция через PostgreSQL schemas
- Роли автоматически создаются при создании нового тенанта

Компоненты:
- user_roles/models.py: модели Role и UserRole
- user_roles/services.py: RoleService для управления ролями
- user_roles/decorators.py: @role_required, @owner_required
- user_roles/mixins.py: RoleBasedAdminMixin, OwnerOnlyAdminMixin
- user_roles/admin.py: админка для управления ролями
- user_roles/management/commands/init_roles.py: команда для инициализации

Изменения:
- accounts/models.py: добавлены helper методы (is_owner, has_role, etc)
- settings.py: добавлен user_roles в TENANT_APPS
- tenants/admin.py: автосоздание ролей при создании тенанта

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 18:06:47 +03:00

102 lines
3.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from django.db import models
from django.conf import settings
from django.utils import timezone
class Role(models.Model):
"""
Роль пользователя.
ВАЖНО: Модель находится в TENANT_APPS, поэтому автоматически изолируется
по тенантам через django-tenants. Каждый тенант имеет свой набор ролей
в своей PostgreSQL schema.
Не нужно явно связывать с тенантом через FK - изоляция происходит автоматически!
"""
OWNER = 'owner'
MANAGER = 'manager'
FLORIST = 'florist'
COURIER = 'courier'
ROLE_CHOICES = [
(OWNER, 'Владелец'),
(MANAGER, 'Менеджер'),
(FLORIST, 'Флорист'),
(COURIER, 'Курьер'),
]
code = models.CharField(
max_length=20,
choices=ROLE_CHOICES,
unique=True,
verbose_name="Код роли"
)
name = models.CharField(
max_length=100,
verbose_name="Название"
)
description = models.TextField(
blank=True,
verbose_name="Описание"
)
is_system = models.BooleanField(
default=True,
verbose_name="Системная роль",
help_text="Системные роли нельзя удалить"
)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = "Роль"
verbose_name_plural = "Роли"
ordering = ['code']
def __str__(self):
return self.name
class UserRole(models.Model):
"""
Роль пользователя в текущем тенанте.
ВАЖНО: Эта модель НЕ связывает пользователя с тенантом!
Связь с тенантом обеспечивается автоматически через django-tenants
(модель в TENANT_APPS = находится в schema тенанта).
UserRole просто говорит: "этот пользователь имеет эту роль" (в рамках текущего тенанта).
Один пользователь = одна роль в рамках одного тенанта.
"""
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='tenant_role',
verbose_name="Пользователь",
help_text="Пользователь из public schema (SHARED_APPS)"
)
role = models.ForeignKey(
Role,
on_delete=models.PROTECT,
related_name='users',
verbose_name="Роль"
)
created_at = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(
settings.AUTH_USER_MODEL,
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='created_user_roles',
verbose_name="Создал"
)
is_active = models.BooleanField(
default=True,
verbose_name="Активен"
)
class Meta:
verbose_name = "Роль пользователя"
verbose_name_plural = "Роли пользователей"
def __str__(self):
return f"{self.user.email} - {self.role.name}"