Введение
Всем доброго времени суток!
В данной статье я хочу рассмотреть базовый функционал подсистемы "Управление доступом", а именно управление профилями доступа для актуальной на текущий момент библиотеки стандартных подсистем (БСП). На момент написания публикации - версия БСП 3.1.5.208. Тестирование практических примеров осуществляется для Платформе 1с 8.3.19.1264.
Публикация будет полезна всем программистам - разработчикам, а так же желающим познакомиться с основным функционалом подсистемы "Управление доступом" в любой современной типовой конфигурации (работающей на БСП).
Материал статьи разбит на несколько частей с практическими примерами, в которых рассматривается проверка доступности ролей, включение или выключение профилей пользователю, программное создание или обновление профилей базы и прочие интересные моменты использования функционала БСП "управление доступом". Примеры публикации актуальны для серверных и файловых баз.
Перейдем к первой части - проверка наличия ролей и программное добавление профилей пользователю:
Часть 1. Проверка наличия роли и программное добавление профиля пользователю.
Самый базовый метод - проверка, что у пользователя есть роль через Профиль группы доступа, в котором он состоит:
Роль1 = УправлениеДоступом.ЕстьРоль("ДобавлениеИзменениеКурсовВалют",,Справочники.Пользователи.НайтиПоНаименованию("ТестПользователь"));
// истина
Данный код будет возвращать Истину, если у пользователя "ТестПользователь" есть роль "ДобавлениеИзменениеКурсовВалют", которая добавлена через профиль группы доступа пользователя:
Рис.1 Профиль пользователя с ролью "Добавление и изменение курсов валют".
Поскольку наш только созданный тестовый пользователь ТестПользователь не имеет право на вход в базу данных попробуем добавить профиль "Пользователь" пользователю ТестПользователь следующим кодом:
УправлениеДоступом.ВключитьПрофильПользователю(Справочники.Пользователи.НайтиПоНаименованию("ТестПользователь"),Справочники.ПрофилиГруппДоступа.НайтиПоНаименованию("Пользователь"));
Смотрим, профиль добавился:
Рис.2 Добавленный профиль "Пользователь" процедурой ВключитьПрофильПользователю.
Теперь, мы можем зайти в базу данным пользователем:
Рис.3 Зашли тестовым пользователем в базу, при назначенном профиле "Пользователь".
Так же, я могу добавить профиль "Администратор" с ролями "Полные права" и "Администратор системы", т.е. программно с помощью БСП в любой типовой конфигурации я могу "раздавать" полные права.
УправлениеДоступом.ВключитьПрофильПользователю(Справочники.Пользователи.НайтиПоНаименованию("ТестПользователь"),Справочники.ПрофилиГруппДоступа.НайтиПоНаименованию("Администратор"));
Отключение любого профиля у пользователя осуществляется вот таким кодом:
УправлениеДоступом.ВыключитьПрофильПользователю(Справочники.Пользователи.НайтиПоНаименованию("ТестПользователь"),Справочники.ПрофилиГруппДоступа.НайтиПоНаименованию("Администратор"));
Так, с базовым включением/выключением профиля мы разобрались, теперь перейдем ко второй части статьи - программное создание профиля доступа с помощью библиотеки стандартных подсистем.
Часть 2. Программное обновление и создание профиля доступа на БСП.
Данную часть статьи я разобью на два подраздела, в которых проведу некоторые эксперименты для обновления или создания нового профиля доступа.
Подраздел 2.1 Программное обновление поставляемого профиля доступа.
Для подготовки профиля доступа, мы воспользуемся типовым программным конструктором, который предлагается в библиотеке стандартных подсистем. Выглядит это вот так:
ГуидПрофиля = "bfd56f51-313d-11e5-b1ac-e0cb4ed5f655"; // Этот гуид профиля "зашит" в базе
ПрограммныйПрофиль = УправлениеДоступом.НовоеОписаниеПрофиляГруппДоступа();
ПрограммныйПрофиль.Имя = "Тестовый профиль (изм2)";
ПрограммныйПрофиль.Идентификатор = ГуидПрофиля;
ПрограммныйПрофиль.Наименование = НСтр("ru = 'Тестовый профиль (изм2)'", ОбщегоНазначения.КодОсновногоЯзыка());
ПрограммныйПрофиль.Описание = НСтр("ru = 'Программно изменил созданный профиль в предприятии'");
// Использование 1С:Предприятия.
ПрограммныйПрофиль.Роли.Добавить("ЗапускВебКлиента");
ПрограммныйПрофиль.Роли.Добавить("ЗапускТолстогоКлиента");
ПрограммныйПрофиль.Роли.Добавить("ЗапускТонкогоКлиента");
ПрограммныйПрофиль.Роли.Добавить("ЗапускМобильногоКлиента");
ПрограммныйПрофиль.Роли.Добавить("ВыводНаПринтерФайлБуферОбмена");
ПрограммныйПрофиль.Роли.Добавить("СохранениеДанныхПользователя");
// Использование программы.
ПрограммныйПрофиль.Роли.Добавить("БазовыеПраваБСП");
ПрограммныйПрофиль.Роли.Добавить("ПросмотрОписанияИзмененийПрограммы");
ПрограммныйПрофиль.Роли.Добавить("ИзменениеТекущегоПользователя");
Данный конструктор уже создает структуру заполнения, которую можно отправить в функцию обновления профиля, заменив с помощью нее роли данного профиля (на настройках видов доступа остановимся в следующей статье).
Воспользуемся вот этой функцией обновления профиля (находится в менеджере справочника ПрофилиГруппДоступа):
//возврат истина или ложь
ПрофильОбновлен = Справочники.ПрофилиГруппДоступа.ОбновитьПрофильИлиПапкуПрофилей(ПрограммныйПрофиль,Ложь);
Типовая функция выглядит вот так (скопирую код в статью, т.к. далее, я буду вносить в эту функцию доработки):
Во-первых, для эксперимента - сделаем эту функцию Экспортной, чтобы мы могли напрямую обращаться к ней через модуль менеджера справочника.
Во-вторых, как заявлено, данная функция может обновлять только поставляемые профили, если я ищу профиль по гуиду - выходит ошибка - профиль не найден в поставке.
Поэтому, я доработал данную функцию (мне показалась, что по условиям она сыроватой на этом релизе), теперь позволяет вносить исправления и в поставляемые профили и создавать новые по типовому конструктору профиля в БСП.
Выглядит эта функция вот так:
Функция ОбновитьПрофильИлиПапкуПрофилей(СвойстваПрофиля, НеОбновлятьРолиПользователей = Ложь) Экспорт
ПрофильИзменен = Ложь;
//ПрофильСсылка = ПоставляемыйПрофильПоИдентификатору(СвойстваПрофиля.Идентификатор);
//Если ПрофильСсылка = Неопределено Тогда
Если ЗначениеЗаполнено(СвойстваПрофиля.Имя) Тогда
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПрофилиГруппДоступа.Ссылка КАК Ссылка,
| ПрофилиГруппДоступа.ИмяПредопределенныхДанных КАК ИмяПредопределенныхДанных
|ИЗ
| Справочник.ПрофилиГруппДоступа КАК ПрофилиГруппДоступа
|ГДЕ
| ПрофилиГруппДоступа.Предопределенный = ИСТИНА";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ИмяПредопределенного = Выборка.ИмяПредопределенныхДанных;
Если ВРег(СвойстваПрофиля.Имя) = ВРег(ИмяПредопределенного) Тогда
ПрофильСсылка = Выборка.Ссылка;
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если ПрофильСсылка = Неопределено
//И СвойстваПрофиля.ЭтоГруппа
И ЗначениеЗаполнено(СвойстваПрофиля.Наименование) Тогда
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПрофилиГруппДоступа.Ссылка КАК Ссылка
|ИЗ
| Справочник.ПрофилиГруппДоступа КАК ПрофилиГруппДоступа
|ГДЕ
| ПрофилиГруппДоступа.Предопределенный = ЛОЖЬ
| И ПрофилиГруппДоступа.ЭтоГруппа
| И ПрофилиГруппДоступа.Наименование = &Наименование";
Запрос.УстановитьПараметр("Наименование", СвойстваПрофиля.Наименование);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
ПрофильСсылка = Выборка.Ссылка;
КонецЕсли;
КонецЕсли;
Если ПрофильСсылка = Неопределено Тогда
// Поставляемый элемент не существует, нужно создать новый.
//ПрофильОбъект = ?(СвойстваПрофиля.ЭтоГруппа, СоздатьГруппу(), СоздатьЭлемент());
ПрофильОбъект = СоздатьЭлемент();
Иначе
// Поставляемый элемент связан с предопределенным элементом.
ПрофильОбъект = ПрофильСсылка.ПолучитьОбъект();
КонецЕсли;
ПрофильОбъект.ИдентификаторПоставляемыхДанных =
Новый УникальныйИдентификатор(СвойстваПрофиля.Идентификатор);
ПрофильИзменен = Истина;
//Иначе
// ПрофильОбъект = ПрофильСсылка.ПолучитьОбъект();
// ПрофильИзменен = ПоставляемыйПрофильИзменен(ПрофильОбъект);
//КонецЕсли;
//
//Если ПрофильИзменен Тогда
Если Не ОбновлениеИнформационнойБазы.ВыполняетсяОбновлениеИнформационнойБазы()
И Не ОбновлениеИнформационнойБазы.ЭтоВызовИзОбработчикаОбновления() Тогда
ЗаблокироватьДанныеДляРедактирования(ПрофильОбъект.Ссылка, ПрофильОбъект.ВерсияДанных);
КонецЕсли;
ПрофильОбъект.Наименование = СвойстваПрофиля.Наименование;
Если ЗначениеЗаполнено(СвойстваПрофиля.Родитель) Тогда
Родитель = ПоставляемыйПрофильПоИдентификатору(СвойстваПрофиля.Родитель);
Если ЗначениеЗаполнено(Родитель) Тогда
ПрофильОбъект.Родитель = Родитель;
КонецЕсли;
КонецЕсли;
//Если Не СвойстваПрофиля.ЭтоГруппа Тогда
ПрофильОбъект.Роли.Очистить();
Для каждого Роль Из ОписаниеРолейПрофиля(СвойстваПрофиля) Цикл
МетаданныеРоли = Метаданные.Роли.Найти(Роль);
Если МетаданныеРоли = Неопределено Тогда
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'При обновлении поставляемого профиля ""%1""
|обнаружена несуществующая роль ""%2"".'"),
СвойстваПрофиля.Наименование,
Роль);
КонецЕсли;
ПрофильОбъект.Роли.Добавить().Роль =
ОбщегоНазначения.ИдентификаторОбъектаМетаданных(МетаданныеРоли);
КонецЦикла;
ПрофильОбъект.ВидыДоступа.Очистить();
Для каждого ОписаниеВидаДоступа Из СвойстваПрофиля.ВидыДоступа Цикл
СвойстваВидаДоступа = УправлениеДоступомСлужебный.СвойстваВидаДоступа(ОписаниеВидаДоступа.Ключ);
Строка = ПрофильОбъект.ВидыДоступа.Добавить();
Строка.ВидДоступа = СвойстваВидаДоступа.Ссылка;
Строка.Предустановленный = ОписаниеВидаДоступа.Значение = "Предустановленный";
Строка.ВсеРазрешены = ОписаниеВидаДоступа.Значение = "ВначалеВсеРазрешены";
КонецЦикла;
ПрофильОбъект.ЗначенияДоступа.Очистить();
Для каждого ОписаниеЗначенияДоступа Из СвойстваПрофиля.ЗначенияДоступа Цикл
СвойстваВидаДоступа = УправлениеДоступомСлужебный.СвойстваВидаДоступа(ОписаниеЗначенияДоступа.ВидДоступа);
СтрокаЗначения = ПрофильОбъект.ЗначенияДоступа.Добавить();
СтрокаЗначения.ВидДоступа = СвойстваВидаДоступа.Ссылка;
Запрос = Новый Запрос(СтрЗаменить("ВЫБРАТЬ Значение(ЗначениеДоступа) КАК Значение",
"ЗначениеДоступа", ОписаниеЗначенияДоступа.ЗначениеДоступа));
СтрокаЗначения.ЗначениеДоступа = Запрос.Выполнить().Выгрузить()[0].Значение;
КонецЦикла;
ПрофильОбъект.Назначение.Очистить();
Для каждого ТипНазначения Из СвойстваПрофиля.Назначение Цикл
СтрокаНазначения = ПрофильОбъект.Назначение.Добавить();
СтрокаНазначения.ТипПользователей = ТипНазначения;
КонецЦикла;
Если НеОбновлятьРолиПользователей Тогда
ПрофильОбъект.ДополнительныеСвойства.Вставить("НеОбновлятьРолиПользователей");
КонецЕсли;
//КонецЕсли;
ОбновлениеИнформационнойБазы.ЗаписатьОбъект(ПрофильОбъект);
Если Не ОбновлениеИнформационнойБазы.ВыполняетсяОбновлениеИнформационнойБазы()
И Не ОбновлениеИнформационнойБазы.ЭтоВызовИзОбработчикаОбновления() Тогда
РазблокироватьДанныеДляРедактирования(ПрофильОбъект.Ссылка);
КонецЕсли;
//КонецЕсли;
Возврат ПрофильИзменен;
КонецФункции
С помощью этой функции вносим изменения про поставляемый профиль менеджера (используя гуид профиля и конструктор выше). Результат выглядит вот так:
Рис.4.Профиль отличается от поставляемого
Теперь, перейдем к созданию своего профиля.
Подраздел 2.2 Программное создание профиля доступа.
Здесь, все тоже самое, только гуид мы создаем самостоятельно. Конструктор и код исполнения вот такой:
ГуидПрофиля = Новый УникальныйИдентификатор();
ПрограммныйПрофиль = УправлениеДоступом.НовоеОписаниеПрофиляГруппДоступа();
ПрограммныйПрофиль.Имя = "Программный профиль 1";
ПрограммныйПрофиль.Идентификатор = ГуидПрофиля;
ПрограммныйПрофиль.Наименование = НСтр("ru = 'Программный профиль 1'", ОбщегоНазначения.КодОсновногоЯзыка());
ПрограммныйПрофиль.Описание = НСтр("ru = 'Программно изменил созданный профиль в предприятии'");
// Использование 1С:Предприятия.
ПрограммныйПрофиль.Роли.Добавить("ЗапускВебКлиента");
ПрограммныйПрофиль.Роли.Добавить("ЗапускТолстогоКлиента");
ПрограммныйПрофиль.Роли.Добавить("ЗапускТонкогоКлиента");
ПрограммныйПрофиль.Роли.Добавить("ЗапускМобильногоКлиента");
ПрограммныйПрофиль.Роли.Добавить("ВыводНаПринтерФайлБуферОбмена");
ПрограммныйПрофиль.Роли.Добавить("СохранениеДанныхПользователя");
// Использование программы.
ПрограммныйПрофиль.Роли.Добавить("БазовыеПраваБСП");
ПрограммныйПрофиль.Роли.Добавить("ПросмотрОписанияИзмененийПрограммы");
//истина или ложь
СоздалиПрофиль = Справочники.ПрофилиГруппДоступа.ОбновитьПрофильИлиПапкуПрофилей(ПрограммныйПрофиль,Ложь);
Получаем программный профиль с ролями:
Рис.5.Программный профиль с ролями
На этом закончим второй раздел и перейдем к выводам и заключению.
Выводы и заключение
В данной статье, я решил поэкспериментировать с программным созданием профилей в рамках системы БСП, используя конструктор профиля и функцию создания/обновления. В начале статьи рассмотрены примеры добавление профилей пользователям, а во второй части статьи - создание и обновление профилей.
Есть еще одна идейка - написать статью и поставить эксперименты с программными настройками видов доступа в профиле.
Надеюсь, что вам понравился данный материал и он будет вам полезен. Спасибо за внимание!
Другие мои материалы по подсистемам БСП
Также прошу ознакомиться с другими моими статьями по интересному функционалу типовых конфигураций в рамках библиотеки стандартных подсистем и по разделам:
Администрирование с помощью БСП:
Журнал регистрации - основные методы работы через БСП
Базовые приемы работы с кластером 1С при помощи БСП
Длительные операции:
БСП - рабочие примеры асинхронного запуска функций и процедур
Работа со штрихкодами и печатными макетами: