Разграничение видимости для отчетов пользователя

База знаний

Модераторы: m0p3e, edward_K, Модераторы

Ответить
m0p3e
Местный житель
Сообщения: 1386
Зарегистрирован: 29 мар 2005, 17:49
Откуда: Москва

Разграничение видимости для отчетов пользователя

Сообщение m0p3e »

Небольшая, но очень приятная доработка для тех, кто разрабатывает отчеты через UserReport (Отчеты пользователя).
Вторжение в стандартный функционал минимально.
Поддерживается наделение правами пользователей и групп пользователей.
Состав:
Интерфейс GetUserReport - строит дерево отчетов поддерживающих разграничение видимости.
Интерфейс UserReportProtect - собственно сам интерфейс раздачи прав.
Интерфейс ViewUserReportAccess - информация о группах/пользователях имеющих доступ к отчету.
Докомпиляция интерфейса UserReport - добавляет вызов ViewUserReportAccess по Ctrl+P;
Ну и встраивание самого интерфейса разграничения в отчеты пользователя.

Для хранения информации о доступе используется стандартная таблица KatLink.

Собираем как есть:

Код: Выделить всё

#include UserReport.vih

#ifdef ComponentVersion
#component "F_UserReport"
#end

#doc
 Выбор доступных отчетов пользователя
#end

Const
  LinkCode = 31910;
End;

Interface GetUserReport 'Отчеты пользователя' EscClose, Cyan;
Show at (,,70,);

const
  IfcPrefix  = 'UserReport_';
  ObjIfcName = 'F_UserReport::IUserReport';
end;

Table Struct ReportList
(
 nRec          : comp
,ReportName    : string[100]
,InterfaceName : string[50]
,cParent       : comp
,Priority      : integer
,isLeaf        : boolean
)
with index
(
 tiReportList01 = NRec (Unique, Surrogate)
,tiReportList02 = cParent + ReportName
,tiReportList03 = cParent + Priority + ReportName
,tiReportList04 = InterfaceName
);

create view vUserRepor
var
  CurGroup  : comp;
  CurReport : string;
as select
  *
from
   ReportList ( tiReportList03 )
  ,ReportList ViewReportList
  ,ReportList ViewReportGroup
Where ((
        CurGroup == ReportList.cParent
      ))
;

Parameters CurReport;

var
  UserReport : IUserReport;


function AddGroup ( GroupName: string; cParent : comp ) : comp;
{
 if GetFirst ReportList where (( cParent   == ReportList.cParent
                             and GroupName == ReportList.ReportName
                              )) <> tsOk
  {
   Insert ReportList set
    ReportList.ReportName := GroupName,
    ReportList.cParent    := cParent,
    ReportList.Priority   := -1000         // Всегда выводим сначала группы, а потом отчеты
  }
 Result := ReportList.nRec;
}; // AddGroup


function AddReport ( ReportName, InterfaceName : string; Priority : integer; cParent : comp) : comp;
{
 var p : byte; p := InStr ( '::', InterfaceName );
 If p > 0
   InterfaceName := SubStr ( InterfaceName, p + 2, Length ( InterfaceName ) - p + 1 )

 insert ReportList set
  ReportList.ReportName    := ReportName,
  ReportList.InterfaceName := InterfaceName,
  ReportList.cParent       := cParent,
  ReportList.Priority      := Priority,
  ReportList.isLeaf        := true;
 Result := ReportList.NRec;
}; // AddReport

function MakeTreeMenu: boolean;
var
  ImpCount, i, j : integer;
  IsVisible      : boolean;
  iName, gName   : string;
  cParent        : comp;
{
 Result := false;
 if ( not LoadImplementationList ( ObjIfcName, IfcPrefix ))
  {
   Message ( 'Не удалось загрузить список отчетов', Error + OkButton );
   Exit;
  }
 ImpCount := GetImplementationCount;
 StartNewVisual ( vtIndicatorVisual, vfTimer + vfBreak + vfConfirm, 'Загрузка списка отчетов', ImpCount );
 _try
  {
   for ( i := 0; i < ImpCount; i++ )
    {
     if GetVipRef ( UserReport, GetImplementationName ( i ) )
      {
       iName := GetImplementationName ( i );
       If UserReport.VisibleInModule ( 0 ) = 'REP_PROTECT'
        {
         // Добавляем группы в список отчетов
         cParent := 0;
         j := 1;
         While True
          Do {
              gName := UserReport.GetGroupName ( j );
              If ( gName = '' )
                {
                 Break;
                }
               else
                {
                 cParent := AddGroup ( gName, cParent );
                 j++;
                }
             }
         // Добавляем отчет
         AddReport ( UserReport.GetReportName, iName, UserReport.GetPriority, cParent );
         FreeVipInterface ( UserReport );
        };
      };
     NextVisual;
    };
  };
  _except on ExUserBreak : {}
  _finally
    StopVisual ( '', 0 );
  UnloadImplementationList;
  If RecordsInTable ( #ReportList ) = 0
   {
    //Message ( 'Нет отчетов с разграничением доступа!', OkButton );
    Exit;
   }
  CurGroup := 0;
  GetFirst ReportList Where (( CurGroup == cParent ));
  Result := true;
end; // MakeTree


Tree trZReports;
Table ReportList;
Fields
  ReportList.ReportName 'Наименование отчета' ('Наименование отчета',, sci1EnEscTree): Protect;
end;


TableEvent Table ReportList;

  cmTreeTop  : CurGroup := 0;
  cmTreeUp   : CurGroup := ReportList.cParent;
  cmTreeDown : CurGroup := ReportList.NRec;

  cmTreeNodeType :
   {
    If ReportList.isLeaf
     TreeSetNodeType ( trZReports, 2 );
   };
  cmTreeNeedOwner :
   {
    If ReportList.cParent <> 0
      TreeJumpToRecord ( trZReports, ReportList.cParent );
     else
      TreeJumpToRecord ( trZReports, 0 );
   }
end;

Public Function GetReportName ( iName : string ) : string;
{
 Result := '<!> Ошибка <!>';
 If RecordsInTable ( #ReportList ) = 0
   MakeTreeMenu;
 If GetFirst ViewReportList Where (( iName == ViewReportList.InterfaceName )) = tsOk
   Result := ViewReportList.ReportName;
}; //Function GetReportName

Public Function GetGroupName ( iName : string ) : string;
{
 Result := '';
 If RecordsInTable ( #ReportList ) = 0
   MakeTreeMenu;
 If GetFirst ViewReportList Where (( iName == ViewReportList.InterfaceName )) = tsOk
  If GetFirst ViewReportGroup Where (( ViewReportList.cParent == ViewReportGroup.nrec )) = tsOk
   Result := ViewReportGroup.ReportName;
}; //Function GetReportName


HandleEvent
 cmInit :
  {
   Delete All ViewReportList;
   MakeTreeMenu;
  }; //cmInit
 cmDefault :
  {
   If ReportList.IsLeaf
    {
     CurReport := ReportList.InterfaceName;
     CloseInterface ( cmDefault );
    };
  };
end;

end.



///////////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
//                                                                                                  \\
///////////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
#doc

#end

Interface UserReportProtect 'Разграничение доступа к отчетам пользователя' EscClose, Cyan;
Show At ( ,,, );
Create View
Var iReports : GetUserReport;
    Prefix : string;

As Select *
From Groups
    ,x$users
    ,KatLink

    ,GroupUsers
    ,KatLink ViewKatLink

Where ((
        Prefix           == KatLink.OwnName
    and LinkCode         == KatLink.CodeTable
      )) and ( x$users.xu$flag and 8 ) = 0
 bounds ByGroup = Groups.atl_nrec  == KatLink.cRec ( noIndex )
 bounds ByUser  = x$users.atl_nrec == KatLink.cRec ( noIndex )
;

TabbedSheet Top ModeTab;
Show At ( ,,40, );

Browse brGroups 'Группы пользователей' ( ,,sci1Esc );
Table Groups;
 Fields
  { FONT = { BOLD = isValid ( tnKatLink ) } };
  Groups.name  'Группа пользователей'   : Protect;
end; //tree

Browse brUsers 'Пользователи' ( ,,sci1Esc );
Table x$users;
 Fields
  { FONT = { BOLD = isValid ( tnKatLink ) } };
  x$users.xu$LoginName  'Учетная запись'   : [ 15 ], Protect;
  x$users.xu$FullName   'Наименование'     : [ 25 ], Protect;
end; //tree

End; //Tabbed

Browse brLink ( ,,sci178Esc );
Show At ( 41,,, );
Table KatLink;
 Fields
  iReports.GetReportName ( KatLink.name )
               'Наименование отчета'   : [ 30 ], Protect;
  iReports.GetGroupName ( KatLink.name )
               'Группа'                : [ 30 ], Protect;
  KatLink.name 'Интерфейс'             : [ 20 ], Protect;
end;

TableEvent Table KatLink;
 cmSetDefault : {
                 ClearBuffer ( #KatLink );
                  KatLink.OwnName   := Prefix;
                  KatLink.CodeTable := LinkCode;
                  Case Prefix Of
                   'REPPROTECT_GROUP' : KatLink.cRec := Groups.atl_nrec;
                   'REPPROTECT_USER'  : KatLink.cRec := x$users.atl_nrec;
                  End;
                  If RunInterface ( GetUserReport, KatLink.name  ) <> cmDefault
                    Abort;
                 SetModified ( true );
                };
 cmInsertRecord : Insert Current KatLink;
 cmUpdateRecord : Update Current KatLink;
 cmDeleteRecord : If Message ( 'Удалить?', YesNo ) = cmYes
                    Delete Current KatLink;
End; //TableEvent KatLink

Public Function GetProtectStatus : string;
{
 var iGroups, iUsers : Integer;
 iGroups := 0;
 iUsers := 0;
 _loop ViewKatLink Where (( 'REPPROTECT_GROUP' == ViewKatLink.OwnName
                        and LinkCode           == ViewKatLink.CodeTable
                         ))
  {
   Inc ( iGroups );
  };
 _loop ViewKatLink Where (( 'REPPROTECT_USER'  == ViewKatLink.OwnName
                        and LinkCode           == ViewKatLink.CodeTable
                         ))
  {
   Inc ( iUsers );
  };
 Result := 'Записей по группам: ' + iGroups + ', по пользователям: ' + iUsers;
}; //Function ProtectStatus

Public Function CheckVisible ( iName : string ) : boolean;
{
 Result := Pr_CurUserAdmin;
 If not Result
  Result := ( GetFirst FastFirstRow ViewKatLink Where (( 'REPPROTECT_USER' == ViewKatLink.OwnName
                                                     and LinkCode          == ViewKatLink.CodeTable
                                                     and iName             == ViewKatLink.name
                                                     and UserId            == ViewKatLink.cRec ( noIndex )
                                                       )) ) = tsOk;
 If not Result
  _loop GroupUsers Where (( UserId == GroupUsers.UserCode ))
   {
    If GetFirst FastFirstRow ViewKatLink Where (( 'REPPROTECT_GROUP'   == ViewKatLink.OwnName
                                              and LinkCode             == ViewKatLink.CodeTable
                                              and iName                == ViewKatLink.name
                                              and GroupUsers.GroupCode == ViewKatLink.cRec ( noIndex )
                                               )) = tsOk
      Result := true;
   }; //loop GroupUsers
}; //Function CheckVisible

HandleEvent
 cmInit :
  {
   SetFormat ( brGroups );
   Prefix := 'REPPROTECT_GROUP';
   AddBounds ( tbByGroup );
   RescanPanel ( #KatLink );
  }; //cmInit
 cmChangeTabbedSheetFormat :
  {
   Case Target Of
    brGroups :
     {
      Prefix := 'REPPROTECT_GROUP';
      SubBounds ( tbByUser  );
      AddBounds ( tbByGroup );
     };
    brUsers  :
     {
      Prefix := 'REPPROTECT_USER';
      SubBounds ( tbByGroup );
      AddBounds ( tbByUser  );
     };
   End;
   RescanPanel ( #KatLink );
  }
End;


END.


///////////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
//                         Отчет по доступности отчета для пользователей                            \\
///////////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
#doc

#end

Interface ViewUserReportAccess 'Доступность отчета' DoAccept, EscClose, Cyan;
Show At ( ,,, );

Table struct pRep
(
 Mode      : integer
,UserId    : string
,UserName  : string
,Remark    : string
,aType     : word
)
with index
(
 pRep0 = Mode + UserId
,pRep1 = UserId
)
; //TableStruct pRep

Create View
Var iReport : string;

As Select *
From x$users
    ,groups
    ,groupusers
    ,KatLink

    ,pRep
    ,pRep pRep2

Where ((
          0 <<= pRep.Mode
     and  0 >>= pRep2.Mode
      ))
;

Window w1;

TabbedSheet Top AccessType;
 Browse b1 'По пользователям';
  Table pRep;
   Fields
    pRep.UserId   'Пользователь' : [ 20 ], Protect;
    pRep.UserName 'Наименование' : [ 20 ], Protect;
    pRep.Remark   'Примечание'   : [ 40 ], Protect;
    If ( pRep.aType = 1, 'Администратор'
       , If ( pRep.aType = 2, 'Персональный'
            , If ( pRep.aType = 3, 'Группа', 'Ошибка' ) ) )
                  'Тип'          : [ 20 ], Protect, { FONT = { Color = If ( pRep.aType = 1, ColorSysRed
                                                                          , If ( pRep.aType = 2, ColorSysGreen
                                                                               , If ( pRep.aType = 3, ColorSysBlue, 0 ) ) ) } };

  End;
 Browse b2 'По правам';
  Table pRep2;
   Fields
    pRep2.UserId   'Наименование' : [ 20 ], Protect;
    pRep2.UserName 'Описание'     : [ 20 ], Protect;
    pRep2.Remark   'Примечание'   : [ 40 ], Protect;
    If ( pRep2.aType = 1, 'Администратор'
       , If ( pRep2.aType = 2, 'Персональный'
            , If ( pRep2.aType = 3, 'Группа', 'Ошибка' ) ) )
                  'Тип'          : [ 20 ], Protect, { FONT = { Color = If ( pRep2.aType = 1, ColorSysRed
                                                                          , If ( pRep2.aType = 2, ColorSysGreen
                                                                               , If ( pRep2.aType = 3, ColorSysBlue, 0 ) ) ) } };
  End;
End; //Tabbed
End; //Window

Function CheckInterfaceProtection : boolean;
{
 Result := false;
 if ( not LoadImplementationList ( 'F_UserReport::IUserReport', 'UserReport_' ))
  {
   Exit;
  }

 var UserReport : IUserReport;
 var i : LongInt;

 For ( i := 0; i < GetImplementationCount; i++ )
  {
   If GetVipRef ( UserReport, GetImplementationName ( i ) )
     {
      If UserReport.VisibleInModule ( 0 ) = 'REP_PROTECT'
       {
        Result := true;
        SetWindowTitle ( w1, 'Доступ пользователей к отчету: "' + UserReport.GetReportName + '"' );
       }
      FreeVipInterface ( UserReport );
     };
  };

 UnloadImplementationList;
}; //Function CheckInterfaceProtection

Procedure MakeAccessTable;
{
 Delete All pRep;

 //Покажем админов
 _loop x$users
  {
   If ( x$users.xu$flag and 8 ) > 0
     continue;

   If x$users.xu$type <> 1
     continue;

   If GetFirst pRep Where (( x$users.xu$loginname == pRep.UserId )) <> tsOk
    {
      pRep.UserId   := x$users.xu$loginname;
      pRep.UserName := x$users.xu$fullname;
      pRep.Remark   := sGetTuneEx ( 'User.Remark', UserOfficeFilial ( x$users.atl_nrec ), x$users.atl_nrec );
      pRep.aType    := 1;
     Insert Current pRep;
    };
  }; //loop x$users

 //Персональный доступ
 _loop x$users
  {
   If ( x$users.xu$flag and 8 ) > 0
     continue;

   If GetFirst KatLink Where (( 'REPPROTECT_USER' == KatLink.OwnName
                            and LinkCode          == KatLink.CodeTable
                            and iReport           == KatLink.Name
                            and x$users.atl_nrec  == KatLink.cRec ( noIndex )
                             )) <> tsOk
     continue;

   If GetFirst pRep Where (( x$users.xu$loginname == pRep.UserId )) <> tsOk
    {
      pRep.UserId   := x$users.xu$loginname;
      pRep.UserName := x$users.xu$fullname;
      pRep.Remark   := sGetTuneEx ( 'User.Remark', UserOfficeFilial ( x$users.atl_nrec ), x$users.atl_nrec );
      pRep.aType    := 2;
     Insert Current pRep;
    }
  }; //loop x$users

 //По группам
 _loop KatLink Where (( 'REPPROTECT_GROUP' == KatLink.OwnName
                    and LinkCode           == KatLink.CodeTable
                    and iReport            == KatLink.Name
                     ))
  {
   If GetFirst groups Where (( KatLink.cRec == Groups.Atl_nrec )) = tsOk
    {
      pRep.Mode     := -1;
      pRep.UserId   := groups.Name;
      pRep.UserName := groups.Description;
      pRep.Remark   := '';
      pRep.aType    := 3;
     Insert Current pRep;
    };

   _loop GroupUsers Where (( KatLink.cRec == GroupUsers.GroupCode ))
    {
     If GetFirst x$users Where (( GroupUsers.UserCode == x$users.atl_nrec )) <> tsOk
       continue;

     If ( x$users.xu$flag and 8 ) > 0
       continue;

     If GetFirst pRep Where (( x$users.xu$loginname == pRep.UserId )) <> tsOk
      {
        pRep.Mode     := 1;
        pRep.UserId   := x$users.xu$loginname;
        pRep.UserName := x$users.xu$fullname;
        pRep.Remark   := sGetTuneEx ( 'User.Remark', UserOfficeFilial ( x$users.atl_nrec ), x$users.atl_nrec );
        pRep.aType    := 3;
       Insert Current pRep;
      }; //loop GroupUsers
    };
  };
}; //Procedure MakeAccessTable

Public Procedure CheckAccess ( iName : string );
{
 iReport := iName;
 If CheckInterfaceProtection
   {
    MakeAccessTable;
    RunWindowModal ( w1 );
   }
  else
   Message ( 'Отчет не поддерживает разграничение доступа!', Information );
}; //Function CheckAccess

END.


///////////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
//                          Ctrl+P просмотр информации о доступе к отчету                           \\
///////////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

Alter Interface UserReport;

HandleEvent
 cmPrintDoc :
   {
    If ReportList.IsLeaf
     If Pr_CurUserAdmin
      {
       var iAccess : ViewUserReportAccess;
       iAccess.CheckAccess ( ReportList.InterfaceName );
      };
   };

End;
End.


///////////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
//                   Добавление интерфейса разграничения в меню отчетов пользователя                \\
///////////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

#include UserReport.vih

VipInterface UserReport_UserReportProtect
  Implements F_UserReport::IUserReport
  Licensed(Free)
;

interface UserReport_UserReportProtect;

create view
  var
    Dummy: Byte;
;

procedure Run;
begin
  RunInterfaceNoModal ( 'F_USERREPORT::UserReportProtect' );
end;

function GetReportName: String;
begin
  GetReportName := 'Разграничение доступа к отчетам пользователя';
end;

function GetGroupName ( Level: Word ): String;
begin
  GetGroupName := '';
end;

function GetPriority: Integer;
begin
  GetPriority := 0;
end;

function VisibleInModule ( Ind: Byte ): String;
var iRepProtect : UserReportProtect;
begin
  Result := '';
   case Ind of
    1: If Pr_CurUserAdmin
         Result := '*'
   end;
end;

end.
Остается только у потомка UserReport, для которого требуется включить разграничение видимости видоизменить функцию VisibleInModule следующим образом:

Код: Выделить всё

function VisibleInModule ( Ind: Byte ): String;
var iRepProtect : UserReportProtect;
begin
  Result := '';
   case Ind of
    1: If iRepProtect.CheckVisible ( CurrentInterfaceName )
         Result := 'StaffMainMenu'; //видимость в кадрах

    0: Result := 'REP_PROTECT'; //маркер определяющий, что отчет поддерживает разграничение.
   end;
end;
Zver
Местный житель
Сообщения: 204
Зарегистрирован: 13 ноя 2012, 12:47
Откуда: СПб
Контактная информация:

Re: Разграничение видимости для отчетов пользователя

Сообщение Zver »

Спасибо, отличная вещь.
Программист-самоучка
Ответить