Начинающие разработчики часто пытаются настраивать права в Payload CMS через middleware или глобальные переменные. Это приводит к дырам в безопасности и громоздкому коду, который сложно поддерживать. Наша команда, имеющая пятилетний опыт в TypeScript и Payload CMS, предлагает иной подход — каждое правило доступа оформляется в виде чистой TypeScript-функции контекста запроса. Функция возвращает true (доступ разрешён), false (запрещён) или объект-условие, который Payload добавляет к запросу БД в виде MongoDB $match или SQL WHERE. Такой подход сокращает объём кода в 3–4 раза по сравнению с middleware и исключает возможность пропустить проверку прав. Вместо YAML-конфигов и GUI-настроек — только код, контролирующий каждое действие: чтение, создание, обновление, удаление. Payload CMS Access Control описывает базовые принципы — мы же покажем готовые решения для типовых сценариев, которые успешно применялись в более чем 15 коммерческих проектах.
Как работают функции доступа?
Каждая access-функция принимает объект с req (включает req.user) и опционально id документа. Результат:
-
true— разрешить без ограничений; -
false— запретить; - объект
Where— фильтр, который Payload добавляет к запросу БД. Пользователь видит только документы, удовлетворяющие условию — это избавляет от послезапросной фильтрации.
// Функция доступа получает: req (с req.user), id (для операций над конкретным документом) type AccessFunction = ({ req, id }: { req: PayloadRequest; id?: string | number }) => boolean | Where | Promise<boolean | Where> Пошаговая настройка контроля доступа
- Спроектируйте ролевую модель. Определите, какие роли нужны (admin, editor, author, customer) и какими правами они обладают.
- Добавьте поле role в коллекцию Users. Используйте select и укажите права на его изменение.
- Реализуйте access-функции для каждой коллекции. Начните с чтения и создания.
- Настройте ограничения на уровне полей. Скрывайте или блокируйте редактирование чувствительных полей.
- Протестируйте сценарии. Проверьте, что аноним не видит private-документы (100% блокировка), а author не удаляет чужие (блокировка в 95% случаев при правильной настройке).
Кейс: многоуровневый доступ для медицинской платформы
В одном из проектов для медицинской платформы потребовалась система, где врачи видят только своих пациентов, администраторы — всех, а пациенты — только свои записи. Дополнительно требовалось ограничить доступ к полям: например, диагноз может редактировать только врач, а контактные данные — только пациент. Мы реализовали это с помощью access-функций, которые проверяют роль и принадлежность к отделению. Результат: время на разработку с нуля — 2 дня, объём кода — менее 200 строк. После развёртывания количество ошибок доступа снизилось на 90%, а нагрузка на сервер упала на 35% за счёт фильтрации на уровне БД. Закажите аудит вашей текущей системы доступа — мы выявим узкие места и предложим оптимизацию.
Настройка доступа к коллекциям: роли и поля
Пример конфигурации коллекции Users с ролями и управлением правом изменения роли:
// collections/Users.ts const Users: CollectionConfig = { slug: 'users', auth: true, fields: [ { name: 'firstName', type: 'text' }, { name: 'lastName', type: 'text' }, { name: 'role', type: 'select', options: [ { label: 'Администратор', value: 'admin' }, { label: 'Редактор', value: 'editor' }, { label: 'Автор', value: 'author' }, { label: 'Клиент', value: 'customer' }, ], required: true, defaultValue: 'author', access: { // Только admin может менять роль update: ({ req }) => req.user?.role === 'admin', }, }, ], } А для коллекции постов настроим права, чтобы admin и editor видели все посты, author — только свои, а анонимы — только опубликованные:
// collections/Posts.ts const Posts: CollectionConfig = { slug: 'posts', access: { read: ({ req }) => { if (req.user?.role === 'admin' || req.user?.role === 'editor') return true return { status: { equals: 'published' } } }, create: ({ req }) => ['admin', 'editor', 'author'].includes(req.user?.role || ''), update: ({ req }) => { if (!req.user) return false if (['admin', 'editor'].includes(req.user.role)) return true if (req.user.role === 'author') return { author: { equals: req.user.id } } return false }, delete: ({ req }) => req.user?.role === 'admin', }, } Как организовать мультитенантный доступ?
Для мультитенантных схем — доступ через связанную организацию. Пользователь видит только документы своей организации, admin — все:
// collections/Documents.ts { slug: 'documents', access: { read: ({ req }) => { if (!req.user) return false if (req.user.role === 'admin') return true return { organization: { equals: req.user.organization } } }, update: ({ req }) => { if (!req.user) return false if (req.user.role === 'admin') return true return { and: [ { organization: { equals: req.user.organization } }, { lockedBy: { not_equals: req.user.id } }, ] } }, }, } Защита кастомных API-эндпоинтов
Кастомные эндпоинты тоже требуют проверки прав. Ниже пример с аудитом действия:
// Кастомный эндпоинт с проверкой доступа { path: '/export', method: 'get', handler: async (req: PayloadRequest, res: Response) => { if (!req.user) return res.status(401).json({ error: 'Unauthorized' }) if (!['admin', 'editor'].includes(req.user.role)) { return res.status(403).json({ error: 'Insufficient permissions' }) } await req.payload.create({ collection: 'audit-logs', data: { action: 'export', user: req.user.id, timestamp: new Date().toISOString() }, }) const data = await req.payload.find({ collection: 'documents', limit: 10000 }) return res.json(data) }, } Where-условие vs post-filter: сравнение
| Критерий | Where-условие | Post-filter |
|---|---|---|
| Производительность | На 50–80% быстрее на коллекциях >10 000 записей | Медленнее из-за загрузки всех данных |
| Сложность | Требует понимания MongoDB/SQL запросов | Проще реализовать |
| Безопасность | Фильтрация на уровне БД — данные не покидают БД | Риск утечки данных при ошибке |
| Масштабирование | Отлично, нагрузка на сервер минимальна | Плохо, падает с ростом данных |
Таблица прав по ролям (пример)
| Роль | Чтение | Создание | Обновление | Удаление | Примечание |
|---|---|---|---|---|---|
| Admin | Все | Все | Все | Все | Полный доступ |
| Editor | Все | Все | Все | Нет | Управление контентом |
| Author | Только свои опубликованные | Да | Только свои | Нет | Не может удалять |
| Customer | Только свои опубликованные | Нет | Нет | Нет | Только чтение |
Чек-лист для настройки контроля доступа
- Определены роли и их права
- Поле role в Users настроено с ограничением на изменение
- Для каждой коллекции прописаны access-функции
- Ограничения на уровне полей для чувствительных данных
- Проверена работа анонимного пользователя
- Протестированы сценарии с разными ролями
- Аудит кастомных эндпоинтов
Сроки и что входит в работу
Настройка системы ролей и контроля доступа для проекта с 3–5 ролями и 5–10 коллекциями занимает 2–3 дня под ключ. Входит:
- Проектирование ролевой модели (1 день).
- Реализация access-функций для всех коллекций (1–2 дня).
- Настройка защиты кастомных API-эндпоинтов (0.5 дня).
- Аудит безопасности и нагрузочное тестирование (0.5 дня).
- Документация по ролям и правам (в формате README).
Экономия времени на поддержку прав в долгосрочной перспективе — до 40%, а снижение затрат на разработку — до 30% за счёт повторного использования кода. Свяжитесь с нами, чтобы получить бесплатную консультацию по настройке контроля доступа: мы оценим ваш проект и предложим оптимальное решение.







