Deprecazione dell'uso di `user.groups` nel modello `User` in JavaScript

Questo è correlato sia a The road to stable, then permanent, for granular_anonymous_and_logged_in_groups_permissions che a Granular group-based permissions for anonymous and logged in users

Nel core, nonché in molti temi e plugin, un pattern come questo è diventato piuttosto comune:

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;
}

Tuttavia, questo non è un modo efficace per verificare i permessi dell’utente. Un utente può essere membro di gruppi che non sono visibili a lui, quindi non vengono serializzati sul client e non possono essere utilizzati in modo coerente o accurato per i controlli di sicurezza.

Per rendere questo aspetto più evidente, rinomineremo currentUser.groups/user.groups in currentUser.visibleGroups/user.visibleGroups nel modello User e deprecheremo la vecchia proprietà. La PR iniziale per farlo è DEV: Deprecate calling user.groups on client directly - Pull Request #42711 - discourse/discourse - GitHub .

Esistono diverse alternative se è necessario verificare il permesso di un utente in base a un elenco di ID di gruppo sul client in JavaScript:

Per i plugin

Estendi il serializzatore current_user con un nuovo attributo e verifica i permessi dell’utente con scope.in_any_groups? lato server, che copre anche i gruppi pseudo come 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) }

Quindi puoi eseguire this.currentUser.has_some_permission sul client.

Per temi e componenti

Per le impostazioni del tema di tipo list con list_type: group, puoi usare resolve_group_membership: true:

copy_button_allowed_groups:
  default: "1|3"
  type: list
  list_type: group
  resolve_group_membership: true

Questo sostituirà settings.copy_button_allowed_groups sul client con settings.user_in_copy_button_allowed_groups (prefissando l’impostazione con user_in_), che è un valore booleano calcolato lato server in base alle appartenenze di gruppo dell’utente.

Questo funziona anche per le impostazioni di oggetto con type: groups . Aggiungi resolve_group_membership: true alla proprietà 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

Quindi l’accesso sarà così:

for (const section of settings.menu_sections) {
  if (section.user_in_groups) {
    // L'utente appartiene ad almeno un gruppo selezionato per questa sezione.
  }
}