Funções
`roles->list`, `listAll`, `iterate`, `get`, `create`, `update`, `delete` e `listPermissions`.
Todos os métodos
use OpenEmail\Constants\ApiScopes; $page = $client->roles->list();echo count($page), PHP_EOL; $role = $client->roles->get('role_8b1f4c2e9a7d3b60e5f1a2c4');echo $role['name'], PHP_EOL; $support = $client->roles->create([ 'name' => 'Support', 'description' => 'Answers the shared inboxes and nothing else.', 'permissions' => [ApiScopes::EMAILS_SEND, ApiScopes::THREADS_WRITE, ApiScopes::LABELS_WRITE],]); echo implode(', ', $support['permissions']), PHP_EOL; $client->roles->update($support['id'], ['permissions' => [...$support['permissions'], ApiScopes::TEMPLATES_READ]]); $client->roles->delete($support['id'], reassignTo: $role['id']); $vocabulary = $client->roles->listPermissions();echo implode(', ', array_column($vocabulary, 'id')), PHP_EOL;$support['permissions'] contém seis entradas, não três: emails:send traz emails:read, threads:write traz threads:read e labels:write traz labels:read. Leia a lista devolvida em vez de a dar por adquirida.
list devolve uma OpenEmail\Result\Page, listAll devolve todas as funções num único array, e iterate devolve um Generator que entrega uma função de cada vez. Uma função volta como um array com chaves em camelCase, por isso $role['permissions'] lê a lista. create e update aceitam o corpo como um único array com os nomes da API, enquanto delete aceita reassignTo: como argumento nomeado.
Uma função diz o que alguém PODE FAZER. A que ENDEREÇOS o pode fazer é o outro eixo e fica em $client->members: veja members->grantAddress e members->revokeAddress na página Membros. «Pode enviar correio» e «pode enviar como invoices@» são frases diferentes, e um espaço de trabalho que contrata um segundo agente de apoio altera a segunda sem tocar na primeira. Uma permissão responde às duas: uma função com addresses:all alcança todos os endereços, incluindo os que forem adicionados depois, sem concessão, e só uma pessoa na aplicação a pode atribuir a uma função.
Baseie a lógica em editable e deletable, e não em builtin nem no nome. Ambos são false apenas para o proprietário, cuja lista é «todas as permissões, incluindo as que forem inventadas para o ano» e é calculada em vez de guardada. Todas as outras funções respondem true a ambos, incluindo as cinco com que um espaço de trabalho é semeado. Uma função que alguém renomeou continua a responder corretamente a ambos, e o seu nome já não lhe diz nada.
update SUBSTITUI a lista de permissões. Não existe uma chamada para conceder uma só, por isso leia a função, altere a entrada que pretendia e devolva-as todas, como faz [...$support['permissions'], ApiScopes::TEMPLATES_READ] acima. Enviar uma permissão deixa a função com exatamente essa, mais o que ela implicar.
delete exige reassignTo: assim que alguém detiver a função. O cliente envia-o como o parâmetro de consulta reassignTo, porque um corpo em DELETE é descartado por vários runtimes e por um bom número de proxies, e omite o parâmetro quando não passa nada. O resultado indica reassigned e keysReassigned em separado, para que um script possa registar o que fez e não o que pediu.
listPermissions é GET /roles/permissions, um caminho fixo que fica exatamente onde iria o id de uma função. O cliente chama esse caminho diretamente em vez de passar a palavra por get, e devolve uma lista simples, não uma OpenEmail\Result\Page: um array por permissão, com id, label, group e scope. scope a false marca as entradas que nenhuma chave pode alguma vez ter. Não passe a palavra a get você mesmo. $client->roles->get('permissions') constrói o mesmo caminho, por isso envia o mesmo pedido e recebe o vocabulário no seu envelope de lista em vez de uma função ou de um 404.
Uma função é o teto de uma chave
Uma chave emitida sob uma função só pode fazer a INTERSEÇÃO dos seus próprios âmbitos com as permissões dessa função, resolvida por pedido na fronteira. Assim, restringir uma função revoga as suas chaves em direto, sem que nenhuma delas seja rodada. Uma chave sem função não tem teto nenhum, o que faz de um roleId null o estado mais amplo em que uma chave pode estar, e não o mais restrito.
É também por isso que roles->delete insiste em ter para onde mover as chaves. Deixá-las órfãs eliminaria por completo o seu teto, promovendo em silêncio todas as credenciais que a função limitava.
GET /keys/self e GET /ping devolvem roleId e grantedScopes ao lado dos scopes efetivos. É assim que se responde a «a minha chave tem emails:send e estou a receber insufficient_scope»: tudo o que esteja em grantedScopes e falte em scopes foi retirado pela função. $client->me->get() e $client->me->ping() devolvem ambos no seu array, por isso array_diff($key['grantedScopes'], $key['scopes']) lista o que a função retirou. A recusa em si é um PermissionException cujo isScopeMissing() é true.
Parâmetros
namestringobrigatório- O nome que o espaço de trabalho dá à função: 1 a 48 caracteres, aparado antes de ser guardado. Os nomes são únicos por espaço de trabalho sem distinguir maiúsculas de minúsculas, pelo que um segundo «Support» é recusado com `role_name_taken` (409), lançado como `ConflictException`, em vez de ser criado ao lado do primeiro.
descriptionstring- Uma frase a dizer para que serve a função, aparada e com 240 caracteres no máximo. Uma string que fique vazia depois de aparada é guardada como null, por isso uma descrição feita de espaços volta como null e não como aquilo que enviou. Em `create`, omita a chave em vez de passar null: o cliente envia um null tal como está, e `create` recusa-o com um 422. Em `update`, `'description' => null` apaga-a.
permissionsarrayobrigatório- O que a função concede, retirado do vocabulário que `listPermissions` serve. Uma string que não conste dele é um 422 em `permissions`, lançado como `ValidationException` com `param` definido como `permissions`, em vez de ser descartada em silêncio, por isso uma gralha é comunicada em vez de lhe custar uma tarde. A lista é EXPANDIDA à entrada (`templates:write` guarda `templates:read` ao seu lado), desduplicada e reposta por ordem canónica, por isso leia a lista guardada a partir da resposta em vez de assumir que é a que enviou.
Resposta
objectstring- Sempre `role`. A lápide devolvida pela eliminação responde com o mesmo valor, o `id` da função, `deleted` a true e as duas contagens de reatribuição, e com nenhum dos outros campos abaixo.
idstring- O id da função, lido como `$role['id']`. É o que o `roleId` de um membro nomeia, aquilo para onde aponta o teto de uma chave de API, e o que `reassignTo:` recebe quando outra função é eliminada e os seus titulares passam para esta.
namestring- O nome que o espaço de trabalho dá à função, aparado e único sem distinguir maiúsculas de minúsculas. Todas as funções, menos a do proprietário, podem ser renomeadas, incluindo as semeadas (`builtin` diz de onde veio uma linha, não como tem de continuar a chamar-se), por isso uma função chamada «Admin» não diz nada de certo sobre o que detém. Um nome a que outra função já responde dá `role_name_taken` (409, com `param` definido como `name`). Renomear o proprietário dá `role_immutable` (409), tal como qualquer outra edição dele.
descriptionstring or null- A frase que descreve a função, ou null quando não foi dada nenhuma. Entrada em branco é armazenada como null tanto no create como no update, por isso isto nunca é uma string vazia.
permissionsarray- Tudo o que a função concede, já expandido e por ordem canónica, e não pela ordem em que alguém o escreveu. Essa ordenação é estrutural: duas funções com as mesmas permissões têm arrays iguais, que é o que permite a um ecrã de definições compará-las com `===` para decidir se o botão Guardar fica ativo.
builtinstring or null- De qual das seis funções semeadas veio esta linha, `owner`, `admin`, `member`, `viewer`, `developer` ou `billing`, ou null para uma que o próprio espaço de trabalho escreveu. Regista a origem e não um estado: uma função semeada é renomeada, recebe outras permissões e é eliminada como qualquer outra. Baseie a lógica em `editable` e `deletable`, e não neste campo. Uma função a que alguém chamou «Admin» não tem de ser a semeada, e a semeada pode já não se chamar assim.
editablebool- Calculado como `builtin !== 'owner'`, pelo que é false apenas para a função de proprietário, e todos os `update` dessa função são recusados com `role_immutable` (409). Todas as outras funções são editáveis por completo (nome, descrição e permissões), incluindo as cinco com que um espaço de trabalho é semeado.
deletablebool- Calculado como `builtin !== 'owner'`: false apenas para a função de proprietário, que volta com `role_undeletable` (409), e true para todas as outras funções, incluindo as semeadas. Verifique-o antes de oferecer o botão e não depois da recusa. Uma função que alguém ainda detenha também precisa de `reassignTo:`, caso contrário a eliminação dá `role_in_use` (409). Ambas as recusas são lançadas como `ConflictException`, e `errorCode` distingue-as.
membersint- Quantas pessoas detêm esta função, contadas a partir das linhas de membro do espaço de trabalho. O proprietário não está entre elas: não tem linha de membro e não lhe pode ser atribuída uma função, por isso a função Owner indica zero titulares mesmo quando a lista de membros o mostra.
apiKeysint- Quantas chaves de API ativas estão limitadas por esta função. As chaves revogadas ficam de fora da contagem, embora uma eliminação volte a apontar todas as linhas de chave que apontavam para a função, incluindo as revogadas. É a segunda população que tem de ser movida antes de a função poder desaparecer, e aquela de que ninguém dá conta: as chaves são programas, e um programa não se queixa.
createdAtstring- Quando a linha da função foi escrita, como string ISO 8601. As linhas integradas são semeadas de forma preguiçosa na primeira vez que algo precisa delas, como uma leitura da lista de funções, a criação de uma função ou o ecrã das chaves de API, e não na criação do espaço de trabalho. Por isso, o carimbo temporal de uma função integrada é o momento em que esse primeiro pedido chegou e não aquele em que o espaço de trabalho foi criado.
updatedAtstring- Quando a função mudou pela última vez, como string ISO 8601. Todos os `update` aceites o fazem avançar, incluindo um que defina um campo com o valor que já tinha.