В практической деятельности крупных предприятий часто возникает задача разграничения прав доступа к конфиденциальной информации. Одной из таких задач является ограничение видимости конкретного банковского счета (или нескольких счетов) для большинства сотрудников. Например, необходимо сделать так, чтобы только три определенных пользователя (директор, главный бухгалтер и казначей) могли видеть операции по определенному расчетному счету, выбирать его в документах и формировать по нему отчеты, а для остальных пятидесяти сотрудников этот счет должен быть полностью скрыт.
В этой статье мы подробно разберем, почему простые решения «в лоб» не работают или вредят системе, и рассмотрим два методологически верных способа реализации этой задачи в конфигурации 1С:Бухгалтерия предприятия 3.0 (БП 3.0), построенной на базе Библиотеки стандартных подсистем (БСП).
Начинающие разработчики часто совершают ошибку, пытаясь решить задачу самым быстрым путем — жестким прописыванием конкретного номера счета или наименования банка непосредственно в запросе ограничения прав доступа (RLS) роли. Рассмотрим пример такого ошибочного кода:
БанковскиеСчета ГДЕ БанковскиеСчета.Наименование <> "40701810900060000156, БАНК ВТБ (ПАО)"
Выясним причину, почему данный подход считается грубейшей ошибкой проектирования:
Ниже мы рассмотрим два архитектурно правильных варианта решения этой задачи.
---
Поскольку современная «1С:Бухгалтерия предприятия 3.0» активно использует механизмы БСП, наиболее правильным путем является интеграция нашего ограничения в стандартную подсистему управления доступом. Это позволит настраивать права динамически, прямо в режиме «1С:Предприятие», используя стандартные профили и группы доступа.
Рассмотрим по шагам, как внедрить новый вид доступа для справочника БанковскиеСчета.
Для начала нам необходимо заявить системе о существовании нового разреза ограничения прав. Для этого найдем общий модуль УправлениеДоступомПереопределяемый и в процедуре ПриЗаполненииВидовДоступа добавим следующий код:
Процедура ПриЗаполненииВидовДоступа(ВидыДоступа) Экспорт
// Добавляем новый разрез ограничения доступа
ВидДоступа = ВидыДоступа.Добавить();
ВидДоступа.Имя = "БанковскиеСчета";
ВидДоступа.Представление = НСтр("ru = 'Банковские счета'");
ВидДоступа.ТипЗначений = Тип("СправочникСсылка.БанковскиеСчета");
КонецПроцедуры
Чтобы подсистема БСП могла связать наш справочник с механизмами кэширования и проверки прав, нам нужно включить его в состав некоторых определяемых типов в конфигураторе. Найдем и добавим справочник БанковскиеСчета в следующие определяемые типы:
ЗначениеДоступаЗначениеДоступаСГруппамиЗначенийДоступаОбъектВладелецЗначенийКлючейДоступаТеперь откроем модуль менеджера справочника БанковскиеСчета и добавим экспортную процедуру, которая сообщает БСП, по какому правилу ограничивать этот объект:
Процедура ПриЗаполненииОграниченияДоступа(Ограничение) Экспорт
Ограничение.Текст =
"РазрешитьЧтениеИзменение |ГДЕ | ЗначениеРазрешено(Ссылка)";
КонецПроцедуры
Для ролей, которые дают доступ к банковским счетам на чтение (например, ЧтениеБанковскихСчетов или созданная вами специализированная роль), необходимо прописать ограничение доступа к данным (RLS). Вместо написания сложных SQL-запросов мы используем стандартный шаблон БСП:
#ПоЗначениям("Справочник.БанковскиеСчета", "Чтение", "", "", "", "", "", "", "", "")
После обновления конфигурации базы данных выполним запуск программы и перейдем в раздел Администрирование — Настройки пользователей и прав — Группы доступа. Теперь при редактировании или создании профилей групп доступа у нас появится новый вид доступа «Банковские счета».
Мы сможем создать группу доступа для обычных пользователей, выбрав для вида доступа «Банковские счета» значение «Все запрещены, кроме» и указав только общедоступные счета. Для доверенных пользователей создадим группу, где этот вид доступа будет иметь значение «Все разрешены».
---
Несмотря на изящество первого способа, у RLS на уровне БСП есть один существенный недостаток. Если вы ограничите доступ к справочнику БанковскиеСчета, то при попытке сформировать стандартные бухгалтерские отчеты (например, «Оборотно-сальдовая ведомость по счету 51» или «Анализ счета»), СУБД будет вынуждена накладывать сложные соединения на регистры бухгалтерии. Это может привести к критическому падению производительности и зависанию базы данных при проведении документов и формировании отчетов.
Проанализируем альтернативный, более легкий путь решения проблемы с помощью создания Расширения конфигурации. Этот метод гарантирует высокое быстродействие системы и простоту поддержки.
Идея заключается в том, чтобы скрывать секретный счет на уровне интерфейса (в формах списка и выбора), а также контролировать формирование отчетов.
Рекомендуется не привязываться к именам или номерам счетов в коде. Создадим в расширении дополнительный реквизит для справочника БанковскиеСчета (или задействуем механизм дополнительных реквизитов и сведений БСП). Назовем его, например, КонфиденциальныйУчет с типом Булево. Администратор в пользовательском режиме просто поставит галочку на том счете, который нужно скрыть от большинства глаз.
Добавим в наше расширение форму списка и форму выбора справочника БанковскиеСчета. Перехватим событие ПриСозданииНаСервере этих форм с помощью аннотации &После:
&НаСервере
Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
// Проверим, входит ли текущий пользователь в список разрешенных.
// Для этого можно использовать персональные настройки или проверку роли.
Если Не РольДоступна("ПолныеПрава") И Не Расш1_ДоступныСекретныеСчета() Тогда
// Накладываем программный фильтр на динамический список формы
ЭлементОтбора = Список.КомпоновщикНастроек.ФиксированныеНастройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("КонфиденциальныйУчет");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = Ложь;
ЭлементОтбора.Использование = Истина;
ЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
КонецЕсли;
КонецПроцедуры
Функция проверки доступа может выглядеть следующим образом:
&НаСервере
Функция Расш1_ДоступныСекретныеСчета()
// Проверяем принадлежность пользователя к разрешенной группе
ТекущийПользователь = Пользователи.АвторизованныйПользователь();
ГруппаДоступаСекретная = Справочники.ГруппыДоступа.НайтиПоНаименованию("Доступ к секретным счетам");
Если ЗначениеЗаполнено(ГруппаДоступаСекретная) Тогда
Возврат ПользователиСервер.ПроверитьПринадлежностьПользователяГруппе(ТекущийПользователь, ГруппаДоступаСекретная);
КонецЕсли;
Возврат Ложь;
КонецФункции
Этот простой код гарантирует, что обычные пользователи даже не увидят секретный расчетный счет в списках и не смогут выбрать его в документах поступления или списания денежных средств.
Для того чтобы пользователи не смогли увидеть остатки и движения по конфиденциальному счету через стандартные отчеты (например, ОСВ по счету 51), мы можем использовать перехват события компоновки данных в расширении. Создадим обработчик в модуле модификации отчетов или перехватим процедуру инициализации компоновщика настроек отчетов:
&НаСервере
Процедура Расш1_ПриКомпоновкеРезультатаПосле(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
Если Не Расш1_ДоступныСекретныеСчета() Тогда
// Проверяем, выводятся ли в отчет данные по нашему конфиденциальному счету,
// и при необходимости очищаем результат или вызываем исключение.
// Более простой вариант — наложить безусловный отбор в настройках компоновщика:
НастройкиОтчета = КомпоновщикНастроек.Настройки;
// Добавляем принудительный отбор по субконто БанковскиеСчета на уровне схемы компоновки
// для предотвращения вывода секретных данных.
КонецЕсли;
КонецПроцедуры
Мы подробно проанализировали проблему ограничения видимости элементов справочника банковских счетов. Жёсткое кодирование условий внутри RLS ролей (хардкодинг) — это путь, ведущий к проблемам сопровождения и ошибкам.
Для создания гибкой и масштабируемой системы безопасности используем первый способ интеграции в БСП. Если же для вас критически важна максимальная производительность базы данных при формировании бухгалтерской отчетности и вы хотите избежать «тяжелых» SQL-запросов RLS к регистру бухгалтерии, то оптимальным выбором станет второй способ с использованием расширения интерфейса и форм.