- Интегрирован django-service-objects 0.7.1 для Service Layer Pattern
- Перенесена вся логика дней рождения из calendar_app → employees:
* UpsertBirthdayEventService - создание/обновление событий ДР
* DeleteBirthdayEventService - удаление событий ДР
* BulkSyncBirthdaysService - массовая синхронизация
* signals_birthday.py - автосинхронизация через post_save/post_delete
* management command sync_birthdays - CLI команда синхронизации
* тесты (11 tests, 6 passing)
- Обновлена миграция 0013_migrate_to_django_scheduler:
* Добавлен ШАГ 5: автоматическая синхронизация дней рождения (131 событие)
* Исключены старые события ДР из миграции (source.endswith(':birthday'))
* Исправлены имена сотрудников (f'{last_name} {first_name}' вместо get_full_name())
* Добавлен цвет #FFC107 для событий дней рождения
- Очищен calendar_app от birthday сервисов:
* Удалены calendar_app/services/birthday_events.py
* Удалены calendar_app/signals_scheduler.py
* Удалены calendar_app/management/commands/sync_birthdays.py
* Удалены calendar_app/tests/test_services.py
* Обновлен apps.py - удалены ссылки на signals_scheduler
- API улучшения:
* Добавлен api/v1/schedule/permissions.py (IsCalendarOwnerOrAdmin)
* Обновлен views.py с правильными permissions
- Документация:
* DJANGO_SERVICE_OBJECTS_INTEGRATION.md - руководство по Service Layer
* CALENDAR_MIGRATION_ANALYSIS.md - анализ миграции
* MODERNIZATION_ANALYSIS.md - анализ модернизации кодовой базы
Цель: подготовка к будущему удалению calendar_app, централизация
логики сотрудников в employees приложении.
Refs: #birthday-refactoring
103 lines
4.0 KiB
Python
103 lines
4.0 KiB
Python
# backend/api/v1/schedule/permissions.py
|
|
"""
|
|
Права доступа для django-scheduler API.
|
|
"""
|
|
from rest_framework import permissions
|
|
from django.contrib.contenttypes.models import ContentType
|
|
from schedule.models import CalendarRelation
|
|
|
|
|
|
class IsOwnerOfCalendar(permissions.BasePermission):
|
|
"""
|
|
Только owner календаря может изменять/удалять календарь.
|
|
Viewer и editor могут только читать календарь.
|
|
"""
|
|
|
|
def has_object_permission(self, request, view, obj):
|
|
"""Проверка прав на календарь."""
|
|
# SAFE_METHODS (GET, HEAD, OPTIONS) доступны всем участникам
|
|
if request.method in permissions.SAFE_METHODS:
|
|
return True
|
|
|
|
# Только owner может изменять/удалять календарь
|
|
return self._is_owner(obj, request.user)
|
|
|
|
@staticmethod
|
|
def _is_owner(calendar, user):
|
|
"""Проверка, является ли пользователь владельцем календаря."""
|
|
if user.is_staff or user.is_superuser:
|
|
return True
|
|
|
|
from django.contrib.auth import get_user_model
|
|
User = get_user_model()
|
|
ct = ContentType.objects.get_for_model(User)
|
|
|
|
return CalendarRelation.objects.filter(
|
|
calendar=calendar,
|
|
content_type=ct,
|
|
object_id=user.id,
|
|
distinction='owner'
|
|
).exists()
|
|
|
|
|
|
class CanEditCalendar(permissions.BasePermission):
|
|
"""
|
|
Права для событий в календаре:
|
|
- owner: полный доступ (create, read, update, delete)
|
|
- editor: может создавать/изменять/удалять события (create, read, update, delete)
|
|
- viewer: только чтение (read)
|
|
"""
|
|
|
|
def has_permission(self, request, view):
|
|
"""Проверка прав на создание события."""
|
|
# Для создания события нужно быть owner или editor календаря
|
|
if view.action == 'create':
|
|
calendar_id = request.data.get('calendar')
|
|
if not calendar_id:
|
|
return False
|
|
|
|
from schedule.models import Calendar
|
|
try:
|
|
calendar = Calendar.objects.get(id=calendar_id)
|
|
except Calendar.DoesNotExist:
|
|
return False
|
|
|
|
return self._can_edit(calendar, request.user)
|
|
|
|
return True
|
|
|
|
def has_object_permission(self, request, view, obj):
|
|
"""Проверка прав на событие."""
|
|
# Event object
|
|
event = obj
|
|
calendar = event.calendar
|
|
|
|
# SAFE_METHODS (GET, HEAD, OPTIONS) доступны всем участникам
|
|
if request.method in permissions.SAFE_METHODS:
|
|
return True
|
|
|
|
# Для изменения/удаления нужны права editor или owner
|
|
return self._can_edit(calendar, request.user)
|
|
|
|
@staticmethod
|
|
def _can_edit(calendar, user):
|
|
"""Проверка, может ли пользователь редактировать события в календаре."""
|
|
if user.is_staff or user.is_superuser:
|
|
return True
|
|
|
|
from django.contrib.auth import get_user_model
|
|
User = get_user_model()
|
|
ct = ContentType.objects.get_for_model(User)
|
|
|
|
# Проверяем роль пользователя в календаре
|
|
try:
|
|
relation = CalendarRelation.objects.get(
|
|
calendar=calendar,
|
|
content_type=ct,
|
|
object_id=user.id
|
|
)
|
|
# Owner и editor могут редактировать, viewer - нет
|
|
return relation.distinction in ['owner', 'editor']
|
|
except CalendarRelation.DoesNotExist:
|
|
return False
|