TMDL demo 1/3: RLS Generator

Disclaimer

This blog post is part of a three-part series based on my speaker session at the European Microsoft Fabric Community Conference 2025 (FabCon) in Vienna, which I had the pleasure of delivering together with my colleague Roger Unholz.

Our session, titled “TMDL Playoffs”, was a fast-paced showdown where we shared our favorite tips and tricks for working with TMDL. In this series, I’ll take a deeper dive into each topic we presented on stage and explore them in more detail.All source files referenced throughout the posts are available in my public GitHub repository.

Please note, that the scripts are not tested for every scenario, that they are only created for demonstration purposes and should never be applied on any running, productive enviroments.
Link: ivsch/TMDLPlayoffs.

Idea

The configuration of Role Level Security (RLS) within Power BI semantic models can sometimes be straightforward, but at other times it can feel like opening Pandora’s box. In most customer scenarios I encounter, the RLS setup is fairly basic. Nevertheless, managing RLS across a large number of semantic models can be a real challenge, especially when ensuring that the correct settings are applied consistently.

To address this, I often maintain role definitions outside of the semantic model to provide a clear overview of all enabled RLS settings. That could be a Excel file as well as a small “security application”. This should then be the basic information for a simple script generator to quickly and reliably apply the defined roles to a Power BI semantic model file.

TMDL RLS definition

To check existing RLS definitions in your Power BI semantic model, first enable the TMDL view in Power BI Desktop settings (currently available under Preview features).

On the right side of your semantic model, you’ll find all the objects available in the TMDL scripting language. If you drag and drop the Roles object into the script window, you’ll see the definition of the roles.

Outcome

Even if it’s not a complete solution for handling complex RLS definitions, the most common/basic scenarios can be covered with the Jupyter Notebook apply_rls in the GitHub source folder.

In the very first cell, you can provide all settings for the roles you want to apply. At the moment, the script only works with string values; it can be extended/adjusted to support other data types.


RLS_DEFINITION = [
    {
        "role_name":"CustomerSegmentManagersEnterprise",
        "table_name":"DimCustomer",
        "rls_field_name":"Segment",
        "allowed_values":["Consumer", "Enterprise"]
    },
    {
        "role_name":"CustomerSegmentManagersSMB",
        "table_name":"DimCustomer",
        "rls_field_name":"Segment",
        "allowed_values":["SMB"]
    }
]

This configuration generates a script for two roles—CustomerSegmentManagersEnterprise and CustomerSegmentManagersSMB—that filters the DimCustomer[Segment] column to the specified values.

With those settings, the following output is provided and can be taken over to existing semantic model files.

Generated createOrReplace TMDL script:

createOrReplace

	role CustomerSegmentManagersEnterprise
		modelPermission: read

		tablePermission DimCustomer = [Segment] == "Consumer" || [Segment] == "Enterprise"


	role CustomerSegmentManagersSMB
		modelPermission: read

		tablePermission DimCustomer = [Segment] == "SMB"

Extendability

With further extensions, this functionality could be applied to an application that centrally defines roles and their respective security settings. This would simplify the management of RLS settings across multiple semantic models. In a pro version, you could even imagine downloading the Power BI semantic model, editing the TMDL role definitions, and re-uploading it via the Fabric REST API.

(Mis-)use custom map visuals in Power BI

Use case

In this blog post, I will show you how to use custom map visuals in Power BI to display something different than a region on a world map.

I first stumbled upon custom map visuals years ago using Reporting Services Mobile Reports. Back then, my boss used to visualize figures on different regions of Switzerland based own region definitions given by the business.

Based on personal interest, I created a dataset using open data to get the votes of members in the Swiss National Council. I want to display the members on their effective place in the seat plan of the parliament. As I looked at the image of the parliament, I suddenly thought about it as a map. It actually displays a certain object placed on a respective geographical location – even if there is no need for longitude and latitude (in terms of placement on our world map)

Swiss Parliament (Source: https://www.parlament.ch)

Approach

I often try to avoid 3rd party visuals and I check first, if the requirement could be fulfilled with a built-in visual. So I gave the custom map visuals a go!

First, you need to activate the shape map visuals in the preview features settings in Power BI desktop. It will show up in your visual selection pane afterwards.

Custom map visuals need a GeoJSON file to display the custom maps. I’d have to generate one using the parliament seating plan.

The seat plan above needs do be represented as GeoJSON file defining the single seats as objects. They also need to have a ID to be able to identify and use them in the report. In this specific example i needed 3rd party tools to convert the seat plan first to a SVG, then to a JSON file (I have used the following converter: Online GIS/CAD Data Converter | SHP, KML, KMZ, TAB, CSV, … (mygeodata.cloud)).

In the JSON file resulting, an id has to be added to every polygon defined in the JSON file. Those Ids are connected to the respective data in Power BI afterwards. Adjustments like this or other transformations can be done with the online tool mapshaper (mapshaper).

Hint

On one point, I had to rotate the whole JSON file by 180 degrees. I was able to achieve this by using the following command in mapshaper: “mapshaper -affine rotate=180”. Just if you are struggling with this 😉

The Id in your data is now connected to the polygons by using the Id in the “Location” attribute of the custom map visual.

Conclusion

This was a first trial on (mis-) using custom map visuals not showing “real” geographic data on the world map but allocating areas on a complete different map, like a seating plan.

Do you have used custom map visuals for other purposes than real world maps as well? Let me know in the comments!

This is my final report in action, showing vote results based on my seating map: