Динамическая безопасность на уровне строк с профилями и пользователями в Power BI: отношение «многие ко многим»
В этом посте мы рассмотрим другой тип безопасности динамической 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 и многими другими функциями).