Блог

    Caché (Кашэ́) — промышленная высокопроизводительная, объектная система управления базами данных, интегрированная с технологией разработки веб-приложений. Единая архитектура данных Caché позволяет разработчикам использовать одновременно объектный, реляционный (SQL) и прямой (NoSQL) доступ к одним и тем же данным, хранение которых обеспечивается ориентированным на транзакции многомерным ядром СУБД.

    http://www.intersystems.ru/cache/

Последние записи


Теги

Информация

Динамическая безопасность на уровне строк (row level security)

добавлено: 19 дек 16
понравилось:0
просмотров: 1363
комментов: 0

теги:

Автор: servit

На DC возник вопрос относительно того, можно ли для той или иной строки таблицы определять права всегда в runtime, и если да, то как.
Отвечаю: можно, и довольно просто.

Для этого нужно:

  • не ограничиваться сообществом DC
  • на уровне движка SQL отключить индекс %RLI (как это сделать было описано здесь), чтобы не делать это каждый раз в самом запросе с помощью %IGNOREINDEX
  • сделать поле %READERLIST всегда вычисляемым.
    Примечание:
    При желании можно при его вычислении "обнулять" права, если это операция INSERT/DELETE, что определяется переменной %oper. По понятным причинам это работает только для SQL.
Для демонстрации разных подходов создадим следующий класс:
demo.test.cls
Class demo.test Extends %Persistent
{

Parameter ROWLEVELSECURITY = 1;

Property %READERLIST As %String CalculatedPrivateSqlComputeCode = {{*} $s(%oper="":"%All",$$$YES:$$$SQLEmptyString)}, SqlComputed ];

Property f1 As %String;

Property f2 As %Integer;

/// d ##class(demo.test).Fill()
ClassMethod 
Fill(3)
{
  
..%KillExtent()
  
i=1:1:&sql(insert into demo.test(f1,f2values('f'||:i,:i))
  
  
zw ^demo.testD,^demo.testI !
  
  
..Test()
}

ClassMethod Test()
{
  
d $SYSTEM.SQL.SetMapSelectability($classname(),"%RLI",$$$YES), $system.SQL.PurgeForTable($classname())
  
  
"yes 1) -----",!!
  
##class(%SQL.Statement).%ExecDirect(,"select * from %IGNOREINDEX %RLI "_$classname()).%Display() !!
  
"yes 2) -----",!!
  
##class(%SQL.Statement).%ExecDirect(,"select * from "_$classname()).%Display() !!

  
d $SYSTEM.SQL.SetMapSelectability($classname(),"%RLI",$$$NO), $system.SQL.PurgeForTable($classname())
  
  
"no 1) -----",!!
  
##class(%SQL.Statement).%ExecDirect(,"select * from %IGNOREINDEX %RLI "_$classname()).%Display() !!
  
"no 2) -----",!!
  
##class(%SQL.Statement).%ExecDirect(,"select * from "_$classname()).%Display() !!
}

}
И выполним в терминале метод Fill из-под пользователя, имеющего роль %All:
USER>##class(demo.test).Fill()
^demo.testD=3
^demo.testD(1)=$lb("","f1",1)
^demo.testD(2)=$lb("","f2",2)
^demo.testD(3)=$lb("","f3",3)
^demo.testI("$a",1)=$zwc(412,1,0)/*$bit(2..4)*/
^demo.testI("%RLI"," "_$c(0),1)=$zwc(412,1,0)/*$bit(2..4)*/

yes 1) -----

ID f1 f2
1 f1 1
2 f2 2
3 f3 3

3 Rows(s) Affected

yes 2) -----

ID f1 f2

0 Rows(s) Affected

no 1) -----

ID f1 f2
1 f1 1
2 f2 2
3 f3 3

3 Rows(s) Affected

no 2) -----

ID f1 f2
1 f1 1
2 f2 2
3 f3 3

3 Rows(s) Affected
PS: конечно, в реальном проекте процедура вычисления будет посложнее, чем банальное %All, и может включать сразу несколько ролей/логинов через запятую.

Комментарии




Необходимо войти на сайт, чтобы оставлять комментарии