تخطَّ إلى المستندات
Ruby

الأعضاء

`members.list` و`list_all` و`iterate` و`get` و`add` و`update` و`remove` و`grant_address` و`revoke_address`، وتوابع الدعوات إلى جانبها.

كل الدوالّ

members.rb
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 في النوع دفاعية لا حالة شوهدت هذه الواجهة تنتجها. وهو يخصّه هو لا مساحة العمل، فلا شيء في هذا المورد يمكنه ضبطه.
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`: أشخاص يحملون عناوين من قبل وجود الأدوار ولم يمنحهم أحد دورًا منذ ذلك الحين.

الدعوات

invitations.rb
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 بينهما.