Ограничения полей, или как обмануть СКД?
Каждое из ограничений полей можно обойти. Рассмотрим варианты обхода и способы обезопасить свой отчет.
Каждый одинэсник знает, что такое СКД. И каждый видел (а может, даже и использовал) эти замечательные галочки ограничений у полей.
Ограничивать поля иногда приходится, чтобы не дать пользователям нагрузить базу сложными условиями, увидеть “лишнее” или даже исказить результат запроса (с СКД такое бывает).
Но мало кто знает, что эти ограничения можно обойти. Давайте проведём эксперимент?
Делаем простой отчет. Для теста возьмём демо-базу ERP 2.4 (но конфигурация не важна). И платформу 8.3.16.1030. На разных версиях платформы могут отличаться нюансы, однако, в общем, описанное ниже будет работать везде.
Сделаем простенький запросик (ограничим выборку, нам ведь много данных не нужно):
Пока никаких ограничений у полей делать не будем и просто выведем все поля в отчет. А в отбор добавим Организация.ИНН и выведем его в быстрый доступ:
А в ПриКомпоновкеРезультата() добавим код, который будет нам выводить текст выполняемого запроса.
Открываем отчет и выполняем. Как видим, в демо-базе есть несколько документов на организации, у которых не указан ИНН.
Отбор прекрасно сработал
Глянем выполняемый СКД запрос. СКД любит делать параметры с именем “П” =)
Всё работает как надо. А теперь поставим ограничение на использование реквизитов поля “Огранизация” в отборах:
В настройках видно, что наш отбор помечен красным крестиком.
Не будем его удалять, а просто попробуем открыть отчет в базе. Уже на этом этапе можно заметить, что в быстрых настройках отбор всё равно виден:
Но пусть, главное же, что он не сработает. Или же…
Как видим, отбор сработал. Может мы что-то перепутали? Давайте откроем здесь же в предприятии наш вариант по кнопке “Изменить вариант отчета”
Всё верно, отбор помечен красным. И в доступных полях нельзя выбрать реквизиты организации.
А что же стало с наши запросом?
Действительно, отбор сработал. И наложился на запрос, несмотря на ограничения.
А что если мы ограничим не только реквизиты поля, но и самого его?
Выполняем отчет
Отбор опять сработал. А что с остальными ограничениями?
Возьмёмся за ограничение выбора. Сначала выведем в отчет ИНН организации. Ну и для наглядности уберем из запроса ПЕРВЫЕ 10
.
Сделаем вывод реквизитов отдельной колонкой и посмотрим на результат
Всё хорошо. Теперь запретим пользователям выбирать реквизиты поля “Организация”:
И попробуем выполнить отчет снова:
Как видим, ИНН не выводится. Хоть в настройках он и остался:
Но есть одна хитрость… Давайте для начала снова снимем ограничения реквизитов у организации.
Перейдём в пользовательские поля и добавим новое поле выражение:
И выведем его в отчет
Проверим результат в базе
А теперь снова установим ограничение на выбор реквизитов организации
И проверим результат
Поле выводится! А что с запросом?
Да, поле попало в запрос. А что, если запретить выбор самого поля “Организация”?
Формируем отчет:
Поле вывелось. Организация пропала, а пользовательское поле всё равно работает. А что в запросе?
Мы успешно обошли ограничения. Примерно так же обстоят дела и с ограничением на группировки и сортировки. И даже параметры. А ведь на них часто разработчики завязывают логику отчета.
А если снять Автозаполнение?
Есть возможность в СКД отключить галку “автозаполнение” и в запросе полностью описать разрешенные поля.
На этом примере мы в доступных для отбора полях не указали “Организация”
Но это тоже не помогает и отбор сработает:
Но, что интересно, запрос такой:
Заметьте, отбора в запросе нет. Но есть выборка Организация.ИНН. А это значит, что фильтрация произойдёт не на уровне SQL, а на Сервере Приложений 1С. (интересно, как это скажется на скорости)
Установка ограничений на поля в самой СКД опять же не помогает
Но попробуем доработать запрос и убрать у него реквизиты организации из списка доступных к выбору полей. Для этого просто уберём “.*” :
Что теперь будет?
Отбор всё равно сработал. Но интересно, что в запросе нет выбора ИНН организации. Как же 1С фильтрует записи? На самом деле нужно копнуть глубже, а для этого глянем макет компоновки:
Теперь в наборах данных появился набор “ОрганизацияРеквизиты”. А в нём такой запрос
СКД усердно старается выполнить условие, которое должно игнорироваться. Какая сила воли!
Остаётся ещё один вариант - вообще убрать поле “Организация” из доступных к выбору. В этом запросе, оно не указано в {} (хоть и указано в основном запросе).
И что теперь?
Наконец-то! Теперь уж точно пользователи не смогут наложить отбор. Правда и поле вывести… И, конечно, это не решение проблемы. Но эксперимент мы провели)
Ну и зачем нам всё это знать?
Теперь мы знаем, что все ограничения полей в СКД можно обойти настройками. Ну и зачем нам это?
Во-первых, для понимания, как работает СКД. Ограничения влияют на пользовательскую доступность, а не на логику отчета. Частично, СКД проверяет и обрезает поля при формировании. Но не всегда, не везде и не совсем =)
Во-вторых, когда вы столкнётесь со странной ситуацией, вы вспомните об этой статье.
Да, в наших примерах мы специально создавали такую ситуацию. Но она может возникнуть (и возникает) и без вашего желания.
Пример из жизни. Жил да был сложный отчет с большим запросом. И пользователи любили в этом отчете выводить реквизиты регистратора. И реквизиты реквизитов регистратора. И делать на них отборы (да ещё и на табличные части). И сильно нагружали этим базу. Аналитики поговорили с пользователями, уточнили все их нужды и разработчик доработал запрос отчета так, чтобы он удовлетворял потребностям пользователей, но при этом меньше нагружал базу. А на поле “Регистратор” наложил ограничения реквизитов. Всё вроде бы хорошо, но в базе осталось множество пользовательских вариантов отчетов, которые содержали отборы типа “Регистратор.Реквизит.Реквизит”. И, несмотря на ограничения в СКД, отчет всё равно нагружал базу, ведь отборы работали.
А есть ещё один интересный способ. Ведь у нас есть возможность сохранить настройки в файл.
И загрузить из файла 😉
Есть такие пользователи, которые любят хранить настройки в файлах. А потом загружать их после обновления базы, боясь, что что-то сломается.
А ещё однажды попался такой умный (и упрямый) пользователь, который любил ковыряться в 1С, лазить в структуре файлов и так далее. В общем, хобби такое у человека. И когда разработчики наложили в одном отчете ограничение на отбор по реквизитам, он воспринял это как вызов. Сохранил настройки в файл, отредактировал их в XML и загрузил обратно. Ну и продолжил нагружать базу своими хитровычурными отборами дальше.
Вот так выглядит наш отбор по ИНН в XML:
А однажды мы нашли ситуацию, когда пользовательский вариант отчета накладывал значение на скрытый параметр. А от него зависела логика варианта отчета. Так что всякое в жизни случается =)
Хотите ещё один способ нарушить правила?
В режиме предприятия заходим в “Изменить вариант”. Как видите, наложить отбор ни на ИНН ни на Организацию нельзя:
Нажимаем волшебную кнопку “Изменить форму”
В элементах находим “Доступные поля полей” и переносим на закладку с отборами:
Теперь у нас слева таблица с доступными к выбору полями, по центру с доступными к отбору, а справа сам отбор.
А сейчас просто мышкой переносим поле Организация.ИНН с самой левой таблицы в самую правую. Как вам результат?)
Да, поле с красным крестиком. Но отбор всё равно сработает.
И что же теперь делать? Вот мы приблизились к решению. И оно простое:
Этот метод хорош и будет спасать нас в большинстве случаев. Если в ПриКомпоновкеРезультата() вы вставите этот метод, то убережёте себя от большинства таких проблем. Просто, не правда ли? Но крайне редко такое делается.
Однако, не все ситуации он обрабатывает. И, к сожалению, он не работает с той ситуацией, которая позволяет пользователю легко нарушать ограничения отборов:
Помните пользовательские поля? Давайте поиграем. Возьмем такой запрос:
У нас нет возможности фильтровать ни по организации, ни по её реквизитам. А теперь добавляем новое пользовательское поле (даже в режиме предприятия).
И делаем на него отбор
И что получится?
Вуаля! Мы обошли запреты.
При этом в доступных к отбору полях организации нет.
И вишенка на торте. КомпоновщикНастроек.Восстановить() НЕ ПОМОГАЕТ.
В данной ситуации, пользовательское поле не является запрещенным. И при его помощи можно наложить и отборы. Можно наложить отборы и сложнее:
Вот такой при этом будет запрос
Какие выводы?
У СКД нет жёстких ограничений.
Но если вдруг нам очень уж нужно, то:
- Используйте КомпоновщикНастроек.Восстановить()
- Снимайте галку “Автозаполнение” (вы ещё ей пользуетесь?)
- При обновлении отчётов, обрабатывайте пользовательские варианты
- Ограничивать не только отбор подчиненных, но и выбор Таким образом вы сможете минимизировать вероятность того, что пользователь обойдет ваши запреты.
UPDATE: поддержка 1С ответила следующее:
Описанное в статье поведение СКД является штатным, то есть ограничения полей влияют только на новую настройку отборов пользователя в интерактивном режиме, старые настройки пользователей (в т.ч., загруженные из файла, или программно установленные отборы) будут работать как и ранее.
Посему ожидать какой-то доработки штатной логики ограничений СКД не стоит. Продолжаем самостоятельно выполнять пункты из выводов статьи =)