Группы доступа / Форма элемента / Модуль формы

файл
///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2024, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

#Область ОписаниеПеременных

&НаКлиенте
Перем ВыборИПодборВнешнихПользователей;

#КонецОбласти

#Область ОбработчикиСобытийФормы

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	
	УстановитьУсловноеОформление();
	
	// СтандартныеПодсистемы.ПодключаемыеКоманды
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ПодключаемыеКоманды") Тогда
		МодульПодключаемыеКоманды = ОбщегоНазначения.ОбщийМодуль("ПодключаемыеКоманды");
		МодульПодключаемыеКоманды.ПриСозданииНаСервере(ЭтотОбъект);
	КонецЕсли;
	// Конец СтандартныеПодсистемы.ПодключаемыеКоманды
	
	// Подготовка вспомогательных данных.
	УправлениеДоступомСлужебный.ПриСозданииНаСервереФормыРедактированияРазрешенныхЗначений(ЭтотОбъект);
	
	НачальнаяНастройкаПриЧтенииИСоздании(Объект);
	
	СправочникВнешниеПользователиДоступен = ПравоДоступа(
		"Просмотр", Метаданные.Справочники.ВнешниеПользователи);
	
	СписокТиповПользователей.Добавить(Тип("СправочникСсылка.Пользователи"));
	СписокТиповПользователей.Добавить(Тип("СправочникСсылка.ВнешниеПользователи"));
	
	// Установка постоянной доступности свойств.
	
	// Определение необходимости настройки ограничений доступа.
	Если НЕ УправлениеДоступом.ОграничиватьДоступНаУровнеЗаписей() Тогда
		Элементы.Доступ.Видимость = Ложь;
	КонецЕсли;
	
	// Установка доступности при открытии формы только для просмотра.
	Элементы.ПользователиПодобрать.Доступность                = НЕ ТолькоПросмотр;
	Элементы.КонтекстноеМенюПользователиПодобрать.Доступность = НЕ ТолькоПросмотр;
	
	Если ОбщегоНазначения.РазделениеВключено()
	   И Объект.Ссылка = ГруппаДоступаАдминистраторы
	   И ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ПользователиВМоделиСервиса") Тогда
		
		МодульПользователиСлужебныйВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("ПользователиСлужебныйВМоделиСервиса");
		Попытка
			ДействияСПользователемСервиса = МодульПользователиСлужебныйВМоделиСервиса.ПолучитьДействияСПользователемСервиса(
				Неопределено, ДействияСПользователемСервиса);
			Если Не ДействияСПользователемСервиса.ИзменениеАдминистративногоДоступа Тогда
				ВызватьИсключение(НСтр("ru = 'Недостаточно прав доступа для изменения состава администраторов.'"), 
					КатегорияОшибки.НарушениеПравДоступа);
			КонецЕсли;
		Исключение
			Если Не Пользователи.ЭтоПолноправныйПользователь() Тогда
				ВызватьИсключение;
			КонецЕсли;
			ТолькоПросмотр = Истина;
			ОшибкаРаботыССервисом = ИнформацияОбОшибке();
		КонецПопытки;
		
	КонецЕсли;
	
	ОбновитьНазначение();
	
	ВыполненаПроцедураПриСозданииНаСервере = Истина;
	
	Если ОбщегоНазначения.ЭтоАвтономноеРабочееМесто() Тогда
		Если Не Объект.Ссылка = ГруппаДоступаАдминистраторы
		   И Не УправлениеДоступомСлужебный.ЭтоПрофильОткрытиеВнешнихОтчетовИОбработок(Объект.Профиль) Тогда
		
			ТолькоПросмотр = Истина;
		Иначе
			ЗапретитьИзменениеВсегоКромеСоставаУчастников();
		КонецЕсли;
	КонецЕсли;
	
	Элементы.ФормаЗаписатьИЗакрыть.Доступность = Не ТолькоПросмотр
		И ПравоДоступа("Редактирование", Метаданные.Справочники.ГруппыДоступа);
	
	Параметры.Свойство("ПерейтиКВидуДоступа",     ПерейтиКВидуДоступа);
	Параметры.Свойство("ПерейтиКЗначениюДоступа", ПерейтиКЗначениюДоступа);
	
КонецПроцедуры

&НаКлиенте
Процедура ПриОткрытии(Отказ)
	
	Если ОтветНаВопросПриОткрытииФормы = "УстановитьТолькоПросмотр" Тогда
		ОтветНаВопросПриОткрытииФормы = "";
		ТолькоПросмотр = Истина;
		Элементы.ФормаЗаписатьИЗакрыть.Доступность = Ложь;
	КонецЕсли;
	
	Если ОтветНаВопросПриОткрытииФормы = "УстановитьПрофильАдминистратор" Тогда
		ОтветНаВопросПриОткрытииФормы = Неопределено;
		Объект.Профиль = ПрофильАдминистратор;
		Модифицированность = Истина;
		
	ИначеЕсли Не ТолькоПросмотр
	        И Объект.Ссылка = ГруппаДоступаАдминистраторы
	        И Объект.Профиль <> ПрофильАдминистратор Тогда
		
		Отказ = Истина;
		ПоказатьВопрос(
			Новый ОписаниеОповещения("ПриОткрытииПослеПодтвержденияУстановкиПрофиляАдминистратор", ЭтотОбъект),
			НСтр("ru = 'У группы доступа Администраторы должен быть профиль Администратор.
			           |
			           |Установить профиль в группе доступа (нет - открыть только для просмотра)?'"),
			РежимДиалогаВопрос.ДаНет,
			,
			КодВозвратаДиалога.Нет);
	Иначе
		Если ОтветНаВопросПриОткрытииФормы = "ОбновитьСоставВидовДоступа" Тогда
			ОтветНаВопросПриОткрытииФормы = "";
			ОбновитьСоставВидовДоступа();
			ИзменилсяСоставВидовДоступаПриЧтении = Ложь;
			
		ИначеЕсли НЕ ТолькоПросмотр И ИзменилсяСоставВидовДоступаПриЧтении Тогда
			
			Отказ = Истина;
			ПоказатьВопрос(
				Новый ОписаниеОповещения("ПриОткрытииПослеПодтвержденияОбновленияВидовДоступа", ЭтотОбъект),
				НСтр("ru = 'Изменился состав видов доступа профиля этой группы доступа.
				           |
				           |Обновить виды доступа в группе доступа (нет - открыть только для просмотра)?'"),
				РежимДиалогаВопрос.ДаНет,
				,
				КодВозвратаДиалога.Нет);
		
		ИначеЕсли НЕ ТолькоПросмотр
			   И НЕ ЗначениеЗаполнено(Объект.Ссылка)
			   И ТипЗнч(ВладелецФормы) = Тип("ТаблицаФормы")
			   И ВладелецФормы.Родитель.Параметры.Свойство("Профиль") Тогда
			
			Если ЗначениеЗаполнено(ВладелецФормы.Родитель.Параметры.Профиль) Тогда
				Объект.Профиль = ВладелецФормы.Родитель.Параметры.Профиль;
				ПодключитьОбработчикОжидания("ОбработчикОжиданияПрофильПриИзменении", 0.1, Истина);
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	
	Если ПерейтиКЗначениюДоступа <> Неопределено Тогда
		ПодключитьОбработчикОжидания("ПерейтиКЗначениюДоступа", 0.1, Истина);
	КонецЕсли;
	
	// СтандартныеПодсистемы.ПодключаемыеКоманды
	Если ОбщегоНазначенияКлиент.ПодсистемаСуществует("СтандартныеПодсистемы.ПодключаемыеКоманды") Тогда
		МодульПодключаемыеКомандыКлиент = ОбщегоНазначенияКлиент.ОбщийМодуль("ПодключаемыеКомандыКлиент");
		МодульПодключаемыеКомандыКлиент.НачатьОбновлениеКоманд(ЭтотОбъект);
	КонецЕсли;
	// Конец СтандартныеПодсистемы.ПодключаемыеКоманды
	
	Если ОшибкаРаботыССервисом <> Неопределено Тогда
		ТекущаяОшибкаРаботыССервисом = ОшибкаРаботыССервисом;
		ОшибкаРаботыССервисом = Неопределено;
		СтандартныеПодсистемыКлиент.ВывестиИнформациюОбОшибке(ТекущаяОшибкаРаботыССервисом);
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ПриПовторномОткрытии()
	
	ПодключитьОбработчикОжидания("ПерейтиКЗначениюДоступа", 0.1, Истина);
	
КонецПроцедуры

&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
	
	Если НЕ ВыполненаПроцедураПриСозданииНаСервере Тогда
		Возврат;
	КонецЕсли;
	
	// СтандартныеПодсистемы.ПодключаемыеКоманды
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ПодключаемыеКоманды") Тогда
		МодульПодключаемыеКомандыКлиентСервер = ОбщегоНазначения.ОбщийМодуль("ПодключаемыеКомандыКлиентСервер");
		МодульПодключаемыеКомандыКлиентСервер.ОбновитьКоманды(ЭтотОбъект, Объект);
	КонецЕсли;
	// Конец СтандартныеПодсистемы.ПодключаемыеКоманды
	
	УправлениеДоступомСлужебный.ПриПовторномЧтенииНаСервереФормыРедактированияРазрешенныхЗначений(ЭтотОбъект, ТекущийОбъект);
	
	НачальнаяНастройкаПриЧтенииИСоздании(ТекущийОбъект);
	
	// СтандартныеПодсистемы.УправлениеДоступом
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.УправлениеДоступом") Тогда
		МодульУправлениеДоступом = ОбщегоНазначения.ОбщийМодуль("УправлениеДоступом");
		МодульУправлениеДоступом.ПриЧтенииНаСервере(ЭтотОбъект, ТекущийОбъект);
	КонецЕсли;
	// Конец СтандартныеПодсистемы.УправлениеДоступом

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

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

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

&НаСервере
Процедура ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
	
	УстановитьПривилегированныйРежим(Истина);
	
	ПрофильПомеченНаУдаление = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Объект.Профиль, "ПометкаУдаления");
	ПрофильПомеченНаУдаление = ?(ПрофильПомеченНаУдаление = Неопределено, Ложь, ПрофильПомеченНаУдаление);
	
	УстановитьПривилегированныйРежим(Ложь);
	
	Если НЕ Объект.ПометкаУдаления И ПрофильПомеченНаУдаление Тогда
		ПараметрыЗаписи.Вставить("ПредупредитьЧтоПрофильПомеченНаУдаление");
	КонецЕсли;
	
	УправлениеДоступомСлужебный.ПослеЗаписиНаСервереФормыРедактированияРазрешенныхЗначений(
		ЭтотОбъект, ТекущийОбъект, ПараметрыЗаписи);
		
	ОбновитьКартинкуКомментария(Элементы.СтраницаКомментарий, Объект.Комментарий);
	
	УправлениеДоступом.ПослеЗаписиНаСервере(ЭтотОбъект, ТекущийОбъект, ПараметрыЗаписи);
	
КонецПроцедуры

&НаКлиенте
Процедура ПослеЗаписи(ПараметрыЗаписи)
	
	Оповестить("Запись_ГруппыДоступа", Новый Структура, Объект.Ссылка);
	
	Если ПараметрыЗаписи.Свойство("ПредупредитьЧтоПрофильПомеченНаУдаление") Тогда
		
		ПоказатьПредупреждение(
			Новый ОписаниеОповещения("ПослеЗаписиЗавершение", ЭтотОбъект, ПараметрыЗаписи),
			НСтр("ru = 'Группа доступа не влияет на права участников
			           |так как ее профиль помечен на удаление.'"));
	Иначе
		ПослеЗаписиЗавершение(ПараметрыЗаписи);
	КонецЕсли;
	
	// СтандартныеПодсистемы.ПодключаемыеКоманды
	Если ОбщегоНазначенияКлиент.ПодсистемаСуществует("СтандартныеПодсистемы.ПодключаемыеКоманды") Тогда
		МодульПодключаемыеКомандыКлиент = ОбщегоНазначенияКлиент.ОбщийМодуль("ПодключаемыеКомандыКлиент");
		МодульПодключаемыеКомандыКлиент.ПослеЗаписи(ЭтотОбъект, Объект, ПараметрыЗаписи);
	КонецЕсли;
	// Конец СтандартныеПодсистемы.ПодключаемыеКоманды
	
КонецПроцедуры

&НаСервере
Процедура ОбработкаПроверкиЗаполненияНаСервере(Отказ, ПроверяемыеРеквизиты)
	
	ПроверенныеРеквизитыОбъекта = Новый Массив;
	Ошибки = Неопределено;
	
	// Проверка незаполненных и повторяющихся пользователей.
	ПроверенныеРеквизитыОбъекта.Добавить("Пользователи.Пользователь");
	ДеревоПользователейСтроки = РеквизитФормыВЗначение("ПользователиГруппы").Строки;
	КоличествоОшибок = ?(Ошибки = Неопределено, 0, Ошибки.Количество());
	
	// Подготовка данных для проверки соответствия типов объектов авторизации.
	Запрос = Новый Запрос;
	Запрос.УстановитьПараметр("Пользователи", ДеревоПользователейСтроки.ВыгрузитьКолонку("Пользователь"));
	Запрос.УстановитьПараметр("Родитель", Объект.Профиль);
	Запрос.Текст =
	"ВЫБРАТЬ
	|	ПрофилиГруппДоступаНазначение.ТипПользователей КАК ТипПользователей
	|ПОМЕСТИТЬ ПрофилиГруппДоступаНазначение
	|ИЗ
	|	Справочник.ПрофилиГруппДоступа.Назначение КАК ПрофилиГруппДоступаНазначение
	|ГДЕ
	|	ПрофилиГруппДоступаНазначение.Ссылка = &Родитель
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	ВнешниеПользователи.Ссылка КАК Ссылка,
	|	ЛОЖЬ КАК Служебный
	|ИЗ
	|	Справочник.ВнешниеПользователи КАК ВнешниеПользователи
	|ГДЕ
	|	НЕ ЛОЖЬ В
	|				(ВЫБРАТЬ ПЕРВЫЕ 1
	|					ЛОЖЬ
	|				ИЗ
	|					ПрофилиГруппДоступаНазначение КАК ПрофилиГруппДоступаНазначение
	|				ГДЕ
	|					ТИПЗНАЧЕНИЯ(ПрофилиГруппДоступаНазначение.ТипПользователей) = ТИПЗНАЧЕНИЯ(ВнешниеПользователи.ОбъектАвторизации))
	|	И ВнешниеПользователи.Ссылка В(&Пользователи)
	|
	|ОБЪЕДИНИТЬ ВСЕ
	|
	|ВЫБРАТЬ
	|	ГруппыВнешнихПользователейНазначение.Ссылка,
	|	ЛОЖЬ
	|ИЗ
	|	Справочник.ГруппыВнешнихПользователей.Назначение КАК ГруппыВнешнихПользователейНазначение
	|ГДЕ
	|	НЕ ЛОЖЬ В
	|				(ВЫБРАТЬ ПЕРВЫЕ 1
	|					ЛОЖЬ
	|				ИЗ
	|					ПрофилиГруппДоступаНазначение КАК ПрофилиГруппДоступаНазначение
	|				ГДЕ
	|					ТИПЗНАЧЕНИЯ(ПрофилиГруппДоступаНазначение.ТипПользователей) = ТИПЗНАЧЕНИЯ(ГруппыВнешнихПользователейНазначение.ТипПользователей))
	|	И ГруппыВнешнихПользователейНазначение.Ссылка В(&Пользователи)
	|
	|ОБЪЕДИНИТЬ ВСЕ
	|
	|ВЫБРАТЬ
	|	Пользователи.Ссылка,
	|	Пользователи.Служебный
	|ИЗ
	|	Справочник.Пользователи КАК Пользователи
	|ГДЕ
	|	(Пользователи.Служебный
	|			ИЛИ НЕ ЛОЖЬ В
	|					(ВЫБРАТЬ ПЕРВЫЕ 1
	|						ЛОЖЬ
	|					ИЗ
	|						ПрофилиГруппДоступаНазначение КАК ПрофилиГруппДоступаНазначение
	|					ГДЕ
	|						ТИПЗНАЧЕНИЯ(ПрофилиГруппДоступаНазначение.ТипПользователей) = ТИП(Справочник.Пользователи)))
	|	И Пользователи.Ссылка В(&Пользователи)
	|
	|ОБЪЕДИНИТЬ ВСЕ
	|
	|ВЫБРАТЬ
	|	ГруппыПользователей.Ссылка,
	|	ЛОЖЬ
	|ИЗ
	|	Справочник.ГруппыПользователей КАК ГруппыПользователей
	|ГДЕ
	|	НЕ ЛОЖЬ В
	|				(ВЫБРАТЬ ПЕРВЫЕ 1
	|					ЛОЖЬ
	|				ИЗ
	|					ПрофилиГруппДоступаНазначение КАК ПрофилиГруппДоступаНазначение
	|				ГДЕ
	|					ТИПЗНАЧЕНИЯ(ПрофилиГруппДоступаНазначение.ТипПользователей) = ТИП(Справочник.Пользователи))
	|	И ГруппыПользователей.Ссылка В(&Пользователи)";
	
	УстановитьПривилегированныйРежим(Истина);
	НедопустимыеПользователи = Запрос.Выполнить().Выгрузить();
	УстановитьПривилегированныйРежим(Ложь);
	НачалоДня = НачалоДня(ТекущаяДатаСеанса());
	
	Для Каждого ТекущаяСтрока Из ДеревоПользователейСтроки Цикл
		НомерСтроки = ДеревоПользователейСтроки.Индекс(ТекущаяСтрока);
		Участник = ТекущаяСтрока.Пользователь;
		СрокДействия = ТекущаяСтрока.СрокДействия;
		
		// Проверка заполнения значения.
		Если Не ЗначениеЗаполнено(Участник) Тогда
			ОбщегоНазначенияКлиентСервер.ДобавитьОшибкуПользователю(Ошибки,
				"ПользователиГруппы[%1].Пользователь",
				УточнитьСообщение(НСтр("ru = 'Пользователь не выбран.'"), Участник),
				"ПользователиГруппы",
				НомерСтроки,
				УточнитьСообщение(НСтр("ru = 'Пользователь в строке %1 не выбран.'"), Участник));
		КонецЕсли;
		Если ЗначениеЗаполнено(СрокДействия) И СрокДействия <= НачалоДня Тогда
			Срок = Формат(СрокДействия, НСтр("ru = 'ДЛФ=D'"));
			ОбщегоНазначенияКлиентСервер.ДобавитьОшибкуПользователю(Ошибки,
				"ПользователиГруппы[%1].Пользователь",
				УточнитьСообщение(НСтр("ru = 'Срок участия %2 должен быть до завтра или более.'"), Срок),
				"ПользователиГруппы",
				НомерСтроки,
				УточнитьСообщение(НСтр("ru = 'Срок участия %2 в строке %1 должен быть до завтра или более.'"), Срок));
		КонецЕсли;
		Если Не ЗначениеЗаполнено(Участник) Тогда
			Продолжить;
		КонецЕсли;
		
		// Проверка наличия повторяющихся значений.
		НайденныеЗначения = ДеревоПользователейСтроки.НайтиСтроки(
			Новый Структура("Пользователь", ТекущаяСтрока.Пользователь));
		
		Если НайденныеЗначения.Количество() > 1 Тогда
			
			Если ТипЗнч(ТекущаяСтрока.Пользователь) = Тип("СправочникСсылка.Пользователи") Тогда
				ТекстДляОднойОшибки      = НСтр("ru = 'Пользователь ""%2"" повторяется.'");
				ТекстДляНесколькихОшибок = НСтр("ru = 'Пользователь ""%2"" в строке %1 повторяется.'");
				
			ИначеЕсли ТипЗнч(ТекущаяСтрока.Пользователь) = Тип("СправочникСсылка.ВнешниеПользователи") Тогда
				ТекстДляОднойОшибки      = НСтр("ru = 'Внешний пользователь ""%2"" повторяется.'");
				ТекстДляНесколькихОшибок = НСтр("ru = 'Внешний пользователь ""%2"" в строке %1 повторяется.'");
				
			ИначеЕсли ТипЗнч(ТекущаяСтрока.Пользователь) = Тип("СправочникСсылка.ГруппыПользователей") Тогда
				ТекстДляОднойОшибки      = НСтр("ru = 'Группа пользователей ""%2"" повторяется.'");
				ТекстДляНесколькихОшибок = НСтр("ru = 'Группа пользователей ""%2"" в строке %1 повторяется.'");
			Иначе
				ТекстДляОднойОшибки      = НСтр("ru = 'Группа внешних пользователей ""%2"" повторяется.'");
				ТекстДляНесколькихОшибок = НСтр("ru = 'Группа внешних пользователей ""%2"" в строке %1 повторяется.'");
			КонецЕсли;
			
			ОбщегоНазначенияКлиентСервер.ДобавитьОшибкуПользователю(Ошибки,
				"ПользователиГруппы[%1].Пользователь",
				УточнитьСообщение(ТекстДляОднойОшибки, Участник),
				"ПользователиГруппы",
				НомерСтроки,
				УточнитьСообщение(ТекстДляНесколькихОшибок, Участник));
		КонецЕсли;
		
		// Проверка наличия только пользователей в предопределенной группе Администраторы.
		Если Объект.Ссылка = ГруппаДоступаАдминистраторы
		   И ТипЗнч(ТекущаяСтрока.Пользователь) <> Тип("СправочникСсылка.Пользователи") Тогда
			
			Если ТипЗнч(ТекущаяСтрока.Пользователь) = Тип("СправочникСсылка.ВнешниеПользователи") Тогда
				ТекстДляОднойОшибки      = НСтр("ru = 'Внешний пользователь ""%2"" недопустим в предопределенной группе доступа Администраторы.'");
				ТекстДляНесколькихОшибок = НСтр("ru = 'Внешний пользователь ""%2"" в строке %1 недопустим в предопределенной группе доступа Администраторы.'");
				
			ИначеЕсли ТипЗнч(ТекущаяСтрока.Пользователь) = Тип("СправочникСсылка.ГруппыПользователей") Тогда
				ТекстДляОднойОшибки      = НСтр("ru = 'Группа пользователей ""%2"" недопустима в предопределенной группе доступа Администраторы.'");
				ТекстДляНесколькихОшибок = НСтр("ru = 'Группа пользователей ""%2"" в строке %1 недопустима в предопределенной группе доступа Администраторы.'");
			Иначе
				ТекстДляОднойОшибки      = НСтр("ru = 'Группа внешних пользователей ""%2"" недопустима в предопределенной группе доступа Администраторы.'");
				ТекстДляНесколькихОшибок = НСтр("ru = 'Группа внешних пользователей ""%2"" в строке %1 недопустима в предопределенной группе доступа Администраторы.'");
			КонецЕсли;
			
			ОбщегоНазначенияКлиентСервер.ДобавитьОшибкуПользователю(Ошибки,
				"ПользователиГруппы[%1].Пользователь",
				УточнитьСообщение(ТекстДляОднойОшибки, Участник),
				"ПользователиГруппы",
				НомерСтроки,
				УточнитьСообщение(ТекстДляНесколькихОшибок, Участник));
		КонецЕсли;
		
		НедопустимыйПользователь = НедопустимыеПользователи.Найти(ТекущаяСтрока.Пользователь, "Ссылка");
		Если НедопустимыйПользователь <> Неопределено Тогда
			
			Если ТипЗнч(ТекущаяСтрока.Пользователь) = Тип("СправочникСсылка.Пользователи") Тогда
				Если НедопустимыйПользователь.Служебный Тогда
					ТекстДляОднойОшибки      = НСтр("ru = 'Права (роли) служебного пользователя ""%2"" не настраиваются интерактивно.'");
					ТекстДляНесколькихОшибок = НСтр("ru = 'Права (роли) служебного пользователя ""%2"" в строке %1 не настраиваются интерактивно.'");
				Иначе
					ТекстДляОднойОшибки      = НСтр("ru = 'Пользователь ""%2"" недопустим для указанного типа участников.'");
					ТекстДляНесколькихОшибок = НСтр("ru = 'Пользователь ""%2"" в строке %1 недопустим для указанного типа участников.'");
				КонецЕсли;
			ИначеЕсли ТипЗнч(ТекущаяСтрока.Пользователь) = Тип("СправочникСсылка.ГруппыПользователей") Тогда
				ТекстДляОднойОшибки      = НСтр("ru = 'Группа пользователей ""%2"" недопустима для указанного типа участников.'");
				ТекстДляНесколькихОшибок = НСтр("ru = 'Группа пользователей ""%2"" в строке %1 недопустима для указанного типа участников.'");
			ИначеЕсли ТипЗнч(ТекущаяСтрока.Пользователь) = Тип("СправочникСсылка.ВнешниеПользователи") Тогда
				ТекстДляОднойОшибки      = НСтр("ru = 'Внешний пользователь ""%2"" недопустим для указанного типа участников.'");
				ТекстДляНесколькихОшибок = НСтр("ru = 'Внешний пользователь ""%2"" в строке %1 недопустим для указанного типа участников.'");
			Иначе // Группа внешних пользователей.
				ТекстДляОднойОшибки      = НСтр("ru = 'Группа внешних пользователей ""%2"" недопустима для указанного типа участников.'");
				ТекстДляНесколькихОшибок = НСтр("ru = 'Группа внешних пользователей ""%2"" в строке %1 недопустима для указанного типа участников.'");
			КонецЕсли;
			
			ОбщегоНазначенияКлиентСервер.ДобавитьОшибкуПользователю(Ошибки,
				"ПользователиГруппы[%1].Пользователь",
				УточнитьСообщение(ТекстДляОднойОшибки, Участник),
				"ПользователиГруппы",
				НомерСтроки,
				УточнитьСообщение(ТекстДляНесколькихОшибок, Участник));
			
		КонецЕсли;
		
	КонецЦикла;
	
	Если НЕ ОбщегоНазначения.РазделениеВключено()
		И Объект.Ссылка = ГруппаДоступаАдминистраторы Тогда
		
		ОписаниеОшибки = "";
		УправлениеДоступомСлужебный.ПроверитьНаличиеПользователяИБВГруппеДоступаАдминистраторы(
			ПользователиГруппы.ПолучитьЭлементы(), ОписаниеОшибки);
		
		Если ЗначениеЗаполнено(ОписаниеОшибки) Тогда
			ОбщегоНазначенияКлиентСервер.ДобавитьОшибкуПользователю(Ошибки,
				"ПользователиГруппы", ОписаниеОшибки, "");
		КонецЕсли;
	КонецЕсли;
	
	// Проверка незаполненных и повторяющихся значений доступа.
	ПропуститьПроверкуВидовИЗначений = Ложь;
	Если КоличествоОшибок <> ?(Ошибки = Неопределено, 0, Ошибки.Количество()) Тогда
		ПропуститьПроверкуВидовИЗначений = Истина;
		Элементы.ПользователиИДоступ.ТекущаяСтраница = Элементы.ПользователиГруппы;
	КонецЕсли;
	
	УправлениеДоступомСлужебныйКлиентСервер.ОбработкаПроверкиЗаполненияНаСервереФормыРедактированияРазрешенныхЗначений(
		ЭтотОбъект, Отказ, ПроверенныеРеквизитыОбъекта, Ошибки, ПропуститьПроверкуВидовИЗначений);
	
	ОбщегоНазначенияКлиентСервер.СообщитьОшибкиПользователю(Ошибки, Отказ);
	
	ПроверяемыеРеквизиты.Удалить(ПроверяемыеРеквизиты.Найти("Объект"));
	ТекущийОбъект = РеквизитФормыВЗначение("Объект");
	
	ТекущийОбъект.ДополнительныеСвойства.Вставить(
		"ПроверенныеРеквизитыОбъекта", ПроверенныеРеквизитыОбъекта);
	
	Если НЕ ТекущийОбъект.ПроверитьЗаполнение() Тогда
		Отказ = Истина;
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти

#Область ОбработчикиСобытийЭлементовШапкиФормы

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

&НаКлиенте
Процедура ПользовательВладелецНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	
	СтандартнаяОбработка = Ложь;
	
КонецПроцедуры

&НаКлиенте
Процедура КомментарийПриИзменении(Элемент)
	
	ОбновитьКартинкуКомментария(Элементы.СтраницаКомментарий, Объект.Комментарий);
	
КонецПроцедуры

#КонецОбласти

#Область ОбработчикиСобытийЭлементовТаблицыФормыПользователи

&НаКлиенте
Процедура ПользователиПриИзменении(Элемент)
	
	Модифицированность = Истина;
	
КонецПроцедуры

&НаКлиенте
Процедура ПользователиПередНачаломДобавления(Элемент, Отказ, Копирование, Родитель, Группа)
	
	Если Элемент.Отображение = ОтображениеТаблицы.Список Тогда
		Если Копирование Тогда
			Отказ = Истина;
			Элементы.Пользователи.ДобавитьСтроку();
		КонецЕсли;
		Возврат;
	КонецЕсли;
	
	Если Копирование Тогда
		
		Если Элемент.ТекущиеДанные.ПолучитьРодителя() <> Неопределено Тогда
			Отказ = Истина;
			
			Элементы.Пользователи.ТекущаяСтрока =
				Элемент.ТекущиеДанные.ПолучитьРодителя().ПолучитьИдентификатор();
			
			Элементы.Пользователи.СкопироватьСтроку();
		КонецЕсли;
		
	ИначеЕсли Элементы.Пользователи.ТекущаяСтрока <> Неопределено Тогда
		Отказ = Истина;
		Элементы.Пользователи.СкопироватьСтроку();
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ПользователиПередНачаломИзменения(Элемент, Отказ)
	
	Если Элемент.ТекущиеДанные.ПолучитьРодителя() <> Неопределено Тогда
		Отказ = Истина;
		
		Элементы.Пользователи.ТекущаяСтрока =
			Элемент.ТекущиеДанные.ПолучитьРодителя().ПолучитьИдентификатор();
		
		Элементы.Пользователи.ИзменитьСтроку();
	КонецЕсли;
	
КонецПроцедуры

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

&НаКлиенте
Процедура ПользователиПриНачалеРедактирования(Элемент, НоваяСтрока, Копирование)
	
	Если Копирование Тогда
		Элемент.ТекущиеДанные.Пользователь = Неопределено;
	КонецЕсли;
	
	Если Элемент.ТекущиеДанные.Пользователь = Неопределено Тогда
		Элемент.ТекущиеДанные.НомерКартинки = -1;
		Элемент.ТекущиеДанные.Пользователь = ПредопределенноеЗначение(
			"Справочник.Пользователи.ПустаяСсылка");
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ПользователиПриОкончанииРедактирования(Элемент, НоваяСтрока, ОтменаРедактирования)
	
	Если НоваяСтрока
	   И Элемент.ТекущиеДанные <> Неопределено
	   И Элемент.ТекущиеДанные.Пользователь = ПредопределенноеЗначение(
	     	"Справочник.Пользователи.ПустаяСсылка") Тогда
		
		Элемент.ТекущиеДанные.Пользователь = Неопределено;
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ПользователиОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
	
	Если РежимПодбора Тогда
		ТипПользователя = ?(ВыборИПодборВнешнихПользователей,
			Новый ОписаниеТипов("СправочникСсылка.ВнешниеПользователи,СправочникСсылка.ГруппыВнешнихПользователей"),
			Новый ОписаниеТипов("СправочникСсылка.Пользователи,СправочникСсылка.ГруппыПользователей"));
		ЭлементыПользователей = ПользователиГруппы.ПолучитьЭлементы();
		Индекс = ЭлементыПользователей.Количество();
		Пока Индекс > 0 Цикл
			Индекс = Индекс - 1;
			ТекущийПользователь = ЭлементыПользователей[Индекс].Пользователь;
			Если Не ЗначениеЗаполнено(ТекущийПользователь)
			 Или ТипПользователя.СодержитТип(ТипЗнч(ТекущийПользователь))
			   И ВыбранноеЗначение.Найти(ТекущийПользователь) = Неопределено Тогда
				ЭлементыПользователей.Удалить(Индекс);
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
	ИзмененныеСтроки = Новый Массив;
	
	Если ТипЗнч(ВыбранноеЗначение) = Тип("Массив") Тогда
		Для Каждого Значение Из ВыбранноеЗначение Цикл
			ЗначениеНайдено = Ложь;
			Для Каждого Элемент Из ПользователиГруппы.ПолучитьЭлементы() Цикл
				Если Элемент.Пользователь = Значение Тогда
					ЗначениеНайдено = Истина;
					Прервать;
				КонецЕсли;
			КонецЦикла;
			Если Не ЗначениеНайдено Тогда
				НовыйЭлемент = ПользователиГруппы.ПолучитьЭлементы().Добавить();
				НовыйЭлемент.Пользователь = Значение;
				ИзмененныеСтроки.Добавить(НовыйЭлемент.ПолучитьИдентификатор());
			КонецЕсли;
		КонецЦикла;
		
	ИначеЕсли Элемент.ТекущиеДанные.Пользователь <> ВыбранноеЗначение Тогда
		Элемент.ТекущиеДанные.Пользователь = ВыбранноеЗначение;
		ИзмененныеСтроки.Добавить(Элемент.ТекущаяСтрока);
	КонецЕсли;
	
	Если РежимПодбора Тогда
		ТипВнешнийПользователь = Новый ОписаниеТипов("СправочникСсылка.ВнешниеПользователи,
			|СправочникСсылка.ГруппыВнешнихПользователей");
		Список = Новый СписокЗначений;
		ЭлементыПользователей = ПользователиГруппы.ПолучитьЭлементы();
		Для Каждого Элемент Из ЭлементыПользователей Цикл
			Список.Добавить(Элемент,
				?(ТипВнешнийПользователь.СодержитТип(ТипЗнч(Элемент.Пользователь)), "2", "1")
					+ Строка(Элемент.Пользователь));
		КонецЦикла;
		Список.СортироватьПоПредставлению();
		НовыйИндекс = 0;
		Для Каждого ЭлементСписка Из Список Цикл
			СтарыйИндекс = ЭлементыПользователей.Индекс(ЭлементСписка.Значение);
			ЭлементыПользователей.Сдвинуть(СтарыйИндекс, НовыйИндекс - СтарыйИндекс);
			НовыйИндекс = НовыйИндекс + 1;
		КонецЦикла;
	КонецЕсли;
	
	Если ИзмененныеСтроки.Количество() > 0 Тогда
		ОбновленныеСтроки = Неопределено;
		ОбновитьПользователейГрупп(ИзмененныеСтроки, ОбновленныеСтроки);
		Для каждого ИдентификаторСтроки Из ОбновленныеСтроки Цикл
			Элементы.Пользователи.Развернуть(ИдентификаторСтроки);
		КонецЦикла;
		Модифицированность = Истина;
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ПользователиПослеУдаления(Элемент)
	
	// Установка отображения дерева.
	ЕстьВложенные = Ложь;
	Для каждого Элемент Из ПользователиГруппы.ПолучитьЭлементы() Цикл
		Если Элемент.ПолучитьЭлементы().Количество() > 0 Тогда
			ЕстьВложенные = Истина;
			Прервать;
		КонецЕсли;
	КонецЦикла;
	
	Элементы.Пользователи.Отображение =
		?(ЕстьВложенные, ОтображениеТаблицы.Дерево, ОтображениеТаблицы.Список);
	
КонецПроцедуры

&НаКлиенте
Процедура ПользовательПриИзменении(Элемент)
	
	Если ЗначениеЗаполнено(Элементы.Пользователи.ТекущиеДанные.Пользователь) Тогда
		ОбновитьПользователейГрупп(Элементы.Пользователи.ТекущаяСтрока);
		Элементы.Пользователи.Развернуть(Элементы.Пользователи.ТекущаяСтрока);
	Иначе
		Элементы.Пользователи.ТекущиеДанные.НомерКартинки = -1;
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ПользовательНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	
	СтандартнаяОбработка = Ложь;
	
	ВыбратьПодобратьПользователей(Ложь);
	РежимПодбора = Ложь;
	
КонецПроцедуры

&НаКлиенте
Процедура ПользовательОчистка(Элемент, СтандартнаяОбработка)
	
	СтандартнаяОбработка = Ложь;
	
	Элементы.Пользователи.ТекущиеДанные.НомерКартинки = -1;
	Элементы.Пользователи.ТекущиеДанные.Пользователь  = ПредопределенноеЗначение(
		"Справочник.Пользователи.ПустаяСсылка");
	
КонецПроцедуры

&НаКлиенте
Процедура ПользовательОкончаниеВводаТекста(Элемент, Текст, ДанныеВыбора, СтандартнаяОбработка)
	
	Если ЗначениеЗаполнено(Текст) Тогда
		СтандартнаяОбработка = Ложь;
		Если Объект.Ссылка = ГруппаДоступаАдминистраторы Тогда
			ДанныеВыбора = УправлениеДоступомСлужебныйВызовСервера.СформироватьДанныеВыбораПользователя(
				Текст, Ложь, Ложь);
		Иначе
			ДанныеВыбора = УправлениеДоступомСлужебныйВызовСервера.СформироватьДанныеВыбораПользователя(
				Текст);
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ПользовательАвтоПодбор(Элемент, Текст, ДанныеВыбора, Ожидание, СтандартнаяОбработка)
	
	Если ЗначениеЗаполнено(Текст) Тогда
		СтандартнаяОбработка = Ложь;
		Если Объект.Ссылка = ГруппаДоступаАдминистраторы Тогда
			ДанныеВыбора = УправлениеДоступомСлужебныйВызовСервера.СформироватьДанныеВыбораПользователя(
				Текст, Ложь, Ложь);
		Иначе
			ДанныеВыбора = УправлениеДоступомСлужебныйВызовСервера.СформироватьДанныеВыбораПользователя(
				Текст);
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти

#Область ОбработчикиСобытийЭлементовТаблицыФормыВидыДоступа

&НаКлиенте
Процедура ВидыДоступаВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
	
	Если Не ТолькоПросмотр
	   И Не Элементы.Доступ.ТолькоПросмотр Тогда
		
		Элементы.ВидыДоступа.ИзменитьСтроку();
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ВидыДоступаПриАктивизацииСтроки(Элемент)
	
	УправлениеДоступомСлужебныйКлиент.ВидыДоступаПриАктивизацииСтроки(
		ЭтотОбъект, Элемент);
	
КонецПроцедуры

&НаКлиенте
Процедура ВидыДоступаПриАктивизацииЯчейки(Элемент)
	
	УправлениеДоступомСлужебныйКлиент.ВидыДоступаПриАктивизацииЯчейки(
		ЭтотОбъект, Элемент);
	
КонецПроцедуры

&НаКлиенте
Процедура ВидыДоступаПриНачалеРедактирования(Элемент, НоваяСтрока, Копирование)
	
	УправлениеДоступомСлужебныйКлиент.ВидыДоступаПриНачалеРедактирования(
		ЭтотОбъект, Элемент, НоваяСтрока, Копирование);
	
КонецПроцедуры

&НаКлиенте
Процедура ВидыДоступаПриОкончанииРедактирования(Элемент, НоваяСтрока, ОтменаРедактирования)
	
	УправлениеДоступомСлужебныйКлиент.ВидыДоступаПриОкончанииРедактирования(
		ЭтотОбъект, Элемент, НоваяСтрока, ОтменаРедактирования);
	
КонецПроцедуры

#Область ОбработчикиСобытийЭлементаВсеРазрешеныПредставлениеТаблицыФормыВидыДоступа

&НаКлиенте
Процедура ВидыДоступаВсеРазрешеныПредставлениеПриИзменении(Элемент)
	
	УправлениеДоступомСлужебныйКлиент.ВидыДоступаВсеРазрешеныПредставлениеПриИзменении(
		ЭтотОбъект, Элемент);
	
КонецПроцедуры

&НаКлиенте
Процедура ВидыДоступаВсеРазрешеныПредставлениеОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
	
	УправлениеДоступомСлужебныйКлиент.ВидыДоступаВсеРазрешеныПредставлениеОбработкаВыбора(
		ЭтотОбъект, Элемент, ВыбранноеЗначение, СтандартнаяОбработка);
	
КонецПроцедуры

#КонецОбласти

#КонецОбласти

#Область ОбработчикиСобытийЭлементовТаблицыФормыЗначенияДоступа

&НаКлиенте
Процедура ЗначенияДоступаПриИзменении(Элемент)
	
	УправлениеДоступомСлужебныйКлиент.ЗначенияДоступаПриИзменении(
		ЭтотОбъект, Элемент);
	
КонецПроцедуры

&НаКлиенте
Процедура ЗначенияДоступаПриНачалеРедактирования(Элемент, НоваяСтрока, Копирование)
	
	УправлениеДоступомСлужебныйКлиент.ЗначенияДоступаПриНачалеРедактирования(
		ЭтотОбъект, Элемент, НоваяСтрока, Копирование);
	
КонецПроцедуры

&НаКлиенте
Процедура ЗначенияДоступаПриОкончанииРедактирования(Элемент, НоваяСтрока, ОтменаРедактирования)
	
	УправлениеДоступомСлужебныйКлиент.ЗначенияДоступаПриОкончанииРедактирования(
		ЭтотОбъект, Элемент, НоваяСтрока, ОтменаРедактирования);
	
КонецПроцедуры

&НаКлиенте
Процедура ЗначенияДоступаОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
	
	УправлениеДоступомСлужебныйКлиент.ЗначенияДоступаОбработкаВыбора(
		ЭтотОбъект, Элемент, ВыбранноеЗначение, СтандартнаяОбработка);
	
КонецПроцедуры

&НаКлиенте
Процедура ЗначениеДоступаНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	
	УправлениеДоступомСлужебныйКлиент.ЗначениеДоступаНачалоВыбора(
		ЭтотОбъект, Элемент, ДанныеВыбора, СтандартнаяОбработка);
	
КонецПроцедуры

&НаКлиенте
Процедура ЗначениеДоступаОчистка(Элемент, СтандартнаяОбработка)
	
	УправлениеДоступомСлужебныйКлиент.ЗначениеДоступаОчистка(
		ЭтотОбъект, Элемент, СтандартнаяОбработка);
	
КонецПроцедуры

&НаКлиенте
Процедура ЗначениеДоступаАвтоПодбор(Элемент, Текст, ДанныеВыбора, Ожидание, СтандартнаяОбработка)
	
	УправлениеДоступомСлужебныйКлиент.ЗначениеДоступаАвтоПодбор(
		ЭтотОбъект, Элемент, Текст, ДанныеВыбора, Ожидание, СтандартнаяОбработка);
	
КонецПроцедуры

&НаКлиенте
Процедура ЗначениеДоступаОкончаниеВводаТекста(Элемент, Текст, ДанныеВыбора, СтандартнаяОбработка)
	
	УправлениеДоступомСлужебныйКлиент.ЗначениеДоступаОкончаниеВводаТекста(
		ЭтотОбъект, Элемент, Текст, ДанныеВыбора, СтандартнаяОбработка);
	
КонецПроцедуры

#КонецОбласти

#Область ОбработчикиКомандФормы

&НаКлиенте
Процедура ЗаписатьИЗакрыть(Команда)
	
	Записать(Новый Структура("ЗаписатьИЗакрыть"));
	
КонецПроцедуры

&НаКлиенте
Процедура Подобрать(Команда)
	
	ВыбратьПодобратьПользователей(Истина);
	РежимПодбора = Истина;
	
КонецПроцедуры

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

&НаКлиенте
Процедура ПодобратьЗначенияДоступа(Команда)
	
	УправлениеДоступомСлужебныйКлиент.ЗначенияДоступаПодобрать(ЭтотОбъект);
	
КонецПроцедуры

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

&НаСервере
Процедура УстановитьУсловноеОформление()
	
	УсловноеОформление.Элементы.Очистить();
	
	Элемент = УсловноеОформление.Элементы.Добавить();
	
	ПолеЭлемента = Элемент.Поля.Элементы.Добавить();
	ПолеЭлемента.Поле = Новый ПолеКомпоновкиДанных(Элементы.СрокДействия.Имя);
	
	ОтборЭлемента = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ОтборЭлемента.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ПользователиГруппы.Уровень");
	ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
	ОтборЭлемента.ПравоеЗначение = 1;
	
	Элемент.Оформление.УстановитьЗначениеПараметра("Видимость", Ложь);
	
КонецПроцедуры

// Продолжение обработчика события ПриОткрытии.
&НаКлиенте
Процедура ПриОткрытииПослеПодтвержденияУстановкиПрофиляАдминистратор(Ответ, Контекст) Экспорт
	
	Если Ответ = КодВозвратаДиалога.Да Тогда
		ОтветНаВопросПриОткрытииФормы = "УстановитьПрофильАдминистратор";
	Иначе
		ОтветНаВопросПриОткрытииФормы = "УстановитьТолькоПросмотр";
	КонецЕсли;
	
	Открыть();
	
КонецПроцедуры

// Продолжение обработчика события ПриОткрытии.
&НаКлиенте
Процедура ПриОткрытииПослеПодтвержденияОбновленияВидовДоступа(Ответ, Контекст) Экспорт
	
	Если Ответ = КодВозвратаДиалога.Да Тогда
		ОтветНаВопросПриОткрытииФормы = "ОбновитьСоставВидовДоступа";
	Иначе
		ОтветНаВопросПриОткрытииФормы = "УстановитьТолькоПросмотр";
	КонецЕсли;
	
	Открыть();
	
КонецПроцедуры

// Продолжение обработчика события ПередЗаписью.
&НаКлиенте
Процедура ПередЗаписьюПродолжение(НовыйПарольПользователяСервиса, ПараметрыЗаписи) Экспорт
	
	Если НовыйПарольПользователяСервиса = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	ПарольПользователяСервиса = НовыйПарольПользователяСервиса;
	
	Попытка
		Записать(ПараметрыЗаписи);
	Исключение
		ПарольПользователяСервиса = Неопределено;
		ВызватьИсключение;
	КонецПопытки;
	
КонецПроцедуры

// Продолжение обработчика события ПослеЗаписи.
&НаКлиенте
Процедура ПослеЗаписиЗавершение(ПараметрыЗаписи) Экспорт
	
	Если ПараметрыЗаписи.Свойство("ЗаписатьИЗакрыть") Тогда
		ПодключитьОбработчикОжидания("ЗакрытьФорму", 0.1, Истина);
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ЗакрытьФорму()
	
	Закрыть();
	
КонецПроцедуры

&НаКлиенте
Процедура ОбработчикОжиданияПрофильПриИзменении()
	
	ПрофильПриИзмененииНаСервере();
	
КонецПроцедуры

&НаСервере
Процедура ЗапретитьИзменениеВсегоКромеСоставаУчастников()
	
	Элементы.Наименование.ТолькоПросмотр          = Истина;
	Элементы.Родитель.Видимость                   = Ложь;
	Элементы.Профиль.ТолькоПросмотр               = Истина;
	Элементы.СвойстваПерсональнойГруппы.Видимость = Ложь;
	Элементы.Комментарий.ТолькоПросмотр           = Истина;
	
КонецПроцедуры

&НаСервере
Процедура НачальнаяНастройкаПриЧтенииИСоздании(ТекущийОбъект)
	
	ПрофильАдминистратор        = УправлениеДоступом.ПрофильАдминистратор();
	ГруппаДоступаАдминистраторы = УправлениеДоступом.ГруппаДоступаАдминистраторы();
	
	Если ТекущийОбъект.Ссылка = ГруппаДоступаАдминистраторы Тогда
		ЗапретитьИзменениеВсегоКромеСоставаУчастников();
		
		Если Не Пользователи.ЭтоПолноправныйПользователь() Тогда
			ТолькоПросмотр = Истина;
			Элементы.ФормаЗаписатьИЗакрыть.Доступность = Ложь;
		КонецЕсли;
	Иначе
		Если ЗначениеЗаполнено(ТекущийОбъект.Пользователь) Тогда
			// Подготовка к режиму персональной группы доступа.
			АвтоЗаголовок = Ложь;
			Заголовок = УправлениеДоступомСлужебныйКлиентСервер.ПредставлениеГруппыДоступа(ТекущийОбъект)
				+ " " + НСтр("ru = '(Группа доступа)'");
			
			Отбор = Новый Структура("Пользователь", ТекущийОбъект.Пользователь);
			НайденныеСтроки = ТекущийОбъект.Пользователи.НайтиСтроки(Отбор);
			ИспользованиеПерсональногоДоступа = НайденныеСтроки.Количество() > 0;
		Иначе
			АвтоЗаголовок = Истина;
		КонецЕсли;
		
		ПользовательЗаполнен = ЗначениеЗаполнено(ТекущийОбъект.Пользователь);
		
		Элементы.Наименование.ТолькоПросмотр                 = ПользовательЗаполнен;
		Элементы.Родитель.ТолькоПросмотр                     = ПользовательЗаполнен;
		Элементы.Профиль.ТолькоПросмотр                      = ПользовательЗаполнен;
		Элементы.СвойстваПерсональнойГруппы.Видимость        = ПользовательЗаполнен;
		Элементы.ПользователиГруппы.Видимость                = НЕ ПользовательЗаполнен;
		
		Элементы.ПользователиИДоступ.ОтображениеСтраниц =
			?(ПользовательЗаполнен,
			  ОтображениеСтраницФормы.Нет,
			  ОтображениеСтраницФормы.ЗакладкиСверху);
		
		Элементы.ВидыДоступа.ПоложениеЗаголовка =
			?(ПользовательЗаполнен,
			  ПоложениеЗаголовкаЭлементаФормы.Верх,
			  ПоложениеЗаголовкаЭлементаФормы.Нет);
		
		Элементы.ПользовательВладелец.ТолькоПросмотр
			= УправлениеДоступомСлужебный.УпрощенныйИнтерфейсНастройкиПравДоступа();
		
		// Подготовка к режиму редактирования пользователей ответственным за участников.
		Если Не Пользователи.ЭтоПолноправныйПользователь() Тогда
			Элементы.Наименование.ТолькоПросмотр = Истина;
			Элементы.Родитель.ТолькоПросмотр = Истина;
			Элементы.Профиль.ТолькоПросмотр = Истина;
			Элементы.Доступ.ТолькоПросмотр = Истина;
			Элементы.Ответственный.ТолькоПросмотр = Истина;
			Элементы.Комментарий.ТолькоПросмотр = Истина;
		КонецЕсли;
	КонецЕсли;
	
	ОбновитьСоставВидовДоступа(Истина);
	
	// Подготовка дерева пользователей.
	ДеревоПользователей = ПользователиГруппы.ПолучитьЭлементы();
	ДеревоПользователей.Очистить();
	Для каждого СтрокаТЧ Из ТекущийОбъект.Пользователи Цикл
		НоваяСтрока = ДеревоПользователей.Добавить();
		НоваяСтрока.Пользователь = СтрокаТЧ.Пользователь;
		НоваяСтрока.СрокДействия = СтрокаТЧ.СрокДействия;
	КонецЦикла;
	ОбновитьПользователейГрупп();
	
	ОбновитьКартинкуКомментария(Элементы.СтраницаКомментарий, Объект.Комментарий);
	
КонецПроцедуры

&НаСервере
Процедура ПрофильПриИзмененииНаСервере()
	
	ОбновитьНазначение();
	УдалитьНеТипичныхПользователей();
	ОбновитьСоставВидовДоступа();
	УправлениеДоступомСлужебныйКлиентСервер.ЗаполнитьСвойстваВидовДоступаВФорме(ЭтотОбъект);
	
КонецПроцедуры

&НаСервере
Процедура ОбновитьНазначение()
	
	Назначение.Очистить();
	НазначениеПредставление = "";
	ПрофильНазначение = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Объект.Профиль, "Назначение");
	Если ТипЗнч(ПрофильНазначение) = Тип("РезультатЗапроса") Тогда
		НазначениеПрофиля = ПрофильНазначение.Выгрузить();
		Для Каждого Участник Из НазначениеПрофиля Цикл
			Если Участник.ТипПользователей <> Неопределено Тогда
				Назначение.Добавить(Участник.ТипПользователей);
				ПредставлениеТипа = Участник.ТипПользователей.Метаданные().Синоним;
				НазначениеПредставление = ?(ПустаяСтрока(НазначениеПредставление),
					ПредставлениеТипа, НазначениеПредставление + ", " + ПредставлениеТипа);
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
	Элементы.Пользователи.Подсказка = НСтр("ru = 'Допустимые участники:'") + " " + НазначениеПредставление;
	
КонецПроцедуры

&НаСервере
Процедура УдалитьНеТипичныхПользователей()
	
	МассивТипов = Новый Массив;
	Для Каждого Элемент Из Назначение Цикл
		МассивТипов.Добавить(ТипЗнч(Элемент.Значение));
	КонецЦикла;
	
	ДеревоПользователей = ПользователиГруппы.ПолучитьЭлементы();
	СсылкиСОбъектомАвторизации = Новый Массив; // Массив из СправочникСсылка.ВнешниеПользователи
	Для Каждого СтрокаДерева Из ДеревоПользователей Цикл
		Если ТипЗнч(СтрокаДерева.Пользователь) = Тип("СправочникСсылка.ВнешниеПользователи") Тогда
			СсылкиСОбъектомАвторизации.Добавить(СтрокаДерева.Пользователь);
		КонецЕсли;
		Если ТипЗнч(СтрокаДерева.Пользователь) = Тип("СправочникСсылка.ГруппыВнешнихПользователей") Тогда
			Для Каждого УчастникГруппы Из СтрокаДерева.ПолучитьЭлементы() Цикл
				СсылкиСОбъектомАвторизации.Добавить(УчастникГруппы.Пользователь);
			КонецЦикла;
		КонецЕсли;
	КонецЦикла;
	ОбъектыАвторизации = ОбщегоНазначения.ЗначениеРеквизитаОбъектов(СсылкиСОбъектомАвторизации, "ОбъектАвторизации");
	
	Индекс = ДеревоПользователей.Количество() - 1;
	Пока Индекс >= 0 Цикл
		
		СтрокаДерева = ДеревоПользователей.Получить(Индекс);
		УдалитьСтроку = Ложь;
		
		Если (ТипЗнч(СтрокаДерева.Пользователь) = Тип("СправочникСсылка.Пользователи")
			Или ТипЗнч(СтрокаДерева.Пользователь) = Тип("СправочникСсылка.ГруппыПользователей"))
			И МассивТипов.Найти(Тип("СправочникСсылка.Пользователи")) = Неопределено Тогда
			
			УдалитьСтроку = Истина;
			
		ИначеЕсли ТипЗнч(СтрокаДерева.Пользователь) = Тип("СправочникСсылка.ВнешниеПользователи")
			И МассивТипов.Найти(ТипЗнч(ОбъектыАвторизации.Получить(СтрокаДерева.Пользователь))) = Неопределено Тогда
			
			УдалитьСтроку = Истина;
			
		ИначеЕсли ТипЗнч(СтрокаДерева.Пользователь) = Тип("СправочникСсылка.ГруппыВнешнихПользователей") Тогда
			
			Для Каждого УчастникГруппы Из СтрокаДерева.ПолучитьЭлементы() Цикл
				
				Если МассивТипов.Найти(ТипЗнч(ОбъектыАвторизации.Получить(УчастникГруппы.Пользователь))) = Неопределено Тогда
					УдалитьСтроку = Истина;
					Прервать;
				КонецЕсли;
				
			КонецЦикла;
			
		КонецЕсли;
		
		Если УдалитьСтроку Тогда
			ДеревоПользователей.Удалить(Индекс);
		КонецЕсли;
		
		Индекс = Индекс - 1;
		
	КонецЦикла;
	
КонецПроцедуры

&НаСервере
Процедура ОбновитьСоставВидовДоступа(Знач ПриЧтенииНаСервере = Ложь)
	
	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	ВидыДоступаПрофиля.ВидДоступа,
	|	ВидыДоступаПрофиля.Предустановленный,
	|	ВидыДоступаПрофиля.ВсеРазрешены
	|ИЗ
	|	Справочник.ПрофилиГруппДоступа.ВидыДоступа КАК ВидыДоступаПрофиля
	|ГДЕ
	|	ВидыДоступаПрофиля.Ссылка = &Ссылка
	|	И НЕ ВидыДоступаПрофиля.Предустановленный";
	
	Запрос.УстановитьПараметр("Ссылка", Объект.Профиль);
	
	УстановитьПривилегированныйРежим(Истина);
	ВидыДоступаПрофиля = Запрос.Выполнить().Выгрузить();
	УстановитьПривилегированныйРежим(Ложь);
	
	ИзменилсяСоставВидовДоступа = Ложь;
	
	// Добавление недостающих видов доступа.
	Индекс = ВидыДоступаПрофиля.Количество() - 1;
	Пока Индекс >= 0 Цикл
		Строка = ВидыДоступаПрофиля[Индекс];
		
		Отбор = Новый Структура("ВидДоступа", Строка.ВидДоступа);
		СвойстваВидаДоступа = УправлениеДоступомСлужебный.СвойстваВидаДоступа(Строка.ВидДоступа);
		
		Если СвойстваВидаДоступа = Неопределено Тогда
			ВидыДоступаПрофиля.Удалить(Строка);
		
		ИначеЕсли Объект.ВидыДоступа.НайтиСтроки(Отбор).Количество() = 0 Тогда
			ИзменилсяСоставВидовДоступа = Истина;
			
			Если ПриЧтенииНаСервере Тогда
				Прервать;
			Иначе
				НоваяСтрока = Объект.ВидыДоступа.Добавить();
				НоваяСтрока.ВидДоступа   = Строка.ВидДоступа;
				НоваяСтрока.ВсеРазрешены = Строка.ВсеРазрешены;
			КонецЕсли;
		КонецЕсли;
		Индекс = Индекс - 1;
	КонецЦикла;
	
	// Удаление лишних видов доступа.
	Индекс = Объект.ВидыДоступа.Количество() - 1;
	Пока Индекс >= 0 Цикл
		
		ВидДоступа = Объект.ВидыДоступа[Индекс].ВидДоступа;
		Отбор = Новый Структура("ВидДоступа", ВидДоступа);
		СвойстваВидаДоступа = УправлениеДоступомСлужебный.СвойстваВидаДоступа(ВидДоступа);
		
		Если СвойстваВидаДоступа = Неопределено
		 ИЛИ ВидыДоступаПрофиля.НайтиСтроки(Отбор).Количество() = 0 Тогда
			
			ИзменилсяСоставВидовДоступа = Истина;
			Если ПриЧтенииНаСервере Тогда
				Прервать;
			Иначе
				Объект.ВидыДоступа.Удалить(Индекс);
				Для каждого ЭлементКоллекции Из Объект.ЗначенияДоступа.НайтиСтроки(Отбор) Цикл
					Объект.ЗначенияДоступа.Удалить(ЭлементКоллекции);
				КонецЦикла;
			КонецЕсли;
		КонецЕсли;
		Индекс = Индекс - 1;
	КонецЦикла;
	
	Модифицированность = Модифицированность
		ИЛИ ИзменилсяСоставВидовДоступа И НЕ ПриЧтенииНаСервере;
	
	// Установка флажка для запроса у пользователя решения обновить состав видов доступа.
	Если ПриЧтенииНаСервере
	     И НЕ Объект.Ссылка.Пустая() // Это новый.
	     И ИзменилсяСоставВидовДоступа
	     И Пользователи.ЭтоПолноправныйПользователь() // Только администратор может обновлять виды доступа.
	     И ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Объект.Ссылка, "Профиль") = Объект.Профиль Тогда
	     
		ИзменилсяСоставВидовДоступаПриЧтении = Истина;
	КонецЕсли;
	
	Элементы.Доступ.Доступность = Объект.ВидыДоступа.Количество() > 0;
	
	// Установка порядка видов доступа по профилю.
	Если НЕ ИзменилсяСоставВидовДоступаПриЧтении Тогда
		Для каждого СтрокаТЧ Из ВидыДоступаПрофиля Цикл
			Отбор = Новый Структура("ВидДоступа", СтрокаТЧ.ВидДоступа);
			Индекс = Объект.ВидыДоступа.Индекс(Объект.ВидыДоступа.НайтиСтроки(Отбор)[0]);
			Объект.ВидыДоступа.Сдвинуть(Индекс, ВидыДоступаПрофиля.Индекс(СтрокаТЧ) - Индекс);
		КонецЦикла;
	КонецЕсли;
	
	УправлениеДоступомСлужебныйКлиентСервер.ЗаполнитьСвойстваВидовДоступаВФорме(ЭтотОбъект);
	
КонецПроцедуры

&НаСервере
Процедура ПоказыватьНеИспользуемыеВидыДоступаНаСервере()
	
	УправлениеДоступомСлужебный.ОбновитьОтображениеНеиспользуемыхВидовДоступа(ЭтотОбъект);
	
КонецПроцедуры

&НаКлиенте
Процедура ПоказатьВыборТипаПользователиИлиВнешниеПользователи(ОбработкаПродолжения)
	
	ВыборИПодборВнешнихПользователей = Ложь;
	
	Если Объект.Ссылка = ГруппаДоступаАдминистраторы Тогда
		ВыполнитьОбработкуОповещения(ОбработкаПродолжения, ВыборИПодборВнешнихПользователей);
		Возврат;
	КонецЕсли;
	
	Если Назначение.Количество() <> 0 Тогда
		
		Если Назначение.НайтиПоЗначению(ПредопределенноеЗначение("Справочник.Пользователи.ПустаяСсылка")) <> Неопределено Тогда
			
			Если Назначение.Количество() <> 1 Тогда
				
				Если ИспользоватьВнешнихПользователей Тогда
					
					СписокТиповПользователей.ПоказатьВыборЭлемента(
						Новый ОписаниеОповещения(
						"ПоказатьВыборТипаПользователиИлиВнешниеПользователиЗавершение",
						ЭтотОбъект,
						ОбработкаПродолжения),
						НСтр("ru = 'Выбор типа данных'"),
						СписокТиповПользователей[0]);
				Иначе
					ВыполнитьОбработкуОповещения(ОбработкаПродолжения, ВыборИПодборВнешнихПользователей);
				КонецЕсли;
				
				Возврат;
				
			КонецЕсли;
			
		Иначе // только для внешних пользователей.
			
			ВыборИПодборВнешнихПользователей = Истина;
			
		КонецЕсли;
		
	КонецЕсли;
	
	ВыполнитьОбработкуОповещения(ОбработкаПродолжения, ВыборИПодборВнешнихПользователей);
	
КонецПроцедуры

&НаКлиенте
Процедура ПоказатьВыборТипаПользователиИлиВнешниеПользователиЗавершение(ВыбранныйЭлемент, ОбработкаПродолжения) Экспорт
	
	Если ВыбранныйЭлемент <> Неопределено Тогда
		ВыборИПодборВнешнихПользователей =
			ВыбранныйЭлемент.Значение = Тип("СправочникСсылка.ВнешниеПользователи");
		
		ВыполнитьОбработкуОповещения(ОбработкаПродолжения, ВыборИПодборВнешнихПользователей);
	Иначе
		ВыполнитьОбработкуОповещения(ОбработкаПродолжения, Неопределено);
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ВыбратьПодобратьПользователей(Подобрать)
	
	ТекущийПользователь = ?(Элементы.Пользователи.ТекущиеДанные = Неопределено,
		Неопределено, Элементы.Пользователи.ТекущиеДанные.Пользователь);
	
	Если НЕ Подобрать
	   И ЗначениеЗаполнено(ТекущийПользователь)
	   И (    ТипЗнч(ТекущийПользователь) = Тип("СправочникСсылка.Пользователи")
	      ИЛИ ТипЗнч(ТекущийПользователь) = Тип("СправочникСсылка.ГруппыПользователей") ) Тогда
	
		ВыборИПодборВнешнихПользователей = Ложь;
	
	ИначеЕсли НЕ Подобрать
	        И ИспользоватьВнешнихПользователей
	        И ЗначениеЗаполнено(ТекущийПользователь)
	        И (    ТипЗнч(ТекущийПользователь) = Тип("СправочникСсылка.ВнешниеПользователи")
	           ИЛИ ТипЗнч(ТекущийПользователь) = Тип("СправочникСсылка.ГруппыВнешнихПользователей") ) Тогда
	
		ВыборИПодборВнешнихПользователей = Истина;
	Иначе
		ПоказатьВыборТипаПользователиИлиВнешниеПользователи(
			Новый ОписаниеОповещения("ВыбратьПодобратьПользователейЗавершение", ЭтотОбъект, Подобрать));
		Возврат;
	КонецЕсли;
	
	ВыбратьПодобратьПользователейЗавершение(ВыборИПодборВнешнихПользователей, Подобрать);
	
КонецПроцедуры

&НаКлиенте
Процедура ВыбратьПодобратьПользователейЗавершение(ВыборИПодборВнешнихПользователей, Подобрать) Экспорт
	
	Если ВыборИПодборВнешнихПользователей = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	ПараметрыФормы = Новый Структура;
	ПараметрыФормы.Вставить("РежимВыбора", Истина);
	ПараметрыФормы.Вставить("ТекущаяСтрока",
		?(Элементы.Пользователи.ТекущиеДанные = Неопределено,
			Неопределено, Элементы.Пользователи.ТекущиеДанные.Пользователь));
	
	Если Подобрать Тогда
		ПараметрыФормы.Вставить("ЗакрыватьПриВыборе", Ложь);
		ПараметрыФормы.Вставить("МножественныйВыбор", Истина);
		ПараметрыФормы.Вставить("РасширенныйПодбор", Истина);
		ПараметрыФормы.Вставить("ПараметрыРасширеннойФормыПодбора",
			ПараметрыРасширеннойФормыПодбора(ВыборИПодборВнешнихПользователей));
	КонецЕсли;
	
	Если Объект.Ссылка <> ГруппаДоступаАдминистраторы Тогда
		Если ВыборИПодборВнешнихПользователей Тогда
			ПараметрыФормы.Вставить("ВыборГруппВнешнихПользователей", Истина);
		Иначе
			ПараметрыФормы.Вставить("ВыборГруппПользователей", Истина);
		КонецЕсли;
	КонецЕсли;
	
	Если ВыборИПодборВнешнихПользователей Тогда
		
		ПараметрыФормы.Вставить("Назначение", Назначение.ВыгрузитьЗначения());
		
		Если Не ИспользоватьВнешнихПользователей Тогда
			ПоказатьПредупреждение(, НСтр("ru = 'Ведение внешних пользователей отключено в настройках приложения.'"));
		ИначеЕсли СправочникВнешниеПользователиДоступен Тогда
			ОткрытьФорму("Справочник.ВнешниеПользователи.ФормаВыбора", ПараметрыФормы, Элементы.Пользователи);
		Иначе
			ВызватьИсключение(НСтр("ru = 'Недостаточно прав для выбора внешних пользователей.'"),
				КатегорияОшибки.НарушениеПравДоступа);
		КонецЕсли;
	Иначе
		ОткрытьФорму("Справочник.Пользователи.ФормаВыбора", ПараметрыФормы, Элементы.Пользователи);
	КонецЕсли;
	
КонецПроцедуры

&НаСервере
Функция ПараметрыРасширеннойФормыПодбора(ВыборИПодборВнешнихПользователей)
	
	ПараметрыПодбора = ПользователиСлужебный.НовыеПараметрыРасширеннойФормыПодбора();
	ПараметрыПодбора.ЗаголовокФормыПодбора = НСтр("ru = 'Подбор участников группы доступа'");
	
	ЭлементыКоллекции = ПользователиГруппы.ПолучитьЭлементы();
	
	ТипПользователя = ?(ВыборИПодборВнешнихПользователей,
		Новый ОписаниеТипов("СправочникСсылка.ВнешниеПользователи,СправочникСсылка.ГруппыВнешнихПользователей"),
		Новый ОписаниеТипов("СправочникСсылка.Пользователи,СправочникСсылка.ГруппыПользователей"));
	
	Для каждого Элемент Из ЭлементыКоллекции Цикл
		Если ТипПользователя.СодержитТип(ТипЗнч(Элемент.Пользователь))
		   И ЗначениеЗаполнено(Элемент.Пользователь) Тогда
			ПараметрыПодбора.ВыбранныеПользователи.Добавить(Элемент.Пользователь);
		КонецЕсли;
	КонецЦикла;
	
	Возврат ПоместитьВоВременноеХранилище(ПараметрыПодбора, УникальныйИдентификатор);
	
КонецФункции

&НаСервере
Процедура ОбновитьПользователейГрупп(ИдентификаторСтроки = Неопределено,
                                     ИзмененныеСтроки = Неопределено)
	
	УстановитьПривилегированныйРежим(Истина);
	ИзмененныеСтроки = Новый Массив;
	
	Если ИдентификаторСтроки = Неопределено Тогда
		ЭлементыКоллекции = ПользователиГруппы.ПолучитьЭлементы();
		
	ИначеЕсли ТипЗнч(ИдентификаторСтроки) = Тип("Массив") Тогда
		ЭлементыКоллекции = Новый Массив;
		Для каждого Идентификатор Из ИдентификаторСтроки Цикл
			ЭлементыКоллекции.Добавить(ПользователиГруппы.НайтиПоИдентификатору(Идентификатор));
		КонецЦикла;
	Иначе
		ЭлементыКоллекции = Новый Массив;
		ЭлементыКоллекции.Добавить(ПользователиГруппы.НайтиПоИдентификатору(ИдентификаторСтроки));
	КонецЕсли;
	
	УчастникиГруппыПользователей = Новый Массив;
	Для Каждого Элемент Из ЭлементыКоллекции Цикл
		ТекущийПользователь = ?(ТипЗнч(Элемент) = Тип("ДанныеФормыЭлементДерева"),
			Элемент.Пользователь, Элемент);
		
		Если ТипЗнч(ТекущийПользователь) = Тип("СправочникСсылка.ГруппыПользователей")
		 Или ТипЗнч(ТекущийПользователь) = Тип("СправочникСсылка.ГруппыВнешнихПользователей") Тогда
		
			УчастникиГруппыПользователей.Добавить(ТекущийПользователь);
		КонецЕсли;
	КонецЦикла;
	
	Запрос = Новый Запрос;
	Запрос.УстановитьПараметр("УчастникиГруппыПользователей", УчастникиГруппыПользователей);
	Запрос.Текст =
	"ВЫБРАТЬ
	|	СоставыГруппПользователей.ГруппаПользователей КАК ГруппаПользователей,
	|	СоставыГруппПользователей.Пользователь КАК Пользователь
	|ИЗ
	|	РегистрСведений.СоставыГруппПользователей КАК СоставыГруппПользователей
	|ГДЕ
	|	СоставыГруппПользователей.ГруппаПользователей В(&УчастникиГруппыПользователей)
	|	И СоставыГруппПользователей.Пользователь.Недействителен <> ИСТИНА
	|	И СоставыГруппПользователей.Пользователь.Служебный <> ИСТИНА";
	
	ПользователиГрупп = Запрос.Выполнить().Выгрузить();
	ПользователиГрупп.Индексы.Добавить("ГруппаПользователей");
	
	Для каждого Элемент Из ЭлементыКоллекции Цикл
		Элемент.Ссылка = Элемент.Пользователь;
		
		Если ТипЗнч(Элемент.Пользователь) = Тип("СправочникСсылка.ГруппыПользователей")
		 ИЛИ ТипЗнч(Элемент.Пользователь) = Тип("СправочникСсылка.ГруппыВнешнихПользователей") Тогда
		
			// Заполнение пользователей группы.
			СтарыеПользователи = Элемент.ПолучитьЭлементы();
			Отбор = Новый Структура("ГруппаПользователей", Элемент.Пользователь);
			НовыеПользователи = ПользователиГрупп.НайтиСтроки(Отбор);
			
			ЕстьИзменения = Ложь;
			
			Если СтарыеПользователи.Количество() <> НовыеПользователи.Количество() Тогда
				СтарыеПользователи.Очистить();
				Для каждого Строка Из НовыеПользователи Цикл
					НовыйЭлемент = СтарыеПользователи.Добавить();
					НовыйЭлемент.Ссылка       = Строка.Пользователь;
					НовыйЭлемент.Пользователь = Строка.Пользователь;
					НовыйЭлемент.Уровень      = 1;
				КонецЦикла;
				ЕстьИзменения = Истина;
			Иначе
				Индекс = 0;
				Для каждого Строка Из СтарыеПользователи Цикл
					
					Если Строка.Ссылка       <> НовыеПользователи[Индекс].Пользователь
					 ИЛИ Строка.Пользователь <> НовыеПользователи[Индекс].Пользователь Тогда
						
						Строка.Ссылка       = НовыеПользователи[Индекс].Пользователь;
						Строка.Пользователь = НовыеПользователи[Индекс].Пользователь;
						ЕстьИзменения = Истина;
					КонецЕсли;
					Индекс = Индекс + 1;
				КонецЦикла;
			КонецЕсли;
			
			Если ЕстьИзменения Тогда
				ИзмененныеСтроки.Добавить(Элемент.ПолучитьИдентификатор());
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
	
	Пользователи.ЗаполнитьНомераКартинокПользователей(
		ПользователиГруппы, "Ссылка", "НомерКартинки", ИдентификаторСтроки, Истина);
	
	// Установка отображения дерева.
	ЕстьДерево = Ложь;
	Для каждого Элемент Из ПользователиГруппы.ПолучитьЭлементы() Цикл
		Если Элемент.ПолучитьЭлементы().Количество() > 0 Тогда
			ЕстьДерево = Истина;
			Прервать;
		КонецЕсли;
	КонецЦикла;
	Элементы.Пользователи.Отображение = ?(ЕстьДерево, ОтображениеТаблицы.Дерево, ОтображениеТаблицы.Список);
	
КонецПроцедуры

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

&НаСервере
Функция УточнитьСообщение(Строка, Значение)
	
	Возврат СтрЗаменить(Строка, "%2", Значение);
	
КонецФункции

&НаКлиентеНаСервереБезКонтекста
Процедура ОбновитьКартинкуКомментария(Элемент, Комментарий)
	
	Элемент.Картинка = ОбщегоНазначенияКлиентСервер.КартинкаКомментария(Комментарий);
	
КонецПроцедуры

&НаКлиенте
Процедура ПерейтиКЗначениюДоступа()
	
	Если ПерейтиКЗначениюДоступа <> Неопределено Тогда
		Элементы.ПользователиИДоступ.ТекущаяСтраница = Элементы.Доступ;
		ТекущийЭлемент = Элементы.Доступ;
		Отбор = Новый Структура("ВидДоступа", ПерейтиКВидуДоступа);
		НайденныеСтроки = Объект.ВидыДоступа.НайтиСтроки(Отбор);
		Если НайденныеСтроки.Количество() = 1 Тогда
			ТекущийЭлемент = Элементы.ВидыДоступаВидДоступаПредставление;
			Элементы.ВидыДоступа.ТекущаяСтрока = НайденныеСтроки[0].ПолучитьИдентификатор();
			Отбор.Вставить("ЗначениеДоступа", ПерейтиКЗначениюДоступа);
			НайденныеСтроки = Объект.ЗначенияДоступа.НайтиСтроки(Отбор);
			Если НайденныеСтроки.Количество() = 1 Тогда
				ТекущийЭлемент = Элементы.ЗначенияДоступаЗначениеДоступа;
				Элементы.ЗначенияДоступа.ТекущаяСтрока = НайденныеСтроки[0].ПолучитьИдентификатор();
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	
	ПерейтиКВидуДоступа     = Неопределено;
	ПерейтиКЗначениюДоступа = Неопределено;
	
КонецПроцедуры

// СтандартныеПодсистемы.ПодключаемыеКоманды

&НаКлиенте
Процедура Подключаемый_ВыполнитьКоманду(Команда)
	МодульПодключаемыеКомандыКлиент = ОбщегоНазначенияКлиент.ОбщийМодуль("ПодключаемыеКомандыКлиент");
	МодульПодключаемыеКомандыКлиент.НачатьВыполнениеКоманды(ЭтотОбъект, Команда, Объект);
КонецПроцедуры

&НаКлиенте
Процедура Подключаемый_ПродолжитьВыполнениеКомандыНаСервере(ПараметрыВыполнения, ДополнительныеПараметры) Экспорт
	ВыполнитьКомандуНаСервере(ПараметрыВыполнения);
КонецПроцедуры

&НаСервере
Процедура ВыполнитьКомандуНаСервере(ПараметрыВыполнения)
	МодульПодключаемыеКоманды = ОбщегоНазначения.ОбщийМодуль("ПодключаемыеКоманды");
	МодульПодключаемыеКоманды.ВыполнитьКоманду(ЭтотОбъект, ПараметрыВыполнения, Объект);
КонецПроцедуры

&НаКлиенте
Процедура Подключаемый_ОбновитьКоманды()
	МодульПодключаемыеКомандыКлиентСервер = ОбщегоНазначенияКлиент.ОбщийМодуль("ПодключаемыеКомандыКлиентСервер");
	МодульПодключаемыеКомандыКлиентСервер.ОбновитьКоманды(ЭтотОбъект, Объект);
КонецПроцедуры

// Конец СтандартныеПодсистемы.ПодключаемыеКоманды

#КонецОбласти

Связанные материалы