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

Участники

`members.list`, `list_all`, `iterate`, `get`, `add`, `update`, `remove`, `grant_address`, `revoke_address` и методы приглашений рядом с ними.

Все методы

members.rb
support_role_id = "role_8b1f4c2e9a7d3b60e5f1a2c4"viewer_role_id = "role_2c7e9a1f4b8d3e60c5a7f1b9" invitation = client.members.add(  email: "[email protected]",  roleId: support_role_id,  addressIds: ["2b81de07-9c3f-4a61-b8e2-5d07f4c19a36"],  access: "member")puts invitation[:id], invitation[:expiresAt] people = client.members.list_allputs people.map { |person| "#{person[:email]} #{person[:userId]}" } sam_id = "q7Vd3kX9mT2pLw8RzN4bYc6HfJ1sGa5E"member = client.members.get(sam_id)puts member.dig(:role, :name), member[:implied] client.members.update(sam_id, roleId: viewer_role_id) address_id = "c40a95f2-1e7b-4d38-a6c9-82f05b3d7e14"client.members.grant_address(sam_id, addressId: address_id, access: "viewer")client.members.revoke_address(sam_id, address_id) removed = client.members.remove(sam_id)puts removed[:addressesRevoked]

У каждого человека два вида доступа, и их нельзя сводить в один. role описывает, что он может делать. addresses описывает, с чем он может это делать. Оба должны совпасть: роль с emails:send при access: "viewer" на invoices@ означает человека, который может отправлять почту, но не с этого адреса. Исключение составляет роль с addresses:all, которая охватывает все адреса независимо от того, что перечислено в addresses, потому что этот Array содержит только прямые выдачи. Поэтому проверьте permissions, прежде чем считать addresses полным охватом человека.

Каждый вызов об одном человеке принимает первым аргументом его userId, а не адрес электронной почты, поэтому берите его из list или list_all, как в примере. Единственное исключение составляет add, потому что он приглашает адрес: userId у человека появляется только после принятия приглашения, а до тех пор приглашение отслеживает list_invitations. Поля тела запроса сохраняют имена API в camelCase (roleId:, addressIds:, addressId:) и передаются именованными аргументами или одним Hash.

list возвращает одну OpenEmail::Page, list_all возвращает всех участников одним Array, а iterate передаёт каждого участника в блок или без блока возвращает Enumerator. Участник возвращается как Hash с ключами типа Symbol, а role является Hash внутри него, поэтому member.dig(:role, :name) читает имя роли.

implied: true означает, что роль никто не выбирал. У человека есть адреса и нет строки роли, поэтому роль выведена из самого широкого имеющегося разрешения. Считайте это «ещё не решено»; превращает вывод в решение update. До тех пор расширение его доступа к адресам молча расширяет и то, что ему можно делать.

Владелец рабочего пространства идёт первой строкой с отметкой isOwner: true, при этом add, update и remove всё равно отклоняют его с member_is_owner, ошибкой 422, выбрасываемой как OpenEmail::ValidationError. Рабочее пространство без совместного доступа сообщает об одном участнике, а не ни об одном, поэтому при подсчёте мест исключайте isOwner: client.members.list_all.count { |member| !member[:isOwner] }.

remove убирает обе оси, роль И каждую выдачу адреса в этом рабочем пространстве, и сообщает addressesRevoked. revoke_address действует узко: для того, кто перешёл в другую команду, а не ушёл.

Параметры

emailStringобязательно
Кого пригласить (с обрезкой пробелов и приведением к нижнему регистру). Аккаунт пока не нужен: приглашение уходит кому угодно, а роль и выдачи применяются, когда человек его примет. Тот, кто уже в рабочем пространстве, даёт `member_is_owner` (422).
roleIdStringобязательно
Роль, которую он получит, от 1 до 128 символов, и это должна быть роль этого рабочего пространства: неизвестный идентификатор даёт `role_not_found` (404), выбрасываемый как `OpenEmail::NotFoundError`. Роль владельца нельзя выдать, и для неё возвращается `role_immutable` (409), потому что сделать кого-то владельцем значит передать рабочее пространство, а такого вызова здесь нет.
addressIdsArray<String>
Адреса, которые несёт приглашение: не более 64 идентификаторов длиной от 1 до 128 символов каждый; они выдаются, когда приглашение принято. Каждый идентификатор проверяется до какой-либо записи, поэтому один идентификатор, не являющийся адресом этого рабочего пространства, приводит к отказу всего вызова с 422 `member_not_found`, и ничего не отправляется. Повторное приглашение того же адреса в течение десяти минут даёт 409 `invitation_too_soon`.
accessString
Что он может делать с каждым идентификатором из `addressIds`: `member` читает адрес и отправляет от его имени, `viewer` только читает. По умолчанию `member`, тот уровень, который всегда использовали консоль и старый путь совместного доступа, поэтому один и тот же вызов значит одно и то же из скрипта и с экрана. Чтобы выдать смешанный доступ, затем вызовите `grant_address` для отличающихся адресов.

Ответ

objectString
Всегда `member`. Ответ на удаление содержит то же значение, `userId`, `deleted: true` и `addressesRevoked`, а остальных полей ниже в нём нет.
userIdString
Идентификатор его учётной записи и дескриптор, который любой другой вызов для участников принимает первым аргументом: `get`, `update`, `remove` и оба вызова для адресов. Добавление человека является единственным вызовом, который вместо этого работает по адресу электронной почты, потому что тот, кто добавляет коллегу, знает его адрес, а не идентификатор.
emailString
Адрес на его аккаунте, возвращаемый в том виде, в каком его хранит та строка. Этот ресурс его никогда не записывает, а приведение к нижнему регистру в `add` касается адреса, который вы отправляете для поиска, а не того, что приходит обратно. После владельца список участников отсортирован по нему, а не по дате присоединения, потому что список читают, чтобы найти конкретного человека, а не чтобы увидеть, что изменилось.
nameString or nil
Отображаемое имя из его учётной записи, где этот столбец всегда заполнен. nil в типе является мерой предосторожности, а не состоянием, которое этот API когда-либо выдавал. Имя принадлежит человеку, а не рабочему пространству, поэтому ничто в этом ресурсе не может его задать.
imageString or nil
Аватар из его учётной записи или nil, если он его не задал.
role.idString or nil
Идентификатор роли, которую он занимает, читается как `member.dig(:role, :id)`, или nil, если её никто не выбирал. См. `implied`. nil здесь является единственным случаем, когда `role` сообщает вывод, а не чьё-то решение.
role.nameString
Имя роли. Для участника с подразумеваемой ролью это имя встроенного шаблона, которому соответствует его доступ, а не строка этого рабочего пространства.
role.builtinString or nil
Какая это встроенная роль: `owner`, `admin`, `member`, `viewer`, `developer` или `billing`, либо nil для пользовательской. `owner` встречается только в строке самого владельца, рядом с `isOwner: true`. Назначение этой роли кому-либо отклоняется с `role_immutable` (409).
isOwnerBoolean
True ровно в одной строке: у аккаунта, на который завязано рабочее пространство. Он обладает всеми правами, что бы ни говорила его строка роли, сортируется первым, а `add`, `update` и `remove` отказывают по нему с `member_is_owner`. При подсчёте мест его исключайте.
impliedBoolean
True, когда у человека есть выдачи адресов, но нет строки участника, поэтому его роль выведена, а не выбрана: любая выдача `member` делает её встроенной ролью Member, иначе Viewer. Для владельца никогда не равно true. Показывайте это как «следует из доступа». Пока `update` не превратит вывод в решение, расширение его доступа к адресам молча расширяет и то, что он может делать.
permissionsArray<String>
Разрешения роли, развёрнутые прямо в участнике, чтобы одно чтение отвечало на вопрос «может ли он?» без запроса роли. Для участника с подразумеваемой ролью они берутся из встроенного ШАБЛОНА, а не из строки роли этого рабочего пространства, поэтому изменение встроенной роли Member не меняет того, что есть у такого участника.
addressesArray<Hash>
Выданные ему адреса, отсортированные по адресу, каждый со своим уровнем доступа. Пусто у того, у кого есть роль и нет выдач. Именно так выглядит новый участник, пока ему не выдан адрес, и это правильный вид отказа, пока вы ещё решаете, что ему следует видеть.
addresses[].addressIdString
Идентификатор адреса, который принимают `grant_address` и `revoke_address`. Идентификатор, который не является адресом этого рабочего пространства, отклоняется обоими, а не порождает сообщение об отзыве, которого не было.
addresses[].addressString
Полный адрес в нижнем регистре, собранный заново из локальной части и домена.
addresses[].accessString
Что он может делать с этим одним адресом: `member` читает его и отправляет от его имени, `viewer` только читает. Чтобы отправка произошла, её должны разрешить и это поле, и роль, поэтому роль с `emails:send` при выдаче `viewer` ни с какого адреса не отправляет. Хранимый столбец называется `role`, а здесь он переименован, чтобы один Hash не нёс два ключа `role` из двух разных словарей.
createdAtString or nil
Когда была записана его строка участника, в виде String ISO 8601, и nil, если строки участника нет вовсе. Этот nil описывает ту же группу, что и `implied: true`: людей, которые получили адреса ещё до появления ролей и которым с тех пор никто не назначил роль.

Приглашения

invitations.rb
waiting = client.members.list_all_invitations waiting.each do |invitation|  client.members.resend_invitation(invitation[:id]) if invitation[:expired]end client.members.revoke_invitation("winv_6bb640f5b99e47deb758f1f5")

add отвечает приглашением, а эти вызовы работают с ним дальше. list_invitations возвращает одну OpenEmail::Page ещё не принятых приглашений, list_all_invitations возвращает их все одним Array, а iterate_invitations передаёт каждое в блок или возвращает Enumerator. resend_invitation отправляет приглашение снова с новой ссылкой и ещё четырнадцатью днями, а revoke_invitation отзывает его. Ожидающее приглашение ничего не даёт, пока его не примут.

resend_invitation отклоняет повторную отправку на тот же адрес в течение десяти минут с 409 invitation_too_soon, а revoke_invitation отклоняет приглашение, которое успели принять, с 409 invitation_accepted. Оба выбрасываются как OpenEmail::ConflictError, поэтому conflict? равно true, а различить их позволяет code.