Дискретный доступ
Contents
Дискретный доступ#
Дискретный доступ позволяет выдавать привилегии в рамках объектов классов или записей в администрируемой выборке.
Настройка привилегии#
Административный объект#
Открыть карточку
Адм. объектаУстановить признак
Дискретный доступПерейти на закладку
Дискретные ограничения доступаСоздать
Дискретное ограничение.
Дискретное ограничение доступа#
Создать новую запись или встать на запись для редактирования
Указать уникальное в рамка адм. объекта имя и наименование
Настроить тип правила
Настроить параметры правила.
На закладке
Скрипт для фильтрации объектных привилегийнаписать sql-запрос, который будет фильтровать списки объектовНа закладке
Скрипт проверки строк по объектному кешунаписать jexl-скрипт, который будет по rop-у объекта или строке выборки возвращать признак, что условие выполнилось для этого объекта.
Тип правила#
Доступны 3 варианта типа правила:
Примитивное
Составное
Без параметров
Примитивное правило#
Состоит из одного параметра.
При анализе прав пользователя со всех его ролей будут собраны значения параметров и собраны в один массив примитивных значений.
Например для числового правила будет собран массив вида: [10, 20, 30]
Составное правило#
Состоит из нескольких параметров.
При анализе прав пользователя используется следующий алгоритм:
Для каждого набора значений, указанных на роли, формируется json-объект вида:
{ <ИД параметра 1>: [<Массив указанных значений>], <ИД параметра 2>: [<Массив указанных значений>], ... <ИД параметра n>: [<Массив указанных значений>] }
Каждая роль может обладать несколькими наборами значений на одно правило. По этому результатом агрегации настроенных значений на роли будет массив, содержащий объекты, указанные в п.1:
[ {json-объект для набора 1}, {json-объект для набора 2}, ... {json-объект для набора n}, ]
При агрегации прав пользователя:
со всех ролей анализируются массивы, описанные в п.2
в json-е заменяются ИД параметров на их имена
каждый элемент массива приводится к строке
собирается результирующий массив, содержащий уникальные строки.
Таким образом исключаются дублирующие настройки на ролях.
Пример агрегации прав пользователя:
[
{
"paramName1": ["a", "b", "c"],
"paramName2": [1, 2, 3]
},
{
"paramName1": ["c", "d", "e"],
"paramName2": [3, 4, 5]
}
]
Правило без параметров#
Не содержит параметров.
При анализе прав пользователя, если хотя на одной роли будет правило без параметров, оно будет проверяться.
Параметры правила#
Позволяют настроить тип данных и ссылочность для значений, которые будут указаны на ролях.
Если правило примитивное, то у него доступен для настройки только один параметр, для составного правила доступны несколько параметров.
Скрипт для фильтрации объектных привилегий#
Используется для фильтрации списков объектов, через наложение макроса универсального фильтра &DefUniFltMacros.
Доступные макросы внутри текста скрипта:
(&<Имя атрибута>)
Будет заменено на указанное имя атрибута. Например,t.id
Для фильтрации доступны все атрибуты дата-сета выборки шапки БО.(¶ms)
Массив строк, в котором будут параметры, собранные со всех ролей пользователя.(&CurrentUserID)
Будет заменено на ИД текущего пользователя.(&CurrentUserName)
Будет заменено на имя текущего пользователя.
Запрос чаще всего представляет из себя exist, в котором джойнится таблица класса, и через массив значений накладываются условия фильтрации.
Скрипт проверки строк по объектному кешу#
Используется для проверки ограничения по объектам, используя объектный кеш.
Представляет из себя jexl-скрипт, который возвращает true, если объект проходит условие, и false - если не проходит.
Доступные переменные:
row\Если адм. объект создан по классу, то в этой переменной будет
ropпроверяемого объекта. Это не исходныйrop, а его оберткаJexlRop, которая позволяет обращаться к полям объекта.Совет
Для получения исходного
ropвоспользуйтесь следующим примером://в переменной jexlRop находится объект класса JexlRop var rop = jexlRop.data()
Если адм. объект создан не по классу, то здесь будет json-представление строки дата-сета выборки.
params
массив значений параметров, собранных со всех ролей пользователя.если правило примитивное - то будет содержать примитивы (строка или число)
если правило составное - то будет содержать строки, каждая из которых - json
Роль#
Открыть карточку роли или выбрать ее в списке;
перейти на закладку
Дискретный доступ;создать новую запись, выбрав адм. объект;
указать значение параметров для ограничений;
сопоставить объектные и элементарные привилегии с нужным значением параметров ограничений, заполнив поле
Ограничение дискретного доступа
Ограничение доступа к объектам класса.#
Выдается через объектные привилегии с системными именами edit# и view#
Совет
Если таких привилегий нет у адм. объекта, то выполните его синхронизацию.
Дискретные ограничения применяются только, если:
это главная выборка адм. объекта (шапка БО);
это не супер-пользователь;
к адм. объекту приминаются настройки администрирования;
адм. объект имеет признак
Дискретный доступ.
Определение объектов для проверки дискретных прав#
При проверке дискретных привилегий строки, в контексте которых требуется проверить наличие прав, определяются методом acRows
Алгоритм работы метода:
Если выборка принадлежит классу (
thisApi() != null), то для всех выделенных записей через поле первичного ключа загружаютсяпровайдеры строк, из них через полеgidRoot_dzопределяются шапки БОЕсли выборка не принадлежит классу (
thisApi() == null), то по всем выделенным строкам собирается json-массив, содержащий на каждую строку json-объект, в котором ключ - имя атрибута, значение - значение атрибута.
Ограничение списков#
Используя значения параметров всех ролей и настроенные «Скрипты для фильтрации объектных привилегий» формируется условие ограничения и накладывается фильтрация через макрос &DefUniFltMacros.
Ограничение открытия карточек#
На открытие карточки используя значения параметров всех ролей выполняется jexl-скрипт, настроенный в Скрипт проверки строк по объектному кешу. Если у пользователя нет прав на объект, то будет выдана ошибка.
Ограничение на редактирование объектов#
На beforeEdit или delete проверяется наличие привилегии edit# (выполняется jexl-скрипт, настроенный в Скрипт проверки строк по объектному кешу). Если у пользователя нет прав на объект, то будет выдана ошибка.
Ограничение на объектные привилегии#
Если для объектной привилегии указано Ограничение дискретного доступа, то такая привилегия может быть проверена только в контексте какого-либо объекта.
Для проверки объектных привилегий используется метод Btk_AdminPkg().hasObjPriv.
Пример:
if (Btk_AdminPkg().hasObjPriv("SomeObjectName", "SomePrivName", Seq(rop))) {
//код, выполняемый при наличии привилегии
}
Если для привилегии, имеющей ограничение, выполнить проверку без передачи объектов, то будет выдана ошибка.
Ограничение на элементарные привилегии#
Для элементарной привилегии может быть указано ограничение дискретного доступа. Если ограничение указано, то при выполнении операции будут проверены права в контексте записей в выборке.
На загрузку выборки или перезагрузку ClassLoader-а происходит подписка на событие выполнения операции.
При выполнении операции проверяются дискретные права на эту элементарную привилегию:
Получение
acRowsДля полученных строк выполняется
jexl-скрипт, настроенный вСкрипт проверки строк по объектному кешуЕсли прав нет, то выдается ошибка.
Примеры скриптов#
Примитивное правило по атрибуту класса#
Правило значимое, тип данных строка. Фильтрация по 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;
}
}
}
Составное правило по 3 атрибутам класса#
Параметры правила:
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;
}
}
Составное правило по 2 атрибутам адм. объекта, созданного не по классу (произвольная выборка)#
Параметры правила:
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;
}
}