Перейти к документации
Ruby

Роли

`roles.list`, `list_all`, `iterate`, `get`, `create`, `update`, `delete` и `list_permissions`.

Все методы

roles.rb
page = client.roles.listputs page.items.size role = client.roles.get("role_8b1f4c2e9a7d3b60e5f1a2c4")puts role[:name] support = client.roles.create(  name: "Support",  description: "Answers the shared inboxes and nothing else.",  permissions: ["emails:send", "threads:write", "labels:write"]) p support[:permissions] client.roles.update(support[:id], permissions: [*support[:permissions], "templates:read"]) client.roles.delete(support[:id], reassign_to: role[:id]) vocabulary = client.roles.list_permissionsp vocabulary.map { |permission| permission[:id] }

support[:permissions] содержит шесть записей, а не три: emails:send приносит с собой emails:read, threads:write приносит threads:read, а labels:write приносит labels:read. Читайте список обратно, а не додумывайте его.

list возвращает одну OpenEmail::Page, list_all возвращает все роли одним Array, а iterate передаёт каждую роль в блок или без блока возвращает Enumerator. Роль возвращается как Hash с ключами типа Symbol, поэтому role[:permissions] читает список. create и update принимают поля тела именованными аргументами или одним Hash, а delete принимает reassign_to:, именованный аргумент в snake_case, который гем переименовывает для API.

Роль говорит, что человек может ДЕЛАТЬ. С какими АДРЕСАМИ он может это делать, это другая ось, и она находится в client.members: см. grant_address и revoke_address на странице об участниках. «Может отправлять почту» и «может отправлять от имени invoices@» являются разными утверждениями, и рабочее пространство, которое нанимает второго сотрудника поддержки, меняет второе, не трогая первое. Одно разрешение отвечает на оба вопроса: роль с addresses:all охватывает все адреса, включая добавленные позже, без отдельной выдачи, и назначить его роли может только человек в приложении.

Ветвитесь по editable и deletable, а не по builtin или имени. Оба равны false только у владельца, чей список означает «все разрешения, включая те, что придумают в следующем году», и вычисляется, а не хранится. Любая другая роль отвечает true на оба, включая пять ролей, с которыми создаётся рабочее пространство. Переименованная роль по-прежнему правильно отвечает на оба, а её имя больше ни о чём не говорит.

update ЗАМЕНЯЕТ список разрешений. Вызова для выдачи одного разрешения нет, поэтому прочитайте роль, измените нужную запись и отправьте весь список обратно, как это делает [*support[:permissions], "templates:read"] выше. Если отправить одно разрешение, у роли останется ровно оно и то, что из него следует.

delete нужен reassign_to:, как только роль кто-то занимает. Гем отправляет его как параметр запроса reassignTo, потому что тело в DELETE отбрасывают несколько сред выполнения и ряд прокси, и не передаёт параметр, если вы ничего не указали. Результат сообщает reassigned и keysReassigned отдельно, поэтому скрипт может записать в журнал то, что он сделал, а не то, о чём просил.

list_permissions соответствует GET /roles/permissions, фиксированному пути, который стоит ровно там, где был бы идентификатор роли. Гем вызывает этот путь напрямую, а не передаёт слово через get, и возвращает обычный Array, а не OpenEmail::Page: по одному Hash на разрешение, с id, label, group и scope. scope: false отмечает записи, которые не может получить ни один ключ. Не передавайте это слово в get сами. client.roles.get("permissions") строит тот же путь, поэтому отправляет тот же запрос и получает словарь разрешений, а не роль или 404.

Роль задаёт потолок для ключа

Ключ, выпущенный под роль, может делать то, что даёт ПЕРЕСЕЧЕНИЕ его собственных областей с разрешениями этой роли, и это вычисляется на границе при каждом запросе. Поэтому сужение роли сразу урезает права её ключей без ротации какого-либо из них. У ключа без роли потолка нет вовсе, поэтому roleId, равный nil, является самым широким состоянием ключа, а не самым узким.

Именно поэтому roles.delete настаивает на том, чтобы было куда перенести ключи. Осиротив их, вы бы полностью сняли потолок, молча повысив в правах каждую учётную запись, которую роль ограничивала.

GET /keys/self и GET /ping сообщают roleId и grantedScopes рядом с действующими scopes. Так находится ответ на вопрос «у моего ключа есть emails:send, а я получаю insufficient_scope»: всё, что есть в grantedScopes и отсутствует в scopes, отняла роль. client.me.get и client.me.ping возвращают оба поля в своём Hash, поэтому key[:grantedScopes] - key[:scopes] перечисляет то, что отняла роль. Сам отказ является OpenEmail::PermissionError, у которого scope_missing? равно true.

Параметры

nameStringобязательно
Как рабочее пространство называет роль: от 1 до 48 символов, пробелы по краям обрезаются перед сохранением. Имена уникальны в пределах рабочего пространства без учёта регистра, поэтому второй «Support» отклоняется с `role_name_taken` (409), выбрасываемым как `OpenEmail::ConflictError`, а не создаётся рядом с первым.
descriptionString
Фраза о том, для чего нужна роль, с обрезанными пробелами по краям, не более 240 символов. Строка, которая после обрезки пуста, сохраняется как nil, поэтому описание из пробелов вернётся как nil, а не как то, что вы отправили. В `create` просто не указывайте его, а не передавайте nil: гем отправляет nil как есть, и `create` отклоняет его с 422. В `update` `description: nil` очищает описание.
permissionsArray<String>обязательно
Что даёт роль, из словаря, который отдаёт `list_permissions`. Строка не из словаря даёт 422 для `permissions`, выбрасываемый как `OpenEmail::ValidationError` с `param`, равным `permissions`, а не отбрасывается молча, поэтому об опечатке вам сообщат, и она не будет стоить вам полдня. На входе список РАСШИРЯЕТСЯ (`templates:write` сохраняет рядом с собой `templates:read`), очищается от дубликатов и приводится к каноническому порядку, поэтому читайте сохранённый список из ответа, а не считайте, что он совпадает с отправленным.

Ответ

objectString
Всегда `role`. Запись об удалении отвечает тем же значением, `id` роли, `deleted: true` и двумя счётчиками переназначения, и никакими другими полями из перечисленных ниже.
idString
Идентификатор роли, читается как `role[:id]`. Именно его называет `roleId` участника, на него указывает потолок API-ключа, и его принимает `reassign_to:`, когда удаляется другая роль и её обладатели переходят на эту.
nameString
Имя роли в рабочем пространстве, с обрезанными пробелами и уникальное без учёта регистра. Любую роль, кроме роли владельца, можно переименовать, включая начальные (`builtin` говорит, откуда взялась строка, а не как она обязана называться), поэтому не считайте «Admin» обещанием того, какие разрешения есть у роли. Имя, которое уже занято другой ролью, даёт `role_name_taken` (409, с `param`, равным `name`). Переименование владельца даёт `role_immutable` (409), как и любое другое его изменение.
descriptionString or nil
Фраза с описанием роли или nil, если описания не дали. Пустой ввод сохраняется как nil и при создании, и при обновлении, поэтому здесь никогда не бывает пустой строки.
permissionsArray<String>
Всё, что даёт роль, уже в расширенном виде и в каноническом порядке, а не в том, в каком кто-то это ввёл. Этот порядок важен: у двух ролей с одинаковыми разрешениями одинаковые Array, и именно поэтому экран настроек может сравнить их через `==`, чтобы решить, активна ли кнопка «Сохранить».
builtinString or nil
Из какой из шести начальных ролей взялась эта строка: `owner`, `admin`, `member`, `viewer`, `developer` или `billing`, либо nil для роли, которую рабочее пространство создало само. Поле фиксирует происхождение, а не статус: начальную роль переименовывают, меняют её разрешения и удаляют, как любую другую. Ветвитесь по `editable` и `deletable`, а не по этому полю. Роль, которую кто-то назвал «Admin», не обязательно начальная, а начальная может уже называться иначе.
editableBoolean
Вычисляется как `builtin != "owner"`, поэтому равно false только у роли владельца, и любой `update` этой роли отклоняется с `role_immutable` (409). Любую другую роль можно изменять полностью (имя, описание и разрешения), включая пять ролей, с которыми создаётся рабочее пространство.
deletableBoolean
Вычисляется как `builtin != "owner"`: false только у роли владельца, для которой возвращается `role_undeletable` (409), и true у всех остальных ролей, включая начальные. Проверяйте его до того, как показать кнопку, а не после отказа. Роли, которую кто-то ещё занимает, нужен также `reassign_to:`, иначе удаление даёт `role_in_use` (409). Оба отказа выбрасываются как `OpenEmail::ConflictError`, а различить их позволяет `code`.
membersInteger
Сколько людей занимают эту роль, по строкам участников рабочего пространства. Владельца среди них нет: у него нет строки участника и ему нельзя назначить роль, поэтому роль владельца сообщает ноль обладателей, хотя список участников его показывает.
apiKeysInteger
Сколько действующих API-ключей ограничено этой ролью. Отозванные ключи не учитываются, хотя удаление перенаправляет каждую строку ключа, указывающую на роль, включая отозванные. Это вторая группа, которую нужно перенести, прежде чем роль можно будет удалить, и её никто не замечает: ключи являются программами, а программа не жалуется.
createdAtString
Когда была записана строка роли, в виде String ISO 8601. Встроенные строки создаются лениво, когда они впервые кому-то понадобятся, например при чтении списка ролей, создании роли или на экране API-ключей, а не при создании рабочего пространства. Поэтому метка времени встроенной роли показывает, когда пришёл этот первый запрос, а не когда было создано рабочее пространство.
updatedAtString
Когда роль в последний раз менялась, в виде String ISO 8601. Его сдвигает каждый принятый `update`, включая тот, что задаёт полю уже имеющееся значение.