Çok kademeli bir perakende zinciri için tasarlanmış, üç farklı RLS pattern'ini tek modelde birleştiren Power BI portfolyo projesi.
NovaRetail, Türkiye genelinde 3 bölge, 9 il ve 34 mağazada faaliyet gösteren kurgusal bir perakende zinciridir. Şirketin farklı rollerdeki çalışanları aynı Power BI raporuna erişir ancak her biri sadece yetkili olduğu veriyi görebilir.
Bu demo, gerçek dünyada karşılaşılan güvenlik gereksinimlerini üç katmanlı bir RLS mimarisi ile modeller:
| Katman | Pattern | Kullanılan DAX | Roller |
|---|---|---|---|
| 1 | Statik RLS | FALSE(), sabit filtre |
HR, Finance |
| 2 | Dinamik RLS | USERPRINCIPALNAME() + LOOKUPVALUE |
RegionDirector, CityManager |
| 3 | Hiyerarşik RLS | PATH() + PATHCONTAINS() |
StoreManager |
Ayrıca Object-Level Security (OLS) ile Finance rolünden hassas maaş kolonu gizlenmiştir.
https://hierdogan.com/NovaRetail-DataDictionary.html
Yıldız şeması (star schema):
- Fact tabloları:
FactSales(~453K satır),FactPerformance(~4.4K satır) - Dimension tabloları:
DimStore,DimEmployee,DimProduct,DimDate,DimCity,DimRegion - Güvenlik tablosu:
DimUserSecurity(izole, sadece DAX ile kullanılır)
DimEmployee tablosu self-referencing hierarchy içerir (ManagerID) ve PATH() fonksiyonu ile organizasyonel zincir üretilir.
Filtre yok — tüm veriye erişim.
[RegionID] IN
CALCULATETABLE(
VALUES(DimUserSecurity[RegionID]),
DimUserSecurity[Email] = USERPRINCIPALNAME()
)
Aynı rol tanımı 3 farklı bölge direktörü için çalışır — kod tekrarı yok.
Aynı pattern, CityID üzerinden.
VAR CurrentUserEmpID =
LOOKUPVALUE(
DimUserSecurity[EmployeeID],
DimUserSecurity[Email], USERPRINCIPALNAME()
)
RETURN
PATHCONTAINS(DimEmployee[ManagerPath], CurrentUserEmpID)
Giriş yapan kullanıcının yönetici zincirinde olduğu tüm çalışanları gösterir.
FactSales: FALSE()
FactPerformance: FALSE()
Satış verisine erişim yok.
DimEmployee[Role] <> "GM"filtresi (executive maaşlar gizli)- OLS ile
DimEmployee[Salary]kolonu tamamen erişilemez
| Test Kullanıcısı | Rol | Beklenen Mağaza | Beklenen Çalışan | Satış Görür mü |
|---|---|---|---|---|
| gm@novaretail.com | GM | 34 | 201 | ✅ |
| marmara.dir@novaretail.com | RegionDirector | ~12 | ~70 | ✅ |
| istanbul.mudur@novaretail.com | CityManager | ~4 | ~25 | ✅ |
| s001.mudur@novaretail.com | StoreManager | 1 | 4-7 | ✅ |
| hr1@novaretail.com | HR | 34 | 201 | ❌ |
| finance1@novaretail.com | Finance | 34 | 200 | ✅ (maaşsız) |
NovaRetail-RLS-Demo/
├── data/ # Sentetik CSV veriler
│ ├── DimRegion.csv
│ ├── DimCity.csv
│ ├── DimStore.csv
│ ├── DimEmployee.csv
│ ├── DimProduct.csv
│ ├── DimDate.csv
│ ├── DimUserSecurity.csv
│ ├── FactSales.csv
│ ├── FactPerformance.csv
│ └── generate_data.py # Sentetik veri üretici (Python)
├── NovaRetail.pbix # Power BI raporu
├── docs/
│ ├── data-model.png # Model diyagramı
│ ├── rls-architecture.png # RLS akış şeması
│ ├── DAX_kodlari.txt # Dax Kodları
│ └── NovaRetail-DataDictionary.html # Veri sözdlüğü
├── assets/
│ ├── 01-sales-overview.png
│ ├── 02-store-employee.png
│ ├── 03-security-info.png
│ ├── 04-security-info_view.png
│ └── rls-demo.gif
└── README.md
- Veri modelleme: Yıldız şeması, self-referencing hierarchy, bidirectional filter kararları
- DAX:
PATH,PATHCONTAINS,PATHLENGTH,USERPRINCIPALNAME,LOOKUPVALUE,CALCULATETABLE,VAR/RETURN, time intelligence - Güvenlik: Statik + dinamik + hiyerarşik RLS, OLS, isolated security tablosu deseni
- Best practice: Debug sayfası, dokümantasyon, test matrisi, sentetik veri üretimi
- Veri mühendisliği: Python ile parametreli veri üretimi, tekrarlanabilir setup
- RLS model seviyesinde çalışır; visual-level güvenlik ayrıca uygulanmalıdır
- Büyük hiyerarşilerde
PATH()performans etkisi yaratabilir — bu demoda 4 kademe olduğu için önemsiz USERPRINCIPALNAME()Desktop'ta boş döner; View as özelliğiyle test edilmelidir- Service'e deploy edildikten sonra roller Power BI Service tarafında kullanıcılara atanmalıdır (Manage Security)
pip install faker
python generate_data.pyScript deterministik seed (42) kullandığı için her çalıştırmada aynı veri üretilir.
assets/ klasöründe alınmış ekran görüntüleri bulunur.




