f7cloud_client/apps/mail/docs/PLAN-FOLDER-SHARING.md
root 8b6a0139db f7cloud_client
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-17 22:59:26 +00:00

15 KiB
Raw Permalink Blame History

План: шаринг папок почты (доступ к папкам других пользователей)

Документ описывает планируемый функционал и возможность реализации без внесения изменений в код. После согласования можно переходить к реализации по этапам.


1. Требуемый функционал (кратко)

  1. Меню папки (три точки)
    В выпадающем меню, которое открывается по нажатию на три точки справа от папки, — пункт «Поделиться» с возможностью выбрать пользователей и/или группы и выдать доступ к папке.

  2. Два уровня прав

    • Только просмотр — чтение писем в папке, без изменений.
    • Полный доступ — чтение, добавление/изменение/удаление писем, создание подпапок и управление ими.
  3. Блок «Папки других пользователей»
    В боковой панели (список ящиков/папок) — отдельная секция «Папки других пользователей», где отображаются:

    • аккаунт (пользователь), который предоставил доступ;
    • список расшаренных папок с подпапками.

2. Оценка возможности реализации

Вывод: реализуемо.
Приложение уже опирается на понятия «аккаунт» и «папка (mailbox)», есть пример шаринга (TextBlockShare), контекстное меню папок и навигация по папкам. Нужно добавить слой «шаринга папок» и продумать, как при открытии папки и работе с письмами учитывать «режим shared» и права.

Ниже — что уже есть и что нужно добавить.


3. Текущая архитектура (релевантные части)

  • Папки (mailbox): сущность Mailbox привязана к account_id. Список папок загружается по аккаунту (MailboxesController::index(accountId)), маршрут вида /box/{mailboxId}.
  • Письма: доступ через MessagesController по mailboxId; везде проверяется принадлежность папки текущему пользователю через getMailbox(currentUserId, mailboxId).
  • Навигация: Navigation.vue строит список из аккаунтов и их папок; каждая папка — NavigationMailbox.vue с контекстным меню (слот #actions).
  • Шаринг в приложении: уже есть модель «объект + с кем поделились» — TextBlockShare (тип, shareWith, id объекта). Аналогичная таблица для папок — естественный следующий шаг.

Ограничение: папки и письма жёстко привязаны к владельцу аккаунта. Чтобы «открыть чужую папку», бэкенд должен:

  • знать, что эта папка расшарена текущему пользователю (или группе, в которой он состоит);
  • при запросах писем/действий использовать аккаунт владельца папки, но проверять права текущего пользователя по таблице шаринга.

4. Предлагаемая архитектура

4.1. Модель данных (бэкенд)

  • Новая таблица (например, oc_mail_mailbox_shares):

    • id
    • owner_user_id — владелец папки (кто шарит)
    • account_id — id почтового аккаунта владельца
    • mailbox_id — id папки в БД (у владельца)
    • share_typeuser | group
    • share_with — uid пользователя или gid группы
    • permissionread | read_write
    • created_at (опционально)
  • Подпапки:
    При шаринге папки доступ предоставляется и на все подпапки с тем же уровнем прав (логика «папка + дерево вниз»). В блоке «Папки других пользователей» отображаются расшаренная папка и её подпапки; подпапки доступны по тому же shareId (для корневой расшаренной папки) или по правилу «дочерняя папка владельца, чья родительская папка расшарена» — при открытии подпапки бэкенд проверяет, что её родитель (или сама папка) фигурирует в шаринге для текущего пользователя.

4.2. Бэкенд: новые/изменённые API

Назначение Метод/маршрут Описание
Создать шаринг POST /api/mailboxes/{id}/share Тело: shareWith, shareType (user/group), permission (read/read_write). Проверка: папка принадлежит текущему пользователю.
Удалить шаринг DELETE /api/mailbox-shares/{shareId} Только владелец.
Список «кому расшарено» GET /api/mailboxes/{id}/shares Для владельца папки — кто имеет доступ.
Список «расшарено мне» GET /api/mailbox-shares (или shared-with-me) Для текущего пользователя: список шарингов (владелец, папка, подпапки, право). Используется для блока «Папки других пользователей».
  • Чтение писем в расшаренной папке:
    Варианты:

    • Ввести «виртуальный» идентификатор расшаренной папки для текущего пользователя (например, shareId). Маршрут вида /box/shared/{shareId}.
    • Или передавать в существующий API писем пару mailboxId + sharedByUserId (или shareId).
      В обоих случаях бэкенд: по shareId (или паре) находит запись в oc_mail_mailbox_shares, проверяет, что shareWith — текущий пользователь (или он в группе), и что permission не ниже read; затем загружает письма через владельца: getMailbox(owner_user_id, mailbox_id) и существующую логику выборки писем.
  • Действия с письмами (перемещение, удаление, флаги и т.д.):
    Те же контроллеры, но при вызове с контекстом «расшаренная папка» дополнительно проверять permission === read_write. При read — возвращать 403 на изменение.

  • Создание подпапок в расшаренной папке:
    Разрешать только при read_write. Создание подпапки на IMAP/бэкенде выполнять от имени владельца аккаунта (как сейчас делается для «своих» папок), но инициировать действие может только пользователь с правом «полный доступ».

4.3. Фронтенд

  • Меню папки (NavigationMailbox.vue, выпадающее по нажатию на три точки справа от папки):

    • Добавить пункт «Поделиться» (иконка «Share»).
    • Условие показа: только для «своих» папок (не для элементов из блока «Папки других пользователей»), при необходимости — исключить системные папки (Входящие/Корзина и т.д.) по тем же правилам, что и для «Переместить папку».
  • Модальное окно «Поделиться папкой»:

    • Выбор получателя: пользователь и/или группа (автодополнение как в «Поделиться» в Файлах или как при выборе получателей в письме).
    • Выбор права: «Только просмотр» / «Полный доступ».
    • Список уже имеющих доступ (при открытии из «Управление доступом» или повторном открытии «Поделиться») и возможность забрать доступ.
  • Блок «Папки других пользователей» в Navigation.vue:

    • Отдельная секция под списком своих аккаунтов.
    • Заголовок: «Папки других пользователей».
    • Данные: результат GET /api/mailbox-shares (или аналог).
    • Группировка по владельцу: под каждым владельцем — список папок (и при варианте B — подпапок).
    • Каждая папка ведёт на маршрут вида /box/shared/{shareId} (или эквивалент с sharedBy + mailboxId).
  • Роут и представление «расшаренная папка»:

    • Новый маршрут, например /box/shared/:shareId.
    • В Home.vue / хранилище: при таком маршруте не искать папку в своих аккаунтах, а подставлять «виртуальную» папку из ответа API shared-with-me (название, владелец, право).
    • Загрузка писем и превью — через существующие API, но с параметром shareId (или аналог), чтобы бэкенд работал в режиме «расшаренная папка».
  • Ограничение UI по праву «только просмотр»:

    • Скрыть или отключить: перемещение писем, удаление, создание подпапок, «Очистить папку» и т.п.
    • Кнопки «Ответить»/«Переслать» — по желанию оставить (это не изменение папки владельца).

5. Открытые вопросы и риски

  1. Группы: при share_type = group проверка доступа: текущий пользователь входит в группу (через IGroupManager). Удаление/изменение шаринга — только владелец папки.
  2. Кэш и синхронизация: письма в расшаренной папке читаются из кэша/IMAP владельца. Нужно понимать, что синхронизация папки выполняется для аккаунта владельца; при первом открытии расшаренной папки кэш владельца может быть пустым — тогда нужна явная синхронизация (как для своих папок) или отложенная подгрузка.
  3. Производительность: при большом числе шарингов запрос «расшарено мне» может быть тяжёлым; имеет смысл отдавать только метаданные (владелец, папка, право), без полного дерева подпапок в первом запросе.
  4. Подпапки при шаринге: реализуются с самого начала: при шаринге папки доступ даётся на неё и на все подпапки; в API «расшарено мне» возвращается дерево (папка + подпапки); при открытии подпапки проверяется, что она является потомком расшаренной папки владельца.

6. Этапы реализации (предварительно)

Этап Содержание
1 Таблица и сущность MailboxShare, маппер, миграция.
2 Сервис/контроллер шаринга: создание/удаление/список по папке, список «расшарено мне».
3 Изменение логики доступа к папке/письмам: при наличии shareId (или контекста shared) разрешать доступ с проверкой прав и от имени владельца.
4 Фронтенд: пункт «Поделиться» в контекстном меню, модальное окно выбора пользователей/групп и прав.
5 Фронтенд: секция «Папки других пользователей», маршрут /box/shared/:shareId, подстановка данных в навигации и в представлении папки.
6 Ограничение действий в UI и в API по праву «только просмотр».
7 Тесты и доработки (подпапки, группы, граничные случаи).

7. Итог

  • Функционал реализуем в рамках текущей архитектуры Mail.
  • Основная работа: новый слой шаринга (БД + API + проверки прав) и доработка навигации/контекстного меню/маршрутизации на фронтенде.
  • Риски управляемые; открытые моменты (подпапки, кэш, производительность) можно зафиксировать в конфиге или упростить в первой версии.

После согласования плана можно приступать к реализации по этапам без активных изменений в текущем коде до начала этапа 1.