Как ограничить права на редактирование справочников через расширение в 1С

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

В процессе сопровождения типовых конфигураций «1С:Предприятие 8» программисты часто сталкиваются с требованиями клиентов ограничить доступ к изменению конкретных объектов для определенных пользователей. При этом ключевым условием является сохранение конфигурации на полной поддержке. Единственным верным инструментом в таком случае выступает механизм расширений.

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

Теория ограничений доступа в 1С: Аксиома ролей

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

Попытка создать роль в расширении с целью ограничить пользователя, у которого в основной конфигурации назначена роль ПолныеПрава или ДобавлениеИзменениеДанныхБухгалтерии, заведомо обречена на провал. Единственный способ решить задачу через роли — полностью лишить пользователя типовых ролей с избыточными правами, создать в расширении собственную роль со всеми необходимыми разрешениями (кроме целевых справочников) и назначить её пользователю. Однако этот путь крайне трудоемок, так как требует поддержки огромного массива прав в актуальном состоянии при обновлениях конфигурации.

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

Архитектурные подходы к ограничению доступа в расширении

Проанализируем ситуацию и выделим два основных метода программного перехвата действий пользователя:

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

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

Разбираем по шагам: Создание гибкой матрицы прав через Регистр Сведений

Хардкодить (прописывать жестко в коде) имена конкретных пользователей, которым запрещено редактирование, крайне не рекомендуется. Это лишает систему гибкости. Гораздо профессиональнее создать в расширении специальный регистр настроек доступа.

Рассмотрим подробнее процесс настройки и программирования нашей системы ограничения доступа.

Шаг 1. Создание регистра настроек в расширении

Добавим в наше расширение новый регистр сведений, который назовем, например, настройка_ПраваДоступаПользователей. Настроим его структуру следующим образом:

В режиме «1С:Предприятие» администратор сможет создать запись: например, для пользователя «Иванов И.И.» указать объект «Справочник.НоменклатурныеГруппы» и установить флаг в значение Истина.

Шаг 2. Заимствование справочников в расширение

Для реализации проверки нам необходимо заимствовать в расширение те справочники, редактирование которых нужно ограничить (в нашем примере это НоменклатурныеГруппы и СтатьиЗатрат). Перенесем их в расширение, кликнув правой кнопкой мыши по объекту в конфигураторе и выбрав команду «Добавить в расширение».

Шаг 3. Программная обработка события ПередЗаписью

В модуле объекта каждого заимствованного справочника нам необходимо перехватить событие записи. Мы воспользуемся аннотацией &Перед для расширения процедуры модуля объекта ПередЗаписью.

Посмотрим на пример программного кода, который решает эту задачу:


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

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

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

Шаг 4. Дружелюбный интерфейс: Блокировка формы

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

Разберем по шагам логику обработки формы:


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

Использование свойства формы ТолькоПросмотр = Истина делает все поля ввода неактивными для редактирования, скрывает кнопки записи и удаления, делая работу пользователя комфортной и предсказуемой.

Преимущества разработанного решения

Проанализировав созданный нами механизм, мы можем выделить следующие ключевые достоинства данного подхода:

Таким образом, использование расширения совместно с объектным кодом перехвата событий и регистром настроек является наиболее профессиональным, стабильным и архитектурно верным решением задачи ограничения доступа к справочникам в среде «1С:Предприятие 8».

← На главную