Skip to content
  1. Компоненты
  2. mxHeadless
  3. Аутентификация
  4. Scopes и ACL

Авторизация ​

После аутентификации mxHeadless проверяет право на действие в четыре шага:

  1. Permission маршрута: публичный или нужен identity
  2. Scope ключа или токена: строка вида {object}.{action}
  3. MODX ACL: контекст, просмотр ресурса, view_unpublished
  4. Field policy: hidden и protected поля

Нет нужного scope у API key / OAuth → 403 scope_denied.

Как проверяются scopes ​

ТипПроверка
API key (mxh_*)Список scopes ключа. Есть * → все действия
OAuth (mxt_*)Scopes токена (пересечение с scopes клиента)
SessionmodX->hasPermission() с той же строкой (resources.read и т.д.)
AnonymousТолько public GET. Scopes не задают

Для интеграций обычно хватает API key. Сессия удобна для mgr и UI на том же origin с CSRF.

Core scopes (фиксированные маршруты) ​

ScopeМаршруты
resources.readGET /resources, GET /resources/{id}, GET /pages/{uri}
resources.createPOST /resources
resources.updatePUT / PATCH /resources/{id}
resources.deleteDELETE /resources/{id}
contexts.readGET /contexts, GET /contexts/{key}, GET /contexts/{key}/settings
chunks.readGET /chunks, GET /chunks/{id}
templates.readGET /templates, GET /templates/{id}
snippets.readGET /snippets, GET /snippets/{id}
tvs.readGET /tvs, GET /tvs/{id}
categories.readGET /categories, GET /categories/{id}
content_types.readGET /content_types, GET /content_types/{id}
preview?preview=true без view_unpublished у сессии. Также участвует в проверке include_deleted
fields.{field}Поле из protectedFields объекта
*Все scopes (только для ключей и токенов)

Meta-маршруты (/, /health, /schema, /docs, /meta/*) и POST /auth/token не требуют scope.

Scopes для /objects/{name} ​

Шаблон из кода: {name}.{action}, где {name} — имя в registry, не PHP-класс и не префикс objects..

ScopeMethodPath
{name}.readGET/objects/{name}, /objects/{name}/{id}
{name}.createPOST/objects/{name}
{name}.updatePUT, PATCH/objects/{name}/{id}
{name}.deleteDELETE/objects/{name}/{id}

Примеры после регистрации MiniShop3-объектов:

ScopeСмысл
products.readКаталог товаров
ms_categories.readКатегории товаров MS3. Core categories.read — элементы modCategory
orders.readЗаказы (обычно не public, плюс ACL)
orders.updateОбновление заказа, если object writable

Список зарегистрированных имён: GET /schema или GET /meta/endpoints на этом сайте.

Пример набора для ключа ​

Публичный фронт (только чтение контента) часто обходится без ключа.

CI / preview:

text
resources.read,preview,chunks.read,templates.read

Каталог MS3 + CMS:

text
resources.read,products.read,ms_categories.read

Admin API (узко, без *):

text
resources.read,resources.create,resources.update,orders.read

Создание ключа: API keys. OAuth: OAuth.

Public vs protected ​

Anonymous может читать discovery, health, schema, docs, meta, GET /resources и GET /pages/{uri} в рамках ACL опубликованных ресурсов.

Элементы, контексты, операции записи и /objects/* требуют учётных данных.

Контекст ​

Контекст запуска: mxheadless_context (по умолчанию web) задаёт контекст при инициализации MODX в шлюзе и api.php. Значение mgr игнорируется.

В запросе: заголовок X-Context или query ?context=. Значение должно входить в mxheadless_allowed_contexts (по умолчанию web,mgr). Иначе 422 Invalid context.

Мутации по id находят строку в любом контексте, затем проверяют доступ context.{key} / context_{key}. Запись context_key на неизвестный или незагружаемый контекст даёт 422, не 500.

Поля ​

Скрытые поля не попадают в JSON. Protected отдаются и записываются только при отдельном field-level праве: scope fields.{field} у ключа или токена, MODX-право mxheadless_fields_{field} у сессии. Запрос fields= на неизвестное или запрещённое поле даёт 422.

ПравоКтоЧто открывает
fields.{field}API key, OAuthПоле {field} из protectedFields на чтение и запись
mxheadless_fields_{field}Сессия MODXТо же для текущего пользователя
mxheadless_fields_allСессия MODXВсе protectedFields объекта

Поля из hiddenFields (properties у resources) не открываются никаким флагом: они вырезаются из ответа и запись в них даёт 422. Поля из immutableFields не пишутся даже с полным набором прав.

Поля из protectedFields у resources: createdby, editedby, deletedby, publishedby.

Preview и deleted ​

QueryКто
preview=trueSession с view_unpublished или scope preview. Достаточно одного из двух: права пользователя-владельца ключа не проверяются
include_deleted=1Не для anonymous. Нужны preview, resources.update, resources.delete, view_unpublished или empty_recycle_bin

См. также ​