Ceci est lié à la fois à The road to stable, then permanent, for granular_anonymous_and_logged_in_groups_permissions et à Granular group-based permissions for anonymous and logged in users
Dans le cœur de l’application ainsi que dans de nombreux thèmes et plugins, un motif comme celui-ci est devenu assez courant :
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;
}
Cependant, ce n’est pas une méthode efficace pour vérifier les autorisations d’un utilisateur. Un utilisateur peut être membre de groupes qui ne sont pas visibles pour lui, de sorte qu’ils ne sont pas sérialisés vers le client et ne peuvent donc pas être utilisés de manière cohérente ou précise pour les vérifications de sécurité.
Pour rendre cela plus évident, nous renommerons currentUser.groups/user.groups en currentUser.visibleGroups/user.visibleGroups dans le modèle User et déprécierons l’ancienne propriété. La PR initiale pour cela est DEV: Deprecate calling user.groups on client directly - Pull Request #42711 - discourse/discourse - GitHub .
Il existe plusieurs alternatives si vous devez vérifier l’autorisation d’un utilisateur sur la base d’une liste d’identifiants de groupes côté client en JavaScript :
Pour les plugins
Étendez le sérialiseur current_user avec un nouvel attribut et vérifiez les autorisations de l’utilisateur avec scope.in_any_groups? côté serveur, ce qui couvre également les groupes pseudo comme logged_in_users et 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) }
Ensuite, vous pouvez utiliser this.currentUser.has_some_permission côté client.
Pour les thèmes et les composants
Pour les paramètres de thème de type list avec list_type: group, vous pouvez utiliser resolve_group_membership: true :
copy_button_allowed_groups:
default: "1|3"
type: list
list_type: group
resolve_group_membership: true
Cela remplacera settings.copy_button_allowed_groups côté client par settings.user_in_copy_button_allowed_groups (en préfixant le paramètre avec user_in_), qui est un booléen calculé côté serveur sur la base des appartenances aux groupes de l’utilisateur.
Cela fonctionne également pour les paramètres d’objet avec type: groups . Ajoutez resolve_group_membership: true à la propriété 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
L’accès se fait alors ainsi :
for (const section of settings.menu_sections) {
if (section.user_in_groups) {
// L'utilisateur appartient à au moins un groupe sélectionné pour cette section.
}
}