15 KiB
План: шаринг папок почты (доступ к папкам других пользователей)
Документ описывает планируемый функционал и возможность реализации без внесения изменений в код. После согласования можно переходить к реализации по этапам.
1. Требуемый функционал (кратко)
-
Меню папки (три точки)
В выпадающем меню, которое открывается по нажатию на три точки справа от папки, — пункт «Поделиться» с возможностью выбрать пользователей и/или группы и выдать доступ к папке. -
Два уровня прав
- Только просмотр — чтение писем в папке, без изменений.
- Полный доступ — чтение, добавление/изменение/удаление писем, создание подпапок и управление ими.
-
Блок «Папки других пользователей»
В боковой панели (список ящиков/папок) — отдельная секция «Папки других пользователей», где отображаются:- аккаунт (пользователь), который предоставил доступ;
- список расшаренных папок с подпапками.
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):idowner_user_id— владелец папки (кто шарит)account_id— id почтового аккаунта владельцаmailbox_id— id папки в БД (у владельца)share_type—user|groupshare_with— uid пользователя или gid группыpermission—read|read_writecreated_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. Открытые вопросы и риски
- Группы: при
share_type = groupпроверка доступа: текущий пользователь входит в группу (черезIGroupManager). Удаление/изменение шаринга — только владелец папки. - Кэш и синхронизация: письма в расшаренной папке читаются из кэша/IMAP владельца. Нужно понимать, что синхронизация папки выполняется для аккаунта владельца; при первом открытии расшаренной папки кэш владельца может быть пустым — тогда нужна явная синхронизация (как для своих папок) или отложенная подгрузка.
- Производительность: при большом числе шарингов запрос «расшарено мне» может быть тяжёлым; имеет смысл отдавать только метаданные (владелец, папка, право), без полного дерева подпапок в первом запросе.
- Подпапки при шаринге: реализуются с самого начала: при шаринге папки доступ даётся на неё и на все подпапки; в API «расшарено мне» возвращается дерево (папка + подпапки); при открытии подпапки проверяется, что она является потомком расшаренной папки владельца.
6. Этапы реализации (предварительно)
| Этап | Содержание |
|---|---|
| 1 | Таблица и сущность MailboxShare, маппер, миграция. |
| 2 | Сервис/контроллер шаринга: создание/удаление/список по папке, список «расшарено мне». |
| 3 | Изменение логики доступа к папке/письмам: при наличии shareId (или контекста shared) разрешать доступ с проверкой прав и от имени владельца. |
| 4 | Фронтенд: пункт «Поделиться» в контекстном меню, модальное окно выбора пользователей/групп и прав. |
| 5 | Фронтенд: секция «Папки других пользователей», маршрут /box/shared/:shareId, подстановка данных в навигации и в представлении папки. |
| 6 | Ограничение действий в UI и в API по праву «только просмотр». |
| 7 | Тесты и доработки (подпапки, группы, граничные случаи). |
7. Итог
- Функционал реализуем в рамках текущей архитектуры Mail.
- Основная работа: новый слой шаринга (БД + API + проверки прав) и доработка навигации/контекстного меню/маршрутизации на фронтенде.
- Риски управляемые; открытые моменты (подпапки, кэш, производительность) можно зафиксировать в конфиге или упростить в первой версии.
После согласования плана можно приступать к реализации по этапам без активных изменений в текущем коде до начала этапа 1.