Как добавить дополнительную группу доступа к контрагенту в 1С:УНФ 1.6 с условием "ИЛИ" для RLS?

Программист 1С v8.3 (Управляемые формы) 1С:Управление нашей фирмой Управленческий учет
← На главную

В мире 1С:Предприятия, особенно при работе с системами вроде 1С:Управление нашей фирмой (УНФ), управление доступом к данным является критически важным аспектом. Часто возникает ситуация, когда стандартные механизмы разграничения прав доступа (RLS) требуют кастомизации для удовлетворения специфических бизнес-требований. Рассмотрим распространенную проблему: необходимость добавления дополнительной группы доступа к объекту Контрагент с условием "ИЛИ" для фильтрации записей в RLS, когда типовые составные группы доступа оказываются неэффективными или неудобными.

Наш сценарий выглядит следующим образом: в объекте Контрагент уже существует реквизит ГруппаДоступа. Требуется добавить новый реквизит, назовем его ДопГруппаДоступа, таким образом, чтобы при применении RLS фильтрация осуществлялась по условию "ИЛИ". Это означает, что пользователь должен иметь доступ к контрагенту, если он включен либо в группу, указанную в ГруппаДоступа, либо в группу, указанную в ДопГруппаДоступа. Стандартные составные группы доступа, которые позволяют объединять несколько групп в одну, в данном случае не подходят из-за предполагаемого огромного количества возможных вариаций и их непрактичности в управлении.

Анализ существующих механизмов и причины их непригодности

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

  1. Реквизит ГруппаДоступа и ДопГруппаДоступа: Если мы просто добавим еще один реквизит типа СправочникСсылка.ГруппыДоступа в Контрагент, стандартные шаблоны RLS не "поймут", что нужно применять условие "ИЛИ" между этими двумя реквизитами. Типовой RLS, как правило, ориентирован на один реквизит или на иерархию групп, применяя условие "И" между различными разрезами доступа, если они есть. В нашем случае, мы хотим гибкости внутри одного разреза (по контрагентам).

  2. Составные группы доступа и их ограничения: Идея создания составных групп доступа, где каждая группа включает в себя комбинацию других групп, кажется логичной на первый взгляд. Однако, как верно подмечено в исходной задаче, если количество возможных вариаций групп доступа (например, "ГруппаА ИЛИ ГруппаБ", "ГруппаА ИЛИ ГруппаВ", "ГруппаБ ИЛИ ГруппаВ" и т.д.) становится слишком большим, управление такими составными группами превращается в кошмар. Это приводит к экспоненциальному росту количества групп, которые нужно создавать, поддерживать и назначать пользователям, что делает систему негибкой и сложной в администрировании.

  3. Стандартное назначение групп пользователям: Другой стандартный подход заключается в том, чтобы просто добавить пользователя в несколько групп доступа. Например, если пользователь должен иметь доступ к контрагенту, который относится к "ГруппеА" или к "ДопГруппеБ", мы можем добавить пользователя в две группы доступа: одну, которая предоставляет доступ к "ГруппеА", и другую, которая предоставляет доступ к "ДопГруппеБ". Типовой RLS при этом будет работать по принципу "ИЛИ": если пользователь имеет доступ хотя бы к одной из групп, он увидит соответствующего контрагента. Однако, этот подход также не решает проблему, если мы хотим, чтобы сам контрагент имел несколько "групп принадлежности", а не только пользователь имел несколько "прав". То есть, проблема не в том, как дать пользователю доступ к нескольким группам, а в том, как контрагенту "присвоить" несколько групп, по которым будет действовать RLS.

  4. Различия между конфигурациями: Важно понимать, что механизмы RLS могут незначительно отличаться в разных конфигурациях. Например, в 1С:Документооборот существуют "разрезы доступа", которые предоставляют более гибкие возможности настройки RLS, чем в 1С:УНФ 1.6. Попытка применить решения, разработанные для одной конфигурации (например, ДО) напрямую к другой (УНФ), может не сработать или потребовать значительной адаптации, как было отмечено в обсуждении.

Выявление истинной потребности: Доступ на уровне контрагента

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

Основное решение: Подход "1:1 контрагент — группа доступа"

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

Как это работает: Создание уникальных групп

Вместо того чтобы добавлять в Контрагента реквизит ДопГруппаДоступа, мы полностью пересматриваем концепцию. Для каждого Контрагента, который требует уникального сочетания прав доступа (выходящего за рамки стандартных групп), мы создаем отдельную, уникальную группу доступа. Например, если у нас есть Контрагент "Ромашка", который должен быть доступен пользователям, имеющим права на "ГруппуА" ИЛИ "ГруппуБ", мы можем создать следующие сущности:

  1. Стандартные группы доступа: У нас уже есть справочник ГруппыДоступа (или ПрофилиГруппДоступа в более новых конфигурациях), где определены общие группы, например, "Менеджеры по продажам", "Финансисты" и т.д.

  2. Специальные "контрагентные" группы доступа: Для каждого уникального Контрагента, или для каждой уникальной комбинации групп, которая должна быть у контрагента (например, "Клиент_ГруппаА_ДопГруппаБ"), мы создаем отдельный элемент в справочнике ГруппыДоступа. Название этой группы может быть, например, Контрагент_ID_Ромашка или Доступ_Ромашка_А_и_Б. Эти группы, по своей сути, будут являться "контейнерами" для специфических прав на конкретных контрагентов.

    Например, создадим группу доступа с названием, отражающим ее назначение:

    
    // Пример названия группы доступа, которую мы можем создать
    НоваяГруппаДоступа.Наименование = "ДоступКонтрагент_Ромашка_ДопГруппа_Аналитики";
    НоваяГруппаДоступа.Записать();
    

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

  3. Связывание контрагента с группой: Чтобы RLS понимал, какая группа относится к какому контрагенту, нам понадобится механизм связывания. Мы можем либо использовать существующий реквизит ГруппаДоступа в Контрагенте для указания этой "специальной" группы, либо добавить вспомогательный регистр сведений, который будет хранить связь Контрагент - ГруппаДоступа. Использование существующего реквизита проще, если Контрагент связан с одной такой "специальной" группой.

Назначение групп пользователям

Теперь, когда у нас есть специальные группы доступа для контрагентов, логика "ИЛИ" реализуется на уровне пользователей:

  1. Пользовательские группы: У пользователя будут стандартные группы доступа (например, "Менеджер Вася", который входит в "ГруппуА").

  2. Дополнительные права: Если пользователь должен иметь доступ к контрагенту "Ромашка" (который связан с "Группой_Ромашка_А_и_Б"), то мы просто включаем этого пользователя в "Группу_Ромашка_А_и_Б".

Таким образом, если пользователь включен в "ГруппуА", он видит все контрагенты, связанные с "ГруппойА". Если он дополнительно включен в "Группу_Ромашка_А_и_Б", он также увидит контрагента "Ромашка", даже если он не относится к "ГруппеА", но относится к "ДопГруппеБ" (которая была "зашита" в "Группу_Ромашка_А_и_Б"). Система RLS будет проверять членство пользователя во всех доступных ему группах доступа и предоставит доступ, если хотя бы одна из них соответствует группе, указанной у контрагента (или в регистре связей).

Преимущества данного подхода

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

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

  3. Четкое разграничение: Каждая уникальная потребность в доступе к конкретному контрагенту (или группе контрагентов) может быть инкапсулирована в отдельную группу доступа.

Недостатки и сложности

  1. Большое количество групп доступа: Если каждый контрагент требует уникальной комбинации прав, то количество групп доступа может стать очень большим. Это усложняет администрирование справочника ГруппыДоступа.

  2. Ручное управление или необходимость автоматизации: Создание и назначение этих 1:1 групп доступа вручную крайне трудоемко. Это неизбежно ведет к необходимости автоматизации.

  3. Потенциальное влияние на производительность: Большое количество групп доступа и сложные условия в RLS могут повлиять на производительность запросов. Важно будет провести тестирование после внедрения.

Автоматизация процесса управления группами доступа

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

  1. Создание групп для новых контрагентов:

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

    
    ПриЗаписи
    
    или
    
    ОбработкаПроведения
    
    для объекта Контрагент.

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

    Эта логика будет гарантировать, что для каждого контрагента, требующего особого доступа, будет создана соответствующая группа.

  2. Назначение/отзыв прав пользователям:

    Назначение пользователей в эти "контрагентные" группы доступа также можно автоматизировать. Это может быть реализовано через:

    • Регламентные задания: Периодически запускаемое регламентное задание может анализировать текущие настройки пользователей и контрагентов, а затем корректировать членство пользователей в группах доступа. Например, если у пользователя есть роль "Менеджер по особым клиентам" и такой клиент "Ромашка" создан, регламентное задание автоматически добавит этого пользователя в группу "Доступ_Ромашка_А_и_Б".

      
      // Пример логики регламентного задания
      Процедура ОбновитьПраваДоступаПользователей()
          // Получить список пользователей, которым нужны особые права
          // Получить список контрагентов с их "контрагентными" группами
          // Проанализировать, какие пользователи должны быть в каких группах
          // Модифицировать регистр сведений "НазначениеПравДоступа"
          // или аналогичный механизм управления членством в группах
      КонецПроцедуры
      
    • Обработчики событий: При изменении роли пользователя или прикреплении его к определенному подразделению, мы можем программно добавлять его в соответствующие "контрагентные" группы.
  3. Использование сегментов (если применимо в УНФ):

    Если в 1С:УНФ 1.6 существует механизм сегментации контрагентов, его можно использовать для более гибкого назначения "контрагентных" групп. Например, можно определить сегменты "ВИП-клиенты", "Клиенты с просрочкой" и т.д. Затем регламентное задание будет формировать "контрагентные" группы доступа на основе этих сегментов и назначать пользователей. Это позволяет избежать создания группы для *каждого* контрагента, если есть возможность объединять их по определенным признакам в сегменты.

    Например, создаем сегмент "Контрагенты_Особого_Обслуживания". Для всех контрагентов, попадающих в этот сегмент, создается одна специальная группа доступа "Доступ_Особое_Обслуживание". Пользователи, имеющие доступ к этому сегменту, включаются в эту группу.

Альтернативные подходы к реализации RLS с условием "ИЛИ"

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

  1. Кастомизация RLS через расширения:

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

    • Доработка общего модуля, отвечающего за формирование условий RLS (например, УправлениеДоступомПереопределяемый, ПраваДоступа или подобных, в зависимости от конфигурации и версии платформы). Мы можем в расширении "перехватить" или дополнить процедуры, формирующие текст запроса RLS.
    • Изменение запросов, используемых для получения данных, к которым применяется RLS. Это может включать добавление дополнительных соединений с таблицей, содержащей ДопГруппаДоступа, и формирование условия "ИЛИ" внутри запроса.

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

  2. Добавление собственного регистра сведений для хранения дополнительных групп доступа:

    Мы можем создать отдельный регистр сведений, который будет хранить связи Контрагент - ДопГруппаДоступа. Например:

    • Регистр сведений: ДопГруппыДоступаКонтрагентов
    • Измерения: Контрагент (тип СправочникСсылка.Контрагенты), ГруппаДоступа (тип СправочникСсылка.ГруппыДоступа)

    Этот регистр затем будет использоваться в условии RLS. В шаблоне RLS для объекта Контрагенты мы будем добавлять условие, которое проверяет членство пользователя в группах, указанных как в основном реквизите контрагента, так и в этом дополнительном регистре.

    Пример условия RLS для Контрагентов (псевдокод):

    
    #Если (ЕстьДоступККонтрагентам) Тогда
        "&ВидДоступа.Чтение" В
        (ВЫБРАТЬ
            ГруппыДоступа.Ссылка
        ИЗ
            Справочник.ГруппыДоступа КАК ГруппыДоступа
        ГДЕ
            ГруппыДоступа.Наименование = "ВсеКонтрагенты"
         ИЛИ
            ГруппыДоступа.Ссылка В (&ГруппыДоступаПользователя) // Основные группы
         ИЛИ
            ГруппыДоступа.Ссылка В
            (ВЫБРАТЬ
                ДопГруппыДоступа.ГруппаДоступа
            ИЗ
                РегистрСведений.ДопГруппыДоступаКонтрагентов КАК ДопГруппыДоступа
            ГДЕ
                ДопГруппыДоступа.Контрагент = &ТекущийКонтрагент // Для текущего контрагента
                И ДопГруппыДоступа.ГруппаДоступа В (&ГруппыДоступаПользователя)
            )
        )
    #КонецЕсли
    

    Это позволит гибко настраивать доступы и легко реализовать условие "ИЛИ" путем объединения результатов запросов по основному реквизиту и по дополнительному регистру.

  3. Использование программного формирования условий RLS:

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

  4. Реализация логики "ИЛИ" в запросах:

    При работе с RLS, если требуется условие "ИЛИ" между несколькими группами доступа, необходимо убедиться, что формируемый RLS-запрос корректно включает это условие. Это может быть достигнуто путем добавления нескольких условий РАЗРЕШЕН_ДОСТУП с оператором ИЛИ или путем использования временных таблиц для сбора всех разрешенных групп доступа (как основных, так и дополнительных) и последующего соединения с ними. Правильное использование ЛЕВОЕ СОЕДИНЕНИЕ или ОБЪЕДИНИТЬ ВСЕ в подзапросах RLS может помочь агрегировать все группы, к которым пользователь имеет доступ, и затем проверить, принадлежит ли контрагент хотя бы к одной из них.

  5. Влияние на производительность:

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

Заключение

Мы рассмотрели проблему добавления дополнительной группы доступа к контрагенту в 1С:УНФ 1.6 с условием "ИЛИ" для RLS, когда стандартные подходы оказываются неэффективными из-за большого количества вариаций. Основное решение, которое было признано наиболее подходящим в обсуждении, заключается в создании "контрагентных" групп доступа по принципу "1:1" или "один сегмент - одна группа". Этот подход позволяет избежать изменения типовых шаблонов RLS, перенося сложность в управление группами доступа и требуя автоматизации.

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

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

← На главную