Разграничение видимости для отчетов пользователя
Добавлено: 18 фев 2014, 19:16
Небольшая, но очень приятная доработка для тех, кто разрабатывает отчеты через UserReport (Отчеты пользователя).
Вторжение в стандартный функционал минимально.
Поддерживается наделение правами пользователей и групп пользователей.
Состав:
Интерфейс GetUserReport - строит дерево отчетов поддерживающих разграничение видимости.
Интерфейс UserReportProtect - собственно сам интерфейс раздачи прав.
Интерфейс ViewUserReportAccess - информация о группах/пользователях имеющих доступ к отчету.
Докомпиляция интерфейса UserReport - добавляет вызов ViewUserReportAccess по Ctrl+P;
Ну и встраивание самого интерфейса разграничения в отчеты пользователя.
Для хранения информации о доступе используется стандартная таблица KatLink.
Собираем как есть:
Остается только у потомка UserReport, для которого требуется включить разграничение видимости видоизменить функцию VisibleInModule следующим образом:
Вторжение в стандартный функционал минимально.
Поддерживается наделение правами пользователей и групп пользователей.
Состав:
Интерфейс 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.
Код: Выделить всё
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;