Descontinuando o uso de `user.groups` no modelo `User` em JavaScript

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

Oi, Martin,
Essas alterações entrarão em vigor quando o PR for mesclado, ou com a próxima atualização após a mesclagem do PR?

Por que isso é importante? Isso não vai quebrar nada. Simplesmente exibirá um aviso no console do navegador, alertando os desenvolvedores para ajustarem seu código.

Eu tenho componentes de tema que sei que dependem disso e queria uma esclarecimento. Se for apenas um aviso, mas que ainda funcionará por um tempo, estou menos preocupado.

Normalmente, o código obsoleto continua sendo suportado até o próximo lançamento de suporte estendido. Caso contrário, os fóruns que o utilizam não teriam a menor chance de ver o aviso antes que algo quebre.

O PR já foi mesclado, então a funcionalidade está deprecada:

Mas sim, como o Moin disse, por enquanto você só receberá avisos de deprecação no console do navegador :slight_smile: Quando introduzimos uma deprecação pela primeira vez, somos obrigados a corrigir todas as instâncias no core + plugins e temas oficiais. Depois, mantemos a deprecação ativa por um tempo, o que nos permite corrigir gradualmente — ou deixar que outros corrijam — temas de terceiros, incluindo temas de clientes.

Isso não se tornará uma remoção permanente de user.groups por bastante tempo, até que tenhamos certeza de que capturamos todos os pontos de chamada. E mesmo assim, começaremos mostrando primeiro um aviso no painel administrativo para os sites que ainda possuem código chamando o antigo método.