Как в 1С 7.7 ограничить пользователю доступ к отдельным элементам справочника?

Программист 1С v7.7 Управленческий учет IT и автоматизация бизнеса
← На главную

В платформе 1С:Предприятие 7.7 система прав доступа устроена на уровне метаданных: разработчик может разрешить или запретить чтение, запись или удаление справочника целиком, однако механизм ограничения прав на уровне записей (RLS — Record Level Security), привычный по версии 8.x, в «семерке» отсутствует. Если перед нами стоит задача запретить определенному сотруднику выбирать конкретный склад или контрагента в документах реализации, решать ее приходится исключительно программными средствами встроенного языка.

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

Особенности платформы и возможные обходные пути

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

  1. Набрать наименование или код склада вручную непосредственно с клавиатуры в поле ввода документа, не открывая форму списка.
  2. Создать новый документ путем копирования старого документа, в котором запрещенный склад уже был выбран.
  3. Использовать механизм ввода на основании других документов.
  4. Воспользоваться универсальными внешними обработками группового изменения реквизитов, если у пользователя есть доступ к запуску внешних отчетов и обработок.

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

Шаг 1. Определение прав и пользователя

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

Первый вариант основан на получении назначенного набора прав с помощью функции НазваниеНабораПрав(). Разберем синтаксис этой функции:


// Синтаксис: НазваниеНабораПрав(<ВыдИспНабПрав>)
// 0 - выдает установленный набор прав (по умолчанию);
// 1 - выдает пустую строку, если контроль прав временно отключен.
Если НазваниеНабораПрав() = "Менеджер" Тогда
    // Действия для ограничения
КонецЕсли;

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

Шаг 2. Фильтрация списка выбора в интерфейсе документа

Чтобы предоставить пользователю для выбора только те склады, к которым у него есть доступ, перехватим стандартное событие открытия формы выбора. Рассмотрим, как это сделать в модуле формы документа:

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

Посмотрим на пример реализации перехвата выбора склада:


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

Шаг 3. Запрет ввода с клавиатуры

Чтобы исключить ручной набор запрещенного значения непосредственно в строке ввода без вызова диалога, проверим значение в процедуре ПриИзмененииРеквизита() формы документа или сделаем поле доступным только по кнопке выбора:


Процедура ПриИзмененииРеквизита(ИдентЭлемента)
    Если ИдентЭлемента = "Склад" Тогда
        Если (НазваниеНабораПрав() = "Менеджер") И (Склад = Константа.Склад1) Тогда
            Предупреждение("У вас нет прав для выбора данного склада!");
            Склад = ПолучитьПустоеЗначение("Справочник.Склады");
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Шаг 4. Блокировка при записи и проведении (закрытие обходных путей)

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

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

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


Процедура ВводНового(ПризнакКопирования)
    Если ПризнакКопирования = 1 Тогда
        Если НазваниеНабораПрав() = "Менеджер" Тогда
            Если Склад = Константа.Склад1 Тогда
                Склад = ПолучитьПустоеЗначение("Справочник.Склады");
            КонецЕсли;
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Процедура ПриЗаписи()
    Если НазваниеНабораПрав() = "Менеджер" Тогда
        Если Склад = Константа.Склад1 Тогда
            Предупреждение("Запрещено сохранять документ с указанным складом!");
            СтатусВозврата(0);
            Возврат;
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Процедура ОбработкаПроведения()
    Если НазваниеНабораПрав() = "Менеджер" Тогда
        Если Склад = Константа.Склад1 Тогда
            Сообщить("Проведение документа по данному складу запрещено!", "!");
            СтатусВозврата(0);
            Возврат;
        КонецЕсли;
    КонецЕсли;
    // Далее стандартный алгоритм проведения...
КонецПроцедуры

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

← На главную