Программное добавление пользователей в базы на БСП

Клиент заказал скрипт для Обновлятора для создания пользователей и назначения им прав в конфигурации на БСП — в БП3 и ЗУП3.

Для начала проверим, как все работает в БП3, наверное в ЗУП3 должно работать аналогично? Если там будет своя специфика, то поправим на месте.

Вообще говоря, 1С предполагает ручное создание пользователей и прав и тема автоматизации этого процесса не документирована, а значит, требуется разбираться и смотреть, что можно использовать из готового кода 1С.

Ручное создание пользователя

Создадим пользователя вручную:

Добавим ему права путем включения в нужную группу доступа:

При всех этих манипуляциях я запустил замер производительности и при запуске 1С выключил режим отладки, чтобы не запускало фоновые задания.

Таким образом я нашел код, где программа создает/обновляет пользователя:

Этот код дает нам примерное понимание, как создавать пользователя программно.

Программное включение/исключение пользователя в группы доступа. Неоптимальное

Теперь нужно разобраться, как включить пользователя в группы доступа. Для этого, на самом деле я не анализировал БСП, а посмотрел ссылки на созданного пользователя в базе:

Пользователям назначаются почему-то персональные группы доступа:

Теперь проверяем — если мы снимаем галочку, то права доступа очищаются:

Очищаются они и в конфигураторе:

Теперь попробуем программно изменить группу доступа, написав такой код:

&НаСервере
Процедура ИзменитьПраваГБ2НаСервере()
	ТекПользователь = Справочники.Пользователи.НайтиПоНаименованию("ГБ2");
	ТекПрофиль = Справочники.ПрофилиГруппДоступа.НайтиПоНаименованию("Главный бухгалтер");
	ТекГруппаДоступа = ДатьПерсональнуюГруппуДоступа(ТекПользователь, ТекПрофиль);
	ТекГруппаДоступаОбъект = ТекГруппаДоступа.ПолучитьОбъект();
	Если ТекГруппаДоступаОбъект.Пользователи.Количество() = 0 Тогда
		НСтр = ТекГруппаДоступаОбъект.Пользователи.Добавить();
		НСтр.Пользователь = ТекПользователь;
		Сообщить("Добавлен профиль:" + ТекПрофиль);
	Иначе
		ТекГруппаДоступаОбъект.Пользователи.Очистить();
		Сообщить("Удален профиль:" + ТекПрофиль);
	КонецЕсли;
	ТекГруппаДоступаОбъект.Записать();
	
	
КонецПроцедуры

&НаСервере
Функция ДатьПерсональнуюГруппуДоступа(Пользователь, Профиль)
	З = Новый Запрос(
	"ВЫБРАТЬ
	|	ГруппыДоступа.Ссылка
	|ИЗ
	|	Справочник.ГруппыДоступа КАК ГруппыДоступа
	|ГДЕ
	|	ГруппыДоступа.Профиль = &Профиль
	|	И ГруппыДоступа.Пользователь = &Пользователь
	|	");
	З.УстановитьПараметр("Пользователь", Пользователь);
	З.УстановитьПараметр("Профиль", Профиль);
	Выборка = З.Выполнить().Выбрать();
	Если Выборка.Следующий() Тогда
		Возврат Выборка.Ссылка;
	КонецЕсли;
КонецФункции

&НаКлиенте
Процедура ИзменитьПраваГБ2(Команда)
	ИзменитьПраваГБ2НаСервере();
КонецПроцедуры

Получилось, при первом запуске у пользователя включилась и группа доступа:

И появились роли в конфигураторе:

Проверил, что повторный запуск кода убирает группу доступа и роли в конфигураторе.

Программное включение/исключение пользователя в группы доступа. Правильное

Пока я разбирался с группами доступа, задал вопрос на Мисте и мне подсказали, как более просто включать пользователя в группы доступа.

Получается, можно указать просто название профиля доступа, а 1С сама сделает всю «грязную работу».

В функции ВключитьПрофильПользователю можно указывать идентификатор профиля, но к сожалению, предопределенный только один Администратор:

Поэтому для универсальности будем искать профиль по наименованию:

&НаСервере
Процедура ИзменитьПрофильГБНаСервере(Включить)
	ТекПользователь = Справочники.Пользователи.НайтиПоНаименованию("ГБ2");
	ТекПрофиль = Справочники.ПрофилиГруппДоступа.НайтиПоНаименованию("Главный бухгалтер");
	Если Включить Тогда
		УправлениеДоступом.ВключитьПрофильПользователю(ТекПользователь, ТекПрофиль);
	Иначе
		УправлениеДоступом.ВыключитьПрофильПользователю(ТекПользователь, ТекПрофиль);
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ВыключитьПрофильГБ(Команда)
	ИзменитьПрофильГБНаСервере(Ложь);
КонецПроцедуры

&НаКлиенте
Процедура ВключитьПрофильГБ(Команда)
	ИзменитьПрофильГБНаСервере(истина);
КонецПроцедуры

Проверки и тестирование показали, что нужные профили подключаются к пользователю и нужные роли создаются у пользователя информационной базы. При этом должны создаваться сами и группы, если их нет. Это упрощает нашу работу.

Программное создание пользователя и назначение ему прав доступа

Попробуем создать пользователя ГБ3 программно и назначить права доступа:

	//Вводные
	ИмяПользователя = "Главный бухгалтер 3";
	ИмяВходаПользователя = "ГБ3";
	Пароль = "123";
	ВходВПрограммуРазрешен = истина;
	АутентификацияСтандартная = истина;
	АутентификацияWindows = ложь;
	ЗапрещеноИзменятьПароль = ложь;
	ПоказыватьВСпискеВыбора = истина;
	
	
	
	//Создаем пользователя
	ОбновляемыеСвойства = Новый Структура();
	ОбновляемыеСвойства.Вставить("Действие", "Записать"); //Не уверен, что без этого будет работать
	ОбновляемыеСвойства.Вставить("ВходВПрограммуРазрешен", ВходВПрограммуРазрешен); 
	ОбновляемыеСвойства.Вставить("Имя", ИмяВходаПользователя); 
	ОбновляемыеСвойства.Вставить("ПолноеИмя", ИмяПользователя); 
	ОбновляемыеСвойства.Вставить("АутентификацияOpenID", ложь); 
	ОбновляемыеСвойства.Вставить("АутентификацияСтандартная", АутентификацияСтандартная); 
	ОбновляемыеСвойства.Вставить("АутентификацияWindows", АутентификацияWindows); 
	ОбновляемыеСвойства.Вставить("Пароль", Пароль); 
	ОбновляемыеСвойства.Вставить("ПарольУстановлен", истина); 
	ОбновляемыеСвойства.Вставить("ЗапрещеноИзменятьПароль", ЗапрещеноИзменятьПароль); 
	ОбновляемыеСвойства.Вставить("ПоказыватьВСпискеВыбора", ПоказыватьВСпискеВыбора); 
	
	
	ПользовательИБСуществует = ПользователиИнформационнойБазы.НайтиПоИмени(ИмяВходаПользователя) <> Неопределено;
	
	Пользователи.УстановитьСвойстваПользователяИБ(ИмяВходаПользователя, ОбновляемыеСвойства, НЕ ПользовательИБСуществует); //Создавать нового ставим всегда в Истина
	
	
	ТекПользователь = Справочники.Пользователи.НайтиПоНаименованию(ОбновляемыеСвойства.ПолноеИмя, истина);
	ПользовательСуществует = ЗначениеЗаполнено(ТекПользователь);
	
	//Записываем пользователя в 1С, если его еще нет в базе
	Если НЕ ПользовательСуществует Тогда
		Пользователь = Справочники.Пользователи.СоздатьЭлемент();	
		Пользователь.Наименование = ОбновляемыеСвойства.ПолноеИмя;
		Пользователь.ДополнительныеСвойства.Вставить(
		"ОписаниеПользователяИБ", ОбновляемыеСвойства);
		Пользователь.Записать();	
		ТекПользователь = Пользователь.Ссылка;
	КонецЕсли;

	ТекПрофиль = Справочники.ПрофилиГруппДоступа.НайтиПоНаименованию("Главный бухгалтер");
	УправлениеДоступом.ВключитьПрофильПользователю(ТекПользователь, ТекПрофиль);

Проверяем — пользователь и пользователь ИБ созданы:

Причем код можно запускать многократно и при этом обновляются свойства пользователя ИБ. Например, я при первом запуске не добавил свойство «Показывать в списке выбора», добавил и при втором запуске оно установилось.

Также устанавливаются роли и профили групп доступа.

Зайдем под этим пользователем в программу — все ОК, входит нормально.

Теперь настало время проверить, как код работает в Обновляторе. Код смотрите в конце статьи.

Скрипт отработал успешно:

Проверяем, при входе в базу пользователь есть, под пользователем в базу заходит:

В списке пользователей пользователь есть:

Права те, что заказывали:

Как быть с не упрощенными правами (ЗУП3)

Аналогично проверяем на ЗУП 3, получаем ошибку:

Опять берем монитор производительности и находим, что в группы добавление происходит в общей форме Пользователи, в процедуре «ВключитьИсключитьИзГруппы«:

К сожалению (и это недостаток 1С), эта процедура не вынесена в общий модуль, но она несложная и ее можно упрощенно вставить даже в наш код.

В итоге получился универсальный код, который работает и для упрощенной и для не упрощенной системы прав.

В упрощенной каждому профилю и пользователю ставится в соответствие персональная группа доступа. В не упрощенном в одну группу доступа можно включать несколько пользователей.

Проверяем — код в ЗУП3 тоже работает:

Итоговый код скрипта для Обновлятора

Важно! Если добавляете администратора и других пользователей, начинайте с администратора, т.к. иначе получите ошибку, что вы не создали администратора.

Вот какой код получился:

#use "updater1c"

// ****************************************************************************
// Переменные модуля
// ****************************************************************************

Перем errors;		// Признак того, что при выполнении скрипта были ошибки.
Перем updater;		// Обновлятор, через который мы получаем информацию о базе,
					// а также вызываем различные функции обновлятора.
Перем connector;	// Коннектор для подключения к базе.
Перем v8;			// Само подключение к базе через коннектор.

// ****************************************************************************
// Ваш код для выполнения обновлятором
// ****************************************************************************

Процедура Главная()

	//=========== НАЧАЛО КОДА ДОБАВЛЕНИЯ ПОЛЬЗОВАТЕЛЕЙ ==========

	
	Т = v8.NewObject("ТаблицаЗначений"); 
	Т.Колонки.Добавить("ПолноеИмя");
	Т.Колонки.Добавить("Имя");
	Т.Колонки.Добавить("Пароль");
	Т.Колонки.Добавить("ВходВПрограммуРазрешен");
	Т.Колонки.Добавить("АутентификацияСтандартная");
	Т.Колонки.Добавить("АутентификацияОС");
	Т.Колонки.Добавить("ПользовательОС");
	Т.Колонки.Добавить("ЗапрещеноИзменятьПароль");
	Т.Колонки.Добавить("ПоказыватьВСпискеВыбора");
	Т.Колонки.Добавить("Профили");
	
	//********** НАЧАЛО: ЗДЕСЬ ОПИСЫВАЕМ ПОЛЬЗОВАТЕЛЕЙ ***************
	
	Если v8.Метаданные.Имя = "БухгалтерияПредприятия" Тогда
	
		//ПОЛЬЗОВАТЕЛИ БП
	
		С = Т.Добавить(); 
		С.ПолноеИмя = "Бухгалтер 4";
		С.Имя = "Бух4";
		С.Пароль = "123";
		С.ВходВПрограммуРазрешен = истина;
		С.АутентификацияСтандартная = истина;
	//	С.АутентификацияОС = ложь;
	//	С.ПользовательОС = Неопределено;
		С.АутентификацияОС = истина;
		С.ПользовательОС = "\\test\test";
		С.ЗапрещеноИзменятьПароль = ложь;
		С.ПоказыватьВСпискеВыбора = истина;
		С.Профили = "Бухгалтер, Главный бухгалтер";
	
	ИначеЕсли v8.Метаданные.Имя = "ЗарплатаИУправлениеПерсоналом" Тогда
	
		//ПОЛЬЗОВАТЕЛИ ЗУП
		
		С = Т.Добавить(); 
		С.ПолноеИмя = "Кадровик 4";
		С.Имя = "Кадровик4";
		С.Пароль = "123";
		С.ВходВПрограммуРазрешен = истина;
		С.АутентификацияСтандартная = истина;
	//	С.АутентификацияОС = ложь;
	//	С.ПользовательОС = Неопределено;
		С.АутентификацияОС = истина;
		С.ПользовательОС = "\\test\test";
		С.ЗапрещеноИзменятьПароль = ложь;
		С.ПоказыватьВСпискеВыбора = истина;
		С.Профили = "Бухгалтер";
		
	КонецЕсли;
	
	
		
	//********** КОНЕЦ ОПИСАНИЯ ПОЛЬЗОВАТЕЛЕЙ ***************
	
	Для Каждого С ИЗ Т Цикл
		
		//Создаем пользователя
		ОбновляемыеСвойства = v8.NewObject("Структура");
		Для Инд = 1 По Т.Колонки.Количество() Цикл
			Колонка = Т.Колонки.Получить(Инд - 1);
			Зн = С.Получить(Инд - 1);
			Если Колонка.Имя = "Профили" Тогда
				Продолжить;
			КонецЕсли;
			Если Зн <> Неопределено Тогда
				ОбновляемыеСвойства.Вставить(Колонка.Имя, Зн);
			КонецЕсли;				
		КонецЦикла;
		ОбновляемыеСвойства.Вставить("Действие", "Записать"); //Не уверен, что без этого будет работать
		ОбновляемыеСвойства.Вставить("ПарольУстановлен", истина); 
		ОбновляемыеСвойства.Вставить("АутентификацияOpenID", ложь); 
		
		
		ПользовательИБСуществует = v8.ПользователиИнформационнойБазы.НайтиПоИмени(С.Имя) <> Неопределено;
		
		v8.Пользователи.УстановитьСвойстваПользователяИБ(С.Имя, ОбновляемыеСвойства, НЕ ПользовательИБСуществует); //Создавать нового ставим всегда в Истина
		
		Сообщить(?(ПользовательИБСуществует, "Добавлен", "Обновлен") + " пользователь ИБ: "  + С.Имя);
		
		ТекПользователь = v8.Справочники.Пользователи.НайтиПоНаименованию(ОбновляемыеСвойства.ПолноеИмя, истина);
		ПользовательСуществует = v8.ЗначениеЗаполнено(ТекПользователь);
		
		//Записываем пользователя в 1С, если его еще нет в базе
		Если НЕ ПользовательСуществует Тогда
			Пользователь = v8.Справочники.Пользователи.СоздатьЭлемент();	
			Пользователь.Наименование = ОбновляемыеСвойства.ПолноеИмя;
			Пользователь.ДополнительныеСвойства.Вставить(
			"ОписаниеПользователяИБ", ОбновляемыеСвойства);
			Пользователь.Записать();	
			ТекПользователь = Пользователь.Ссылка;
			Сообщить("Создан пользователь базы: "  + С.Имя);
		КонецЕсли;
	
		МассивПрофили = СтрРазделить(С.Профили, ",");
		Для Каждого ИмяПрофиля ИЗ МассивПрофили Цикл
			ИмяПрофиля = СокрЛП(ИмяПрофиля);
			Если v8.УправлениеДоступомСлужебный.УпрощенныйИнтерфейсНастройкиПравДоступа() Тогда
				ТекПрофиль = v8.Справочники.ПрофилиГруппДоступа.НайтиПоНаименованию(ИмяПрофиля);
				Если Не v8.ЗначениеЗаполнено(ТекПрофиль) Тогда
					Сообщить("Не найден профиль: " + ИмяПрофиля, СтатусСообщения.Важное);
					Продолжить;
				КонецЕсли;
				v8.УправлениеДоступом.ВключитьПрофильПользователю(ТекПользователь, ТекПрофиль);
			Иначе
				ТекГруппа = v8.Справочники.ГруппыДоступа.НайтиПоНаименованию(ИмяПрофиля);
				Если Не v8.ЗначениеЗаполнено(ТекГруппа) Тогда
					Сообщить("Не найдена группа: " + ИмяПрофиля, СтатусСообщения.Важное);
					Продолжить;
				КонецЕсли;
				
				//Код скопирован из типовой формы ПраваДоступа, несколько упрощен
				ГруппаДоступаОбъект = ТекГруппа.ПолучитьОбъект();
				Добавить = истина;
				Если Добавить Тогда
					Если ГруппаДоступаОбъект.Пользователи.Найти(ТекПользователь, "Пользователь") = Неопределено Тогда
						ГруппаДоступаОбъект.Пользователи.Добавить().Пользователь = ТекПользователь;
					КонецЕсли;
				Иначе
					СтрокаТЧ = ГруппаДоступаОбъект.Пользователи.Найти(ТекПользователь, "Пользователь");
					Если СтрокаТЧ <> Неопределено Тогда
						ГруппаДоступаОбъект.Пользователи.Удалить(СтрокаТЧ);
					КонецЕсли;
				КонецЕсли;
				ГруппаДоступаОбъект.Записать();
			КонецЕсли;
		КонецЦикла;
	КонецЦикла;
	
	//=========== КОНЕЦ КОДА ДОБАВЛЕНИЯ ПОЛЬЗОВАТЕЛЕЙ ==========
	

КонецПроцедуры


// ****************************************************************************
// Служебные процедуры
// ****************************************************************************

Процедура ПриНачалеРаботы()

	errors = Ложь;

	updater = Новый Updater1C;

	// Если в скрипте не планируется использовать
	// подключение к базе - просто закомментируйте
	// две нижние строки.
	connector = updater.CreateConnector();
	v8 = updater.BaseConnectNew(connector);
	
КонецПроцедуры

Процедура ПриОкончанииРаботы()

	Если v8 <> Неопределено Тогда
		Попытка
			ОсвободитьОбъект(v8);
			v8 = Неопределено;
		Исключение
		КонецПопытки;
	КонецЕсли;
	
	Если connector <> Неопределено Тогда
		Попытка
			ОсвободитьОбъект(connector);
			connector = Неопределено;
		Исключение
		КонецПопытки;
	КонецЕсли;
	
	Если updater <> Неопределено Тогда
		Попытка
			ОсвободитьОбъект(updater);
			updater = Неопределено;
		Исключение
		КонецПопытки;
	КонецЕсли;

	Если errors Тогда
		ЗавершитьРаботу(1);
	КонецЕсли;

КонецПроцедуры

// ****************************************************************************
// Инициализация и запуск скрипта
// ****************************************************************************

ПриНачалеРаботы();

Попытка	
	Главная();
	updater.КодПользователяВыполнился();
Исключение
	errors = Истина;
	Сообщить("" + ОписаниеОшибки() + "");
КонецПопытки;

ПриОкончанииРаботы();

Как видно, можно использовать один скрипт для разных баз, прописывая пользователей для разных типов баз (БП, ЗУП) отдельно.

Если в скрипте у Вас возникнут ошибки и вы захотите отладиться, это будет проблематично во внешнем соединении, поэтому просто удалите из кода все строки «v8.» и замените NewObject на Новый, тогда можно будет запускать код в обычной консоли кода.

Кто хочет посмотреть мою тестовую обработку, вот она:

Объем факт: 4 час.

fixin

Программирую на 1С с 1999 года. В 1С просто Гений. В 2020 году ушел из офиса на вольные хлеба фриланса. Принимаю заказы.

Читайте также:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *