No desenvolvimento de aplicações modernas, a segurança e a gestão fina do acesso aos dados são essenciais. Graças ao evento restrict em 4D, é possível filtrar dinamicamente os dados acessíveis a um usuário baseado em seu perfil, privilégios, e informação armazenada na sessão.
Esse blog explica como aproveitar esse evento, particularmente no contexto de uma integração com 4D Qodly Pro, para garantir que apenas dados relevantes sejam expostos.
Performance Review Application
Entendendo o evento restrict
O evento restrict é um mecanismo de filtragem automático aplicado às entidades de uma classe de dados em ORDA. É ativado para restringir os resultados da consulta (all(), query(), acesso API REST, etc.) com base num contexto específico (informação do utilizador, privilégios, etc.).
Principais benefícios:
- Filtragem dinâmica: Sempre que uma consulta é executada, o filtro definido por restrict é aplicado automaticamente.
- Controle de acesso granular: O acesso pode ser totalmente restrito ou limitado a registos específicos com base nas funções do utilizador, privilégios ou dados contextuais, como a localização geográfica ou o departamento.
- Separação da lógica: A implementação dessa filtragem é independente da lógica de negócios da aplicação, facilitando a manutenção e atualizações de segurança.
Para mais detalhes, a documentação oficial de 4D sobre filtragem de entidades oferece uma visão abrangente dessa caraterística.
Privilégio vs. Restrição: Diferenças chave
Em 4D, o controle de acesso é gerenciado através de privilégios e restrições, que trabalham juntos para garantir um acesso seguro e granular aos dados. Entender a distinção entre esses dois mecanismos é crucial para desenhar um modelo de segurança robusto.
Privilégios: Controlando o acesso a estruturas de dados
Um privilégio determina se um utilizador está autorizado a acessar uma tabela, um campo ou uma função na base de dados. Funciona como um mecanismo de controlo de acesso de alto nível que concede ou nega o acesso a todo um conjunto de dados ou função.
Exemplo de casos de utilização:
- Um utilizador básico pode ter acesso apenas de leitura à tabela Funcionários, mas não pode editar ou eliminar registos.
- Um gestor pode ter privilégios adicionais que lhe permitam modificar registos de empregados no seu departamento.
- Um administrador de RH pode ter acesso a campos sensíveis, como informações salariais, enquanto os empregados normais não podem ver esses detalhes.
Restrições: Refinamento do acesso ao nível do registo
Enquanto os privilégios controlam o acesso a um nível estrutural, as restrições determinam quais os registos específicos dentro de uma tabela autorizada que um utilizador pode ver ou interagir. O evento on restrict filtra dinamicamente os dados com base no contexto do utilizador, garantindo que os utilizadores apenas acedem a registos relevantes, respeitando as regras de segurança predefinidas.
Exemplos de casos de uso:
- Um colaborador pode aceder apenas aos seus próprios registos na tabela Employee.
- Um gestor pode ver os registos dos seus subordinados diretos.
- Um administrador de RH pode ver todos os empregados.
Casos de uso
Exemplo 1: Combinação de privilégios e contexto de sessão para restringir dados
Neste exemplo, implementamos o evento restrict na classe de dados Employee para filtrar a lista de empregados devolvida. O código a seguir ilustra como usar as informações e os privilégios da sessão para determinar o acesso aos dados:
Function event restrict() : cs.EmployeeSelection
var $obj : Object
If (Session=Null)
$obj:=Storage
Else
$obj:=Session.storage
End if
Case of
: (Session.hasPrivilege("authentify"))
return This.all()
: (Session.hasPrivilege("generatePDF"))
return This.all()
: (Session.hasPrivilege("createReview"))
return This.all()
: (Session.hasPrivilege("webadmin"))
return This.all()
: ($obj.Employee.role="Collaborator")
return This.query("ID = :1"; $obj.Employee.ID)
: ($obj.Employee.role="Manager")
return This.query("ID_Supervisor = :1"; $obj.Employee.ID)
: (($obj.Employee.role="HR") && (Session.hasPrivilege("hr")))
return This.all()
Else
return This.newSelection()
End case
Como funciona
- Filtragem baseada em privilégios: A função hasPrivilege() verifica se a sessão do utilizador inclui privilégios específicos. Por exemplo, os funcionários de RH com o privilégio “hr” têm acesso a todos os registos de funcionários.
- Elevação temporária de função: Para acções como a autenticação, a geração de documentos ou a criação de revisões, a promoção de privilégios pode conceder temporariamente direitos alargados sem alterar as definições globais do utilizador.
- Filtragem baseada na sessão: A propriedade da função (armazenada no Armazenamento ou no Armazenamento de sessão) dita os níveis de acesso. Os colaboradores só podem ver os seus próprios registos, os gestores podem acessa os empregados subordinados e o pessoal de RH pode ver todos os empregados.
- Retorno padrão seguro: Se nenhuma condição for atendida, This.newSelection() garante que o usuário não receba dados em vez de acesso irrestrito.
Nota: O privilégio webadmin é usado pelo Data Explorer em 4D. Se quiser que os seus dados sejam acessíveis através do Data Explorer, deve tratar o caso para o privilégio webadmin. Em nosso exemplo, concedemos acesso total ao Data Explorer retornando This.all() quando esse privilégio estiver presente.
Exemplo 2: Integração no Qodly Studio utilizando acções ou funções padrão
Este segundo exemplo demonstra como restringir o acesso a revisões na classe de dados Revisão com base na função do utilizador.
Function event restrict() : cs.ReviewSelection
var $obj : Object
If (Session=Null)
$obj:=Storage
Else
$obj:=Session.storage
End if
If ($obj.Employee.role=Null)
return Null
End if
Case of
: (($obj.Employee.role="HR") && (Session.hasPrivilege("hr")))
return This.all().orderBy("Date desc")
: ($obj.Employee.role="Manager")
return This.query("Employee.ID_Supervisor = :1"; $obj.Employee.ID).orderBy("Date desc")
: ($obj.Employee.role="Collaborator")
return This.query("ID_Employee = :1"; $obj.Employee.ID).orderBy("Date desc")
: (Session.hasPrivilege("webadmin"))
return This.all()
Else
return This.newSelection()
End case
Utilizar ações padrão
Na página de colaborador da aplicação Qodly, o utilizador tem o papel de colaborador e só pode consultar as suas próprias avaliações.
No Qodly Studio, definimos a ação standard Todos para preencher a tabela de dados no evento de carregamento da página do colaborador. Normalmente, a ação standard Todos obtém todas as avaliações. Mas, como adicionámos o evento restrict à classe de dados das avaliações. Só recuperamos as avaliações autorizadas com a função de colaborador.
Usando funções personalizadas
Na página Manager, os utilizadores com a função “Manager” podem ver todas as revisões relacionadas com os seus subordinados. Adicionamos uma funcionalidade de filtragem avançada para refinar os resultados por ano e estado.
Na classe de dados Review, temos a função loadReviews:
exposed Function loadReviews($departement : cs.DepartementEntity; $year : Integer; $status : cs.ReviewStatusEntity) : cs.ReviewSelection
Case of
: (($departement=Null) && ($status=Null))
return This.query("Date >= :1 AND Date <= :2"; String($year)+"/01/01"; String($year)+"/12/31")
: (($departement#Null) && ($status=Null))
return This.query("Employee.ID_Departement = :1 AND Date >= :2 AND Date <= :3"; $departement.ID; String($year)+"/01/01"; String($year)+"/12/31")
: (($departement=Null) && ($status#Null))
return This.query("ID_Status = :1 AND Date >= :2 AND Date <= :3"; $status.ID; String($year)+"/01/01"; String($year)+"/12/31")
: (($departement#Null) && ($status#Null))
return This.query("Employee.ID_Departement = :1 AND ID_Status = :2 AND Date >= :3 AND Date <= :4"; $departement.ID; $status.ID; String($year)+"/01/01"; String($year)+"/12/31")
Else
return This.newSelection()
End case
No Qodly Studio, esta função é acionada pelo evento de alteração de dados para as fontes de dados do ano e do estado.
Para a entrada de ano:
Para a caixa de seleção de estado:
O filtro personalizado é combinado com a restrição global fornecida por on restrict, permitindo-lhe refinar os seus resultados, respeitando as regras de segurança previamente definidas.
Próximo
O evento restrict em 4D prova ser uma ferramenta poderosa para gerir dinamicamente o acesso aos dados. Aproveitando os privilégios do utilizador e o armazenamento de sessão, assegura um controlo de acesso granular sem adicionar complexidade à lógica do negócio. Além disso, a integração com mecanismos complementares como promover e a adição de filtros personalizados fornecem maior flexibilidade para atender a requisitos específicos.
Para aprofundar seu entendimento desse tópico, consulte a documentação oficial sobre entidades ORDA assim como o blog 4D dedicado a filtragem de dados.