KeystoneJS: гранулярний контроль доступу та рольова модель
При розробці headless CMS на KeystoneJS часто потрібно розмежувати доступ між редакторами, модераторами та адміністраторами, а також приховати внутрішні нотатки від звичайних користувачів. Типове рішення — багаторівнева система управління доступом: на рівні операцій (CRUD), окремих елементів і конкретних полів. Ми допомогли більш ніж 30 проектам налаштувати такі моделі «під ключ» — від аналітики до деплою, з гарантією безпеки та продуктивності. В одному з проектів для видавничого дому знадобилося 7 ролей з різним доступом до 15 списків — рольова модель через БД дозволила змінювати права без перезапуску сервера, що скоротило час на узгодження змін на 40%.
Чому KeystoneJS виграє у Strapi в гнучкості доступу?
Strapi використовує жорсткі ролі з фіксованими дозволами, а Directus пропонує лише три рівні (public, readonly, full). KeystoneJS дає чотири рівні — Operation, Filter, Item, Field — плюс можливість зберігати ролі в базі. Це дозволяє реалізувати будь-які бізнес-правила без хардкоду. Наприклад, ми налаштували систему, де редактор може редагувати лише свої чернетки, модератор — публікувати чужі, а адмін — видаляти. Налаштування зайняло 3 дні, тоді як на Strapi довелося б писати кастомний middleware, що збільшило б термін до 2 тижнів — це в 4.5 рази довше.
Як налаштувати контроль доступу для кількох ролей в KeystoneJS?
Розберемо налаштування на прикладі типового проекту. Спочатку визначте списки та ролі. Для кожної ролі створіть запис у списку Role з полями-прапорцями, як показано нижче. Потім в access-функціях кожного списку перевіряйте ці прапорці. Такий підхід гнучкий і дозволяє керувати правами через адмінку.
Рівні доступу KeystoneJS: від операцій до полів
Система доступу KeystoneJS побудована на чотирьох рівнях. Кожен вирішує своє завдання.
| Рівень | Що контролює | Коли застосовується | Приклад |
|---|---|---|---|
| Operation Access | CRUD-операції цілком | До вибірки з БД | Тільки адмін може видаляти |
| Filter Access | Видимі записи через фільтр | Автоматично в запит | Редактор бачить лише свої пости |
| Item Access | Конкретний запис після вибірки | Після завантаження з БД | Редактор може змінювати лише чернетки |
| Field Access | Конкретне поле | При читанні/записі | Зарплату бачать лише HR |
Ці рівні детально описані в документації KeystoneJS Access Control Guide. Ось приклад комбінованого налаштування для списку Post:
access: { operation: { query: ({ session }) => !!session, create: ({ session }) => session?.data?.role?.canManagePosts, update: ({ session }) => ['editor', 'admin'].includes(session?.data?.role), delete: ({ session }) => session?.data?.role === 'admin', }, filter: { query: ({ session }) => { if (session?.data?.role === 'admin') return true; return { author: { id: { equals: session?.data?.id } } }; }, }, item: { update: async ({ session, item }) => { if (session?.data?.role === 'admin') return true; return item.status === 'draft' && item.authorId === session?.data?.id; }, }, fields: { internalNotes: text({ access: { read: ({ session }) => session?.data?.role === 'admin', create: ({ session }) => session?.data?.role === 'admin', update: ({ session }) => session?.data?.role === 'admin', }, }), salary: integer({ access: { read: ({ session }) => ['admin', 'hr'].includes(session?.data?.role), update: ({ session }) => session?.data?.role === 'admin', }, }), }, }, Як зберігати ролі в базі даних?
Замість хардкоду ролей у коді — зберігання прав у БД. Це дозволяє змінювати дозволи через адмінку без перезапуску.
Порівняння підходів:
| Підхід | Гнучкість | Можливість зміни без деплою | Продуктивність |
|---|---|---|---|
| Хардкод в access-функціях | Низька | Ні | Висока |
| Зберігання в БД (список Role) | Висока | Так | Середня (додатковий запит) |
// lists/Role.ts export const Role = list({ access: { operation: { query: allowAll, create: ({ session }) => session?.data?.role === 'admin', update: ({ session }) => session?.data?.role === 'admin', delete: ({ session }) => session?.data?.role === 'admin', }, }, fields: { name: text({ validation: { isRequired: true }, isIndexed: 'unique' }), canManagePosts: checkbox({ defaultValue: false }), canManageUsers: checkbox({ defaultValue: false }), canManageRoles: checkbox({ defaultValue: false }), canPublish: checkbox({ defaultValue: false }), users: relationship({ ref: 'User.role', many: true }), }, }); // auth.ts sessionData: 'id name email role { canManagePosts canManageUsers canPublish }', Використання в списку Post:
access: { operation: { create: ({ session }) => !!session?.data?.role?.canManagePosts, update: ({ session }) => !!session?.data?.role?.canManagePosts, delete: ({ session }) => !!session?.data?.role?.canManagePosts, }, }, Як ми налаштовуємо доступ: процес та обсяг робіт
- Аналіз об'єктів і ролей — визначаємо списки, операції, поля. На виході матриця прав.
- Проектування рольової моделі — створюємо список Role з чекбоксами для кожного дозволу.
- Реалізація access-функцій — пишемо Operation, Filter, Item, Field для кожного списку.
- Тестування сценаріїв — перевіряємо права для кожної ролі (до 20 кейсів).
- Деплой та моніторинг — розгортаємо на сервері та слідкуємо за логами.
Що входить в роботу
- Розробка рольової моделі (до 10 списків)
- Налаштування CRUD-доступу для кожного списку
- Фільтрація видимості записів
- Приховування/блокування полів
- Інтеграція з вашою системою аутентифікації
- Тестування сценаріїв доступу
- Документація щодо доступних ролей та прав
- Гарантія на коректну роботу прав доступу
Часті помилки при налаштуванні доступу
Новачки часто плутають рівні — наприклад, використовують Filter Access, коли потрібен Item Access. Filter Access працює автоматично на етапі запиту і не може перевірити поля елемента, які ще не завантажені. Item Access підходить для перевірки статусу запису або авторства. Ще одна типова помилка — забути включити потрібні поля ролі в sessionData. Без цього access-функції не побачать права. Ми перевіряємо всі сценарії, щоб виключити такі ситуації.
Терміни та вартість
Налаштування типової рольової моделі (3–4 ролі, 5–10 списків) займає 2–4 дні. Вартість розраховується індивідуально — напишіть нам, оцінимо ваш проект за 1 день. Отримайте консультацію інженера по вашому проекту.
Досвідчені інженери з 5+ роками роботи з KeystoneJS допоможуть реалізувати навіть складні сценарії доступу. Зв'яжіться з нами для оцінки — це безкоштовно.







