Проверка доступности прав на уровне RLS на запись объекта

1. a45 88 24.03.16 10:26 Сейчас в теме
Доброго времени суток.

подскажите есть ли штатный (или может какие-то наработки) механизм проверки прав доступа на уровне RLS на запись объекта ?

на Справочник ХХХ назначены RLS на запись, перед определённой обработкой необходимо проверить объект на доступность прав по RLS, если нет то прервать обработку, если есть то создать несколько объектов и изменить значение в проверяемом объекте.
По теме из базы знаний
Ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
3. ZergKRSK 130 24.03.16 10:39 Сейчас в теме
(1) a45, может ПравоДоступа ?..
whilefor; +1 Ответить
6. vovan_victory 65 24.03.16 11:08 Сейчас в теме
(1) a45, как вариант

Попытка
Процедура ПередЗаписью(Отказ)
......
НовыйЭлементСправочника.Записать();
Исключение
Отказ = Истина;
КонецПопытки;
....
КонецПроцедуры
Показать


Если прав нет, то при записи получиться ошибка.
7. a45 88 24.03.16 11:14 Сейчас в теме
(6)
да, сейчас на подобном варианте остановился, не совсем конечно то что надо - ибо есть реквизиты (редактор, дата изменения) которые изменяются подпиской, если Объект.Записать() то эти реквизиты перезаполнятся, а на 2м этапе пользователь переобуется (отменит ввод) - получится зазря первоначальный элемент записывали...
9. vovan_victory 65 24.03.16 11:20 Сейчас в теме
(7) a45, ну так перенесите перезаполнение этих реквизитов после попытки. Правда тогда придется еще раз записывать объект, но зато, данные будут меняться только в нужный момент.
14. _liana 13.04.20 20:07 Сейчас в теме
(6) мне помог такой вариант ... если попытка прочитать конкретное поле конкретного документа удачно заканчивается - то работаю с данными этого документа, если Исключение - то права не дают.ю я пропускаю такой объект
15. vovan_victory 65 13.04.20 21:32 Сейчас в теме
(14)
Глобальный контекст (Global context)
ПравоДоступа (AccessRight)
Синтаксис:
ПравоДоступа(<Право>, <ОбъектМетаданных>, <Пользователь/Роль>, <СтандартныйРеквизитСтандартнаяТабличнаяЧасть>)

Справочник = Метаданные.Справочники.Конкуренты;
Если Не ПравоДоступа("Чтение", Справочник) Тогда
    Предупреждение(НСтр("ru = 'Доступ к данному справочнику закрыт!';"
     + " en = 'Access denied!'"));
КонецЕсли;
16. _liana 14.04.20 10:26 Сейчас в теме
(15) нет, это не то

У меня в запросе собираются документы Реализация по отбору, причём часть из этих документов закрыто по RLS для пользователя (Контрагент в недоступной ему группе доступа).
Так вот проблема была, когда обращаешься к реквизитам отобранных документов, если документ для данного пользователя запрещен для просмотра ... выходит ошибка.
Через Попытку я проверяю возможность прочитать реквизит:
* если не читаемо, то я НЕ делаю обращение к реквизитам, но сам документ вывожу в отчет (это даёт сделать),
* если читаемо - то дополнительно реквизиты вывожу в отчет

Меня это полностью устраивает )))

PS
в запросе мне не надо фильтровать "ТОЛЬКО РАЗРЕШЕННЫЕ", так как в отчет должны попасть все документы по отбору, включая запрещенные к просмотру у данного пользователя.
2. AnryMc 848 24.03.16 10:33 Сейчас в теме
Ну... Лично я такого не знаю, но

РЛС пишется для Роли и решение МОЖНО/НЕЛЬЗЯ принимается в результате выполнения запроса,

так что в крайнем случае можно для определенных Ролей проанализировать результат аналогичного запроса...
8. a45 88 24.03.16 11:17 Сейчас в теме
(2)
РЛС только на "Запись", чтение свободное.

(3),(5)
ПравоДоступа() - это на весь справочник, нужно на конкретную запись
10. Perrojka 24.03.16 11:20 Сейчас в теме
(8) a45, Ну как вариант - поискать пользователя в регистрах там где РЛС настраивается. И на основе данных запроса допускать к транзакции или нет. Не самый приятный способ для реализации.
4. whilefor 24.03.16 10:42 Сейчас в теме
Должно помочь:
"Если ПравоДоступа("Редактирование", ТвойОбъект,) Тогда"
Восьмой; +1 Ответить
5. AnryMc 848 24.03.16 10:48 Сейчас в теме
(4) whilefor, (3) ZergKRSK,

"Право доступа" и "Выполнить проверку прав доступа" - судя по описанию - делают это с ОБЪЕКТОМ МЕТАДАННЫХ а не с ЭЛЕМЕНТОМ.

Т.е. можно проверить право на запись всего справочника (как задано в конфигураторе), а не к конкретной записи (элементу) данного справочника с учетом ограничений РЛС.
limonas; PLAstic; ellavs; Восьмой; +4 Ответить
11. ellavs 1043 23.07.19 22:11 Сейчас в теме
Возникла аналогичная задача, нужно показать кнопку в зависимости от наличия права доступа к определенному документу. Кнопка позволяет добавлять связанные с этим документом документы. Использовать проверку через "Запись" - не вариант, т.к. просто так перезаписывать "объект проверки права" не желательно.
Решение не нашлось?
12. Viktor_Ermakov 369 24.07.19 17:32 Сейчас в теме
Так же есть потребность в этом. Я пока ничего не нашел штатного или в БСП хотя там есть интересная функция: УправлениеДоступом.ЕстьПраво()...
Но для того что бы ей пользоваться, нужно что то еще записывать в регистры.

Я думаю самый простой вариант, и без костылей, сделать запрос к объекту метаданных с "РАЗРЕШЕННЫЕ" и проверить результат на вхождение требуемой ссылки, если ее там нет, значит доступа нет, ну и наоборот!)
justaria; Vyacheslav_Kochnev; +2 Ответить
13. ellavs 1043 25.07.19 08:22 Сейчас в теме
(12)
сделать запрос к объекту метаданных с "РАЗРЕШЕННЫЕ" и проверить результат

Наверно это сработает, если нет доступа на чтение. Как вариант действительно подойдет.
У меня доступ на чтение есть у всех, а на запись - по RLS. Получается никак не проверить, кроме как попыткой записи...
17. Vyacheslav_Kochnev 142 30.11.20 21:21 Сейчас в теме
(12)
УправлениеДоступом

нашёл ещё пару интересных функций в УправлениеДоступом:
УправлениеДоступом.ЧтениеРазрешено(Ссылка);
УправлениеДоступом.ИзменениеРазрешено(Ссылка);

Может кому-то пригодится.

П.С. БСП версии 3.0.3.48
Agrozentr; Surushi; Mizhgan42; annak2980; Diks_Soft; serg1c; BarsukM; vipetrov2; +8 Ответить
18. vipetrov2 18.03.21 07:59 Сейчас в теме
Запрос.Текст = "ВЫБРАТЬ РАЗРЕШЕННЫЕ &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Ссылка);
Если Запрос.Выполнить().Пустой() Тогда
//Нет прав на чтение
КонецЕсли;


С правами на запись сложнее, там надо будет анализировать сами RLS.
Вариант из предыдущего поста рабочий
УправлениеДоступом.ЧтениеРазрешено(Ссылка);
УправлениеДоступом.ИзменениеРазрешено(Ссылка);
21. vladyko_kiu 09.08.23 10:41 Сейчас в теме
(18) Такой запрос не сработал, он возвращает строку со ссылкой "объект не найден..." и запрос уже получается не пустым.
Но, развивая эту мысль, накидал такую функцию:
&НаСервереБезКонтекста
Функция ЧтениеРазрешено(Ссылка)
	
	Если НЕ ЗначениеЗаполнено(Ссылка) Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Запрос = Новый Запрос;
	
	ТаблицаЗапрос = Метаданные.НайтиПоТипу(ТипЗнч(Ссылка)).ПолноеИмя();
	ТаблицаИмя = СтрЗаменить(ТаблицаЗапрос, ".", "");
	
	Запрос.Текст = Запрос.Текст +
	"ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 1
	|	" + ТаблицаИмя + ".Ссылка КАК Ссылка
	|ИЗ
	|	" + ТаблицаЗапрос + " КАК " + ТаблицаИмя + "
	|ГДЕ
	|	" + ТаблицаИмя + ".Ссылка = &Ссылка";
	Запрос.УстановитьПараметр("Ссылка", Ссылка);
	
	Если Запрос.Выполнить().Пустой() Тогда
		Возврат Ложь;
	Иначе
		Возврат Истина;
	КонецЕсли;
	
КонецФункции
Показать

Тестил на 8.3.17, скармливал ссылки на элементы справочников. Предположительно, она много чего жрать должна.
UPD: и да, это только проверка на чтение, не на запись, на вопрос ветки не отвечает.
22. vipetrov2 25.09.23 09:26 Сейчас в теме
(21)
Действительно "ВЫБРАТЬ РАЗРЕШЕННЫЕ" не всегда отрабатывает. Я не знаю почему.

Еще в коде встречал такое

Если СтрНайти(Строка(Ссылка), "объект не найден") > 0 Тогда
      //Нет прав на чтение
КонецЕсли;
19. SanTis_Lugansk 12.08.21 12:56 Сейчас в теме
может так:
Попытка
ЕстьПраво = Истина;
НачатьТранзакцию();
Записать();
ОтменитьТранзакцию();
Исключение
ЕстьПраво = Ложь;
КонецПопытки;
20. Matveev_VS 165 25.01.22 17:17 Сейчас в теме
ВЫБРАТЬ ПЕРВЫЕ 1
ИСТИНА КАК ЗначениеИстина
ИЗ
РегистрСведений.КлючиДоступаКОбъектам КАК КлючиДоступаКОбъектам
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.КлючиДоступаНаборовГруппДоступа КАК РазрешенныеКлючиДоступа
ПО (КлючиДоступаКОбъектам.Объект = &Объект)
И (РазрешенныеКлючиДоступа.КлючДоступа = КлючиДоступаКОбъектам.КлючДоступаПользователей)
И (РазрешенныеКлючиДоступа.НаборГруппДоступа В (&РазрешенныйНаборГруппДоступа, &РазрешенныйПустойНаборГруппДоступа))
И (РазрешенныеКлючиДоступа.Изменение)
23. begemot 269 12.11.23 13:44 Сейчас в теме
Для обычных форм

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

Процедура УстановитьНедоступностьФормы(Форма) Экспорт
	
	Форма.ТолькоПросмотр = Истина;
	
	Для каждого ЭлементФормы Из Форма.ЭлементыФормы Цикл
		ТипЭлемента = ТипЗнч(ЭлементФормы);
		Если ТипЭлемента = Тип("ПолеВвода")
			ИЛИ ТипЗнч(ЭлементФормы) = Тип("ТабличноеПоле")
			ИЛИ ТипЗнч(ЭлементФормы) = Тип("ПолеТабличногоДокумента") Тогда
			ЭлементФормы.ТолькоПросмотр = Истина;
		ИначеЕсли ТипЭлемента = Тип("Кнопка") Тогда
			ЭлементФормы.Доступность = Ложь;
		ИначеЕсли ТипЭлемента = Тип("КоманднаяПанель") Тогда
			ЭлементФормы.Доступность = Ложь;
			УстановитьНедоступностьКнопкамКоманднойПанели(ЭлементФормы.Кнопки);
		КонецЕсли;
	КонецЦикла;
	
КонецПроцедуры

Процедура УстановитьНедоступностьКнопкамКоманднойПанели(Кнопки)
	
	Для каждого Кнопка Из Кнопки Цикл
		Если Кнопка.ТипКнопки = ТипКнопкиКоманднойПанели.Действие Тогда
			Если Кнопка.ИзменяетДанные Тогда
				Кнопка.Доступность = Ложь;
			КонецЕсли;
			ДействиеСтрокой = Строка(Кнопка.Действие);
			Если ДействиеСтрокой = "Записать" ИЛИ ДействиеСтрокой = "Записать и закрыть" Тогда
				Кнопка.Доступность = Ложь;
			КонецЕсли;
		ИначеЕсли Кнопка.ТипКнопки = ТипКнопкиКоманднойПанели.Подменю Тогда
			УстановитьНедоступностьКнопкамКоманднойПанели(Кнопка.Кнопки);
		КонецЕсли;
	КонецЦикла;
	
КонецПроцедуры
Показать
24. Hobbit_Jedi 24.08.24 15:38 Сейчас в теме
По мотивам обсуждения написал вот такое (делюсь - пользуйтесь).

// Назаренко_СВ 2024-08-24
//
// Проверяет доступен ли указанный объект БД для изменения текущему пользователю (с учетом РЛС).
// Если нет права на чтение, то считаем, что и на изменение права нет.
//
//Параметры:
// Ссылка – ЛюбаяСсылка – Ссылка на проверяемый объект БД (Справочник, Документ и т.п.).
//
//Возвращаемое значение:
// Булево – Признак того, что с учетом РЛС данный объект доступен пользователю для изменения.
//
Функция ОбъектДоступенДляИзменения(Ссылка) Экспорт
	ВозвращаемоеЗначение = Истина;
	Если ЗначениеЗаполнено(Ссылка) Тогда
		НачатьТранзакцию();
		Попытка
			Объект = Ссылка.ПолучитьОбъект();
			Объект.ОбменДанными.Загрузка = Истина;
			Объект.Записать();
		Исключение
			Информация = ИнформацияОбОшибке();
			Если ОбработкаОшибок.КатегорияОшибкиДляПользователя(Информация) = КатегорияОшибки.НарушениеПравДоступа Тогда
				ВозвращаемоеЗначение = Ложь;
			Иначе
				ВызватьИсключение;
			КонецЕсли;
		КонецПопытки;
		ОтменитьТранзакцию();
	Иначе
		// Т.к. РЛС не распространяется на еще не записанные объекты, то к пустой ссылке доступ есть всегда.
	КонецЕсли;
	
	Возврат ВозвращаемоеЗначение;
КонецФункции
Показать


*Писал и тестил на 8.3.22.2501.
25. user1880116 24.08.24 16:29 Сейчас в теме
(24)
Писал и тестил
Какой великолепный пример нарушения счетчика вложенных транзакций.

Тестил он...
Hobbit_Jedi; +1 Ответить
26. Hobbit_Jedi 24.08.24 17:37 Сейчас в теме
(25) :))))
Ну да. Точно. Надо еще перед ВызватьИсключение воткнуть ОтменитьТранзакцию();

Благодарю за подсказку.

*Пора на отдых. :)))
27. user1880116 24.08.24 18:29 Сейчас в теме
(26) Да оно все равно у тебя не то проверяет.

Представь что доступ на запись объекта у тебя есть. Ты его записываешь, оно начинает отрабатывать цепочку подписок на запись и где-то внутри получает отлуп по отсутствию прав на чтение.

И всё.
28. Hobbit_Jedi 24.08.24 18:40 Сейчас в теме
(27)
(27)
оно начинает отрабатывать цепочку подписок на запись

Так я. вроде, ОбменДанными.Загрузка.Истина установил, чтоб оно в обработчиках не бродило.
Если конфа в целом кривая, то тут уже ничего не поделать (хуже уже не будет).


Можешь предложить альтернативу для конфигураций без БСП и без того, чтобы перегонять все метаданные в справочники?
29. user1880116 24.08.24 20:14 Сейчас в теме
(28)
ОбменДанными.Загрузка.Истина установил
Ну открой и посмотри, например, БСПшный обработчик ЗаписатьВерсиюДокумента.

хуже уже не будет
Хуже как раз будет. Потому что ты маскируешь исходную ошибку и возвращаешь неверный результат.
30. Hobbit_Jedi 24.08.24 22:29 Сейчас в теме
(29)
открой и посмотри, например, БСПшный обработчик

(28)
для конфигураций без БСП



(28)
Можешь предложить альтернативу?
31. user1880116 25.08.24 10:30 Сейчас в теме
(30) Ты пример кода-то посмотрел? Или увидел три буквы "БСП", возбудился и поскакал?
32. Hobbit_Jedi 25.08.24 18:18 Сейчас в теме
(31)
Ты пример кода-то посмотрел?

Если ты об этом
(29)
Ну открой и посмотри, например, БСПшный обработчик ЗаписатьВерсиюДокумента.

то я думал, что это пример кода, который будет глючить, т.к. ему пофиг на ОбменДанными.Загрузка.

А там есть пример, как определить доступно ли по РЛС пользователю изменение документа, версия которого записывается?


Или ты о каком примере кода?
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот