Преамбула :)
Конечно, это не первая подобная обработка, но тем не менее я все таки решил выложить поскольку считаю, что из-за своей простоты (ненавороченности) позволяет получить навыки работы
- С процедурой «ПравоДоступа» - основной процедурой определения прав
- С объектами метаданных (построениедерева метаданных и т.д.)
- С отчетами типа «шахматки»
В обрате отсутствуют какие-либо отборы и настройки. Если есть необходимость их можно доработать, но тут их нет именно потому, что обработку старались сделать как можно проще (на совершенство обработка не претендует :) )
Постановка задачи.
Необходимо получить отчет по доступу ролей к объектам метаданных (сегодня озадачили этим J). При этом рассматриваются только три возможных состояния:
- Роли доступно свойство «Изменение» (другое не проверяется)
- Роли доступно свойство «Чтение» (если изменение не доступно, т.е. «Изменение» имеет более высокий приоритет чем «Чтение»)
- В остальных случаях считается что роли ничего не доступно.
Действительно, если роли доступно «Редактирование» или «Пометка на удаление», то «Изменение» ей так же должно быть доступно, а если доступно «Просмотр», то обязательно доступно «Чтение». Поэтому, для читабельности отчета (иначе он просто потеряет читабельность) мы и контролируем эти два права (Изменение и Чтение).
Так же необходимо проверить права роли на работу с самой конфигурацией («Монопольный режим», «Администрирование» и т.д.)
Отчет должен быть представлен в виде шахматки:
- Строки «Объекты метаданных»
- Колонки «Роли»
Реализация задачи
В общем случае последовательность работ такая:
- Создаем список ролей
- Создаем список контролируемых прав (с учетом приоритета)
- Создаем список объектов метаданных
- Сравниваем все три параметра в процедуре «ПравоДоступа» и выводим результат.
Для реализации создадим новую обработку и форму, весь программный код поместим в модуль формы. На форме создадим «табличное поле» («ПолеТабличногоДокумента1») куда будем выводить отчет. Кроме того будут реквизиты формы:
дМетаданных – дерево метаданных (вывод нужно организовать с учетом иерархии). Конечно, от него можно отказаться и просто организовать обход по метаданным, но лучше его оставить, так как если потребуется поставить фильтр на объекты в отчет оно может здорово пригодится (достаточно в дереве добавить новую колонку, проставить в нее соответствующий признак, и при выводе учитывать – в данной обработке не реализовано).
спРоли – список ролей в конфигурации. Так же при необходимости отборов добавляем на форму и используем свойство «Пометка».
спПрав – список контролируемых прав с учетом приоритетов (то что важнее заносится раньше).
Соответственно в форму при открытии укажем процедуры по заполнению всех нужных списков.
Процедура ПриОткрытии()
Роли_ПолучитьСписок();
Роли_СписокПрав();
ДеревоМетаданных();
КонецПроцедуры
Начнем с простого – список прав (их всего две), и список ролей
Процедура Роли_СписокПрав()
спПрав.Добавить("Изменение");
спПрав.Добавить("Чтение");
КонецПРоцедуры
Процедура Роли_ПолучитьСписок()
спРоли = новый СписокЗначений;
Для каждого РОль Из Метаданные.Роли Цикл
ОбработкаПрерыванияПОльзователя();
спРоли.Добавить(РОль,РОль_Описание(РОль));
КонецЦикла;
КонецПроцедуры
Функция РОль_Описание(Роль)
Результат = РОль.Представление();
Если Результат<>РОль.Имя Тогда
Результат = Результат+"["+Роль.Имя+"]";
КонецЕсли;
возврат Результат;
КонецФункции
При формировании отчета мы хотим видеть пользовательское представление метаданных и ролей, а так же их представление в метаданных (поэтому и вводим Функцию «РОль_Описание» - в принципе ее можно описать непосредственно в процедуре «Роли_ПолучитьСписок» - дело вкуса :) )
Если посмотреть в описании процедуры «ПравоДоступа» то такие права как «Администрирование» тоже по идеи нужно отнести в СписокПрав, но исходя из целесообразности и наглядности отчета мы условно отнесем их к метаданным и занесем в дальнейшем в дМетаданные (что бы видеть их как строки – создадим отдельную ветку).
Дерево метаданных состоит из двух колонок «Описание» и «Представление»
Процедура ДеревоМетаданных() Экспорт
дМетаданные.Колонки.Добавить("Объект");
дМетаданные.Колонки.Добавить("Представление");
ДеревоМетаданных_ДобавитьАдминистрирование();
ДеревоМетаданных_Добавить("Справочники");
ДеревоМетаданных_Добавить("Документы");
ДеревоМетаданных_Добавить("ЖурналыДокументов","Журналы документов");
ДеревоМетаданных_Добавить("Перечисления");
ДеревоМетаданных_Добавить("Отчеты");
ДеревоМетаданных_Добавить("Обработки");
ДеревоМетаданных_Добавить("ПланыВидовХарактеристик","Планы видов характеристик");
ДеревоМетаданных_Добавить("ПланыСчетов","Планы счетов");
ДеревоМетаданных_Добавить("ПланыВидовРасчета","Планы видов расчета");
ДеревоМетаданных_Добавить("РегистрыСведений","Регистры сведений");
ДеревоМетаданных_Добавить("РегистрыНакопления","Регистры накопления");
ДеревоМетаданных_Добавить("РегистрыБухгалтерии","Регистры бухгалтерии");
ДеревоМетаданных_Добавить("РегистрыРасчета","Регистры расчета");
ДеревоМетаданных_Добавить("БизнесПроцессы","Бизнес-процессы");
ДеревоМетаданных_Добавить("Задачи");
КонецПроцедуры
ПРоцедура ДеревоМетаданных_ДобавитьАдминистрирование()
СтрокаГр = дМетаданные.Строки.Добавить();
СтрокаГр.Объект = "Администрирование";
СтрокаГр.Представление = "Права на конфигурацию в целом";
мсПрав = новый СписокЗначений;
мсПрав.Добавить("Администрирование","Администрирование");
мсПрав.Добавить("МонопольныйРежим","Монопольный режим");
мсПрав.Добавить("АктивныеПользователи","Просмотр списка активных пользователей");
мсПрав.Добавить("ЖурналРегистрации","Журнал регистрации");
мсПрав.Добавить("ВнешнееСоединение","Внешнее соединение");
мсПрав.Добавить("Automation","Использование automation");
мсПрав.Добавить("ИнтерактивноеОткрытиеВнешнихОбработок","Интерактивное открытие внешних обработок");
мсПрав.Добавить("ИнтерактивноеОткрытиеВнешнихОтчетов","Интерактивное открытие внешних отчетов");
мсПрав.Добавить("Вывод","Вывод на печать, запись и копирование в буфер обмена");
мсПрав.Добавить("ОбновлениеКонфигурацииБазыДанных","Обновление конфигурации базы данных");
Для каждого эл Из мсПрав Цикл
ОбработкаПрерыванияПОльзователя();
НС = СтрокаГр.Строки.Добавить();
НС.Объект = Эл.Значение;
НС.Представление = Эл.Представление;
КонецЦикла;
КонецПРоцедуры
Процедура ДеревоМетаданных_Добавить(что,Представление="")
Первая = истина;
Для каждого мет Из Метаданные[что] Цикл
Если Первая Тогда
СтрокаГр = дМетаданные.Строки.Добавить();
СтрокаГр.Объект = Что;
Если ПустаяСтрока(Представление) Тогда
СтрокаГР.Представление = Что;
иначе
СтрокаГР.Представление = Представление;
КонецЕсли;
первая = Ложь;
КонецЕсли;
строка = СтрокаГр.Строки.Добавить();
Строка.Объект = Мет.Имя;
Строка.Представление = Мет.Представление();
КонецЦикла;
КонецПроцедуры
Как было сказано для ряда прав мы создаем отдельную ветку «Администрирование» (процедура «ДеревоМетаданных_ДобавитьАдминистрирование()»), и определять эту ветку мы будем по объекту «Администрирование». Остальные возможные объекты метаданных мы добавляем с помощью процедуры ДеревоМетаданных_Добавить(,). При этом в процедуре ДеревоМетаданных_Добавить мы контролируем что бы хотя бы один объект такого типа есть (иначе ветка не нужна). Кроме того, если «Представление» в параметрах процедуры не задана, то считаем что прдеставление равно типу.
Далее, нам нужно будет создать макет, имеющий вертикальные и горизонтальные секции (для формирования шахматки). Кроме того, поскольку мы формируем шахматку с использованием разных процедур то в форме объявим две переменные: Макет и ТабДок (ТабДок – это результирующий отчет).
Дальше собственно формируем сам отчет с использованием (как уже несколько раз было сказано J ) процедуры «ПравоДоступа». Учтем один нюанс, если нам нужно получить права роли на какой-то отдельный объект метаданных (из нашего дерева), то мы должны передать в процедуру ПравоДоступа(,,), где «Право» из списка Прав. Но если нам нужно получить права ролей из ветки “Администрирование», то в качестве Метаданных используется сама конфигурация (т.е. просто МЕТАДАННЫЕ), а права у нас уходят в дерево Метаданных, и тогда нужно использовать ПравоДоступа(,Метаданные,), а результат уже просто доступно это право или нет.
Для этого создадим отдельную функцию:
Функция РОль_Права(Мет,Роль)
Результат = "";
Если ТипЗнч(Мет)=Тип("Строка") Тогда
// это проверка Административных прав
Если ПравоДоступа(Мет,Метаданные,РОль) Тогда
Результат = "Да";
иначе
результат = "";
КонецЕсли;
возврат Результат;
КонецЕсли;
Для каждого Право Из спПрав Цикл
ОбработкаПрерыванияПОльзователя();
Если ПравоДоступа(Право.Значение,Мет,РОль) Тогда
Результат = Право.Значение;
прервать;
КонецЕсли;
КонецЦикла;
возврат Результат;
КонецФункции
В которую если у нас контролируется права на объект метаданных в качестве первого параметра и передаем этот объект (функция в этом случае возвращает значение права учетом приоритета), а если нужно право из ветки «Администрирование», то передаем строковую переменную с именем этого права (функция возвращает «Да» или). По типу первого параметра и определяется, как использовать функцию ПравоДоступа.
Формирование самого отчета делаем при помощи процедур
Процедура Сфомировать_Вывод(ИмяСекции,данные=Неопределено)
Сек = Макет.ПолучитьОбласть(ИмяСекции+"|Начало");
пСек = Сек.Параметры;
Уровень = 0;
ЭтоАдминистирирование = ТипЗнч(Данные)=Тип("СтрокаДереваЗначений");
Если ИмяСекции="С1" Тогда
уровень = 1;
пСек.Объект = данные;
ИначеЕсли ИмяСекции="С2" Тогда
уровень = 2;
Если ЭтоАдминистирирование Тогда
пСек.Объект = данные.Представление;
пСек.Обозначение = данные.Объект;
иначе
пСек.Объект = данные.Представление();
пСек.Обозначение = данные.Имя;
КонецЕсли;
КонецЕсли;
ТабДок.Вывести(Сек,Уровень);
Для каждого Роль Из спРоли Цикл
ОбработкаПрерыванияПОльзователя();
Сек = Макет.ПолучитьОбласть(ИмяСекции+"|В1");
пСек = Сек.Параметры;
Если ИмяСекции = "Ш1" Тогда
пСек.РОль = Роль.Представление;
иначеЕСли ИмяСекции = "С2" Тогда
Если ЭтоАдминистирирование Тогда
Права = РОль_Права(данные.Объект,Роль.Значение);
иначе
Права = РОль_Права(данные,Роль.Значение);
КонецЕсли;
Если Права = "Изменение" или Права="Да" тогда
Сек.Область("ТекПрава").ЦветФона = WebЦвета.СветлоЗеленый;
ИначеЕсли Права = "Чтение" тогда
Сек.Область("ТекПрава").ЦветФона = WebЦвета.Желтый;
КонецЕсли;
пСек.Права = Права;
КонецЕсли;
ТабДок.Присоединить(Сек);
КонецЦикла;
ТабДок.Присоединить(Макет.ПолучитьОбласть(ИмяСекции+"|Конец"));
КонецПроцедуры
Процедура Сфомировать(Кнопка)
ТабДок = ЭлементыФормы.ПолеТабличногоДокумента1;
ТабДок.Очистить();
Макет = ПолучитьМакет("Макет");
Сфомировать_Вывод("Ш1");
ТабДок.ФиксацияСверху = ТабДок.ВысотаТаблицы;
ТабДок.ФиксацияСлева = 2;
ТабДок.НачатьАвтогруппировкуСтрок();
Для каждого Ст1 Из дМетаданные.Строки Цикл
ОбработкаПрерыванияПОльзователя();
ЭтоАдминистирирование = Ст1.Объект = "Администрирование";
Если ЭтоАдминистирирование Тогда
Мет1 = Метаданные;
иначе
Мет1 = Метаданные[Ст1.ОБъект];
КонецЕсли;
Сфомировать_Вывод("С1",Ст1.Представление);
Для каждого Ст2 Из Ст1.Строки Цикл
ОбработкаПрерыванияПОльзователя();
Если ЭтоАдминистирирование Тогда
Мет2 = Ст2;
иначе
Мет2 = Мет1[СокрЛП(Ст2.ОБъект)];
КонецЕсли;
Сфомировать_Вывод("С2",Мет2);
КонецЦикла;
КонецЦикла;
ТабДок.ЗакончитьАвтогруппировкуСтрок();
Сфомировать_Вывод("И1");
КонецПроцедуры
Сфомировать – организует таблицу и обход по строкам
Сфомировать_Вывод – организует обход по колонкам
Ну и для красоты отчета те роли, которые имеют право «Изменение» или «Да» (для администрирования) окрашиваем зеленым, роли на «Чтение» - желтым. Для этого создали в секции специальную именованную область.
Собственно и все, может кому пригодится как исходная «точка» для написания нечто подобного, к примеру, если нужно получить права не по ролям а по пользователям, то список ролей меняем на список пользователей и в ПравоДоступа передаем не роль а конкретного пользователя.
Р.S. Надеюсь, не очень занудно получилось :) и подскажите, как в публикации выделить кусок текста как "код программы" (теги CODE как в сообщениях почему-то не работают, или я их не правильно использую).