Участники
`members.list`, `list_all`, `iterate`, `get`, `add`, `update`, `remove`, `grant_address`, `revoke_address` и методы приглашений рядом с ними.
Все методы
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`: людей, которые получили адреса ещё до появления ролей и которым с тех пор никто не назначил роль.
Приглашения
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.