В практике разработчика 1С часто возникает задача: выполнить операцию, на которую у текущего пользователя нет прав. Типичный пример — удаление ошибочно созданных документов в конфигурации «Управление торговлей 10.3» или других решениях на обычных формах. При попытке выполнить Удалить() система выбрасывает ошибку «Нарушение прав доступа!», а стандартный метод УстановитьПривилегированныйРежим(Истина) внутри внешней обработки почему-то не срабатывает. Давайте детально разберем, почему это происходит и как правильно решить задачу.
Проанализируем архитектуру «1С:Предприятия». Главная причина неудачи заключается в контексте выполнения кода. В обычном приложении код, написанный в модуле формы (даже внешней обработки), всегда выполняется на стороне клиента. Метод УстановитьПривилегированныйРежим() предназначен для выполнения на сервере (или в файловом варианте). В клиент-серверном варианте вызов этого метода на клиенте просто игнорируется платформой: он не выдает ошибку, но и не расширяет права пользователя. Проверить это можно с помощью функции ПривилегированныйРежим(), которая в таких условиях всегда будет возвращать Ложь.
Рассмотрим основные шаги и решения для обхода этого ограничения.
Это самый надежный и правильный способ с точки зрения архитектуры 1С. Поскольку нам нужно выполнить код на сервере с полными правами, мы должны вынести процедуру удаления в специальное место в конфигурации.
РаботаСОбъектамиПривилегированная).Пример кода в общем модуле:
Процедура УдалитьОбъектНаСервере(СсылкаНаОбъект) Экспорт
// Получаем объект из ссылки, так как метод Удалить() доступен только у объекта
Объект = СсылкаНаОбъект.ПолучитьОбъект();
Если Объект <> Неопределено Тогда
// Отключаем проверки бизнес-логики, которые могут помешать удалению
Объект.ОбменДанными.Загрузка = Истина;
Объект.Удалить();
КонецЕсли;
КонецПроцедуры
Теперь в вашей внешней обработке (в модуле формы) достаточно вызвать эту процедуру:
Процедура КоманднаяПанельУдалить(Кнопка)
// Цикл по выборке документов
Пока Выборка.Следующий() Цикл
РаботаСОбъектамиПривилегированная.УдалитьОбъектНаСервере(Выборка.Ссылка);
КонецЦикла;
КонецПроцедуры
Иногда ошибка прав доступа возникает не из-за отсутствия права на само удаление, а из-за срабатывания подписок на события или кода в модуле документа (например, при попытке отменить проведение или проверить остатки). Чтобы минимизировать влияние стороннего кода, всегда используйте свойство ОбменДанными.Загрузка = Истина.
Проанализируем ситуацию: когда мы устанавливаем этот флаг, платформа понимает, что объект записывается (или удаляется) в режиме обмена, и пропускает большинство проверок в процедурах ПередЗаписью, ПриЗаписи, ПередУдалением. Это не заменяет права на удаление, но часто решает проблему косвенных блокировок.
Если вы используете современные конфигурации, где внешние обработки подключаются через справочник «Дополнительные отчеты и обработки» (БСП), обратите внимание на Безопасный режим. Если обработка запущена в безопасном режиме, то использование привилегированного режима в ней запрещено программно на уровне платформы.
Выясним причину: безопасность системы 1С блокирует попытки расширения прав из недоверенных внешних файлов. Чтобы это обойти, при регистрации обработки необходимо указать режим работы «Небезопасный» (или «Разрешить расширенные права»), что потребует прав администратора при настройке.
Если вы категорически не можете вносить изменения в конфигурацию (добавлять общий модуль), существует «хитрый» способ — использование COM-соединения к этой же самой базе.
V83.COMConnector) с текущей базой данных.Delete().Посмотрим на пример логики:
// Пример логики (упрощенно)
Connector = Новый COMОбъект("V83.COMConnector");
База = Connector.Connect("Srvr='ServerName';Ref='BaseName';Usr='Admin';Pwd='123'");
ДокументОбъект = База.Документы.РеализацияТоваровУслуг.FindByNumber("001", Дата).GetObject();
ДокументОбъект.Delete();
Поскольку сессия через COM работает под администратором, права текущего пользователя в текущем сеансе не будут иметь значения.
Ссылка.ПолучитьОбъект() может возвращать ошибку?Важный нюанс: если в системе настроены ограничения RLS (Record Level Security) на уровне записей, пользователь может даже не иметь прав на «Чтение» этого документа. В таком случае метод ПолучитьОбъект() вернет Неопределено или вызовет ошибку прав еще до вызова удаления. Именно поэтому вынос кода в привилегированный модуль на сервере является единственным системным способом решения, так как серверный контекст с полными правами «видит» все записи базы данных, игнорируя настройки RLS.
Резюме: для успешного удаления документов без прав в обычном приложении необходимо перенести логику на сервер в привилегированный общий модуль и использовать флаг ОбменДанными.Загрузка для обхода логических проверок.