Dies bezieht sich sowohl auf The road to stable, then permanent, for granular_anonymous_and_logged_in_groups_permissions als auch auf Granular group-based permissions for anonymous and logged in users
Im Kern sowie in vielen Themes und Plugins ist ein Muster wie dieses ziemlich verbreitet:
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;
}
Dies ist jedoch keine effektive Methode, um die Berechtigungen eines Benutzers zu prüfen. Ein Benutzer kann Mitglied von Gruppen sein, die für ihn nicht sichtbar sind, daher werden diese nicht an den Client serialisiert und können nicht konsistent oder genau für Sicherheitsprüfungen verwendet werden.
Um dies deutlicher zu machen, benennen wir currentUser.groups/user.groups im User-Modell in currentUser.visibleGroups/user.visibleGroups um und kennzeichnen die alte Eigenschaft als veraltet. Der erste PR dafür ist DEV: Deprecate calling user.groups on client directly - Pull Request #42711 - discourse/discourse - GitHub .
Es gibt mehrere Alternativen, falls du auf dem Client in JavaScript die Berechtigung eines Benutzers basierend auf einer Liste von Gruppen-IDs prüfen musst:
Für Plugins
Erweitere den current_user-Serializer um ein neues Attribut und prüfe die Berechtigungen des Benutzers serverseitig mit scope.in_any_groups?, was auch Pseudogruppen wie logged_in_users und anonymous_users abdeckt:
add_to_serializer(
:current_user,
:has_some_permission,
include_condition: -> do
SiteSetting.plugin_enabled
end,
) { scope.in_any_groups?(SiteSetting.group_list_setting_map) }
Danach kannst du auf dem Client this.currentUser.has_some_permission aufrufen.
Für Themes und Komponenten
Für Theme-Einstellungen vom Typ list mit list_type: group kannst du resolve_group_membership: true verwenden:
copy_button_allowed_groups:
default: "1|3"
type: list
list_type: group
resolve_group_membership: true
Dies ersetzt settings.copy_button_allowed_groups auf dem Client durch settings.user_in_copy_button_allowed_groups (mit dem Präfix user_in_), was ein boolescher Wert ist, der serverseitig basierend auf den Gruppenmitgliedschaften des Benutzers berechnet wird.
Dies funktioniert auch für Objekteinstellungen mit type: groups. Füge der groups-Eigenschaft resolve_group_membership: true hinzu:
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
Der Zugriff sieht dann so aus:
for (const section of settings.menu_sections) {
if (section.user_in_groups) {
// User is in at least one selected group for this section.
}
}