Isso está relacionado tanto a The road to stable, then permanent, for granular_anonymous_and_logged_in_groups_permissions quanto a Granular group-based permissions for anonymous and logged in users
No core, bem como em muitos temas e plugins, um padrão como este se tornou bastante comum:
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;
}
No entanto, esta não é uma maneira eficaz de verificar as permissões do usuário. Um usuário pode ser membro de grupos que não são visíveis para ele, portanto, não são serializados para o cliente e, assim, não podem ser usados de forma consistente ou precisa para verificações de segurança.
Para tornar isso mais óbvio, estamos renomeando currentUser.groups/user.groups para currentUser.visibleGroups/user.visibleGroups no modelo User e descontinuando a propriedade antiga. O PR inicial para fazer isso é DEV: Deprecate calling user.groups on client directly - Pull Request #42711 - discourse/discourse - GitHub .
Há várias alternativas se você precisar verificar a permissão de um usuário com base em uma lista de IDs de grupos no cliente em JavaScript:
Para plugins
Estenda o serializador current_user com um novo atributo e verifique as permissões do usuário com scope.in_any_groups? no lado do servidor, o que também cobre grupos pseudos como logged_in_users e 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) }
Então, você pode fazer this.currentUser.has_some_permission no cliente.
Para temas e componentes
Para configurações de tema do tipo list com list_type: group, você pode usar resolve_group_membership: true:
copy_button_allowed_groups:
default: "1|3"
type: list
list_type: group
resolve_group_membership: true
Isso substituirá settings.copy_button_allowed_groups no cliente por settings.user_in_copy_button_allowed_groups (prefixando a configuração com user_in_), que é um booleano calculado no lado do servidor com base nas associações de grupos do usuário.
Isso também funciona para configurações de objeto com type: groups. Adicione resolve_group_membership: true à propriedade 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
Em seguida, o acesso fica assim:
for (const section of settings.menu_sections) {
if (section.user_in_groups) {
// O usuário está em pelo menos um grupo selecionado para esta seção.
}
}