Динамическая безопасность на уровне строк с профилями и пользователями в Power BI: отношение «многие ко многим»

Tags: Power BI, PowerBI, RLS

В этом посте мы рассмотрим другой тип безопасности динамической RLS, который касается пользователей и их профилей. Иногда у вас есть пользовательская часть из нескольких групп (или профилей), и профиль содержит несколько пользователей. Это отношение «многие ко многим» необходимо также включить в работу системы безопасности в Power BI. Вы хотите, чтобы все пользователи видели данные, относящиеся к их собственным профилям. Поскольку эта модель включает в себя отношение «многие ко многим», реализация этого немного отличается от обычной динамической RLS.

Необходимое условие

Для прочтения этого поста было бы гораздо лучше иметь представление о простой динамической безопасности на уровне строк с помощью функции Username или UserPrincipalName. пожалуйста, прочитайте этот пост.

Сценарий

Представьте, что Марк работает в компании. Марк является частью группы продаж в Сиэтле. Он должен видеть все сделки купли-продажи, связанные с Сиэтлом. Также; он входит в группу по продажам в Портленде и должен видеть детали транзакций в Портленде. С другой стороны, есть другие люди, у которых их доступ отличается. Дэвид входит в группу продаж Чикаго, а также Сиэтла. Эта ситуация создает отношение «многие ко многим» между таблицей пользователей и таблицей профилей, как показано ниже:

 

Чтобы вы могли следовать примеру, вот примерные наборы данных для каждой таблицы:

Таблица пользователей

 

Важно, чтобы таблица пользователей включала столбец для своих учетных записей Power BI (в данном примере - электронная почта).

Таблица профиля

 

Вы могли бы также назвать это филиалом или магазином или группой.

Таблица профиля пользователя

 

Эта таблица содержит отношения или связь между пользователями и их профилями.

Таблица транзакций

 

Каждая транзакция связана с профилем. Все пользователи в этом профиле должны иметь доступ к транзакции, помеченной для этого профиля.

Полная схема модели

 

Разница между этой моделью и простой динамической безопасностью на уровне строк заключается в том, что в этой модели мы имеем отношение «многие ко многим», и распространение фильтра будет не таким простым, как в простой модели.

Фильтрация пользователей не работает

Сама фильтрация пользователей в этом случае не будет решением. Вот роль, определенная в пользовательской таблице с фильтром DAX:

[email]=UserPrincipalName()

 

Этот DAX-фильтр в таблице User будет фильтровать профиль пользователя, но он не будет фильтровать таблицу Profile, поэтому в результате он не будет фильтровать таблицу транзакций.

 

Направление взаимосвязи между таблицей профиля и таблицей профилей пользователей не позволяет фильтру распространяться из профиля пользователя в таблицу профилей. В результате данные таблицы транзакций продаж не будут отфильтрованы с помощью фильтра DAX, определенного в пользовательской таблице. Есть много способов, с помощью которых вы можете получить это решение. В этом посте мы объясним два метода:

Перекрестный фильтр или двунаправленные отношения

Этот метод не рекомендуется, особенно из-за проблем с производительностью, однако мы хотели бы начать с него, потому что он помогает понять, как работают отношения в DAX. Для использования этого метода; вам нужно изменить направление взаимосвязи между таблицей профилей и таблицей профилей пользователей на двустороннее, а также вам нужно проверить опцию «Apply security filter in both directions».

 

После этого изменения ваша конфигурация безопасности на уровне строк будет работать отлично, как показано ниже:

 

Диаграмма модели теперь проходит фильтр до таблицы транзакций продаж:

 

Этот метод прост в реализации. Однако не рекомендован. Применение двустороннего отношения и фильтра безопасности значительно снизит производительность вашего решения Power BI. С другой стороны, если у вас много таблиц, связанных друг с другом круговой зависимостью, вы не всегда сможете применять двустороннего отношения. Поэтому мы рекомендуем следующий метод.

Фильтрация данных через DAX

Из-за вышеуказанных проблем, рекомендуется использовать этот метод. Этот метод в основном пропускает фильтры через написание некоторой логики в DAX. Существует много способов реализации этой логики с DAX. Вы можете написать функцию LookupValue, функцию Filter или многими другими способами. Мы объясним это с помощью функции фильтра.

 

В этом методе вам не нужно менять направление отношений, чтобы они стали двусторонними. В этом методе вам нужно найти способ фильтрации данных в таблице профиля. Если вы отфильтруете данные в таблице профиля, то данные в таблице Sales Transactions будут отфильтрованы автоматически. Один из способов фильтрации - сначала найти все идентификаторы профиля из профиля пользователя, который связан с вошедшим в систему пользователем:

Шаг 1: Найдите все строки в профиле пользователя для вошедшего в систему пользователя

Вы можете использовать простую функцию FILTER (), чтобы получить все строки из профиля пользователя для вошедшего в систему пользователя:

 

2

3

4

FILTER(

'User Profile',

RELATED(User[Email])=USERPRINCIPALNAME()

)

Этот код будет возвращать вложенную таблицу из таблицы профиля пользователя, которая представляет собой только строки, связанные с вошедшим в систему пользователем. из этого списка давайте получим только их ID профиля на следующем шаге:

Шаг 2: Получите идентификаторы профиля из списка

Вы можете использовать функцию SelectColumns () DAX только для выбора столбца профиля (который является идентификатором профиля):

 

1

2

3

4

5

6

7

8

SELECTCOLUMNS(

FILTER(

'User Profile',

RELATED(User[Email])=USERPRINCIPALNAME()

),

"Profile"

,[Profile]

)

Теперь этот код DAX вернет таблицу с одним столбцом, который является идентификатором профилей.

Шаг 3: Фильтруйте таблицу профилей, где идентификатор соответствует таблице выше

Теперь мы можем использовать ключевое слово IN для фильтрации данных таблицы профиля только для вошедшего в систему пользователя:

 

1

2

3

4

5

6

7

8

[ID] IN SELECTCOLUMNS(

FILTER(

'User Profile',

RELATED(User[Email])=USERPRINCIPALNAME()

),

"Profile"

,[Profile]

)

 

Этот фильтр должен быть записан в таблице профиля, как показано ниже:

 

В результате этот метод работает отлично, как и ожидалось;

 

Схема этого метода представляет собой однонаправленное отношение. Тем не менее, DAX-фильтр распространяется с логикой, которую мы написали в роли.

 

Резюме

Применение безопасности на уровне строк имеет много вариантов. В этом посте вы узнали о том, как использовать концепцию  Users and Groups (или Profiles) и преодолели проблему «многие ко многим» для обеспечения безопасности на уровне строк. Вы узнали о двух методах; какой из них был рекомендуемым подходом. Есть и другие способы реализации этого сценария (с LookupValue и многими другими функциями).

No Comments

Add a Comment