Ver Mensaje Individual
  #5  
Antiguo 08-08-2007
Avatar de ArdiIIa
[ArdiIIa] ArdiIIa is offline
Miembro Premium
 
Registrado: nov 2003
Ubicación: Valencia city
Posts: 1.481
Reputación: 22
ArdiIIa Va por buen camino
Hola martinzcr

Yo tengo implementado un sistema consistente en lo siguiente:

Una tabla:
Código:
NOMBRE VAR_CHAR_15 NOT NULL ---->CODIFICADO
PASSWD VAR_CHAR_15 NOT NULL ---->CODIFICADO
PRIVILEGIOS BLOB
Los dos primeros campos, están codificados para que ningún listo toque nada de nada. El tercero no, pero se podría también....
El campo privilegios, viene a ser un INI con todas las opciones del programa, mas o menos así:

Código:
Cuentas Bancarias=S
Máquinas=S
Materiales=S
OT Fijas=S
Libreta de Contactos=S
Buscar Contactos=S
Pedidos de Clientes=S
Ofertas a Clientes=S
OT=S
Partes Diarios=S
Horas Trabajo Operarios=S
Pedidos a Proveedores=S
Petición de Presupuesto=S
Albaranes=S
Facturas=S
Notas de Entrega=S
Configuración=S
Ejercicios=N
Gestor de Correo=S
Usuarios=S
Donde cada elemento, se corresponde con un item del menú del programa. En mi caso, utilizo ActionManager, por lo que sería mas correcto decir, que cada elemento se corresponde con un TAction.


En el Form donde se encuentra el TreeView, el procedimiento que asisna los elementos, viene a ser algo así....



Código Delphi [-]
// ESTE PROCEDIMIENTO INICIALIZA el treevie de LOS OBJETOS DE SEGURIDAD
// PARA TENER PRIVILEGIOS DE ACCESO A LAS DIFERENTES SECCIONES DEL PROGRAMA
Procedure TFormUsuarios.MakeSecurity( TreeView : TTreeView);

Function Delsigno(Item : String) : String;
Begin
Delete( Item , Pos('&' , Item) ,1) ;
Result := Item;
End;

function FindAction (Caption : string) : TAction;
var
  i : Integer;
begin
  Result := nil;
  with FormMain.ActionManager1 do
   begin
    for I := 0 to ActionCount - 1 do    { Iterate }
     begin
      if TAction(Actions[i]).Caption = Caption then
      begin
        Result := TAction(Actions[i]);
        Break;
      end;
    end;    { for }
  end;  { with }
end;


Var
TreeNode, SubTreeNode : TTreeNode;
I,X : Integer;
cTemp : String;
Action : TAction;
Begin

LockWindowUpdate(Treeview.Handle);
TreeView.Items.Clear;

For I := 0 To FormMain.ActionManager1.ActionBars.ActionBars[0].Items.Count -4 DO

Begin
cTemp := DelSigno(FormMain.ActionManager1.ActionBars.ActionBars[0].Items[i].Caption);
TreeNode := TreeView.Items.Add(nil,cTemp);
TreeNode.ImageIndex := -1;
TreeNode.SelectedIndex := -1;

    For X := 0 to FormMain.ActionManager1.ActionBars.ActionBars[0].Items[i].Items.Count -1 DO
    Begin
    cTemp := DelSigno(FormMain.ActionManager1.ActionBars.ActionBars[0].Items[i].Items[x].Caption);
    if cTemp = '-' then continue;
    Action := FindAction(cTemp);
    if Action <> NIL then
    Begin

    SubTreeNode := TreeView.Items.AddChild(TreeNode,cTemp);
    SubTreeNode.ImageIndex := Action.ImageIndex;
    SubTreeNode.SelectedIndex := Action.ImageIndex;

    if Seguridad.FindItem(Action.Caption) <> NIL then
    SubTreeNode.Data := Seguridad.FindItem(Action.Caption)
    End;
    End;

End;
Treeview.FullExpand;
Treeview.Selected := Treeview.Items[0];
LockWindowUpdate(0);
End;

Dos procedimientos de carga y grabación de datos, necesarios para la gestión:



Código Delphi [-]

//Graba Los valores a la base de datos
procedure TFormUsuarios.Button1Click(Sender: TObject);
Var
Stream : TMemoryStream;
begin
Stream := NIL;
Try

    Stream:= TMemoryStream.Create;
    Seguridad.SaveToStream(Stream);
    Datamodule1.IBTableUsuarios.Edit;
    TMemoField(Datamodule1.IBTableUsuarios.FieldByName('Privilegios')).LoadFromStream(Stream);
    Datamodule1.IBTableUsuarios.FieldByName('Nombre').AsString := FormMain.Encrypt(Edit1.Text ,55423);
    Datamodule1.IBTableUsuarios.FieldByName('PassWd').AsString := FormMain.Encrypt(Edit2.Text ,55423);
    Datamodule1.IBTableUsuarios.Post;
finally
    Stream.Free
End
end;

//Carga Seguridad con los valores de la base de datos
procedure TFormUsuarios.DataSourceUsuariosDataChange(Sender: TObject;  Field: TField);
Var
Stream : TMemoryStream;
begin
Stream := NIL;
IF Datamodule1.IBTableUsuarios.State IN dsEditModes then exit;
Try
Stream:= TMemoryStream.Create;
TMemoField(Datamodule1.IBTableUsuarios.FieldByName('Privilegios')).SaveToStream(Stream);
Seguridad.LoadFromStream(Stream);
MakeSecurity(TreeView1);
Edit1.Text := FormMain.Decrypt(Datamodule1.IBTableUsuarios.FieldByName('Nombre').AsString,55423);
Edit2.Text := FormMain.Decrypt(Datamodule1.IBTableUsuarios.FieldByName('PassWd').AsString,55423);
Finally
Stream.Free;
End;
end;


Y finalmente, verás que se cita por ahí un objeto llamado seguridad, que no es otra cosa que un objeto derivado de la clase TCollection, que contiene una lista (TStrings) de todos los objetos TAction del programa y que los activa o desactiva en base a las selecciones hechas por el usuario.
El código de seguridad, es este:

Código Delphi [-]
unit Unit_Objetos_Seguridad;

interface
uses Classes,SysUtils,ActnList;


type


TFormSectionItem = class(TCollectionItem)
  public
    Action : TAction;
    Accesible : Boolean;
  end;



  TFormSectionItems = class(TCollection)
  private
    FStream : TStrings;
    function GetItem(Index: Integer): TFormSectionItem;
    procedure SetItem(Index: Integer; Value: TFormSectionItem);
    Procedure Initial;
  protected
    procedure Update(Item: TCollectionItem); override;
  public
    constructor Create;
    destructor Destroy ; override;
    function Add: TFormSectionItem;
    Procedure SaveToStream( Stream : TMemoryStream);
    procedure LoadFromStream( Stream : TMemoryStream);
    Function FindItem(Caption : String) : TFormSectionItem;
    procedure SetActionValues;
    property Items[Index: Integer]: TFormSectionItem read GetItem write SetItem; default;
  end;



(*
TFormSecurityItem = class(TCollectionItem)
  public
    FormName : String;
    Accesible : Boolean;
    Secciones : TFormSectionItems;
  end;


TFormSecurityItems = class(TCollection)
  private
    function GetItem(Index: Integer): TFormSecurityItem;
    procedure SetItem(Index: Integer; Value: TFormSecurityItem);
  protected
    procedure Update(Item: TCollectionItem); override;
  public
    constructor Create;
    function Add: TFormSecurityItem;
    property Items[Index: Integer]: TFormSecurityItem read GetItem write SetItem; default;
  end;

  *)



implementation

uses UnitMain;


//******************//
constructor TFormSectionItems.Create;
begin
  inherited Create(TFormSectionItem);
  FStream := TStringList.Create;
  Initial;
end;


destructor TFormSectionItems.Destroy;
begin
   FStream.Free;
  inherited Destroy;
end;


Function TFormSectionItems.FindItem(Caption : String) : TFormSectionItem;
Var I : Integer;
Begin
Result := NIL;
For I := 0 to Count -1 DO
if Items[i].Action.Caption = Caption then
Begin
Result := Items[i];
Break;
End;

End;



Procedure TFormSectionItems.Initial;

Function Delsigno(Item : String) : String;
Begin
System.Delete( Item , Pos('&' , Item) ,1) ;
Result := Item;
End;

Function FindAction (Caption : string) : TAction;
var
  i : Integer;
begin
  Result := nil;
  with FormMain.ActionManager1 do
   begin
    for I := 0 to ActionCount - 1 do    { Iterate }
     begin
      if TAction(Actions[i]).Caption = Caption then
      begin
        Result := TAction(Actions[i]);
        Break;
      end;
    end;    { for }
  end;  { with }
end;


Var
Item : TFormSectionItem;
I,X : Integer;
cTemp : String;
Action : TAction;
Begin

For I := 0 To FormMain.ActionManager1.ActionBars.ActionBars[0].Items.Count -4 DO
Begin
    For X := 0 to FormMain.ActionManager1.ActionBars.ActionBars[0].Items[i].Items.Count -1 DO
    Begin
    cTemp := DelSigno(FormMain.ActionManager1.ActionBars.ActionBars[0].Items[i].Items[x].Caption);
    if cTemp = '-' then continue;
    Action := FindAction(cTemp);
    if Action <> NIL then
    Begin
    Item := Add;
    Item.Action := Action;
    Item.Accesible := Action.Enabled;
    End;
    End;
End;

End;



procedure TFormSectionItems.SaveToStream( Stream : TMemoryStream);
Var
I : Integer;
cTemp : String;
begin
FStream.Clear;
For I := 0 To Count -1 DO
    Begin
    if Items[i].Accesible then
    cTemp := '=S'
    else
    cTemp := '=N';
    FStream.Add( Items[i].Action.Caption + cTemp)
    End;
   //FStream.Text := FormMain.Encrypt(FStream.Text,761);
   FStream.SaveToStream(Stream);
   Stream.Position := 0;
end;


procedure TFormSectionItems.LoadFromStream(Stream : TMemoryStream);
Var
I,Z : Integer;
begin
Stream.Position := 0;
FStream.LOadFromStream(Stream);
//FStream.Text := FormMain.Decrypt(FStream.Text,761);
For I := 0 To Count -1 DO
    Begin
    Z := FStream.IndexOfName( Items[i].Action.Caption );
    if Z <> -1 then
       Begin
       Items[i].Accesible := (FStream.ValueFromIndex[Z] = 'S');
       //Items[i].Action.Enabled := Items[i].Accesible;
       End;
     End;

End;




procedure TFormSectionItems.SetActionValues;
Var
I : Integer;
begin
For I := 0 To Count -1 DO
    Items[i].Action.Enabled := Items[i].Accesible;
end;




procedure TFormSectionItems.Update(Item: TCollectionItem);
begin
  inherited;
end;

function TFormSectionItems.GetItem(Index: Integer): TFormSectionItem;
begin
  Result := TFormSectionItem(inherited GetItem(Index));
end;

procedure TFormSectionItems.SetItem(Index: Integer; Value: TFormSectionItem);
begin
  inherited SetItem(Index, Value);
end;

function TFormSectionItems.Add: TFormSectionItem;
begin
  Result := TFormSectionItem(inherited Add);
end;


A la hora de ejecutar el programa y establecer la parametrización de cada usuario, sería algo tal como esto...

Código Delphi [-]
    Seguridad := TFormSectionItems.Create;


    TMemoField(Datamodule1.IBTableUsuarios.FieldByName('Privilegios')).SaveToStream(Stream);
    Seguridad.LoadFromStream(Stream);
    // Pone todas las TAction del Menú
    // Conforme a los valores del usuario que hizo login
    Seguridad.SetActionValues;

Verás que la table IBTableUsuarios, ya estaría posionada sobre el usuario en cuestión, por que previamente se habría identificado.... (otra cuestión aparte)



Básicamente, eso es todo. Lo único comentarte que en mi sistema, utilizo un TreeView normal y corriente, por lo que para que comentas y la forma en la que lo planteas:

Cita:
Todas las opciones del árbol deben poderse marcar o desmarcar. En caso de desmarcar un nodo, se tienen que desmarcar los hijos también.
Creo que lo ideal sería que utilizaras un VirtualTreeView, que si te lo permitiría. (es que en aquellas fecha, yo no conocía ese excelente componente...).

Espero que te sirva de orientación.

NOTA: El código está adaptado a un programa específico y no garantizo que su uso tal cual está, vaya a funcionar en cualquier otro programa.

Saludos.
__________________
Un poco de tu generosidad puede salvar la vida a un niño. ASÍ DE SENCILLO

Última edición por ArdiIIa fecha: 08-08-2007 a las 11:36:46.
Responder Con Cita