Lugar adequado para propor um predicado de permissões?

Com o objetivo de propor uma solução para Restrict exposure of full name to certain groups, gostaria de definir um predicado de permissão (do lado do servidor) que responda à pergunta

Com base no escopo/contexto do usuário atual, é aceitável revelar o nome completo de (outros) usuários?

(O escopo pode ser definido por uma solicitação do cliente ou por alguma etapa de processamento interno, como a geração de mensagens de e-mail de resumo.)

Qual é a construção correta para tal predicado? Onde no codebase ele deveria residir? Estou pensando que talvez isso pertença a um guardian — estou no caminho certo? Alguma opinião sobre qual deles?

Imagino que este novo predicado englobaria muitas (mas não todas) instâncias de SiteSettings.enable_names? atualmente no codebase. (Atingir os Serializers que produzem plugs de user.name resolve a maioria dos vazamentos de dados, mas não todos.) Um bom benefício disso é que introduziria um ponto de extensão pelo qual um plugin futuro poderia alterar o comportamento (atualmente não é possível, pelo que sei, ou eu faria isso!). Portanto, se eu conseguir fazer isso funcionar, isso se tornaria um pull-request para o core do discourse — e eu gostaria de enviar um PR que tenha esperança de ser aceito.

1 curtida

Aqui está o que aprendi/deduzi:

  • Guardian é de fato a coisa que encapsula “O que o usuário tem permissão para fazer?” (Uma instância de Guardian tem uma instância de User, também.)
  • Assim, o local apropriado para um predicado de permissão é simplesmente como um método em Guardian (lib/guardian.rb).
    • Se o método for “O usuário pode fazer Z para um objeto Xxxx?”, então ele provavelmente pertence a um dos arquivos de mixin XxxxGuardian (lib/guardian/...).
    • Caso contrário, ele vai para a definição base de Guardian.
  • ApplicationController gerencia um atributo guardian refletindo a solicitação/cliente atual e o fornece aos serializadores como seu scope, então o Guardian atual está disponível quando necessário (exceto quando não está[1])
  • Existem lugares onde um Guardian pronto não está disponível, tipicamente em uma tarefa de backend executada pelo sistema, mas se você tiver um identificador para um “usuário agindo” (por exemplo, o usuário destinatário, ao gerar uma notificação por e-mail), você pode criar um guardião apropriado na hora: Guardian.new(the_user).

  1. ↩︎