Упрощенная обработка по просмотру прав по ролям на объекты конфигурации


Обработка предназначена для получения «шахматки» прав по ролям и объектам метаданных. Написано для 8.1 но перекодировать в 8.2 проблемы нет (для использовании в 8.2 в текущем виде необходимо запускать ее в «обычном приложении»).

Преамбула :)

 

Конечно, это не первая подобная обработка, но тем не менее я все таки решил выложить поскольку считаю, что из-за своей простоты (ненавороченности) позволяет получить навыки работы

  1. С процедурой «ПравоДоступа» - основной процедурой определения прав
  2. С объектами метаданных (построениедерева метаданных и т.д.)
  3. С отчетами типа «шахматки»

 

В обрате отсутствуют какие-либо отборы и настройки. Если есть необходимость их можно доработать, но тут их нет именно потому, что обработку старались сделать как можно проще (на совершенство обработка не претендует :) )

 

Постановка задачи.

 

Необходимо получить отчет по доступу ролей к объектам метаданных (сегодня озадачили этим J). При этом рассматриваются только три возможных состояния:

  • Роли доступно свойство «Изменение» (другое не проверяется)
  • Роли доступно свойство «Чтение» (если изменение не доступно, т.е. «Изменение» имеет более высокий приоритет чем «Чтение»)
  • В остальных случаях считается что роли ничего не доступно.

 Действительно, если роли доступно «Редактирование» или «Пометка на удаление», то «Изменение» ей так же должно быть доступно, а если доступно «Просмотр», то обязательно доступно «Чтение». Поэтому, для читабельности отчета (иначе он просто потеряет читабельность) мы и контролируем эти два права (Изменение и Чтение).

 

Так же необходимо проверить права роли на работу с самой конфигурацией («Монопольный режим», «Администрирование» и т.д.)

 

Отчет должен быть представлен в виде шахматки:

  • Строки «Объекты метаданных»
  • Колонки «Роли»

 

Реализация задачи

 

В общем случае последовательность работ такая:

  1. Создаем список ролей
  2. Создаем список контролируемых прав (с учетом приоритета)
  3. Создаем список объектов метаданных
  4. Сравниваем все три параметра в процедуре «ПравоДоступа» и выводим результат.

 

Для реализации создадим новую обработку и форму, весь программный код поместим в модуль формы. На форме создадим «табличное поле» («ПолеТабличногоДокумента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 как в сообщениях почему-то не работают, или я их не правильно использую).

Файлы обработки:

-