هذا مرتبط بكل من The road to stable, then permanent, for granular_anonymous_and_logged_in_groups_permissions و Granular group-based permissions for anonymous and logged in users
في النواة (Core) وكذلك في العديد من القوالب (Themes) والإضافات (Plugins)، أصبح نمطًا شائعًا جدًا استخدام ما يلي:
const groupIds = this.currentUser.groups.map((g) => g.id);
const allowedGroupIds = this.siteSettings.some_group_setting.split("|").map((groupId) => parseInt(groupId, 10));
const hasPermission = allowedGroups.some((groupId) =>
userGroupIds.includes(groupId)
);
if (!hasPermission) {
return;
}
ومع ذلك، فإن هذه ليست طريقة فعالة للتحقق من صلاحيات المستخدم. يمكن أن يكون المستخدم عضوًا في مجموعات غير مرئية له، وبالتالي لا يتم تسلسلها (serialized) إلى العميل (client)، مما يجعلها غير قابلة للاستخدام بشكل متسق أو دقيق للتحقق الأمني.
لجعل هذا أوضح، سنقوم بإعادة تسمية currentUser.groups/user.groups إلى currentUser.visibleGroups/user.visibleGroups في نموذج User وإلغاء استخدام الخاصية القديمة. أول طلب دمج (PR) للقيام بذلك هو DEV: Deprecate calling user.groups on client directly - Pull Request #42711 - discourse/discourse - GitHub .
توجد بدائل متعددة إذا كنت بحاجة إلى التحقق من صلاحية المستخدم بناءً على قائمة معرّفات المجموعات (Group IDs) على العميل في جافاسكربت:
للإضافات (Plugins)
قم بتمديد مُسلسل (serializer) current_user بخاصية جديدة، وتحقق من صلاحيات المستخدم باستخدام scope.in_any_groups? على جانب الخادم، والذي يغطي أيضًا المجموعات الوهمية (pseudogroups) مثل logged_in_users و anonymous_users:
add_to_serializer(
:current_user,
:has_some_permission,
include_condition: -> do
SiteSetting.plugin_enabled
end,
) { scope.in_any_groups?(SiteSetting.group_list_setting_map) }
ثم يمكنك استخدام this.currentUser.has_some_permission على العميل.
للقوالب (Themes) والمكونات (Components)
لإعدادات القالب من النوع list مع list_type: group، يمكنك استخدام resolve_group_membership: true:
copy_button_allowed_groups:
default: "1|3"
type: list
list_type: group
resolve_group_membership: true
سيؤدي هذا إلى استبدال settings.copy_button_allowed_groups على العميل بـ settings.user_in_copy_button_allowed_groups (مع إضافة بادئة user_in_ للإعداد)، وهو قيمة منطقية (boolean) تُحسب على جانب الخادم بناءً على عضويات المستخدم في المجموعات.
يعمل هذا أيضًا مع إعدادات الكائنات (object settings) التي تحتوي على type: groups. أضف resolve_group_membership: true إلى الخاصية groups:
menu_sections:
type: objects
default:
- name: section 1
groups:
- 1
- 3
schema:
name: menu section
properties:
name:
type: string
groups:
type: groups
resolve_group_membership: true
يبدو الوصول إليها على هذا النحو:
for (const section of settings.menu_sections) {
if (section.user_in_groups) {
// المستخدم عضو في مجموعة واحدة على الأقل من المجموعات المحددة لهذا القسم.
}
}