Corp/backend/tests/test_calendar_permissions.py
Игорь Надеин 7a055c79cb fix: исправлены JS ошибки в календаре и emoji-picker
- Создана заглушка для calendarEventDragDrop.js с экспортом initCalendarEventDragDrop
- Закомментирован импорт несуществующего database.js в emoji-picker/index.js
- Исправлена ошибка 'does not provide an export named initCalendarEventDragDrop'
- Исправлена ошибка 404 для emoji-picker/database.js
2026-02-23 12:26:03 +03:00

301 lines
11 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.

"""
Тесты для проверки прав доступа к календарям.
Проверяет исправление бага, где обычные пользователи не могли
создавать события в глобальных календарях с правом can_edit.
"""
from datetime import date
import pytest
from calendar_app.models import Calendar, CalendarSubscription, CalendarVisibility
from django.contrib.auth import get_user_model
from rest_framework import status
from rest_framework.test import APIClient
User = get_user_model()
@pytest.fixture
def api_client():
"""API клиент."""
return APIClient()
@pytest.fixture
def admin_user(db):
"""Создаёт администратора."""
return User.objects.create_superuser(
username="admin", email="admin@test.com", password="admin123"
)
@pytest.fixture
def regular_user(db):
"""Создаёт обычного пользователя."""
return User.objects.create_user(
username="user",
email="user@test.com",
password="user123",
phone_number="+79001234567",
send_activation_email=False,
)
@pytest.fixture
def global_calendar(db, admin_user):
"""Создаёт глобальный календарь."""
return Calendar.objects.create(
title="Общий календарь",
description="Календарь для всех",
visibility=CalendarVisibility.PUBLIC,
default_can_edit=False, # По умолчанию не могут редактировать
created_by=admin_user,
)
@pytest.mark.django_db
class TestGlobalCalendarPermissions:
"""Тесты прав доступа для глобальных календарей."""
def test_admin_can_create_event_in_global_calendar(
self, api_client, admin_user, global_calendar
):
"""Админ может создавать события в глобальном календаре."""
api_client.force_authenticate(user=admin_user)
response = api_client.post(
"/api/v1/calendar/events/",
{
"calendar_id": global_calendar.id,
"title": "Встреча админов",
"start_date": "2026-03-01",
"all_day": True,
},
format="json",
)
assert response.status_code == status.HTTP_201_CREATED
assert response.data["title"] == "Встреча админов"
def test_regular_user_cannot_create_without_permission(
self, api_client, regular_user, global_calendar
):
"""Обычный пользователь НЕ может создавать без прав."""
api_client.force_authenticate(user=regular_user)
response = api_client.post(
"/api/v1/calendar/events/",
{
"calendar_id": global_calendar.id,
"title": "Попытка создать",
"start_date": "2026-03-01",
"all_day": True,
},
format="json",
)
assert response.status_code == status.HTTP_403_FORBIDDEN
def test_regular_user_can_create_with_subscription(
self, api_client, regular_user, global_calendar
):
"""Обычный пользователь МОЖЕТ создавать с подпиской can_edit=True."""
# Создаём подписку с правом редактирования
CalendarSubscription.objects.create(
calendar=global_calendar, user=regular_user, can_edit=True
)
api_client.force_authenticate(user=regular_user)
response = api_client.post(
"/api/v1/calendar/events/",
{
"calendar_id": global_calendar.id,
"title": "Событие пользователя",
"start_date": "2026-03-01",
"all_day": True,
},
format="json",
)
assert response.status_code == status.HTTP_201_CREATED
assert response.data["title"] == "Событие пользователя"
def test_regular_user_cannot_create_with_readonly_subscription(
self, api_client, regular_user, global_calendar
):
"""Пользователь НЕ может создавать с подпиской can_edit=False."""
# Создаём подписку БЕЗ права редактирования
CalendarSubscription.objects.create(
calendar=global_calendar, user=regular_user, can_edit=False
)
api_client.force_authenticate(user=regular_user)
response = api_client.post(
"/api/v1/calendar/events/",
{
"calendar_id": global_calendar.id,
"title": "Попытка создать",
"start_date": "2026-03-01",
"all_day": True,
},
format="json",
)
assert response.status_code == status.HTTP_403_FORBIDDEN
def test_regular_user_can_create_when_default_can_edit_true(
self, api_client, regular_user, admin_user
):
"""Пользователь МОЖЕТ создавать если default_can_edit=True."""
# Создаём календарь с default_can_edit=True
calendar = Calendar.objects.create(
title="Открытый календарь",
visibility=CalendarVisibility.PUBLIC,
default_can_edit=True, # ✅ Все могут редактировать
created_by=admin_user,
)
# Подписываем пользователя (обязательно для доступа)
CalendarSubscription.objects.create(
calendar=calendar, user=regular_user, can_edit=True
)
api_client.force_authenticate(user=regular_user)
response = api_client.post(
"/api/v1/calendar/events/",
{
"calendar_id": calendar.id,
"title": "Открытое событие",
"start_date": "2026-03-01",
"all_day": True,
},
format="json",
)
assert response.status_code == status.HTTP_201_CREATED
assert response.data["title"] == "Открытое событие"
@pytest.mark.django_db
class TestLegacyCalendarPermissions:
"""Тесты обратной совместимости с legacy календарями."""
def test_regular_user_cannot_create_in_company_calendar(
self, api_client, regular_user
):
"""Обычный пользователь НЕ может создавать в календаре компании (legacy)."""
api_client.force_authenticate(user=regular_user)
response = api_client.post(
"/api/v1/calendar/events/",
{
# Без calendar_id, department_id, employee_id = календарь компании
"title": "Попытка создать",
"start_date": "2026-03-01",
"all_day": True,
},
format="json",
)
assert response.status_code == status.HTTP_403_FORBIDDEN
def test_admin_can_create_in_company_calendar(self, api_client, admin_user):
"""Админ МОЖЕТ создавать в календаре компании (legacy)."""
api_client.force_authenticate(user=admin_user)
response = api_client.post(
"/api/v1/calendar/events/",
{
"title": "Собрание компании",
"start_date": "2026-03-01",
"all_day": True,
},
format="json",
)
assert response.status_code == status.HTTP_201_CREATED
assert response.data["title"] == "Собрание компании"
def test_user_can_create_in_personal_calendar(self, api_client, regular_user):
"""Пользователь МОЖЕТ создавать в своём личном календаре."""
api_client.force_authenticate(user=regular_user)
response = api_client.post(
"/api/v1/calendar/events/",
{
"employee_id": regular_user.id,
"title": "Личное событие",
"start_date": "2026-03-01",
"all_day": True,
},
format="json",
)
assert response.status_code == status.HTTP_201_CREATED
assert response.data["title"] == "Личное событие"
@pytest.mark.django_db
class TestEventUpdateDeletePermissions:
"""Тесты прав на обновление и удаление событий."""
def test_user_can_update_own_event_in_global_calendar(
self, api_client, regular_user, global_calendar
):
"""Пользователь МОЖЕТ обновлять своё событие если есть права."""
from calendar_app.models import CalendarEvent
# Даём права
CalendarSubscription.objects.create(
calendar=global_calendar, user=regular_user, can_edit=True
)
# Создаём событие
event = CalendarEvent.objects.create(
calendar=global_calendar,
title="Моё событие",
start_date=date(2026, 3, 1),
all_day=True,
created_by=regular_user,
)
api_client.force_authenticate(user=regular_user)
response = api_client.patch(
f"/api/v1/calendar/events/{event.id}/",
{"title": "Обновлённое событие"},
format="json",
)
assert response.status_code == status.HTTP_200_OK
assert response.data["title"] == "Обновлённое событие"
def test_user_cannot_update_without_permission(
self, api_client, regular_user, global_calendar, admin_user
):
"""Пользователь НЕ может обновлять без прав."""
from calendar_app.models import CalendarEvent
# Создаём событие БЕЗ прав у пользователя
event = CalendarEvent.objects.create(
calendar=global_calendar,
title="Событие админа",
start_date=date(2026, 3, 1),
all_day=True,
created_by=admin_user,
)
api_client.force_authenticate(user=regular_user)
response = api_client.patch(
f"/api/v1/calendar/events/{event.id}/",
{"title": "Попытка обновить"},
format="json",
)
assert response.status_code == status.HTTP_403_FORBIDDEN