Допустим, поставлена задача ограничения доступа к некоторым организациям с одним условием. Необходимо полное исчезновение организаций: чтобы их не было нигде, ни в договорах контрагентов, ни в кассах ККМ, ни в списках документов, ни в отчетах и т.д. и т.п.
Рассмотрим для примера УТ 10.3.
На первый взгляд ничего сложного. Создаем группу пользователей в справочнике "Группы пользователей", заполняем пользователями (неполноправными), которым надо ограничить доступ к организациям. Задаем доступные для просмотра организации в регистре сведений "Настройки прав доступа пользователей". Включаем константу "Ограничить права доступа на уровне записей". Что видит пользователь в программе после перезапуска. В справочнике "Организации" только те, что разрешены. Но там, где встречаются скрытые организации в поле "Организация" написано "Объект не найден...". Доступа к редактированию этих объектов нет, но не совсем то, что задумывалось.
Это происходит от того, что в правах доступа к объектам (кроме справочника "Организации", контактной информации и еще некоторых объектов, не прописаны ограничения доступа на уровне записей. Особенно в нетиповых конфигурациях, когда новые роли и метаданные добавляются в конфигурацию в условиях, приближенных к боевым, без оглядки на будущее. И даже в типовой УТ 10.3, у роли МенеджерПоПродажам, например, нет ограничения доступа на уровне записей у корректировки реализации, в отличие от документа-основания - реализации товаров и услуг:
Что есть на программном уровне
На программном уровне платформа 8.2 позволяет посмотреть, есть ли у выбранной роли право чтения/добавления/изменения/удаления выбранного метаданного, а также имеется ли у этого права ограничение доступа RLS, но самого значения ограничения доступа нет:
ЕстьПравоНаЧтение = Ложь;
ЕстьОграничениеРЛС = Ложь;
МетаданныеРоль = Метаданные.Роли["МенеджерПоПродажам"];
МетаданныеСправочника = Метаданные.Справочники["Организации"];
ПравоНаЧтение = ПараметрыДоступа("Read", МетаданныеСправочника, "Ссылка", МетаданныеРоль);
Если ПравоНаЧтение.Доступность Тогда
ЕстьПравоНаЧтение = Истина;
Если ПравоНаЧтение.ОграничениеУсловием Тогда
ЕстьОграничениеРЛС = Истина;
КонецЕсли;
КонецЕсли;
У большинства ролей уже написаны шаблоны ограничений доступа. Их можно посмотреть, открыв роль в конфигураторе и перейдя на вкладку "Шаблоны ограничений".
Вручную ограничить можно, но долго. Запустить поиск по дереву конфигурации по слову Организация. Пройтись по дереву, открывая каждый найденный объект, пройтись по правам этого объекта для каждой роли, и для ролей, имеющих доступ к объекту в разрешенных правах проставить типовой шаблон или свой текст ограничения доступа.
Попробуем автоматизировать.
Как все-таки можно посмотреть содержимое ограничений доступа RLS программно
Выгрузим файлы конфигурации. Конфигурация - Выгрузить файлы конфигурации.
Оставим флажки только на правах:
Посмотрим XML-файл Роль.МенеджерПоПродажам.Права.xml.
Ветка прав доступа с ограничениями на документ "Заказ покупателя":
В конце файла находятся сами шаблоны ограничений для выбранной роли.
Как это обработать
Используем встроенный в конфигурацию механизм ПостроительDOM.
Прочитаем документ.
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ПолныйПутькФайлу);
ПостроительDOM = Новый ПостроительDOM;
ДокументDOM = ПостроительDOM.Прочитать(ЧтениеXML);
Затем, при помощи ОбходДереваDOM, обойдем дерево.
Для перехода вглубь используется метод СледующийУзел(), для перехода по родительским узлам (объекты, права) используется метод СледующийСоседний(), для возврата на родительский узел используется запоминание узла-родителя и переход на него в конце цикла установкой текущего узла.
Там, где содержится условие ограничения доступа, заменяем на нужное нам, если нет - добавляем.
ОбходДереваDOM = Новый ОбходДереваDOM(ДокументDOM);
// переход на уровень rights
ТекУзел = ОбходДереваDOM.СледующийУзел();
// переход на уровень object
ТекУзел = ОбходДереваDOM.СледующийУзел();
// ОБХОД ОБЪЕКТОВ
Пока ТекУзел <> Неопределено Цикл
// переход вглубь дерева на уровень name
ТекУзел = ОбходДереваDOM.СледующийУзел();
// переход на уровень right
ТекУзел = ОбходДереваDOM.СледующийСоседний();
// ОБХОД ПРАВ
Пока ТекУзел <> Неопределено Цикл
ОбработкаПрерыванияПользователя();
УзелПрава = ОбходДереваDOM.ТекущийУзел;
// переход вглубь дерева на уровень name
ТекУзел = ОбходДереваDOM.СледующийУзел();
ЕстьОграничениеПоУсловию = Ложь;
Пока ТекУзел <> Неопределено Цикл
ОбработкаПрерыванияПользователя();
Если ТекУзел.ИмяУзла = "restrictionByCondition" Тогда
ЕстьОграничениеПоУсловию = Истина;
// переход вглубь дерева на уровень condition
ТекУзел = ОбходДереваDOM.СледующийУзел();
ТекУзел.ПервыйДочерний.ТекстовоеСодержимое = НовоеЗначениеОграничения;
Сообщить(ИмяМетаданного + ": заменено ограничение " + ТекУзел.ПервыйДочерний.ТекстовоеСодержимое);
ВнесеныИзменения = Истина;
Прервать;
КонецЕсли;
ТекУзел = ОбходДереваDOM.СледующийСоседний();
КонецЦикла;
Если НЕ ЕстьОграничениеПоУсловию Тогда
// вставка условия
НовыйУзелЗначения1 = ДокументDOM.СоздатьЭлемент("restrictionByCondition");
НовыйУзелЗначения2 = ДокументDOM.СоздатьЭлемент("condition");
НовыйУзелЗначения2.ТекстовоеСодержимое = НовоеЗначениеОграничения;
НовыйУзелЗначения1.ДобавитьДочерний(НовыйУзелЗначения2);
УзелПрава.ДобавитьДочерний(НовыйУзелЗначения1);
Сообщить(ИмяМетаданного + ": добавлено ограничение " + УзелПрава.ПервыйДочерний.ТекстовоеСодержимое);
ВнесеныИзменения = Истина;
КонецЕсли;
// возврат на уровень прав
ОбходДереваDOM.ТекущийУзел = УзелПрава;
ТекУзел = ОбходДереваDOM.СледующийСоседний();
КонецЦикла;
// возврат на уровень объекта
ОбходДереваDOM.ТекущийУзел = УзелОбъекта;
ТекУзел = ОбходДереваDOM.СледующийСоседний();
КонецЦикла;
Обработанный файл записываем.
ЧтениеXML.Закрыть();
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл(ИмяСохраняемогоФайла);
ЗаписьDOM = Новый ЗаписьDOM;
ЗаписьDOM.Записать(ДокументDOM, ЗаписьXML);
ЗаписьXML.Закрыть();
И последнее - загружаем измененные файлы обратно. Конфигурация - Загрузить файлы конфигурации.
Также оставим флажки только на правах.
Сохраняем измененную конфигурацию и готово.
Что умеет приложенная к статье обработка
- Выбирает все метаданные с возможностью ограничений доступа по RLS с отбором по имени реквизита. Имя реквизита можно не задавать, тогда будут выбраны все метаданные.
- Позволяет пропустить конструкции запрета ГДЕ Ложь
- Позволяет добавлять ограничение роли, а не заменять при наличии уже существующего ограничения
- Отбирает для редактирования только те роли, которые имеют право изменять выбранные метаданные
- Позволяет дополнительно отобрать по сформированным спискам роли и метаданные
- Позволяет указать текст ограничения доступа для четырех видов ограничений: чтение, изменение, добавление, удаление; для регистров сведений, накопления и т.д. будут применены только чтение и изменение
- Анализирует выгруженные файлы прав, изменяет в них отмеченные роли и метаданные. Измененные файлы обработка складывает в подпапку "_out" указанной папки с файлами.
- Позволяет копировать шаблоны ограничений доступа с одной роли на другую (вкладка Отборы, вкладка Роли, кнопка Копировать шаблоны ролей)
- В качестве материала для анализа формирует кросс-таблицу по ролям и метаданным с указанием доступа и наличием ограничений доступа по RLS по всем ролям и метаданным по отбору
- Может использоваться в качестве учебного материала по обходу дерева метаданных и обработке xml-файлов через механизм ПостроительDOM
Спасибо за внимание и труд к прочтению статьи, понимаю, что материал специфический, но вдруг кому-то в чем-то поможет разобраться...