Allow and Deny

Lateral 8.5

Porcentagem Traduzida

Neste capítulo, você irá:

  • Aprenda sobre os callbacks Allow e Deny.
  • Entenda em que order os callbacks são chamados.
  • O sistema de segurança do Meteor nos permite controlar modificações ao banco de dados sem precisarmos definir Métodos toda vez que nós queremos fazer mudanças.

    Por nós necessitarmos fazer tarefas auxiliares como decorar o post com propriedades extras e tomar uma ação especial quando o URL do post já ter sido postada, usar um Método post específico fazia bastante sentido ao se criar um post.

    Por outro lado, nós não precisamos realmente criar novos Métodos para atualizar e deletar posts. Nós apenas precisamos checar se o usuário tem permissão para fazer tais ações, e isto foi feito pelas callbacks allow e deny.

    Usar estas callbacks nos permite sermos mais declarativos quanto às modificações ao banco de dados, e dizer que tipo de atualizações podem ser feitas. O fato delas se integrarem ao sistema de contas é um bônus adicional.

    Callbacks múltiplas

    Nós podemos definir quantas callbacks allow quanto necessárias. Nós precisamos que pelo menos uma delas retorne true para a dada mudança que está ocorrendo. Então quando Posts.insert é chamado no navegador (não importa se é do código do aplicativo do lado do cliente ou do console), o servidor irá em resposta chamar quaisquer checagens de insert permitidas que ele puder até encontrar uma que retorne true. Se ele não encontrar nenhuma, ele não permitirá o insert, e retornará um erro 403 para o cliente.

    Similarmente, nós podemos definir uma ou mais callbacks deny. Se qualquer uma dessas callbacks retornar true, a mudança será cancelada e um 403 será retornado. A lógica disto significa que para um insertbem-sucedido, uma ou mais callback allow insert assim como cada callback deny insert serão executadas.

    Note: n/e stands for Not Executed
    Note: n/e stands for Not Executed

    Em outras palavras, Meteor começa a lista de callback primeiro com deny, então com allow, e executa cada callback até que uma delas retorne true.

    Um exemplo prático deste padrão poderia ser ter duas callbacks allow(), uma que checa se o post pertence ao usuário atual, e a segunda que checa se o usuário atual tem direitos administrativos. Se o usuário atual é um administrador, isto garante que ele poderá atualizar qualquer post, já que pelo menos uma dessas callbacks retornará true.

    Compensação de Latência

    Lembre que Métodos de mutação do banco de dados (tais como .update()) tem sua latência compensada, assim como qualquer outro Método. Por exemplo, se você tentar deletar um post que não pertence a você através do console, você verá que o post brevemente desaparece ao passo que sua coleção local perde o documento, mas então re-aparece assim que o servidor informa que, não, de fato o documento não foi deletado.

    Claro que este comportamento não é um problema quando acionado pelo console (até mesmo porque se os usuários estiverem tentando bagunçar com informação no console, não é realmente um problema seu o que acontece no navegador deles). Entretanto, você precisa assegurar que isto não aconteça na sua interface do usuário. Por exemplo, você precisa tomar cuidado para assegurar que você não está mostrando aos usuários botões de deletar para documentos que eles não têm permissão para tanto.

    Felizmente, já que você pode compartilhar código de permissão entre o cliente e o servidor (por exemplo, você poderia escrever uma função de biblioteca canDeletePost(user, post) e pô-la no diretório compartilhado /lib), fazer isto normalmente não requer muito código extra.

    Permissões do lado do servidor

    Lembre que o sistema de permissões se refere apenas às mutações do banco de dados iniciadas no cliente. No servidor, o Meteor assume que todas operações são permitidas.

    Isto signfica que se você tivesse que escrever um Método Meteor deletePost do lado do servidor que pudesse ser chamado do cliente, qualquer um seria capaz de deletar qualquer post. Então você provavelmente não quer fazer isso a não ser que você cheque as permissões do usuário dentro do Método também.

    Usando Deny como uma Callback

    Finalmente, um truque que você pode fazer com deny é usá-la como uma callbaclk “onX”. Por exemplo, você pode conseguir uma timestamp lastModified com o código seguinte:

    Posts.deny({
      update: function(userId, doc, fields, modifier) {
        doc.lastModified = +(new Date());
        return false;
      },
      transform: null
    });
    

    Como callbacks deny rodam para cada update bem-sucedido, nós sabemos que essa callback rodará e poderá fazer mudanças ao documento de uma forma estruturada.

    Admitidamente, esta técnica é tipo um hack, então você pode querer fazer atualizações usando um Método no lugar. De qualquer forma, ainda é bom saber, e no futuro nós podemos esperar que algum tipo de callback beforeUpdate esteja disponível.