Это связано как с The road to stable, then permanent, for granular_anonymous_and_logged_in_groups_permissions, так и с Granular group-based permissions for anonymous and logged in users
В ядре, а также во многих темах и плагинах, стала довольно распространена такая схема:
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;
}
Однако это неэффективный способ проверки прав пользователя. Пользователь может быть участником групп, которые ему не видны, поэтому они не сериализуются на клиенте и, следовательно, не могут использоваться последовательно и точно для проверок безопасности.
Чтобы сделать это более очевидным, мы переименовываем currentUser.groups/user.groups в currentUser.visibleGroups/user.visibleGroups в модели User и объявляем старое свойство устаревшим. Первый PR для реализации этого изменения — DEV: Deprecate calling user.groups on client directly - Pull Request #42711 - discourse/discourse - GitHub .
Если вам нужно проверять права пользователя на основе списка идентификаторов групп на клиенте в JavaScript, существует несколько альтернатив:
Для плагинов
Расширьте сериализатор current_user новым атрибутом и проверяйте права пользователя с помощью scope.in_any_groups? на стороне сервера, что также покрывает псевдогруппы, такие как 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.
Для тем и компонентов
Для настроек темы типа 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_), что является булевым значением, вычисляемым на стороне сервера на основе членства пользователя в группах.
Это также работает для объектных настроек с 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) {
// Пользователь входит хотя бы в одну выбранную группу для этого раздела.
}
}