|
|
|
RLS
|
|||
|---|---|---|---|
|
#18+
Возникла проблема с RLS вида "У пользователя недостаточно прав для на исполнение операции над базой данных". Исходная ситуация такая: 1. Самописная конфигурация. 2. Стандартная модель трехзвенной ИС (клиент 1С - сервер 1С - сервер СУБД). 3. Платформа 1С Предприятие 8.1.15.14. 4. Сервер СУБД - MS SQL 2005 EE SP3 x86. 5. Объектом, в отношении которого используются RLS, является документ "Договор". Задача - ограничить выборку договоров по подразделениям, разрешенным пользователю. 6. Для ограничения доступа используются справочник "Подразделения" с иерархией элементов, по которым собственно и ограничивается выборка договоров, и регистр сведений "ПраваДоступаПользователейКОбъектам", скопированный из типовых конфигураций 1С. 7. На прикладном уровне в регистре сведений по пользователю указывается филиал, по которому выборка договоров должна быть ограничена, а также уровень доступа, по которому производится ограничение - "Чтение", "Добавление", "Изменение". Т.е. пользователь должен видеть только те договора, в которых указанный филиал совпадает с филиалом, указанным в его настройках в регистре сведений. Пользователь должен также видеть все договора, в которых подразделения подчиняются по иерархии элементов филиалу. Все эти средства ограничения доступа частично скопированы с типовых конфигураций 1С (УПП), а частично написаны самостоятельно. Приведу конкретный пример ограничения RLS, установленного на право "Чтение" документа "Договор": Код: plaintext где: ВладелецДоговора - СправочникСсылка.Подразделения. &ПодразделенияПользователяНаЧтение - параметр сеанса, заполняемый фиксированным массивом подразделений. Массив разрешенных подразделений ПриНачалеРаботыСистемы() вычисляется своими запросома, плюс туда же добавляется само подразделение, указанное в РС. После всех этих прелюдий - внимание, проблема! Пользователю необходимо провести договор "задним числом". Но он не может этого сделать и обращается ко мне. Вот что накопал я в отладчике: 1. Если пользователь пытается ЗАПИСАТЬ или ПРОВЕСТИ новый документ с датой, меньшей, чем текущая, то платформа выдает сообщение "У пользователя недостаточно прав...". 2. Если пользователь пытается ЗАПИСАТЬ или ПРОВЕСТИ новый документ с датой, равной текущей, то все проходит нормально. 3. Если пользователь открывает документ, сохраненный в предыдущем пункте, и меняет текущую дату на дату "заднего числа", то документ записывается и проводится нормально. Поэтому возник вопрос - причем тут дата? Расследование в отладчике показало, что сообщение "У пользователя..." платформа выдает еще до исполнения события формы ПередЗаписью(). И вот тут начинается самое интересное! Профайлером был отловлен запрос, который платформа выдает сиквелу еще до исполнения события формы ПередЗаписью(). Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.07.2010, 14:32 |
|
||
|
RLS
|
|||
|---|---|---|---|
|
#18+
Большой список уникальных идентификаторов подразделений, перечисленный в запросе - это тот самый фиксированный массив разрешенных пользователю подразделений. При этом попытка выполнить этот запрос непосредственно на сиквеле вызывает такую ошибку: Код: plaintext 1. Насколько я понял, ошибка возникает в случае, когда сиквел во внутреннем Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. Код: plaintext 1. Для проверки этой теории я принудительно задал числовой тип с плавающей запятой, закомментировав строки с тегом "оригинальный код" и раскомментировав строки с "тестовый код". Результат выборки такой: 2010-06-04 15:31:51.000 0x90C1005056BA636711DF72D87102A470 4000000000.02010-06-04 15:31:50.000 0x90C1005056BA636711DF72D87102A46C 4000000000.02010-06-04 15:31:49.000 0x8D1D005056BA636711DF6FAEAA313EB1 4000000000.02010-06-04 14:39:22.000 0x8D1D005056BA636711DF6FAEAA313EA4 4000000000.02010-06-04 14:26:12.000 0x8D1D005056BA636711DF6FAEAA313E9E 4000000000.02010-06-04 14:24:10.000 0x8268005056BA1CA711DF6FB4C56972FA 4000000000.02010-06-04 14:23:06.000 0x8268005056BA1CA711DF6FB4C56972F8 4000000000.02010-06-04 14:21:46.000 0x8268005056BA1CA711DF6FB4C56972F6 4000000000.02010-06-04 14:20:02.000 0x8268005056BA1CA711DF6FB4C56972F4 4000000000.02010-06-04 14:18:26.000 0x8268005056BA1CA711DF6FB4C56972F2 4000000000.02010-06-04 12:05:46.000 0x8D1D005056BA636711DF6FAEAA313E9A 4000000000.02010-06-04 12:04:04.000 0x8D1D005056BA636711DF6FAEAA313E96 4000000000.02010-06-04 11:58:33.000 0x8D1D005056BA636711DF6FAEAA313E8D 4000000000.02010-06-04 11:56:22.000 0x8D1D005056BA636711DF6FAEAA313E89 4000000000.02010-06-04 11:27:40.000 0x8268005056BA1CA711DF6FAA199F5974 4000000000.02010-06-04 11:01:42.000 0x8268005056BA1CA711DF6FA7071384A8 2000000000.02010-06-04 10:41:12.000 0x8268005056BA1CA711DF6F9C5F665573 4000000000.02010-06-04 10:36:56.000 0x8268005056BA1CA711DF6F9C5F665571 4000000000.02010-06-04 10:32:39.000 0x8268005056BA1CA711DF6F9C5F66556F 4000000000.02010-06-04 10:24:29.000 0x8268005056BA1CA711DF6F9C5F66556B 4000000000.02010-06-04 10:23:56.000 0x8268005056BA1CA711DF6F9C5F66556A 4000000000.02010-06-04 10:23:27.000 0x8268005056BA1CA711DF6F9C5F665569 4000000000.02010-06-04 09:46:46.000 0x8268005056BA1CA711DF6F9C5F665565 4000000000.02010-06-04 09:46:14.000 0x8268005056BA1CA711DF6F9C5F665564 4000000000.02010-06-04 09:45:25.000 0x8268005056BA1CA711DF6F9C5F665563 4000000000.02010-06-04 00:00:00.000 0x8D1D005056BA636711DF6FAEAA313E91 4000000000.0 Представленный список - это выборка СУЩЕСТВУЮЩИХ перед вставкой нового документа в базу договоров. Причем только один из них был введен по разрешенному пользователю подразделению (_f_1 = 2000000000.0). Т.е. 25 из 26 полученных договоров вызовут арифметическое переполнение. Но вот что меня удивляет и чего я не понимаю: 1. Почему запрос RLS Код: plaintext Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 2. Как договора с неразрешенными подразделениями оказались в выборке? По моим расчетам, там должен был оказаться только один договор 2010-06-04 11:01:42.000 0x8268005056BA1CA711DF6FA7071384A8 2000000000.0 3. И почему платформа посылает этот запрос ДО записи в базу данных? Это точно, потому что я профайлером отлавливал все запросы, приходящие к СУБД от момента нажатия кнопки "Записать" в форме до момента исполнения обработчика события ПередЗаписью() формы документа? Отлавливая все запросы при записи документа в текущей дате, все происходит нормальным образом (все обработчики обрабатывают успешно, отказов никто не дает, кроме того, неинтересные места пропущены), т.е.: 1. Выполняется обработчик события формы документа ПередЗаписью(). 2. Выполняется обработчик события формы документа ПриЗаписи(). 3. На сиквеле выполняется команда BEGIN TRANSACTION (платформа неявно начинает транзакцию, т.к. управление блокировками документа - автоматически). 4. Выполняется обработчик события модуля документа ПередЗаписью(). 5. На сиквеле выполняется команда INSERT INTO _Document68 WITH(REPEATABLEREAD) и в таблицу документа заносятся все его данные. 6. Выполняется такой вот интересный запрос: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. Вот тут, как я понял, еще раз выполняется проверка RLS, наверное, на право добавить новый договор, и опять мы проверяем входимость подразделения договора в список разрешенных. 7. Выполняется обработчик ПриЗаписи(). 8. На сиквеле выполняется команда COMMIT TRANSACTION. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.07.2010, 15:23 |
|
||
|
RLS
|
|||
|---|---|---|---|
|
#18+
И еще маленькое дополнение к теме. Я читал в интернете, что RLS-ные запросы по-разному выполняются в зависимости от версии сиквела (2000 или 2005). Так вот, я решил проверить эту теорию. Таблицу _Document68 документа "Договор" я скопировал на MS SQL Server 2000 SP4, также имеющийся у нас, и выполнил там запрос RLS, который я приводил в начале темы. Результат одинаков - оба сиквела, и 2000, и 2005 выдают сообщение об арифметическом переполнении. Вопросы у меня к Вам в дополнение к ранее заданным: 1. Почему платформа посылает запросы RLS еще до вставки нового документа в базу?! 2. И как (и можно ли вообще) обойти это желание платформы выполнить запрос RLS в базу по СУЩЕСТВУЮЩИМ!!! в базе документам в то время, когда записываемого договора еще в базе нет?! Он же в этот момент существует пока только в ОЗУ клиента как объект вида ДокументОбъект.Договор. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.07.2010, 15:35 |
|
||
|
RLS
|
|||
|---|---|---|---|
|
#18+
То, что сообщение сиквела Код: plaintext 1. Код: plaintext Но что за странные фокусы такие с 2 и 4 миллиардами?! Зачем принудительно вызывать переполнение на сиквеле?! И еще не знаю, слух не слух... Мне сказали, что выбор сиквелом по умолчанию типа int обусловлен неверными настройками языка операционной системы - или сиквела, или клиента, или сервера 1С. Мол, при правильных языковых настройках он бы писал не 200000000000, а 200000000000.0, а это уже нормально обрабатывается движком сиквела (без арифметического переполнения). Это так? Кто-нибудь может подтвердить или опровергнуть эту теорию? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.07.2010, 15:43 |
|
||
|
RLS
|
|||
|---|---|---|---|
|
#18+
И еще вопрос :) - может на преждевременное выполнение запроса RLS как-то влиять режим проведения документа (выключено, включено с разрешением оперативного проведения, включено с запретом оперативного проведения)? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.07.2010, 15:46 |
|
||
|
RLS
|
|||
|---|---|---|---|
|
#18+
Up. Никто ничего не можетответить по возникшим проблемам? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.07.2010, 11:19 |
|
||
|
RLS
|
|||
|---|---|---|---|
|
#18+
отвечу на часть. сам не понял до конца в чём цимус. GrayMagellan Но что за странные фокусы такие с 2 и 4 миллиардами?! Зачем принудительно вызывать переполнение на сиквеле?! Ну так действительно может выглядить проверка доступа на чтение к текущему документу. Сделали SELECT TOP 1 если нет доступа то вываливается ошибка и всё откатывается. ну пускай. 0x000000000 это ссылка на текущий документ (пока он не записан). И еще не знаю, слух не слух... Мне сказали, что выбор сиквелом по умолчанию типа int обусловлен неверными настройками языка операционной системы - или сиквела, или клиента, или сервера 1С. Мол, при правильных языковых настройках он бы писал не 200000000000, а 200000000000.0, а это уже нормально обрабатывается движком сиквела (без арифметического переполнения). Это так? Кто-нибудь может подтвердить или опровергнуть эту теорию? это НЕ так. всегда будет переполнение. WHERE ( _Document68._Date_Time > {ts '2010-06-04 00:00:00'} OR _Document68._Date_Time = {ts '2010-06-04 00:00:00'} AND _Document68._IDRRef > 0x00000000000000000000000000000000 ) AND _Document68._Date_Time <= {ts '2010-06-04 23:59:59'} AND _Document68._IDRRef <> 0x00000000000000000000000000000000 ORDER BY У меня тоже возникает вопрос причём тут дата. у вас есть другие RLS на этом доке? во всех ролях пользователя? Приведите их тут. Я так понимаю это проверка на наличие других документов в этот день. Она из неоткуда чтоли взялась? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.07.2010, 16:14 |
|
||
|
RLS
|
|||
|---|---|---|---|
|
#18+
Нет. Других RLS на этот документ нет. Он существует в единственном числе в том виде как я привел в начале темы. Проблема в том, что если я временно убираю TOP 1 и обманываю систему, меняя тип вычисляемого выражения с int на decimal, то получаю такую выборку, как я привел в примере. С тем упорядочиванием (по дате ввода в базу с убыванием), которое задает платформа, в этой выборке первым оказывается договор, введенный 2010-06-04 15:31:51.000 (последний введенный в течение суток 4 июня 2010 года), но подразделение, которое в нем указано, не входит в список, перечисленный во внутреннем CASE, поэтому переменная _f_1 приравнивается к 4 млрд.: _f_2 _f_3 _f_1 2010-06-04 15:31:51.000 0x90C1005056BA636711DF72D87102A470 4000000000.0 Как я понимаю свою проблему, она заключается в том, что RLS запрос платформой упаковывается не в условие WHERE основного запроса, а идет как вычисляемое поле _f_1, и результат вычислений может быть либо 4000000000 (доступа нет), либо 2000000000 (доступ есть). Я думаю, что арифметическое переполнение у сиквела возникает уже в процессе вычисления первой же строчки результата. При этом, насколько я понимаю, все RLS запросы оформляются системой в виде вычисляемого поля во внутреннем кейсе, поэтому я как прикладной программист, пишущий RLS-запрос в Конфигураторе, не могу повлиять на весь SQL-запрос, формируемый платформой. Но может быть можно, написав RLS-запрос по-другому, заставить платформу формировать SQL-запрос без этих дурацких вычислений 2/4 млрд и без арифметического переполнения? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.07.2010, 14:32 |
|
||
|
RLS
|
|||
|---|---|---|---|
|
#18+
Проблема в том, что если я временно убираю TOP 1 и обманываю систему, меняя тип вычисляемого выражения с int на decimal, то получаю такую выборку, как я привел в примере. Да забейте на этот int уже. Считайте что всё правильно тут. При этом, насколько я понимаю, все RLS запросы оформляются системой в виде вычисляемого поля во внутреннем кейсе, поэтому я как прикладной программист, пишущий RLS-запрос в Конфигураторе, не могу повлиять на весь SQL-запрос, формируемый платформой. Не разбираюсь я в RLS к сожалению )) Не похоже что это ваш запрос. дата то откуда здесь? WHERE( _Document68._Date_Time > {ts '2010-06-04 00:00:00'} OR _Document68._Date_Time = {ts '2010-06-04 00:00:00'} AND _Document68._IDRRef > 0x00000000000000000000000000000000 ) AND _Document68._Date_Time <= {ts '2010-06-04 23:59:59'} AND _Document68._IDRRef <> 0x00000000000000000000000000000000 Это тупо проверка на поиск другого документа в этот день которая обламывается потому что нет доступа на чтение к полю Дата(СASE после даты). Откуда берётся проверка я не знаю.фильтр не добавляется в where потому что это встроенный запрос и в нём не указано что надо фильтровать только по разрешённым для пользователя (это можно так). в типовой запрет не стоит на системные поля типа ссылки даты и прочее. они открыты а прочие поля закрыты. может в этом проблема. Совет: Выполните встроенный запрос во внешней обработке 1с "Выбрать ссылка,дата Из Договоры" под этим пользователем и посмотрите во что он оттранслируется. далее для интереса : "Выбрать Разрешенные ссылка,дата Из Договоры". если в первом случае будет такая же ошибка и такой же CASE, то вроде всё ясно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.07.2010, 15:44 |
|
||
|
RLS
|
|||
|---|---|---|---|
|
#18+
Не похоже что это ваш запрос. дата то откуда здесь? WHERE( _Document68._Date_Time > {ts '2010-06-04 00:00:00'} OR _Document68._Date_Time = {ts '2010-06-04 00:00:00'} AND _Document68._IDRRef > 0x00000000000000000000000000000000 ) AND _Document68._Date_Time <= {ts '2010-06-04 23:59:59'} AND _Document68._IDRRef <> 0x00000000000000000000000000000000 А дату, и вообще все это WHERE, платформа сама добавила. Я этого в запрос RLS не ставил. Запрос RLS в Конфигураторе вообще выглядит так: Код: plaintext Фишка в том, что по этому WHERE из базы поступает выборка из 26 договоров. Поля _f_2 и _f_3 - это столбцы таблицы документа. А вот поле _f_1 - вычисляемое. И вот она начинает каждую строчку из этих 26 проверять на условие входимости в список разрешенных подразделений. Если подразделение договора входит, то _f_1 принимает значение 2 000 000 000, а если не входит, то _f_1 принимает значение 4 000 000 000, и вот тут возникает ошибка арифметического переполнения. Как ее обойти? Как составить запрос RLS так, чтобы ее обойти? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.07.2010, 16:14 |
|
||
|
RLS
|
|||
|---|---|---|---|
|
#18+
И еще фишка в том, что в запросах RLS нельзя написать ни "ВЫБРАТЬ", ни "ВЫБРАТЬ РАЗРЕШЕННЫЕ". А так-то я этот запрос RLS конечно в консоли запросов отлаживал. В консоли запросов он выглядит так: Код: plaintext 1. 2. 3. 4. 5. И он прекрасно работает. Я же не делаю там никаких кейсов. У меня в консоли запросов отбор договоров по вхождению разрешенных подразделений идет в конструкции ГДЕ (WHERE), поэтому в выборку приходят только те договора, которые удовлетворяют условию. А в запросе, трансформированном платформой, в условие WHERE идет не отбор договоров по списку, а отбор по суткам даты документа (2010-06-04 - это сутки даты документа, которая равна 04 июня 2010). А мое условие отбора идет как вычисляемое поле _f_3 во внутреннем кейсе. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.07.2010, 16:25 |
|
||
|
RLS
|
|||
|---|---|---|---|
|
#18+
И еще фишка в том, что в запросах RLS нельзя написать ни "ВЫБРАТЬ", ни "ВЫБРАТЬ РАЗРЕШЕННЫЕ". Нет ну я понимаю когда я вас читаю в полглаза, но вы то зачем так со мной )) я ж пытаюсь помочь всё таки. ознакомтесь с мануалом короче: http://www.kb.mista.ru/article.php?id=33 Заданные ограничения добавляются системой к КАЖДОМУ запросу, даже тем, которые платформа генерирует самостоятельно для реализации пользовательского интерфейса или других функций. Ограничения на доступ к данным работают в двух режимах: • в режиме динамического списка производится простая фильтрация разрешенных записей, таким образом, пользователь просто не видит запрещенные данные. • в режиме выборки – нарушение ограничения влечет за собой исключение, таким образом, запрос не будет выполнен вовсе, значит, практически все запросы конфигурации могут «налететь» на ограничение. В язык запросов было введено новое ключевое слово «Разрешенные», которое пишется сразу после «Выбрать». Если оно указано, то запрос выбирает только разрешенные записи, а остальные «не видит». и ещё себя процитирую автор в типовой запрет не стоит на системные поля типа ссылки даты и прочее. они открыты а прочие поля закрыты. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.07.2010, 20:57 |
|
||
|
RLS
|
|||
|---|---|---|---|
|
#18+
RLS прочие поля->ограничение Выбрать * from Договор -> вылет Выбрать Разрешенные from Договор -> ок. Добавляем RLS поля ссылка, дата -> пустое ограничение Выбрать Ссылка, Дата from Договор -> ок. 1с ки нету под рукой поэтому я исходя из того что написано выше делаю заключение и не претендую на истину. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.07.2010, 21:03 |
|
||
|
|

start [/forum/topic.php?fid=28&msg=36720230&tid=1522217]: |
0ms |
get settings: |
10ms |
get forum list: |
15ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
195ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
54ms |
get tp. blocked users: |
1ms |
| others: | 245ms |
| total: | 540ms |

| 0 / 0 |
