Все вы знаете, что есть модуль с возможностью выполнения всего под полными правами — за это отвечает галочка «Привилегированный».
На текущем месте работы у нас такой модуль используется для логирования. У нас есть регистр сведений, на который у обычных пользователей нет права даже на чтение; запись в этот регистр происходит при помощи модуля с привилегированным режимом.
Вдруг понадобилось создать временную внешнюю обработку для выполнения внутреннего функционала, который использует логирование через модуль, описанный выше. И получилось так, что логирование перестало работать, по причине нехватки прав.
Хотя даже не так. Мне сказали починить, но я поначалу не мог повторить нехватку прав, так как у меня всё срабатывало и нормально работало. Сейчас я понимаю, что мне, видимо, «дико везло», так как когда я тестировал — поймал некорректное поведение системы.
Немного сумбурно?
Давайте всё по порядку.
Я смог смоделировать данную ситуацию дома, поэтому рассказываю, как это повторить, чтобы стало понятно.
1 Я взял последнюю версию БСП и включил возможность доработки.
2 Добавил регистр сведений «дсЛогирование»:
3 Создал привилегированный модуль «дсЛогированиеРежимБогаСервер»:
Функция ЗаписьЛога(Ключ,СборщикЛога)Экспорт
Место = "дсЛогированиеРежимБогаСервер.ЗаписьЛога";
Результат = Истина;
// ++
текМесто = СтрШаблон("[ДоЗаписи] %1",Место);
СборщикЛога.Добавить(Новый Структура("Период,Место,Включен",
ТекущаяДатаСеанса(),текМесто,ПривилегированныйРежим()));
// --
ДатаВремя = ТекущаяДатаСеанса();
ТипЛога = Перечисления.дсТипЛога.Информация;
Попытка
НаборЗаписей = РегистрыСведений.дсЛогирование.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.ДатаВремя.Установить(ДатаВремя);
НаборЗаписей.Отбор.Ключ.Установить(Ключ);
НаборЗаписей.Отбор.ТипЛога.Установить(ТипЛога);
НаборЗаписей.Прочитать();
Если НаборЗаписей.Количество() = 0 Тогда
НоваяЗаписьРегистра = НаборЗаписей.Добавить();
НоваяЗаписьРегистра.ДатаВремя = ДатаВремя;
НоваяЗаписьРегистра.Ключ = Ключ;
НоваяЗаписьРегистра.ТипЛога = ТипЛога;
Иначе
НоваяЗаписьРегистра = НаборЗаписей[0];
КонецЕсли;
НоваяЗаписьРегистра.Информация = "ЗаписьЛога";
НаборЗаписей.Записать();
Исключение
Результат = Ложь;
ТекстОшибки = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
ЗаписьЖурналаРегистрации("Ошибка",УровеньЖурналаРегистрации.Ошибка,,,СтрШаблон("%1 - Ошибка:%2",Место,ТекстОшибки));
КонецПопытки;
Если Не Результат Тогда
СборщикЛога.Добавить(Новый Структура("Период,Место,Включен",
ТекущаяДатаСеанса(),
СтрШаблон("%1 - Ошибка:%2",Место,ТекстОшибки),
ПривилегированныйРежим()));
КонецЕсли;
// ++
текМесто = СтрШаблон("[ПослеЗаписи] %1",Место);
СборщикЛога.Добавить(Новый Структура("Период,Место,Включен",
ТекущаяДатаСеанса(),текМесто,ПривилегированныйРежим()));
// --
Возврат Результат;
КонецФункции
Примечание:
СборщикЛога – Массив структур в котором я отмечаю время запуска, место запуска, наличие\отсутствие привилегированного режима.
Место – текстом написан название модуля и функции. Используется для логирования.
Ключ – Тип запуска. Обычный запуск или через фоновое задание.
5 Создал модуль без привилегированного режима «дсЛогированиеСервер», в котором вызываю функцию из привилегированного модуля:
Процедура ОбычныйЗапуск(Ключ="ОбычныйЗапуск", СборщикЛога=Неопределено, АдресРезультата = "") Экспорт
Место = "дсЛогированиеСервер.ОбычныйЗапуск";
Если Не ЗначениеЗаполнено(СборщикЛога) Тогда
СборщикЛога = Новый Массив;
КонецЕсли;
// ++
текМесто = СтрШаблон("[ДоЗаписиВЛог] %1",Место);
СборщикЛога.Добавить(Новый Структура("Период,Место,Включен",
ТекущаяДатаСеанса(),текМесто,ПривилегированныйРежим()));
// --
дсЛогированиеРежимБогаСервер.ЗаписьЛога(Ключ,СборщикЛога);
// ++
текМесто = СтрШаблон("[ПослеЗаписиВЛог] %1",Место);
СборщикЛога.Добавить(Новый Структура("Период,Место,Включен",
ТекущаяДатаСеанса(),текМесто,ПривилегированныйРежим()));
// --
Если ЗначениеЗаполнено(АдресРезультата) Тогда
ПоместитьВоВременноеХранилище(СборщикЛога,АдресРезультата);
КонецЕсли;
КонецПроцедуры
Примечание:
СборщикЛога – Массив структур в котором я отмечаю время запуска, место запуска, наличие\отсутствие привилегированного режима.
Место – текстом написан название модуля и функции. Используется для логирования.
Ключ – Тип запуска. Обычный запуск или через фоновое задание.
АдресРезультата – При запуске в фоновом задании по данному адресу будет сохранен СборщикЛога.
6 Добавил обработку для выполнения логирования «дсПривилегированныйРежим»:
В обработке есть две кнопки «Обычный запуск» и «Обычный запуск ФЗ». Есть таблица значений для вывода информации из сборщика логов.
&НаКлиенте
Процедура ОбычныйЗапуск(Команда)
ОбычныйЗапускНаСервере();
КонецПроцедуры
&НаСервере
Процедура ОбычныйЗапускНаСервере()
ПройденныйПуть.Очистить();
СборщикЛога = Новый Массив;
дсЛогированиеСервер.ОбычныйЗапуск("ОбычныйЗапуск",СборщикЛога);
Для Каждого ТекущийЛог из СборщикЛога Цикл
НоваяСтрока = ПройденныйПуть.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, ТекущийЛог);
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ОбычныйЗапускФЗ(Команда)
ОбычныйЗапускФЗНаСервере();
КонецПроцедуры
&НаСервере
Процедура ОбычныйЗапускФЗНаСервере()
ПройденныйПуть.Очистить();
СборщикЛога = Новый Массив;
ПараметрыВыполнения = Новый Массив;
ПараметрыВыполнения.Добавить("ОбычныйЗапускФЗ");
ПараметрыВыполнения.Добавить(СборщикЛога);
ИдентификаторФЗ = Строка(Новый УникальныйИдентификатор);
АдресХранилища = ПоместитьВоВременноеХранилище(Неопределено, УникальныйИдентификатор);
ПараметрыВыполнения.Добавить(АдресХранилища);
ФоновыеЗадания.Выполнить("дсЛогированиеСервер.ОбычныйЗапуск",
ПараметрыВыполнения,ИдентификаторФЗ,"ОбычныйЗапускФЗ");
Задания = ФоновыеЗадания.ПолучитьФоновыеЗадания(
Новый Структура("Ключ,Наименование",ИдентификаторФЗ,"ОбычныйЗапускФЗ"));
Если Задания.Количество() > 0 Тогда
Задание = Задания[0];
Задание = Задание.ОжидатьЗавершенияВыполнения(10);
Пока Задание.Состояние = СостояниеФоновогоЗадания.Активно Цикл
Задание = Задание.ОжидатьЗавершенияВыполнения(10);
КонецЦикла;
СборщикЛога = ПолучитьИзВременногоХранилища(АдресХранилища);
Если ТипЗнч(СборщикЛога) = Тип("Массив") Тогда
Для Каждого ТекущийЛог из СборщикЛога Цикл
НоваяСтрока = ПройденныйПуть.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, ТекущийЛог);
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Схема работы запуска из конфигуратора.
Схема работы запуска из внешней обработки.
Если кратко, то всё работает так же, но в момент логирования — как повезёт.
Может отработать с привилегированным режимом, а может — без.
При этом стандартное поведение, заложенное фирмой 1С, должно работать без привилегированного режима.
То есть в моём случае как раз должна происходить нехватка прав!
Вот так:
Но, если вы посмотрите видео выше, то увидите, что при запуске в режиме фонового задания иногда будет вот такая картина. Которая показывает, что все работает вопреки.
Я не могу понять, как оно отрабатывает, такое ощущение, что в самой платформе что-то периодически перезапускается, и в момент перезапуска можно поймать момент, когда стандартные проверки ещё не применились…
Но это, как говорится, — «мысли вслух»😉
Как сделать, чтобы логирование работало?
1 Создать нужные роли, дающие права на регистр.
2 Если у вас конфигурация с БСП, тогда можно добавить обработку в подсистему «Дополнительные обработки и отчеты» с выключенным режимом безопасности.
3 Если у вас конфигурация без БСП или вы не хотите использовать «Дополнительные обработки и отчеты», можно добавить команду, обработку или еще что-то в конфигуратор открывающее вашу обработку:
Пример -> https://its.1c.ru/db/metod8dev/content/3556/hdoc
&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
//Помещаем обработку во временном хранилище
АдресХранилища = "";
Результат = ПоместитьФайл(АдресХранилища, "C:\ВнешняяОбработка.epf", , Ложь);
ИмяОбработки = ПодключитьВнешнююОбработку(АдресХранилища);
// Откроем форму подключенной внешней обработки
ОткрытьФорму("ВнешняяОбработка."+ ИмяОбработки +".Форма");
КонецПроцедуры
&НаСервере
Функция ПодключитьВнешнююОбработку(АдресХранилища)
ОписаниеЗащиты = Новый ОписаниеЗащитыОтОпасныхДействий;
ОписаниеЗащиты.ПредупреждатьОбОпасныхДействиях = Ложь;
Возврат ВнешниеОбработки.Подключить(АдресХранилища,,Ложь,ОписаниеЗащиты);
КонецФункции
4 Настроить профиль безопасности.
Может быть, есть еще варианты, но я думаю, достаточно и этих.
На этом статью завершаю.
Надеюсь, кто-то сэкономит время, а кто-то починит этот баг 😉
Всем интересных задач и удачи!
Вступайте в нашу телеграмм-группу Инфостарт