Как ограничить выбор значений перечисления в поле ввода в зависимости от роли пользователя

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке бизнес-логики в управляемых формах 1С 8.3 часто возникает задача предоставить пользователю возможность выбирать только определенные статусы документа или справочника в зависимости от имеющихся у него прав. При этом стандартные механизмы ограничения на уровне записей (RLS) для объектов метаданных типа Перечисление не применяются, так как права чтения задаются только на весь объект целиком.

Разберем по шагам основные способы решения этой задачи, проанализируем нюансы их применения и рассмотрим готовые примеры программного кода.

Вариант 1. Обработка получения данных выбора в модуле менеджера перечисления

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

Платформа 1С автоматически вызывает этот обработчик при открытии выпадающего списка, автоподборе текста и быстром вводе по строке. Разработчику не требуется вручную обращаться к методу ПолучитьДанныеВыбора() на форме — система выполняет перехват прозрачно.

Рассмотрим порядок действий для реализации этого варианта:

  1. Откроем дерево метаданных конфигурации, найдем нужное перечисление и перейдем в его Модуль менеджера (обратите внимание: процедура размещается именно в модуле менеджера перечисления, а не документа или формы).
  2. Создадим экспортную процедуру ОбработкаПолученияДанныхВыбора со стандартной сигнатурой параметров.
  3. Отключим стандартную обработку и сформируем собственный СписокЗначений с допустимыми элементами.

Посмотрим на пример кода в модуле менеджера перечисления:


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

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

Обратите внимание: проверка прав с помощью функции БСП УправлениеДоступом.ЕстьРоль() предпочтительнее устаревших платформенных методов, так как она корректно учитывает назначение ролей через профили и группы доступа пользователей.

Вариант 2. Локальная настройка списка выбора на конкретной управляемой форме

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

Разберем реализацию локального списка выбора:

  1. В свойствах элемента формы (поля ввода) установим флаги РежимВыбораИзСписка = Истина и КнопкаСпискаВыбора = Истина.
  2. В серверном обработчике ПриСозданииНаСервере заполним коллекцию СписокВыбора разрешенными значениями.

Посмотрим на пример кода в модуле управляемой формы:


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

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

Вариант 3. Асинхронный выбор через метод ПоказатьВыборИзСписка

Если набор допустимых статусов зависит от динамического контекста документа (например, от текущего статуса, автора документа или суммы) и должен рассчитываться непосредственно в момент клика, используем событие НачалоВыбораИзСписка.

Проанализируем пример асинхронного вызова списка:


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

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

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

Обязательная серверная валидация безопасности

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

Для полноценной защиты бизнес-логики обязательно продублируем контроль прав в модуле объекта перед записью:


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

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

← На главную