Desenvolvimento - Delphi

Delphi: Controle de Acesso - TreeView para gerenciamento de usuários

Amigos do mundo Delphi, quem nunca se deparou com o problema de fazer uma rotina para controlar a segurança dos acessos dos usuários em um sistema?

por George De Luca



Amigos do mundo Delphi, quem nunca se deparou com o problema de fazer uma rotina para controlar a segurança dos acessos dos usuários em um sistema?

Trata-se de um componente herdado do TTreeView, que é capaz de fazer todo o gerenciamento dos acessos de cada usuário ou grupo de usuários.

Instalação

Com o Delphi 7 aberto, feche o projeto através do menu File e depois em Close All.

Clique no menu File e depois Open, procurando o arquivo Seguranca.dpk.

Clique no botão Compile e depois em Install. Veja a Figura 1.


Figura 1. Tela para instalação do componente

O componente instalado está na Figura 2.


Figura 2. Componente Instalado

Tabela Exemplo

Primeiramente crie uma tabela que irá guardar os acessos que cada usuário/grupo terá. Veja a Listagem 0 o script desta tabela.

O campo "usuário" poderá ser de qualquer tamanho e também deverá estar relacionado com uma tabela usuário. Não irei mostrar os detalhes de banco neste artigo, para maiores detalhes baixe o exemplo completo no site.

Listagem 0 - Tabela Segurança

CREATE TABLE SEGURANCA (
    USUARIO   	VARCHAR(7) NOT NULL,
    TAG		INTEGER NOT NULL,
    ACESSO     	INTEGER,
    INCLUSAO   INTEGER,
    ALTERACAO  INTEGER,
    EXCLUSAO   INTEGER,
    RELATORIO  INTEGER
);

ALTER TABLE SEGURANCA ADD CONSTRAINT PK_SEGURANCA PRIMARY KEY (USUARIO, TAG);

Os campos INCLUSAO, ALTERACAO, EXCLUSAO E RELATORIO quando estiverem com o valor 0 será porque o usuário não terá acesso a opção e 1 quando tiver acesso.

Os cadastros e relatórios que o usuário não tiver acesso algum, não terão nenhuma linha gravada na tabela. O componente internamente trabalha com ClientDataSet. Com isso pode-se trabalhar com qualquer tipo de banco de dados (o exemplo proposto está em Firebird) e também com qualquer tipo de componente de acesso como dbExpress.

Menu Principal

Crie um formulário colocando o nome de FrmPrincipal e coloque um TMainMenu como mostrado na Figura 3.


Figura 3 . Exemplo do formato do menu principal que será feito o controle de acesso

Para usar o componente temos que utilizar alguns "macetes" onde dentro do componente será identificado e executará de acordo com o programado.

Em cada menu que será usado, teremos que modificar o valor das propriedades Tag e HelpContext da seguinte forma:

  • A propriedade Tag identifica qual o código que será guardado na tabela do banco de dados, e precisa seguir uma ordem. Os menus principais seguem uma seqüência iniciando de 10 (10,11,12,13,...) e nos sub-menus colocamos o código do menu pai e em seguida a sua seqüência (Tabela 1).

  • O HelpContext identifica o tipo de opção do menu (Cadastro, Relatório ou Sub-menu). As opções que forem de cadastro (Inclusão, Alteração e Exclusão) terão o valor de 1, as opções que forem de relatório será 2 e os sub-menus 3. Veja na Tabela 1 como ficará o exemplo proposto.


Tabela 1. Valores para as propriedades do TMainMenu

Os itens de menus que não serão usados (como separadores e a opção Sair), deixe a Tag e o HelpContext igual a 0 que assim não interferirá no controle de acesso.

O menu que já exista num sistema já pronto poderá ser alterado facilmente para que possa ser usado em conjunto com o componente em questão.

Data Module

Adicione mais um Data Module ao projeto e coloque o nome de DtmDados (Figura 4).


Figura 4 . Data Module

Repare que apesar de não ter comentado em momento algum a tabela de usuários coloquei o conjunto SQLDataSet, DataSetProvider e ClientDataSet, pois na verdade está tabela será de acordo com o sistema que o leitor irá trabalhar.

No sqlSeguranca coloque o seguinte SQL:

SELECT S.* 
FROM SEGURANCA S, USUARIOS U
WHERE S.USUARIO = :USUARIO AND S.USUARIO = U.USUARIO
ORDER BY S.TAG

Não entrarei em detalhes neste item. Para saber mais detalhes baixe no site este o exemplo completo. Interface

Adicione mais um formulário ao projeto e coloque o nome de FrmAcessos. Adicione a ele um GroupBox com Align = alTop e um Panel com Align = alBottom e o componente TreeSeguranca com Align = alClient.

No GroupBox adicione um DBLookupComboBox (dbcUsuarios), um DBText (dbtNome) e um BitBtn (bbtOK); no Panel adicione 3 BitBtns; adicione também ao formulário um ImageList.Veja a disposição dos componentes na Figura 5.


Figura 5 . Formulário para gerenciar os acessos dos usuários

Associe o DataSource dsUsuario do data module ao dbcUsuarios e dsSeguranca e o ImageList ao TreeSeguranca.

No ImageLista insira 7 imagens. Cada imagem é usada com um propósito na TreeSeguranca. Veja na Tabela 2 para que cada imagem serve.


Tabela 2. Objetivos das imagens

A listagem completa deste exemplo está na Listagem 1.

Listagem 1. UAcessos.pas

unit UAcessos;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, ExtCtrls, DB, StdCtrls,Buttons, ImgList, TreeSeguranca, 
  Mask, DBCtrls, Provider,SqlExpr, DBClient;
type
  TfrmAcessos = class(TForm)
    GroupBox: TGroupBox;
    TreeSeguranca: TTreeSeguranca;
    bbtOK: TBitBtn;
    ImageList1: TImageList;
    Panel1: TPanel;
    dbcUsuarios: TDBLookupComboBox;
    dbtNome: TDBText;
    Bevel1: TBevel;
    bbtGRAVAR: TBitBtn;
    bbtCANCELAR: TBitBtn;
    bbtFECHAR: TBitBtn;
    procedure FormActivate(Sender: TObject);
    procedure bbtOKClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure bbtGRAVARClick(Sender: TObject);
    procedure bbtCANCELARClick(Sender: TObject);
    procedure bbtFECHARClick(Sender: TObject);
  private
    { Private declarations }
    procedure HabilitaDesabilita;

  public
    { Public declarations }
  end;

var
  frmAcessos: TfrmAcessos;
implementation
uses UDmCadastro, UPrincipal;
{$R *.dfm}
procedure TfrmAcessos.FormActivate(Sender: TObject);
begin
   dtmDados.cdsUsuario.Open;
   dbtNome.Caption := "";

   // indica em qual formulario esta o menu principal
   TreeSeguranca.pFormulario := frmMenu;
end;

// botao Ok
procedure TfrmAcessos.bbtOKClick(Sender: TObject);
begin
   // passa o codigo do usuario para o componente
   TreeSeguranca.pUsuario := dtmDados.cdsUsuarioUSUARIO.Value;
   // ativo a arvore
   TreeSeguranca.AtivaTree;

   HabilitaDesabilita;
end;

// fechamento do formulario
procedure TfrmAcessos.FormClose(Sender: TObject; var Action: TCloseAction);
begin
   dtmDados.cdsUsuario.Close;
end;

// habilito e desabilito os botoes e outros componentes visuais necessarios
procedure TfrmAcessos.HabilitaDesabilita;
begin
   TreeSeguranca.Enabled := not TreeSeguranca.Enabled;
   bbtGRAVAR.Enabled     := not bbtGRAVAR.Enabled;
   bbtCANCELAR.Enabled   := not bbtCANCELAR.Enabled;
   bbtOK.Enabled         := not bbtOK.Enabled;
   dbcUsuarios.Enabled   := not dbcUsuarios.Enabled;
   dbtNome.Enabled       := not dbtNome.Enabled;
end;

procedure TfrmAcessos.bbtGRAVARClick(Sender: TObject);
begin
  // grava os itens da grade marcada na tabela
  TreeSeguranca.Salvar;
  HabilitaDesabilita;
end;

// botao cancelar
procedure TfrmAcessos.bbtCANCELARClick(Sender: TObject);
begin
   HabilitaDesabilita;
   dbtNome.Caption := "";
End;

// botao fechar
procedure TfrmAcessos.bbtFECHARClick(Sender: TObject);
begin
   Close;
end;
end.

Executando

Informe um usuário pela DBLookupComboBox e clique no botão Ok. Neste momento irão aparecer os menus e se caso algum usuário já tiver algum acesso será mostrado.

Veja como fica a tela ao ser executada na Figura 6.


Figura 6. Execução do programa

Marque e desmarque os acessos clicando 2x em cima dos nós da árvore e ao final clique no botão Gravar ou caso queira cancelar no botão Cancelar.

Na Listagem 2 mostro um exemplo de como poderá ser usado os acessos gravados na tabela Seguranca num formulário que tenha o menu principal e na Listagem 3 outro exemplo de como usar num formulário de cadastro.

Listagem 2. Exemplo de rotina para bloqueio dos menus

procedure Bloqueio;
Var
  mtag, mpos : Integer;
begin
   With dtmCadastro.cdsSEGURANCA Do
   Begin
      Close;
      // usuario que esta entrando no sistema
      Params[0].AsString := pUsuario;  
      Open;
   End;
   mpos := 0;
   While mpos <= ComponentCount-1 Do
   Begin
      If Components[mpos] is TMenuItem then
      Begin
         mtag := TMenuItem(Components[mpos]).Tag;
         If mtag > 0 Then
         Begin
            If dtmCadastro.cdsSEGURANCA.Locate("TAG",mtag,[loCaseInsensitive]) Then
            Begin
               TMenuItem(Components[mpos]).Visible := TMenuItem(Components[mpos]).Enabled;
            End
            Else
               TMenuItem(Components[mpos]).Visible := False;
         End;
      End;
      Inc(mpos);
   End;
   dtmCadastro.cdsSEGURANCA.Close;
end;

Listagem 3. Exemplo de rotina para acessos num form de cadastro

// neste exemplo a variavel usuario contem o codigo do usuario
// bbtInclusao, bbtExcluir, bbtGravar, bbtCancelar são botoes
// dtsCADASTRO é um DataSource 
Procedure BloqueioBotao(mtag : Integer);
begin
   With dtmCadastro.cdsSEGURANCA Do
   Begin
      Close;
      Params[0].AsString := Usuario;
      Open;
      Locate("TAG",mTag,[loCaseInsensitive]);
      If bbtINCLUIR.Visible Then
         bbtINCLUIR.Visible := (FieldByName("INCLUSAO").AsInteger = 1);
      If bbtEXCLUIR.Visible Then
         bbtEXCLUIR.Visible := (FieldByName("EXCLUSAO").AsInteger = 1);

      // desabilito o modo edicao pelo DataSource	
      dtsCADASTRO.AutoEdit := (FieldByName("ALTERACAO").AsInteger = 1);

      // caso nao esteja habilitado nenhum dos botoes e nem o mode de
      // alteracao, desabilito os botoes de gravar e cancelar
      If (FieldByName("INCLUSAO").AsInteger = 0) And
         (FieldByName("ALTERACAO").AsInteger = 0) And
         (FieldByName("EXCLUSAO").AsInteger = 0) Then
      Begin
         bbtGRAVAR.Visible   := False;
         bbtCANCELAR.Visible := False;
      End;
   End;
End;

Infelizmente este componente tem uma limitação, por ele estar utilizando o HelpContext para parâmetros não poderemos vincular Help ao menu.

Conclusões

Vimos neste artigo a construção de um componente na qual pudéssemos criar um controle de acessos simples e rápido com os sistemas que já temos prontos.

Depois é só implementar como será feito internamente nos sistemas as verificações pelos dados gravados na tabela segurança.

Até ao próximo, amigos.

Download do Componente: acesso.zip.

Link

Site do autor: www.deluca.eti.br

George De Luca

George De Luca - Analista de sistemas com experiência desde 1994 e pós-graduado (MBA) em gestão empresaria. Experiência em diversos mercados como comércio, indústria, varejo e governamental. Atualmente é CIO da Intersystem em Portugal.