Участники
`members->list`, `listAll`, `iterate`, `get`, `add`, `update`, `remove`, `grantAddress`, `revokeAddress`, `grantDomain`, `revokeDomain` и методы приглашений рядом с ними.
Все методы
$supportRoleId = 'role_8b1f4c2e9a7d3b60e5f1a2c4';$viewerRoleId = 'role_2c7e9a1f4b8d3e60c5a7f1b9'; $invitation = $client->members->add([ 'email' => '[email protected]', 'roleId' => $supportRoleId, 'addressIds' => ['2b81de07-9c3f-4a61-b8e2-5d07f4c19a36'], 'access' => 'member',]);echo $invitation['id'], ' ', $invitation['expiresAt'], PHP_EOL; foreach ($client->members->listAll() as $person) { echo $person['email'], ' ', $person['userId'], PHP_EOL;} $samId = 'q7Vd3kX9mT2pLw8RzN4bYc6HfJ1sGa5E';$member = $client->members->get($samId);echo $member['role']['name'], $member['implied'] ? ' (implied)' : '', PHP_EOL; $client->members->update($samId, ['roleId' => $viewerRoleId]); $addressId = 'c40a95f2-1e7b-4d38-a6c9-82f05b3d7e14';$client->members->grantAddress($samId, ['addressId' => $addressId, 'access' => 'viewer']);$client->members->revokeAddress($samId, $addressId); $removed = $client->members->remove($samId);echo $removed['addressesRevoked'], PHP_EOL;У каждого человека два вида доступа, и их нельзя сводить в один. role описывает, что он может делать. addresses и domains описывают, с чем он может это делать. Оба должны совпасть: роль с emails:send при access, равном viewer, на invoices@ означает человека, который может отправлять почту, но не с этого адреса. Исключение составляет роль с addresses:all, которая охватывает все адреса независимо от того, что перечислено в addresses, потому что этот массив содержит только прямые выдачи. Поэтому проверьте permissions, прежде чем считать addresses полным охватом человека.
Каждый вызов об одном человеке принимает первым аргументом его userId, а не адрес электронной почты, поэтому берите его из list или listAll, как в примере. Единственное исключение составляет add, потому что он приглашает адрес: userId у человека появляется только после принятия приглашения, а до тех пор приглашение отслеживает listInvitations. Тело add, update, grantAddress и grantDomain представляет собой один массив с ключами по именам API в camelCase (roleId, addressIds, addressId).
list возвращает одну OpenEmail\Result\Page, listAll возвращает всех участников одним массивом, а iterate возвращает Generator, который выдаёт участников по одному. Участник возвращается как массив с ключами в camelCase, а role является массивом внутри него, поэтому $member['role']['name'] читает имя роли.
Если implied равно true, роль никто не выбирал. У человека есть адреса или домены и нет строки роли, поэтому роль выведена из самой широкой выдачи, которая у него есть. Считайте это состоянием «ещё не решено», а превращает вывод в решение именно update. До тех пор расширение его доступа к адресам молча расширяет и то, что ему можно делать.
Владелец рабочего пространства идёт первой строкой, где isOwner равно true, при этом add, update и remove всё равно отклоняют его с member_is_owner, ошибкой 422, выбрасываемой как ValidationException. Рабочее пространство без совместного доступа сообщает об одном участнике, а не ни об одном, поэтому при подсчёте мест исключайте isOwner: count(array_filter($client->members->listAll(), fn(array $member): bool => !$member['isOwner'])).
remove убирает обе оси, роль И каждую выдачу адреса и домена в этом рабочем пространстве, и сообщает в addressesRevoked, сколько выдач отозвано, включая домены. revokeAddress действует узко: для того, кто перешёл в другую команду, а не ушёл, а revokeDomain делает то же самое для целого домена.
add, update, remove и четыре вызова выдачи и отзыва запрашивают у токена доступа OAuth код подтверждения, а у API-ключа никогда. Пока у токена нет подтверждения, они выбрасывают PermissionException, у которого isStepUpRequired() равно true. add и grantDomain также требуют тарифа, включающего команду, а на тарифе без неё выбрасывают PermissionException, у которого errorCode равно plan_required.
Параметры
emailstringобязательно- Кого пригласить (с обрезкой пробелов и приведением к нижнему регистру). Аккаунт пока не нужен: приглашение уходит кому угодно, а роль и выдачи применяются, когда человек его примет. Тот, кто уже в рабочем пространстве, даёт `member_is_owner` (422). Адрес, который входит со своим собственным паролем, пригласить нельзя: для него возвращается `mailbox_login` (403), поэтому пригласите вместо него личный адрес электронной почты этого человека.
roleIdstringобязательно- Роль, которую он получит, от 1 до 128 символов, и это должна быть роль этого рабочего пространства: неизвестный идентификатор даёт `role_not_found` (404), выбрасываемый как `NotFoundException`. Роль владельца нельзя выдать, и для неё возвращается `role_immutable` (409), потому что сделать кого-то владельцем значит передать рабочее пространство, а такого вызова здесь нет.
addressIdsarray- Адреса, которые несёт приглашение: не более 64 идентификаторов длиной от 1 до 128 символов каждый; они выдаются, когда приглашение принято. Каждый идентификатор проверяется до какой-либо записи, поэтому один идентификатор, не являющийся адресом этого рабочего пространства, приводит к отказу всего вызова с 422 `member_not_found`, и ничего не отправляется. Повторное приглашение того же адреса в течение десяти минут даёт 409 `invitation_too_soon`.
domainIdsarray- Целые домены, которые несёт приглашение, не более 64 идентификаторов, выдаваемые, когда его примут. Доступ к домену охватывает все адреса на этом домене, включая созданные позже. Идентификатор, который не является доменом этого рабочего пространства, даёт 422 `member_not_found`, как и для адреса.
accessstring- Что он может делать с каждым идентификатором из `addressIds` и `domainIds`: `member` читает адрес и отправляет от его имени, `viewer` только читает. По умолчанию `member`, тот уровень, который всегда использовали консоль и старый путь совместного доступа, поэтому один и тот же вызов значит одно и то же из скрипта и с экрана. Чтобы выдать смешанный доступ, затем вызовите `grantAddress` для отличающихся адресов.
Ответ
objectstring- Всегда `member`. Ответ на удаление содержит то же значение, `userId`, `deleted`, равное true, и `addressesRevoked`, а остальных полей ниже в нём нет.
userIdstring- Идентификатор его учётной записи и дескриптор, который любой другой вызов для участников принимает первым аргументом: `get`, `update`, `remove` и четыре вызова выдачи и отзыва. Добавление человека является единственным вызовом, который вместо этого работает по адресу электронной почты, потому что тот, кто добавляет коллегу, знает его адрес, а не идентификатор.
emailstring- Адрес на его аккаунте, возвращаемый в том виде, в каком его хранит та строка. Этот ресурс его никогда не записывает, а приведение к нижнему регистру в `add` касается адреса, который вы отправляете для поиска, а не того, что приходит обратно. После владельца список участников отсортирован по нему, а не по дате присоединения, потому что список читают, чтобы найти конкретного человека, а не чтобы увидеть, что изменилось.
namestring or null- Отображаемое имя из его учётной записи, где этот столбец всегда заполнен. null в типе является мерой предосторожности, а не состоянием, которое этот API когда-либо выдавал. Имя принадлежит человеку, а не рабочему пространству, поэтому ничто в этом ресурсе не может его задать.
imagestring or null- Его аватар, взятый из аккаунта; null, если он его не задал.
role.idstring or null- Идентификатор роли, которую он занимает, читается как `$member['role']['id']`, или null, если её никто не выбирал. См. `implied`. null здесь является единственным случаем, когда `role` сообщает вывод, а не чьё-то решение.
role.namestring- Имя роли. Для участника с подразумеваемой ролью это имя встроенного шаблона, которому соответствует его доступ, а не строка этого рабочего пространства.
role.builtinstring or null- Какая это встроенная роль: `owner`, `admin`, `member`, `viewer`, `developer` или `billing`, либо null для пользовательской. `owner` встречается только в строке самого владельца, рядом с `isOwner`, равным true. Назначение этой роли кому-либо отклоняется с `role_immutable` (409).
isOwnerbool- True ровно в одной строке: у аккаунта, на который завязано рабочее пространство. Он обладает всеми правами, что бы ни говорила его строка роли, сортируется первым, а `add`, `update` и `remove` отказывают по нему с `member_is_owner`. При подсчёте мест его исключайте.
impliedbool- True, когда у человека есть выдачи адресов или доменов, но нет строки участника, поэтому его роль выведена, а не выбрана: любая выдача `member` делает её встроенной ролью Member, иначе Viewer. Для владельца никогда не равно true. Показывайте это как «следует из доступа». Пока `update` не превратит вывод в решение, расширение его доступа к адресам молча расширяет и то, что он может делать.
permissionsarray- Разрешения роли, развёрнутые прямо в участнике, чтобы одно чтение отвечало на вопрос «может ли он?» без запроса роли. Для участника с подразумеваемой ролью они берутся из встроенного ШАБЛОНА, а не из строки роли этого рабочего пространства, поэтому изменение встроенной роли Member не меняет того, что есть у такого участника.
addressesarray- Выданные ему адреса, отсортированные по адресу, по одному массиву на адрес, каждый со своим уровнем доступа. Пусто у того, у кого есть роль и нет выдач. Именно так выглядит новый участник, пока ему не выдан адрес, и это правильный вид отказа, пока вы ещё решаете, что ему следует видеть.
addresses[].addressIdstring- Идентификатор адреса; именно его принимают `grantAddress` и `revokeAddress`. Идентификатор, не являющийся адресом этого рабочего пространства, отклоняется в обоих вызовах, вместо того чтобы сообщить об отзыве, которого не было.
addresses[].addressstring- Полный адрес в нижнем регистре, собранный заново из локальной части и домена.
addresses[].accessstring- Что он может делать с этим одним адресом: `member` читает его и отправляет от его имени, `viewer` только читает. Чтобы отправка произошла, её должны разрешить и это поле, и роль, поэтому роль с `emails:send` при выдаче `viewer` ни с какого адреса не отправляет. Хранимый столбец называется `role`, а здесь он переименован, чтобы один массив не нёс два ключа `role` из двух разных словарей.
domainsarray- Целые домены, которые ему выданы, каждый с `domainId`, `domain` и `access`. Доступ к домену охватывает все адреса на нём, включая созданные позже, поэтому читайте его вместе с `addresses`, прежде чем решить, что у человека нет доступа к адресу. `grantDomain` и `revokeDomain` принимают `domainId`.
createdAtstring or null- Когда была записана его строка участника, в виде строки ISO 8601, и null, если строки участника нет вовсе. Этот null описывает ту же группу, что и `implied`, равное true: людей, которые получили выдачи ещё до появления ролей и которым с тех пор никто не назначил роль.
Приглашения
$waiting = $client->members->listAllInvitations(); foreach ($waiting as $invitation) { if ($invitation['expired']) { $client->members->resendInvitation($invitation['id']); }} $client->members->revokeInvitation('winv_6bb640f5b99e47deb758f1f5');add отвечает приглашением, а эти вызовы работают с ним дальше. listInvitations возвращает одну OpenEmail\Result\Page ещё не принятых приглашений, listAllInvitations возвращает их все одним массивом, а iterateInvitations возвращает Generator, который выдаёт их по одному. resendInvitation отправляет приглашение снова с новой ссылкой и ещё четырнадцатью днями, а revokeInvitation отзывает его. Ожидающее приглашение ничего не даёт, пока его не примут.
Приглашение представляет собой массив с id, email, role, addresses, domains, expiresAt, expired, lastSentAt и createdAt. delivered и deliveryError сообщают, чем закончилась отправка последнего письма с приглашением, поэтому скрипт может отличить приглашение, которое было лишь записано, от того, которое до кого-то дошло.
resendInvitation отклоняет повторную отправку на тот же адрес в течение десяти минут с 409 invitation_too_soon, а revokeInvitation отклоняет приглашение, которое успели принять, с 409 invitation_accepted. Оба выбрасываются как ConflictException, поэтому isConflict() равно true, а различить их позволяет errorCode.