ロール
`roles.list`、`get`、`create`、`update`、`delete`、`listPermissions`。
すべてのメソッド
const roles = await openemail.roles.list()const role = await openemail.roles.get('role_…') const support = await openemail.roles.create({ name: 'Support', description: 'Answers the shared inboxes and nothing else.', permissions: ['emails:send', 'threads:write', 'labels:write'],}) console.log(support.permissions) await openemail.roles.update(support.id, { permissions: [...support.permissions, 'templates:read'],}) await openemail.roles.delete(support.id, { reassignTo: 'role_…' }) const vocabulary = await openemail.roles.listPermissions()support.permissions の要素は 3 つではなく 6 つになる。emails:send は emails:read を、threads:write は threads:read を、labels:write は labels:read を連れてくるからである。中身を推測せず、リストを読み直すこと。
ロールが定めるのは、その人が何をしてよいかである。どのアドレスに対してそれをしてよいかはもう一方の軸であり、openemail.members に属する。そちらの grantAddress と revokeAddress を参照。「メールを送信してよい」と「invoices@ として送信してよい」は別の文であり、サポート担当者をもう 1 人雇ったワークスペースは、前者に触れずに後者だけを変更する。
分岐には builtin の名前ではなく editable と deletable を使うこと。両方が false になるのはオーナーだけであり、その権限リストは「来年生まれるものも含めたすべての権限」であって、保存されているのではなく計算される。それ以外のロールは、ワークスペースに最初から用意される 5 つを含めて、どちらにも true を返す。誰かが名前を変更したロールでも両方の値は正しいままであり、一方で名前はもう何も語らなくなっている。
update は権限リストを置き換える。1 件だけ付与する呼び出しは存在しないため、ロールを読み取り、目的の項目を変更したうえで全件を送り返すこと。権限を 1 つだけ送れば、そのロールが持つのはその 1 つと、そこから含意されるものだけになる。
そのロールを誰か 1 人でも持っている時点で、delete には reassignTo が必要になる。これはクエリパラメーターとして渡す。DELETE のボディは、いくつかのランタイムと少なからぬプロキシで破棄されるからである。結果は reassigned と keysReassigned を別々に報告するため、スクリプトは依頼した内容ではなく実際に行われた内容を記録できる。
listPermissions() は GET /roles/permissions であり、ロール id が入る位置にちょうど固定のパスが置かれている。クライアントはこの文字列を get に通すのではなくハードコードしているため、本当に「permissions」という名前のロールを取得しようとすれば、ロールの取得として扱われて 404 が返る。これは入力された内容に対する正直な答えである。scope: false は、どのキーも決して保持できない項目を示す。
ロールはキーの上限である
ロールに紐付けて発行されたキーができることは、そのキー自身のスコープとロールの権限の積集合であり、リクエストごとに境界で解決される。したがってロールを狭めれば、キーをローテーションしなくても、そのキーの権限はその場で取り消される。逆にロールを持たないキーには上限がまったくないため、ロールが null であることはキーにとって最も狭い状態ではなく、最も広い状態である。
roles.delete がキーの移動先を必須としているのもそのためである。キーを孤立させれば上限が丸ごと外れ、そのロールが抑えていたすべての資格情報が黙って昇格してしまう。
GET /keys/self と GET /ping は、実効的な scopes と並べて roleId と grantedScopes を返す。「キーには emails:send があるのに insufficient_scope が返る」という疑問はこれで解決する。grantedScopes にあって scopes にないものは、ロールによって取り除かれたものである。openemail.me.get() と openemail.me.ping() は、その両方を型付きで返す。
パラメーター
namestring必須- ワークスペースがそのロールを呼ぶ名前。1 〜 48 文字で、保存前にトリムされる。名前はワークスペース内で大文字小文字を区別せず一意であるため、2 つ目の「Support」は最初のものと並べて作成されるのではなく `role_name_taken`(409)で拒否される。
descriptionstring- そのロールが何のためのものかを述べる 1 文。トリムされ、最大 240 文字。トリムすると空になる文字列は null として保存されるため、空白だけの説明は送った値ではなく null として返る。
permissionsPermission[]必須- そのロールが付与する権限。`listPermissions()` が提供する語彙から選ぶ。語彙にない文字列は黙って捨てられるのではなく `permissions` に対する 422 となるため、打ち間違いは半日を失う代わりに報告される。リストは受け取り時に展開され(`templates:write` は `templates:read` も並べて保存する)、重複が除かれ、正規の順序に並べ直される。送った内容がそのまま保存されていると考えず、レスポンスから保存後のリストを読み取ること。
レスポンス
object'role'- 常に `role`。削除時のトゥームストーンも同じ値に加えて、そのロールの `id`、`deleted: true`、2 つの再割り当て件数を返し、以下の他のフィールドは返さない。
idstring- ロールの id。メンバーの `roleId` が指す値であり、API キーの上限が指す値であり、このロールを削除するときに `reassignTo` が受け取る値でもある。
namestring- ワークスペースにおけるそのロールの名前。トリムされ、大文字小文字を区別せず一意である。オーナーのロールを除けば、初期投入されたものも含めてすべてのロールを改名できる(`builtin` はその行の出自を示すものであって、名前を固定するものではない)。したがって「Admin」という名前を、そのロールが持つ権限の保証として読んではならない。他のロールがすでに名乗っている名前は `role_name_taken`(409、`param: "name"`)になる。オーナーの改名は、その他のあらゆる編集と同じく `role_immutable`(409)になる。
descriptionstring | null- ロールを説明する文。指定されなかった場合は null。空白だけの入力は create でも update でも null として保存されるため、この値が空文字列になることはない。
permissionsPermission[]- そのロールが付与するすべての権限。入力された順ではなく、展開済みかつ正規の順序で並ぶ。この順序には意味がある。同じ権限を持つ 2 つのロールは JSON として等しく比較され、それによって設定画面は差分を取り、保存ボタンを有効にするかどうかを判断できる。
builtin'owner' | 'admin' | 'member' | 'viewer' | 'developer' | 'billing' | null- この行が、初期投入される 6 つのロールのどれに由来するか。ワークスペースが自分で作成したロールでは null。これは出自の記録であって状態ではない。初期投入されたロールも、他と同じように改名され、権限を変更され、削除される。分岐にはこの値ではなく `editable` と `deletable` を使うこと。誰かが「Admin」と名付けたロールが初期投入のものであるとはかぎらず、初期投入のものがもうその名前で呼ばれていないこともある。
editableboolean- `builtin !== 'owner'` として計算されるため、false になるのはオーナーのロールだけであり、そのロールに対する PATCH はすべて `role_immutable`(409)で拒否される。それ以外のロールは、ワークスペースに初期投入される 5 つも含めて、名前・説明・権限のすべてを編集できる。
deletableboolean- `builtin !== 'owner'` として計算される。false になるのはオーナーのロールだけで、その削除は `role_undeletable`(409)で返る。初期投入されたものを含め、それ以外のロールでは true になる。拒否された後ではなく、ボタンを表示する前にこの値を確認すること。ただし、まだ誰かが持っているロールには `reassignTo` も必要であり、指定しなければ削除は `role_in_use`(409)になる。
membersnumber- このロールを持つ人数。ワークスペースのメンバー行から数える。オーナーはここに含まれない。オーナーにはメンバー行がなくロールを割り当てることもできないため、メンバー一覧には現れていても、Owner ロールの保持者は 0 と報告される。
apiKeysnumber- このロールによって上限を課されている有効な API キーの数。失効したキーは数に含まれないが、削除時にはそのロールを指すすべてのキー行が、失効したものも含めて付け替えられる。これはロールを削除する前に移さなければならないもう 1 つの集団であり、誰も気づかない方の集団でもある。キーはプログラムであり、プログラムは文句を言わない。
createdAtstring- ロールの行が書き込まれた日時。ISO 8601。組み込みロールの行は、ワークスペース作成時ではなく、ロール一覧の読み取り、ロールの作成、API キー画面の表示など、初めて必要になった時点で遅延的に生成される。そのため組み込みロールのタイムスタンプは、その最初のリクエストが届いた時刻であり、ワークスペースが作られた時刻ではない。
updatedAtstring- ロールが最後に変更された日時。ISO 8601。受理された PATCH はすべてこの値を更新する。すでに保持している値をそのまま設定した場合も同様である。