Дискретный доступ в отчётах и примеры скриптов#
В документе описана интеграция дискретного доступа с печатными формами: как настроить ограничение в отчёте, какие макросы использовать для Jasper/Word/Excel. Также содержит готовые примеры скриптов фильтрации и проверки по кешу для типовых сценариев.
Материал отвечает на вопросы: как ограничить данные в печатной форме по правам пользователя, как сформировать макрос для запроса, какие шаблоны скриптов использовать для примитивных и составных правил.
Для печатных форм и отчётов дискретный доступ применяется через макросы, которые при построении формы заменяются на выражения фильтрации. Если запрос печатной формы обращается к администрируемой таблице, но не содержит необходимых макросов, система блокирует печать и сообщает о необходимости добавить макросы.
Настройка в отчётах#
Для проверки доступа к объектам внутри запросов печатных форм используйте макросы. При построении формы макросы заменяются на скрипты фильтрации на основе:
настроек администрируемого объекта;
параметров, настроенных в ролях пользователя.
Важно
Если в запросе печатной формы не прописаны необходимые макросы, но есть обращение к администрируемой таблице, система не позволит распечатать документ и выведет ошибку с просьбой добавить макросы.
Настройка дискретного доступа в отчётах
В отчёте
Rpt_Reportна закладке «Настройка контроля доступа к данным печатной формы» выберите администрируемый объект.Укажите объектную привилегию (по умолчанию проверяется
viewReport#).В поле «Список алиасов» укажите алиасы таблиц через
;(по умолчанию —t).
Система автоматически сгенерирует макросы для вставки в запрос.
Макросы для Jasper-отчётов#
Макрос передаётся как параметр с именем:
DM_(<системное_имя_административного_объекта>)_(<алиас_таблицы>)
В запросе используйте параметр со знаком !:
<parameter name="DM_(BTK_USER)_(T)" class="java.lang.String">
<defaultValueExpression><![CDATA["1=2"]]></defaultValueExpression>
</parameter>
<queryString>
<![CDATA[select sHeadLine_dz
from btk_user t
where $P!{DM_(BTK_USER)_(T)}]]>
</queryString>
Совет
Для тестирования можно указать значение по умолчанию 1=1, но перед загрузкой в приложение удалите его, чтобы избежать случайного предоставления полного доступа.
Макросы для отчётов «Текстовый», «Excel», «Word»#
Макрос формируется по шаблону:
&DM_(<системное_имя_административного_объекта>)_(<алиас_таблицы>)
Пример для печатной формы типа «Word»:
[#&Order= select sHeadLine_dz, sMnemoCode_dz from BTK_USER t
where &DM_(Btk_User) #]
Примеры скриптов#
Примитивное правило по атрибуту класса#
Правило значимое, тип данных — строка. Фильтрация по LIKE атрибута sCode.
Скрипт фильтрации объектных привилегий:
select 1
from RplTst_ClassTree tt
join (
select cast(json_array_elements_text(cast((¶ms) as json)) as varchar) as sCode
) as codes
on tt.sCode like codes.sCode
where tt.id = (&id)
Скрипт проверки строк по объектному кешу:
for (p: params) {
if (row.sCode != null && p != null) {
if (like(row.sCode, p)) {
return true;
}
}
}
Примитивное правило по атрибуту коллекции#
Правило ссылочное на Btk_Group. Фильтрация по прямому вхождению объекта в группу (Btk_ObjectGroup).
Скрипт фильтрации объектных привилегий:
select 1
from Rpltst_TestGroup tt
join Btk_ObjectGroup og
on tt.gid = og.gidSrcObject
join (
select cast(json_array_elements_text(cast((¶ms) as json)) as int8) as id
) as params
on og.idGroup = params.id
where tt.id = (&id)
Скрипт проверки строк по объектному кешу:
for (p: params) {
var rops = toJRops(Btk_ObjectGroupApi.byParent(row.data())).asList();
if (p != null) {
for (r: rops) {
if (r.idGroup == p) {
return true;
}
}
}
}
Примитивное правило по администрируемому объекту (произвольная выборка)#
Правило значимое, тип данных — строка. Регистронезависимая фильтрация по LIKE поля sClass.
Скрипт фильтрации объектных привилегий:
select 1
from json_array_elements_text(cast((¶ms) as json)) as p
where upper((&sClass)) like upper(p)
Скрипт проверки строк по объектному кешу:
for (p: params) {
if (row.sClass != null && p != null) {
if (like(row.sClass.toUpperCase(), p.toUpperCase())) {
return true;
}
}
}
Составное правило по трём атрибутам класса#
Параметры:
dDate— значимый, дата;nNumber— значимый, число;sCaption— значимый, строка.
Фильтрация: дата меньше указанной, число равно указанному, наименование совпадает по LIKE (регистронезависимо).
Скрипт фильтрации объектных привилегий:
select 1
from RplTst_AllDbTypes tt
where tt.id = (&id)
and exists (
select 1
from (
select v -> 'dDate' as dDate
,v -> 'nNumber' as nNumber
,v -> 'sCaption' as sCaption
from json_array_elements(cast((¶ms) as json)) as v
) p
where exists (
select 1
from json_array_elements_text(p.dDate) pp
where tt.dDate <= to_timestamp(pp, 'DD.MM.YYYY HH24:MI:SS')
)
and exists (
select 1
from json_array_elements_text(p.nNumber) pp
where tt.nNumber = cast(pp as numeric)
)
and exists (
select 1
from json_array_elements_text(p.sCaption) pp
where upper(tt.sCaption) like upper(pp)
)
)
Скрипт проверки строк по объектному кешу:
for (p: params) {
var jObj = toJObject(p);
var res = true;
// проверка даты
if (res) {
res = false;
var aValues = jObj.childJArray("dDate");
var i = 0;
while(i < aValues.size() && !res) {
var value = aValues.getDate(i);
if (row.dDate <= value) {
res = true;
}
i = i + 1;
}
}
// проверка числа
if (res) {
res = false;
var aValues = jObj.childJArray("nNumber");
var i = 0;
while(i < aValues.size() && !res) {
var value = aValues.getNumber(i);
if (row.nNumber == value) {
res = true;
}
i = i + 1;
}
}
// проверка наименования
if (res) {
res = false;
var aValues = jObj.childJArray("sCaption");
var i = 0;
while(i < aValues.size() && !res) {
var value = aValues.getString(i);
if (row.sCaption != null && value != null) {
if (like(row.sCaption.toUpperCase(), value.toUpperCase())) {
res = true;
}
}
i = i + 1;
}
}
if (res) {
return true;
}
}
Составное правило по атрибуту класса и коллекции#
Параметры:
sCaption— значимый, строка;idGroup— ссылочный наBtk_Group.
Фильтрация: наименование совпадает по LIKE (регистронезависимо) и есть прямое вхождение в группу (Btk_ObjectGroup).
Скрипт фильтрации объектных привилегий:
select 1
from RplTst_TestGroup tt
where tt.id = (&id)
and exists (
select 1
from (
select v -> 'sCaption' as sCaption
,v -> 'idGroup' as idGroup
from json_array_elements(cast((¶ms) as json)) as v
) p
where exists (
select 1
from json_array_elements_text(p.sCaption) pp
where upper(tt.sCaption) like upper(pp)
)
and exists (
select 1
from Btk_ObjectGroup og
join json_array_elements_text(p.idGroup) pp
on og.idGroup = cast(pp as int8)
where og.gidSrcObject = tt.gid
)
)
Скрипт проверки строк по объектному кешу:
for (p: params) {
var jObj = toJObject(p);
var res = true;
// проверка наименования
if (res) {
res = false;
var aValues = jObj.childJArray("sCaption");
var i = 0;
while(i < aValues.size() && !res) {
var value = aValues.getString(i);
if (row.sCaption != null && value != null) {
if (like(row.sCaption.toUpperCase(), value.toUpperCase())) {
res = true;
}
}
i = i + 1;
}
}
// проверка группы
if (res) {
res = false;
var rops = toJRops(Btk_ObjectGroupApi.byParent(row.data())).asList();
var aValues = jObj.childJArray("idGroup");
var i = 0;
while(i < aValues.size() && !res) {
var value = aValues.getLong(i);
for (r: rops) {
if (r.idGroup == value) {
res = true;
}
}
i = i + 1;
}
}
if (res) {
return true;
}
}
Составное правило по двум атрибутам (произвольная выборка)#
Параметры:
sClass— значимый, строка;idRefClass— ссылочный наBtk_Class.
Фильтрация: sClass совпадает по LIKE (регистронезависимо), idRefClass совпадает точно.
Скрипт фильтрации объектных привилегий:
select 1
from (
select v -> 'sClass' as sClass
,v -> 'idRefClass' as idRefClass
from json_array_elements(cast((¶ms) as json)) as v
) p
where exists (
select 1
from json_array_elements_text(p.sClass) pp
where upper((&sClass)) like upper(pp)
)
and exists (
select 1
from json_array_elements_text(p.idRefClass) pp
where (&idRefClass) = cast(pp as int8)
)
Скрипт проверки строк по объектному кешу:
for (p: params) {
var jObj = toJObject(p);
var res = true;
// проверка sClass
if (res) {
res = false;
var aValues = jObj.childJArray("sClass");
var i = 0;
while(i < aValues.size() && !res) {
var value = aValues.getString(i);
if (row.sClass != null && value != null) {
if (like(row.sClass.toUpperCase(), value.toUpperCase())) {
res = true;
}
}
i = i + 1;
}
}
// проверка idRefClass
if (res) {
res = false;
var aValues = jObj.childJArray("idRefClass");
var i = 0;
while(i < aValues.size() && !res) {
var value = aValues.getLong(i);
if (row.idRefClass == value) {
res = true;
}
i = i + 1;
}
}
if (res) {
return true;
}
}