""" Permissions для communications API """ import rules from rest_framework import permissions from ..utils import user_can_access_chat class ChatPermission(permissions.BasePermission): """ Проверка прав доступа к чатам Правила: - GET/HEAD/OPTIONS - проверка через user_can_access_chat (учитывает participants) - PUT/PATCH - владелец или админ (change_chat через django-rules) - DELETE - только владелец (delete_chat через django-rules) """ def has_permission(self, request, view): """Базовая проверка - пользователь авторизован""" return request.user and request.user.is_authenticated def has_object_permission(self, request, view, obj): """Проверка прав на конкретный объект (чат)""" # Custom actions имеют свои проверки прав внутри if hasattr(view, "action") and view.action in [ "add_member", "remove_member", "pin", "notifications", "change_role", "leave", "mark_read", "messages", "messages_around", ]: # Для mark_read и загрузки сообщений достаточно иметь доступ к чату if view.action in ["mark_read", "messages", "messages_around"]: return user_can_access_chat(obj, request.user) return True # Безопасные методы - проверяем доступ через user_can_access_chat # (это обходит prefetch cache и делает прямой запрос) if request.method in permissions.SAFE_METHODS: return user_can_access_chat(obj, request.user) # Изменение чата - только владелец или админ if request.method in ["PUT", "PATCH"]: return rules.test_rule( "communications.change_chat", request.user, obj ) # Удаление чата - только владелец if request.method == "DELETE": return rules.test_rule( "communications.delete_chat", request.user, obj ) return False class MessagePermission(permissions.BasePermission): """ Проверка прав доступа к сообщениям через django-rules Правила: - GET - доступ к чату сообщения - POST создание - участник чата + can_send_messages - POST react/unreact - участник чата (включая гостей) - PUT/PATCH - автор сообщения - DELETE - автор или админ чата """ def has_permission(self, request, view): """Базовая проверка - пользователь авторизован""" if not (request.user and request.user.is_authenticated): return False # При создании сообщения проверяем права на отправку в чат if request.method == "POST" and view.action in ["create", "upload"]: # Получаем chat_id из данных запроса chat_id = request.data.get("chat") or request.data.get("chat_id") if not chat_id: # Если нет chat_id, DRF вернет ошибку валидации позже return True # Проверяем права на отправку сообщений try: from ..models import Chat chat = Chat.objects.get(pk=chat_id) # Используем django-rules проверку return rules.test_rule( "communications.send_message", request.user, chat ) except Chat.DoesNotExist: # Если чат не найден, сам view вернет 404. return True return True def has_object_permission(self, request, view, obj): """Проверка прав на конкретное сообщение""" # Custom actions с POST (react, unreact) - доступны всем участникам if hasattr(view, "action") and view.action in ["react", "unreact"]: # Для реакций достаточно быть участником чата # (даже гость может ставить реакции) return rules.test_rule( "communications.view_message", request.user, obj ) # Просмотр - доступ к чату if request.method in permissions.SAFE_METHODS: return rules.test_rule( "communications.view_message", request.user, obj ) # Редактирование - автор if request.method in ["PUT", "PATCH"]: return rules.test_rule( "communications.change_message", request.user, obj ) # Удаление - автор или админ if request.method == "DELETE": return rules.test_rule( "communications.delete_message", request.user, obj ) return False