В платформе 1С:Предприятие 7.7 система прав доступа устроена на уровне метаданных: разработчик может разрешить или запретить чтение, запись или удаление справочника целиком, однако механизм ограничения прав на уровне записей (RLS — Record Level Security), привычный по версии 8.x, в «семерке» отсутствует. Если перед нами стоит задача запретить определенному сотруднику выбирать конкретный склад или контрагента в документах реализации, решать ее приходится исключительно программными средствами встроенного языка.
Проанализируем технические особенности платформы и разберем по шагам, как построить надежную систему разграничения доступа к данным.
Прежде чем приступать к написанию кода, важно понимать, что простого визуального скрытия элемента в форме списка недостаточно. Если ограничить только выбор из справочника, пользователь может обойти запрет следующими способами:
Именно поэтому правильная реализация должна состоять из двух обязательных уровней: удобного интерфейсного фильтра при выборе и жесткого программного контроля при записи и проведении документа.
Для проверки того, относится ли текущий пользователь к категории с ограничениями, мы можем использовать штатные системные функции. Рассмотрим два основных подхода:
Первый вариант основан на получении назначенного набора прав с помощью функции НазваниеНабораПрав(). Разберем синтаксис этой функции:
// Синтаксис: НазваниеНабораПрав(<ВыдИспНабПрав>)
// 0 - выдает установленный набор прав (по умолчанию);
// 1 - выдает пустую строку, если контроль прав временно отключен.
Если НазваниеНабораПрав() = "Менеджер" Тогда
// Действия для ограничения
КонецЕсли;
Второй, более надежный вариант, заключается в проверке логина текущей сессии через ИмяПользователя() или сопоставлении пользователя со специально созданной таблицей настроек доступа (например, через служебный справочник или константы со списком значений). Это исключает зависимость логики от переименования наборов прав в конфигураторе.
Чтобы предоставить пользователю для выбора только те склады, к которым у него есть доступ, перехватим стандартное событие открытия формы выбора. Рассмотрим, как это сделать в модуле формы документа:
ПриНачалеВыбораЗначения().СписокЗначений.ИспользоватьСписокЭлементов().Посмотрим на пример реализации перехвата выбора склада:
Процедура ПриНачалеВыбораЗначения(ИдентЭлемента, ФлагСтандОбр)
Если ИдентЭлемента = "Склад" Тогда
Если НазваниеНабораПрав() = "Менеджер" Тогда
// Отменяем стандартное открытие формы выбора
ФлагСтандОбр = 0;
// Формируем список доступных складов
СпРазрешенных = СоздатьОбъект("СписокЗначений");
СпрСкл = СоздатьОбъект("Справочник.Склады");
СпрСкл.ВыбратьЭлементы();
Пока СпрСкл.ПолучитьЭлемент() = 1 Цикл
// Исключаем запрещенный Склад №1
Если СпрСкл.ТекущийЭлемент() <> Константа.Склад1 Тогда
СпРазрешенных.ДобавитьЗначение(СпрСкл.ТекущийЭлемент());
КонецЕсли;
КонецЦикла;
// Открываем форму списка с отбором
КонтекстФормы = 0;
ОткрытьФорму("Справочник.Склады.ДляВыбора", КонтекстФормы, 1);
КонтекстФормы.ИспользоватьСписокЭлементов(СпРазрешенных);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Чтобы исключить ручной набор запрещенного значения непосредственно в строке ввода без вызова диалога, проверим значение в процедуре ПриИзмененииРеквизита() формы документа или сделаем поле доступным только по кнопке выбора:
Процедура ПриИзмененииРеквизита(ИдентЭлемента)
Если ИдентЭлемента = "Склад" Тогда
Если (НазваниеНабораПрав() = "Менеджер") И (Склад = Константа.Склад1) Тогда
Предупреждение("У вас нет прав для выбора данного склада!");
Склад = ПолучитьПустоеЗначение("Справочник.Склады");
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Интерфейсные ограничения можно обойти, поэтому обязательно добавим контроль целостности бизнес-логики в модуле документа. Разберем ключевые события жизненного цикла объекта:
ВводНового(). Параметр ПризнакКопирования равен 1, если документ создается копированием.ПриЗаписи() проверяем права и выбранный реквизит. Если обнаружено нарушение, вызываем СтатусВозврата(0) и завершаем процедуру оператором Возврат.ОбработкаПроведения() дублируем проверку. Это защитит базу данных от несанкционированного проведения документов внешними обработками.Посмотрим на пример кода в модуле документа:
Процедура ВводНового(ПризнакКопирования)
Если ПризнакКопирования = 1 Тогда
Если НазваниеНабораПрав() = "Менеджер" Тогда
Если Склад = Константа.Склад1 Тогда
Склад = ПолучитьПустоеЗначение("Справочник.Склады");
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Процедура ПриЗаписи()
Если НазваниеНабораПрав() = "Менеджер" Тогда
Если Склад = Константа.Склад1 Тогда
Предупреждение("Запрещено сохранять документ с указанным складом!");
СтатусВозврата(0);
Возврат;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Процедура ОбработкаПроведения()
Если НазваниеНабораПрав() = "Менеджер" Тогда
Если Склад = Константа.Склад1 Тогда
Сообщить("Проведение документа по данному складу запрещено!", "!");
СтатусВозврата(0);
Возврат;
КонецЕсли;
КонецЕсли;
// Далее стандартный алгоритм проведения...
КонецПроцедуры
Такой комплексный подход полностью закрывает уязвимости платформы 1С 7.7, обеспечивая надежное разграничение прав пользователей на уровне конкретных элементов справочников.