Дискретный доступ в отчётах и примеры скриптов#

В документе описана интеграция дискретного доступа с печатными формами: как настроить ограничение в отчёте, какие макросы использовать для Jasper/Word/Excel. Также содержит готовые примеры скриптов фильтрации и проверки по кешу для типовых сценариев.
Материал отвечает на вопросы: как ограничить данные в печатной форме по правам пользователя, как сформировать макрос для запроса, какие шаблоны скриптов использовать для примитивных и составных правил.

Для печатных форм и отчётов дискретный доступ применяется через макросы, которые при построении формы заменяются на выражения фильтрации. Если запрос печатной формы обращается к администрируемой таблице, но не содержит необходимых макросов, система блокирует печать и сообщает о необходимости добавить макросы.

Настройка в отчётах#

Для проверки доступа к объектам внутри запросов печатных форм используйте макросы. При построении формы макросы заменяются на скрипты фильтрации на основе:

  • настроек администрируемого объекта;

  • параметров, настроенных в ролях пользователя.

Важно

Если в запросе печатной формы не прописаны необходимые макросы, но есть обращение к администрируемой таблице, система не позволит распечатать документ и выведет ошибку с просьбой добавить макросы.

Настройка дискретного доступа в отчётах

  1. В отчёте Rpt_Report на закладке «Настройка контроля доступа к данным печатной формы» выберите администрируемый объект.

  2. Укажите объектную привилегию (по умолчанию проверяется viewReport#).

  3. В поле «Список алиасов» укажите алиасы таблиц через ; (по умолчанию — 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((&params) 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((&params) 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((&params) 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;
    }
  }  
}

Составное правило по трём атрибутам класса#

Параметры:

  1. dDate — значимый, дата;

  2. nNumber — значимый, число;

  3. 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((&params) 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;
  }
}

Составное правило по атрибуту класса и коллекции#

Параметры:

  1. sCaption — значимый, строка;

  2. 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((&params) 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;
  }
}

Составное правило по двум атрибутам (произвольная выборка)#

Параметры:

  1. sClass — значимый, строка;

  2. idRefClass — ссылочный на Btk_Class.

Фильтрация: sClass совпадает по LIKE (регистронезависимо), idRefClass совпадает точно.

Скрипт фильтрации объектных привилегий:

select 1
   from (
     select v -> 'sClass' as sClass
          ,v -> 'idRefClass' as idRefClass
       from json_array_elements(cast((&params) 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;
  }
}