نقشها
`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 شش مدخل دارد نه سه: emails:send همراه خود emails:read میآورد، threads:write همراه خود threads:read و labels:write همراه خود labels:read. بهجای فرض کردن، فهرست را دوباره بخوانید.
یک نقش میگوید کسی چه کاری میتواند بکند. اینکه روی کدام آدرسها، محور دیگری است و روی openemail.members زندگی میکند. grantAddress و revokeAddress را آنجا ببینید. «میتواند ایمیل بفرستد» و «میتواند از invoices@ بفرستد» دو جملهٔ متفاوتاند، و فضای کاریای که کارشناس پشتیبانی دومی استخدام میکند دومی را تغییر میدهد بیآنکه به اولی دست بزند.
بهجای نام builtin، روی editable و deletable شاخه بزنید. هر دو تنها برای مالک false هستند، که فهرستش «هر مجوزی، از جمله مجوزهایی که سال آینده اختراع میشوند» است و محاسبه میشود نه ذخیره؛ هر نقش دیگری به هر دو پاسخ true میدهد، از جمله همان پنج نقشی که هر فضای کاری با آنها آغاز میشود. نقشی که کسی نامش را عوض کرده باشد هم به هر دو درست پاسخ میدهد، و نامش دیگر چیزی به شما نمیگوید.
update فهرست مجوزها را جایگزین میکند. هیچ فراخوانیای برای اعطای تکی وجود ندارد، پس نقش را بخوانید، مدخلی را که در نظر داشتید تغییر دهید و همهٔ آنها را بازبفرستید. فرستادن یک مجوز، نقش را با دقیقاً همان یک مجوز بهعلاوهٔ هر چه آن را در پی دارد باقی میگذارد.
به محض آنکه کسی نقش را داشته باشد، delete به reassignTo نیاز دارد، و آن بهصورت یک پارامتر query میرود چون بدنه روی DELETE در چندین محیط اجرا و شماری از پراکسیها کنار گذاشته میشود. نتیجه، reassigned و keysReassigned را جداگانه گزارش میکند، تا یک اسکریپت بتواند آنچه را انجام داده لاگ کند نه آنچه را خواسته است.
listPermissions() همان GET /roles/permissions است، مسیری ثابت که دقیقاً جایی نشسته که شناسهٔ یک نقش مینشیند. کلاینت بهجای عبور دادن آن رشته از get، آن را hard-code میکند، پس درخواست نقشی که واقعاً «permissions» نام دارد یک درخواست نقش است و یک 404 Not Found میگیرد، که پاسخ صادقانه به همان چیزی است که تایپ شده. scope: false مدخلهایی را نشانه میزند که هیچ کلیدی هرگز نمیتواند داشته باشد.
نقش، سقفِ یک کلید است
کلیدی که در برابر یک نقش صادر شده باشد، میتواند اشتراک اسکوپهای خودش با مجوزهای آن نقش را انجام دهد، که در هر درخواست روی مرز محاسبه میشود. پس باریک کردن یک نقش، کلیدهایش را زنده باطل میکند بدون آنکه هیچکدام چرخانده شوند، و کلیدی که نقشی ندارد اصلاً سقفی ندارد، و همین باعث میشود نقشِ null گستردهترین حالتی باشد که یک کلید میتواند در آن باشد، نه باریکترین.
به همین دلیل هم هست که roles.delete اصرار دارد جایی برای انتقال کلیدها وجود داشته باشد. بیسرپرست گذاشتنشان سقفشان را یکسره برمیداشت و هر اعتبارنامهای را که آن نقش محدودش میکرد بیصدا ارتقا میداد.
GET /keys/self و GET /ping مقادیر roleId و grantedScopes را کنار scopes مؤثر گزارش میکنند، و اینگونه است که به «کلید من emails:send دارد و insufficient_scope میگیرم» پاسخ داده میشود: هر چیزی که در grantedScopes هست و در scopes نیست، به دست نقش گرفته شده است. openemail.me.get() و openemail.me.ping() هر دو را، تایپشده، برمیگردانند.
پارامترها
namestringالزامی- فضای کاری نقش را چه مینامد: 1 تا 48 نویسه، که پیش از ذخیره trim میشود. نامها در هر فضای کاری بدون حساسیت به بزرگی حروف یکتا هستند، پس «Support» دوم با `role_name_taken` (409 Conflict) رد میشود نه اینکه کنار اولی ساخته شود.
descriptionstring- جملهای که میگوید نقش برای چیست، trimشده و حداکثر 240 نویسه. رشتهای که پس از trim خالی باشد بهصورت null ذخیره میشود، پس توضیحی که از فاصله ساخته شده باشد بهجای آنچه فرستادهاید بهصورت null بازمیگردد.
permissionsPermission[]الزامی- آنچه نقش اعطا میکند، برگرفته از واژگانی که `listPermissions()` سرو میکند؛ رشتهای که در آن نباشد روی `permissions` یک 422 است نه اینکه بیصدا کنار گذاشته شود، پس یک اشتباه تایپی گزارش میشود بهجای آنکه یک بعدازظهر را از شما بگیرد. فهرست هنگام ورود گسترده میشود (`templates:write` کنار خود `templates:read` را ذخیره میکند)، یکتاسازی و به ترتیب متعارف بازچیده میشود، پس فهرست ذخیرهشده را از پاسخ بخوانید بهجای آنکه فرض کنید همان است که فرستادهاید.
پاسخ
object'role'- همیشه `role`. سنگقبرِ حذف با همین مقدار، `id` نقش، `deleted: true` و دو شمارندهٔ واگذاری پاسخ میدهد، و هیچیک از فیلدهای دیگرِ زیر.
idstring- شناسهٔ نقش. همان چیزی است که `roleId` یک عضو نام میبرد، همان چیزی که سقف یک API key به آن اشاره میکند، و همان چیزی که هنگام حذف این نقش `reassignTo` میگیرد.
namestring- نام فضای کاری برای این نقش، trimشده و بدون حساسیت به بزرگی حروف یکتا. هر نقشی جز نقش مالک را میتوان تغییر نام داد، از جمله نقشهای seedشده (`builtin` میگوید یک ردیف از کجا آمده، نه اینکه باید چه نامی بماند)، پس «Admin» را وعدهای دربارهٔ آنچه نقش دارد نخوانید. نامی که نقشی دیگر از پیش به آن پاسخ میدهد `role_name_taken` است (409 Conflict، با `param: "name"`)؛ تغییر نام مالک `role_immutable` (409 Conflict) است، مثل هر ویرایش دیگری روی آن.
descriptionstring | null- جملهای که نقش را توصیف میکند، یا وقتی چیزی داده نشده باشد null. ورودی خالی در هر دو create و update بهصورت null ذخیره میشود، پس این هرگز رشتهٔ خالی نیست.
permissionsPermission[]- هر آنچه نقش اعطا میکند، از پیش گستردهشده و به ترتیب متعارف، نه به ترتیبی که کسی تایپ کرده است. آن ترتیب باربر است: دو نقش با مجوزهای یکسان بهصورت JSON برابر مقایسه میشوند، و همین است که به صفحهٔ تنظیمات اجازه میدهد آنها را diff کند تا تصمیم بگیرد دکمهٔ ذخیره فعال باشد یا نه.
builtin'owner' | 'admin' | 'member' | 'viewer' | 'developer' | 'billing' | null- اینکه این ردیف از کدامیک از شش نقش seedشده آمده است، یا برای نقشی که خودِ فضای کاری نوشته null. این فیلد خاستگاه seed را ثبت میکند نه یک وضعیت را: یک نقش seedشده هم مثل هر نقش دیگری تغییر نام میدهد، مجوزهایش عوض میشود و حذف میشود. بهجای این، روی `editable` و `deletable` شاخه بزنید. نقشی که کسی «Admin» نامیده لازم نیست همان نقش seedشده باشد، و آن نقش seedشده هم شاید دیگر چنین نامی نداشته باشد.
editableboolean- بهصورت `builtin !== 'owner'` محاسبه میشود، پس تنها برای نقش مالک false است و هر PATCH روی آن نقش با `role_immutable` (409 Conflict) رد میشود. هر نقش دیگری بهطور کامل قابل ویرایش است (نام، توضیح و مجوزها)، از جمله همان پنج نقشی که فضای کاری با آنها seed میشود.
deletableboolean- بهصورت `builtin !== 'owner'` محاسبه میشود: تنها برای نقش مالک false است، که با `role_undeletable` (409 Conflict) بازمیگردد، و برای هر نقش دیگری از جمله نقشهای seedشده true. پیش از نمایش دکمه آن را بررسی کنید نه پس از رد شدن، هرچند نقشی که هنوز کسی آن را دارد به `reassignTo` هم نیاز دارد وگرنه حذف `role_in_use` (409 Conflict) میشود.
membersnumber- چند نفر این نقش را دارند، شمردهشده از ردیفهای عضویت فضای کاری. مالک میان آنها نیست: او ردیف عضویت ندارد و نمیتوان به او نقش داد، پس نقش Owner صفر دارنده گزارش میکند هرچند فهرست اعضا او را نشان میدهد.
apiKeysnumber- چند API key زندهٔ فعال زیر سقف این نقش هستند؛ کلیدهای باطلشده در شمارش نمیآیند، هرچند یک حذف، هر ردیف کلیدی را که به نقش اشاره میکند، از جمله باطلشدهها، بازنشانه میکند. این جمعیت دومی است که پیش از رفتن نقش باید منتقل شود، و همان که کسی متوجهش نمیشود: کلیدها برنامهاند و برنامه شکایت نمیکند.
createdAtstring- زمان نوشته شدن ردیف نقش، ISO-8601. ردیفهای داخلی بهصورت تنبل و در نخستین باری که چیزی به آنها نیاز دارد seed میشوند، مثل خواندن فهرست نقشها، ساختن یک نقش یا صفحهٔ API key، نه هنگام ساخت فضای کاری؛ پس مهر زمانی یک نقش داخلی، زمان رسیدن همان نخستین درخواست است نه زمان ساخته شدن فضای کاری.
updatedAtstring- زمان آخرین تغییر نقش، ISO-8601. هر PATCH پذیرفتهشده آن را جلو میبرد، حتی PATCHی که فیلدی را به همان مقداری که داشته تنظیم کند.