Introdução ao App Builder - Apêndice D: Segurança no App Builder (Avançado)
Este é o quarto e último apêndice da série de tutoriais Introdução ao App Builder. Estes apêndices complementam as lições da série e fornecem informações mais detalhadas sobre os conceitos apresentados.
Nesta lição, exploraremos a camada de segurança do App Builder, a área onde controlamos quem pode acessar nossa aplicação e quais partes de seus dados cada usuário tem permissão para visualizar ou alterar.
Funções
Funções são como o App Builder organiza permissões para uma fonte de dados. Uma função pode receber permissões de Leitura, Inserção, Atualização e Exclusão em uma tabela ou objeto de negócio, e os usuários obtêm suas funções indiretamente, através da associação em um ou mais grupos de segurança. Grupos organizam usuários; funções organizam permissões. Para uma explicação detalhada de como cada permissão afeta o que um usuário pode visualizar e fazer, consulte Privilégios e permissões.
Vamos criar um conjunto de funções para nossa fonte de dados Northwinds que reflitam funções comuns em uma empresa: Superusuário, Somente Leitura, Operações, RH e Vendas. Cada uma apresenta uma forma diferente de conceder permissões, desde aceleradores amplos até controle preciso, objeto por objeto.
Superusuário
Crie uma função Superusuário seguindo estas etapas:
-
Em App Workbench > Fontes de Dados, selecione a fonte Northwinds (Padrão).
-
Na seção Camada de Lógica de Negócio, clique em Funções. A caixa de diálogo Funções é aberta.
-
Clique em + Superusuário. O App Builder cria automaticamente uma função chamada Superusuário com permissões completas em todas as tabelas e objetos de negócio da fonte de dados.
Dica
+ Superusuário é um acelerador: em vez de criar uma função e depois conceder Leitura, Inserção, Atualização e Exclusão um objeto por vez, ele cria a função e concede todas as quatro permissões em tudo de uma vez.
Somente Leitura
Agora, crie uma função Somente Leitura seguindo estas etapas:
-
Clique em + Função.
-
No campo Nome, digite
Somente Leitura. -
No campo Descrição, digite uma descrição como
Acesso somente visualização a todos os dados do Northwinds. -
Clique em Salvar.
-
Expanda o acordeão Tabelas e clique em Conceder Leitura para dar à função Somente Leitura acesso de leitura a todas as tabelas de uma vez.
-
Expanda o acordeão Objetos de Negócio e clique em Conceder Leitura para fazer o mesmo com todos os objetos de negócio.
Dica
A caixa de diálogo Funções oferece vários aceleradores para conceder permissões em massa:
- Conceder Leitura e os botões equivalentes para Inserção, Atualização e Exclusão concedem essa permissão a todas as tabelas ou objetos de negócio de uma vez.
- Conceder ao Criar concede automaticamente uma nova permissão a uma função sempre que uma nova tabela ou objeto de negócio é criado, para que você não precise revisitar a caixa de diálogo Funções toda vez que seu modelo de dados cresce.
- As caixas de seleção Permissões Padrão definem quais permissões Conceder ao Criar aplica por padrão.
Operações
A função Operações gerencia o inventário principal, relacionamentos com fornecedores e atendimento de pedidos que mantêm o negócio funcionando nos bastidores. Ela supervisiona categorias de produtos, atualiza preços e níveis de estoque, gerencia contatos de fornecedores e atribui transportadoras para entregar pedidos de clientes.
-
Clique em + Função.
-
No campo Nome, digite
Operações. -
Clique em Salvar.
-
Clique no ícone Páginas na linha Operações para outra forma de acelerar a criação de funções: em vez de conceder permissões tabela por tabela, você seleciona quais páginas uma função precisa, e o App Builder concede as permissões subjacentes das quais essas páginas dependem.
-
Selecione as páginas Fornecedores, Fornecedor, Transportadoras, Transportadora, Produtos, Produto e Categorias, e conceda acesso completo (Leitura, Inserção, Atualização e Exclusão) a todas elas.
-
Selecione as páginas Início, Clientes, Cliente, Pedidos, Pedido, Funcionários e Funcionário, e conceda apenas acesso de Leitura a todas elas, já que Operações precisa visualizar esses dados sem poder alterá-los.
HR
O papel HR gerencia registros de funcionários, suas atribuições regionais e a estrutura organizacional. Requer acesso preciso e granular em vez de concessões amplas no nível de tabela ou página.
-
Clique em + Role.
-
No campo Name, digite
HR. -
Clique em Save.
-
No painel da função, clique em + Permissions para adicionar objetos específicos um de cada vez.
-
Adicione as regras Employee (Source), Region (Source), Region (List) e Employee (Network) para conceder ao HR acesso total a cada uma. Adicionar uma permissão dessa forma concede acesso total (Read, Insert, Update e Delete) por padrão.
Practice time: Create the Sales role
O papel Sales precisa gerenciar clientes e pedidos, visualizar dados de produtos, categorias, transportadoras e funcionários, e ver os relatórios que criamos. Não deve ter acesso a dados administrativos como fornecedores ou a tabela de parâmetros.
Usando o mesmo acelerador de ícone Pages que usou para Operations, crie um papel Sales com o seguinte acesso:
- Acesso total às páginas Customers, Customer, Orders e Order.
- Acesso de Read às páginas Products, Product, Categories, Shippers, Shipper, Employees, Employee e Order Total by Employee.
Não selecione as páginas Suppliers, Supplier ou Parameter, para que Sales não tenha acesso a elas.
Application Groups
Depois que as funções existem, as permissões se tornam restritivas por padrão: um usuário só recebe as permissões de uma função se seus grupos concederem essa função. Como sua própria conta de usuário ainda não está em nenhum grupo, criar as funções acima o bloqueia de seu próprio aplicativo, a menos que as conecte a usuários reais.
-
Na página Roles, clique em Application Groups.
-
Clique em Create.
-
No campo Name, use o padrão [App Name] [Role], por exemplo
Northwinds Superuser. No campo Description, descreva quem pertence ao grupo. -
Clique no ícone de marca de seleção para salvar.
-
No painel Roles, clique em Grant ao lado da função Superuser para conectá-la ao grupo de aplicativo Northwinds Superuser.
Importante
Prefira grupos de aplicativo em vez de grupos regulares quando o propósito de um grupo é específico para um aplicativo. Grupos de aplicativo são enviados junto com o aplicativo como parte de uma versão (LP), portanto são automaticamente levados para ambientes upstream como QA e Production. Grupos regulares existem por ambiente do App Builder e não se movem com o aplicativo. Consulte Users and groups para saber mais sobre a diferença.
Practice time: Create the remaining application groups
Repita as etapas acima para criar um grupo de aplicativo para cada uma das outras funções que criou: Read Only, Operations, HR e Sales.
Por fim, adicione-se ao grupo Northwinds Superuser para não perder o acesso ao aplicativo que vem construindo:
-
Navegue até IDE > User Management > Groups.
-
Encontre o grupo Northwinds Superuser e clique em + Membership.
-
Selecione seu usuário.
-
Clique no ícone de marca de seleção para salvar.
Agora deve ter permissões totais novamente, pois seu usuário pertence ao grupo Northwinds Superuser, que concede a você a função Superuser.
Reach
Reach é a implementação do App Builder de segurança em nível de linha. Enquanto as funções que acabamos de criar controlam quais operações um usuário pode executar em um objeto de dados como um todo, Reach controla quais linhas desse objeto de dados um usuário pode ver ou afetar em primeiro lugar. Reach é implementado pelo mecanismo de negócios do App Builder, portanto funciona da mesma forma independentemente do banco de dados subjacente.
Reach é construído a partir de três conceitos:
-
Reach rule: Uma regra de negócio regular, como as que criamos em Appendix B, que determina quais segmentos dos dados um usuário pode acessar. As regras de Reach normalmente usam a função mvSQL
who()para correlacionar o usuário atual com os dados que ele tem permissão de ver. -
Token de Reach: A única coluna selecionada em uma regra de Reach, identificada pelo tipo de uso de coluna Reach Token, que identifica um segmento de dados, como uma região ou uma unidade de negócios.
-
Registro de Reach: A configuração que anexa uma regra de Reach a um objeto de dados, especificando qual coluna nesse objeto de dados corresponde ao token da regra de Reach e, opcionalmente, qual função a restrição se aplica.
Lembre-se da Lição 5 que adicionamos uma coluna RegionID à nossa tabela Employee e atribuímos alguns funcionários à East Coast Region e outros à West Coast Region. Usaremos a mesma configuração para restringir a página Employees de modo que cada usuário veja apenas funcionários de sua própria região.
Primeiro, precisamos de uma forma de identificar qual registro de funcionário corresponde ao usuário atualmente conectado. Usaremos o UserID do funcionário em vez do nome de usuário, pois um nome de usuário pode mudar ao longo do tempo, enquanto um UserID permanece constante durante toda a vida da conta.
-
Vincule a fonte de dados Vinyl (Sealed) integrada ao seu aplicativo para usar seus objetos de dados públicos: em App Workbench > Data Sources, clique em + Data Source. A caixa de diálogo Add a Source to your application abre.
-
Selecione Link to existing source, depois localize e selecione Vinyl (Sealed) na lista de fontes de dados existentes.
-
Clique em Link Sources.
-
Clique em Done.
Agora, vamos dar à tabela Employee uma coluna correspondente.
-
Em App Workbench > Tables, localize a tabela Employee e abra-a.
-
Clique em + Column.
-
Dê à nova coluna o nome
UserID. Na seção Data Types, certifique-se de que o campo Logical tem Unique ID selecionado, o que define automaticamente o campo Physical como UUID. -
Clique em Save.
-
Em App Workbench > Rules, localize a regra Employee (Source) e abra-a.
-
Na aba Tables, localize a coluna UserID e marque sua caixa de seleção para incluí-la.
Em vez de digitar esse valor manualmente, vamos adicionar um controle para que possa ser definido pela interface, da mesma forma que seria necessário em um ambiente real de produção.
-
Em App Workbench > Pages, localize a página Employee e abra-a.
-
No painel Page Panel Layout, clique em Controls.
-
Clique em + Control.
-
No menu Column, selecione UserID e clique em Next.
-
Em Source, selecione User_Read, o objeto de dados público exposto pela fonte de dados Vinyl (Sealed) que você vinculou acima. A seleção Key (Column) deve ser UserId e Title (Column) deve ser UserName.
-
Clique em Next e depois em Finish.
-
Navegue até a página Employees, abra qualquer funcionário já atribuído a uma região e use o novo campo para selecionar o usuário com o qual você faz login no App Builder.
Leitura adicional
User_Read é um dos vários objetos de dados públicos que o App Builder disponibiliza para uso em suas regras. Consulte User_Read e Access to public data objects para saber mais.
Agora, vamos criar a regra de Reach.
-
Em App Workbench > Rules, clique em + Rule.
-
No campo Name, digite
Employee (Region Access). -
No campo Purpose, selecione Reach.
-
No campo Target, selecione Employee.
-
Clique em Create.
-
Na aba Tables, selecione RegionID e UserID, além da coluna de chave primária EmployeeID que já está selecionada.
-
Na aba Where, clique em + Where Clause. No campo Left Expression, digite
E.UserID, no campo Operator, selecione=, e no campo Right Expression, digitewho('userid'). Clique em Save. -
Na aba Columns, clique duas vezes na coluna RegionID. Na seção Advanced, defina seu Column Usage Type como Reach Token. Clique em Save.
-
Clique em Results no painel Rule para confirmar que a regra retorna uma única linha, contendo a região do registro de funcionário que você selecionou anteriormente.
Por fim, vamos registrar essa regra Reach para que ela restrinja o objeto de negócio Employee (Source).
-
Em App Workbench > Rules, localize e abra a regra Employee (Source).
-
No painel Rule, clique em Reach. A caixa de diálogo Reach abre.
-
Clique em + Reach.
-
No campo Reach Rule, selecione Employee (Region Access).
-
No campo Binding Column, selecione RegionID.
-
Deixe o campo Role em branco por enquanto, para que a restrição se aplique a todos os usuários, incluindo o seu, enquanto testamos. Certifique-se de que Active está marcado.
-
Clique em Save.
Visite a visualização da página Employees. Agora você deve ver apenas funcionários que compartilham uma região com o registro de funcionário que você selecionou, em vez da lista inteira.
Nota
Em uma aplicação real, você provavelmente não gostaria que essa restrição afetasse administradores. Agora que a regra está confirmada como funcionando, edite o registro Reach novamente e defina seu campo Role para a função Sales que criamos anteriormente. Dessa forma, apenas usuários cujos grupos concedem a função Sales são restritos por região, enquanto usuários com a função Superuser mantêm visibilidade total.
Nota
Registrar uma regra Reach em um objeto de negócio restringe apenas esse objeto específico, não todas as regras construídas sobre sua tabela subjacente. Por exemplo, a regra Employee (Network) que construímos em Appendix C também consulta a tabela Employee, mas como é um objeto de negócio separado de Employee (Source), ela não é restrita por uma regra Reach registrada apenas em Employee (Source). Para restringir todas as regras construídas em uma tabela, registre a regra Reach no nível da tabela em vez de em um objeto de negócio individual.
Hora de praticar: Estenda o acesso por região para clientes
Funcionários não são os únicos dados do Northwinds que poderiam se beneficiar do acesso baseado em região. Vamos aplicar a mesma restrição à tabela Customer.
-
Seguindo as etapas usadas acima para a tabela Employee, adicione uma coluna RegionID à tabela Customer, adicione-a à regra Customer (Source) e adicione um controle de lista Region (originário de Region (List)) à página pop-up Customer. Use o novo controle para atribuir uma região a alguns registros de cliente.
-
Crie uma nova regra Reach chamada
Customer (Region Access), com Purpose definido como Reach e Target definido como Customer. Na aba Tables, clique em + Tables para adicionar a tabela Employee, unida a Customer em RegionID. -
Reutilize a mesma cláusula Where e tipo de uso de coluna Reach Token da regra Employee (Region Access), desta vez selecionando RegionID da tabela Employee. Combinado com a junção, a regra agora retorna apenas clientes que compartilham uma região com o funcionário atualmente conectado.
-
Registre a nova regra no objeto de negócio Customer (Source), desta vez vinculando-a à coluna RegionID da própria tabela Customer.
-
Visite a visualização da página Customers para confirmar que apenas clientes da sua região estão visíveis.
Dica
Em App Workbench, navegue até a aba Roles. Selecionar uma função na grade mostra seu diagrama de página à direita; páginas com segurança em nível de linha aplicada mostram um ícone de mão, facilitando ver rapidamente quais páginas dessa função são restritas por Reach.
Leitura complementar
Este exemplo apenas toca na superfície do que o Reach pode fazer. Para uma descrição completa dos conceitos do Reach, cenários suportados e limitações, consulte Reach.
Block
O tipo de uso de coluna Block impede que uma linha seja editada, excluída ou ambas. Diferentemente de Roles, que se aplicam a um objeto de dados inteiro, e Reach, que controla a visibilidade de linhas, Block controla o que um usuário pode fazer com uma linha que já consegue ver. Um objeto de dados pode usar apenas uma coluna Block, e seu valor determina a restrição:
| Valor da célula | Descrição |
|---|---|
1 |
Impede a edição dessa linha. |
2 |
Impede a exclusão dessa linha. |
3 |
Impede tanto a edição quanto a exclusão da linha. |
| Qualquer outro valor | Não impede nada. |
É possível adicionar uma coluna Block em dois níveis diferentes, e o local onde você a adiciona determina o alcance da restrição. Adicioná-la a uma tabela na camada de dados aplica a restrição globalmente, em todos os lugares onde os dados dessa tabela são usados em todo o aplicativo. Adicioná-la como uma expressão em um objeto de negócio na camada de lógica, como faremos abaixo, aplica a restrição apenas onde esse objeto de negócio específico é usado.
Em vez de retornar esses números diretamente, também é possível usar a função mvSQL Block(), que aceita valores mais legíveis: None, Edit, Delete e EditAndDelete.
Depois que um pedido é enviado, seus itens de linha não devem mais sofrer alterações. Vamos bloquear a edição e exclusão de linhas OrderDetail para qualquer pedido que já tenha uma ShippedDate.
-
Em App Workbench > Rules, localize e abra a regra OrderDetail (Source).
-
Na guia Tables, clique em + Tables e adicione a tabela Order.
-
Na guia Joins, o App Builder já deve ter criado uma junção interna entre OrderDetail e Order em OrderID. Se não tiver feito isso, crie-a.
-
Na guia Columns, clique em + Column. No campo Column or Expression, insira
IIF(O.ShippedDate IS NOT NULL, Block(EditAndDelete), Block(None)). No campo Alias, insiraBlock. -
Clique em Save.
-
Clique duas vezes na nova coluna Block. Na seção Advanced, defina seu Column Usage Type como Block. Clique em Save.
Visite a visualização da página Orders e selecione um pedido que já tenha uma ShippedDate. No painel Order Details, os ícones de edição e exclusão não devem mais aparecer para nenhuma linha. Selecione um pedido que ainda não foi enviado e esses ícones devem estar disponíveis como de costume.
Hora de praticar: Bloquear o próprio pedido
Os itens de linha não são os únicos registros que não devem sofrer alterações após o envio. Aplique a mesma lógica diretamente à regra Order (Source): adicione uma coluna Block com a expressão IIF(ShippedDate IS NOT NULL, Block(EditAndDelete), Block(None)) e defina seu Column Usage Type como Block. Como ShippedDate já pertence à tabela Order, nenhuma junção é necessária desta vez. Teste seus resultados na visualização da página Orders: os pedidos enviados não devem mais mostrar seus próprios ícones de edição e exclusão.
Vinculações de capacidade
As vinculações de capacidade são um tipo de vinculação especializado que vincula o estado funcional de um painel filho aos dados de um painel pai ou objeto de dados de página. Elas podem ser usadas para ocultar ou desabilitar controles, de forma semelhante ao Block, mas com uma vantagem importante: as vinculações de capacidade também podem afetar o botão Create de um painel. Isso é algo que o Block não consegue fazer, pois esse botão existe independentemente de qualquer linha específica.
Uma coluna vinculada a capacidade pode retornar valores diferentes para controlar o estado de um controle vinculado:
| Valor da célula | Descrição |
|---|---|
1 |
Oculta o controle. |
2 |
Desabilita o controle, deixando-o visível mas inutilizável. |
| Qualquer outro valor | Reverte para o comportamento padrão do controle. |
Vamos usar isso para desabilitar o botão Create no painel Order Details sempre que seu pedido pai já tiver sido enviado, impedindo que novos itens de linha sejam adicionados a um envio que já saiu.
-
Em App Workbench > Rules, localize e abra a regra Order (Source).
-
Na guia Columns, clique em + Column. No campo Column or Expression, insira
IIF(ShippedDate IS NOT NULL, 2, 0). No campo Alias, insiraLockNewDetails. -
Clique em Salvar.
-
Abra a página Pedidos e selecione Gaveta de Ações > Live Designer.
-
Clique no ícone de coluna de vinculação no painel Detalhes do Pedido. A caixa de diálogo Colunas de Vinculação é aberta:

-
Clique em + Vinculação e defina o campo Tipo como Capacidade.
-
No campo Pai, selecione LockNewDetails.
-
No campo Evento Intrínseco, selecione Inserir.
-
Clique em Salvar.
Visite a visualização da página Pedidos e selecione um pedido enviado. O botão Criar no painel Detalhes do Pedido agora deve estar desabilitado. Selecione um pedido que não foi enviado e o botão deve estar clicável novamente.
Hora de praticar: Ocultar em vez de desabilitar
As vinculações de capacidade suportam outros status além de desabilitar um controle. Um valor de 1 oculta um controle completamente em vez de desabilitá-lo. Altere a expressão LockNewDetails para IIF(ShippedDate IS NOT NULL, 1, 0) e teste seus resultados: o botão Criar no painel Detalhes do Pedido agora deve desaparecer completamente em pedidos enviados, em vez de permanecer visível mas inutilizável.
Formatação condicional
As vinculações de bloco e capacidade cobrem as formas integradas com as quais os usuários interagem com um registro: os ícones de edição e exclusão, e o botão Criar de um painel. No entanto, qualquer botão vinculado a um evento personalizado, como os botões Quantidade Mais e Quantidade Menos que adicionamos no Apêndice B, ignora ambos. Nem o Bloco nem o Evento Intrínseco de uma vinculação de capacidade se aplicam a um evento personalizado, portanto esses botões continuam funcionando mesmo em pedidos enviados, permitindo que os usuários alterem uma Quantidade que não deveria mais ser editável.
A formatação condicional permite ocultar ou desabilitar um controle com base no valor de qualquer coluna, independentemente de qual evento ele está vinculado. Vamos usá-la para desabilitar o botão Quantidade Menos após um pedido ser enviado.
-
Abra a página Pedidos e selecione Gaveta de Ações > Live Designer.
-
Selecione o botão que executa o evento Quantidade Menos.
-
Clique em Mais > Estilos.
-
Clique em + Formatação condicional.
-
No campo Coluna de Origem, selecione ShippedDate.
-
No campo Operador, selecione Não é Nulo.
-
No campo Estado, selecione Desabilitado.
-
Clique em Salvar.
Visite a visualização da página Pedidos e selecione um pedido enviado. O botão Quantidade Menos agora deve estar desabilitado. Selecione um pedido que não foi enviado e o botão deve estar clicável novamente.
Hora de praticar: Estender a formatação condicional
Repita as etapas acima para o botão que executa o evento Quantidade Mais.
Em seguida, aplique a mesma restrição ao botão Excluir Detalhes do Pedido no painel Pedidos, desta vez definindo seu Estado como Oculto em vez de Desabilitado, para que você possa ver como os dois estados diferem. Após um pedido ser enviado, o botão deve desaparecer completamente em vez de permanecer visível mas inutilizável.
Aprendizado adicional
Isso conclui este aprofundamento nos detalhes da camada de segurança do App Builder. Se ainda não o fez, consulte o Apêndice A para uma análise mais detalhada da camada de dados, o Apêndice B para a camada de negócios ou o Apêndice C para a camada de interface do usuário.
Para continuar aprendendo sobre o App Builder, visite a Universidade Jitterbit.