Управление доступом в модуле tasks (ITaskAccess / TaskAccess)

Документ описывает права на задачи и колонки в рамках модуля tasks. Все проверки делегируются в IProjectAccess (модуль projects), т.к. задачи/колонки живут внутри досок проектов.

1. Порт ITaskAccess

Файл: modules/tasks/application/port/ITaskAccess.php

interface ITaskAccess
{
    public function getProjectIdsByColumnId(int $columnId): array;
    public function canViewTask(int $userId, int $taskId): bool;
    public function canCreateTask(int $userId, int $boardId): bool;
    public function canUpdateTask(int $userId, int $taskId): bool;
    public function canDeleteTask(int $userId, int $taskId): bool;
    public function canHardDeleteTask(int $userId, int $taskId): bool;
    public function canRestoreTask(int $userId, int $taskId): bool;
    public function canAssignTask(int $userId, int $taskId, int $assigneeId): bool;
    public function canCommentOnTask(int $userId, int $taskId): bool;
    public function canAddStickerToTask(int $userId, int $taskId): bool;
    public function canCreateColumn(int $userId, int $boardId): bool;
    public function canUpdateColumn(int $userId, int $columnId): bool;
    public function canDeleteColumn(int $userId, int $columnId): bool;
    public function canMoveTaskToColumn(int $userId, int $taskId, int $columnId): bool;
}

2. Реализация TaskAccess

Файл: modules/tasks/infrastructure/access/TaskAccess.php

Зависимости: ITaskRepository, IBoardColumnRepository, IProjectAccess.

Правила

МетодЛогика
getProjectIdsByColumnIdколонка → доска → проект (через IProjectAccess::getProjectIdByBoardId)
canViewTaskзадача существует && canViewBoard(boardId)
canCreateTaskcanViewBoard(boardId)
canUpdateTaskcanViewTask
canDeleteTaskcanViewTask
canHardDeleteTaskcanManageBoard(boardId)
canRestoreTaskcanViewTask
canAssignTaskcanViewTask
canCommentOnTaskcanViewTask
canAddStickerToTaskcanViewTask
canCreateColumncanManageBoard(boardId)
canUpdateColumnколонка существует && canManageBoard(boardId)
canDeleteColumnколонка пустая (нет задач) && canManageBoard(boardId)
canMoveTaskToColumnзадача и колонка существуют, одна доска, canViewBoard(boardId)

Ключевые нюансы

3. Использование в хендлерах

if (!$this->taskAccess->canViewTask($userId, $taskId)) {
    throw new PermissionDeniedException('Нет доступа к задаче');
}

Все хендлеры модуля получают ITaskAccess через DI.

4. Диаграмма делегирования

graph TD
    T[TaskAccess] -->|canViewTask| P[IProjectAccess]
    T -->|canManageBoard| P
    T -->|getProjectIdByBoardId| P
    P --> PB[Project: какая доска/проект]
    T -->|findById| TR[ITaskRepository]
    T -->|countByColumn| TR
    T -->|findById| CR[IBoardColumnRepository]